Skip to content

Commit f44352c

Browse files
committed
fixup: review fixes
1 parent 6ff58c0 commit f44352c

File tree

8 files changed

+249
-192
lines changed

8 files changed

+249
-192
lines changed

packages/core/src/integrations/express/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ export const patchExpressModule = (options: ExpressIntegrationOptions) => {
112112
function useTrace(this: ExpressApplication, ...args: Parameters<typeof originalRouterUse>) {
113113
const route = originalRouterUse.apply(this, args);
114114
const layer = this.stack[this.stack.length - 1];
115-
if (!layer) return route;
115+
if (!layer) {
116+
return route;
117+
}
116118
patchLayer(options, layer, getLayerPath(args));
117119
return route;
118120
},

packages/core/src/integrations/express/patch-layer.ts

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1+
import { DEBUG_BUILD } from '../../debug-build';
12
import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';
23
import { SPAN_STATUS_ERROR, startSpanManual, withActiveSpan } from '../../tracing';
4+
import { debug } from '../../utils/debug-logger';
35
import type { SpanAttributes } from '../../types-hoist/span';
46
import { getActiveSpan } from '../../utils/spanUtils';
57
import { getStoredLayers, storeLayer } from './request-layer-store';
68
import {
79
type ExpressRequest,
810
type ExpressResponse,
9-
kLayerPatched,
1011
type ExpressIntegrationOptions,
1112
type ExpressLayer,
1213
ATTR_HTTP_ROUTE,
1314
ATTR_EXPRESS_TYPE,
1415
ATTR_EXPRESS_NAME,
15-
type ExpressLayerType,
1616
ExpressLayerType_MIDDLEWARE,
1717
ExpressLayerType_ROUTER,
1818
} from './types';
@@ -21,27 +21,31 @@ import {
2121
getActualMatchedRoute,
2222
getConstructedRoute,
2323
getLayerMetadata,
24-
getSpanName,
2524
isLayerIgnored,
2625
} from './utils';
26+
import { getIsolationScope } from '../../currentScopes';
27+
import { getDefaultIsolationScope } from '../../defaultScopes';
28+
import { getOriginalFunction, markFunctionWrapped } from '../../utils/object';
2729

2830
export type ExpressPatchLayerOptions = Pick<
2931
ExpressIntegrationOptions,
3032
'onRouteResolved' | 'ignoreLayers' | 'ignoreLayersType'
3133
>;
3234

3335
export function patchLayer(options: ExpressPatchLayerOptions, maybeLayer?: ExpressLayer, layerPath?: string): void {
34-
if (!maybeLayer) {
36+
if (!maybeLayer?.handle) {
3537
return;
3638
}
3739
const layer = maybeLayer;
3840

41+
const layerHandleOriginal = layer.handle;
42+
3943
// avoid patching multiple times the same layer
40-
if (layer[kLayerPatched] === true) return;
41-
layer[kLayerPatched] = true;
44+
if (getOriginalFunction(layerHandleOriginal)) {
45+
return;
46+
}
4247

43-
const originalHandle = layer.handle;
44-
if (originalHandle.length === 4) {
48+
if (layerHandleOriginal.length === 4) {
4549
// todo: instrument error handlers
4650
return;
4751
}
@@ -57,10 +61,12 @@ export function patchLayer(options: ExpressPatchLayerOptions, maybeLayer?: Expre
5761
// Without a parent span, this request is being ignored, so skip it
5862
const parentSpan = getActiveSpan();
5963
if (!parentSpan) {
60-
return originalHandle.apply(this, [req, res, ...otherArgs]);
64+
return layerHandleOriginal.apply(this, [req, res, ...otherArgs]);
6165
}
6266

63-
if (layerPath) storeLayer(req, layerPath);
67+
if (layerPath) {
68+
storeLayer(req, layerPath);
69+
}
6470
const storedLayers = getStoredLayers(req);
6571
const isLayerPathStored = !!layerPath;
6672

@@ -70,8 +76,8 @@ export function patchLayer(options: ExpressPatchLayerOptions, maybeLayer?: Expre
7076
options.onRouteResolved?.(actualMatchedRoute);
7177

7278
const metadata = getLayerMetadata(constructedRoute, layer, layerPath);
73-
const name = metadata.attributes[ATTR_EXPRESS_NAME] as string ?? metadata.name;
74-
const type = metadata.attributes[ATTR_EXPRESS_TYPE] as ExpressLayerType;
79+
const name = metadata.attributes[ATTR_EXPRESS_NAME];
80+
const type = metadata.attributes[ATTR_EXPRESS_TYPE];
7581
const attributes: SpanAttributes = Object.assign(metadata.attributes, {
7682
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.express',
7783
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${type}.express`,
@@ -91,18 +97,21 @@ export function patchLayer(options: ExpressPatchLayerOptions, maybeLayer?: Expre
9197
if (isLayerPathStored && type === ExpressLayerType_MIDDLEWARE) {
9298
storedLayers.pop();
9399
}
94-
return originalHandle.apply(this, [req, res, ...otherArgs]);
100+
return layerHandleOriginal.apply(this, [req, res, ...otherArgs]);
95101
}
96102

97-
const spanName = getSpanName(
98-
{
99-
request: req,
100-
layerType: type,
101-
route: constructedRoute,
102-
},
103-
name,
104-
);
105-
return startSpanManual({ name: spanName, attributes }, span => {
103+
const currentScope = getIsolationScope();
104+
if (currentScope !== getDefaultIsolationScope()) {
105+
if (type === 'request_handler') {
106+
// type cast b/c Otel unfortunately types info.request as any :(
107+
const method = req.method ? req.method.toUpperCase() : 'GET';
108+
currentScope.setTransactionName(`${method} ${constructedRoute}`);
109+
}
110+
} else {
111+
DEBUG_BUILD && debug.warn('Isolation scope is still default isolation scope - skipping setting transactionName');
112+
}
113+
114+
return startSpanManual({ name, attributes }, span => {
106115
let spanHasEnded = false;
107116
// TODO: Fix router spans (getRouterPath does not work properly) to
108117
// have useful names before removing this branch
@@ -121,7 +130,9 @@ export function patchLayer(options: ExpressPatchLayerOptions, maybeLayer?: Expre
121130
// verify we have a callback
122131
for (let i = 0; i < otherArgs.length; i++) {
123132
const callback = otherArgs[i] as Function;
124-
if (typeof callback !== 'function') continue;
133+
if (typeof callback !== 'function') {
134+
continue;
135+
}
125136

126137
//oxlint-disable-next-line no-explicit-any
127138
otherArgs[i] = function (...args: any[]) {
@@ -155,7 +166,7 @@ export function patchLayer(options: ExpressPatchLayerOptions, maybeLayer?: Expre
155166
}
156167

157168
try {
158-
return originalHandle.apply(this, [req, res, ...otherArgs]);
169+
return layerHandleOriginal.apply(this, [req, res, ...otherArgs]);
159170
} catch (anyError) {
160171
const [_, message] = asErrorAndMessage(anyError);
161172
// intentionally do not record the exception here, because
@@ -186,21 +197,23 @@ export function patchLayer(options: ExpressPatchLayerOptions, maybeLayer?: Expre
186197
// ref: https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1950
187198
// ref: https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2271
188199
// oxlint-disable-next-line guard-for-in
189-
for (const key in originalHandle as Function & Record<string, unknown>) {
200+
for (const key in layerHandleOriginal as Function & Record<string, unknown>) {
190201
// skip standard function prototype fields that both have
191202
if (key in layerHandlePatched) {
192203
continue;
193204
}
194205
Object.defineProperty(layerHandlePatched, key, {
195206
get() {
196-
return originalHandle[key];
207+
return layerHandleOriginal[key];
197208
},
198209
set(value) {
199-
originalHandle[key] = value;
210+
layerHandleOriginal[key] = value;
200211
},
201212
});
202213
}
203214

215+
markFunctionWrapped(layerHandlePatched, layerHandleOriginal);
216+
204217
Object.defineProperty(layer, 'handle', {
205218
enumerable: true,
206219
configurable: true,

packages/core/src/integrations/express/request-layer-store.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ import type { ExpressRequest } from './types';
44
const requestLayerStore = new WeakMap<ExpressRequest, string[]>();
55
export const storeLayer = (req: ExpressRequest, layer: string) => {
66
const store = requestLayerStore.get(req);
7-
if (!store) requestLayerStore.set(req, [layer]);
8-
else store.push(layer);
7+
if (!store) {
8+
requestLayerStore.set(req, [layer]);
9+
} else {
10+
store.push(layer);
11+
}
912
};
1013

1114
export const getStoredLayers = (req: ExpressRequest) => {
12-
const store = requestLayerStore.get(req);
13-
if (store) return store;
14-
else {
15-
const store: string[] = [];
15+
let store = requestLayerStore.get(req);
16+
if (!store) {
17+
store = [];
1618
requestLayerStore.set(req, store);
17-
return store;
1819
}
20+
return store;
1921
};

packages/core/src/integrations/express/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { RequestEventData } from '../../types-hoist/request';
22
import type { SpanAttributes } from '../../types-hoist/span';
33

4-
export const kLayerPatched: unique symbol = Symbol('express-layer-patched');
54
export const ATTR_EXPRESS_NAME = 'express.name';
65
export const ATTR_HTTP_ROUTE = 'http.route';
76
export const ATTR_EXPRESS_TYPE = 'express.type';

packages/core/src/integrations/express/utils.ts

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import { getIsolationScope } from '../../currentScopes';
2-
import { DEBUG_BUILD } from '../../debug-build';
3-
import { getDefaultIsolationScope } from '../../defaultScopes';
4-
import { debug } from '../../utils/debug-logger';
51
import type { SpanAttributes } from '../../types-hoist/span';
62
import { getStoredLayers } from './request-layer-store';
73
import type {
@@ -10,7 +6,6 @@ import type {
106
ExpressLayer,
117
ExpressLayerType,
128
ExpressRequest,
13-
ExpressRequestInfo,
149
IgnoreMatcher,
1510
LayerPathSegment,
1611
MiddlewareError,
@@ -27,17 +22,6 @@ import {
2722
} from './types';
2823
import { isMatchingPattern } from '../../utils/string';
2924

30-
/**
31-
* Check whether the given obj match pattern
32-
* @param constant e.g URL of request
33-
* @param obj obj to inspect
34-
* @param pattern Match pattern
35-
*/
36-
export const satisfiesPattern = (constant: string, pattern: IgnoreMatcher): boolean => {
37-
// XXX replace calls to satisfiesPattern with this:
38-
return isMatchingPattern(constant, pattern, true);
39-
};
40-
4125
/**
4226
* Converts a user-provided error value into an error and error message pair
4327
*
@@ -66,7 +50,7 @@ export const getLayerMetadata = (
6650
layer: ExpressLayer,
6751
layerPath?: string,
6852
): {
69-
attributes: SpanAttributes;
53+
attributes: SpanAttributes & { [ATTR_EXPRESS_NAME]: string; [ATTR_EXPRESS_TYPE]: ExpressLayerType };
7054
name: string;
7155
} => {
7256
if (layer.name === 'router') {
@@ -136,10 +120,12 @@ export const isLayerIgnored = (
136120
if (Array.isArray(config?.ignoreLayersType) && config?.ignoreLayersType?.includes(type)) {
137121
return true;
138122
}
139-
if (!Array.isArray(config?.ignoreLayers)) return false;
123+
if (!Array.isArray(config?.ignoreLayers)) {
124+
return false;
125+
}
140126
try {
141127
for (const pattern of config.ignoreLayers) {
142-
if (satisfiesPattern(name, pattern)) {
128+
if (isMatchingPattern(name, pattern, true)) {
143129
return true;
144130
}
145131
}
@@ -251,20 +237,6 @@ export const hasDefaultProp = (
251237
default: ExpressExport;
252238
} => !!express && typeof express === 'object' && 'default' in express && typeof express.default === 'function';
253239

254-
export function getSpanName(info: ExpressRequestInfo<unknown>, defaultName: string): string {
255-
if (getIsolationScope() === getDefaultIsolationScope()) {
256-
DEBUG_BUILD && debug.warn('Isolation scope is still default isolation scope - skipping setting transactionName');
257-
return defaultName;
258-
}
259-
if (info.layerType === 'request_handler') {
260-
// type cast b/c Otel unfortunately types info.request as any :(
261-
const req = info.request as { method?: string };
262-
const method = req.method ? req.method.toUpperCase() : 'GET';
263-
getIsolationScope().setTransactionName(`${method} ${info.route}`);
264-
}
265-
return defaultName;
266-
}
267-
268240
function getStatusCodeFromResponse(error: MiddlewareError): number {
269241
const statusCode = error.status || error.statusCode || error.status_code || error.output?.statusCode;
270242
return statusCode ? parseInt(statusCode as string, 10) : 500;

0 commit comments

Comments
 (0)