Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ Deno.test('hapi instrumentation: orchestrion:@hapi/hapi:route channel wraps the
"'parent' transaction",
);

const hapiSpan = parent.spans?.find(s => s.op === 'router.hapi');
assertExists(hapiSpan, `expected a router.hapi span, got ops: ${parent.spans?.map(s => s.op).join(', ')}`);
const hapiSpan = parent.spans?.find(s => s.op === 'router');
assertExists(hapiSpan, `expected a router span, got ops: ${parent.spans?.map(s => s.op).join(', ')}`);
assertEquals(hapiSpan!.description, 'GET /hello');
assertEquals(hapiSpan!.data?.['hapi.type'], 'router');
assertEquals(hapiSpan!.data?.['http.route'], '/hello');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ test('Sends successful transaction', async ({ baseURL }) => {
'hapi.type': 'router',
'http.method': 'GET',
'http.route': '/test-success',
'sentry.op': 'router.hapi',
'sentry.op': 'router',
'sentry.origin': 'auto.http.hapi',
},
description: 'GET /test-success',
op: 'router.hapi',
op: 'router',
origin: 'auto.http.hapi',
parent_span_id: expect.stringMatching(/[a-f0-9]{16}/),
span_id: expect.stringMatching(/[a-f0-9]{16}/),
Expand All @@ -91,12 +91,12 @@ test('Sends successful transaction', async ({ baseURL }) => {
// this comes from "onPreResponse"
data: {
'hapi.type': 'server.ext',
'sentry.op': 'server.ext.hapi',
'sentry.op': 'middleware',
'sentry.origin': 'auto.http.hapi',
'server.ext.type': 'onPreResponse',
},
description: 'ext - onPreResponse',
op: 'server.ext.hapi',
op: 'middleware',
origin: 'auto.http.hapi',
parent_span_id: expect.stringMatching(/[a-f0-9]{16}/),
span_id: expect.stringMatching(/[a-f0-9]{16}/),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ test('instruments RegExp router routes', async ({ baseURL }) => {
expect(transactionEvent.spans).toEqual(
expect.arrayContaining([
expect.objectContaining({
op: 'router.koa',
op: 'router',
origin: 'auto.http.koa',
data: expect.objectContaining({
'koa.type': 'router',
'sentry.op': 'router.koa',
'sentry.op': 'router',
'sentry.origin': 'auto.http.koa',
'http.route': '/^\\/test-regexp/',
}),
Expand All @@ -43,12 +43,12 @@ test('instruments nested routers with the composed http.route', async ({ baseURL
expect(transactionEvent.spans).toEqual(
expect.arrayContaining([
expect.objectContaining({
op: 'router.koa',
op: 'router',
description: '/:first/details/:id',
data: expect.objectContaining({
'koa.type': 'router',
'http.route': '/:first/details/:id',
'sentry.op': 'router.koa',
'sentry.op': 'router',
'sentry.origin': 'auto.http.koa',
}),
}),
Expand All @@ -69,9 +69,7 @@ test('does not instrument the same middleware twice', async ({ baseURL }) => {

// The route stack is [sharedRouteMiddleware, sharedRouteMiddleware, handler]; the repeated
// middleware instance is skipped, leaving one span for it plus the handler span.
const dedupSpans = transactionEvent.spans?.filter(
span => span.op === 'router.koa' && span.description === '/test-dedup',
);
const dedupSpans = transactionEvent.spans?.filter(span => span.op === 'router' && span.description === '/test-dedup');
expect(dedupSpans).toHaveLength(2);
});

Expand All @@ -90,7 +88,7 @@ test('marks the layer span as errored when a handler throws', async ({ baseURL }
expect(transactionEvent.spans).toEqual(
expect.arrayContaining([
expect.objectContaining({
op: 'router.koa',
op: 'router',
origin: 'auto.http.koa',
status: 'internal_error',
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ test('Sends an API route transaction', async ({ baseURL }) => {
'koa.name': '/test-transaction',
'koa.type': 'router',
'sentry.origin': 'auto.http.koa',
'sentry.op': 'router.koa',
'sentry.op': 'router',
},
op: 'router.koa',
op: 'router',
description: '/test-transaction',
parent_span_id: expect.stringMatching(/[a-f0-9]{16}/),
span_id: expect.stringMatching(/[a-f0-9]{16}/),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const run = async () => {
},
});

// Server extension produces a `server.ext.hapi` span.
// Server extension produces a `middleware` span.
server.ext('onPreResponse', (request, h) => h.continue);

await Sentry.setupHapiErrorHandler(server);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ describe('hapi auto-instrumentation', () => {
'http.method': 'GET',
'hapi.type': 'router',
'sentry.origin': origin,
'sentry.op': 'router.hapi',
'sentry.op': 'router',
}),
description: 'GET /',
op: 'router.hapi',
op: 'router',
origin,
status: 'ok',
}),
Expand Down Expand Up @@ -70,12 +70,12 @@ describe('hapi auto-instrumentation', () => {
}),
expect.objectContaining({
description: 'ext - onPreResponse',
op: 'server.ext.hapi',
op: 'middleware',
origin,
data: expect.objectContaining({
'hapi.type': 'server.ext',
'server.ext.type': 'onPreResponse',
'sentry.op': 'server.ext.hapi',
'sentry.op': 'middleware',
'sentry.origin': origin,
}),
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ describe('koa auto-instrumentation', () => {
// Router layer span (from `@koa/router`), carrying the matched route.
expect.objectContaining({
description: '/',
op: 'router.koa',
op: 'router',
origin,
data: expect.objectContaining({
'http.route': '/',
'koa.type': 'router',
'koa.name': '/',
'sentry.op': 'router.koa',
'sentry.op': 'router',
'sentry.origin': origin,
}),
}),
Expand Down Expand Up @@ -73,13 +73,13 @@ describe('koa auto-instrumentation', () => {
spans: expect.arrayContaining([
expect.objectContaining({
description: '/test-param/:id',
op: 'router.koa',
op: 'router',
origin,
data: expect.objectContaining({
'http.route': '/test-param/:id',
'koa.type': 'router',
'koa.name': '/test-param/:id',
'sentry.op': 'router.koa',
'sentry.op': 'router',
'sentry.origin': origin,
}),
}),
Expand Down
17 changes: 10 additions & 7 deletions packages/core/src/integrations/express/patch-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ import {
ATTR_EXPRESS_TYPE,
ATTR_EXPRESS_NAME,
ExpressLayerType_ROUTER,
ExpressLayerType_MIDDLEWARE,
ExpressLayerType_REQUEST_HANDLER,
} from './types';
import {
asErrorAndMessage,
Expand All @@ -58,6 +60,13 @@ import { getDefaultIsolationScope } from '../../defaultScopes';
import { getOriginalFunction, markFunctionWrapped } from '../../utils/object';
import { setSDKProcessingMetadata } from './set-sdk-processing-metadata';

// TODO(conventions): Replace `'handler'` and `'router'` with their span op constants once they are released in `@sentry/conventions`.
const EXPRESS_TYPE_TO_SPAN_OP: Record<string, string> = {
[ExpressLayerType_MIDDLEWARE]: WEB_SERVER_MIDDLEWARE_SPAN_OP,
[ExpressLayerType_REQUEST_HANDLER]: 'handler',
[ExpressLayerType_ROUTER]: 'router',
};

export type ExpressPatchLayerOptions = Pick<
ExpressIntegrationOptions,
'onRouteResolved' | 'ignoreLayers' | 'ignoreLayersType'
Expand Down Expand Up @@ -124,13 +133,7 @@ export function patchLayer(
const type = metadata.attributes[ATTR_EXPRESS_TYPE];
const attributes: SpanAttributes = Object.assign(metadata.attributes, {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.express',
[SENTRY_OP]:
type === 'middleware'
? WEB_SERVER_MIDDLEWARE_SPAN_OP
: type === 'request_handler'
? // TODO(conventions): Replace with the `handler` span op constant once it is released in `@sentry/conventions`.
'handler'
: `${type}.express`,
[SENTRY_OP]: EXPRESS_TYPE_TO_SPAN_OP[type],
});
if (actualMatchedRoute) {
attributes[ATTR_HTTP_ROUTE] = actualMatchedRoute;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ describe('patchLayer', () => {
data: {
'express.name': '/c',
'express.type': 'router',
'sentry.op': 'router.express',
'sentry.op': 'router',
'sentry.origin': 'auto.http.express',
},
description: '/c',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ const ORIGIN = 'auto.http.express';
const ATTR_EXPRESS_NAME = 'express.name';
const ATTR_EXPRESS_TYPE = 'express.type';

// TODO(conventions): Replace `'handler'` and `'router'` with their span op constants once they are released in `@sentry/conventions`.
const EXPRESS_TYPE_TO_SPAN_OP: Record<string, string> = {
middleware: WEB_SERVER_MIDDLEWARE_SPAN_OP,
request_handler: 'handler',
router: 'router',
};

const NOOP = (): void => {};

let _isInstrumented = false;
Expand Down Expand Up @@ -221,13 +228,7 @@ function getSpanForLayer(data: HandleChannelContext, options: ExpressIntegration
name,
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
[SENTRY_OP]:
type === 'middleware'
? WEB_SERVER_MIDDLEWARE_SPAN_OP
: type === 'request_handler'
? // TODO(conventions): Replace with the `handler` span op constant once it is released in `@sentry/conventions`.
'handler'
: `${type}.express`,
[SENTRY_OP]: EXPRESS_TYPE_TO_SPAN_OP[type],
[ATTR_EXPRESS_NAME]: name,
[ATTR_EXPRESS_TYPE]: type,
...(matchedRoute ? { [HTTP_ROUTE]: matchedRoute } : {}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
* wrap logic from the vendored `@opentelemetry/instrumentation-hapi`
* (upstream @opentelemetry/instrumentation-hapi@0.64.0). Span output (names,
* origins, attributes) is kept close to that instrumentation — except the
* plugin-route op, which is normalized to the cross-framework `handler` op;
* span creation goes through the `@sentry/core` API and the OTel active-span
* guard is replaced with `getActiveSpan()`.
* span ops, which are normalized to cross-framework ops (`handler` for plugin
* routes, `router` for routes, `middleware` for server extensions); span
* creation goes through the `@sentry/core` API and the OTel active-span guard
* is replaced with `getActiveSpan()`.
*/

import { getActiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/core';
import { SENTRY_OP } from '@sentry/conventions/attributes';
import { WEB_SERVER_MIDDLEWARE_SPAN_OP } from '@sentry/conventions/op';
import type {
LifecycleMethod,
PatchableExtMethod,
Expand Down Expand Up @@ -105,10 +107,16 @@ export const getExtMetadata = (
};
};

// TODO(conventions): Replace `'handler'` and `'router'` with their span op constants once they are released in `@sentry/conventions`.
const HAPI_TYPE_TO_SPAN_OP: Record<string, string> = {
[HapiLayerType.PLUGIN]: 'handler',
[HapiLayerType.ROUTER]: 'router',
[HapiLayerType.EXT]: WEB_SERVER_MIDDLEWARE_SPAN_OP,
};

function startMetadataSpan(metadata: SpanMetadata, original: () => unknown): unknown {
const hapiType = metadata.attributes[AttributeNames.HAPI_TYPE];
// TODO(conventions): Replace `'handler'` with the `handler` span op constant once it is released in `@sentry/conventions`.
const op = hapiType === HapiLayerType.PLUGIN ? 'handler' : `${hapiType}.hapi`;
const op = hapiType ? HAPI_TYPE_TO_SPAN_OP[hapiType] : undefined;
return startSpan(
{
name: metadata.name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ function patchLayer(
name,
attributes: {
...metadata.attributes,
[SENTRY_OP]: layerType === LAYER_TYPE.MIDDLEWARE ? WEB_SERVER_MIDDLEWARE_SPAN_OP : `${layerType}.koa`,
// TODO(conventions): Replace `'router'` with the `router` span op constant once it is released in `@sentry/conventions`.
[SENTRY_OP]: layerType === LAYER_TYPE.MIDDLEWARE ? WEB_SERVER_MIDDLEWARE_SPAN_OP : 'router',
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
},
},
Expand Down
Loading