Skip to content
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

feat(nextjs): Add status to data-fetcher spans #5777

Merged
merged 1 commit into from
Sep 20, 2022
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
22 changes: 19 additions & 3 deletions packages/nextjs/src/config/wrappers/wrapperUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export function callTracedServerSideDataFetcher<F extends (...args: any[]) => Pr
op: 'nextjs.data.server',
name: options.requestedRouteName,
...traceparentData,
status: 'ok',
metadata: {
source: 'route',
dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext,
Expand All @@ -116,6 +117,7 @@ export function callTracedServerSideDataFetcher<F extends (...args: any[]) => Pr
const dataFetcherSpan = requestTransaction.startChild({
op: 'nextjs.data.server',
description: `${options.dataFetchingMethodName} (${options.dataFetcherRouteName})`,
status: 'ok',
});

const currentScope = getCurrentHub().getScope();
Expand All @@ -137,6 +139,17 @@ export function callTracedServerSideDataFetcher<F extends (...args: any[]) => Pr

try {
return await origFunction(...origFunctionArguments);
} catch (e) {
// Since we finish the span before the error can bubble up and trigger the handlers in `registerErrorInstrumentation`
// that set the transaction status, we need to manually set the status of the span & transaction
dataFetcherSpan.setStatus('internal_error');

const transaction = dataFetcherSpan.transaction;
if (transaction) {
transaction.setStatus('internal_error');
}

throw e;
} finally {
dataFetcherSpan.finish();
}
Expand Down Expand Up @@ -178,14 +191,17 @@ export async function callDataFetcherTraced<F extends (...args: any[]) => Promis
const span = transaction.startChild({
op: 'nextjs.data.server',
description: `${dataFetchingMethodName} (${parameterizedRoute})`,
status: 'ok',
});

try {
return await origFunction(...origFunctionArgs);
} catch (err) {
if (span) {
span.finish();
}
// Since we finish the span before the error can bubble up and trigger the handlers in `registerErrorInstrumentation`
// that set the transaction status, we need to manually set the status of the span & transaction
transaction.setStatus('internal_error');
span.setStatus('internal_error');
span.finish();

// TODO Copy more robust error handling over from `withSentry`
captureException(err);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const assert = require('assert');

const { sleep } = require('../utils/common');
const { getAsync, interceptEventRequest } = require('../utils/server');
const { getAsync, interceptEventRequest, interceptTracingRequest } = require('../utils/server');

module.exports = async ({ url: urlBase, argv }) => {
const url = `${urlBase}/withErrorServerSideProps`;
Expand All @@ -28,8 +28,32 @@ module.exports = async ({ url: urlBase, argv }) => {
'errorServerSideProps',
);

const capturedTransactionRequest = interceptTracingRequest(
{
contexts: {
trace: {
op: 'nextjs.data.server',
status: 'internal_error',
},
},
transaction: '/withErrorServerSideProps',
transaction_info: {
source: 'route',
changes: [],
propagations: 0,
},
type: 'transaction',
request: {
url,
},
},
argv,
'errorServerSideProps',
);

await getAsync(url);
await sleep(250);

assert.ok(capturedRequest.isDone(), 'Did not intercept expected request');
assert.ok(capturedTransactionRequest.isDone(), 'Did not intercept expected transaction request');
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = async ({ url: urlBase, argv }) => {
contexts: {
trace: {
op: 'nextjs.data.server',
status: 'ok',
},
},
transaction: '/[id]/withInitialProps',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = async ({ url: urlBase, argv }) => {
contexts: {
trace: {
op: 'nextjs.data.server',
status: 'ok',
},
},
transaction: '/[id]/withServerSideProps',
Expand Down