Skip to content

feat(suspect-commits): Add analytics events #14080

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 51 additions & 3 deletions src/sentry/static/sentry/app/components/events/eventCauseEmpty.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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;

Expand All @@ -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 = {
Expand All @@ -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),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor nit: These will be coerced for you, you don't have to manually parse int.

project_id: parseInt(project.id, 10),
platform: project.platform,
});
}

render() {
Expand All @@ -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')}
</Button>
Expand All @@ -111,15 +147,27 @@ class EventCauseEmpty extends React.Component {
<Tooltip title={t('Remind me next week')}>
<SnoozeButton
size="small"
onClick={() => this.handleClick('snoozed')}
onClick={() =>
this.handleClick({
action: 'snoozed',
eventKey: 'event_cause.snoozed',
eventName: 'Event Cause Snoozed',
})
}
data-test-id="snoozed"
>
{t('Snooze')}
</SnoozeButton>
</Tooltip>
<DismissButton
size="small"
onClick={() => this.handleClick('dismissed')}
onClick={() =>
this.handleClick({
action: 'dismissed',
eventKey: 'event_cause.dismissed',
eventName: 'Event Cause Dismissed',
})
}
data-test-id="dismissed"
>
{t('Dismiss')}
Expand Down
51 changes: 50 additions & 1 deletion tests/js/spec/components/events/eventCauseEmpty.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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() {
Expand All @@ -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(
<EventCauseEmpty organization={organization} project={project} />,
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,
});
});
});