Skip to content
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
2 changes: 1 addition & 1 deletion src/sentry/api/endpoints/organization_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from sentry import features
from sentry.models.project import Project

ALLOWED_GROUPINGS = frozenset(('issue.id', 'project.id'))
ALLOWED_GROUPINGS = frozenset(('issue.id', 'project.id', 'transaction'))
logger = logging.getLogger(__name__)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import UserBadge from 'app/components/idBadge/userBadge';
import DateTime from 'app/components/dateTime';
import pinIcon from 'app/../images/location-pin.png';

import {t} from 'app/locale';
import {QueryLink} from './styles';

export const MODAL_QUERY_KEYS = ['eventSlug', 'groupSlug'];
Expand All @@ -20,7 +21,7 @@ export const PIN_ICON = `image://${pinIcon}`;
export const ALL_VIEWS = deepFreeze([
{
id: 'all',
name: 'All Events',
name: t('All Events'),
data: {
fields: ['event', 'type', 'project', 'user', 'time'],
sort: ['-timestamp', '-id'],
Expand All @@ -37,7 +38,7 @@ export const ALL_VIEWS = deepFreeze([
},
{
id: 'errors',
name: 'Errors',
name: t('Errors'),
data: {
fields: ['error', 'event_count', 'user_count', 'project', 'last_seen'],
groupby: ['issue.id', 'project.id'],
Expand All @@ -49,7 +50,7 @@ export const ALL_VIEWS = deepFreeze([
},
{
id: 'csp',
name: 'CSP',
name: t('CSP'),
data: {
fields: ['csp', 'event_count', 'user_count', 'project', 'last_seen'],
groupby: ['issue.id', 'project.id'],
Expand All @@ -65,6 +66,25 @@ export const ALL_VIEWS = deepFreeze([
],
columnWidths: ['3fr', '70px', '70px', '1fr', '1.5fr'],
},
{
id: 'transactions',
name: t('Transactions'),
data: {
fields: ['transaction', 'project'],
groupby: ['transaction', 'project.id'],
sort: ['-transaction'],
query: 'event.type:transaction',
},
tags: [
'event.type',
'release',
'project.name',
'user.email',
'user.ip',
'environment',
],
columnWidths: ['3fr', '1fr', '1fr', '1fr', '1fr', '1fr', '1fr'],
},
]);

/**
Expand All @@ -73,6 +93,26 @@ export const ALL_VIEWS = deepFreeze([
* displays with a custom render function.
*/
export const SPECIAL_FIELDS = {
transaction: {
fields: ['project.name', 'transaction'],
sortField: 'transaction',
renderFunc: (data, {organization, location}) => {
const target = {
pathname: `/organizations/${organization.slug}/events/`,
query: {
...location.query,
transactionSlug: `${data['project.name']}:${data.transaction}`,
},
};
return (
<Container>
<Link css={overflowEllipsis} to={target} aria-label={data.transaction}>
{data.transaction}
</Link>
</Container>
);
},
},
event: {
fields: ['title', 'id', 'project.name'],
sortField: 'title',
Expand All @@ -83,7 +123,7 @@ export const SPECIAL_FIELDS = {
};
return (
<Container>
<Link css={overflowEllipsis} to={target} data-test-id="event-title">
<Link css={overflowEllipsis} to={target} aria-label={data.title}>
{data.title}
</Link>
</Container>
Expand Down Expand Up @@ -172,7 +212,7 @@ export const SPECIAL_FIELDS = {
};
return (
<Container>
<Link css={overflowEllipsis} to={target} data-test-id="event-title">
<Link css={overflowEllipsis} to={target} aria-label={data.issue_title}>
{data.issue_title}
</Link>
</Container>
Expand All @@ -192,7 +232,7 @@ export const SPECIAL_FIELDS = {
};
return (
<Container>
<Link css={overflowEllipsis} to={target} data-test-id="event-title">
<Link css={overflowEllipsis} to={target} aria-label={data.issue_title}>
{data.issue_title}
</Link>
</Container>
Expand Down
4 changes: 2 additions & 2 deletions tests/acceptance/test_organization_events_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def test_modal_from_all_events(self, mock_now):
self.wait_until_loaded()

# Click the event link to open the modal
self.browser.element('[data-test-id="event-title"]').click()
self.browser.element('[aria-label="{}"]'.format(event.title)).click()
self.wait_until_loaded()

header = self.browser.element('[data-test-id="modal-dialog"] h2')
Expand Down Expand Up @@ -169,7 +169,7 @@ def test_modal_from_errors_view(self, mock_now):
self.wait_until_loaded()

# Click the event link to open the modal
self.browser.element('[data-test-id="event-title"]').click()
self.browser.element('[aria-label="{}"]'.format(event.title)).click()
self.wait_until_loaded()

self.browser.snapshot('events-v2 - grouped error modal')
Expand Down
5 changes: 3 additions & 2 deletions tests/js/spec/views/organizationEventsV2/index.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import {mount} from 'enzyme';
import OrganizationEventsV2 from 'app/views/organizationEventsV2';

describe('OrganizationEventsV2', function() {
const eventTitle = 'Oh no something bad';
beforeEach(function() {
MockApiClient.addMockResponse({
url: '/organizations/org-slug/events/',
body: [
{
id: 'deadbeef',
title: 'Oh no something bad',
title: eventTitle,
'project.name': 'project-slug',
timestamp: '2019-05-23T22:12:48+00:00',
},
Expand Down Expand Up @@ -108,7 +109,7 @@ describe('OrganizationEventsV2', function() {
TestStubs.routerContext()
);

const link = wrapper.find('Table Link[data-test-id="event-title"]').first();
const link = wrapper.find(`Table Link[aria-label="${eventTitle}"]`).first();
expect(link.props().to.query).toEqual({eventSlug: 'project-slug:deadbeef'});
});

Expand Down
2 changes: 1 addition & 1 deletion tests/snuba/api/endpoints/test_organization_events_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ def test_invalid_groupby(self):
},
)
assert response.status_code == 400, response.content
assert response.data['detail'] == 'Invalid groupby value requested. Allowed values are project.id, issue.id'
assert response.data['detail'] == 'Invalid groupby value requested. Allowed values are transaction, project.id, issue.id'

def test_non_aggregated_fields_with_groupby(self):
self.login_as(user=self.user)
Expand Down