diff --git a/packages/node-experimental/src/integrations/http.ts b/packages/node-experimental/src/integrations/http.ts index 5f45334da290..d6e6a825d8a1 100644 --- a/packages/node-experimental/src/integrations/http.ts +++ b/packages/node-experimental/src/integrations/http.ts @@ -95,8 +95,11 @@ export class Http implements Integration { new HttpInstrumentation({ requireParentforOutgoingSpans: true, requireParentforIncomingSpans: false, - applyCustomAttributesOnSpan: (span, req, res) => { - this._onSpan(span as unknown as OtelSpan, req, res); + requestHook: (span, req) => { + this._updateSentrySpan(span as unknown as OtelSpan, req); + }, + responseHook: (span, res) => { + this._addRequestBreadcrumb(span as unknown as OtelSpan, res); }, }), ], @@ -136,64 +139,70 @@ export class Http implements Integration { return; }; - /** Handle an emitted span from the HTTP instrumentation. */ - private _onSpan( - span: OtelSpan, - request: ClientRequest | IncomingMessage, - response: IncomingMessage | ServerResponse, - ): void { - const data = getRequestSpanData(span, request, response); + /** Update the Sentry span data based on the OTEL span. */ + private _updateSentrySpan(span: OtelSpan, request: ClientRequest | IncomingMessage): void { + const data = getRequestSpanData(span); const { attributes } = span; const sentrySpan = _INTERNAL_getSentrySpan(span.spanContext().spanId); - if (sentrySpan) { - sentrySpan.origin = 'auto.http.otel.http'; + if (!sentrySpan) { + return; + } - const additionalData: Record = { - url: data.url, - }; + sentrySpan.origin = 'auto.http.otel.http'; - if (sentrySpan instanceof Transaction && span.kind === SpanKind.SERVER) { - sentrySpan.setMetadata({ request }); - } + const additionalData: Record = { + url: data.url, + }; - if (attributes[SemanticAttributes.HTTP_STATUS_CODE]) { - const statusCode = attributes[SemanticAttributes.HTTP_STATUS_CODE] as string; - additionalData['http.response.status_code'] = statusCode; + if (sentrySpan instanceof Transaction && span.kind === SpanKind.SERVER) { + sentrySpan.setMetadata({ request }); + } - sentrySpan.setTag('http.status_code', statusCode); - } + if (attributes[SemanticAttributes.HTTP_STATUS_CODE]) { + const statusCode = attributes[SemanticAttributes.HTTP_STATUS_CODE] as string; + additionalData['http.response.status_code'] = statusCode; - if (data['http.query']) { - additionalData['http.query'] = data['http.query'].slice(1); - } - if (data['http.fragment']) { - additionalData['http.fragment'] = data['http.fragment'].slice(1); - } + sentrySpan.setTag('http.status_code', statusCode); + } - Object.keys(additionalData).forEach(prop => { - const value = additionalData[prop]; - sentrySpan.setData(prop, value); - }); + if (data['http.query']) { + additionalData['http.query'] = data['http.query'].slice(1); + } + if (data['http.fragment']) { + additionalData['http.fragment'] = data['http.fragment'].slice(1); } - if (this._breadcrumbs) { - getCurrentHub().addBreadcrumb( - { - category: 'http', - data: { - status_code: response.statusCode, - ...data, - }, - type: 'http', - }, - { - event: 'response', - request, - response, - }, - ); + Object.keys(additionalData).forEach(prop => { + const value = additionalData[prop]; + sentrySpan.setData(prop, value); + }); + } + + /** Add a breadcrumb for outgoing requests. */ + private _addRequestBreadcrumb(span: OtelSpan, response: IncomingMessage | ServerResponse): void { + if (!this._breadcrumbs || span.kind !== SpanKind.CLIENT) { + return; } + + const data = getRequestSpanData(span); + getCurrentHub().addBreadcrumb( + { + category: 'http', + data: { + status_code: response.statusCode, + ...data, + }, + type: 'http', + }, + { + event: 'response', + // TODO FN: Do we need access to `request` here? + // If we do, we'll have to use the `applyCustomAttributesOnSpan` hook instead, + // but this has worse context semantics than request/responseHook. + response, + }, + ); } } diff --git a/packages/node-experimental/src/utils/getRequestSpanData.ts b/packages/node-experimental/src/utils/getRequestSpanData.ts index 8d5d45f5f907..d238077bd9df 100644 --- a/packages/node-experimental/src/utils/getRequestSpanData.ts +++ b/packages/node-experimental/src/utils/getRequestSpanData.ts @@ -2,16 +2,11 @@ import type { Span as OtelSpan } from '@opentelemetry/sdk-trace-base'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import type { SanitizedRequestData } from '@sentry/types'; import { getSanitizedUrlString, parseUrl } from '@sentry/utils'; -import type { ClientRequest, IncomingMessage, ServerResponse } from 'http'; /** * Get sanitizied request data from an OTEL span. */ -export function getRequestSpanData( - span: OtelSpan, - _request: ClientRequest | IncomingMessage, - _response: IncomingMessage | ServerResponse, -): SanitizedRequestData { +export function getRequestSpanData(span: OtelSpan): SanitizedRequestData { const data: SanitizedRequestData = { url: span.attributes[SemanticAttributes.HTTP_URL] as string, 'http.method': (span.attributes[SemanticAttributes.HTTP_METHOD] as string) || 'GET',