Skip to content

Commit

Permalink
fix(profiles): Need to wrap user query in parenthesis (#71102)
Browse files Browse the repository at this point in the history
Users can use boolean operators in the query which can have an impact on
the condition. For example they added `transaction:foo OR
transaction:bar` the query actually becomes `(has:profile.id AND
transaction:foo) OR transaction:bar`. which is incorrect.
  • Loading branch information
Zylphrex authored May 17, 2024
1 parent b1bc0bd commit e11c7da
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 5 deletions.
50 changes: 49 additions & 1 deletion static/app/utils/profiling/hooks/useProfileEvents.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,61 @@ describe('useProfileEvents', function () {
MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/events/`,
body,
match: [MockApiClient.matchQuery({dataset: 'profiles'})],
match: [MockApiClient.matchQuery({dataset: 'profiles', query: 'transaction:foo'})],
});

const {result} = renderHook(useProfileEvents, {
wrapper: TestContext,
initialProps: {
fields,
query: 'transaction:foo',
sort: {key: 'count()', order: 'desc' as const},
referrer: '',
},
});

await waitFor(() => result.current.isSuccess);
expect(result.current.data).toEqual(body);
});

it('handles querying the api using discover', async function () {
const {organization: organizationUsingTransactions} = initializeOrg({
organization: {features: ['profiling-using-transactions']},
});

function TestContextUsingTransactions({children}: {children?: ReactNode}) {
return (
<QueryClientProvider client={makeTestQueryClient()}>
<OrganizationContext.Provider value={organizationUsingTransactions}>
{children}
</OrganizationContext.Provider>
</QueryClientProvider>
);
}

const fields = ['count()'];

const body: EventsResults<(typeof fields)[number]> = {
data: [],
meta: {fields: {}, units: {}},
};

MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/events/`,
body,
match: [
MockApiClient.matchQuery({
dataset: 'discover',
query: 'has:profile.id (transaction:foo)',
}),
],
});

const {result} = renderHook(useProfileEvents, {
wrapper: TestContextUsingTransactions,
initialProps: {
fields,
query: 'transaction:foo',
sort: {key: 'count()', order: 'desc' as const},
referrer: '',
},
Expand Down
2 changes: 1 addition & 1 deletion static/app/utils/profiling/hooks/useProfileEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function useProfileEvents<F extends string>({
let dataset: 'profiles' | 'discover' = 'profiles';
if (organization.features.includes('profiling-using-transactions')) {
dataset = 'discover';
query = `has:profile.id ${query ?? ''}`;
query = `has:profile.id ${query ? `(${query})` : ''}`;
}

const path = `/organizations/${organization.slug}/events/`;
Expand Down
67 changes: 65 additions & 2 deletions static/app/utils/profiling/hooks/useProfileEventsStats.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,15 @@ describe('useProfileEvents', function () {
units: {count: null},
},
},
match: [MockApiClient.matchQuery({dataset: 'profiles'})],
match: [MockApiClient.matchQuery({dataset: 'profiles', query: 'transaction:foo'})],
});

const {result} = renderHook(useProfileEventsStats, {
wrapper: TestContext,
initialProps: {
dataset: 'profiles' as const,
yAxes,
query: 'transaction:foo',
referrer: '',
},
});
Expand Down Expand Up @@ -126,14 +127,15 @@ describe('useProfileEvents', function () {
},
},
},
match: [MockApiClient.matchQuery({dataset: 'profiles'})],
match: [MockApiClient.matchQuery({dataset: 'profiles', query: 'transaction:foo'})],
});

const {result} = renderHook(useProfileEventsStats, {
wrapper: TestContext,
initialProps: {
dataset: 'profiles' as const,
yAxes,
query: 'transaction:foo',
referrer: '',
},
});
Expand All @@ -152,4 +154,65 @@ describe('useProfileEvents', function () {
timestamps: [0, 5],
});
});

it('handles 1 axis using discover', async function () {
const {organization: organizationUsingTransactions} = initializeOrg({
organization: {features: ['profiling-using-transactions']},
});

function TestContextUsingTransactions({children}: {children?: ReactNode}) {
return (
<QueryClientProvider client={makeTestQueryClient()}>
<OrganizationContext.Provider value={organizationUsingTransactions}>
{children}
</OrganizationContext.Provider>
</QueryClientProvider>
);
}

const yAxes = ['count()'];

MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/events-stats/`,
body: {
data: [
[0, [{count: 1}]],
[5, [{count: 2}]],
],
start: 0,
end: 10,
meta: {
fields: {count: 'integer'},
units: {count: null},
},
},
match: [
MockApiClient.matchQuery({
dataset: 'discover',
query: 'has:profile.id (transaction:foo)',
}),
],
});

const {result} = renderHook(useProfileEventsStats, {
wrapper: TestContextUsingTransactions,
initialProps: {
dataset: 'profiles' as const,
yAxes,
query: 'transaction:foo',
referrer: '',
},
});

await waitFor(() => result.current.isSuccess);
expect(result.current.data).toEqual({
data: [{axis: 'count()', values: [1, 2]}],
meta: {
dataset: 'discover',
start: 0,
end: 10,
},
timestamps: [0, 5],
});
});
});
2 changes: 1 addition & 1 deletion static/app/utils/profiling/hooks/useProfileEventsStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function useProfileEventsStats<F extends string>({
}

if (dataset === 'discover') {
query = `has:profile.id ${query ?? ''}`;
query = `has:profile.id ${query ? `(${query})` : ''}`;
}

const path = `/organizations/${organization.slug}/events-stats/`;
Expand Down

0 comments on commit e11c7da

Please sign in to comment.