Skip to content

Commit 9371029

Browse files
FlarnavmarchaudNaseem
authored
chore: avoid unneeded context.with in http instrumentation (#2043)
Avoid the overhead of context.with() by directly passing the extracted context to tracer.startSpan(). This ensures also that the extracted context is not accidently propagated out of the HTTP instrumentation. Co-authored-by: Valentin Marchaud <[email protected]> Co-authored-by: Naseem <[email protected]>
1 parent 9fc1b10 commit 9371029

File tree

1 file changed

+71
-68
lines changed
  • packages/opentelemetry-instrumentation-http/src

1 file changed

+71
-68
lines changed

packages/opentelemetry-instrumentation-http/src/http.ts

+71-68
Original file line numberDiff line numberDiff line change
@@ -405,72 +405,35 @@ export class HttpInstrumentation extends InstrumentationBase<Http> {
405405
}),
406406
};
407407

408-
return context.with(propagation.extract(ROOT_CONTEXT, headers), () => {
409-
const span = instrumentation._startHttpSpan(
410-
`${component.toLocaleUpperCase()} ${method}`,
411-
spanOptions
412-
);
413-
414-
return context.with(setSpan(context.active(), span), () => {
415-
context.bind(request);
416-
context.bind(response);
417-
418-
if (instrumentation._getConfig().requestHook) {
419-
instrumentation._callRequestHook(span, request);
420-
}
421-
if (instrumentation._getConfig().responseHook) {
422-
instrumentation._callResponseHook(span, response);
423-
}
424-
425-
// Wraps end (inspired by:
426-
// https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/blob/master/src/instrumentations/instrumentation-connect.ts#L75)
427-
const originalEnd = response.end;
428-
response.end = function (
429-
this: http.ServerResponse,
430-
..._args: ResponseEndArgs
431-
) {
432-
response.end = originalEnd;
433-
// Cannot pass args of type ResponseEndArgs,
434-
const returned = safeExecuteInTheMiddle(
435-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
436-
() => response.end.apply(this, arguments as any),
437-
error => {
438-
if (error) {
439-
utils.setSpanWithError(span, error);
440-
instrumentation._closeHttpSpan(span);
441-
throw error;
442-
}
443-
}
444-
);
445-
446-
const attributes = utils.getIncomingRequestAttributesOnResponse(
447-
request,
448-
response
449-
);
408+
const ctx = propagation.extract(ROOT_CONTEXT, headers);
409+
const span = instrumentation._startHttpSpan(
410+
`${component.toLocaleUpperCase()} ${method}`,
411+
spanOptions,
412+
ctx
413+
);
450414

451-
span
452-
.setAttributes(attributes)
453-
.setStatus(utils.parseResponseStatus(response.statusCode));
454-
455-
if (instrumentation._getConfig().applyCustomAttributesOnSpan) {
456-
safeExecuteInTheMiddle(
457-
() =>
458-
instrumentation._getConfig().applyCustomAttributesOnSpan!(
459-
span,
460-
request,
461-
response
462-
),
463-
() => {},
464-
true
465-
);
466-
}
415+
return context.with(setSpan(ctx, span), () => {
416+
context.bind(request);
417+
context.bind(response);
467418

468-
instrumentation._closeHttpSpan(span);
469-
return returned;
470-
};
419+
if (instrumentation._getConfig().requestHook) {
420+
instrumentation._callRequestHook(span, request);
421+
}
422+
if (instrumentation._getConfig().responseHook) {
423+
instrumentation._callResponseHook(span, response);
424+
}
471425

472-
return safeExecuteInTheMiddle(
473-
() => original.apply(this, [event, ...args]),
426+
// Wraps end (inspired by:
427+
// https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/blob/master/src/instrumentations/instrumentation-connect.ts#L75)
428+
const originalEnd = response.end;
429+
response.end = function (
430+
this: http.ServerResponse,
431+
..._args: ResponseEndArgs
432+
) {
433+
response.end = originalEnd;
434+
// Cannot pass args of type ResponseEndArgs,
435+
const returned = safeExecuteInTheMiddle(
436+
() => response.end.apply(this, arguments as never),
474437
error => {
475438
if (error) {
476439
utils.setSpanWithError(span, error);
@@ -479,7 +442,43 @@ export class HttpInstrumentation extends InstrumentationBase<Http> {
479442
}
480443
}
481444
);
482-
});
445+
446+
const attributes = utils.getIncomingRequestAttributesOnResponse(
447+
request,
448+
response
449+
);
450+
451+
span
452+
.setAttributes(attributes)
453+
.setStatus(utils.parseResponseStatus(response.statusCode));
454+
455+
if (instrumentation._getConfig().applyCustomAttributesOnSpan) {
456+
safeExecuteInTheMiddle(
457+
() =>
458+
instrumentation._getConfig().applyCustomAttributesOnSpan!(
459+
span,
460+
request,
461+
response
462+
),
463+
() => {},
464+
true
465+
);
466+
}
467+
468+
instrumentation._closeHttpSpan(span);
469+
return returned;
470+
};
471+
472+
return safeExecuteInTheMiddle(
473+
() => original.apply(this, [event, ...args]),
474+
error => {
475+
if (error) {
476+
utils.setSpanWithError(span, error);
477+
instrumentation._closeHttpSpan(span);
478+
throw error;
479+
}
480+
}
481+
);
483482
});
484483
};
485484
}
@@ -576,7 +575,11 @@ export class HttpInstrumentation extends InstrumentationBase<Http> {
576575
};
577576
}
578577

579-
private _startHttpSpan(name: string, options: SpanOptions) {
578+
private _startHttpSpan(
579+
name: string,
580+
options: SpanOptions,
581+
ctx = context.active()
582+
) {
580583
/*
581584
* If a parent is required but not present, we use a `NoopSpan` to still
582585
* propagate context without recording it.
@@ -587,16 +590,16 @@ export class HttpInstrumentation extends InstrumentationBase<Http> {
587590
: this._getConfig().requireParentforIncomingSpans;
588591

589592
let span: Span;
590-
const currentSpan = getSpan(context.active());
593+
const currentSpan = getSpan(ctx);
591594

592595
if (requireParent === true && currentSpan === undefined) {
593596
// TODO: Refactor this when a solution is found in
594597
// https://github.com/open-telemetry/opentelemetry-specification/issues/530
595-
span = NOOP_TRACER.startSpan(name, options);
598+
span = NOOP_TRACER.startSpan(name, options, ctx);
596599
} else if (requireParent === true && currentSpan?.context().isRemote) {
597600
span = currentSpan;
598601
} else {
599-
span = this.tracer.startSpan(name, options);
602+
span = this.tracer.startSpan(name, options, ctx);
600603
}
601604
this._spanNotEnded.add(span);
602605
return span;

0 commit comments

Comments
 (0)