diff --git a/src/sentry/static/sentry/app/components/events/eventCauseEmpty.jsx b/src/sentry/static/sentry/app/components/events/eventCauseEmpty.jsx index 8a8c39e14253db..584acbafb7e8f7 100644 --- a/src/sentry/static/sentry/app/components/events/eventCauseEmpty.jsx +++ b/src/sentry/static/sentry/app/components/events/eventCauseEmpty.jsx @@ -13,6 +13,7 @@ import SentryTypes from 'app/sentryTypes'; import {snoozedDays} from 'app/utils/promptsActivity'; import space from 'app/styles/space'; import {t} from 'app/locale'; +import {trackAdhocEvent, trackAnalyticsEvent} from 'app/utils/analytics'; import Tooltip from 'app/components/tooltip'; import withApi from 'app/utils/withApi'; @@ -48,6 +49,21 @@ class EventCauseEmpty extends React.Component { this.fetchData(); } + componentDidUpdate(_prevProps, prevState) { + const {project, organization} = this.props; + const {shouldShow} = this.state; + + if (!prevState.shouldShow && shouldShow) { + // send to reload only due to high event volume + trackAdhocEvent({ + eventKey: 'event_cause.viewed', + org_id: parseInt(organization.id, 10), + project_id: parseInt(project.id, 10), + platform: project.platform, + }); + } + } + async fetchData() { const {api, project, organization} = this.props; @@ -72,7 +88,7 @@ class EventCauseEmpty extends React.Component { return true; } - handleClick(action) { + handleClick({action, eventKey, eventName}) { const {api, project, organization} = this.props; const data = { @@ -82,6 +98,19 @@ class EventCauseEmpty extends React.Component { status: action, }; promptsUpdate(api, data).then(this.setState({shouldShow: false})); + this.trackAnalytics({eventKey, eventName}); + } + + trackAnalytics({eventKey, eventName}) { + const {project, organization} = this.props; + + trackAnalyticsEvent({ + eventKey, + eventName, + organization_id: parseInt(organization.id, 10), + project_id: parseInt(project.id, 10), + platform: project.platform, + }); } render() { @@ -103,6 +132,13 @@ class EventCauseEmpty extends React.Component { size="small" priority="primary" href="https://docs.sentry.io/workflow/releases/#create-release" + onClick={() => + this.trackAnalytics({ + eventKey: 'event_cause.docs_clicked', + eventName: 'Event Cause Docs Clicked', + }) + } + data-test-id="read-the-docs" > {t('Read the docs')} @@ -111,7 +147,13 @@ class EventCauseEmpty extends React.Component { this.handleClick('snoozed')} + onClick={() => + this.handleClick({ + action: 'snoozed', + eventKey: 'event_cause.snoozed', + eventName: 'Event Cause Snoozed', + }) + } data-test-id="snoozed" > {t('Snooze')} @@ -119,7 +161,13 @@ class EventCauseEmpty extends React.Component { this.handleClick('dismissed')} + onClick={() => + this.handleClick({ + action: 'dismissed', + eventKey: 'event_cause.dismissed', + eventName: 'Event Cause Dismissed', + }) + } data-test-id="dismissed" > {t('Dismiss')} diff --git a/tests/js/spec/components/events/eventCauseEmpty.spec.jsx b/tests/js/spec/components/events/eventCauseEmpty.spec.jsx index 90e9ddd0465e90..b8927913aaa3da 100644 --- a/tests/js/spec/components/events/eventCauseEmpty.spec.jsx +++ b/tests/js/spec/components/events/eventCauseEmpty.spec.jsx @@ -3,12 +3,15 @@ import moment from 'moment'; import {mount} from 'enzyme'; import EventCauseEmpty from 'app/components/events/eventCauseEmpty'; +import {trackAdhocEvent, trackAnalyticsEvent} from 'app/utils/analytics'; + +jest.mock('app/utils/analytics'); describe('EventCauseEmpty', function() { let putMock; const routerContext = TestStubs.routerContext(); const organization = TestStubs.Organization(); - const project = TestStubs.Project(); + const project = TestStubs.Project({platform: 'javascript'}); beforeEach(function() { MockApiClient.clearMockResponses(); @@ -38,6 +41,13 @@ describe('EventCauseEmpty', function() { wrapper.update(); expect(wrapper.find('CommitRow').exists()).toBe(true); + + expect(trackAdhocEvent).toHaveBeenCalledWith({ + eventKey: 'event_cause.viewed', + org_id: parseInt(organization.id, 10), + project_id: parseInt(project.id, 10), + platform: project.platform, + }); }); it('can be snoozed', async function() { @@ -68,6 +78,14 @@ describe('EventCauseEmpty', function() { ); expect(wrapper.find('CommitRow').exists()).toBe(false); + + expect(trackAnalyticsEvent).toHaveBeenCalledWith({ + eventKey: 'event_cause.snoozed', + eventName: 'Event Cause Snoozed', + organization_id: parseInt(organization.id, 10), + project_id: parseInt(project.id, 10), + platform: project.platform, + }); }); it('does not render when snoozed', async function() { @@ -142,6 +160,14 @@ describe('EventCauseEmpty', function() { ); expect(wrapper.find('CommitRow').exists()).toBe(false); + + expect(trackAnalyticsEvent).toHaveBeenCalledWith({ + eventKey: 'event_cause.dismissed', + eventName: 'Event Cause Dismissed', + organization_id: parseInt(organization.id, 10), + project_id: parseInt(project.id, 10), + platform: project.platform, + }); }); it('does not render when dismissed', async function() { @@ -161,4 +187,27 @@ describe('EventCauseEmpty', function() { expect(wrapper.find('CommitRow').exists()).toBe(false); }); + + it('can capture analytics on docs click', async function() { + const wrapper = mount( + , + routerContext + ); + + await tick(); + wrapper.update(); + + wrapper + .find('[data-test-id="read-the-docs"]') + .first() + .simulate('click'); + + expect(trackAnalyticsEvent).toHaveBeenCalledWith({ + eventKey: 'event_cause.docs_clicked', + eventName: 'Event Cause Docs Clicked', + organization_id: parseInt(organization.id, 10), + project_id: parseInt(project.id, 10), + platform: project.platform, + }); + }); });