Skip to content

ref(node-experimental): Refactor usage of startChild() #11047

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

Merged
merged 1 commit into from
Mar 12, 2024
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
58 changes: 21 additions & 37 deletions packages/tracing-internal/src/node/integrations/apollo.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Hub, SentrySpan } from '@sentry/core';
import type { EventProcessor } from '@sentry/types';
import { arrayify, fill, isThenable, loadModule, logger } from '@sentry/utils';
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/core';
import { arrayify, fill, loadModule, logger } from '@sentry/utils';

import { DEBUG_BUILD } from '../../common/debug-build';
import type { LazyLoadedIntegration } from './lazy';
Expand Down Expand Up @@ -75,7 +74,7 @@ export class Apollo implements LazyLoadedIntegration<GraphQLModule & ApolloModul
/**
* @inheritDoc
*/
public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
public setupOnce(): void {
if (this._useNest) {
const pkg = this.loadDependency();

Expand All @@ -99,7 +98,7 @@ export class Apollo implements LazyLoadedIntegration<GraphQLModule & ApolloModul
return function (this: unknown) {
const resolvers = arrayify(orig.call(this));

const instrumentedResolvers = instrumentResolvers(resolvers, getCurrentHub);
const instrumentedResolvers = instrumentResolvers(resolvers);

return instrumentedResolvers;
};
Expand Down Expand Up @@ -146,7 +145,7 @@ export class Apollo implements LazyLoadedIntegration<GraphQLModule & ApolloModul

const resolvers = arrayify(this.config.resolvers);

this.config.resolvers = instrumentResolvers(resolvers, getCurrentHub);
this.config.resolvers = instrumentResolvers(resolvers);

return orig.call(this);
};
Expand All @@ -155,15 +154,15 @@ export class Apollo implements LazyLoadedIntegration<GraphQLModule & ApolloModul
}
}

