diff --git a/.changeset/red-rocks-teach.md b/.changeset/red-rocks-teach.md new file mode 100644 index 0000000000..75ac5aaab0 --- /dev/null +++ b/.changeset/red-rocks-teach.md @@ -0,0 +1,5 @@ +--- +"@envelop/sentry": patch +--- + +Adds the root sentry span to a resolver's context - so you can safely grab it from your own code without relying on singletons. diff --git a/packages/plugins/sentry/__tests__/sentry.spec.ts b/packages/plugins/sentry/__tests__/sentry.spec.ts index 638fcad1f0..38ecd2f576 100644 --- a/packages/plugins/sentry/__tests__/sentry.spec.ts +++ b/packages/plugins/sentry/__tests__/sentry.spec.ts @@ -43,8 +43,7 @@ describe('sentry', () => { } `); - // run sentry flush - await new Promise(res => setTimeout(res, 10)); + await Sentry.flush(); const reports = sentryTestkit.reports(); expect(reports).toHaveLength(1); @@ -89,8 +88,7 @@ describe('sentry', () => { } `); - // run sentry flush - await new Promise(res => setTimeout(res, 10)); + await Sentry.flush(); expect(sentryTestkit.reports()).toHaveLength(0); }); @@ -130,8 +128,7 @@ describe('sentry', () => { } `); - // run sentry flush - await new Promise(res => setTimeout(res, 10)); + await Sentry.flush(); const reports = sentryTestkit.reports(); expect(reports).toHaveLength(1); @@ -176,8 +173,7 @@ describe('sentry', () => { } `); - // run sentry flush - await new Promise(res => setTimeout(res, 10)); + await Sentry.flush(); expect(sentryTestkit.reports()).toHaveLength(0); }); @@ -246,8 +242,7 @@ describe('sentry', () => { } `); - // run sentry flush - await new Promise(res => setTimeout(res, 10)); + await Sentry.flush(); const reports = sentryTestkit.reports(); expect(reports).toHaveLength(1); @@ -257,3 +252,40 @@ describe('sentry', () => { }); }); }); + +test('sets the span in the query context', async () => { + const { testkit: sentryTestkit, sentryTransport } = createSentryTestkit(); + Sentry.init({ + dsn: 'https://public@sentry.example.com/2', + transport: sentryTransport, + }); + + // The test verifies that the span is set in the context, which would be + // available as the third argument + const schema = makeExecutableSchema({ + typeDefs: /* GraphQL */ ` + type Query { + hasSentryInContext: String! + } + `, + resolvers: { + Query: { + hasSentryInContext: async (args, info, ctx) => { + return !!ctx.sentry; + }, + }, + }, + }); + + const envelopTestkit = createTestkit([useSentry()], schema); + const result = await envelopTestkit.execute('{ hasSentryInContext }'); + expect(result).toMatchInlineSnapshot(` + Object { + "data": Object { + "hasSentryInContext": "true", + }, + } + `); + + await Sentry.flush(); +}); diff --git a/packages/plugins/sentry/src/index.ts b/packages/plugins/sentry/src/index.ts index 39985303fc..f73a4b401e 100644 --- a/packages/plugins/sentry/src/index.ts +++ b/packages/plugins/sentry/src/index.ts @@ -104,7 +104,7 @@ export const useSentry = (options: SentryPluginOptions = {}): Plugin => { } return { - onExecute({ args }) { + onExecute({ args, extendContext }) { if (skipOperation(args)) { return; } @@ -179,6 +179,8 @@ export const useSentry = (options: SentryPluginOptions = {}): Plugin => { Sentry.configureScope(scope => options.configureScope!(args, scope)); } + extendContext({ sentry: { scope } }); + return { onExecuteDone(payload) { const handleResult: OnExecuteDoneHookResultOnNextHook<{}> = ({ result, setResult }) => {