diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 652d9daa2e39..d332007ee284 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -20,7 +20,6 @@ updates: - dependency-name: "@sentry/esbuild-plugin" - dependency-name: "@opentelemetry/*" - dependency-name: "@prisma/instrumentation" - - dependency-name: "opentelemetry-instrumentation-fetch-node" versioning-strategy: increase commit-message: prefix: feat diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/tests/request-instrumentation.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-14/tests/request-instrumentation.test.ts index 061c9d3cc5d6..65b9c4312d91 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-14/tests/request-instrumentation.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-14/tests/request-instrumentation.test.ts @@ -15,7 +15,7 @@ test('Should send a transaction with a fetch span', async ({ page }) => { expect(transactionEvent.spans).toContainEqual( expect.objectContaining({ data: expect.objectContaining({ - 'http.method': 'GET', + 'http.request.method': 'GET', 'sentry.op': 'http.client', 'sentry.origin': 'auto.http.otel.node_fetch', }), diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/scenario.ts b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/scenario.ts index 191797a10c15..9bbd9c9c1aeb 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/scenario.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/scenario.ts @@ -11,8 +11,6 @@ Sentry.init({ }); async function run(): Promise { - // Since fetch is lazy loaded, we need to wait a bit until it's fully instrumented - await new Promise(resolve => setTimeout(resolve, 100)); await fetch(`${process.env.SERVER_URL}/api/v0`).then(res => res.text()); await fetch(`${process.env.SERVER_URL}/api/v1`).then(res => res.text()); await fetch(`${process.env.SERVER_URL}/api/v2`).then(res => res.text()); diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-unsampled/scenario.ts b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-unsampled/scenario.ts index 91c38bf2b23a..9ab4c58967f2 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-unsampled/scenario.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-unsampled/scenario.ts @@ -13,8 +13,6 @@ Sentry.init({ async function run(): Promise { // Wrap in span that is not sampled await Sentry.startSpan({ name: 'outer' }, async () => { - // Since fetch is lazy loaded, we need to wait a bit until it's fully instrumented - await new Promise(resolve => setTimeout(resolve, 100)); await fetch(`${process.env.SERVER_URL}/api/v0`).then(res => res.text()); await fetch(`${process.env.SERVER_URL}/api/v1`).then(res => res.text()); await fetch(`${process.env.SERVER_URL}/api/v2`).then(res => res.text()); diff --git a/packages/bun/src/integrations/bunserver.ts b/packages/bun/src/integrations/bunserver.ts index 93a3f94dd4a0..193ae6f286ca 100644 --- a/packages/bun/src/integrations/bunserver.ts +++ b/packages/bun/src/integrations/bunserver.ts @@ -1,4 +1,5 @@ import { + SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, captureException, @@ -65,7 +66,7 @@ function instrumentBunServeOptions(serveOptions: Parameters[0] const parsedUrl = parseUrl(request.url); const attributes: SpanAttributes = { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.bun.serve', - 'http.request.method': request.method || 'GET', + [SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD]: request.method || 'GET', [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url', }; if (parsedUrl.search) { diff --git a/packages/cloudflare/src/request.ts b/packages/cloudflare/src/request.ts index 7a474c3b27cb..1c51a08c194c 100644 --- a/packages/cloudflare/src/request.ts +++ b/packages/cloudflare/src/request.ts @@ -1,9 +1,11 @@ import type { ExecutionContext, IncomingRequestCfProperties } from '@cloudflare/workers-types'; import { + SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, + SEMANTIC_ATTRIBUTE_URL_FULL, captureException, continueTrace, flush, @@ -45,8 +47,8 @@ export function wrapRequestHandler( [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.cloudflare', [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url', [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server', - ['http.request.method']: request.method, - ['url.full']: request.url, + [SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD]: request.method, + [SEMANTIC_ATTRIBUTE_URL_FULL]: request.url, }; const contentLength = request.headers.get('content-length'); diff --git a/packages/core/src/semanticAttributes.ts b/packages/core/src/semanticAttributes.ts index 2c268110854c..2d24c52a15ea 100644 --- a/packages/core/src/semanticAttributes.ts +++ b/packages/core/src/semanticAttributes.ts @@ -41,3 +41,7 @@ export const SEMANTIC_ATTRIBUTE_CACHE_HIT = 'cache.hit'; export const SEMANTIC_ATTRIBUTE_CACHE_KEY = 'cache.key'; export const SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE = 'cache.item_size'; + +/** TODO: Remove these once we update to latest semantic conventions */ +export const SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD = 'http.request.method'; +export const SEMANTIC_ATTRIBUTE_URL_FULL = 'url.full'; diff --git a/packages/node/package.json b/packages/node/package.json index 9a7091ef57fc..56ab710a1586 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -86,6 +86,7 @@ "@opentelemetry/instrumentation-nestjs-core": "0.40.0", "@opentelemetry/instrumentation-pg": "0.44.0", "@opentelemetry/instrumentation-redis-4": "0.42.0", + "@opentelemetry/instrumentation-undici": "0.5.0", "@opentelemetry/resources": "^1.25.1", "@opentelemetry/sdk-trace-base": "^1.25.1", "@opentelemetry/semantic-conventions": "^1.25.1", @@ -99,9 +100,6 @@ "devDependencies": { "@types/node": "^14.18.0" }, - "optionalDependencies": { - "opentelemetry-instrumentation-fetch-node": "1.2.3" - }, "scripts": { "build": "run-p build:transpile build:types", "build:dev": "yarn build", diff --git a/packages/node/src/integrations/node-fetch.ts b/packages/node/src/integrations/node-fetch.ts index fa7a9974135a..0726c2c63f9b 100644 --- a/packages/node/src/integrations/node-fetch.ts +++ b/packages/node/src/integrations/node-fetch.ts @@ -1,32 +1,9 @@ -import type { Span } from '@opentelemetry/api'; -import { trace } from '@opentelemetry/api'; -import { context, propagation } from '@opentelemetry/api'; -import { addBreadcrumb, defineIntegration, getCurrentScope, hasTracingEnabled } from '@sentry/core'; -import { - addOpenTelemetryInstrumentation, - generateSpanContextForPropagationContext, - getPropagationContextFromSpan, -} from '@sentry/opentelemetry'; +import type { UndiciRequest, UndiciResponse } from '@opentelemetry/instrumentation-undici'; +import { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici'; +import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, addBreadcrumb, defineIntegration } from '@sentry/core'; +import { addOpenTelemetryInstrumentation } from '@sentry/opentelemetry'; import type { IntegrationFn, SanitizedRequestData } from '@sentry/types'; -import { getSanitizedUrlString, logger, parseUrl } from '@sentry/utils'; -import { DEBUG_BUILD } from '../debug-build'; -import { NODE_MAJOR } from '../nodeVersion'; - -import type { FetchInstrumentation } from 'opentelemetry-instrumentation-fetch-node'; - -import { addOriginToSpan } from '../utils/addOriginToSpan'; - -interface FetchRequest { - method: string; - origin: string; - path: string; - headers: string | string[]; -} - -interface FetchResponse { - headers: Buffer[]; - statusCode: number; -} +import { getSanitizedUrlString, parseUrl } from '@sentry/utils'; interface NodeFetchOptions { /** @@ -46,106 +23,38 @@ const _nativeNodeFetchIntegration = ((options: NodeFetchOptions = {}) => { const _breadcrumbs = typeof options.breadcrumbs === 'undefined' ? true : options.breadcrumbs; const _ignoreOutgoingRequests = options.ignoreOutgoingRequests; - async function getInstrumentation(): Promise { - // Only add NodeFetch if Node >= 18, as previous versions do not support it - if (NODE_MAJOR < 18) { - DEBUG_BUILD && logger.log('NodeFetch is not supported on Node < 18, skipping instrumentation...'); - return; - } - - try { - const pkg = await import('opentelemetry-instrumentation-fetch-node'); - const { FetchInstrumentation } = pkg; - - class SentryNodeFetchInstrumentation extends FetchInstrumentation { - // We extend this method so we have access to request _and_ response for the breadcrumb - public onHeaders({ request, response }: { request: FetchRequest; response: FetchResponse }): void { - if (_breadcrumbs) { - _addRequestBreadcrumb(request, response); - } - - return super.onHeaders({ request, response }); - } - } - - return new SentryNodeFetchInstrumentation({ - ignoreRequestHook: (request: FetchRequest) => { + return { + name: 'NodeFetch', + setupOnce() { + const instrumentation = new UndiciInstrumentation({ + requireParentforSpans: false, + ignoreRequestHook: request => { const url = getAbsoluteUrl(request.origin, request.path); - const tracingDisabled = !hasTracingEnabled(); const shouldIgnore = _ignoreOutgoingRequests && url && _ignoreOutgoingRequests(url); - if (shouldIgnore) { - return true; - } - - // If tracing is disabled, we still want to propagate traces - // So we do that manually here, matching what the instrumentation does otherwise - if (tracingDisabled) { - const ctx = context.active(); - const addedHeaders: Record = {}; - - // We generate a virtual span context from the active one, - // Where we attach the URL to the trace state, so the propagator can pick it up - const activeSpan = trace.getSpan(ctx); - const propagationContext = activeSpan - ? getPropagationContextFromSpan(activeSpan) - : getCurrentScope().getPropagationContext(); - - const spanContext = generateSpanContextForPropagationContext(propagationContext); - // We know that in practice we'll _always_ haven a traceState here - spanContext.traceState = spanContext.traceState?.set('sentry.url', url); - const ctxWithUrlTraceState = trace.setSpanContext(ctx, spanContext); - - propagation.inject(ctxWithUrlTraceState, addedHeaders); - - const requestHeaders = request.headers; - if (Array.isArray(requestHeaders)) { - Object.entries(addedHeaders).forEach(headers => requestHeaders.push(...headers)); - } else { - request.headers += Object.entries(addedHeaders) - .map(([k, v]) => `${k}: ${v}\r\n`) - .join(''); - } - - // Prevent starting a span for this request - return true; - } - - return false; + return !!shouldIgnore; }, - onRequest: ({ span }: { span: Span }) => { - _updateSpan(span); + startSpanHook: () => { + return { + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.node_fetch', + }; + }, + responseHook: (_, { request, response }) => { + if (_breadcrumbs) { + addRequestBreadcrumb(request, response); + } }, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as any); - } catch (error) { - // Could not load instrumentation - DEBUG_BUILD && logger.log('Error while loading NodeFetch instrumentation: \n', error); - } - } - - return { - name: 'NodeFetch', - setupOnce() { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - getInstrumentation().then(instrumentation => { - if (instrumentation) { - addOpenTelemetryInstrumentation(instrumentation); - } }); + + addOpenTelemetryInstrumentation(instrumentation); }, }; }) satisfies IntegrationFn; export const nativeNodeFetchIntegration = defineIntegration(_nativeNodeFetchIntegration); -/** Update the span with data we need. */ -function _updateSpan(span: Span): void { - addOriginToSpan(span, 'auto.http.otel.node_fetch'); -} - /** Add a breadcrumb for outgoing requests. */ -function _addRequestBreadcrumb(request: FetchRequest, response: FetchResponse): void { +function addRequestBreadcrumb(request: UndiciRequest, response: UndiciResponse): void { const data = getBreadcrumbData(request); addBreadcrumb( @@ -165,7 +74,7 @@ function _addRequestBreadcrumb(request: FetchRequest, response: FetchResponse): ); } -function getBreadcrumbData(request: FetchRequest): Partial { +function getBreadcrumbData(request: UndiciRequest): Partial { try { const url = new URL(request.path, request.origin); const parsedUrl = parseUrl(url.toString()); diff --git a/packages/opentelemetry/src/propagator.ts b/packages/opentelemetry/src/propagator.ts index 40b8a8139b0d..4ed5a15532d2 100644 --- a/packages/opentelemetry/src/propagator.ts +++ b/packages/opentelemetry/src/propagator.ts @@ -5,6 +5,7 @@ import { propagation, trace } from '@opentelemetry/api'; import { W3CBaggagePropagator, isTracingSuppressed } from '@opentelemetry/core'; import { SEMATTRS_HTTP_URL } from '@opentelemetry/semantic-conventions'; import type { continueTrace } from '@sentry/core'; +import { SEMANTIC_ATTRIBUTE_URL_FULL } from '@sentry/core'; import { hasTracingEnabled } from '@sentry/core'; import { getRootSpan } from '@sentry/core'; import { spanToJSON } from '@sentry/core'; @@ -292,7 +293,8 @@ function getExistingBaggage(carrier: unknown): string | undefined { * 2. Else, if the active span has no URL attribute (e.g. it is unsampled), we check a special trace state (which we set in our sampler). */ function getCurrentURL(span: Span): string | undefined { - const urlAttribute = spanToJSON(span).data?.[SEMATTRS_HTTP_URL]; + const spanData = spanToJSON(span).data; + const urlAttribute = spanData?.[SEMATTRS_HTTP_URL] || spanData?.[SEMANTIC_ATTRIBUTE_URL_FULL]; if (urlAttribute) { return urlAttribute; } diff --git a/packages/opentelemetry/src/sampler.ts b/packages/opentelemetry/src/sampler.ts index 446c325f3ac7..03d47989ae1d 100644 --- a/packages/opentelemetry/src/sampler.ts +++ b/packages/opentelemetry/src/sampler.ts @@ -5,8 +5,10 @@ import { TraceState } from '@opentelemetry/core'; import type { Sampler, SamplingResult } from '@opentelemetry/sdk-trace-base'; import { SamplingDecision } from '@opentelemetry/sdk-trace-base'; import { + SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, + SEMANTIC_ATTRIBUTE_URL_FULL, hasTracingEnabled, sampleSpan, } from '@sentry/core'; @@ -54,7 +56,7 @@ export class SentrySampler implements Sampler { // but we want to leave downstream sampling decisions up to the server if ( spanKind === SpanKind.CLIENT && - spanAttributes[SEMATTRS_HTTP_METHOD] && + (spanAttributes[SEMATTRS_HTTP_METHOD] || spanAttributes[SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD]) && (!parentSpan || parentContext?.isRemote) ) { return wrapSamplingDecision({ decision: undefined, context, spanAttributes }); @@ -196,7 +198,7 @@ function getBaseTraceState(context: Context, spanAttributes: SpanAttributes): Tr let traceState = parentContext?.traceState || new TraceState(); // We always keep the URL on the trace state, so we can access it in the propagator - const url = spanAttributes[SEMATTRS_HTTP_URL]; + const url = spanAttributes[SEMATTRS_HTTP_URL] || spanAttributes[SEMANTIC_ATTRIBUTE_URL_FULL]; if (url && typeof url === 'string') { traceState = traceState.set(SENTRY_TRACE_STATE_URL, url); } diff --git a/packages/opentelemetry/src/utils/isSentryRequest.ts b/packages/opentelemetry/src/utils/isSentryRequest.ts index 3381b7833cea..c8b11c9e680c 100644 --- a/packages/opentelemetry/src/utils/isSentryRequest.ts +++ b/packages/opentelemetry/src/utils/isSentryRequest.ts @@ -1,5 +1,5 @@ import { SEMATTRS_HTTP_URL } from '@opentelemetry/semantic-conventions'; -import { getClient, isSentryRequestUrl } from '@sentry/core'; +import { SEMANTIC_ATTRIBUTE_URL_FULL, getClient, isSentryRequestUrl } from '@sentry/core'; import type { AbstractSpan } from '../types'; import { spanHasAttributes } from './spanTypes'; @@ -16,7 +16,7 @@ export function isSentryRequestSpan(span: AbstractSpan): boolean { const { attributes } = span; - const httpUrl = attributes[SEMATTRS_HTTP_URL]; + const httpUrl = attributes[SEMATTRS_HTTP_URL] || attributes[SEMANTIC_ATTRIBUTE_URL_FULL]; if (!httpUrl) { return false; diff --git a/packages/opentelemetry/src/utils/parseSpanDescription.ts b/packages/opentelemetry/src/utils/parseSpanDescription.ts index b600b81f8aec..07354313f331 100644 --- a/packages/opentelemetry/src/utils/parseSpanDescription.ts +++ b/packages/opentelemetry/src/utils/parseSpanDescription.ts @@ -14,7 +14,12 @@ import { import type { SpanAttributes, TransactionSource } from '@sentry/types'; import { getSanitizedUrlString, parseUrl, stripUrlQueryAndFragment } from '@sentry/utils'; -import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; +import { + SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD, + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SEMANTIC_ATTRIBUTE_URL_FULL, +} from '@sentry/core'; import { SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION } from '../semanticAttributes'; import type { AbstractSpan } from '../types'; import { getSpanKind } from './getSpanKind'; @@ -45,10 +50,7 @@ export function inferSpanData(name: string, attributes: SpanAttributes, kind: Sp } // if http.method exists, this is an http request span - // - // TODO: Referencing `http.request.method` is a temporary workaround until the semantic - // conventions export an attribute key for it. - const httpMethod = attributes['http.request.method'] || attributes[SEMATTRS_HTTP_METHOD]; + const httpMethod = attributes[SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD] || attributes[SEMATTRS_HTTP_METHOD]; if (httpMethod) { return descriptionForHttpMethod({ attributes, name, kind }, httpMethod); } @@ -213,7 +215,7 @@ export function getSanitizedUrl( // This is the relative path of the URL, e.g. /sub const httpTarget = attributes[SEMATTRS_HTTP_TARGET]; // This is the full URL, including host & query params etc., e.g. https://example.com/sub?foo=bar - const httpUrl = attributes[SEMATTRS_HTTP_URL]; + const httpUrl = attributes[SEMATTRS_HTTP_URL] || attributes[SEMANTIC_ATTRIBUTE_URL_FULL]; // This is the normalized route name - may not always be available! const httpRoute = attributes[SEMATTRS_HTTP_ROUTE]; diff --git a/yarn.lock b/yarn.lock index 246bb480abd9..edab1265fe2c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7242,6 +7242,14 @@ "@opentelemetry/redis-common" "^0.36.2" "@opentelemetry/semantic-conventions" "^1.27.0" +"@opentelemetry/instrumentation-undici@0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.5.0.tgz#50782ff300027d0d0664fb60a3c12227586d5ebd" + integrity sha512-aNTeSrFAVcM9qco5DfZ9DNXu6hpMRe8Kt8nCDHfMWDB3pwgGVUE76jTdohc+H/7eLRqh4L7jqs5NSQoHw7S6ww== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.52.0" + "@opentelemetry/instrumentation@0.53.0", "@opentelemetry/instrumentation@^0.53.0": version "0.53.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz#e6369e4015eb5112468a4d45d38dcada7dad892d" @@ -7265,18 +7273,7 @@ semver "^7.5.2" shimmer "^1.2.1" -"@opentelemetry/instrumentation@^0.46.0": - version "0.46.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.46.0.tgz#a8a252306f82e2eace489312798592a14eb9830e" - integrity sha512-a9TijXZZbk0vI5TGLZl+0kxyFfrXHhX6Svtz7Pp2/VBlCSKrazuULEyoJQrOknJyFWNMEmbbJgOciHCCpQcisw== - dependencies: - "@types/shimmer" "^1.0.2" - import-in-the-middle "1.7.1" - require-in-the-middle "^7.1.1" - semver "^7.5.2" - shimmer "^1.2.1" - -"@opentelemetry/instrumentation@^0.49 || ^0.50 || ^0.51 || ^0.52.0", "@opentelemetry/instrumentation@^0.52.1": +"@opentelemetry/instrumentation@^0.49 || ^0.50 || ^0.51 || ^0.52.0", "@opentelemetry/instrumentation@^0.52.0", "@opentelemetry/instrumentation@^0.52.1": version "0.52.1" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz#2e7e46a38bd7afbf03cf688c862b0b43418b7f48" integrity sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw== @@ -20661,16 +20658,6 @@ import-in-the-middle@1.4.2: cjs-module-lexer "^1.2.2" module-details-from-path "^1.0.3" -import-in-the-middle@1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz#3e111ff79c639d0bde459bd7ba29dd9fdf357364" - integrity sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg== - dependencies: - acorn "^8.8.2" - acorn-import-assertions "^1.9.0" - cjs-module-lexer "^1.2.2" - module-details-from-path "^1.0.3" - import-in-the-middle@^1.11.0, import-in-the-middle@^1.8.1: version "1.11.0" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.0.tgz#a94c4925b8da18256cde3b3b7b38253e6ca5e708" @@ -26192,14 +26179,6 @@ opener@^1.5.2: resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== -opentelemetry-instrumentation-fetch-node@1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/opentelemetry-instrumentation-fetch-node/-/opentelemetry-instrumentation-fetch-node-1.2.3.tgz#beb24048bdccb1943ba2a5bbadca68020e448ea7" - integrity sha512-Qb11T7KvoCevMaSeuamcLsAD+pZnavkhDnlVL0kRozfhl42dKG5Q3anUklAFKJZjY3twLR+BnRa6DlwwkIE/+A== - dependencies: - "@opentelemetry/instrumentation" "^0.46.0" - "@opentelemetry/semantic-conventions" "^1.17.0" - opentelemetry-instrumentation-remix@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/opentelemetry-instrumentation-remix/-/opentelemetry-instrumentation-remix-0.7.1.tgz#ef90ede718612786f7015e5496bd25cac8c49ce3"