@sentry/node 9.11.0 → 9.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/index.js +5 -4
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/integrations/anr/index.js +3 -3
- package/build/cjs/integrations/anr/index.js.map +1 -1
- package/build/cjs/integrations/context.js +3 -3
- package/build/cjs/integrations/context.js.map +1 -1
- package/build/cjs/integrations/http/SentryHttpInstrumentation.js +6 -2
- package/build/cjs/integrations/http/SentryHttpInstrumentation.js.map +1 -1
- package/build/cjs/integrations/http/index.js.map +1 -1
- package/build/cjs/integrations/local-variables/local-variables-async.js +1 -1
- package/build/cjs/integrations/node-fetch/index.js +11 -7
- package/build/cjs/integrations/node-fetch/index.js.map +1 -1
- package/build/cjs/integrations/tracing/graphql.js +31 -3
- package/build/cjs/integrations/tracing/graphql.js.map +1 -1
- package/build/cjs/integrations/winston.js +151 -0
- package/build/cjs/integrations/winston.js.map +1 -0
- package/build/cjs/logs/capture.js +29 -0
- package/build/cjs/logs/capture.js.map +1 -0
- package/build/cjs/{log.js → logs/exports.js} +8 -30
- package/build/cjs/logs/exports.js.map +1 -0
- package/build/cjs/otel/instrument.js +50 -2
- package/build/cjs/otel/instrument.js.map +1 -1
- package/build/cjs/sdk/client.js +23 -1
- package/build/cjs/sdk/client.js.map +1 -1
- package/build/cjs/sdk/index.js +2 -2
- package/build/cjs/sdk/index.js.map +1 -1
- package/build/esm/index.js +4 -4
- package/build/esm/integrations/anr/index.js +1 -1
- package/build/esm/integrations/anr/worker-script.js +2 -2
- package/build/esm/integrations/http/SentryHttpInstrumentation.js +6 -2
- package/build/esm/integrations/http/SentryHttpInstrumentation.js.map +1 -1
- package/build/esm/integrations/http/index.js.map +1 -1
- package/build/esm/integrations/local-variables/local-variables-async.js +1 -1
- package/build/esm/integrations/local-variables/worker-script.js +2 -2
- package/build/esm/integrations/node-fetch/index.js +11 -7
- package/build/esm/integrations/node-fetch/index.js.map +1 -1
- package/build/esm/integrations/tracing/express.js +1 -1
- package/build/esm/integrations/tracing/fastify.js +1 -1
- package/build/esm/integrations/tracing/graphql.js +32 -4
- package/build/esm/integrations/tracing/graphql.js.map +1 -1
- package/build/esm/integrations/tracing/koa.js +1 -1
- package/build/esm/integrations/winston.js +149 -0
- package/build/esm/integrations/winston.js.map +1 -0
- package/build/esm/logs/capture.js +27 -0
- package/build/esm/logs/capture.js.map +1 -0
- package/build/esm/{log.js → logs/exports.js} +2 -25
- package/build/esm/logs/exports.js.map +1 -0
- package/build/esm/otel/instrument.js +50 -2
- package/build/esm/otel/instrument.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/sdk/client.js +24 -2
- package/build/esm/sdk/client.js.map +1 -1
- package/build/esm/sdk/index.js +2 -2
- package/build/esm/sdk/index.js.map +1 -1
- package/build/types/index.d.ts +3 -3
- package/build/types/index.d.ts.map +1 -1
- package/build/types/integrations/http/SentryHttpInstrumentation.d.ts +8 -0
- package/build/types/integrations/http/SentryHttpInstrumentation.d.ts.map +1 -1
- package/build/types/integrations/http/index.d.ts +8 -0
- package/build/types/integrations/http/index.d.ts.map +1 -1
- package/build/types/integrations/node-fetch/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/graphql.d.ts +2 -1
- package/build/types/integrations/tracing/graphql.d.ts.map +1 -1
- package/build/types/integrations/winston.d.ts +44 -0
- package/build/types/integrations/winston.d.ts.map +1 -0
- package/build/types/logs/capture.d.ts +11 -0
- package/build/types/logs/capture.d.ts.map +1 -0
- package/build/{types-ts3.8/log.d.ts → types/logs/exports.d.ts} +150 -158
- package/build/types/logs/exports.d.ts.map +1 -0
- package/build/types/otel/instrument.d.ts +3 -4
- package/build/types/otel/instrument.d.ts.map +1 -1
- package/build/types/sdk/client.d.ts +1 -0
- package/build/types/sdk/client.d.ts.map +1 -1
- package/build/types-ts3.8/index.d.ts +3 -3
- package/build/types-ts3.8/integrations/http/SentryHttpInstrumentation.d.ts +8 -0
- package/build/types-ts3.8/integrations/http/index.d.ts +8 -0
- package/build/types-ts3.8/integrations/tracing/graphql.d.ts +2 -1
- package/build/types-ts3.8/integrations/winston.d.ts +44 -0
- package/build/types-ts3.8/logs/capture.d.ts +18 -0
- package/build/{types/log.d.ts → types-ts3.8/logs/exports.d.ts} +150 -151
- package/build/types-ts3.8/otel/instrument.d.ts +3 -4
- package/build/types-ts3.8/sdk/client.d.ts +1 -0
- package/package.json +3 -3
- package/build/cjs/integrations/console.js +0 -37
- package/build/cjs/integrations/console.js.map +0 -1
- package/build/cjs/log.js.map +0 -1
- package/build/esm/integrations/console.js +0 -35
- package/build/esm/integrations/console.js.map +0 -1
- package/build/esm/log.js.map +0 -1
- package/build/types/integrations/console.d.ts +0 -5
- package/build/types/integrations/console.d.ts.map +0 -1
- package/build/types/log.d.ts.map +0 -1
- package/build/types-ts3.8/integrations/console.d.ts +0 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/integrations/http/index.ts"],"sourcesContent":["import type { ClientRequest, IncomingMessage, RequestOptions, ServerResponse } from 'node:http';\nimport { diag } from '@opentelemetry/api';\nimport type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http';\nimport { HttpInstrumentation } from '@opentelemetry/instrumentation-http';\nimport type { Span } from '@sentry/core';\nimport { defineIntegration, getClient } from '@sentry/core';\nimport { generateInstrumentOnce } from '../../otel/instrument';\nimport type { NodeClient } from '../../sdk/client';\nimport type { HTTPModuleRequestIncomingMessage } from '../../transports/http-module';\nimport type { NodeClientOptions } from '../../types';\nimport { addOriginToSpan } from '../../utils/addOriginToSpan';\nimport { getRequestUrl } from '../../utils/getRequestUrl';\nimport type { SentryHttpInstrumentationOptions } from './SentryHttpInstrumentation';\nimport { SentryHttpInstrumentation } from './SentryHttpInstrumentation';\nimport { SentryHttpInstrumentationBeforeOtel } from './SentryHttpInstrumentationBeforeOtel';\n\nconst INTEGRATION_NAME = 'Http';\n\nconst INSTRUMENTATION_NAME = '@opentelemetry_sentry-patched/instrumentation-http';\n\ninterface HttpOptions {\n /**\n * Whether breadcrumbs should be recorded for outgoing requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * If set to false, do not emit any spans.\n * This will ensure that the default HttpInstrumentation from OpenTelemetry is not setup,\n * only the Sentry-specific instrumentation for request isolation is applied.\n *\n * If `skipOpenTelemetrySetup: true` is configured, this defaults to `false`, otherwise it defaults to `true`.\n */\n spans?: boolean;\n\n /**\n * Whether the integration should create [Sessions](https://docs.sentry.io/product/releases/health/#sessions) for incoming requests to track the health and crash-free rate of your releases in Sentry.\n * Read more about Release Health: https://docs.sentry.io/product/releases/health/\n *\n * Defaults to `true`.\n */\n trackIncomingRequestsAsSessions?: boolean;\n\n /**\n * Number of milliseconds until sessions tracked with `trackIncomingRequestsAsSessions` will be flushed as a session aggregate.\n *\n * Defaults to `60000` (60s).\n */\n sessionFlushingDelayMS?: number;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n *\n * The `url` param contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * For example: `'https://someService.com/users/details?id=123'`\n *\n * The `request` param contains the original {@type RequestOptions} object used to make the outgoing request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreOutgoingRequests?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests to URLs where the given callback returns `true`.\n * Spans will be non recording if tracing is disabled.\n *\n * The `urlPath` param consists of the URL path and query string (if any) of the incoming request.\n * For example: `'/users/details?id=123'`\n *\n * The `request` param contains the original {@type IncomingMessage} object of the incoming request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreIncomingRequests?: (urlPath: string, request: IncomingMessage) => boolean;\n\n /**\n * If true, do not generate spans for incoming requests at all.\n * This is used by Remix to avoid generating spans for incoming requests, as it generates its own spans.\n */\n disableIncomingRequestSpans?: boolean;\n\n /**\n * Additional instrumentation options that are passed to the underlying HttpInstrumentation.\n */\n instrumentation?: {\n requestHook?: (span: Span, req: ClientRequest | HTTPModuleRequestIncomingMessage) => void;\n responseHook?: (span: Span, response: HTTPModuleRequestIncomingMessage | ServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: ClientRequest | HTTPModuleRequestIncomingMessage,\n response: HTTPModuleRequestIncomingMessage | ServerResponse,\n ) => void;\n\n /**\n * You can pass any configuration through to the underlying instrumentation.\n * Note that there are no semver guarantees for this!\n */\n _experimentalConfig?: ConstructorParameters<typeof HttpInstrumentation>[0];\n };\n}\n\nconst instrumentSentryHttpBeforeOtel = generateInstrumentOnce(`${INTEGRATION_NAME}.sentry-before-otel`, () => {\n return new SentryHttpInstrumentationBeforeOtel();\n});\n\nconst instrumentSentryHttp = generateInstrumentOnce<SentryHttpInstrumentationOptions>(\n `${INTEGRATION_NAME}.sentry`,\n options => {\n return new SentryHttpInstrumentation(options);\n },\n);\n\nexport const instrumentOtelHttp = generateInstrumentOnce<HttpInstrumentationConfig>(INTEGRATION_NAME, config => {\n const instrumentation = new HttpInstrumentation(config);\n\n // We want to update the logger namespace so we can better identify what is happening here\n try {\n instrumentation['_diag'] = diag.createComponentLogger({\n namespace: INSTRUMENTATION_NAME,\n });\n // @ts-expect-error We are writing a read-only property here...\n instrumentation.instrumentationName = INSTRUMENTATION_NAME;\n } catch {\n // ignore errors here...\n }\n\n return instrumentation;\n});\n\n/** Exported only for tests. */\nexport function _shouldInstrumentSpans(options: HttpOptions, clientOptions: Partial<NodeClientOptions> = {}): boolean {\n // If `spans` is passed in, it takes precedence\n // Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true`\n return typeof options.spans === 'boolean' ? options.spans : !clientOptions.skipOpenTelemetrySetup;\n}\n\n/**\n * The http integration instruments Node's internal http and https modules.\n * It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span.\n */\nexport const httpIntegration = defineIntegration((options: HttpOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // Below, we instrument the Node.js HTTP API three times. 2 times Sentry-specific, 1 time OTEL specific.\n // Due to timing reasons, we sometimes need to apply Sentry instrumentation _before_ we apply the OTEL\n // instrumentation (e.g. to flush on serverless platforms), and sometimes we need to apply Sentry instrumentation\n // _after_ we apply OTEL instrumentation (e.g. for isolation scope handling and breadcrumbs).\n\n // This is Sentry-specific instrumentation that is applied _before_ any OTEL instrumentation.\n if (process.env.VERCEL) {\n // Currently this instrumentation only does something when deployed on Vercel, so to save some overhead, we short circuit adding it here only for Vercel.\n // If it's functionality is extended in the future, feel free to remove the if statement and this comment.\n instrumentSentryHttpBeforeOtel();\n }\n\n const instrumentSpans = _shouldInstrumentSpans(options, getClient<NodeClient>()?.getOptions());\n\n // This is the \"regular\" OTEL instrumentation that emits spans\n if (instrumentSpans) {\n const instrumentationConfig = getConfigWithDefaults(options);\n instrumentOtelHttp(instrumentationConfig);\n }\n\n // This is Sentry-specific instrumentation that is applied _after_ any OTEL instrumentation.\n instrumentSentryHttp({\n ...options,\n // If spans are not instrumented, it means the HttpInstrumentation has not been added\n // In that case, we want to handle incoming trace extraction ourselves\n extractIncomingTraceFromHeader: !instrumentSpans,\n });\n },\n };\n});\n\n/**\n * Determines if @param req is a ClientRequest, meaning the request was created within the express app\n * and it's an outgoing request.\n * Checking for properties instead of using `instanceOf` to avoid importing the request classes.\n */\nfunction _isClientRequest(req: ClientRequest | HTTPModuleRequestIncomingMessage): req is ClientRequest {\n return 'outputData' in req && 'outputSize' in req && !('client' in req) && !('statusCode' in req);\n}\n\n/**\n * Detects if an incoming request is a prefetch request.\n */\nfunction isKnownPrefetchRequest(req: HTTPModuleRequestIncomingMessage): boolean {\n // Currently only handles Next.js prefetch requests but may check other frameworks in the future.\n return req.headers['next-router-prefetch'] === '1';\n}\n\nfunction getConfigWithDefaults(options: Partial<HttpOptions> = {}): HttpInstrumentationConfig {\n const instrumentationConfig = {\n ...options.instrumentation?._experimentalConfig,\n\n disableIncomingRequestInstrumentation: options.disableIncomingRequestSpans,\n\n ignoreOutgoingRequestHook: request => {\n const url = getRequestUrl(request);\n\n if (!url) {\n return false;\n }\n\n const _ignoreOutgoingRequests = options.ignoreOutgoingRequests;\n if (_ignoreOutgoingRequests?.(url, request)) {\n return true;\n }\n\n return false;\n },\n\n ignoreIncomingRequestHook: request => {\n // request.url is the only property that holds any information about the url\n // it only consists of the URL path and query string (if any)\n const urlPath = request.url;\n\n const method = request.method?.toUpperCase();\n // We do not capture OPTIONS/HEAD requests as transactions\n if (method === 'OPTIONS' || method === 'HEAD') {\n return true;\n }\n\n const _ignoreIncomingRequests = options.ignoreIncomingRequests;\n if (urlPath && _ignoreIncomingRequests?.(urlPath, request)) {\n return true;\n }\n\n return false;\n },\n\n requireParentforOutgoingSpans: false,\n requireParentforIncomingSpans: false,\n requestHook: (span, req) => {\n addOriginToSpan(span, 'auto.http.otel.http');\n if (!_isClientRequest(req) && isKnownPrefetchRequest(req)) {\n span.setAttribute('sentry.http.prefetch', true);\n }\n\n options.instrumentation?.requestHook?.(span, req);\n },\n responseHook: (span, res) => {\n options.instrumentation?.responseHook?.(span, res);\n },\n applyCustomAttributesOnSpan: (\n span: Span,\n request: ClientRequest | HTTPModuleRequestIncomingMessage,\n response: HTTPModuleRequestIncomingMessage | ServerResponse,\n ) => {\n options.instrumentation?.applyCustomAttributesOnSpan?.(span, request, response);\n },\n } satisfies HttpInstrumentationConfig;\n\n return instrumentationConfig;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/integrations/http/index.ts"],"sourcesContent":["import type { ClientRequest, IncomingMessage, RequestOptions, ServerResponse } from 'node:http';\nimport { diag } from '@opentelemetry/api';\nimport type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http';\nimport { HttpInstrumentation } from '@opentelemetry/instrumentation-http';\nimport type { Span } from '@sentry/core';\nimport { defineIntegration, getClient } from '@sentry/core';\nimport { generateInstrumentOnce } from '../../otel/instrument';\nimport type { NodeClient } from '../../sdk/client';\nimport type { HTTPModuleRequestIncomingMessage } from '../../transports/http-module';\nimport type { NodeClientOptions } from '../../types';\nimport { addOriginToSpan } from '../../utils/addOriginToSpan';\nimport { getRequestUrl } from '../../utils/getRequestUrl';\nimport type { SentryHttpInstrumentationOptions } from './SentryHttpInstrumentation';\nimport { SentryHttpInstrumentation } from './SentryHttpInstrumentation';\nimport { SentryHttpInstrumentationBeforeOtel } from './SentryHttpInstrumentationBeforeOtel';\n\nconst INTEGRATION_NAME = 'Http';\n\nconst INSTRUMENTATION_NAME = '@opentelemetry_sentry-patched/instrumentation-http';\n\ninterface HttpOptions {\n /**\n * Whether breadcrumbs should be recorded for outgoing requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * If set to false, do not emit any spans.\n * This will ensure that the default HttpInstrumentation from OpenTelemetry is not setup,\n * only the Sentry-specific instrumentation for request isolation is applied.\n *\n * If `skipOpenTelemetrySetup: true` is configured, this defaults to `false`, otherwise it defaults to `true`.\n */\n spans?: boolean;\n\n /**\n * Whether the integration should create [Sessions](https://docs.sentry.io/product/releases/health/#sessions) for incoming requests to track the health and crash-free rate of your releases in Sentry.\n * Read more about Release Health: https://docs.sentry.io/product/releases/health/\n *\n * Defaults to `true`.\n */\n trackIncomingRequestsAsSessions?: boolean;\n\n /**\n * Number of milliseconds until sessions tracked with `trackIncomingRequestsAsSessions` will be flushed as a session aggregate.\n *\n * Defaults to `60000` (60s).\n */\n sessionFlushingDelayMS?: number;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n *\n * The `url` param contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * For example: `'https://someService.com/users/details?id=123'`\n *\n * The `request` param contains the original {@type RequestOptions} object used to make the outgoing request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreOutgoingRequests?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests to URLs where the given callback returns `true`.\n * Spans will be non recording if tracing is disabled.\n *\n * The `urlPath` param consists of the URL path and query string (if any) of the incoming request.\n * For example: `'/users/details?id=123'`\n *\n * The `request` param contains the original {@type IncomingMessage} object of the incoming request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreIncomingRequests?: (urlPath: string, request: IncomingMessage) => boolean;\n\n /**\n * Do not capture the request body for incoming HTTP requests to URLs where the given callback returns `true`.\n * This can be useful for long running requests where the body is not needed and we want to avoid capturing it.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * @param request Contains the {@type RequestOptions} object used to make the outgoing request.\n */\n ignoreIncomingRequestBody?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * If true, do not generate spans for incoming requests at all.\n * This is used by Remix to avoid generating spans for incoming requests, as it generates its own spans.\n */\n disableIncomingRequestSpans?: boolean;\n\n /**\n * Additional instrumentation options that are passed to the underlying HttpInstrumentation.\n */\n instrumentation?: {\n requestHook?: (span: Span, req: ClientRequest | HTTPModuleRequestIncomingMessage) => void;\n responseHook?: (span: Span, response: HTTPModuleRequestIncomingMessage | ServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: ClientRequest | HTTPModuleRequestIncomingMessage,\n response: HTTPModuleRequestIncomingMessage | ServerResponse,\n ) => void;\n\n /**\n * You can pass any configuration through to the underlying instrumentation.\n * Note that there are no semver guarantees for this!\n */\n _experimentalConfig?: ConstructorParameters<typeof HttpInstrumentation>[0];\n };\n}\n\nconst instrumentSentryHttpBeforeOtel = generateInstrumentOnce(`${INTEGRATION_NAME}.sentry-before-otel`, () => {\n return new SentryHttpInstrumentationBeforeOtel();\n});\n\nconst instrumentSentryHttp = generateInstrumentOnce<SentryHttpInstrumentationOptions>(\n `${INTEGRATION_NAME}.sentry`,\n options => {\n return new SentryHttpInstrumentation(options);\n },\n);\n\nexport const instrumentOtelHttp = generateInstrumentOnce<HttpInstrumentationConfig>(INTEGRATION_NAME, config => {\n const instrumentation = new HttpInstrumentation(config);\n\n // We want to update the logger namespace so we can better identify what is happening here\n try {\n instrumentation['_diag'] = diag.createComponentLogger({\n namespace: INSTRUMENTATION_NAME,\n });\n // @ts-expect-error We are writing a read-only property here...\n instrumentation.instrumentationName = INSTRUMENTATION_NAME;\n } catch {\n // ignore errors here...\n }\n\n return instrumentation;\n});\n\n/** Exported only for tests. */\nexport function _shouldInstrumentSpans(options: HttpOptions, clientOptions: Partial<NodeClientOptions> = {}): boolean {\n // If `spans` is passed in, it takes precedence\n // Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true`\n return typeof options.spans === 'boolean' ? options.spans : !clientOptions.skipOpenTelemetrySetup;\n}\n\n/**\n * The http integration instruments Node's internal http and https modules.\n * It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span.\n */\nexport const httpIntegration = defineIntegration((options: HttpOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // Below, we instrument the Node.js HTTP API three times. 2 times Sentry-specific, 1 time OTEL specific.\n // Due to timing reasons, we sometimes need to apply Sentry instrumentation _before_ we apply the OTEL\n // instrumentation (e.g. to flush on serverless platforms), and sometimes we need to apply Sentry instrumentation\n // _after_ we apply OTEL instrumentation (e.g. for isolation scope handling and breadcrumbs).\n\n // This is Sentry-specific instrumentation that is applied _before_ any OTEL instrumentation.\n if (process.env.VERCEL) {\n // Currently this instrumentation only does something when deployed on Vercel, so to save some overhead, we short circuit adding it here only for Vercel.\n // If it's functionality is extended in the future, feel free to remove the if statement and this comment.\n instrumentSentryHttpBeforeOtel();\n }\n\n const instrumentSpans = _shouldInstrumentSpans(options, getClient<NodeClient>()?.getOptions());\n\n // This is the \"regular\" OTEL instrumentation that emits spans\n if (instrumentSpans) {\n const instrumentationConfig = getConfigWithDefaults(options);\n instrumentOtelHttp(instrumentationConfig);\n }\n\n // This is Sentry-specific instrumentation that is applied _after_ any OTEL instrumentation.\n instrumentSentryHttp({\n ...options,\n // If spans are not instrumented, it means the HttpInstrumentation has not been added\n // In that case, we want to handle incoming trace extraction ourselves\n extractIncomingTraceFromHeader: !instrumentSpans,\n });\n },\n };\n});\n\n/**\n * Determines if @param req is a ClientRequest, meaning the request was created within the express app\n * and it's an outgoing request.\n * Checking for properties instead of using `instanceOf` to avoid importing the request classes.\n */\nfunction _isClientRequest(req: ClientRequest | HTTPModuleRequestIncomingMessage): req is ClientRequest {\n return 'outputData' in req && 'outputSize' in req && !('client' in req) && !('statusCode' in req);\n}\n\n/**\n * Detects if an incoming request is a prefetch request.\n */\nfunction isKnownPrefetchRequest(req: HTTPModuleRequestIncomingMessage): boolean {\n // Currently only handles Next.js prefetch requests but may check other frameworks in the future.\n return req.headers['next-router-prefetch'] === '1';\n}\n\nfunction getConfigWithDefaults(options: Partial<HttpOptions> = {}): HttpInstrumentationConfig {\n const instrumentationConfig = {\n ...options.instrumentation?._experimentalConfig,\n\n disableIncomingRequestInstrumentation: options.disableIncomingRequestSpans,\n\n ignoreOutgoingRequestHook: request => {\n const url = getRequestUrl(request);\n\n if (!url) {\n return false;\n }\n\n const _ignoreOutgoingRequests = options.ignoreOutgoingRequests;\n if (_ignoreOutgoingRequests?.(url, request)) {\n return true;\n }\n\n return false;\n },\n\n ignoreIncomingRequestHook: request => {\n // request.url is the only property that holds any information about the url\n // it only consists of the URL path and query string (if any)\n const urlPath = request.url;\n\n const method = request.method?.toUpperCase();\n // We do not capture OPTIONS/HEAD requests as transactions\n if (method === 'OPTIONS' || method === 'HEAD') {\n return true;\n }\n\n const _ignoreIncomingRequests = options.ignoreIncomingRequests;\n if (urlPath && _ignoreIncomingRequests?.(urlPath, request)) {\n return true;\n }\n\n return false;\n },\n\n requireParentforOutgoingSpans: false,\n requireParentforIncomingSpans: false,\n requestHook: (span, req) => {\n addOriginToSpan(span, 'auto.http.otel.http');\n if (!_isClientRequest(req) && isKnownPrefetchRequest(req)) {\n span.setAttribute('sentry.http.prefetch', true);\n }\n\n options.instrumentation?.requestHook?.(span, req);\n },\n responseHook: (span, res) => {\n options.instrumentation?.responseHook?.(span, res);\n },\n applyCustomAttributesOnSpan: (\n span: Span,\n request: ClientRequest | HTTPModuleRequestIncomingMessage,\n response: HTTPModuleRequestIncomingMessage | ServerResponse,\n ) => {\n options.instrumentation?.applyCustomAttributesOnSpan?.(span, request, response);\n },\n } satisfies HttpInstrumentationConfig;\n\n return instrumentationConfig;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { isDebuggerEnabled } from '../../utils/debug.js';
|
|
|
4
4
|
import { LOCAL_VARIABLES_KEY, functionNamesMatch } from './common.js';
|
|
5
5
|
|
|
6
6
|
// This string is a placeholder that gets overwritten with the worker code.
|
|
7
|
-
const base64WorkerScript = '
|
|
7
|
+
const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA5LjEzLjAgKDZlNzc1YzYpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyBlfWZyb20ibm9kZTppbnNwZWN0b3IvcHJvbWlzZXMiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIHR9ZnJvbSJub2RlOndvcmtlcl90aHJlYWRzIjtjb25zdCBuPWdsb2JhbFRoaXMsbz0idW5kZWZpbmVkIj09dHlwZW9mIF9fU0VOVFJZX0RFQlVHX198fF9fU0VOVFJZX0RFQlVHX18saT0iOS4xMy4wIjtjb25zdCBhPVsiZGVidWciLCJpbmZvIiwid2FybiIsImVycm9yIiwibG9nIiwiYXNzZXJ0IiwidHJhY2UiXSxzPXt9O2Z1bmN0aW9uIGMoZSl7aWYoISgiY29uc29sZSJpbiBuKSlyZXR1cm4gZSgpO2NvbnN0IHQ9bi5jb25zb2xlLG89e30saT1PYmplY3Qua2V5cyhzKTtpLmZvckVhY2goKGU9Pntjb25zdCBuPXNbZV07b1tlXT10W2VdLHRbZV09bn0pKTt0cnl7cmV0dXJuIGUoKX1maW5hbGx5e2kuZm9yRWFjaCgoZT0+e3RbZV09b1tlXX0pKX19IWZ1bmN0aW9uKGUsdCxvPW4pe2NvbnN0IGE9by5fX1NFTlRSWV9fPW8uX19TRU5UUllfX3x8e30scz1hW2ldPWFbaV18fHt9O3NbZV18fChzW2VdPXQoKSl9KCJsb2dnZXIiLChmdW5jdGlvbigpe2xldCBlPSExO2NvbnN0IHQ9e2VuYWJsZTooKT0+e2U9ITB9LGRpc2FibGU6KCk9PntlPSExfSxpc0VuYWJsZWQ6KCk9PmV9O3JldHVybiBvP2EuZm9yRWFjaCgobz0+e3Rbb109KC4uLnQpPT57ZSYmYygoKCk9PntuLmNvbnNvbGVbb10oYFNlbnRyeSBMb2dnZXIgWyR7b31dOmAsLi4udCl9KSl9fSkpOmEuZm9yRWFjaCgoZT0+e3RbZV09KCk9Pnt9fSkpLHR9KSk7Y29uc3Qgcj0iX19TRU5UUllfRVJST1JfTE9DQUxfVkFSSUFCTEVTX18iO2NvbnN0IHU9dDtmdW5jdGlvbiBsKC4uLmUpe3UuZGVidWcmJmMoKCgpPT5jb25zb2xlLmxvZygiW0xvY2FsVmFyaWFibGVzIFdvcmtlcl0iLC4uLmUpKSl9YXN5bmMgZnVuY3Rpb24gZihlLHQsbixvKXtjb25zdCBpPWF3YWl0IGUucG9zdCgiUnVudGltZS5nZXRQcm9wZXJ0aWVzIix7b2JqZWN0SWQ6dCxvd25Qcm9wZXJ0aWVzOiEwfSk7b1tuXT1pLnJlc3VsdC5maWx0ZXIoKGU9PiJsZW5ndGgiIT09ZS5uYW1lJiYhaXNOYU4ocGFyc2VJbnQoZS5uYW1lLDEwKSkpKS5zb3J0KCgoZSx0KT0+cGFyc2VJbnQoZS5uYW1lLDEwKS1wYXJzZUludCh0Lm5hbWUsMTApKSkubWFwKChlPT5lLnZhbHVlPy52YWx1ZSkpfWFzeW5jIGZ1bmN0aW9uIGcoZSx0LG4sbyl7Y29uc3QgaT1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pO29bbl09aS5yZXN1bHQubWFwKChlPT5bZS5uYW1lLGUudmFsdWU/LnZhbHVlXSkpLnJlZHVjZSgoKGUsW3Qsbl0pPT4oZVt0XT1uLGUpKSx7fSl9ZnVuY3Rpb24gZChlLHQpe2UudmFsdWUmJigidmFsdWUiaW4gZS52YWx1ZT92b2lkIDA9PT1lLnZhbHVlLnZhbHVlfHxudWxsPT09ZS52YWx1ZS52YWx1ZT90W2UubmFtZV09YDwke2UudmFsdWUudmFsdWV9PmA6dFtlLm5hbWVdPWUudmFsdWUudmFsdWU6ImRlc2NyaXB0aW9uImluIGUudmFsdWUmJiJmdW5jdGlvbiIhPT1lLnZhbHVlLnR5cGU/dFtlLm5hbWVdPWA8JHtlLnZhbHVlLmRlc2NyaXB0aW9ufT5gOiJ1bmRlZmluZWQiPT09ZS52YWx1ZS50eXBlJiYodFtlLm5hbWVdPSI8dW5kZWZpbmVkPiIpKX1hc3luYyBmdW5jdGlvbiBiKGUsdCl7Y29uc3Qgbj1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pLG89e307Zm9yKGNvbnN0IHQgb2Ygbi5yZXN1bHQpaWYodC52YWx1ZT8ub2JqZWN0SWQmJiJBcnJheSI9PT10LnZhbHVlLmNsYXNzTmFtZSl7Y29uc3Qgbj10LnZhbHVlLm9iamVjdElkO2F3YWl0IGYoZSxuLHQubmFtZSxvKX1lbHNlIGlmKHQudmFsdWU/Lm9iamVjdElkJiYiT2JqZWN0Ij09PXQudmFsdWUuY2xhc3NOYW1lKXtjb25zdCBuPXQudmFsdWUub2JqZWN0SWQ7YXdhaXQgZyhlLG4sdC5uYW1lLG8pfWVsc2UgdC52YWx1ZSYmZCh0LG8pO3JldHVybiBvfWxldCBwOyhhc3luYyBmdW5jdGlvbigpe2NvbnN0IHQ9bmV3IGU7dC5jb25uZWN0VG9NYWluVGhyZWFkKCksbCgiQ29ubmVjdGVkIHRvIG1haW4gdGhyZWFkIik7bGV0IG49ITE7dC5vbigiRGVidWdnZXIucmVzdW1lZCIsKCgpPT57bj0hMX0pKSx0Lm9uKCJEZWJ1Z2dlci5wYXVzZWQiLChlPT57bj0hMCxhc3luYyBmdW5jdGlvbihlLHtyZWFzb246dCxkYXRhOntvYmplY3RJZDpufSxjYWxsRnJhbWVzOm99KXtpZigiZXhjZXB0aW9uIiE9PXQmJiJwcm9taXNlUmVqZWN0aW9uIiE9PXQpcmV0dXJuO2lmKHA/LigpLG51bGw9PW4pcmV0dXJuO2NvbnN0IGk9W107Zm9yKGxldCB0PTA7dDxvLmxlbmd0aDt0Kyspe2NvbnN0e3Njb3BlQ2hhaW46bixmdW5jdGlvbk5hbWU6YSx0aGlzOnN9PW9bdF0sYz1uLmZpbmQoKGU9PiJsb2NhbCI9PT1lLnR5cGUpKSxyPSJnbG9iYWwiIT09cy5jbGFzc05hbWUmJnMuY2xhc3NOYW1lP2Ake3MuY2xhc3NOYW1lfS4ke2F9YDphO2lmKHZvaWQgMD09PWM/Lm9iamVjdC5vYmplY3RJZClpW3RdPXtmdW5jdGlvbjpyfTtlbHNle2NvbnN0IG49YXdhaXQgYihlLGMub2JqZWN0Lm9iamVjdElkKTtpW3RdPXtmdW5jdGlvbjpyLHZhcnM6bn19fWF3YWl0IGUucG9zdCgiUnVudGltZS5jYWxsRnVuY3Rpb25PbiIse2Z1bmN0aW9uRGVjbGFyYXRpb246YGZ1bmN0aW9uKCkgeyB0aGlzLiR7cn0gPSB0aGlzLiR7cn0gfHwgJHtKU09OLnN0cmluZ2lmeShpKX07IH1gLHNpbGVudDohMCxvYmplY3RJZDpufSksYXdhaXQgZS5wb3N0KCJSdW50aW1lLnJlbGVhc2VPYmplY3QiLHtvYmplY3RJZDpufSl9KHQsZS5wYXJhbXMpLnRoZW4oKGFzeW5jKCk9PntuJiZhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpfSksKGFzeW5jIGU9PntuJiZhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpfSkpfSkpLGF3YWl0IHQucG9zdCgiRGVidWdnZXIuZW5hYmxlIik7Y29uc3Qgbz0hMSE9PXUuY2FwdHVyZUFsbEV4Y2VwdGlvbnM7aWYoYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOm8/ImFsbCI6InVuY2F1Z2h0In0pLG8pe2NvbnN0IGU9dS5tYXhFeGNlcHRpb25zUGVyU2Vjb25kfHw1MDtwPWZ1bmN0aW9uKGUsdCxuKXtsZXQgbz0wLGk9NSxhPTA7cmV0dXJuIHNldEludGVydmFsKCgoKT0+ezA9PT1hP28+ZSYmKGkqPTIsbihpKSxpPjg2NDAwJiYoaT04NjQwMCksYT1pKTooYS09MSwwPT09YSYmdCgpKSxvPTB9KSwxZTMpLnVucmVmKCksKCk9PntvKz0xfX0oZSwoYXN5bmMoKT0+e2woIlJhdGUtbGltaXQgbGlmdGVkLiIpLGF3YWl0IHQucG9zdCgiRGVidWdnZXIuc2V0UGF1c2VPbkV4Y2VwdGlvbnMiLHtzdGF0ZToiYWxsIn0pfSksKGFzeW5jIGU9PntsKGBSYXRlLWxpbWl0IGV4Y2VlZGVkLiBEaXNhYmxpbmcgY2FwdHVyaW5nIG9mIGNhdWdodCBleGNlcHRpb25zIGZvciAke2V9IHNlY29uZHMuYCksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJ1bmNhdWdodCJ9KX0pKX19KSgpLmNhdGNoKChlPT57bCgiRmFpbGVkIHRvIHN0YXJ0IGRlYnVnZ2VyIixlKX0pKSxzZXRJbnRlcnZhbCgoKCk9Pnt9KSwxZTQpOw==';
|
|
8
8
|
|
|
9
9
|
function log(...args) {
|
|
10
10
|
logger.log('[LocalVariables]', ...args);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! @sentry/node 9.
|
|
2
|
-
import{Session as e}from"node:inspector/promises";import{workerData as t}from"node:worker_threads";const n=globalThis,o="undefined"==typeof __SENTRY_DEBUG__||__SENTRY_DEBUG__,i="9.
|
|
1
|
+
/*! @sentry/node 9.13.0 (6e775c6) | https://github.com/getsentry/sentry-javascript */
|
|
2
|
+
import{Session as e}from"node:inspector/promises";import{workerData as t}from"node:worker_threads";const n=globalThis,o="undefined"==typeof __SENTRY_DEBUG__||__SENTRY_DEBUG__,i="9.13.0";const a=["debug","info","warn","error","log","assert","trace"],s={};function c(e){if(!("console"in n))return e();const t=n.console,o={},i=Object.keys(s);i.forEach((e=>{const n=s[e];o[e]=t[e],t[e]=n}));try{return e()}finally{i.forEach((e=>{t[e]=o[e]}))}}!function(e,t,o=n){const a=o.__SENTRY__=o.__SENTRY__||{},s=a[i]=a[i]||{};s[e]||(s[e]=t())}("logger",(function(){let e=!1;const t={enable:()=>{e=!0},disable:()=>{e=!1},isEnabled:()=>e};return o?a.forEach((o=>{t[o]=(...t)=>{e&&c((()=>{n.console[o](`Sentry Logger [${o}]:`,...t)}))}})):a.forEach((e=>{t[e]=()=>{}})),t}));const r="__SENTRY_ERROR_LOCAL_VARIABLES__";const u=t;function l(...e){u.debug&&c((()=>console.log("[LocalVariables Worker]",...e)))}async function f(e,t,n,o){const i=await e.post("Runtime.getProperties",{objectId:t,ownProperties:!0});o[n]=i.result.filter((e=>"length"!==e.name&&!isNaN(parseInt(e.name,10)))).sort(((e,t)=>parseInt(e.name,10)-parseInt(t.name,10))).map((e=>e.value?.value))}async function g(e,t,n,o){const i=await e.post("Runtime.getProperties",{objectId:t,ownProperties:!0});o[n]=i.result.map((e=>[e.name,e.value?.value])).reduce(((e,[t,n])=>(e[t]=n,e)),{})}function d(e,t){e.value&&("value"in e.value?void 0===e.value.value||null===e.value.value?t[e.name]=`<${e.value.value}>`:t[e.name]=e.value.value:"description"in e.value&&"function"!==e.value.type?t[e.name]=`<${e.value.description}>`:"undefined"===e.value.type&&(t[e.name]="<undefined>"))}async function b(e,t){const n=await e.post("Runtime.getProperties",{objectId:t,ownProperties:!0}),o={};for(const t of n.result)if(t.value?.objectId&&"Array"===t.value.className){const n=t.value.objectId;await f(e,n,t.name,o)}else if(t.value?.objectId&&"Object"===t.value.className){const n=t.value.objectId;await g(e,n,t.name,o)}else t.value&&d(t,o);return o}let p;(async function(){const t=new e;t.connectToMainThread(),l("Connected to main thread");let n=!1;t.on("Debugger.resumed",(()=>{n=!1})),t.on("Debugger.paused",(e=>{n=!0,async function(e,{reason:t,data:{objectId:n},callFrames:o}){if("exception"!==t&&"promiseRejection"!==t)return;if(p?.(),null==n)return;const i=[];for(let t=0;t<o.length;t++){const{scopeChain:n,functionName:a,this:s}=o[t],c=n.find((e=>"local"===e.type)),r="global"!==s.className&&s.className?`${s.className}.${a}`:a;if(void 0===c?.object.objectId)i[t]={function:r};else{const n=await b(e,c.object.objectId);i[t]={function:r,vars:n}}}await e.post("Runtime.callFunctionOn",{functionDeclaration:`function() { this.${r} = this.${r} || ${JSON.stringify(i)}; }`,silent:!0,objectId:n}),await e.post("Runtime.releaseObject",{objectId:n})}(t,e.params).then((async()=>{n&&await t.post("Debugger.resume")}),(async e=>{n&&await t.post("Debugger.resume")}))})),await t.post("Debugger.enable");const o=!1!==u.captureAllExceptions;if(await t.post("Debugger.setPauseOnExceptions",{state:o?"all":"uncaught"}),o){const e=u.maxExceptionsPerSecond||50;p=function(e,t,n){let o=0,i=5,a=0;return setInterval((()=>{0===a?o>e&&(i*=2,n(i),i>86400&&(i=86400),a=i):(a-=1,0===a&&t()),o=0}),1e3).unref(),()=>{o+=1}}(e,(async()=>{l("Rate-limit lifted."),await t.post("Debugger.setPauseOnExceptions",{state:"all"})}),(async e=>{l(`Rate-limit exceeded. Disabling capturing of caught exceptions for ${e} seconds.`),await t.post("Debugger.setPauseOnExceptions",{state:"uncaught"})}))}})().catch((e=>{l("Failed to start debugger",e)})),setInterval((()=>{}),1e4);
|
|
@@ -5,14 +5,19 @@ import { SentryNodeFetchInstrumentation } from './SentryNodeFetchInstrumentation
|
|
|
5
5
|
|
|
6
6
|
const INTEGRATION_NAME = 'NodeFetch';
|
|
7
7
|
|
|
8
|
-
const instrumentOtelNodeFetch = generateInstrumentOnce(
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const instrumentOtelNodeFetch = generateInstrumentOnce(
|
|
9
|
+
INTEGRATION_NAME,
|
|
10
|
+
UndiciInstrumentation,
|
|
11
|
+
(options) => {
|
|
12
|
+
return getConfigWithDefaults(options);
|
|
13
|
+
},
|
|
14
|
+
);
|
|
11
15
|
|
|
12
16
|
const instrumentSentryNodeFetch = generateInstrumentOnce(
|
|
13
17
|
`${INTEGRATION_NAME}.sentry`,
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
SentryNodeFetchInstrumentation,
|
|
19
|
+
(options) => {
|
|
20
|
+
return options;
|
|
16
21
|
},
|
|
17
22
|
);
|
|
18
23
|
|
|
@@ -24,8 +29,7 @@ const _nativeNodeFetchIntegration = ((options = {}) => {
|
|
|
24
29
|
|
|
25
30
|
// This is the "regular" OTEL instrumentation that emits spans
|
|
26
31
|
if (instrumentSpans) {
|
|
27
|
-
|
|
28
|
-
instrumentOtelNodeFetch(instrumentationConfig);
|
|
32
|
+
instrumentOtelNodeFetch(options);
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
// This is the Sentry-specific instrumentation that creates breadcrumbs & propagates traces
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/integrations/node-fetch/index.ts"],"sourcesContent":["import type { UndiciInstrumentationConfig } from '@opentelemetry/instrumentation-undici';\nimport { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici';\nimport type { IntegrationFn } from '@sentry/core';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, defineIntegration, getClient } from '@sentry/core';\nimport { generateInstrumentOnce } from '../../otel/instrument';\nimport type { NodeClient } from '../../sdk/client';\nimport type { NodeClientOptions } from '../../types';\nimport
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/integrations/node-fetch/index.ts"],"sourcesContent":["import type { UndiciInstrumentationConfig } from '@opentelemetry/instrumentation-undici';\nimport { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici';\nimport type { IntegrationFn } from '@sentry/core';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, defineIntegration, getClient } from '@sentry/core';\nimport { generateInstrumentOnce } from '../../otel/instrument';\nimport type { NodeClient } from '../../sdk/client';\nimport type { NodeClientOptions } from '../../types';\nimport { SentryNodeFetchInstrumentation } from './SentryNodeFetchInstrumentation';\n\nconst INTEGRATION_NAME = 'NodeFetch';\n\ninterface NodeFetchOptions {\n /**\n * Whether breadcrumbs should be recorded for requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * If set to false, do not emit any spans.\n * This will ensure that the default UndiciInstrumentation from OpenTelemetry is not setup,\n * only the Sentry-specific instrumentation for breadcrumbs & trace propagation is applied.\n *\n * If `skipOpenTelemetrySetup: true` is configured, this defaults to `false`, otherwise it defaults to `true`.\n */\n spans?: boolean;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing fetch requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n */\n ignoreOutgoingRequests?: (url: string) => boolean;\n}\n\nconst instrumentOtelNodeFetch = generateInstrumentOnce(\n INTEGRATION_NAME,\n UndiciInstrumentation,\n (options: NodeFetchOptions) => {\n return getConfigWithDefaults(options);\n },\n);\n\nconst instrumentSentryNodeFetch = generateInstrumentOnce(\n `${INTEGRATION_NAME}.sentry`,\n SentryNodeFetchInstrumentation,\n (options: NodeFetchOptions) => {\n return options;\n },\n);\n\nconst _nativeNodeFetchIntegration = ((options: NodeFetchOptions = {}) => {\n return {\n name: 'NodeFetch',\n setupOnce() {\n const instrumentSpans = _shouldInstrumentSpans(options, getClient<NodeClient>()?.getOptions());\n\n // This is the \"regular\" OTEL instrumentation that emits spans\n if (instrumentSpans) {\n instrumentOtelNodeFetch(options);\n }\n\n // This is the Sentry-specific instrumentation that creates breadcrumbs & propagates traces\n // This must be registered after the OTEL one, to ensure that the core trace propagation logic takes presedence\n // Otherwise, the sentry-trace header may be set multiple times\n instrumentSentryNodeFetch(options);\n },\n };\n}) satisfies IntegrationFn;\n\nexport const nativeNodeFetchIntegration = defineIntegration(_nativeNodeFetchIntegration);\n\n// Matching the behavior of the base instrumentation\nfunction getAbsoluteUrl(origin: string, path: string = '/'): string {\n const url = `${origin}`;\n\n if (url.endsWith('/') && path.startsWith('/')) {\n return `${url}${path.slice(1)}`;\n }\n\n if (!url.endsWith('/') && !path.startsWith('/')) {\n return `${url}/${path.slice(1)}`;\n }\n\n return `${url}${path}`;\n}\n\nfunction _shouldInstrumentSpans(options: NodeFetchOptions, clientOptions: Partial<NodeClientOptions> = {}): boolean {\n // If `spans` is passed in, it takes precedence\n // Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true`\n return typeof options.spans === 'boolean' ? options.spans : !clientOptions.skipOpenTelemetrySetup;\n}\n\nfunction getConfigWithDefaults(options: Partial<NodeFetchOptions> = {}): UndiciInstrumentationConfig {\n const instrumentationConfig = {\n requireParentforSpans: false,\n ignoreRequestHook: request => {\n const url = getAbsoluteUrl(request.origin, request.path);\n const _ignoreOutgoingRequests = options.ignoreOutgoingRequests;\n const shouldIgnore = _ignoreOutgoingRequests && url && _ignoreOutgoingRequests(url);\n\n return !!shouldIgnore;\n },\n startSpanHook: () => {\n return {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.node_fetch',\n };\n },\n } satisfies UndiciInstrumentationConfig;\n\n return instrumentationConfig;\n}\n"],"names":[],"mappings":";;;;;AASA,MAAM,gBAAA,GAAmB,WAAW;;AAyBpC,MAAM,uBAAA,GAA0B,sBAAsB;AACtD,EAAE,gBAAgB;AAClB,EAAE,qBAAqB;AACvB,EAAE,CAAC,OAAO,KAAuB;AACjC,IAAI,OAAO,qBAAqB,CAAC,OAAO,CAAC;AACzC,GAAG;AACH,CAAC;;AAED,MAAM,yBAAA,GAA4B,sBAAsB;AACxD,EAAE,CAAC,EAAA,gBAAA,CAAA,OAAA,CAAA;AACA,EAAA,8BAAA;AACA,EAAA,CAAA,OAAA,KAAA;AACA,IAAA,OAAA,OAAA;AACA,GAAA;AACA,CAAA;;AAEA,MAAA,2BAAA,IAAA,CAAA,OAAA,GAAA,EAAA,KAAA;AACA,EAAA,OAAA;AACA,IAAA,IAAA,EAAA,WAAA;AACA,IAAA,SAAA,GAAA;AACA,MAAA,MAAA,eAAA,GAAA,sBAAA,CAAA,OAAA,EAAA,SAAA,EAAA,EAAA,UAAA,EAAA,CAAA;;AAEA;AACA,MAAA,IAAA,eAAA,EAAA;AACA,QAAA,uBAAA,CAAA,OAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA,MAAA,yBAAA,CAAA,OAAA,CAAA;AACA,KAAA;AACA,GAAA;AACA,CAAA,CAAA;;AAEA,MAAA,0BAAA,GAAA,iBAAA,CAAA,2BAAA;;AAEA;AACA,SAAA,cAAA,CAAA,MAAA,EAAA,IAAA,GAAA,GAAA,EAAA;AACA,EAAA,MAAA,GAAA,GAAA,CAAA,EAAA,MAAA,CAAA,CAAA;;AAEA,EAAA,IAAA,GAAA,CAAA,QAAA,CAAA,GAAA,CAAA,IAAA,IAAA,CAAA,UAAA,CAAA,GAAA,CAAA,EAAA;AACA,IAAA,OAAA,CAAA,EAAA,GAAA,CAAA,EAAA,IAAA,CAAA,KAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AACA;;AAEA,EAAA,IAAA,CAAA,GAAA,CAAA,QAAA,CAAA,GAAA,CAAA,IAAA,CAAA,IAAA,CAAA,UAAA,CAAA,GAAA,CAAA,EAAA;AACA,IAAA,OAAA,CAAA,EAAA,GAAA,CAAA,CAAA,EAAA,IAAA,CAAA,KAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AACA;;AAEA,EAAA,OAAA,CAAA,EAAA,GAAA,CAAA,EAAA,IAAA,CAAA,CAAA;AACA;;AAEA,SAAA,sBAAA,CAAA,OAAA,EAAA,aAAA,GAAA,EAAA,EAAA;AACA;AACA;AACA,EAAA,OAAA,OAAA,OAAA,CAAA,KAAA,KAAA,SAAA,GAAA,OAAA,CAAA,KAAA,GAAA,CAAA,aAAA,CAAA,sBAAA;AACA;;AAEA,SAAA,qBAAA,CAAA,OAAA,GAAA,EAAA,EAAA;AACA,EAAA,MAAA,qBAAA,GAAA;AACA,IAAA,qBAAA,EAAA,KAAA;AACA,IAAA,iBAAA,EAAA,OAAA,IAAA;AACA,MAAA,MAAA,GAAA,GAAA,cAAA,CAAA,OAAA,CAAA,MAAA,EAAA,OAAA,CAAA,IAAA,CAAA;AACA,MAAA,MAAA,uBAAA,GAAA,OAAA,CAAA,sBAAA;AACA,MAAA,MAAA,YAAA,GAAA,uBAAA,IAAA,GAAA,IAAA,uBAAA,CAAA,GAAA,CAAA;;AAEA,MAAA,OAAA,CAAA,CAAA,YAAA;AACA,KAAA;AACA,IAAA,aAAA,EAAA,MAAA;AACA,MAAA,OAAA;AACA,QAAA,CAAA,gCAAA,GAAA,2BAAA;AACA,OAAA;AACA,KAAA;AACA,GAAA;;AAEA,EAAA,OAAA,qBAAA;AACA;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
|
|
2
|
-
import { defineIntegration, getIsolationScope, getDefaultIsolationScope, logger, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP
|
|
2
|
+
import { defineIntegration, httpRequestToRequestData, getIsolationScope, captureException, getDefaultIsolationScope, logger, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP } from '@sentry/core';
|
|
3
3
|
import { DEBUG_BUILD } from '../../debug-build.js';
|
|
4
4
|
import { generateInstrumentOnce } from '../../otel/instrument.js';
|
|
5
5
|
import { addOriginToSpan } from '../../utils/addOriginToSpan.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FastifyInstrumentation } from '@opentelemetry/instrumentation-fastify';
|
|
2
|
-
import { defineIntegration,
|
|
2
|
+
import { defineIntegration, captureException, getIsolationScope, getClient, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
|
|
3
3
|
import { generateInstrumentOnce } from '../../otel/instrument.js';
|
|
4
4
|
import { ensureIsWrapped } from '../../utils/ensureIsWrapped.js';
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql';
|
|
2
|
-
import { spanToJSON, getRootSpan
|
|
2
|
+
import { defineIntegration, spanToJSON, getRootSpan } from '@sentry/core';
|
|
3
3
|
import { SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION } from '@sentry/opentelemetry';
|
|
4
4
|
import { generateInstrumentOnce } from '../../otel/instrument.js';
|
|
5
5
|
import { addOriginToSpan } from '../../utils/addOriginToSpan.js';
|
|
@@ -8,10 +8,11 @@ const INTEGRATION_NAME = 'Graphql';
|
|
|
8
8
|
|
|
9
9
|
const instrumentGraphql = generateInstrumentOnce(
|
|
10
10
|
INTEGRATION_NAME,
|
|
11
|
-
|
|
11
|
+
GraphQLInstrumentation,
|
|
12
|
+
(_options) => {
|
|
12
13
|
const options = getOptionsWithDefaults(_options);
|
|
13
14
|
|
|
14
|
-
return
|
|
15
|
+
return {
|
|
15
16
|
...options,
|
|
16
17
|
responseHook(span) {
|
|
17
18
|
addOriginToSpan(span, 'auto.graphql.otel.graphql');
|
|
@@ -40,9 +41,19 @@ const instrumentGraphql = generateInstrumentOnce(
|
|
|
40
41
|
} else {
|
|
41
42
|
rootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION, newOperation);
|
|
42
43
|
}
|
|
44
|
+
|
|
45
|
+
if (!spanToJSON(rootSpan).data['original-description']) {
|
|
46
|
+
rootSpan.setAttribute('original-description', spanToJSON(rootSpan).description);
|
|
47
|
+
}
|
|
48
|
+
// Important for e.g. @sentry/aws-serverless because this would otherwise overwrite the name again
|
|
49
|
+
rootSpan.updateName(
|
|
50
|
+
`${spanToJSON(rootSpan).data['original-description']} (${getGraphqlOperationNamesFromAttribute(
|
|
51
|
+
existingOperations,
|
|
52
|
+
)})`,
|
|
53
|
+
);
|
|
43
54
|
}
|
|
44
55
|
},
|
|
45
|
-
}
|
|
56
|
+
};
|
|
46
57
|
},
|
|
47
58
|
);
|
|
48
59
|
|
|
@@ -84,5 +95,22 @@ function getOptionsWithDefaults(options) {
|
|
|
84
95
|
};
|
|
85
96
|
}
|
|
86
97
|
|
|
98
|
+
// copy from packages/opentelemetry/utils
|
|
99
|
+
function getGraphqlOperationNamesFromAttribute(attr) {
|
|
100
|
+
if (Array.isArray(attr)) {
|
|
101
|
+
const sorted = attr.slice().sort();
|
|
102
|
+
|
|
103
|
+
// Up to 5 items, we just add all of them
|
|
104
|
+
if (sorted.length <= 5) {
|
|
105
|
+
return sorted.join(', ');
|
|
106
|
+
} else {
|
|
107
|
+
// Else, we add the first 5 and the diff of other operations
|
|
108
|
+
return `${sorted.slice(0, 5).join(', ')}, +${sorted.length - 5}`;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return `${attr}`;
|
|
113
|
+
}
|
|
114
|
+
|
|
87
115
|
export { graphqlIntegration, instrumentGraphql };
|
|
88
116
|
//# sourceMappingURL=graphql.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql.js","sources":["../../../../src/integrations/tracing/graphql.ts"],"sourcesContent":["import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql';\nimport { defineIntegration, getRootSpan, spanToJSON } from '@sentry/core';\nimport type { IntegrationFn } from '@sentry/core';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION } from '@sentry/opentelemetry';\nimport { generateInstrumentOnce } from '../../otel/instrument';\n\nimport { addOriginToSpan } from '../../utils/addOriginToSpan';\n\ninterface GraphqlOptions {\n /**\n * Do not create spans for resolvers.\n *\n * Defaults to true.\n */\n ignoreResolveSpans?: boolean;\n\n /**\n * Don't create spans for the execution of the default resolver on object properties.\n *\n * When a resolver function is not defined on the schema for a field, graphql will\n * use the default resolver which just looks for a property with that name on the object.\n * If the property is not a function, it's not very interesting to trace.\n * This option can reduce noise and number of spans created.\n *\n * Defaults to true.\n */\n ignoreTrivialResolveSpans?: boolean;\n\n /**\n * If this is enabled, a http.server root span containing this span will automatically be renamed to include the operation name.\n * Set this to `false` if you do not want this behavior, and want to keep the default http.server span name.\n *\n * Defaults to true.\n */\n useOperationNameForRootSpan?: boolean;\n}\n\nconst INTEGRATION_NAME = 'Graphql';\n\nexport const instrumentGraphql = generateInstrumentOnce
|
|
1
|
+
{"version":3,"file":"graphql.js","sources":["../../../../src/integrations/tracing/graphql.ts"],"sourcesContent":["import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql';\nimport { defineIntegration, getRootSpan, spanToJSON } from '@sentry/core';\nimport type { IntegrationFn } from '@sentry/core';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION } from '@sentry/opentelemetry';\nimport { generateInstrumentOnce } from '../../otel/instrument';\n\nimport { addOriginToSpan } from '../../utils/addOriginToSpan';\nimport type { AttributeValue } from '@opentelemetry/api';\n\ninterface GraphqlOptions {\n /**\n * Do not create spans for resolvers.\n *\n * Defaults to true.\n */\n ignoreResolveSpans?: boolean;\n\n /**\n * Don't create spans for the execution of the default resolver on object properties.\n *\n * When a resolver function is not defined on the schema for a field, graphql will\n * use the default resolver which just looks for a property with that name on the object.\n * If the property is not a function, it's not very interesting to trace.\n * This option can reduce noise and number of spans created.\n *\n * Defaults to true.\n */\n ignoreTrivialResolveSpans?: boolean;\n\n /**\n * If this is enabled, a http.server root span containing this span will automatically be renamed to include the operation name.\n * Set this to `false` if you do not want this behavior, and want to keep the default http.server span name.\n *\n * Defaults to true.\n */\n useOperationNameForRootSpan?: boolean;\n}\n\nconst INTEGRATION_NAME = 'Graphql';\n\nexport const instrumentGraphql = generateInstrumentOnce(\n INTEGRATION_NAME,\n GraphQLInstrumentation,\n (_options: GraphqlOptions) => {\n const options = getOptionsWithDefaults(_options);\n\n return {\n ...options,\n responseHook(span) {\n addOriginToSpan(span, 'auto.graphql.otel.graphql');\n\n const attributes = spanToJSON(span).data;\n\n // If operation.name is not set, we fall back to use operation.type only\n const operationType = attributes['graphql.operation.type'];\n const operationName = attributes['graphql.operation.name'];\n\n if (options.useOperationNameForRootSpan && operationType) {\n const rootSpan = getRootSpan(span);\n const rootSpanAttributes = spanToJSON(rootSpan).data;\n\n const existingOperations = rootSpanAttributes[SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION] || [];\n\n const newOperation = operationName ? `${operationType} ${operationName}` : `${operationType}`;\n\n // We keep track of each operation on the root span\n // This can either be a string, or an array of strings (if there are multiple operations)\n if (Array.isArray(existingOperations)) {\n (existingOperations as string[]).push(newOperation);\n rootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION, existingOperations);\n } else if (typeof existingOperations === 'string') {\n rootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION, [existingOperations, newOperation]);\n } else {\n rootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION, newOperation);\n }\n\n if (!spanToJSON(rootSpan).data['original-description']) {\n rootSpan.setAttribute('original-description', spanToJSON(rootSpan).description);\n }\n // Important for e.g. @sentry/aws-serverless because this would otherwise overwrite the name again\n rootSpan.updateName(\n `${spanToJSON(rootSpan).data['original-description']} (${getGraphqlOperationNamesFromAttribute(\n existingOperations,\n )})`,\n );\n }\n },\n };\n },\n);\n\nconst _graphqlIntegration = ((options: GraphqlOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // We set defaults here, too, because otherwise we'd update the instrumentation config\n // to the config without defaults, as `generateInstrumentOnce` automatically calls `setConfig(options)`\n // when being called the second time\n instrumentGraphql(getOptionsWithDefaults(options));\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [graphql](https://www.npmjs.com/package/graphql) library.\n *\n * For more information, see the [`graphqlIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/graphql/).\n *\n * @param {GraphqlOptions} options Configuration options for the GraphQL integration.\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.graphqlIntegration()],\n * });\n */\nexport const graphqlIntegration = defineIntegration(_graphqlIntegration);\n\nfunction getOptionsWithDefaults(options?: GraphqlOptions): GraphqlOptions {\n return {\n ignoreResolveSpans: true,\n ignoreTrivialResolveSpans: true,\n useOperationNameForRootSpan: true,\n ...options,\n };\n}\n\n// copy from packages/opentelemetry/utils\nfunction getGraphqlOperationNamesFromAttribute(attr: AttributeValue): string {\n if (Array.isArray(attr)) {\n const sorted = attr.slice().sort();\n\n // Up to 5 items, we just add all of them\n if (sorted.length <= 5) {\n return sorted.join(', ');\n } else {\n // Else, we add the first 5 and the diff of other operations\n return `${sorted.slice(0, 5).join(', ')}, +${sorted.length - 5}`;\n }\n }\n\n return `${attr}`;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { KoaInstrumentation } from '@opentelemetry/instrumentation-koa';
|
|
2
2
|
import { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';
|
|
3
|
-
import { getIsolationScope, getDefaultIsolationScope, logger, spanToJSON,
|
|
3
|
+
import { defineIntegration, captureException, getIsolationScope, getDefaultIsolationScope, logger, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP } from '@sentry/core';
|
|
4
4
|
import { DEBUG_BUILD } from '../../debug-build.js';
|
|
5
5
|
import { generateInstrumentOnce } from '../../otel/instrument.js';
|
|
6
6
|
import { ensureIsWrapped } from '../../utils/ensureIsWrapped.js';
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { captureLog } from '../logs/capture.js';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_CAPTURED_LEVELS = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];
|
|
4
|
+
|
|
5
|
+
// See: https://github.com/winstonjs/triple-beam
|
|
6
|
+
const LEVEL_SYMBOL = Symbol.for('level');
|
|
7
|
+
const MESSAGE_SYMBOL = Symbol.for('message');
|
|
8
|
+
const SPLAT_SYMBOL = Symbol.for('splat');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Options for the Sentry Winston transport.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new Sentry Winston transport that fowards logs to Sentry. Requires `_experiments.enableLogs` to be enabled.
|
|
16
|
+
*
|
|
17
|
+
* Supports Winston 3.x.x.
|
|
18
|
+
*
|
|
19
|
+
* @param TransportClass - The Winston transport class to extend.
|
|
20
|
+
* @returns The extended transport class.
|
|
21
|
+
*
|
|
22
|
+
* @experimental This method will experience breaking changes. This is not yet part of
|
|
23
|
+
* the stable Sentry SDK API and can be changed or removed without warning.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* const winston = require('winston');
|
|
28
|
+
* const Transport = require('winston-transport');
|
|
29
|
+
*
|
|
30
|
+
* const transport = Sentry.createSentryWinstonTransport(Transport);
|
|
31
|
+
*
|
|
32
|
+
* const logger = winston.createLogger({
|
|
33
|
+
* transports: [transport],
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
function createSentryWinstonTransport(
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
|
+
TransportClass,
|
|
40
|
+
sentryWinstonOptions,
|
|
41
|
+
) {
|
|
42
|
+
// @ts-ignore - We know this is safe because SentryWinstonTransport extends TransportClass
|
|
43
|
+
class SentryWinstonTransport extends TransportClass {
|
|
44
|
+
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
|
+
constructor(options) {
|
|
47
|
+
super(options);
|
|
48
|
+
this._levels = new Set(sentryWinstonOptions?.levels ?? DEFAULT_CAPTURED_LEVELS);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Forwards a winston log to the Sentry SDK.
|
|
53
|
+
*/
|
|
54
|
+
log(info, callback) {
|
|
55
|
+
try {
|
|
56
|
+
setImmediate(() => {
|
|
57
|
+
// @ts-ignore - We know this is safe because SentryWinstonTransport extends TransportClass
|
|
58
|
+
this.emit('logged', info);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (!isObject(info)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const levelFromSymbol = info[LEVEL_SYMBOL];
|
|
66
|
+
|
|
67
|
+
// See: https://github.com/winstonjs/winston?tab=readme-ov-file#streams-objectmode-and-info-objects
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
69
|
+
const { level, message, timestamp, ...attributes } = info;
|
|
70
|
+
// Remove all symbols from the remaining attributes
|
|
71
|
+
attributes[LEVEL_SYMBOL] = undefined;
|
|
72
|
+
attributes[MESSAGE_SYMBOL] = undefined;
|
|
73
|
+
attributes[SPLAT_SYMBOL] = undefined;
|
|
74
|
+
|
|
75
|
+
const logSeverityLevel = WINSTON_LEVEL_TO_LOG_SEVERITY_LEVEL_MAP[levelFromSymbol ] ?? 'info';
|
|
76
|
+
if (this._levels.has(logSeverityLevel)) {
|
|
77
|
+
captureLog(logSeverityLevel, message , {
|
|
78
|
+
...attributes,
|
|
79
|
+
'sentry.origin': 'auto.logging.winston',
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
} catch {
|
|
83
|
+
// do nothing
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (callback) {
|
|
87
|
+
callback();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return SentryWinstonTransport ;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function isObject(anything) {
|
|
96
|
+
return typeof anything === 'object' && anything != null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// npm
|
|
100
|
+
// {
|
|
101
|
+
// error: 0,
|
|
102
|
+
// warn: 1,
|
|
103
|
+
// info: 2,
|
|
104
|
+
// http: 3,
|
|
105
|
+
// verbose: 4,
|
|
106
|
+
// debug: 5,
|
|
107
|
+
// silly: 6
|
|
108
|
+
// }
|
|
109
|
+
//
|
|
110
|
+
// syslog
|
|
111
|
+
// {
|
|
112
|
+
// emerg: 0,
|
|
113
|
+
// alert: 1,
|
|
114
|
+
// crit: 2,
|
|
115
|
+
// error: 3,
|
|
116
|
+
// warning: 4,
|
|
117
|
+
// notice: 5,
|
|
118
|
+
// info: 6,
|
|
119
|
+
// debug: 7,
|
|
120
|
+
// }
|
|
121
|
+
const WINSTON_LEVEL_TO_LOG_SEVERITY_LEVEL_MAP = {
|
|
122
|
+
// npm
|
|
123
|
+
silly: 'trace',
|
|
124
|
+
// npm and syslog
|
|
125
|
+
debug: 'debug',
|
|
126
|
+
// npm
|
|
127
|
+
verbose: 'debug',
|
|
128
|
+
// npm
|
|
129
|
+
http: 'debug',
|
|
130
|
+
// npm and syslog
|
|
131
|
+
info: 'info',
|
|
132
|
+
// syslog
|
|
133
|
+
notice: 'info',
|
|
134
|
+
// npm
|
|
135
|
+
warn: 'warn',
|
|
136
|
+
// syslog
|
|
137
|
+
warning: 'warn',
|
|
138
|
+
// npm and syslog
|
|
139
|
+
error: 'error',
|
|
140
|
+
// syslog
|
|
141
|
+
emerg: 'fatal',
|
|
142
|
+
// syslog
|
|
143
|
+
alert: 'fatal',
|
|
144
|
+
// syslog
|
|
145
|
+
crit: 'fatal',
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export { createSentryWinstonTransport };
|
|
149
|
+
//# sourceMappingURL=winston.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"winston.js","sources":["../../../src/integrations/winston.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport type { LogSeverityLevel } from '@sentry/core';\nimport { captureLog } from '../logs/capture';\n\nconst DEFAULT_CAPTURED_LEVELS: Array<LogSeverityLevel> = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];\n\n// See: https://github.com/winstonjs/triple-beam\nconst LEVEL_SYMBOL = Symbol.for('level');\nconst MESSAGE_SYMBOL = Symbol.for('message');\nconst SPLAT_SYMBOL = Symbol.for('splat');\n\n/**\n * Options for the Sentry Winston transport.\n */\ninterface WinstonTransportOptions {\n /**\n * Use this option to filter which levels should be captured. By default, all levels are captured.\n *\n * @example\n * ```ts\n * const transport = Sentry.createSentryWinstonTransport(Transport, {\n * // Only capture error and warn logs\n * levels: ['error', 'warn'],\n * });\n * ```\n */\n levels?: Array<LogSeverityLevel>;\n}\n\n/**\n * Creates a new Sentry Winston transport that fowards logs to Sentry. Requires `_experiments.enableLogs` to be enabled.\n *\n * Supports Winston 3.x.x.\n *\n * @param TransportClass - The Winston transport class to extend.\n * @returns The extended transport class.\n *\n * @experimental This method will experience breaking changes. This is not yet part of\n * the stable Sentry SDK API and can be changed or removed without warning.\n *\n * @example\n * ```ts\n * const winston = require('winston');\n * const Transport = require('winston-transport');\n *\n * const transport = Sentry.createSentryWinstonTransport(Transport);\n *\n * const logger = winston.createLogger({\n * transports: [transport],\n * });\n * ```\n */\nexport function createSentryWinstonTransport<TransportStreamInstance extends object>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TransportClass: new (options?: any) => TransportStreamInstance,\n sentryWinstonOptions?: WinstonTransportOptions,\n): typeof TransportClass {\n // @ts-ignore - We know this is safe because SentryWinstonTransport extends TransportClass\n class SentryWinstonTransport extends TransportClass {\n private _levels: Set<LogSeverityLevel>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public constructor(options?: any) {\n super(options);\n this._levels = new Set(sentryWinstonOptions?.levels ?? DEFAULT_CAPTURED_LEVELS);\n }\n\n /**\n * Forwards a winston log to the Sentry SDK.\n */\n public log(info: unknown, callback: () => void): void {\n try {\n setImmediate(() => {\n // @ts-ignore - We know this is safe because SentryWinstonTransport extends TransportClass\n this.emit('logged', info);\n });\n\n if (!isObject(info)) {\n return;\n }\n\n const levelFromSymbol = info[LEVEL_SYMBOL];\n\n // See: https://github.com/winstonjs/winston?tab=readme-ov-file#streams-objectmode-and-info-objects\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { level, message, timestamp, ...attributes } = info;\n // Remove all symbols from the remaining attributes\n attributes[LEVEL_SYMBOL] = undefined;\n attributes[MESSAGE_SYMBOL] = undefined;\n attributes[SPLAT_SYMBOL] = undefined;\n\n const logSeverityLevel = WINSTON_LEVEL_TO_LOG_SEVERITY_LEVEL_MAP[levelFromSymbol as string] ?? 'info';\n if (this._levels.has(logSeverityLevel)) {\n captureLog(logSeverityLevel, message as string, {\n ...attributes,\n 'sentry.origin': 'auto.logging.winston',\n });\n }\n } catch {\n // do nothing\n }\n\n if (callback) {\n callback();\n }\n }\n }\n\n return SentryWinstonTransport as typeof TransportClass;\n}\n\nfunction isObject(anything: unknown): anything is Record<string | symbol, unknown> {\n return typeof anything === 'object' && anything != null;\n}\n\n// npm\n// {\n// error: 0,\n// warn: 1,\n// info: 2,\n// http: 3,\n// verbose: 4,\n// debug: 5,\n// silly: 6\n// }\n//\n// syslog\n// {\n// emerg: 0,\n// alert: 1,\n// crit: 2,\n// error: 3,\n// warning: 4,\n// notice: 5,\n// info: 6,\n// debug: 7,\n// }\nconst WINSTON_LEVEL_TO_LOG_SEVERITY_LEVEL_MAP: Record<string, LogSeverityLevel> = {\n // npm\n silly: 'trace',\n // npm and syslog\n debug: 'debug',\n // npm\n verbose: 'debug',\n // npm\n http: 'debug',\n // npm and syslog\n info: 'info',\n // syslog\n notice: 'info',\n // npm\n warn: 'warn',\n // syslog\n warning: 'warn',\n // npm and syslog\n error: 'error',\n // syslog\n emerg: 'fatal',\n // syslog\n alert: 'fatal',\n // syslog\n crit: 'fatal',\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { format } from 'node:util';
|
|
2
|
+
import { _INTERNAL_captureLog } from '@sentry/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Capture a log with the given level.
|
|
6
|
+
*
|
|
7
|
+
* @param level - The level of the log.
|
|
8
|
+
* @param message - The message to log.
|
|
9
|
+
* @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100.
|
|
10
|
+
*/
|
|
11
|
+
function captureLog(level, ...args) {
|
|
12
|
+
const [messageOrMessageTemplate, paramsOrAttributes, maybeAttributes] = args;
|
|
13
|
+
if (Array.isArray(paramsOrAttributes)) {
|
|
14
|
+
const attributes = { ...maybeAttributes };
|
|
15
|
+
attributes['sentry.message.template'] = messageOrMessageTemplate;
|
|
16
|
+
paramsOrAttributes.forEach((param, index) => {
|
|
17
|
+
attributes[`sentry.message.parameter.${index}`] = param;
|
|
18
|
+
});
|
|
19
|
+
const message = format(messageOrMessageTemplate, ...paramsOrAttributes);
|
|
20
|
+
_INTERNAL_captureLog({ level, message, attributes });
|
|
21
|
+
} else {
|
|
22
|
+
_INTERNAL_captureLog({ level, message: messageOrMessageTemplate, attributes: paramsOrAttributes });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { captureLog };
|
|
27
|
+
//# sourceMappingURL=capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.js","sources":["../../../src/logs/capture.ts"],"sourcesContent":["import { format } from 'node:util';\n\nimport type { LogSeverityLevel, Log, ParameterizedString } from '@sentry/core';\nimport { _INTERNAL_captureLog } from '@sentry/core';\n\nexport type CaptureLogArgs =\n | [message: ParameterizedString, attributes?: Log['attributes']]\n | [messageTemplate: string, messageParams: Array<unknown>, attributes?: Log['attributes']];\n\n/**\n * Capture a log with the given level.\n *\n * @param level - The level of the log.\n * @param message - The message to log.\n * @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100.\n */\nexport function captureLog(level: LogSeverityLevel, ...args: CaptureLogArgs): void {\n const [messageOrMessageTemplate, paramsOrAttributes, maybeAttributes] = args;\n if (Array.isArray(paramsOrAttributes)) {\n const attributes = { ...maybeAttributes };\n attributes['sentry.message.template'] = messageOrMessageTemplate;\n paramsOrAttributes.forEach((param, index) => {\n attributes[`sentry.message.parameter.${index}`] = param;\n });\n const message = format(messageOrMessageTemplate, ...paramsOrAttributes);\n _INTERNAL_captureLog({ level, message, attributes });\n } else {\n _INTERNAL_captureLog({ level, message: messageOrMessageTemplate, attributes: paramsOrAttributes });\n }\n}\n"],"names":[],"mappings":";;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,UAAU,CAAC,KAAK,EAAoB,GAAG,IAAI,EAAwB;AACnF,EAAE,MAAM,CAAC,wBAAwB,EAAE,kBAAkB,EAAE,eAAe,CAAE,GAAE,IAAI;AAC9E,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE;AACzC,IAAI,MAAM,UAAW,GAAE,EAAE,GAAG,iBAAiB;AAC7C,IAAI,UAAU,CAAC,yBAAyB,CAAA,GAAI,wBAAwB;AACpE,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK;AACjD,MAAM,UAAU,CAAC,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAA,CAAA,GAAA,KAAA;AACA,KAAA,CAAA;AACA,IAAA,MAAA,OAAA,GAAA,MAAA,CAAA,wBAAA,EAAA,GAAA,kBAAA,CAAA;AACA,IAAA,oBAAA,CAAA,EAAA,KAAA,EAAA,OAAA,EAAA,UAAA,EAAA,CAAA;AACA,GAAA,MAAA;AACA,IAAA,oBAAA,CAAA,EAAA,KAAA,EAAA,OAAA,EAAA,wBAAA,EAAA,UAAA,EAAA,kBAAA,EAAA,CAAA;AACA;AACA;;;;"}
|
|
@@ -1,29 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { _INTERNAL_captureLog } from '@sentry/core';
|
|
1
|
+
import { captureLog } from './capture.js';
|
|
3
2
|
export { fmt } from '@sentry/core';
|
|
4
3
|
|
|
5
|
-
/**
|
|
6
|
-
* Capture a log with the given level.
|
|
7
|
-
*
|
|
8
|
-
* @param level - The level of the log.
|
|
9
|
-
* @param message - The message to log.
|
|
10
|
-
* @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100.
|
|
11
|
-
*/
|
|
12
|
-
function captureLog(level, ...args) {
|
|
13
|
-
const [messageOrMessageTemplate, paramsOrAttributes, maybeAttributes] = args;
|
|
14
|
-
if (Array.isArray(paramsOrAttributes)) {
|
|
15
|
-
const attributes = { ...maybeAttributes };
|
|
16
|
-
attributes['sentry.message.template'] = messageOrMessageTemplate;
|
|
17
|
-
paramsOrAttributes.forEach((param, index) => {
|
|
18
|
-
attributes[`sentry.message.param.${index}`] = param;
|
|
19
|
-
});
|
|
20
|
-
const message = format(messageOrMessageTemplate, ...paramsOrAttributes);
|
|
21
|
-
_INTERNAL_captureLog({ level, message, attributes });
|
|
22
|
-
} else {
|
|
23
|
-
_INTERNAL_captureLog({ level, message: messageOrMessageTemplate, attributes: paramsOrAttributes });
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
4
|
/**
|
|
28
5
|
* @summary Capture a log with the `trace` level. Requires `_experiments.enableLogs` to be enabled.
|
|
29
6
|
*
|
|
@@ -190,4 +167,4 @@ function fatal(...args) {
|
|
|
190
167
|
}
|
|
191
168
|
|
|
192
169
|
export { debug, error, fatal, info, trace, warn };
|
|
193
|
-
//# sourceMappingURL=
|
|
170
|
+
//# sourceMappingURL=exports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exports.js","sources":["../../../src/logs/exports.ts"],"sourcesContent":["import { captureLog, type CaptureLogArgs } from './capture';\n\n/**\n * @summary Capture a log with the `trace` level. Requires `_experiments.enableLogs` to be enabled.\n *\n * You can either pass a message and attributes or a message template, params and attributes.\n *\n * @example\n *\n * ```\n * Sentry.logger.trace('Starting database connection', {\n * database: 'users',\n * connectionId: 'conn_123'\n * });\n * ```\n *\n * @example With template strings\n *\n * ```\n * Sentry.logger.trace('Database connection %s established for %s',\n * ['successful', 'users'],\n * { connectionId: 'conn_123' }\n * );\n * ```\n */\nexport function trace(...args: CaptureLogArgs): void {\n captureLog('trace', ...args);\n}\n\n/**\n * @summary Capture a log with the `debug` level. Requires `_experiments.enableLogs` to be enabled.\n *\n * You can either pass a message and attributes or a message template, params and attributes.\n *\n * @example\n *\n * ```\n * Sentry.logger.debug('Cache miss for user profile', {\n * userId: 'user_123',\n * cacheKey: 'profile:user_123'\n * });\n * ```\n *\n * @example With template strings\n *\n * ```\n * Sentry.logger.debug('Cache %s for %s: %s',\n * ['miss', 'user profile', 'key not found'],\n * { userId: 'user_123' }\n * );\n * ```\n */\nexport function debug(...args: CaptureLogArgs): void {\n captureLog('debug', ...args);\n}\n\n/**\n * @summary Capture a log with the `info` level. Requires `_experiments.enableLogs` to be enabled.\n *\n * You can either pass a message and attributes or a message template, params and attributes.\n *\n * @example\n *\n * ```\n * Sentry.logger.info('User profile updated', {\n * userId: 'user_123',\n * updatedFields: ['email', 'preferences']\n * });\n * ```\n *\n * @example With template strings\n *\n * ```\n * Sentry.logger.info('User %s updated their %s',\n * ['John Doe', 'profile settings'],\n * { userId: 'user_123' }\n * );\n * ```\n */\nexport function info(...args: CaptureLogArgs): void {\n captureLog('info', ...args);\n}\n\n/**\n * @summary Capture a log with the `warn` level. Requires `_experiments.enableLogs` to be enabled.\n *\n * You can either pass a message and attributes or a message template, params and attributes.\n *\n * @example\n *\n * ```\n * Sentry.logger.warn('Rate limit approaching', {\n * endpoint: '/api/users',\n * currentRate: '95/100',\n * resetTime: '2024-03-20T10:00:00Z'\n * });\n * ```\n *\n * @example With template strings\n *\n * ```\n * Sentry.logger.warn('Rate limit %s for %s: %s',\n * ['approaching', '/api/users', '95/100 requests'],\n * { resetTime: '2024-03-20T10:00:00Z' }\n * );\n * ```\n */\nexport function warn(...args: CaptureLogArgs): void {\n captureLog('warn', ...args);\n}\n\n/**\n * @summary Capture a log with the `error` level. Requires `_experiments.enableLogs` to be enabled.\n *\n * You can either pass a message and attributes or a message template, params and attributes.\n *\n * @example\n *\n * ```\n * Sentry.logger.error('Failed to process payment', {\n * orderId: 'order_123',\n * errorCode: 'PAYMENT_FAILED',\n * amount: 99.99\n * });\n * ```\n *\n * @example With template strings\n *\n * ```\n * Sentry.logger.error('Payment processing failed for order %s: %s',\n * ['order_123', 'insufficient funds'],\n * { amount: 99.99 }\n * );\n * ```\n */\nexport function error(...args: CaptureLogArgs): void {\n captureLog('error', ...args);\n}\n\n/**\n * @summary Capture a log with the `fatal` level. Requires `_experiments.enableLogs` to be enabled.\n *\n * You can either pass a message and attributes or a message template, params and attributes.\n *\n * @example\n *\n * ```\n * Sentry.logger.fatal('Database connection pool exhausted', {\n * database: 'users',\n * activeConnections: 100,\n * maxConnections: 100\n * });\n * ```\n *\n * @example With template strings\n *\n * ```\n * Sentry.logger.fatal('Database %s: %s connections active',\n * ['connection pool exhausted', '100/100'],\n * { database: 'users' }\n * );\n * ```\n */\nexport function fatal(...args: CaptureLogArgs): void {\n captureLog('fatal', ...args);\n}\n\nexport { fmt } from '@sentry/core';\n"],"names":[],"mappings":";;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,KAAK,CAAC,GAAG,IAAI,EAAwB;AACrD,EAAE,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;AAC9B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,KAAK,CAAC,GAAG,IAAI,EAAwB;AACrD,EAAE,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;AAC9B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,IAAI,CAAC,GAAG,IAAI,EAAwB;AACpD,EAAE,UAAU,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC;AAC7B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,IAAI,CAAC,GAAG,IAAI,EAAwB;AACpD,EAAE,UAAU,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC;AAC7B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,KAAK,CAAC,GAAG,IAAI,EAAwB;AACrD,EAAE,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;AAC9B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,KAAK,CAAC,GAAG,IAAI,EAAwB;AACrD,EAAE,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;AAC9B;;;;"}
|