diff --git a/.changeset/clever-rice-perform.md b/.changeset/clever-rice-perform.md new file mode 100644 index 0000000000..f909db008c --- /dev/null +++ b/.changeset/clever-rice-perform.md @@ -0,0 +1,5 @@ +--- +'@envelop/sentry': minor +--- + +Make it possible to get the active span in the GraphQL resolver diff --git a/packages/plugins/sentry/__tests__/sentry.spec.ts b/packages/plugins/sentry/__tests__/sentry.spec.ts index 4e5a42ccb6..62349381b2 100644 --- a/packages/plugins/sentry/__tests__/sentry.spec.ts +++ b/packages/plugins/sentry/__tests__/sentry.spec.ts @@ -5,6 +5,7 @@ import { useSentry } from '@envelop/sentry'; import { assertSingleExecutionValue, createTestkit } from '@envelop/testing'; import { makeExecutableSchema } from '@graphql-tools/schema'; import * as Sentry from '@sentry/node'; +import { Span } from '@sentry/types'; import '@sentry/tracing'; describe('sentry', () => { @@ -252,4 +253,46 @@ describe('sentry', () => { name: 'Error', }); }); + + test('get the active span', async () => { + const { testkit: sentryTestkit, sentryTransport } = createSentryTestkit(); + Sentry.init({ + dsn: 'https://public@sentry.example.com/1', + transport: sentryTransport, + }); + + let activeSpan: Span | undefined; + const schema = makeExecutableSchema({ + typeDefs: /* GraphQL */ ` + type Query { + hello: String! + } + `, + resolvers: { + Query: { + hello: async () => { + activeSpan = Sentry.getActiveSpan(); + return 'Hello!'; + }, + }, + }, + }); + + const envelopTestkit = createTestkit([useSentry()], schema); + const result = await envelopTestkit.execute('{ hello }'); + expect(result).toMatchInlineSnapshot(` + { + "data": { + "hello": "Hello!", + }, + } + `); + expect(activeSpan).not.toBeUndefined(); + + // run sentry flush + await new Promise(res => setTimeout(res, 10)); + + const reports = sentryTestkit.reports(); + expect(reports).toHaveLength(0); + }); }); diff --git a/packages/plugins/sentry/src/index.ts b/packages/plugins/sentry/src/index.ts index 0e4c41bf50..3c0f410603 100644 --- a/packages/plugins/sentry/src/index.ts +++ b/packages/plugins/sentry/src/index.ts @@ -108,7 +108,7 @@ export const useSentry = = {}>( } return { - onExecute({ args }) { + onExecute({ args, executeFn, setExecuteFn }) { if (skipOperation(args)) { return; } @@ -152,6 +152,9 @@ export const useSentry = = {}>( options.configureScope(args, Sentry.getCurrentScope()); } + // Give access to the span during resolvers execution + setExecuteFn(args => Sentry.withActiveSpan(rootSpan, () => executeFn(args))); + return { onExecuteDone(payload) { const handleResult: OnExecuteDoneHookResultOnNextHook<{}> = ({