function instrumentResolvers(resolvers: ApolloModelResolvers[], getCurrentHub: () => Hub): ApolloModelResolvers[] {
function instrumentResolvers(resolvers: ApolloModelResolvers[]): ApolloModelResolvers[] {
return resolvers.map(model => {
Object.keys(model).forEach(resolverGroupName => {
Object.keys(model[resolverGroupName]).forEach(resolverName => {
if (typeof model[resolverGroupName][resolverName] !== 'function') {
return;
}

wrapResolver(model, resolverGroupName, resolverName, getCurrentHub);
wrapResolver(model, resolverGroupName, resolverName);
});
});

Expand All @@ -174,37 +173,22 @@ function instrumentResolvers(resolvers: ApolloModelResolvers[], getCurrentHub: (
/**
* Wrap a single resolver which can be a parent of other resolvers and/or db operations.
*/
function wrapResolver(
model: ApolloModelResolvers,
resolverGroupName: string,
resolverName: string,
getCurrentHub: () => Hub,
): void {
function wrapResolver(model: ApolloModelResolvers, resolverGroupName: string, resolverName: string): void {
fill(model[resolverGroupName], resolverName, function (orig: () => unknown | Promise<unknown>) {
return function (this: unknown, ...args: unknown[]) {
// eslint-disable-next-line deprecation/deprecation
const scope = getCurrentHub().getScope();
// eslint-disable-next-line deprecation/deprecation
const parentSpan = scope.getSpan() as SentrySpan | undefined;
// eslint-disable-next-line deprecation/deprecation
const span = parentSpan?.startChild({
name: `${resolverGroupName}.${resolverName}`,
op: 'graphql.resolve',
origin: 'auto.graphql.apollo',
});

const rv = orig.call(this, ...args);

if (isThenable(rv)) {
return rv.then((res: unknown) => {
span?.end();
return res;
});
}

span?.end();

return rv;
return startSpan(
{
onlyIfParent: true,
name: `${resolverGroupName}.${resolverName}`,
op: 'graphql.resolve',
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.graphql.apollo',
},
},
() => {
return orig.call(this, ...args);
},
);
};
});
}
42 changes: 25 additions & 17 deletions packages/tracing-internal/src/node/integrations/express.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable max-lines */
import type { Transaction } from '@sentry/core';
import { startInactiveSpan, withActiveSpan } from '@sentry/core';
import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, spanToJSON } from '@sentry/core';
import type { Integration, PolymorphicRequest } from '@sentry/types';
import {
Expand Down Expand Up @@ -153,11 +154,12 @@ function wrap(fn: Function, method: Method): (...args: any[]) => void {
return function (this: NodeJS.Global, req: unknown, res: ExpressResponse & SentryTracingResponse): void {
const transaction = res.__sentry_transaction;
if (transaction) {
// eslint-disable-next-line deprecation/deprecation
const span = transaction.startChild({
name: fn.name,
op: `middleware.express.${method}`,
origin: 'auto.middleware.express',
const span = withActiveSpan(transaction, () => {
return startInactiveSpan({
name: fn.name,
op: `middleware.express.${method}`,
origin: 'auto.middleware.express',
});
});
res.once('finish', () => {
span.end();
Expand All @@ -174,12 +176,15 @@ function wrap(fn: Function, method: Method): (...args: any[]) => void {
next: () => void,
): void {
const transaction = res.__sentry_transaction;
// eslint-disable-next-line deprecation/deprecation
const span = transaction?.startChild({
name: fn.name,
op: `middleware.express.${method}`,
origin: 'auto.middleware.express',
});
const span = transaction
? withActiveSpan(transaction, () => {
return startInactiveSpan({
name: fn.name,
op: `middleware.express.${method}`,
origin: 'auto.middleware.express',
});
})
: undefined;
fn.call(this, req, res, function (this: NodeJS.Global, ...args: unknown[]): void {
span?.end();
next.call(this, ...args);
Expand All @@ -195,12 +200,15 @@ function wrap(fn: Function, method: Method): (...args: any[]) => void {
next: () => void,
): void {
const transaction = res.__sentry_transaction;
// eslint-disable-next-line deprecation/deprecation
const span = transaction?.startChild({
name: fn.name,
op: `middleware.express.${method}`,
origin: 'auto.middleware.express',
});
const span = transaction
? withActiveSpan(transaction, () => {
return startInactiveSpan({
name: fn.name,
op: `middleware.express.${method}`,
origin: 'auto.middleware.express',
});
})
: undefined;
fn.call(this, err, req, res, function (this: NodeJS.Global, ...args: unknown[]): void {
span?.end();
next.call(this, ...args);
Expand Down
51 changes: 16 additions & 35 deletions packages/tracing-internal/src/node/integrations/graphql.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Hub, SentrySpan } from '@sentry/core';
import type { EventProcessor } from '@sentry/types';
import { fill, isThenable, loadModule, logger } from '@sentry/utils';
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/core';
import { fill, loadModule, logger } from '@sentry/utils';

import { DEBUG_BUILD } from '../../common/debug-build';
import type { LazyLoadedIntegration } from './lazy';
Expand Down Expand Up @@ -35,7 +34,7 @@ export class GraphQL implements LazyLoadedIntegration<GraphQLModule> {
/**
* @inheritDoc
*/
public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
public setupOnce(): void {
const pkg = this.loadDependency();

if (!pkg) {
Expand All @@ -45,37 +44,19 @@ export class GraphQL implements LazyLoadedIntegration<GraphQLModule> {

fill(pkg, 'execute', function (orig: () => void | Promise<unknown>) {
return function (this: unknown, ...args: unknown[]) {
// eslint-disable-next-line deprecation/deprecation
const scope = getCurrentHub().getScope();
// eslint-disable-next-line deprecation/deprecation
const parentSpan = scope.getSpan() as SentrySpan | undefined;

// eslint-disable-next-line deprecation/deprecation
const span = parentSpan?.startChild({
name: 'execute',
op: 'graphql.execute',
origin: 'auto.graphql.graphql',
});

// eslint-disable-next-line deprecation/deprecation
scope?.setSpan(span);

const rv = orig.call(this, ...args);

if (isThenable(rv)) {
return rv.then((res: unknown) => {
span?.end();
// eslint-disable-next-line deprecation/deprecation
scope?.setSpan(parentSpan);

return res;
});
}

span?.end();
// eslint-disable-next-line deprecation/deprecation
scope?.setSpan(parentSpan);
return rv;
return startSpan(
{
onlyIfParent: true,
name: 'execute',
op: 'graphql.execute',
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.graphql.graphql',
},
},
() => {
return orig.call(this, ...args);
},
);
};
});
}
Expand Down
48 changes: 21 additions & 27 deletions packages/tracing-internal/src/node/integrations/mongo.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Hub, SentrySpan } from '@sentry/core';
import type { EventProcessor, SpanContext } from '@sentry/types';
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan } from '@sentry/core';
import { getClient } from '@sentry/core';
import type { EventProcessor, SpanAttributes, StartSpanOptions } from '@sentry/types';
import { fill, isThenable, loadModule, logger } from '@sentry/utils';

import { DEBUG_BUILD } from '../../common/debug-build';
Expand Down Expand Up @@ -138,7 +139,7 @@ export class Mongo implements LazyLoadedIntegration<MongoModule> {
/**
* @inheritDoc
*/
public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
public setupOnce(_: (callback: EventProcessor) => void): void {
const pkg = this.loadDependency();

if (!pkg) {
Expand All @@ -147,42 +148,36 @@ export class Mongo implements LazyLoadedIntegration<MongoModule> {
return;
}

this._instrumentOperations(pkg.Collection, this._operations, getCurrentHub);
this._instrumentOperations(pkg.Collection, this._operations);
}

/**
* Patches original collection methods
*/
private _instrumentOperations(collection: MongoCollection, operations: Operation[], getCurrentHub: () => Hub): void {
operations.forEach((operation: Operation) => this._patchOperation(collection, operation, getCurrentHub));
private _instrumentOperations(collection: MongoCollection, operations: Operation[]): void {
operations.forEach((operation: Operation) => this._patchOperation(collection, operation));
}

/**
* Patches original collection to utilize our tracing functionality
*/
private _patchOperation(collection: MongoCollection, operation: Operation, getCurrentHub: () => Hub): void {
private _patchOperation(collection: MongoCollection, operation: Operation): void {
if (!(operation in collection.prototype)) return;

const getSpanContext = this._getSpanContextFromOperationArguments.bind(this);

fill(collection.prototype, operation, function (orig: () => void | Promise<unknown>) {
return function (this: unknown, ...args: unknown[]) {
const lastArg = args[args.length - 1];
const hub = getCurrentHub();
// eslint-disable-next-line deprecation/deprecation
const scope = hub.getScope();
// eslint-disable-next-line deprecation/deprecation
const client = hub.getClient();
// eslint-disable-next-line deprecation/deprecation
const parentSpan = scope.getSpan() as SentrySpan | undefined;

const client = getClient();

const sendDefaultPii = client?.getOptions().sendDefaultPii;

// Check if the operation was passed a callback. (mapReduce requires a different check, as
// its (non-callback) arguments can also be functions.)
if (typeof lastArg !== 'function' || (operation === 'mapReduce' && args.length === 2)) {
// eslint-disable-next-line deprecation/deprecation
const span = parentSpan?.startChild(getSpanContext(this, operation, args, sendDefaultPii));
const span = startInactiveSpan(getSpanContext(this, operation, args, sendDefaultPii));
const maybePromiseOrCursor = orig.call(this, ...args);

if (isThenable(maybePromiseOrCursor)) {
Expand Down Expand Up @@ -213,8 +208,7 @@ export class Mongo implements LazyLoadedIntegration<MongoModule> {
}
}

// eslint-disable-next-line deprecation/deprecation
const span = parentSpan?.startChild(getSpanContext(this, operation, args.slice(0, -1)));
const span = startInactiveSpan(getSpanContext(this, operation, args.slice(0, -1)));

return orig.call(this, ...args.slice(0, -1), function (err: Error, result: unknown) {
span?.end();
Expand All @@ -232,19 +226,19 @@ export class Mongo implements LazyLoadedIntegration<MongoModule> {
operation: Operation,
args: unknown[],
sendDefaultPii: boolean | undefined = false,
): SpanContext {
const data: { [key: string]: string } = {
): StartSpanOptions {
const attributes: SpanAttributes = {
'db.system': 'mongodb',
'db.name': collection.dbName,
'db.operation': operation,
'db.mongodb.collection': collection.collectionName,
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `${collection.collectionName}.${operation}`,
};
const spanContext: SpanContext = {
const spanContext: StartSpanOptions = {
op: 'db',
// TODO v8: Use `${collection.collectionName}.${operation}`
origin: 'auto.db.mongo',
name: operation,
data,
attributes,
onlyIfParent: true,
};

// If the operation takes no arguments besides `options` and `callback`, or if argument
Expand All @@ -262,11 +256,11 @@ export class Mongo implements LazyLoadedIntegration<MongoModule> {
// Special case for `mapReduce`, as the only one accepting functions as arguments.
if (operation === 'mapReduce') {
const [map, reduce] = args as { name?: string }[];
data[signature[0]] = typeof map === 'string' ? map : map.name || '<anonymous>';
data[signature[1]] = typeof reduce === 'string' ? reduce : reduce.name || '<anonymous>';
attributes[signature[0]] = typeof map === 'string' ? map : map.name || '<anonymous>';
attributes[signature[1]] = typeof reduce === 'string' ? reduce : reduce.name || '<anonymous>';
} else {
for (let i = 0; i < signature.length; i++) {
data[`db.mongodb.${signature[i]}`] = JSON.stringify(args[i]);
attributes[`db.mongodb.${signature[i]}`] = JSON.stringify(args[i]);
}
}
} catch (_oO) {
Expand Down
Loading