@sentry/node-core
Advanced tools
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const diagch = require('diagnostics_channel'); | ||
| const url = require('url'); | ||
| const core = require('@sentry/core'); | ||
| const outgoingFetchRequest = require('../../utils/outgoingFetchRequest.js'); | ||
| const attributes = require('@sentry/conventions/attributes'); | ||
| const debugBuild = require('../../debug-build.js'); | ||
| const ATTR_HTTP_REQUEST_METHOD_ORIGINAL = "http.request.method_original"; | ||
| const _channelSubs = []; | ||
| const spanFromReq = /* @__PURE__ */ new WeakMap(); | ||
| const ignoreRequestMap = /* @__PURE__ */ new WeakMap(); | ||
| const propagationDecisionMap = new core.LRUMap(100); | ||
| function instrumentUndici(config = {}) { | ||
| if (_channelSubs.length) { | ||
| return; | ||
| } | ||
| subscribeToChannel("undici:request:create", (message) => onRequestCreated(config, message)); | ||
| subscribeToChannel( | ||
| "undici:client:sendHeaders", | ||
| (message) => onRequestHeaders(config, message) | ||
| ); | ||
| subscribeToChannel("undici:request:headers", (message) => onResponseHeaders(config, message)); | ||
| subscribeToChannel("undici:request:trailers", (message) => onDone(message)); | ||
| subscribeToChannel("undici:request:error", (message) => onError(message)); | ||
| } | ||
| function safeExecute(fn, onError2) { | ||
| try { | ||
| return fn(); | ||
| } catch (error) { | ||
| onError2(error); | ||
| return void 0; | ||
| } | ||
| } | ||
| function subscribeToChannel(diagnosticChannel, onMessage) { | ||
| const [major = 0, minor = 0] = process.version.replace("v", "").split(".").map((n) => Number(n)); | ||
| const useNewSubscribe = major > 18 || major === 18 && minor >= 19; | ||
| if (useNewSubscribe) { | ||
| _channelSubs.push(diagch.subscribe?.(diagnosticChannel, onMessage)); | ||
| } else { | ||
| _channelSubs.push(diagch.channel(diagnosticChannel).subscribe(onMessage)); | ||
| } | ||
| } | ||
| function parseRequestHeaders(request) { | ||
| const result = /* @__PURE__ */ new Map(); | ||
| if (Array.isArray(request.headers)) { | ||
| for (let i = 0; i < request.headers.length; i += 2) { | ||
| const key = request.headers[i]; | ||
| const value = request.headers[i + 1]; | ||
| if (typeof key === "string" && value !== void 0) { | ||
| result.set(key.toLowerCase(), value); | ||
| } | ||
| } | ||
| } else if (typeof request.headers === "string") { | ||
| const headers = request.headers.split("\r\n"); | ||
| for (const line of headers) { | ||
| if (!line) { | ||
| continue; | ||
| } | ||
| const colonIndex = line.indexOf(":"); | ||
| if (colonIndex === -1) { | ||
| continue; | ||
| } | ||
| const key = line.substring(0, colonIndex).toLowerCase(); | ||
| const value = line.substring(colonIndex + 1).trim(); | ||
| const allValues = result.get(key); | ||
| if (allValues && Array.isArray(allValues)) { | ||
| allValues.push(value); | ||
| } else if (allValues) { | ||
| result.set(key, [allValues, value]); | ||
| } else { | ||
| result.set(key, value); | ||
| } | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| function onRequestCreated(config, { request }) { | ||
| const url$1 = getAbsoluteUrl(request.origin, request.path); | ||
| const ignoredByCallback = safeExecute( | ||
| () => !!config.ignoreOutgoingRequests?.(url$1), | ||
| (e) => e && debugBuild.DEBUG_BUILD && core.debug.error("caught ignoreOutgoingRequests error: ", e) | ||
| ); | ||
| const ignoreForBreadcrumbs = core.isTracingSuppressed() || !!ignoredByCallback; | ||
| ignoreRequestMap.set(request, ignoreForBreadcrumbs); | ||
| if (!config.spans) { | ||
| if (config.tracePropagation !== false && !ignoreForBreadcrumbs) { | ||
| outgoingFetchRequest.addTracePropagationHeadersToFetchRequest(request, propagationDecisionMap); | ||
| } | ||
| return; | ||
| } | ||
| if (request.method === "CONNECT" || ignoredByCallback) { | ||
| return; | ||
| } | ||
| let requestUrl; | ||
| try { | ||
| requestUrl = new url.URL(request.path, request.origin); | ||
| } catch (err) { | ||
| debugBuild.DEBUG_BUILD && core.debug.warn("could not determine url.full:", err); | ||
| return; | ||
| } | ||
| const urlScheme = requestUrl.protocol.replace(":", ""); | ||
| const requestMethod = getRequestMethod(request.method); | ||
| const attributes$1 = { | ||
| [attributes.HTTP_REQUEST_METHOD]: requestMethod, | ||
| [ATTR_HTTP_REQUEST_METHOD_ORIGINAL]: request.method, | ||
| [attributes.URL_FULL]: requestUrl.toString(), | ||
| [attributes.URL_PATH]: requestUrl.pathname, | ||
| [attributes.URL_QUERY]: requestUrl.search, | ||
| [attributes.URL_SCHEME]: urlScheme, | ||
| [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.otel.node_fetch" | ||
| }; | ||
| if (url$1.startsWith("data:")) { | ||
| const sanitizedUrl = core.stripDataUrlContent(url$1); | ||
| attributes$1["http.url"] = sanitizedUrl; | ||
| attributes$1[attributes.URL_FULL] = sanitizedUrl; | ||
| attributes$1[core.SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME] = `${request.method || "GET"} ${sanitizedUrl}`; | ||
| } | ||
| const schemePorts = { https: "443", http: "80" }; | ||
| const serverAddress = requestUrl.hostname; | ||
| const serverPort = requestUrl.port || schemePorts[urlScheme]; | ||
| attributes$1[attributes.SERVER_ADDRESS] = serverAddress; | ||
| if (serverPort && !isNaN(Number(serverPort))) { | ||
| attributes$1[attributes.SERVER_PORT] = Number(serverPort); | ||
| } | ||
| const headersMap = parseRequestHeaders(request); | ||
| const userAgentValues = headersMap.get("user-agent"); | ||
| if (userAgentValues) { | ||
| const userAgent = Array.isArray(userAgentValues) ? userAgentValues[userAgentValues.length - 1] : userAgentValues; | ||
| attributes$1[attributes.USER_AGENT_ORIGINAL] = userAgent; | ||
| } | ||
| const client = core.getClient(); | ||
| const span = core.startInactiveSpan({ | ||
| name: requestMethod === "_OTHER" ? "HTTP" : requestMethod, | ||
| kind: core.SPAN_KIND.CLIENT, | ||
| attributes: attributes$1, | ||
| onlyIfParent: !client || !core.hasSpanStreamingEnabled(client) | ||
| }); | ||
| safeExecute( | ||
| () => config.requestHook?.(span, request), | ||
| (e) => e && debugBuild.DEBUG_BUILD && core.debug.error("caught requestHook error: ", e) | ||
| ); | ||
| outgoingFetchRequest.addTracePropagationHeadersToFetchRequest(request, propagationDecisionMap, span); | ||
| spanFromReq.set(request, span); | ||
| } | ||
| function onRequestHeaders(config, { request, socket }) { | ||
| const span = spanFromReq.get(request); | ||
| if (!span) { | ||
| return; | ||
| } | ||
| const { remoteAddress, remotePort } = socket; | ||
| const spanAttributes = { | ||
| [attributes.NETWORK_PEER_ADDRESS]: remoteAddress, | ||
| [attributes.NETWORK_PEER_PORT]: remotePort | ||
| }; | ||
| if (config.headersToSpanAttributes?.requestHeaders) { | ||
| const headersToAttribs = new Set(config.headersToSpanAttributes.requestHeaders.map((n) => n.toLowerCase())); | ||
| const headersMap = parseRequestHeaders(request); | ||
| for (const [name, value] of headersMap.entries()) { | ||
| if (headersToAttribs.has(name)) { | ||
| const attrValue = Array.isArray(value) ? value : [value]; | ||
| spanAttributes[`http.request.header.${name}`] = attrValue; | ||
| } | ||
| } | ||
| } | ||
| span.setAttributes(spanAttributes); | ||
| } | ||
| function onResponseHeaders(config, { request, response }) { | ||
| const breadcrumbsEnabled = config.breadcrumbs !== false; | ||
| if (breadcrumbsEnabled && !ignoreRequestMap.get(request)) { | ||
| outgoingFetchRequest.addFetchRequestBreadcrumb(request, response); | ||
| } | ||
| const span = spanFromReq.get(request); | ||
| if (!span) { | ||
| return; | ||
| } | ||
| const spanAttributes = { | ||
| [attributes.HTTP_RESPONSE_STATUS_CODE]: response.statusCode | ||
| }; | ||
| safeExecute( | ||
| () => config.responseHook?.(span, { request, response }), | ||
| (e) => e && debugBuild.DEBUG_BUILD && core.debug.error("caught responseHook error: ", e) | ||
| ); | ||
| if (config.headersToSpanAttributes?.responseHeaders) { | ||
| const headersToAttribs = /* @__PURE__ */ new Set(); | ||
| config.headersToSpanAttributes?.responseHeaders.forEach((name) => headersToAttribs.add(name.toLowerCase())); | ||
| for (let idx = 0; idx < response.headers.length; idx = idx + 2) { | ||
| const nameBuf = response.headers[idx]; | ||
| const valueBuf = response.headers[idx + 1]; | ||
| if (nameBuf === void 0 || valueBuf === void 0) { | ||
| continue; | ||
| } | ||
| const name = nameBuf.toString().toLowerCase(); | ||
| const value = valueBuf; | ||
| if (headersToAttribs.has(name)) { | ||
| const attrName = `http.response.header.${name}`; | ||
| if (!Object.prototype.hasOwnProperty.call(spanAttributes, attrName)) { | ||
| spanAttributes[attrName] = [value.toString()]; | ||
| } else { | ||
| spanAttributes[attrName].push(value.toString()); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| span.setAttributes(spanAttributes); | ||
| if (response.statusCode >= 400) { | ||
| span.setStatus(core.getSpanStatusFromHttpCode(response.statusCode)); | ||
| } | ||
| } | ||
| function onDone({ request }) { | ||
| const span = spanFromReq.get(request); | ||
| if (!span) { | ||
| return; | ||
| } | ||
| span.end(); | ||
| spanFromReq.delete(request); | ||
| } | ||
| function onError({ request, error }) { | ||
| const span = spanFromReq.get(request); | ||
| if (!span) { | ||
| return; | ||
| } | ||
| span.setStatus({ | ||
| code: core.SPAN_STATUS_ERROR, | ||
| message: error.message | ||
| }); | ||
| span.end(); | ||
| spanFromReq.delete(request); | ||
| } | ||
| function getRequestMethod(original) { | ||
| const knownMethods = { | ||
| CONNECT: true, | ||
| OPTIONS: true, | ||
| HEAD: true, | ||
| GET: true, | ||
| POST: true, | ||
| PUT: true, | ||
| PATCH: true, | ||
| DELETE: true, | ||
| TRACE: true, | ||
| // QUERY from https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/ | ||
| QUERY: true | ||
| }; | ||
| if (original.toUpperCase() in knownMethods) { | ||
| return original.toUpperCase(); | ||
| } | ||
| return "_OTHER"; | ||
| } | ||
| function getAbsoluteUrl(origin, path = "/") { | ||
| const url = `${origin}`; | ||
| if (url.endsWith("/") && path.startsWith("/")) { | ||
| return `${url}${path.slice(1)}`; | ||
| } | ||
| if (!url.endsWith("/") && !path.startsWith("/")) { | ||
| return `${url}/${path}`; | ||
| } | ||
| return `${url}${path}`; | ||
| } | ||
| exports.instrumentUndici = instrumentUndici; | ||
| //# sourceMappingURL=undici-instrumentation.js.map |
| {"version":3,"file":"undici-instrumentation.js","sources":["../../../../src/integrations/node-fetch/undici-instrumentation.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/ed97091c9890dd18e52759f2ea98e9d7593b3ae4/packages/instrumentation-undici\n * - Upstream version: @opentelemetry/instrumentation-undici@0.24.0\n * - Tracking issue: https://github.com/getsentry/sentry-javascript/issues/20165\n * - Refactored to use Sentry's span APIs instead of OpenTelemetry tracing APIs\n * - Dropped the OTel metrics (no MeterProvider is wired up) and the dead\n * `requireParentforSpans` code path (the SDK always passes `false`)\n * - Dropped the `@opentelemetry/instrumentation` base (undici reports via `diagnostics_channel`,\n * so no module patching was needed) — exposed as a plain `instrumentUndici()` function that the\n * integration wires up directly\n */\n\n/* eslint-disable max-lines */\n\nimport * as diagch from 'diagnostics_channel';\nimport { URL } from 'url';\n\nimport type { Span, SpanAttributes } from '@sentry/core';\nimport {\n debug,\n getClient,\n getSpanStatusFromHttpCode,\n hasSpanStreamingEnabled,\n isTracingSuppressed,\n LRUMap,\n SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_KIND,\n SPAN_STATUS_ERROR,\n startInactiveSpan,\n stripDataUrlContent,\n} from '@sentry/core';\nimport { addFetchRequestBreadcrumb, addTracePropagationHeadersToFetchRequest } from '../../utils/outgoingFetchRequest';\nimport {\n HTTP_REQUEST_METHOD,\n HTTP_RESPONSE_STATUS_CODE,\n NETWORK_PEER_ADDRESS,\n NETWORK_PEER_PORT,\n SERVER_ADDRESS,\n SERVER_PORT,\n URL_FULL,\n URL_PATH,\n URL_QUERY,\n URL_SCHEME,\n USER_AGENT_ORIGINAL,\n} from '@sentry/conventions/attributes';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport type {\n NodeFetchOptions,\n UndiciRequest,\n RequestErrorMessage,\n RequestHeadersMessage,\n RequestMessage,\n RequestTrailersMessage,\n ResponseHeadersMessage,\n} from './types';\n\n// `http.request.method_original` is not part of `@sentry/conventions`, so we keep it inline.\nconst ATTR_HTTP_REQUEST_METHOD_ORIGINAL = 'http.request.method_original';\n\n// Keep ref to avoid https://github.com/nodejs/node/issues/42170 bug\n// We can replace this with _isInstrumented once we drop support for Node.js 18.18.0\nconst _channelSubs: Array<unknown> = [];\nconst spanFromReq = new WeakMap<UndiciRequest, Span>();\n// Whether breadcrumbs (and span-less trace propagation) should be skipped for a given request.\n// We evaluate this at request-creation time because the active context is no longer correct by the\n// time the response-headers event fires.\nconst ignoreRequestMap = new WeakMap<UndiciRequest, boolean>();\n// Caches trace-propagation decisions per URL so we don't recompute the `tracePropagationTargets` regexes per request.\nconst propagationDecisionMap = new LRUMap<string, boolean>(100);\n\n/**\n * Instrument outgoing HTTP requests made through `undici` or the global `fetch` API: emit `http.client`\n * spans, record breadcrumbs, and propagate traces into the outgoing request headers.\n *\n * Span creation is gated by the `spans` option (defaults to `true`). When spans are disabled, breadcrumbs\n * are still recorded and trace propagation headers are still injected (gated by `tracePropagation`).\n *\n * undici reports its request lifecycle via `diagnostics_channel`, so rather than patching any module we\n * subscribe to those channels directly. This is idempotent — subsequent calls are no-ops once the\n * channels have been subscribed to, and the config of the first call wins.\n *\n * A combination of https://github.com/elastic/apm-agent-nodejs and\n * https://github.com/gadget-inc/opentelemetry-instrumentations/blob/main/packages/opentelemetry-instrumentation-undici/src/index.ts\n */\nexport function instrumentUndici(config: NodeFetchOptions = {}): void {\n // Avoid duplicate subscriptions\n if (_channelSubs.length) {\n return;\n }\n\n subscribeToChannel('undici:request:create', message => onRequestCreated(config, message as RequestMessage));\n subscribeToChannel('undici:client:sendHeaders', message =>\n onRequestHeaders(config, message as RequestHeadersMessage),\n );\n subscribeToChannel('undici:request:headers', message => onResponseHeaders(config, message as ResponseHeadersMessage));\n subscribeToChannel('undici:request:trailers', message => onDone(message as RequestTrailersMessage));\n subscribeToChannel('undici:request:error', message => onError(message as RequestErrorMessage));\n}\n\n/** Replaces OTel's `safeExecuteInTheMiddle`: run `fn`, route any error to `onError`, and swallow it. */\nfunction safeExecute<T>(fn: () => T, onError: (error: unknown) => void): T | undefined {\n try {\n return fn();\n } catch (error) {\n onError(error);\n return undefined;\n }\n}\n\nfunction subscribeToChannel(\n diagnosticChannel: string,\n onMessage: (message: unknown, name: string | symbol) => void,\n): void {\n // `diagnostics_channel` had a ref counting bug until v18.19.0.\n // https://github.com/nodejs/node/pull/47520\n const [major = 0, minor = 0] = process.version\n .replace('v', '')\n .split('.')\n .map(n => Number(n));\n const useNewSubscribe = major > 18 || (major === 18 && minor >= 19);\n\n if (useNewSubscribe) {\n _channelSubs.push(diagch.subscribe?.(diagnosticChannel, onMessage));\n } else {\n _channelSubs.push(diagch.channel(diagnosticChannel).subscribe(onMessage));\n }\n}\n\nfunction parseRequestHeaders(request: UndiciRequest): Map<string, string | string[]> {\n const result = new Map<string, string | string[]>();\n\n if (Array.isArray(request.headers)) {\n // headers are an array [k1, v2, k2, v2] (undici v6+)\n // values could be string or a string[] for multiple values\n for (let i = 0; i < request.headers.length; i += 2) {\n const key = request.headers[i];\n const value = request.headers[i + 1];\n\n // Key should always be a string, but the types don't know that, and let's be safe\n if (typeof key === 'string' && value !== undefined) {\n result.set(key.toLowerCase(), value);\n }\n }\n } else if (typeof request.headers === 'string') {\n // headers are a raw string (undici v5)\n // headers could be repeated in several lines for multiple values\n const headers = request.headers.split('\\r\\n');\n for (const line of headers) {\n if (!line) {\n continue;\n }\n const colonIndex = line.indexOf(':');\n if (colonIndex === -1) {\n // Invalid header? Probably this can't happen, but again let's be safe.\n continue;\n }\n const key = line.substring(0, colonIndex).toLowerCase();\n const value = line.substring(colonIndex + 1).trim();\n const allValues = result.get(key);\n\n if (allValues && Array.isArray(allValues)) {\n allValues.push(value);\n } else if (allValues) {\n result.set(key, [allValues, value]);\n } else {\n result.set(key, value);\n }\n }\n }\n return result;\n}\n\n// This is the 1st message we receive for each request (fired after request creation). Here we will\n// create the span and populate some atttributes, then link the span to the request for further\n// span processing\nfunction onRequestCreated(config: NodeFetchOptions, { request }: RequestMessage): void {\n const url = getAbsoluteUrl(request.origin, request.path);\n\n const ignoredByCallback = safeExecute(\n () => !!config.ignoreOutgoingRequests?.(url),\n e => e && DEBUG_BUILD && debug.error('caught ignoreOutgoingRequests error: ', e),\n );\n\n // Breadcrumbs & span-less trace propagation are additionally skipped when tracing is suppressed.\n // We store this here because the active context is no longer correct in later channel events.\n const ignoreForBreadcrumbs = isTracingSuppressed() || !!ignoredByCallback;\n ignoreRequestMap.set(request, ignoreForBreadcrumbs);\n\n // When spans are disabled we do not create a span, but we still inject trace propagation headers\n // directly (unless disabled via `tracePropagation`).\n if (!config.spans) {\n if (config.tracePropagation !== false && !ignoreForBreadcrumbs) {\n addTracePropagationHeadersToFetchRequest(request, propagationDecisionMap);\n }\n return;\n }\n\n // Ignore span creation if:\n // - the outgoing request is ignored via config\n // - method is 'CONNECT'\n if (request.method === 'CONNECT' || ignoredByCallback) {\n return;\n }\n\n let requestUrl;\n try {\n requestUrl = new URL(request.path, request.origin);\n } catch (err) {\n DEBUG_BUILD && debug.warn('could not determine url.full:', err);\n // Skip instrumenting this request.\n return;\n }\n const urlScheme = requestUrl.protocol.replace(':', '');\n const requestMethod = getRequestMethod(request.method);\n const attributes: SpanAttributes = {\n [HTTP_REQUEST_METHOD]: requestMethod,\n [ATTR_HTTP_REQUEST_METHOD_ORIGINAL]: request.method,\n [URL_FULL]: requestUrl.toString(),\n [URL_PATH]: requestUrl.pathname,\n [URL_QUERY]: requestUrl.search,\n [URL_SCHEME]: urlScheme,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.node_fetch',\n };\n\n // Sanitize data URLs to prevent long base64 strings in span attributes\n if (url.startsWith('data:')) {\n const sanitizedUrl = stripDataUrlContent(url);\n attributes['http.url'] = sanitizedUrl;\n attributes[URL_FULL] = sanitizedUrl;\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME] = `${request.method || 'GET'} ${sanitizedUrl}`;\n }\n\n const schemePorts: Record<string, string> = { https: '443', http: '80' };\n const serverAddress = requestUrl.hostname;\n const serverPort = requestUrl.port || schemePorts[urlScheme];\n\n attributes[SERVER_ADDRESS] = serverAddress;\n if (serverPort && !isNaN(Number(serverPort))) {\n attributes[SERVER_PORT] = Number(serverPort);\n }\n\n // Get user agent from headers\n const headersMap = parseRequestHeaders(request);\n const userAgentValues = headersMap.get('user-agent');\n\n if (userAgentValues) {\n // NOTE: having multiple user agents is not expected so\n // we're going to take last one like `curl` does\n // ref: https://curl.se/docs/manpage.html#-A\n const userAgent = Array.isArray(userAgentValues) ? userAgentValues[userAgentValues.length - 1] : userAgentValues;\n attributes[USER_AGENT_ORIGINAL] = userAgent;\n }\n\n // Outside of span streaming, only record an `http.client` span when it has a parent. An orphan\n // one (no local parent) is left to the server for the downstream sampling decision: `onlyIfParent`\n // still creates a non-recording span so trace propagation headers are injected, but it isn't\n // emitted as a standalone transaction. This rule also lives in `SentrySampler`, but that only runs\n // when an OpenTelemetry SDK tracer provider is set up, so we enforce it here too, which covers\n // SDKs that don't use an OpenTelemetry tracer provider at all.\n const client = getClient();\n const span = startInactiveSpan({\n name: requestMethod === '_OTHER' ? 'HTTP' : requestMethod,\n kind: SPAN_KIND.CLIENT,\n attributes,\n onlyIfParent: !client || !hasSpanStreamingEnabled(client),\n });\n\n // Execute the request hook if defined\n safeExecute(\n () => config.requestHook?.(span, request),\n e => e && DEBUG_BUILD && debug.error('caught requestHook error: ', e),\n );\n\n // Context propagation goes last so no hook can tamper the propagation headers.\n // We propagate the trace data of the freshly created client span (not the active parent span)\n // so downstream services are parented to the http.client span, matching the upstream behavior.\n // This also de-duplicates against any trace headers the user set manually (e.g. via `getTraceData()`).\n addTracePropagationHeadersToFetchRequest(request, propagationDecisionMap, span);\n\n spanFromReq.set(request, span);\n}\n\n// This is the 2nd message we receive for each request. It is fired when connection with\n// the remote is established and about to send the first byte. Here we do have info about the\n// remote address and port so we can populate some `network.*` attributes into the span\nfunction onRequestHeaders(config: NodeFetchOptions, { request, socket }: RequestHeadersMessage): void {\n const span = spanFromReq.get(request);\n\n if (!span) {\n return;\n }\n\n const { remoteAddress, remotePort } = socket;\n const spanAttributes: SpanAttributes = {\n [NETWORK_PEER_ADDRESS]: remoteAddress,\n [NETWORK_PEER_PORT]: remotePort,\n };\n\n // After hooks have been processed (which may modify request headers)\n // we can collect the headers based on the configuration\n if (config.headersToSpanAttributes?.requestHeaders) {\n const headersToAttribs = new Set(config.headersToSpanAttributes.requestHeaders.map(n => n.toLowerCase()));\n const headersMap = parseRequestHeaders(request);\n\n for (const [name, value] of headersMap.entries()) {\n if (headersToAttribs.has(name)) {\n const attrValue = Array.isArray(value) ? value : [value];\n spanAttributes[`http.request.header.${name}`] = attrValue;\n }\n }\n }\n\n span.setAttributes(spanAttributes);\n}\n\n// This is the 3rd message we get for each request and it's fired when the server\n// headers are received, body may not be accessible yet.\n// From the response headers we can set the status and content length\nfunction onResponseHeaders(config: NodeFetchOptions, { request, response }: ResponseHeadersMessage): void {\n // Breadcrumbs are recorded independently of spans, so this runs even when span creation is disabled.\n const breadcrumbsEnabled = config.breadcrumbs !== false;\n if (breadcrumbsEnabled && !ignoreRequestMap.get(request)) {\n addFetchRequestBreadcrumb(request, response);\n }\n\n const span = spanFromReq.get(request);\n\n if (!span) {\n return;\n }\n\n const spanAttributes: SpanAttributes = {\n [HTTP_RESPONSE_STATUS_CODE]: response.statusCode,\n };\n\n // Execute the response hook if defined\n safeExecute(\n () => config.responseHook?.(span, { request, response }),\n e => e && DEBUG_BUILD && debug.error('caught responseHook error: ', e),\n );\n\n if (config.headersToSpanAttributes?.responseHeaders) {\n const headersToAttribs = new Set<string>();\n config.headersToSpanAttributes?.responseHeaders.forEach(name => headersToAttribs.add(name.toLowerCase()));\n\n for (let idx = 0; idx < response.headers.length; idx = idx + 2) {\n const nameBuf = response.headers[idx];\n const valueBuf = response.headers[idx + 1];\n if (nameBuf === undefined || valueBuf === undefined) {\n continue;\n }\n const name = nameBuf.toString().toLowerCase();\n const value = valueBuf;\n\n if (headersToAttribs.has(name)) {\n const attrName = `http.response.header.${name}`;\n if (!Object.prototype.hasOwnProperty.call(spanAttributes, attrName)) {\n spanAttributes[attrName] = [value.toString()];\n } else {\n (spanAttributes[attrName] as string[]).push(value.toString());\n }\n }\n }\n }\n\n span.setAttributes(spanAttributes);\n\n // Resolve the HTTP status code to a Sentry span status here (like the raw http client/server\n // instrumentation does) instead of setting a bare error and deferring to downstream inference.\n // The SentryTracerProvider's status finalization reads the already-stringified span status, which\n // can no longer be inferred back to `not_found` etc. the way the OpenTelemetry SDK exporter's\n // `mapStatus` does from the raw `{ code, message }`.\n if (response.statusCode >= 400) {\n span.setStatus(getSpanStatusFromHttpCode(response.statusCode));\n }\n}\n\n// This is the last event we receive if the request went without any errors\nfunction onDone({ request }: RequestTrailersMessage): void {\n const span = spanFromReq.get(request);\n\n if (!span) {\n return;\n }\n\n span.end();\n spanFromReq.delete(request);\n}\n\n// This is the event we get when something is wrong in the request like\n// - invalid options when calling `fetch` global API or any undici method for request\n// - connectivity errors such as unreachable host\n// - requests aborted through an `AbortController.signal`\n// NOTE: server errors are considered valid responses and it's the lib consumer\n// who should deal with that.\nfunction onError({ request, error }: RequestErrorMessage): void {\n const span = spanFromReq.get(request);\n\n if (!span) {\n return;\n }\n\n // NOTE: in `undici@6.3.0` when request aborted the error type changes from\n // a custom error (`RequestAbortedError`) to a built-in `DOMException` carrying\n // some differences:\n // - `code` is from DOMEXception (ABORT_ERR: 20)\n // - `message` changes\n // - stacktrace is smaller and contains node internal frames\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: error.message,\n });\n span.end();\n spanFromReq.delete(request);\n}\n\nfunction getRequestMethod(original: string): string {\n const knownMethods = {\n CONNECT: true,\n OPTIONS: true,\n HEAD: true,\n GET: true,\n POST: true,\n PUT: true,\n PATCH: true,\n DELETE: true,\n TRACE: true,\n // QUERY from https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/\n QUERY: true,\n };\n\n if (original.toUpperCase() in knownMethods) {\n return original.toUpperCase();\n }\n\n return '_OTHER';\n}\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}`;\n }\n\n return `${url}${path}`;\n}\n"],"names":["LRUMap","onError","url","DEBUG_BUILD","debug","isTracingSuppressed","addTracePropagationHeadersToFetchRequest","URL","attributes","HTTP_REQUEST_METHOD","URL_FULL","URL_PATH","URL_QUERY","URL_SCHEME","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","stripDataUrlContent","SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME","SERVER_ADDRESS","SERVER_PORT","USER_AGENT_ORIGINAL","getClient","startInactiveSpan","SPAN_KIND","hasSpanStreamingEnabled","NETWORK_PEER_ADDRESS","NETWORK_PEER_PORT","addFetchRequestBreadcrumb","HTTP_RESPONSE_STATUS_CODE","getSpanStatusFromHttpCode","SPAN_STATUS_ERROR"],"mappings":";;;;;;;;;AA8DA,MAAM,iCAAA,GAAoC,8BAAA;AAI1C,MAAM,eAA+B,EAAC;AACtC,MAAM,WAAA,uBAAkB,OAAA,EAA6B;AAIrD,MAAM,gBAAA,uBAAuB,OAAA,EAAgC;AAE7D,MAAM,sBAAA,GAAyB,IAAIA,WAAA,CAAwB,GAAG,CAAA;AAgBvD,SAAS,gBAAA,CAAiB,MAAA,GAA2B,EAAC,EAAS;AAEpE,EAAA,IAAI,aAAa,MAAA,EAAQ;AACvB,IAAA;AAAA,EACF;AAEA,EAAA,kBAAA,CAAmB,uBAAA,EAAyB,CAAA,OAAA,KAAW,gBAAA,CAAiB,MAAA,EAAQ,OAAyB,CAAC,CAAA;AAC1G,EAAA,kBAAA;AAAA,IAAmB,2BAAA;AAAA,IAA6B,CAAA,OAAA,KAC9C,gBAAA,CAAiB,MAAA,EAAQ,OAAgC;AAAA,GAC3D;AACA,EAAA,kBAAA,CAAmB,wBAAA,EAA0B,CAAA,OAAA,KAAW,iBAAA,CAAkB,MAAA,EAAQ,OAAiC,CAAC,CAAA;AACpH,EAAA,kBAAA,CAAmB,yBAAA,EAA2B,CAAA,OAAA,KAAW,MAAA,CAAO,OAAiC,CAAC,CAAA;AAClG,EAAA,kBAAA,CAAmB,sBAAA,EAAwB,CAAA,OAAA,KAAW,OAAA,CAAQ,OAA8B,CAAC,CAAA;AAC/F;AAGA,SAAS,WAAA,CAAe,IAAaC,QAAAA,EAAkD;AACrF,EAAA,IAAI;AACF,IAAA,OAAO,EAAA,EAAG;AAAA,EACZ,SAAS,KAAA,EAAO;AACd,IAAAA,SAAQ,KAAK,CAAA;AACb,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEA,SAAS,kBAAA,CACP,mBACA,SAAA,EACM;AAGN,EAAA,MAAM,CAAC,KAAA,GAAQ,CAAA,EAAG,QAAQ,CAAC,CAAA,GAAI,QAAQ,OAAA,CACpC,OAAA,CAAQ,KAAK,EAAE,CAAA,CACf,MAAM,GAAG,CAAA,CACT,IAAI,CAAA,CAAA,KAAK,MAAA,CAAO,CAAC,CAAC,CAAA;AACrB,EAAA,MAAM,eAAA,GAAkB,KAAA,GAAQ,EAAA,IAAO,KAAA,KAAU,MAAM,KAAA,IAAS,EAAA;AAEhE,EAAA,IAAI,eAAA,EAAiB;AACnB,IAAA,YAAA,CAAa,IAAA,CAAK,MAAA,CAAO,SAAA,GAAY,iBAAA,EAAmB,SAAS,CAAC,CAAA;AAAA,EACpE,CAAA,MAAO;AACL,IAAA,YAAA,CAAa,KAAK,MAAA,CAAO,OAAA,CAAQ,iBAAiB,CAAA,CAAE,SAAA,CAAU,SAAS,CAAC,CAAA;AAAA,EAC1E;AACF;AAEA,SAAS,oBAAoB,OAAA,EAAwD;AACnF,EAAA,MAAM,MAAA,uBAAa,GAAA,EAA+B;AAElD,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ,OAAO,CAAA,EAAG;AAGlC,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,QAAQ,OAAA,CAAQ,MAAA,EAAQ,KAAK,CAAA,EAAG;AAClD,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAA;AAC7B,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,OAAA,CAAQ,CAAA,GAAI,CAAC,CAAA;AAGnC,MAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,KAAA,KAAU,MAAA,EAAW;AAClD,QAAA,MAAA,CAAO,GAAA,CAAI,GAAA,CAAI,WAAA,EAAY,EAAG,KAAK,CAAA;AAAA,MACrC;AAAA,IACF;AAAA,EACF,CAAA,MAAA,IAAW,OAAO,OAAA,CAAQ,OAAA,KAAY,QAAA,EAAU;AAG9C,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,KAAA,CAAM,MAAM,CAAA;AAC5C,IAAA,KAAA,MAAW,QAAQ,OAAA,EAAS;AAC1B,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA;AAAA,MACF;AACA,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AACnC,MAAA,IAAI,eAAe,EAAA,EAAI;AAErB,QAAA;AAAA,MACF;AACA,MAAA,MAAM,MAAM,IAAA,CAAK,SAAA,CAAU,CAAA,EAAG,UAAU,EAAE,WAAA,EAAY;AACtD,MAAA,MAAM,QAAQ,IAAA,CAAK,SAAA,CAAU,UAAA,GAAa,CAAC,EAAE,IAAA,EAAK;AAClD,MAAA,MAAM,SAAA,GAAY,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA;AAEhC,MAAA,IAAI,SAAA,IAAa,KAAA,CAAM,OAAA,CAAQ,SAAS,CAAA,EAAG;AACzC,QAAA,SAAA,CAAU,KAAK,KAAK,CAAA;AAAA,MACtB,WAAW,SAAA,EAAW;AACpB,QAAA,MAAA,CAAO,GAAA,CAAI,GAAA,EAAK,CAAC,SAAA,EAAW,KAAK,CAAC,CAAA;AAAA,MACpC,CAAA,MAAO;AACL,QAAA,MAAA,CAAO,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAKA,SAAS,gBAAA,CAAiB,MAAA,EAA0B,EAAE,OAAA,EAAQ,EAAyB;AACrF,EAAA,MAAMC,KAAA,GAAM,cAAA,CAAe,OAAA,CAAQ,MAAA,EAAQ,QAAQ,IAAI,CAAA;AAEvD,EAAA,MAAM,iBAAA,GAAoB,WAAA;AAAA,IACxB,MAAM,CAAC,CAAC,MAAA,CAAO,yBAAyBA,KAAG,CAAA;AAAA,IAC3C,OAAK,CAAA,IAAKC,sBAAA,IAAeC,UAAA,CAAM,KAAA,CAAM,yCAAyC,CAAC;AAAA,GACjF;AAIA,EAAA,MAAM,oBAAA,GAAuBC,wBAAA,EAAoB,IAAK,CAAC,CAAC,iBAAA;AACxD,EAAA,gBAAA,CAAiB,GAAA,CAAI,SAAS,oBAAoB,CAAA;AAIlD,EAAA,IAAI,CAAC,OAAO,KAAA,EAAO;AACjB,IAAA,IAAI,MAAA,CAAO,gBAAA,KAAqB,KAAA,IAAS,CAAC,oBAAA,EAAsB;AAC9D,MAAAC,6DAAA,CAAyC,SAAS,sBAAsB,CAAA;AAAA,IAC1E;AACA,IAAA;AAAA,EACF;AAKA,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,SAAA,IAAa,iBAAA,EAAmB;AACrD,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,UAAA;AACJ,EAAA,IAAI;AACF,IAAA,UAAA,GAAa,IAAIC,OAAA,CAAI,OAAA,CAAQ,IAAA,EAAM,QAAQ,MAAM,CAAA;AAAA,EACnD,SAAS,GAAA,EAAK;AACZ,IAAAJ,sBAAA,IAAeC,UAAA,CAAM,IAAA,CAAK,+BAAA,EAAiC,GAAG,CAAA;AAE9D,IAAA;AAAA,EACF;AACA,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,QAAA,CAAS,OAAA,CAAQ,KAAK,EAAE,CAAA;AACrD,EAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,OAAA,CAAQ,MAAM,CAAA;AACrD,EAAA,MAAMI,YAAA,GAA6B;AAAA,IACjC,CAACC,8BAAmB,GAAG,aAAA;AAAA,IACvB,CAAC,iCAAiC,GAAG,OAAA,CAAQ,MAAA;AAAA,IAC7C,CAACC,mBAAQ,GAAG,UAAA,CAAW,QAAA,EAAS;AAAA,IAChC,CAACC,mBAAQ,GAAG,UAAA,CAAW,QAAA;AAAA,IACvB,CAACC,oBAAS,GAAG,UAAA,CAAW,MAAA;AAAA,IACxB,CAACC,qBAAU,GAAG,SAAA;AAAA,IACd,CAACC,qCAAgC,GAAG;AAAA,GACtC;AAGA,EAAA,IAAIZ,KAAA,CAAI,UAAA,CAAW,OAAO,CAAA,EAAG;AAC3B,IAAA,MAAM,YAAA,GAAea,yBAAoBb,KAAG,CAAA;AAC5C,IAAAM,YAAA,CAAW,UAAU,CAAA,GAAI,YAAA;AACzB,IAAAA,YAAA,CAAWE,mBAAQ,CAAA,GAAI,YAAA;AACvB,IAAAF,YAAA,CAAWQ,+CAA0C,CAAA,GAAI,CAAA,EAAG,QAAQ,MAAA,IAAU,KAAK,IAAI,YAAY,CAAA,CAAA;AAAA,EACrG;AAEA,EAAA,MAAM,WAAA,GAAsC,EAAE,KAAA,EAAO,KAAA,EAAO,MAAM,IAAA,EAAK;AACvE,EAAA,MAAM,gBAAgB,UAAA,CAAW,QAAA;AACjC,EAAA,MAAM,UAAA,GAAa,UAAA,CAAW,IAAA,IAAQ,WAAA,CAAY,SAAS,CAAA;AAE3D,EAAAR,YAAA,CAAWS,yBAAc,CAAA,GAAI,aAAA;AAC7B,EAAA,IAAI,cAAc,CAAC,KAAA,CAAM,MAAA,CAAO,UAAU,CAAC,CAAA,EAAG;AAC5C,IAAAT,YAAA,CAAWU,sBAAW,CAAA,GAAI,MAAA,CAAO,UAAU,CAAA;AAAA,EAC7C;AAGA,EAAA,MAAM,UAAA,GAAa,oBAAoB,OAAO,CAAA;AAC9C,EAAA,MAAM,eAAA,GAAkB,UAAA,CAAW,GAAA,CAAI,YAAY,CAAA;AAEnD,EAAA,IAAI,eAAA,EAAiB;AAInB,IAAA,MAAM,SAAA,GAAY,MAAM,OAAA,CAAQ,eAAe,IAAI,eAAA,CAAgB,eAAA,CAAgB,MAAA,GAAS,CAAC,CAAA,GAAI,eAAA;AACjG,IAAAV,YAAA,CAAWW,8BAAmB,CAAA,GAAI,SAAA;AAAA,EACpC;AAQA,EAAA,MAAM,SAASC,cAAA,EAAU;AACzB,EAAA,MAAM,OAAOC,sBAAA,CAAkB;AAAA,IAC7B,IAAA,EAAM,aAAA,KAAkB,QAAA,GAAW,MAAA,GAAS,aAAA;AAAA,IAC5C,MAAMC,cAAA,CAAU,MAAA;AAAA,gBAChBd,YAAA;AAAA,IACA,YAAA,EAAc,CAAC,MAAA,IAAU,CAACe,6BAAwB,MAAM;AAAA,GACzD,CAAA;AAGD,EAAA,WAAA;AAAA,IACE,MAAM,MAAA,CAAO,WAAA,GAAc,IAAA,EAAM,OAAO,CAAA;AAAA,IACxC,OAAK,CAAA,IAAKpB,sBAAA,IAAeC,UAAA,CAAM,KAAA,CAAM,8BAA8B,CAAC;AAAA,GACtE;AAMA,EAAAE,6DAAA,CAAyC,OAAA,EAAS,wBAAwB,IAAI,CAAA;AAE9E,EAAA,WAAA,CAAY,GAAA,CAAI,SAAS,IAAI,CAAA;AAC/B;AAKA,SAAS,gBAAA,CAAiB,MAAA,EAA0B,EAAE,OAAA,EAAS,QAAO,EAAgC;AACpG,EAAA,MAAM,IAAA,GAAO,WAAA,CAAY,GAAA,CAAI,OAAO,CAAA;AAEpC,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,aAAA,EAAe,UAAA,EAAW,GAAI,MAAA;AACtC,EAAA,MAAM,cAAA,GAAiC;AAAA,IACrC,CAACkB,+BAAoB,GAAG,aAAA;AAAA,IACxB,CAACC,4BAAiB,GAAG;AAAA,GACvB;AAIA,EAAA,IAAI,MAAA,CAAO,yBAAyB,cAAA,EAAgB;AAClD,IAAA,MAAM,gBAAA,GAAmB,IAAI,GAAA,CAAI,MAAA,CAAO,uBAAA,CAAwB,cAAA,CAAe,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,WAAA,EAAa,CAAC,CAAA;AACxG,IAAA,MAAM,UAAA,GAAa,oBAAoB,OAAO,CAAA;AAE9C,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,CAAA,IAAK,UAAA,CAAW,SAAQ,EAAG;AAChD,MAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,IAAI,CAAA,EAAG;AAC9B,QAAA,MAAM,YAAY,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,KAAA,GAAQ,CAAC,KAAK,CAAA;AACvD,QAAA,cAAA,CAAe,CAAA,oBAAA,EAAuB,IAAI,CAAA,CAAE,CAAA,GAAI,SAAA;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAA,CAAK,cAAc,cAAc,CAAA;AACnC;AAKA,SAAS,iBAAA,CAAkB,MAAA,EAA0B,EAAE,OAAA,EAAS,UAAS,EAAiC;AAExG,EAAA,MAAM,kBAAA,GAAqB,OAAO,WAAA,KAAgB,KAAA;AAClD,EAAA,IAAI,kBAAA,IAAsB,CAAC,gBAAA,CAAiB,GAAA,CAAI,OAAO,CAAA,EAAG;AACxD,IAAAC,8CAAA,CAA0B,SAAS,QAAQ,CAAA;AAAA,EAC7C;AAEA,EAAA,MAAM,IAAA,GAAO,WAAA,CAAY,GAAA,CAAI,OAAO,CAAA;AAEpC,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,cAAA,GAAiC;AAAA,IACrC,CAACC,oCAAyB,GAAG,QAAA,CAAS;AAAA,GACxC;AAGA,EAAA,WAAA;AAAA,IACE,MAAM,MAAA,CAAO,YAAA,GAAe,MAAM,EAAE,OAAA,EAAS,UAAU,CAAA;AAAA,IACvD,OAAK,CAAA,IAAKxB,sBAAA,IAAeC,UAAA,CAAM,KAAA,CAAM,+BAA+B,CAAC;AAAA,GACvE;AAEA,EAAA,IAAI,MAAA,CAAO,yBAAyB,eAAA,EAAiB;AACnD,IAAA,MAAM,gBAAA,uBAAuB,GAAA,EAAY;AACzC,IAAA,MAAA,CAAO,uBAAA,EAAyB,gBAAgB,OAAA,CAAQ,CAAA,IAAA,KAAQ,iBAAiB,GAAA,CAAI,IAAA,CAAK,WAAA,EAAa,CAAC,CAAA;AAExG,IAAA,KAAA,IAAS,GAAA,GAAM,GAAG,GAAA,GAAM,QAAA,CAAS,QAAQ,MAAA,EAAQ,GAAA,GAAM,MAAM,CAAA,EAAG;AAC9D,MAAA,MAAM,OAAA,GAAU,QAAA,CAAS,OAAA,CAAQ,GAAG,CAAA;AACpC,MAAA,MAAM,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,GAAA,GAAM,CAAC,CAAA;AACzC,MAAA,IAAI,OAAA,KAAY,MAAA,IAAa,QAAA,KAAa,MAAA,EAAW;AACnD,QAAA;AAAA,MACF;AACA,MAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,QAAA,EAAS,CAAE,WAAA,EAAY;AAC5C,MAAA,MAAM,KAAA,GAAQ,QAAA;AAEd,MAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,IAAI,CAAA,EAAG;AAC9B,QAAA,MAAM,QAAA,GAAW,wBAAwB,IAAI,CAAA,CAAA;AAC7C,QAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,eAAe,IAAA,CAAK,cAAA,EAAgB,QAAQ,CAAA,EAAG;AACnE,UAAA,cAAA,CAAe,QAAQ,CAAA,GAAI,CAAC,KAAA,CAAM,UAAU,CAAA;AAAA,QAC9C,CAAA,MAAO;AACL,UAAC,eAAe,QAAQ,CAAA,CAAe,IAAA,CAAK,KAAA,CAAM,UAAU,CAAA;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAA,CAAK,cAAc,cAAc,CAAA;AAOjC,EAAA,IAAI,QAAA,CAAS,cAAc,GAAA,EAAK;AAC9B,IAAA,IAAA,CAAK,SAAA,CAAUwB,8BAAA,CAA0B,QAAA,CAAS,UAAU,CAAC,CAAA;AAAA,EAC/D;AACF;AAGA,SAAS,MAAA,CAAO,EAAE,OAAA,EAAQ,EAAiC;AACzD,EAAA,MAAM,IAAA,GAAO,WAAA,CAAY,GAAA,CAAI,OAAO,CAAA;AAEpC,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA;AAAA,EACF;AAEA,EAAA,IAAA,CAAK,GAAA,EAAI;AACT,EAAA,WAAA,CAAY,OAAO,OAAO,CAAA;AAC5B;AAQA,SAAS,OAAA,CAAQ,EAAE,OAAA,EAAS,KAAA,EAAM,EAA8B;AAC9D,EAAA,MAAM,IAAA,GAAO,WAAA,CAAY,GAAA,CAAI,OAAO,CAAA;AAEpC,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA;AAAA,EACF;AAQA,EAAA,IAAA,CAAK,SAAA,CAAU;AAAA,IACb,IAAA,EAAMC,sBAAA;AAAA,IACN,SAAS,KAAA,CAAM;AAAA,GAChB,CAAA;AACD,EAAA,IAAA,CAAK,GAAA,EAAI;AACT,EAAA,WAAA,CAAY,OAAO,OAAO,CAAA;AAC5B;AAEA,SAAS,iBAAiB,QAAA,EAA0B;AAClD,EAAA,MAAM,YAAA,GAAe;AAAA,IACnB,OAAA,EAAS,IAAA;AAAA,IACT,OAAA,EAAS,IAAA;AAAA,IACT,IAAA,EAAM,IAAA;AAAA,IACN,GAAA,EAAK,IAAA;AAAA,IACL,IAAA,EAAM,IAAA;AAAA,IACN,GAAA,EAAK,IAAA;AAAA,IACL,KAAA,EAAO,IAAA;AAAA,IACP,MAAA,EAAQ,IAAA;AAAA,IACR,KAAA,EAAO,IAAA;AAAA;AAAA,IAEP,KAAA,EAAO;AAAA,GACT;AAEA,EAAA,IAAI,QAAA,CAAS,WAAA,EAAY,IAAK,YAAA,EAAc;AAC1C,IAAA,OAAO,SAAS,WAAA,EAAY;AAAA,EAC9B;AAEA,EAAA,OAAO,QAAA;AACT;AAGA,SAAS,cAAA,CAAe,MAAA,EAAgB,IAAA,GAAe,GAAA,EAAa;AAClE,EAAA,MAAM,GAAA,GAAM,GAAG,MAAM,CAAA,CAAA;AAErB,EAAA,IAAI,IAAI,QAAA,CAAS,GAAG,KAAK,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG;AAC7C,IAAA,OAAO,GAAG,GAAG,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AAAA,EAC/B;AAEA,EAAA,IAAI,CAAC,IAAI,QAAA,CAAS,GAAG,KAAK,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG;AAC/C,IAAA,OAAO,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAAA,EACvB;AAEA,EAAA,OAAO,CAAA,EAAG,GAAG,CAAA,EAAG,IAAI,CAAA,CAAA;AACtB;;;;"} |
| import * as diagch from 'diagnostics_channel'; | ||
| import { URL } from 'url'; | ||
| import { LRUMap, isTracingSuppressed, debug, stripDataUrlContent, SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME, getClient, startInactiveSpan, SPAN_KIND, hasSpanStreamingEnabled, getSpanStatusFromHttpCode, SPAN_STATUS_ERROR, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; | ||
| import { addTracePropagationHeadersToFetchRequest, addFetchRequestBreadcrumb } from '../../utils/outgoingFetchRequest.js'; | ||
| import { URL_QUERY, URL_PATH, URL_FULL, SERVER_ADDRESS, SERVER_PORT, USER_AGENT_ORIGINAL, HTTP_RESPONSE_STATUS_CODE, URL_SCHEME, HTTP_REQUEST_METHOD, NETWORK_PEER_PORT, NETWORK_PEER_ADDRESS } from '@sentry/conventions/attributes'; | ||
| import { DEBUG_BUILD } from '../../debug-build.js'; | ||
| const ATTR_HTTP_REQUEST_METHOD_ORIGINAL = "http.request.method_original"; | ||
| const _channelSubs = []; | ||
| const spanFromReq = /* @__PURE__ */ new WeakMap(); | ||
| const ignoreRequestMap = /* @__PURE__ */ new WeakMap(); | ||
| const propagationDecisionMap = new LRUMap(100); | ||
| function instrumentUndici(config = {}) { | ||
| if (_channelSubs.length) { | ||
| return; | ||
| } | ||
| subscribeToChannel("undici:request:create", (message) => onRequestCreated(config, message)); | ||
| subscribeToChannel( | ||
| "undici:client:sendHeaders", | ||
| (message) => onRequestHeaders(config, message) | ||
| ); | ||
| subscribeToChannel("undici:request:headers", (message) => onResponseHeaders(config, message)); | ||
| subscribeToChannel("undici:request:trailers", (message) => onDone(message)); | ||
| subscribeToChannel("undici:request:error", (message) => onError(message)); | ||
| } | ||
| function safeExecute(fn, onError2) { | ||
| try { | ||
| return fn(); | ||
| } catch (error) { | ||
| onError2(error); | ||
| return void 0; | ||
| } | ||
| } | ||
| function subscribeToChannel(diagnosticChannel, onMessage) { | ||
| const [major = 0, minor = 0] = process.version.replace("v", "").split(".").map((n) => Number(n)); | ||
| const useNewSubscribe = major > 18 || major === 18 && minor >= 19; | ||
| if (useNewSubscribe) { | ||
| _channelSubs.push(diagch.subscribe?.(diagnosticChannel, onMessage)); | ||
| } else { | ||
| _channelSubs.push(diagch.channel(diagnosticChannel).subscribe(onMessage)); | ||
| } | ||
| } | ||
| function parseRequestHeaders(request) { | ||
| const result = /* @__PURE__ */ new Map(); | ||
| if (Array.isArray(request.headers)) { | ||
| for (let i = 0; i < request.headers.length; i += 2) { | ||
| const key = request.headers[i]; | ||
| const value = request.headers[i + 1]; | ||
| if (typeof key === "string" && value !== void 0) { | ||
| result.set(key.toLowerCase(), value); | ||
| } | ||
| } | ||
| } else if (typeof request.headers === "string") { | ||
| const headers = request.headers.split("\r\n"); | ||
| for (const line of headers) { | ||
| if (!line) { | ||
| continue; | ||
| } | ||
| const colonIndex = line.indexOf(":"); | ||
| if (colonIndex === -1) { | ||
| continue; | ||
| } | ||
| const key = line.substring(0, colonIndex).toLowerCase(); | ||
| const value = line.substring(colonIndex + 1).trim(); | ||
| const allValues = result.get(key); | ||
| if (allValues && Array.isArray(allValues)) { | ||
| allValues.push(value); | ||
| } else if (allValues) { | ||
| result.set(key, [allValues, value]); | ||
| } else { | ||
| result.set(key, value); | ||
| } | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| function onRequestCreated(config, { request }) { | ||
| const url = getAbsoluteUrl(request.origin, request.path); | ||
| const ignoredByCallback = safeExecute( | ||
| () => !!config.ignoreOutgoingRequests?.(url), | ||
| (e) => e && DEBUG_BUILD && debug.error("caught ignoreOutgoingRequests error: ", e) | ||
| ); | ||
| const ignoreForBreadcrumbs = isTracingSuppressed() || !!ignoredByCallback; | ||
| ignoreRequestMap.set(request, ignoreForBreadcrumbs); | ||
| if (!config.spans) { | ||
| if (config.tracePropagation !== false && !ignoreForBreadcrumbs) { | ||
| addTracePropagationHeadersToFetchRequest(request, propagationDecisionMap); | ||
| } | ||
| return; | ||
| } | ||
| if (request.method === "CONNECT" || ignoredByCallback) { | ||
| return; | ||
| } | ||
| let requestUrl; | ||
| try { | ||
| requestUrl = new URL(request.path, request.origin); | ||
| } catch (err) { | ||
| DEBUG_BUILD && debug.warn("could not determine url.full:", err); | ||
| return; | ||
| } | ||
| const urlScheme = requestUrl.protocol.replace(":", ""); | ||
| const requestMethod = getRequestMethod(request.method); | ||
| const attributes = { | ||
| [HTTP_REQUEST_METHOD]: requestMethod, | ||
| [ATTR_HTTP_REQUEST_METHOD_ORIGINAL]: request.method, | ||
| [URL_FULL]: requestUrl.toString(), | ||
| [URL_PATH]: requestUrl.pathname, | ||
| [URL_QUERY]: requestUrl.search, | ||
| [URL_SCHEME]: urlScheme, | ||
| [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.otel.node_fetch" | ||
| }; | ||
| if (url.startsWith("data:")) { | ||
| const sanitizedUrl = stripDataUrlContent(url); | ||
| attributes["http.url"] = sanitizedUrl; | ||
| attributes[URL_FULL] = sanitizedUrl; | ||
| attributes[SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME] = `${request.method || "GET"} ${sanitizedUrl}`; | ||
| } | ||
| const schemePorts = { https: "443", http: "80" }; | ||
| const serverAddress = requestUrl.hostname; | ||
| const serverPort = requestUrl.port || schemePorts[urlScheme]; | ||
| attributes[SERVER_ADDRESS] = serverAddress; | ||
| if (serverPort && !isNaN(Number(serverPort))) { | ||
| attributes[SERVER_PORT] = Number(serverPort); | ||
| } | ||
| const headersMap = parseRequestHeaders(request); | ||
| const userAgentValues = headersMap.get("user-agent"); | ||
| if (userAgentValues) { | ||
| const userAgent = Array.isArray(userAgentValues) ? userAgentValues[userAgentValues.length - 1] : userAgentValues; | ||
| attributes[USER_AGENT_ORIGINAL] = userAgent; | ||
| } | ||
| const client = getClient(); | ||
| const span = startInactiveSpan({ | ||
| name: requestMethod === "_OTHER" ? "HTTP" : requestMethod, | ||
| kind: SPAN_KIND.CLIENT, | ||
| attributes, | ||
| onlyIfParent: !client || !hasSpanStreamingEnabled(client) | ||
| }); | ||
| safeExecute( | ||
| () => config.requestHook?.(span, request), | ||
| (e) => e && DEBUG_BUILD && debug.error("caught requestHook error: ", e) | ||
| ); | ||
| addTracePropagationHeadersToFetchRequest(request, propagationDecisionMap, span); | ||
| spanFromReq.set(request, span); | ||
| } | ||
| function onRequestHeaders(config, { request, socket }) { | ||
| const span = spanFromReq.get(request); | ||
| if (!span) { | ||
| return; | ||
| } | ||
| const { remoteAddress, remotePort } = socket; | ||
| const spanAttributes = { | ||
| [NETWORK_PEER_ADDRESS]: remoteAddress, | ||
| [NETWORK_PEER_PORT]: remotePort | ||
| }; | ||
| if (config.headersToSpanAttributes?.requestHeaders) { | ||
| const headersToAttribs = new Set(config.headersToSpanAttributes.requestHeaders.map((n) => n.toLowerCase())); | ||
| const headersMap = parseRequestHeaders(request); | ||
| for (const [name, value] of headersMap.entries()) { | ||
| if (headersToAttribs.has(name)) { | ||
| const attrValue = Array.isArray(value) ? value : [value]; | ||
| spanAttributes[`http.request.header.${name}`] = attrValue; | ||
| } | ||
| } | ||
| } | ||
| span.setAttributes(spanAttributes); | ||
| } | ||
| function onResponseHeaders(config, { request, response }) { | ||
| const breadcrumbsEnabled = config.breadcrumbs !== false; | ||
| if (breadcrumbsEnabled && !ignoreRequestMap.get(request)) { | ||
| addFetchRequestBreadcrumb(request, response); | ||
| } | ||
| const span = spanFromReq.get(request); | ||
| if (!span) { | ||
| return; | ||
| } | ||
| const spanAttributes = { | ||
| [HTTP_RESPONSE_STATUS_CODE]: response.statusCode | ||
| }; | ||
| safeExecute( | ||
| () => config.responseHook?.(span, { request, response }), | ||
| (e) => e && DEBUG_BUILD && debug.error("caught responseHook error: ", e) | ||
| ); | ||
| if (config.headersToSpanAttributes?.responseHeaders) { | ||
| const headersToAttribs = /* @__PURE__ */ new Set(); | ||
| config.headersToSpanAttributes?.responseHeaders.forEach((name) => headersToAttribs.add(name.toLowerCase())); | ||
| for (let idx = 0; idx < response.headers.length; idx = idx + 2) { | ||
| const nameBuf = response.headers[idx]; | ||
| const valueBuf = response.headers[idx + 1]; | ||
| if (nameBuf === void 0 || valueBuf === void 0) { | ||
| continue; | ||
| } | ||
| const name = nameBuf.toString().toLowerCase(); | ||
| const value = valueBuf; | ||
| if (headersToAttribs.has(name)) { | ||
| const attrName = `http.response.header.${name}`; | ||
| if (!Object.prototype.hasOwnProperty.call(spanAttributes, attrName)) { | ||
| spanAttributes[attrName] = [value.toString()]; | ||
| } else { | ||
| spanAttributes[attrName].push(value.toString()); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| span.setAttributes(spanAttributes); | ||
| if (response.statusCode >= 400) { | ||
| span.setStatus(getSpanStatusFromHttpCode(response.statusCode)); | ||
| } | ||
| } | ||
| function onDone({ request }) { | ||
| const span = spanFromReq.get(request); | ||
| if (!span) { | ||
| return; | ||
| } | ||
| span.end(); | ||
| spanFromReq.delete(request); | ||
| } | ||
| function onError({ request, error }) { | ||
| const span = spanFromReq.get(request); | ||
| if (!span) { | ||
| return; | ||
| } | ||
| span.setStatus({ | ||
| code: SPAN_STATUS_ERROR, | ||
| message: error.message | ||
| }); | ||
| span.end(); | ||
| spanFromReq.delete(request); | ||
| } | ||
| function getRequestMethod(original) { | ||
| const knownMethods = { | ||
| CONNECT: true, | ||
| OPTIONS: true, | ||
| HEAD: true, | ||
| GET: true, | ||
| POST: true, | ||
| PUT: true, | ||
| PATCH: true, | ||
| DELETE: true, | ||
| TRACE: true, | ||
| // QUERY from https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/ | ||
| QUERY: true | ||
| }; | ||
| if (original.toUpperCase() in knownMethods) { | ||
| return original.toUpperCase(); | ||
| } | ||
| return "_OTHER"; | ||
| } | ||
| function getAbsoluteUrl(origin, path = "/") { | ||
| const url = `${origin}`; | ||
| if (url.endsWith("/") && path.startsWith("/")) { | ||
| return `${url}${path.slice(1)}`; | ||
| } | ||
| if (!url.endsWith("/") && !path.startsWith("/")) { | ||
| return `${url}/${path}`; | ||
| } | ||
| return `${url}${path}`; | ||
| } | ||
| export { instrumentUndici }; | ||
| //# sourceMappingURL=undici-instrumentation.js.map |
| {"version":3,"file":"undici-instrumentation.js","sources":["../../../../src/integrations/node-fetch/undici-instrumentation.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/ed97091c9890dd18e52759f2ea98e9d7593b3ae4/packages/instrumentation-undici\n * - Upstream version: @opentelemetry/instrumentation-undici@0.24.0\n * - Tracking issue: https://github.com/getsentry/sentry-javascript/issues/20165\n * - Refactored to use Sentry's span APIs instead of OpenTelemetry tracing APIs\n * - Dropped the OTel metrics (no MeterProvider is wired up) and the dead\n * `requireParentforSpans` code path (the SDK always passes `false`)\n * - Dropped the `@opentelemetry/instrumentation` base (undici reports via `diagnostics_channel`,\n * so no module patching was needed) — exposed as a plain `instrumentUndici()` function that the\n * integration wires up directly\n */\n\n/* eslint-disable max-lines */\n\nimport * as diagch from 'diagnostics_channel';\nimport { URL } from 'url';\n\nimport type { Span, SpanAttributes } from '@sentry/core';\nimport {\n debug,\n getClient,\n getSpanStatusFromHttpCode,\n hasSpanStreamingEnabled,\n isTracingSuppressed,\n LRUMap,\n SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_KIND,\n SPAN_STATUS_ERROR,\n startInactiveSpan,\n stripDataUrlContent,\n} from '@sentry/core';\nimport { addFetchRequestBreadcrumb, addTracePropagationHeadersToFetchRequest } from '../../utils/outgoingFetchRequest';\nimport {\n HTTP_REQUEST_METHOD,\n HTTP_RESPONSE_STATUS_CODE,\n NETWORK_PEER_ADDRESS,\n NETWORK_PEER_PORT,\n SERVER_ADDRESS,\n SERVER_PORT,\n URL_FULL,\n URL_PATH,\n URL_QUERY,\n URL_SCHEME,\n USER_AGENT_ORIGINAL,\n} from '@sentry/conventions/attributes';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport type {\n NodeFetchOptions,\n UndiciRequest,\n RequestErrorMessage,\n RequestHeadersMessage,\n RequestMessage,\n RequestTrailersMessage,\n ResponseHeadersMessage,\n} from './types';\n\n// `http.request.method_original` is not part of `@sentry/conventions`, so we keep it inline.\nconst ATTR_HTTP_REQUEST_METHOD_ORIGINAL = 'http.request.method_original';\n\n// Keep ref to avoid https://github.com/nodejs/node/issues/42170 bug\n// We can replace this with _isInstrumented once we drop support for Node.js 18.18.0\nconst _channelSubs: Array<unknown> = [];\nconst spanFromReq = new WeakMap<UndiciRequest, Span>();\n// Whether breadcrumbs (and span-less trace propagation) should be skipped for a given request.\n// We evaluate this at request-creation time because the active context is no longer correct by the\n// time the response-headers event fires.\nconst ignoreRequestMap = new WeakMap<UndiciRequest, boolean>();\n// Caches trace-propagation decisions per URL so we don't recompute the `tracePropagationTargets` regexes per request.\nconst propagationDecisionMap = new LRUMap<string, boolean>(100);\n\n/**\n * Instrument outgoing HTTP requests made through `undici` or the global `fetch` API: emit `http.client`\n * spans, record breadcrumbs, and propagate traces into the outgoing request headers.\n *\n * Span creation is gated by the `spans` option (defaults to `true`). When spans are disabled, breadcrumbs\n * are still recorded and trace propagation headers are still injected (gated by `tracePropagation`).\n *\n * undici reports its request lifecycle via `diagnostics_channel`, so rather than patching any module we\n * subscribe to those channels directly. This is idempotent — subsequent calls are no-ops once the\n * channels have been subscribed to, and the config of the first call wins.\n *\n * A combination of https://github.com/elastic/apm-agent-nodejs and\n * https://github.com/gadget-inc/opentelemetry-instrumentations/blob/main/packages/opentelemetry-instrumentation-undici/src/index.ts\n */\nexport function instrumentUndici(config: NodeFetchOptions = {}): void {\n // Avoid duplicate subscriptions\n if (_channelSubs.length) {\n return;\n }\n\n subscribeToChannel('undici:request:create', message => onRequestCreated(config, message as RequestMessage));\n subscribeToChannel('undici:client:sendHeaders', message =>\n onRequestHeaders(config, message as RequestHeadersMessage),\n );\n subscribeToChannel('undici:request:headers', message => onResponseHeaders(config, message as ResponseHeadersMessage));\n subscribeToChannel('undici:request:trailers', message => onDone(message as RequestTrailersMessage));\n subscribeToChannel('undici:request:error', message => onError(message as RequestErrorMessage));\n}\n\n/** Replaces OTel's `safeExecuteInTheMiddle`: run `fn`, route any error to `onError`, and swallow it. */\nfunction safeExecute<T>(fn: () => T, onError: (error: unknown) => void): T | undefined {\n try {\n return fn();\n } catch (error) {\n onError(error);\n return undefined;\n }\n}\n\nfunction subscribeToChannel(\n diagnosticChannel: string,\n onMessage: (message: unknown, name: string | symbol) => void,\n): void {\n // `diagnostics_channel` had a ref counting bug until v18.19.0.\n // https://github.com/nodejs/node/pull/47520\n const [major = 0, minor = 0] = process.version\n .replace('v', '')\n .split('.')\n .map(n => Number(n));\n const useNewSubscribe = major > 18 || (major === 18 && minor >= 19);\n\n if (useNewSubscribe) {\n _channelSubs.push(diagch.subscribe?.(diagnosticChannel, onMessage));\n } else {\n _channelSubs.push(diagch.channel(diagnosticChannel).subscribe(onMessage));\n }\n}\n\nfunction parseRequestHeaders(request: UndiciRequest): Map<string, string | string[]> {\n const result = new Map<string, string | string[]>();\n\n if (Array.isArray(request.headers)) {\n // headers are an array [k1, v2, k2, v2] (undici v6+)\n // values could be string or a string[] for multiple values\n for (let i = 0; i < request.headers.length; i += 2) {\n const key = request.headers[i];\n const value = request.headers[i + 1];\n\n // Key should always be a string, but the types don't know that, and let's be safe\n if (typeof key === 'string' && value !== undefined) {\n result.set(key.toLowerCase(), value);\n }\n }\n } else if (typeof request.headers === 'string') {\n // headers are a raw string (undici v5)\n // headers could be repeated in several lines for multiple values\n const headers = request.headers.split('\\r\\n');\n for (const line of headers) {\n if (!line) {\n continue;\n }\n const colonIndex = line.indexOf(':');\n if (colonIndex === -1) {\n // Invalid header? Probably this can't happen, but again let's be safe.\n continue;\n }\n const key = line.substring(0, colonIndex).toLowerCase();\n const value = line.substring(colonIndex + 1).trim();\n const allValues = result.get(key);\n\n if (allValues && Array.isArray(allValues)) {\n allValues.push(value);\n } else if (allValues) {\n result.set(key, [allValues, value]);\n } else {\n result.set(key, value);\n }\n }\n }\n return result;\n}\n\n// This is the 1st message we receive for each request (fired after request creation). Here we will\n// create the span and populate some atttributes, then link the span to the request for further\n// span processing\nfunction onRequestCreated(config: NodeFetchOptions, { request }: RequestMessage): void {\n const url = getAbsoluteUrl(request.origin, request.path);\n\n const ignoredByCallback = safeExecute(\n () => !!config.ignoreOutgoingRequests?.(url),\n e => e && DEBUG_BUILD && debug.error('caught ignoreOutgoingRequests error: ', e),\n );\n\n // Breadcrumbs & span-less trace propagation are additionally skipped when tracing is suppressed.\n // We store this here because the active context is no longer correct in later channel events.\n const ignoreForBreadcrumbs = isTracingSuppressed() || !!ignoredByCallback;\n ignoreRequestMap.set(request, ignoreForBreadcrumbs);\n\n // When spans are disabled we do not create a span, but we still inject trace propagation headers\n // directly (unless disabled via `tracePropagation`).\n if (!config.spans) {\n if (config.tracePropagation !== false && !ignoreForBreadcrumbs) {\n addTracePropagationHeadersToFetchRequest(request, propagationDecisionMap);\n }\n return;\n }\n\n // Ignore span creation if:\n // - the outgoing request is ignored via config\n // - method is 'CONNECT'\n if (request.method === 'CONNECT' || ignoredByCallback) {\n return;\n }\n\n let requestUrl;\n try {\n requestUrl = new URL(request.path, request.origin);\n } catch (err) {\n DEBUG_BUILD && debug.warn('could not determine url.full:', err);\n // Skip instrumenting this request.\n return;\n }\n const urlScheme = requestUrl.protocol.replace(':', '');\n const requestMethod = getRequestMethod(request.method);\n const attributes: SpanAttributes = {\n [HTTP_REQUEST_METHOD]: requestMethod,\n [ATTR_HTTP_REQUEST_METHOD_ORIGINAL]: request.method,\n [URL_FULL]: requestUrl.toString(),\n [URL_PATH]: requestUrl.pathname,\n [URL_QUERY]: requestUrl.search,\n [URL_SCHEME]: urlScheme,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.node_fetch',\n };\n\n // Sanitize data URLs to prevent long base64 strings in span attributes\n if (url.startsWith('data:')) {\n const sanitizedUrl = stripDataUrlContent(url);\n attributes['http.url'] = sanitizedUrl;\n attributes[URL_FULL] = sanitizedUrl;\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME] = `${request.method || 'GET'} ${sanitizedUrl}`;\n }\n\n const schemePorts: Record<string, string> = { https: '443', http: '80' };\n const serverAddress = requestUrl.hostname;\n const serverPort = requestUrl.port || schemePorts[urlScheme];\n\n attributes[SERVER_ADDRESS] = serverAddress;\n if (serverPort && !isNaN(Number(serverPort))) {\n attributes[SERVER_PORT] = Number(serverPort);\n }\n\n // Get user agent from headers\n const headersMap = parseRequestHeaders(request);\n const userAgentValues = headersMap.get('user-agent');\n\n if (userAgentValues) {\n // NOTE: having multiple user agents is not expected so\n // we're going to take last one like `curl` does\n // ref: https://curl.se/docs/manpage.html#-A\n const userAgent = Array.isArray(userAgentValues) ? userAgentValues[userAgentValues.length - 1] : userAgentValues;\n attributes[USER_AGENT_ORIGINAL] = userAgent;\n }\n\n // Outside of span streaming, only record an `http.client` span when it has a parent. An orphan\n // one (no local parent) is left to the server for the downstream sampling decision: `onlyIfParent`\n // still creates a non-recording span so trace propagation headers are injected, but it isn't\n // emitted as a standalone transaction. This rule also lives in `SentrySampler`, but that only runs\n // when an OpenTelemetry SDK tracer provider is set up, so we enforce it here too, which covers\n // SDKs that don't use an OpenTelemetry tracer provider at all.\n const client = getClient();\n const span = startInactiveSpan({\n name: requestMethod === '_OTHER' ? 'HTTP' : requestMethod,\n kind: SPAN_KIND.CLIENT,\n attributes,\n onlyIfParent: !client || !hasSpanStreamingEnabled(client),\n });\n\n // Execute the request hook if defined\n safeExecute(\n () => config.requestHook?.(span, request),\n e => e && DEBUG_BUILD && debug.error('caught requestHook error: ', e),\n );\n\n // Context propagation goes last so no hook can tamper the propagation headers.\n // We propagate the trace data of the freshly created client span (not the active parent span)\n // so downstream services are parented to the http.client span, matching the upstream behavior.\n // This also de-duplicates against any trace headers the user set manually (e.g. via `getTraceData()`).\n addTracePropagationHeadersToFetchRequest(request, propagationDecisionMap, span);\n\n spanFromReq.set(request, span);\n}\n\n// This is the 2nd message we receive for each request. It is fired when connection with\n// the remote is established and about to send the first byte. Here we do have info about the\n// remote address and port so we can populate some `network.*` attributes into the span\nfunction onRequestHeaders(config: NodeFetchOptions, { request, socket }: RequestHeadersMessage): void {\n const span = spanFromReq.get(request);\n\n if (!span) {\n return;\n }\n\n const { remoteAddress, remotePort } = socket;\n const spanAttributes: SpanAttributes = {\n [NETWORK_PEER_ADDRESS]: remoteAddress,\n [NETWORK_PEER_PORT]: remotePort,\n };\n\n // After hooks have been processed (which may modify request headers)\n // we can collect the headers based on the configuration\n if (config.headersToSpanAttributes?.requestHeaders) {\n const headersToAttribs = new Set(config.headersToSpanAttributes.requestHeaders.map(n => n.toLowerCase()));\n const headersMap = parseRequestHeaders(request);\n\n for (const [name, value] of headersMap.entries()) {\n if (headersToAttribs.has(name)) {\n const attrValue = Array.isArray(value) ? value : [value];\n spanAttributes[`http.request.header.${name}`] = attrValue;\n }\n }\n }\n\n span.setAttributes(spanAttributes);\n}\n\n// This is the 3rd message we get for each request and it's fired when the server\n// headers are received, body may not be accessible yet.\n// From the response headers we can set the status and content length\nfunction onResponseHeaders(config: NodeFetchOptions, { request, response }: ResponseHeadersMessage): void {\n // Breadcrumbs are recorded independently of spans, so this runs even when span creation is disabled.\n const breadcrumbsEnabled = config.breadcrumbs !== false;\n if (breadcrumbsEnabled && !ignoreRequestMap.get(request)) {\n addFetchRequestBreadcrumb(request, response);\n }\n\n const span = spanFromReq.get(request);\n\n if (!span) {\n return;\n }\n\n const spanAttributes: SpanAttributes = {\n [HTTP_RESPONSE_STATUS_CODE]: response.statusCode,\n };\n\n // Execute the response hook if defined\n safeExecute(\n () => config.responseHook?.(span, { request, response }),\n e => e && DEBUG_BUILD && debug.error('caught responseHook error: ', e),\n );\n\n if (config.headersToSpanAttributes?.responseHeaders) {\n const headersToAttribs = new Set<string>();\n config.headersToSpanAttributes?.responseHeaders.forEach(name => headersToAttribs.add(name.toLowerCase()));\n\n for (let idx = 0; idx < response.headers.length; idx = idx + 2) {\n const nameBuf = response.headers[idx];\n const valueBuf = response.headers[idx + 1];\n if (nameBuf === undefined || valueBuf === undefined) {\n continue;\n }\n const name = nameBuf.toString().toLowerCase();\n const value = valueBuf;\n\n if (headersToAttribs.has(name)) {\n const attrName = `http.response.header.${name}`;\n if (!Object.prototype.hasOwnProperty.call(spanAttributes, attrName)) {\n spanAttributes[attrName] = [value.toString()];\n } else {\n (spanAttributes[attrName] as string[]).push(value.toString());\n }\n }\n }\n }\n\n span.setAttributes(spanAttributes);\n\n // Resolve the HTTP status code to a Sentry span status here (like the raw http client/server\n // instrumentation does) instead of setting a bare error and deferring to downstream inference.\n // The SentryTracerProvider's status finalization reads the already-stringified span status, which\n // can no longer be inferred back to `not_found` etc. the way the OpenTelemetry SDK exporter's\n // `mapStatus` does from the raw `{ code, message }`.\n if (response.statusCode >= 400) {\n span.setStatus(getSpanStatusFromHttpCode(response.statusCode));\n }\n}\n\n// This is the last event we receive if the request went without any errors\nfunction onDone({ request }: RequestTrailersMessage): void {\n const span = spanFromReq.get(request);\n\n if (!span) {\n return;\n }\n\n span.end();\n spanFromReq.delete(request);\n}\n\n// This is the event we get when something is wrong in the request like\n// - invalid options when calling `fetch` global API or any undici method for request\n// - connectivity errors such as unreachable host\n// - requests aborted through an `AbortController.signal`\n// NOTE: server errors are considered valid responses and it's the lib consumer\n// who should deal with that.\nfunction onError({ request, error }: RequestErrorMessage): void {\n const span = spanFromReq.get(request);\n\n if (!span) {\n return;\n }\n\n // NOTE: in `undici@6.3.0` when request aborted the error type changes from\n // a custom error (`RequestAbortedError`) to a built-in `DOMException` carrying\n // some differences:\n // - `code` is from DOMEXception (ABORT_ERR: 20)\n // - `message` changes\n // - stacktrace is smaller and contains node internal frames\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: error.message,\n });\n span.end();\n spanFromReq.delete(request);\n}\n\nfunction getRequestMethod(original: string): string {\n const knownMethods = {\n CONNECT: true,\n OPTIONS: true,\n HEAD: true,\n GET: true,\n POST: true,\n PUT: true,\n PATCH: true,\n DELETE: true,\n TRACE: true,\n // QUERY from https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/\n QUERY: true,\n };\n\n if (original.toUpperCase() in knownMethods) {\n return original.toUpperCase();\n }\n\n return '_OTHER';\n}\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}`;\n }\n\n return `${url}${path}`;\n}\n"],"names":["onError"],"mappings":"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"} |
| import { NodeFetchOptions } from './types'; | ||
| /** | ||
| * Instrument outgoing HTTP requests made through `undici` or the global `fetch` API: emit `http.client` | ||
| * spans, record breadcrumbs, and propagate traces into the outgoing request headers. | ||
| * | ||
| * Span creation is gated by the `spans` option (defaults to `true`). When spans are disabled, breadcrumbs | ||
| * are still recorded and trace propagation headers are still injected (gated by `tracePropagation`). | ||
| * | ||
| * undici reports its request lifecycle via `diagnostics_channel`, so rather than patching any module we | ||
| * subscribe to those channels directly. This is idempotent — subsequent calls are no-ops once the | ||
| * channels have been subscribed to, and the config of the first call wins. | ||
| * | ||
| * A combination of https://github.com/elastic/apm-agent-nodejs and | ||
| * https://github.com/gadget-inc/opentelemetry-instrumentations/blob/main/packages/opentelemetry-instrumentation-undici/src/index.ts | ||
| */ | ||
| export declare function instrumentUndici(config?: NodeFetchOptions): void; | ||
| //# sourceMappingURL=undici-instrumentation.d.ts.map |
| import type { NodeFetchOptions } from './types'; | ||
| /** | ||
| * Instrument outgoing HTTP requests made through `undici` or the global `fetch` API: emit `http.client` | ||
| * spans, record breadcrumbs, and propagate traces into the outgoing request headers. | ||
| * | ||
| * Span creation is gated by the `spans` option (defaults to `true`). When spans are disabled, breadcrumbs | ||
| * are still recorded and trace propagation headers are still injected (gated by `tracePropagation`). | ||
| * | ||
| * undici reports its request lifecycle via `diagnostics_channel`, so rather than patching any module we | ||
| * subscribe to those channels directly. This is idempotent — subsequent calls are no-ops once the | ||
| * channels have been subscribed to, and the config of the first call wins. | ||
| * | ||
| * A combination of https://github.com/elastic/apm-agent-nodejs and | ||
| * https://github.com/gadget-inc/opentelemetry-instrumentations/blob/main/packages/opentelemetry-instrumentation-undici/src/index.ts | ||
| */ | ||
| export declare function instrumentUndici(config?: NodeFetchOptions): void; | ||
| //# sourceMappingURL=undici-instrumentation.d.ts.map |
| {"version":3,"file":"undici-instrumentation.d.ts","sourceRoot":"","sources":["../../../../src/integrations/node-fetch/undici-instrumentation.ts"],"names":[],"mappings":"AAmDA,OAAO,KAAK,EACV,gBAAgB,EAOjB,MAAM,SAAS,CAAC;AAgBjB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,GAAE,gBAAqB,GAAG,IAAI,CAapE"} |
@@ -8,2 +8,3 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const index$5 = require('./integrations/node-fetch/index.js'); | ||
| const undiciInstrumentation = require('./integrations/node-fetch/undici-instrumentation.js'); | ||
| const SentryNodeFetchInstrumentation = require('./integrations/node-fetch/SentryNodeFetchInstrumentation.js'); | ||
@@ -39,3 +40,2 @@ const contextManager = require('./otel/contextManager.js'); | ||
| const esmLoader = require('./sdk/esmLoader.js'); | ||
| const detection = require('./utils/detection.js'); | ||
| const createMissingInstrumentationContext = require('./utils/createMissingInstrumentationContext.js'); | ||
@@ -53,2 +53,3 @@ const http = require('./transports/http.js'); | ||
| exports.nativeNodeFetchIntegration = index$5.nativeNodeFetchIntegration; | ||
| exports.instrumentUndici = undiciInstrumentation.instrumentUndici; | ||
| exports.SentryNodeFetchInstrumentation = SentryNodeFetchInstrumentation.SentryNodeFetchInstrumentation; | ||
@@ -174,3 +175,2 @@ exports.SentryContextManager = contextManager.SentryContextManager; | ||
| exports.initializeEsmLoader = esmLoader.initializeEsmLoader; | ||
| exports.isCjs = detection.isCjs; | ||
| exports.createMissingInstrumentationContext = createMissingInstrumentationContext.createMissingInstrumentationContext; | ||
@@ -177,0 +177,0 @@ exports.makeNodeTransport = http.makeNodeTransport; |
@@ -10,3 +10,3 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const { isPromise } = util.types; | ||
| const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZS1jb3JlIDEwLjYzLjAgKDIzNjJlOWYpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyB0fWZyb20ibm9kZTppbnNwZWN0b3IiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIG4scGFyZW50UG9ydCBhcyBlfWZyb20ibm9kZTp3b3JrZXJfdGhyZWFkcyI7aW1wb3J0e3Bvc2l4IGFzIHIsc2VwIGFzIG99ZnJvbSJub2RlOnBhdGgiO2ltcG9ydCphcyBpIGZyb20ibm9kZTpodHRwIjtpbXBvcnQqYXMgcyBmcm9tIm5vZGU6aHR0cHMiO2ltcG9ydHtSZWFkYWJsZSBhcyBjfWZyb20ibm9kZTpzdHJlYW0iO2ltcG9ydHtjcmVhdGVHemlwIGFzIHV9ZnJvbSJub2RlOnpsaWIiO2ltcG9ydCphcyBhIGZyb20ibm9kZTpuZXQiO2ltcG9ydCphcyBmIGZyb20ibm9kZTp0bHMiO2NvbnN0IGg9InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fLHA9Z2xvYmFsVGhpcyxkPSIxMC42My4wIjtmdW5jdGlvbiBsKCl7cmV0dXJuIGcocCkscH1mdW5jdGlvbiBnKHQpe2NvbnN0IG49dC5fX1NFTlRSWV9fPXQuX19TRU5UUllfX3x8e307cmV0dXJuIG4udmVyc2lvbj1uLnZlcnNpb258fGQsbltkXT1uW2RdfHx7fX1mdW5jdGlvbiBtKHQsbixlPXApe2NvbnN0IHI9ZS5fX1NFTlRSWV9fPWUuX19TRU5UUllfX3x8e30sbz1yW2RdPXJbZF18fHt9O3JldHVybiBvW3RdfHwob1t0XT1uKCkpfWNvbnN0IHk9e307ZnVuY3Rpb24gYih0KXtpZighKCJjb25zb2xlImluIHApKXJldHVybiB0KCk7Y29uc3Qgbj1wLmNvbnNvbGUsZT17fSxyPU9iamVjdC5rZXlzKHkpO3IuZm9yRWFjaCh0PT57Y29uc3Qgcj15W3RdO2VbdF09blt0XSxuW3RdPXJ9KTt0cnl7cmV0dXJuIHQoKX1maW5hbGx5e3IuZm9yRWFjaCh0PT57blt0XT1lW3RdfSl9fWZ1bmN0aW9uIHYoKXtyZXR1cm4gUygpLmVuYWJsZWR9ZnVuY3Rpb24gXyh0LC4uLm4pe2gmJnYoKSYmYigoKT0+e3AuY29uc29sZVt0XShgU2VudHJ5IExvZ2dlciBbJHt0fV06YCwuLi5uKX0pfWZ1bmN0aW9uIFMoKXtyZXR1cm4gaD9tKCJsb2dnZXJTZXR0aW5ncyIsKCk9Pih7ZW5hYmxlZDohMX0pKTp7ZW5hYmxlZDohMX19Y29uc3Qgdz17ZW5hYmxlOmZ1bmN0aW9uKCl7UygpLmVuYWJsZWQ9ITB9LGRpc2FibGU6ZnVuY3Rpb24oKXtTKCkuZW5hYmxlZD0hMX0saXNFbmFibGVkOnYsbG9nOmZ1bmN0aW9uKC4uLnQpe18oImxvZyIsLi4udCl9LHdhcm46ZnVuY3Rpb24oLi4udCl7Xygid2FybiIsLi4udCl9LGVycm9yOmZ1bmN0aW9uKC4uLnQpe18oImVycm9yIiwuLi50KX19LCQ9L2NhcHR1cmVNZXNzYWdlfGNhcHR1cmVFeGNlcHRpb24vO2Z1bmN0aW9uIEUodCl7cmV0dXJuIHRbdC5sZW5ndGgtMV18fHt9fWNvbnN0IHg9Ijxhbm9ueW1vdXM+Ijtjb25zdCBOPU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7ZnVuY3Rpb24gQyh0LG4pe3JldHVybiBOLmNhbGwodCk9PT1gW29iamVjdCAke259XWB9ZnVuY3Rpb24gaih0KXtyZXR1cm4gQm9vbGVhbih0Py50aGVuJiYiZnVuY3Rpb24iPT10eXBlb2YgdC50aGVuKX1mdW5jdGlvbiBSKHQsbil7dHJ5e3JldHVybiB0IGluc3RhbmNlb2Ygbn1jYXRjaHtyZXR1cm4hMX19ZnVuY3Rpb24gQSh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2goTi5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBXZWJBc3NlbWJseS5FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBSKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uSSh0KX07aWYobj10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJlIobixFdmVudCkpe2NvbnN0e3R5cGU6bix0YXJnZXQ6ZSxjdXJyZW50VGFyZ2V0OnIsZGV0YWlsOm99PXQ7cmV0dXJue3R5cGU6bix0YXJnZXQ6ZSxjdXJyZW50VGFyZ2V0OnIsLi4ubz97ZGV0YWlsOm99Ont9LC4uLkkodCl9fXZhciBuO3JldHVybiB0fWZ1bmN0aW9uIEkodCl7cmV0dXJuIm9iamVjdCI9PXR5cGVvZiB0JiZudWxsIT09dD9PYmplY3QuZnJvbUVudHJpZXMoT2JqZWN0LmVudHJpZXModCkpOnt9fWxldCBPO2Z1bmN0aW9uIFQodCl7aWYodm9pZCAwIT09TylyZXR1cm4gTz9PKHQpOnQoKTtjb25zdCBuPVN5bWJvbC5mb3IoIl9fU0VOVFJZX1NBRkVfUkFORE9NX0lEX1dSQVBQRVJfXyIpLGU9cDtyZXR1cm4gbiBpbiBlJiYiZnVuY3Rpb24iPT10eXBlb2YgZVtuXT8oTz1lW25dLE8odCkpOihPPW51bGwsdCgpKX1mdW5jdGlvbiBrKCl7cmV0dXJuIFQoKCk9Pk1hdGgucmFuZG9tKCkpfWZ1bmN0aW9uIFAoKXtyZXR1cm4gVCgoKT0+RGF0ZS5ub3coKSl9Y29uc3QgRD1TeW1ib2wuZm9yKCJzZW50cnkuc2tpcE5vcm1hbGl6YXRpb24iKSxVPVN5bWJvbC5mb3IoInNlbnRyeS5vdmVycmlkZU5vcm1hbGl6YXRpb25EZXB0aCIpO2Z1bmN0aW9uIEIodCxuPTEwMCxlPTEvMCl7dHJ5e3JldHVybiBMKCIiLHQsbixlKX1jYXRjaCh0KXtyZXR1cm57RVJST1I6YCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke3R9KWB9fX1mdW5jdGlvbiBMKHQsbixlPTEvMCxyPTEvMCxvPWZ1bmN0aW9uKCl7Y29uc3QgdD1uZXcgV2Vha1NldDtmdW5jdGlvbiBuKG4pe3JldHVybiEhdC5oYXMobil8fCh0LmFkZChuKSwhMSl9ZnVuY3Rpb24gZShuKXt0LmRlbGV0ZShuKX1yZXR1cm5bbixlXX0oKSl7Y29uc3RbaSxzXT1vO2lmKG51bGw9PW58fFsiYm9vbGVhbiIsInN0cmluZyJdLmluY2x1ZGVzKHR5cGVvZiBuKXx8Im51bWJlciI9PXR5cGVvZiBuJiZOdW1iZXIuaXNGaW5pdGUobikpcmV0dXJuIG47Y29uc3QgYz1mdW5jdGlvbih0LG4pe3RyeXtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGdsb2JhbCYmbj09PWdsb2JhbClyZXR1cm4iW0dsb2JhbF0iO2lmKCJudW1iZXIiPT10eXBlb2YgbiYmIU51bWJlci5pc0Zpbml0ZShuKSlyZXR1cm5gWyR7bn1dYDtpZigiZnVuY3Rpb24iPT10eXBlb2YgbilyZXR1cm5gW0Z1bmN0aW9uOiAke2Z1bmN0aW9uKHQpe3RyeXtyZXR1cm4gdCYmImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQubmFtZXx8eH1jYXRjaHtyZXR1cm4geH19KG4pfV1gO2lmKCJzeW1ib2wiPT10eXBlb2YgbilyZXR1cm5gWyR7U3RyaW5nKG4pfV1gO2lmKCJiaWdpbnQiPT10eXBlb2YgbilyZXR1cm5gW0JpZ0ludDogJHtTdHJpbmcobil9XWA7Y29uc3QgdD1mdW5jdGlvbih0KXtjb25zdCBuPU9iamVjdC5nZXRQcm90b3R5cGVPZih0KTtyZXR1cm4gbj8uY29uc3RydWN0b3I/bi5jb25zdHJ1Y3Rvci5uYW1lOiJudWxsIHByb3RvdHlwZSJ9KG4pO3JldHVybmBbb2JqZWN0ICR7dH1dYH1jYXRjaCh0KXtyZXR1cm5gKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH19KDAsbik7aWYoIWMuc3RhcnRzV2l0aCgiW29iamVjdCAiKSlyZXR1cm4gYztpZihmdW5jdGlvbih0KXtyZXR1cm4gQm9vbGVhbih0W0RdKX0obikpcmV0dXJuIG47Y29uc3QgdT1mdW5jdGlvbih0KXtjb25zdCBuPXRbVV07cmV0dXJuIm51bWJlciI9PXR5cGVvZiBuP246dm9pZCAwfShuKSxhPXZvaWQgMCE9PXU/dTplO2lmKDA9PT1hKXJldHVybiBjLnJlcGxhY2UoIm9iamVjdCAiLCIiKTtpZihpKG4pKXJldHVybiJbQ2lyY3VsYXIgfl0iO2NvbnN0IGY9bjtpZihmJiYiZnVuY3Rpb24iPT10eXBlb2YgZi50b0pTT04pdHJ5e3JldHVybiBMKCIiLGYudG9KU09OKCksYS0xLHIsbyl9Y2F0Y2h7fWNvbnN0IGg9QXJyYXkuaXNBcnJheShuKT9bXTp7fTtsZXQgcD0wO2NvbnN0IGQ9QShuKTtmb3IoY29uc3QgdCBpbiBkKXtpZighT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGQsdCkpY29udGludWU7aWYocD49cil7aFt0XT0iW01heFByb3BlcnRpZXMgfl0iO2JyZWFrfWNvbnN0IG49ZFt0XTtoW3RdPUwodCxuLGEtMSxyLG8pLHArK31yZXR1cm4gcyhuKSxofWZ1bmN0aW9uIE0odCxuKXtjb25zdCBlPW4ucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL1t8XFx7fSgpW1xdXiQrKj8uXS9nLCJcXCQmIik7bGV0IHI9dDt0cnl7cj1kZWNvZGVVUkkodCl9Y2F0Y2h7fXJldHVybiByLnJlcGxhY2UoL1xcL2csIi8iKS5yZXBsYWNlKC93ZWJwYWNrOlwvPy9nLCIiKS5yZXBsYWNlKG5ldyBSZWdFeHAoYChmaWxlOi8vKT8vKiR7ZX0vKmAsImlnIiksImFwcDovLy8iKX1mdW5jdGlvbiB6KHQsbj0wKXtyZXR1cm4ic3RyaW5nIiE9dHlwZW9mIHR8fDA9PT1ufHx0Lmxlbmd0aDw9bj90OmAke3Quc2xpY2UoMCxuKX0uLi5gfWxldCBGO2Z1bmN0aW9uIEcodD1mdW5jdGlvbigpe2NvbnN0IHQ9cDtyZXR1cm4gdC5jcnlwdG98fHQubXNDcnlwdG99KCkpe3RyeXtpZih0Py5yYW5kb21VVUlEKXJldHVybiBUKCgpPT50LnJhbmRvbVVVSUQoKSkucmVwbGFjZSgvLS9nLCIiKX1jYXRjaHt9cmV0dXJuIEZ8fChGPSIxMDAwMDAwMDEwMDA0MDAwODAwMDEwMDAwMDAwMDAwMCIpLEYucmVwbGFjZSgvWzAxOF0vZyx0PT4odF4oMTYqaygpJjE1KT4+dC80KS50b1N0cmluZygxNikpfWZ1bmN0aW9uIEooKXtyZXR1cm4gUCgpLzFlM31sZXQgVztmdW5jdGlvbiBZKCl7cmV0dXJuKFc/PyhXPWZ1bmN0aW9uKCl7Y29uc3R7cGVyZm9ybWFuY2U6dH09cDtpZighdD8ubm93fHwhdC50aW1lT3JpZ2luKXJldHVybiBKO2NvbnN0IG49dC50aW1lT3JpZ2luO3JldHVybigpPT4obitUKCgpPT50Lm5vdygpKSkvMWUzfSgpKSkoKX1mdW5jdGlvbiBIKHQpe2NvbnN0IG49WSgpLGU9e3NpZDpHKCksaW5pdDohMCx0aW1lc3RhbXA6bixzdGFydGVkOm4sZHVyYXRpb246MCxzdGF0dXM6Im9rIixlcnJvcnM6MCxpZ25vcmVEdXJhdGlvbjohMSx0b0pTT046KCk9PmZ1bmN0aW9uKHQpe3JldHVybntzaWQ6YCR7dC5zaWR9YCxpbml0OnQuaW5pdCxzdGFydGVkOm5ldyBEYXRlKDFlMyp0LnN0YXJ0ZWQpLnRvSVNPU3RyaW5nKCksdGltZXN0YW1wOm5ldyBEYXRlKDFlMyp0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxzdGF0dXM6dC5zdGF0dXMsZXJyb3JzOnQuZXJyb3JzLGRpZDoibnVtYmVyIj09dHlwZW9mIHQuZGlkfHwic3RyaW5nIj09dHlwZW9mIHQuZGlkP2Ake3QuZGlkfWA6dm9pZCAwLGR1cmF0aW9uOnQuZHVyYXRpb24sYWJub3JtYWxfbWVjaGFuaXNtOnQuYWJub3JtYWxfbWVjaGFuaXNtLGF0dHJzOntyZWxlYXNlOnQucmVsZWFzZSxlbnZpcm9ubWVudDp0LmVudmlyb25tZW50LGlwX2FkZHJlc3M6dC5pcEFkZHJlc3MsdXNlcl9hZ2VudDp0LnVzZXJBZ2VudH19fShlKX07cmV0dXJuIHQmJksoZSx0KSxlfWZ1bmN0aW9uIEsodCxuPXt9KXtpZihuLnVzZXImJighdC5pcEFkZHJlc3MmJm4udXNlci5pcF9hZGRyZXNzJiYodC5pcEFkZHJlc3M9bi51c2VyLmlwX2FkZHJlc3MpLHQuZGlkfHxuLmRpZHx8KHQuZGlkPW4udXNlci5pZHx8bi51c2VyLmVtYWlsfHxuLnVzZXIudXNlcm5hbWUpKSx0LnRpbWVzdGFtcD1uLnRpbWVzdGFtcHx8WSgpLG4uYWJub3JtYWxfbWVjaGFuaXNtJiYodC5hYm5vcm1hbF9tZWNoYW5pc209bi5hYm5vcm1hbF9tZWNoYW5pc20pLG4uaWdub3JlRHVyYXRpb24mJih0Lmlnbm9yZUR1cmF0aW9uPW4uaWdub3JlRHVyYXRpb24pLG4uc2lkJiYodC5zaWQ9MzI9PT1uLnNpZC5sZW5ndGg/bi5zaWQ6RygpKSx2b2lkIDAhPT1uLmluaXQmJih0LmluaXQ9bi5pbml0KSwhdC5kaWQmJm4uZGlkJiYodC5kaWQ9YCR7bi5kaWR9YCksIm51bWJlciI9PXR5cGVvZiBuLnN0YXJ0ZWQmJih0LnN0YXJ0ZWQ9bi5zdGFydGVkKSx0Lmlnbm9yZUR1cmF0aW9uKXQuZHVyYXRpb249dm9pZCAwO2Vsc2UgaWYoIm51bWJlciI9PXR5cGVvZiBuLmR1cmF0aW9uKXQuZHVyYXRpb249bi5kdXJhdGlvbjtlbHNle2NvbnN0IG49dC50aW1lc3RhbXAtdC5zdGFydGVkO3QuZHVyYXRpb249bj49MD9uOjB9bi5yZWxlYXNlJiYodC5yZWxlYXNlPW4ucmVsZWFzZSksbi5lbnZpcm9ubWVudCYmKHQuZW52aXJvbm1lbnQ9bi5lbnZpcm9ubWVudCksIXQuaXBBZGRyZXNzJiZuLmlwQWRkcmVzcyYmKHQuaXBBZGRyZXNzPW4uaXBBZGRyZXNzKSwhdC51c2VyQWdlbnQmJm4udXNlckFnZW50JiYodC51c2VyQWdlbnQ9bi51c2VyQWdlbnQpLCJudW1iZXIiPT10eXBlb2Ygbi5lcnJvcnMmJih0LmVycm9ycz1uLmVycm9ycyksbi5zdGF0dXMmJih0LnN0YXR1cz1uLnN0YXR1cyl9ZnVuY3Rpb24gWih0LG4sZT0yKXtpZighbnx8Im9iamVjdCIhPXR5cGVvZiBufHxlPD0wKXJldHVybiBuO2lmKHQmJjA9PT1PYmplY3Qua2V5cyhuKS5sZW5ndGgpcmV0dXJuIHQ7Y29uc3Qgcj17Li4udH07Zm9yKGNvbnN0IHQgaW4gbilPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobix0KSYmKHJbdF09WihyW3RdLG5bdF0sZS0xKSk7cmV0dXJuIHJ9ZnVuY3Rpb24gcSgpe3JldHVybiBHKCl9ZnVuY3Rpb24gVigpe3JldHVybiBHKCkuc3Vic3RyaW5nKDE2KX1mdW5jdGlvbiBRKHQpe2lmKHQpe2lmKCJvYmplY3QiPT10eXBlb2YgdCYmImRlcmVmImluIHQmJiJmdW5jdGlvbiI9PXR5cGVvZiB0LmRlcmVmKXRyeXtyZXR1cm4gdC5kZXJlZigpfWNhdGNoe3JldHVybn1yZXR1cm4gdH19Y29uc3QgWD0iX3NlbnRyeVNwYW4iO2Z1bmN0aW9uIHR0KHQsbil7bj9mdW5jdGlvbih0LG4sZSl7dHJ5e09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LG4se3ZhbHVlOmUsd3JpdGFibGU6ITAsY29uZmlndXJhYmxlOiEwfSl9Y2F0Y2h7aCYmdy5sb2coYEZhaWxlZCB0byBhZGQgbm9uLWVudW1lcmFibGUgcHJvcGVydHkgIiR7U3RyaW5nKG4pfSIgdG8gb2JqZWN0YCx0KX19KHQsWCxmdW5jdGlvbih0KXt0cnl7Y29uc3Qgbj1wLldlYWtSZWY7aWYoImZ1bmN0aW9uIj09dHlwZW9mIG4pcmV0dXJuIG5ldyBuKHQpfWNhdGNoe31yZXR1cm4gdH0obikpOmRlbGV0ZSB0W1hdfWZ1bmN0aW9uIG50KHQpe3JldHVybiBRKHRbWF0pfWNsYXNzIGV0e2NvbnN0cnVjdG9yKCl7dGhpcy50PSExLHRoaXMubz1bXSx0aGlzLmk9W10sdGhpcy51PVtdLHRoaXMuaD1bXSx0aGlzLnA9e30sdGhpcy5sPXt9LHRoaXMubT17fSx0aGlzLnY9e30sdGhpcy5fPXt9LHRoaXMuUz17fSx0aGlzLk49e3RyYWNlSWQ6cSgpLHNhbXBsZVJhbmQ6aygpfX1jbG9uZSgpe2NvbnN0IHQ9bmV3IGV0O3JldHVybiB0LnU9Wy4uLnRoaXMudV0sdC5sPXsuLi50aGlzLmx9LHQubT17Li4udGhpcy5tfSx0LnY9ey4uLnRoaXMudn0sdC5fPXsuLi50aGlzLl99LHRoaXMuXy5mbGFncyYmKHQuXy5mbGFncz17dmFsdWVzOlsuLi50aGlzLl8uZmxhZ3MudmFsdWVzXX0pLHQucD10aGlzLnAsdC5DPXRoaXMuQyx0Lmo9dGhpcy5qLHQuUj10aGlzLlIsdC5BPXRoaXMuQSx0Lmk9Wy4uLnRoaXMuaV0sdC5oPVsuLi50aGlzLmhdLHQuUz17Li4udGhpcy5TfSx0Lk49ey4uLnRoaXMuTn0sdC5JPXRoaXMuSSx0Lk89dGhpcy5PLHQuVD10aGlzLlQsdHQodCxudCh0aGlzKSksdH1zZXRDbGllbnQodCl7dGhpcy5JPXR9c2V0TGFzdEV2ZW50SWQodCl7dGhpcy5PPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuSX1sYXN0RXZlbnRJZCgpe3JldHVybiB0aGlzLk99YWRkU2NvcGVMaXN0ZW5lcih0KXt0aGlzLm8ucHVzaCh0KX1hZGRFdmVudFByb2Nlc3Nvcih0KXtyZXR1cm4gdGhpcy5pLnB1c2godCksdGhpc31zZXRVc2VyKHQpe3JldHVybiB0aGlzLnA9dHx8e2VtYWlsOnZvaWQgMCxpZDp2b2lkIDAsaXBfYWRkcmVzczp2b2lkIDAsdXNlcm5hbWU6dm9pZCAwfSx0aGlzLmomJksodGhpcy5qLHt1c2VyOnR9KSx0aGlzLmsoKSx0aGlzfWdldFVzZXIoKXtyZXR1cm4gdGhpcy5wfXNldENvbnZlcnNhdGlvbklkKHQpe3JldHVybiB0aGlzLlQ9dHx8dm9pZCAwLHRoaXMuaygpLHRoaXN9c2V0VGFncyh0KXtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4udH0sdGhpcy5rKCksdGhpc31zZXRUYWcodCxuKXtyZXR1cm4gdGhpcy5zZXRUYWdzKHtbdF06bn0pfXNldEF0dHJpYnV0ZXModCl7cmV0dXJuIHRoaXMubT17Li4udGhpcy5tLC4uLnR9LHRoaXMuaygpLHRoaXN9c2V0QXR0cmlidXRlKHQsbil7cmV0dXJuIHRoaXMuc2V0QXR0cmlidXRlcyh7W3RdOm59KX1yZW1vdmVBdHRyaWJ1dGUodCl7cmV0dXJuIHQgaW4gdGhpcy5tJiYoZGVsZXRlIHRoaXMubVt0XSx0aGlzLmsoKSksdGhpc31zZXRFeHRyYXModCl7cmV0dXJuIHRoaXMudj17Li4udGhpcy52LC4uLnR9LHRoaXMuaygpLHRoaXN9c2V0RXh0cmEodCxuKXtyZXR1cm4gdGhpcy52PXsuLi50aGlzLnYsW3RdOm59LHRoaXMuaygpLHRoaXN9c2V0RmluZ2VycHJpbnQodCl7cmV0dXJuIHRoaXMuQT10LHRoaXMuaygpLHRoaXN9c2V0TGV2ZWwodCl7cmV0dXJuIHRoaXMuQz10LHRoaXMuaygpLHRoaXN9c2V0VHJhbnNhY3Rpb25OYW1lKHQpe3JldHVybiB0aGlzLlI9dCx0aGlzLmsoKSx0aGlzfXNldENvbnRleHQodCxuKXtyZXR1cm4gbnVsbD09PW4/ZGVsZXRlIHRoaXMuX1t0XTp0aGlzLl9bdF09bix0aGlzLmsoKSx0aGlzfXNldFNlc3Npb24odCl7cmV0dXJuIHQ/dGhpcy5qPXQ6ZGVsZXRlIHRoaXMuaix0aGlzLmsoKSx0aGlzfWdldFNlc3Npb24oKXtyZXR1cm4gdGhpcy5qfXVwZGF0ZSh0KXtpZighdClyZXR1cm4gdGhpcztjb25zdCBuPSJmdW5jdGlvbiI9PXR5cGVvZiB0P3QodGhpcyk6dCxlPW4gaW5zdGFuY2VvZiBldD9uLmdldFNjb3BlRGF0YSgpOkMobiwiT2JqZWN0Iik/dDp2b2lkIDA7Y29uc3R7dGFnczpyLGF0dHJpYnV0ZXM6byxleHRyYTppLHVzZXI6cyxjb250ZXh0czpjLGxldmVsOnUsZmluZ2VycHJpbnQ6YT1bXSxwcm9wYWdhdGlvbkNvbnRleHQ6Zixjb252ZXJzYXRpb25JZDpofT1lfHx7fTtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4ucn0sdGhpcy5tPXsuLi50aGlzLm0sLi4ub30sdGhpcy52PXsuLi50aGlzLnYsLi4uaX0sdGhpcy5fPXsuLi50aGlzLl8sLi4uY30scyYmT2JqZWN0LmtleXMocykubGVuZ3RoJiYodGhpcy5wPXMpLHUmJih0aGlzLkM9dSksYS5sZW5ndGgmJih0aGlzLkE9YSksZiYmKHRoaXMuTj1mKSxoJiYodGhpcy5UPWgpLHRoaXN9Y2xlYXIoKXtyZXR1cm4gdGhpcy51PVtdLHRoaXMubD17fSx0aGlzLm09e30sdGhpcy52PXt9LHRoaXMucD17fSx0aGlzLl89e30sdGhpcy5DPXZvaWQgMCx0aGlzLlI9dm9pZCAwLHRoaXMuQT12b2lkIDAsdGhpcy5qPXZvaWQgMCx0aGlzLlQ9dm9pZCAwLHR0KHRoaXMsdm9pZCAwKSx0aGlzLmg9W10sdGhpcy5zZXRQcm9wYWdhdGlvbkNvbnRleHQoe3RyYWNlSWQ6cSgpLHNhbXBsZVJhbmQ6aygpfSksdGhpcy5rKCksdGhpc31hZGRCcmVhZGNydW1iKHQsbil7Y29uc3QgZT0ibnVtYmVyIj09dHlwZW9mIG4/bjoxMDA7aWYoZTw9MClyZXR1cm4gdGhpcztjb25zdCByPXt0aW1lc3RhbXA6SigpLC4uLnQsbWVzc2FnZTp0Lm1lc3NhZ2U/eih0Lm1lc3NhZ2UsMjA0OCk6dC5tZXNzYWdlfTtyZXR1cm4gdGhpcy51LnB1c2gociksdGhpcy51Lmxlbmd0aD5lJiYodGhpcy51PXRoaXMudS5zbGljZSgtZSksdGhpcy5JPy5yZWNvcmREcm9wcGVkRXZlbnQoImJ1ZmZlcl9vdmVyZmxvdyIsImxvZ19pdGVtIikpLHRoaXMuaygpLHRoaXN9Z2V0TGFzdEJyZWFkY3J1bWIoKXtyZXR1cm4gdGhpcy51W3RoaXMudS5sZW5ndGgtMV19Y2xlYXJCcmVhZGNydW1icygpe3JldHVybiB0aGlzLnU9W10sdGhpcy5rKCksdGhpc31hZGRBdHRhY2htZW50KHQpe3JldHVybiB0aGlzLmgucHVzaCh0KSx0aGlzfWNsZWFyQXR0YWNobWVudHMoKXtyZXR1cm4gdGhpcy5oPVtdLHRoaXN9Z2V0U2NvcGVEYXRhKCl7cmV0dXJue2JyZWFkY3J1bWJzOnRoaXMudSxhdHRhY2htZW50czp0aGlzLmgsY29udGV4dHM6dGhpcy5fLHRhZ3M6dGhpcy5sLGF0dHJpYnV0ZXM6dGhpcy5tLGV4dHJhOnRoaXMudix1c2VyOnRoaXMucCxsZXZlbDp0aGlzLkMsZmluZ2VycHJpbnQ6dGhpcy5BfHxbXSxldmVudFByb2Nlc3NvcnM6dGhpcy5pLHByb3BhZ2F0aW9uQ29udGV4dDp0aGlzLk4sc2RrUHJvY2Vzc2luZ01ldGFkYXRhOnRoaXMuUyx0cmFuc2FjdGlvbk5hbWU6dGhpcy5SLHNwYW46bnQodGhpcyksY29udmVyc2F0aW9uSWQ6dGhpcy5UfX1zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEodCl7cmV0dXJuIHRoaXMuUz1aKHRoaXMuUyx0LDIpLHRoaXN9c2V0UHJvcGFnYXRpb25Db250ZXh0KHQpe3JldHVybiB0aGlzLk49dCx0aGlzfWdldFByb3BhZ2F0aW9uQ29udGV4dCgpe3JldHVybiB0aGlzLk59Y2FwdHVyZUV4Y2VwdGlvbih0LG4pe2NvbnN0IGU9bj8uZXZlbnRfaWR8fEcoKTtpZighdGhpcy5JKXJldHVybiBoJiZ3Lndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBleGNlcHRpb24hIiksZTtjb25zdCByPW5ldyBFcnJvcigiU2VudHJ5IHN5bnRoZXRpY0V4Y2VwdGlvbiIpO3JldHVybiB0aGlzLkkuY2FwdHVyZUV4Y2VwdGlvbih0LHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpyLC4uLm4sZXZlbnRfaWQ6ZX0sdGhpcyksZX1jYXB0dXJlTWVzc2FnZSh0LG4sZSl7Y29uc3Qgcj1lPy5ldmVudF9pZHx8RygpO2lmKCF0aGlzLkkpcmV0dXJuIGgmJncud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIG1lc3NhZ2UhIikscjtjb25zdCBvPWU/LnN5bnRoZXRpY0V4Y2VwdGlvbj8/bmV3IEVycm9yKHQpO3JldHVybiB0aGlzLkkuY2FwdHVyZU1lc3NhZ2UodCxuLHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpvLC4uLmUsZXZlbnRfaWQ6cn0sdGhpcykscn1jYXB0dXJlRXZlbnQodCxuKXtjb25zdCBlPXQuZXZlbnRfaWR8fG4/LmV2ZW50X2lkfHxHKCk7cmV0dXJuIHRoaXMuST8odGhpcy5JLmNhcHR1cmVFdmVudCh0LHsuLi5uLGV2ZW50X2lkOmV9LHRoaXMpLGUpOihoJiZ3Lndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBldmVudCEiKSxlKX1rKCl7dGhpcy50fHwodGhpcy50PSEwLHRoaXMuby5mb3JFYWNoKHQ9Pnt0KHRoaXMpfSksdGhpcy50PSExKX19Y29uc3QgcnQ9dD0+dCBpbnN0YW5jZW9mIFByb21pc2UmJiF0W290XSxvdD1TeW1ib2woImNoYWluZWQgUHJvbWlzZUxpa2UiKSxpdD0odCxuKT0+e2lmKCFuKXJldHVybiB0O2xldCBlPSExO2Zvcihjb25zdCByIGluIHQpe2lmKHIgaW4gbiljb250aW51ZTtlPSEwO2NvbnN0IG89dFtyXTsiZnVuY3Rpb24iPT10eXBlb2Ygbz9PYmplY3QuZGVmaW5lUHJvcGVydHkobixyLHt2YWx1ZTooLi4ubik9Pm8uYXBwbHkodCxuKSxlbnVtZXJhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMCx3cml0YWJsZTohMH0pOm5bcl09b31yZXR1cm4gZSYmT2JqZWN0LmFzc2lnbihuLHtbb3RdOiEwfSksbn07Y2xhc3Mgc3R7Y29uc3RydWN0b3IodCxuKXtsZXQgZSxyO2U9dHx8bmV3IGV0LHI9bnx8bmV3IGV0LHRoaXMuUD1be3Njb3BlOmV9XSx0aGlzLkQ9cn13aXRoU2NvcGUodCl7Y29uc3Qgbj10aGlzLlUoKTtsZXQgZTt0cnl7ZT10KG4pfWNhdGNoKHQpe3Rocm93IHRoaXMuQigpLHR9cmV0dXJuIGooZSk/KCh0LG4sZSk9Pntjb25zdCByPXQudGhlbih0PT4obih0KSx0KSx0PT57dGhyb3cgZSh0KSx0fSk7cmV0dXJuIHJ0KHIpJiZydCh0KT9yOml0KHQscil9KShlLCgpPT50aGlzLkIoKSwoKT0+dGhpcy5CKCkpOih0aGlzLkIoKSxlKX1nZXRDbGllbnQoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLmNsaWVudH1nZXRTY29wZSgpe3JldHVybiB0aGlzLmdldFN0YWNrVG9wKCkuc2NvcGV9Z2V0SXNvbGF0aW9uU2NvcGUoKXtyZXR1cm4gdGhpcy5EfWdldFN0YWNrVG9wKCl7cmV0dXJuIHRoaXMuUFt0aGlzLlAubGVuZ3RoLTFdfVUoKXtjb25zdCB0PXRoaXMuZ2V0U2NvcGUoKS5jbG9uZSgpO3JldHVybiB0aGlzLlAucHVzaCh7Y2xpZW50OnRoaXMuZ2V0Q2xpZW50KCksc2NvcGU6dH0pLHR9Qigpe3JldHVybiEodGhpcy5QLmxlbmd0aDw9MSkmJiEhdGhpcy5QLnBvcCgpfX1mdW5jdGlvbiBjdCgpe2NvbnN0IHQ9ZyhsKCkpO3JldHVybiB0LnN0YWNrPXQuc3RhY2t8fG5ldyBzdChtKCJkZWZhdWx0Q3VycmVudFNjb3BlIiwoKT0+bmV3IGV0KSxtKCJkZWZhdWx0SXNvbGF0aW9uU2NvcGUiLCgpPT5uZXcgZXQpKX1mdW5jdGlvbiB1dCh0KXtyZXR1cm4gY3QoKS53aXRoU2NvcGUodCl9ZnVuY3Rpb24gYXQodCxuKXtjb25zdCBlPWN0KCk7cmV0dXJuIGUud2l0aFNjb3BlKCgpPT4oZS5nZXRTdGFja1RvcCgpLnNjb3BlPXQsbih0KSkpfWZ1bmN0aW9uIGZ0KHQpe3JldHVybiBjdCgpLndpdGhTY29wZSgoKT0+dChjdCgpLmdldElzb2xhdGlvblNjb3BlKCkpKX1mdW5jdGlvbiBodCh0KXtjb25zdCBuPWcodCk7cmV0dXJuIG4uYWNzP24uYWNzOnt3aXRoSXNvbGF0aW9uU2NvcGU6ZnQsd2l0aFNjb3BlOnV0LHdpdGhTZXRTY29wZTphdCx3aXRoU2V0SXNvbGF0aW9uU2NvcGU6KHQsbik9PmZ0KG4pLGdldEN1cnJlbnRTY29wZTooKT0+Y3QoKS5nZXRTY29wZSgpLGdldElzb2xhdGlvblNjb3BlOigpPT5jdCgpLmdldElzb2xhdGlvblNjb3BlKCl9fWZ1bmN0aW9uIHB0KCl7cmV0dXJuIGh0KGwoKSkuZ2V0Q3VycmVudFNjb3BlKCkuZ2V0Q2xpZW50KCl9ZnVuY3Rpb24gZHQodCl7Y29uc3Qgbj10O3JldHVybntzY29wZTpuLl9zZW50cnlTY29wZSxpc29sYXRpb25TY29wZTpRKG4uX3NlbnRyeUlzb2xhdGlvblNjb3BlKX19Y29uc3QgbHQ9InNlbnRyeS0iO2Z1bmN0aW9uIGd0KHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7aWYoIXR8fChuPXQsIUMobiwiU3RyaW5nIikmJiFBcnJheS5pc0FycmF5KHQpKSlyZXR1cm47dmFyIG47aWYoQXJyYXkuaXNBcnJheSh0KSlyZXR1cm4gdC5yZWR1Y2UoKHQsbik9Pntjb25zdCBlPW10KG4pO3JldHVybiBPYmplY3QuZW50cmllcyhlKS5mb3JFYWNoKChbbixlXSk9Pnt0W25dPWV9KSx0fSx7fSk7cmV0dXJuIG10KHQpfSh0KTtpZighbilyZXR1cm47Y29uc3QgZT1PYmplY3QuZW50cmllcyhuKS5yZWR1Y2UoKHQsW24sZV0pPT57aWYobi5zdGFydHNXaXRoKGx0KSl7dFtuLnNsaWNlKDcpXT1lfXJldHVybiB0fSx7fSk7cmV0dXJuIE9iamVjdC5rZXlzKGUpLmxlbmd0aD4wP2U6dm9pZCAwfWZ1bmN0aW9uIG10KHQpe3JldHVybiB0LnNwbGl0KCIsIikubWFwKHQ9Pntjb25zdCBuPXQuaW5kZXhPZigiPSIpO2lmKC0xPT09bilyZXR1cm5bXTtyZXR1cm5bdC5zbGljZSgwLG4pLHQuc2xpY2UobisxKV0ubWFwKHQ9Pnt0cnl7cmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudCh0LnRyaW0oKSl9Y2F0Y2h7cmV0dXJufX0pfSkucmVkdWNlKCh0LFtuLGVdKT0+KG4mJmUmJih0W25dPWUpLHQpLHt9KX1jb25zdCB5dD0vXm8oXGQrKVwuLztmdW5jdGlvbiBidCh0LG49ITEpe2NvbnN0e2hvc3Q6ZSxwYXRoOnIscGFzczpvLHBvcnQ6aSxwcm9qZWN0SWQ6cyxwcm90b2NvbDpjLHB1YmxpY0tleTp1fT10O3JldHVybmAke2N9Oi8vJHt1fSR7biYmbz9gOiR7b31gOiIifUAke2V9JHtpP2A6JHtpfWA6IiJ9LyR7cj9gJHtyfS9gOnJ9JHtzfWB9ZnVuY3Rpb24gdnQodCl7Y29uc3Qgbj10LmdldE9wdGlvbnMoKSx7aG9zdDplfT10LmdldERzbigpfHx7fTtsZXQgcjtyZXR1cm4gbi5vcmdJZD9yPVN0cmluZyhuLm9yZ0lkKTplJiYocj1mdW5jdGlvbih0KXtjb25zdCBuPXQubWF0Y2goeXQpO3JldHVybiBuPy5bMV19KGUpKSxyfWZ1bmN0aW9uIF90KHQpe2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZSxpc1JlbW90ZTpyfT10LnNwYW5Db250ZXh0KCksbz1yP246RXQodCkucGFyZW50X3NwYW5faWQsaT1kdCh0KS5zY29wZTtyZXR1cm57cGFyZW50X3NwYW5faWQ6byxzcGFuX2lkOnI/aT8uZ2V0UHJvcGFnYXRpb25Db250ZXh0KCkucHJvcGFnYXRpb25TcGFuSWR8fFYoKTpuLHRyYWNlX2lkOmV9fWZ1bmN0aW9uIFN0KHQpe3JldHVybiB0JiZ0Lmxlbmd0aD4wP3QubWFwKCh7Y29udGV4dDp7c3BhbklkOnQsdHJhY2VJZDpuLHRyYWNlRmxhZ3M6ZSwuLi5yfSxhdHRyaWJ1dGVzOm99KT0+KHtzcGFuX2lkOnQsdHJhY2VfaWQ6bixzYW1wbGVkOjE9PT1lLGF0dHJpYnV0ZXM6bywuLi5yfSkpOnZvaWQgMH1mdW5jdGlvbiB3dCh0KXtyZXR1cm4ibnVtYmVyIj09dHlwZW9mIHQ/JHQodCk6QXJyYXkuaXNBcnJheSh0KT90WzBdK3RbMV0vMWU5OnQgaW5zdGFuY2VvZiBEYXRlPyR0KHQuZ2V0VGltZSgpKTpZKCl9ZnVuY3Rpb24gJHQodCl7cmV0dXJuIHQ+OTk5OTk5OTk5OT90LzFlMzp0fWZ1bmN0aW9uIEV0KHQpe2lmKGZ1bmN0aW9uKHQpe3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiB0LmdldFNwYW5KU09OfSh0KSlyZXR1cm4gdC5nZXRTcGFuSlNPTigpO2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZX09dC5zcGFuQ29udGV4dCgpO2lmKGZ1bmN0aW9uKHQpe2NvbnN0IG49dDtyZXR1cm4hIShuLmF0dHJpYnV0ZXMmJm4uc3RhcnRUaW1lJiZuLm5hbWUmJm4uZW5kVGltZSYmbi5zdGF0dXMpfSh0KSl7Y29uc3R7YXR0cmlidXRlczpyLHN0YXJ0VGltZTpvLG5hbWU6aSxlbmRUaW1lOnMsc3RhdHVzOmMsbGlua3M6dX09dDtyZXR1cm57c3Bhbl9pZDpuLHRyYWNlX2lkOmUsZGF0YTpyLGRlc2NyaXB0aW9uOmkscGFyZW50X3NwYW5faWQ6eHQodCksc3RhcnRfdGltZXN0YW1wOnd0KG8pLHRpbWVzdGFtcDp3dChzKXx8dm9pZCAwLHN0YXR1czpOdChjKSxvcDpyWyJzZW50cnkub3AiXSxvcmlnaW46clsic2VudHJ5Lm9yaWdpbiJdLGxpbmtzOlN0KHUpfX1yZXR1cm57c3Bhbl9pZDpuLHRyYWNlX2lkOmUsc3RhcnRfdGltZXN0YW1wOjAsZGF0YTp7fX19ZnVuY3Rpb24geHQodCl7cmV0dXJuInBhcmVudFNwYW5JZCJpbiB0P3QucGFyZW50U3BhbklkOiJwYXJlbnRTcGFuQ29udGV4dCJpbiB0P3QucGFyZW50U3BhbkNvbnRleHQ/LnNwYW5JZDp2b2lkIDB9ZnVuY3Rpb24gTnQodCl7aWYodCYmMCE9PXQuY29kZSlyZXR1cm4gMT09PXQuY29kZT8ib2siOnQubWVzc2FnZXx8ImludGVybmFsX2Vycm9yIn1jb25zdCBDdD1mdW5jdGlvbih0KXtyZXR1cm4gdC5fc2VudHJ5Um9vdFNwYW58fHR9O2Z1bmN0aW9uIGp0KHQpe2lmKCJib29sZWFuIj09dHlwZW9mIF9fU0VOVFJZX1RSQUNJTkdfXyYmIV9fU0VOVFJZX1RSQUNJTkdfXylyZXR1cm4hMTtjb25zdCBuPXR8fHB0KCk/LmdldE9wdGlvbnMoKTtyZXR1cm4hKCFufHxudWxsPT1uLnRyYWNlc1NhbXBsZVJhdGUmJiFuLnRyYWNlc1NhbXBsZXIpfWNvbnN0IFJ0PVN5bWJvbC5mb3IoInNlbnRyeS5ub25SZWNvcmRpbmdTcGFuIik7ZnVuY3Rpb24gQXQodCxuKXtjb25zdCBlPW4uZ2V0T3B0aW9ucygpLHtwdWJsaWNLZXk6cn09bi5nZXREc24oKXx8e30sbz17ZW52aXJvbm1lbnQ6ZS5lbnZpcm9ubWVudHx8InByb2R1Y3Rpb24iLHJlbGVhc2U6ZS5yZWxlYXNlLHB1YmxpY19rZXk6cix0cmFjZV9pZDp0LG9yZ19pZDp2dChuKX07cmV0dXJuIG4uZW1pdCgiY3JlYXRlRHNjIixvKSxvfWZ1bmN0aW9uIEl0KHQsbil7Y29uc3QgZT1uLmdldFByb3BhZ2F0aW9uQ29udGV4dCgpO3JldHVybiBlLmRzY3x8QXQoZS50cmFjZUlkLHQpfWZ1bmN0aW9uIE90KHQpe2NvbnN0IG49cHQoKTtpZighbilyZXR1cm57fTtjb25zdCBlPUN0KHQpLHI9RXQoZSksbz1yLmRhdGEsaT1lLnNwYW5Db250ZXh0KCkudHJhY2VTdGF0ZSxzPWk/LmdldCgic2VudHJ5LnNhbXBsZV9yYXRlIik/P29bInNlbnRyeS5zYW1wbGVfcmF0ZSJdPz9vWyJzZW50cnkucHJldmlvdXNfdHJhY2Vfc2FtcGxlX3JhdGUiXTtmdW5jdGlvbiBjKHQpe3JldHVybiJudW1iZXIiIT10eXBlb2YgcyYmInN0cmluZyIhPXR5cGVvZiBzfHwodC5zYW1wbGVfcmF0ZT1gJHtzfWApLHR9Y29uc3QgdT1lLl9mcm96ZW5Ec2M7aWYodSlyZXR1cm4gYyh1KTtpZihmdW5jdGlvbih0KXtyZXR1cm4hIXQmJiEwPT09dFtSdF19KGUpJiYhanQobi5nZXRPcHRpb25zKCkpKXtjb25zdCB0PWR0KGUpLnNjb3BlO2lmKHQpcmV0dXJuIGMoey4uLkl0KG4sdCl9KX1jb25zdCBhPWk/LmdldCgic2VudHJ5LmRzYyIpLGY9YSYmZ3QoYSk7aWYoZilyZXR1cm4gYyhmKTtjb25zdCBoPUF0KHQuc3BhbkNvbnRleHQoKS50cmFjZUlkLG4pLHA9b1sic2VudHJ5LnNvdXJjZSJdPz9vWyJzZW50cnkuc3Bhbi5zb3VyY2UiXSxkPXIuZGVzY3JpcHRpb247cmV0dXJuInVybCIhPT1wJiZkJiYoaC50cmFuc2FjdGlvbj1kKSxqdCgpJiYoaC5zYW1wbGVkPVN0cmluZyhmdW5jdGlvbih0KXtjb25zdHt0cmFjZUZsYWdzOm59PXQuc3BhbkNvbnRleHQoKTtyZXR1cm4gMT09PW59KGUpKSxoLnNhbXBsZV9yYW5kPWk/LmdldCgic2VudHJ5LnNhbXBsZV9yYW5kIik/P2R0KGUpLnNjb3BlPy5nZXRQcm9wYWdhdGlvbkNvbnRleHQoKS5zYW1wbGVSYW5kLnRvU3RyaW5nKCkpLGMoaCksbi5lbWl0KCJjcmVhdGVEc2MiLGgsZSksaH1mdW5jdGlvbiBUdCh0LG49W10pe3JldHVyblt0LG5dfWZ1bmN0aW9uIGt0KHQsbil7Y29uc3QgZT10WzFdO2Zvcihjb25zdCB0IG9mIGUpe2lmKG4odCx0WzBdLnR5cGUpKXJldHVybiEwfXJldHVybiExfWZ1bmN0aW9uIFB0KHQpe2NvbnN0IG49ZyhwKTtyZXR1cm4gbi5lbmNvZGVQb2x5ZmlsbD9uLmVuY29kZVBvbHlmaWxsKHQpOihuZXcgVGV4dEVuY29kZXIpLmVuY29kZSh0KX1mdW5jdGlvbiBEdCh0KXtjb25zdFtuLGVdPXQ7bGV0IHI9SlNPTi5zdHJpbmdpZnkobik7ZnVuY3Rpb24gbyh0KXsic3RyaW5nIj09dHlwZW9mIHI/cj0ic3RyaW5nIj09dHlwZW9mIHQ/cit0OltQdChyKSx0XTpyLnB1c2goInN0cmluZyI9PXR5cGVvZiB0P1B0KHQpOnQpfWZvcihjb25zdCB0IG9mIGUpe2NvbnN0W24sZV09dDtpZihvKGBcbiR7SlNPTi5zdHJpbmdpZnkobil9XG5gKSwic3RyaW5nIj09dHlwZW9mIGV8fGUgaW5zdGFuY2VvZiBVaW50OEFycmF5KW8oZSk7ZWxzZXtsZXQgdDt0cnl7dD1KU09OLnN0cmluZ2lmeShlKX1jYXRjaHt0PUpTT04uc3RyaW5naWZ5KEIoZSkpfW8odCl9fXJldHVybiJzdHJpbmciPT10eXBlb2Ygcj9yOmZ1bmN0aW9uKHQpe2NvbnN0IG49dC5yZWR1Y2UoKHQsbik9PnQrbi5sZW5ndGgsMCksZT1uZXcgVWludDhBcnJheShuKTtsZXQgcj0wO2Zvcihjb25zdCBuIG9mIHQpZS5zZXQobixyKSxyKz1uLmxlbmd0aDtyZXR1cm4gZX0ocil9Y29uc3QgVXQ9e3Nlc3Npb25zOiJzZXNzaW9uIixldmVudDoiZXJyb3IiLGNsaWVudF9yZXBvcnQ6ImludGVybmFsIix1c2VyX3JlcG9ydDoiZGVmYXVsdCIscHJvZmlsZV9jaHVuazoicHJvZmlsZSIscmVwbGF5X2V2ZW50OiJyZXBsYXkiLHJlcGxheV9yZWNvcmRpbmc6InJlcGxheSIsY2hlY2tfaW46Im1vbml0b3IiLHJhd19zZWN1cml0eToic2VjdXJpdHkiLGxvZzoibG9nX2l0ZW0iLHRyYWNlX21ldHJpYzoibWV0cmljIn07ZnVuY3Rpb24gQnQodCl7cmV0dXJuIGZ1bmN0aW9uKHQpe3JldHVybiB0IGluIFV0fSh0KT9VdFt0XTp0fWZ1bmN0aW9uIEx0KHQpe2lmKCF0Py5zZGspcmV0dXJuO2NvbnN0e25hbWU6bix2ZXJzaW9uOmV9PXQuc2RrO3JldHVybntuYW1lOm4sdmVyc2lvbjplfX1mdW5jdGlvbiBNdCh0LG4sZSxyKXtjb25zdCBvPUx0KGUpLGk9dC50eXBlJiYicmVwbGF5X2V2ZW50IiE9PXQudHlwZT90LnR5cGU6ImV2ZW50IjshZnVuY3Rpb24odCxuKXtpZighbilyZXR1cm4gdDtjb25zdCBlPXQuc2RrfHx7fTt0LnNkaz17Li4uZSxuYW1lOmUubmFtZXx8bi5uYW1lLHZlcnNpb246ZS52ZXJzaW9ufHxuLnZlcnNpb24saW50ZWdyYXRpb25zOlsuLi50LnNkaz8uaW50ZWdyYXRpb25zfHxbXSwuLi5uLmludGVncmF0aW9uc3x8W11dLHBhY2thZ2VzOlsuLi50LnNkaz8ucGFja2FnZXN8fFtdLC4uLm4ucGFja2FnZXN8fFtdXSxzZXR0aW5nczp0LnNkaz8uc2V0dGluZ3N8fG4uc2V0dGluZ3M/ey4uLnQuc2RrPy5zZXR0aW5ncywuLi5uLnNldHRpbmdzfTp2b2lkIDB9fSh0LGU/LnNkayk7Y29uc3Qgcz1mdW5jdGlvbih0LG4sZSxyKXtjb25zdCBvPXQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhPy5keW5hbWljU2FtcGxpbmdDb250ZXh0O3JldHVybntldmVudF9pZDp0LmV2ZW50X2lkLHNlbnRfYXQ6bmV3IERhdGUoUCgpKS50b0lTT1N0cmluZygpLC4uLm4mJntzZGs6bn0sLi4uISFlJiZyJiZ7ZHNuOmJ0KHIpfSwuLi5vJiZ7dHJhY2U6b319fSh0LG8scixuKTtkZWxldGUgdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE7cmV0dXJuIFR0KHMsW1t7dHlwZTppfSx0XV0pfWNvbnN0IHp0PSJfX1NFTlRSWV9TVVBQUkVTU19UUkFDSU5HX18iO2Z1bmN0aW9uIEZ0KHQpe2NvbnN0IG49aHQobCgpKTtyZXR1cm4gbi5zdXBwcmVzc1RyYWNpbmc/bi5zdXBwcmVzc1RyYWNpbmcodCk6ZnVuY3Rpb24oLi4udCl7Y29uc3Qgbj1odChsKCkpO2lmKDI9PT10Lmxlbmd0aCl7Y29uc3RbZSxyXT10O3JldHVybiBlP24ud2l0aFNldFNjb3BlKGUscik6bi53aXRoU2NvcGUocil9cmV0dXJuIG4ud2l0aFNjb3BlKHRbMF0pfShuPT57bi5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1t6dF06ITB9KTtjb25zdCBlPXQoKTtyZXR1cm4gbi5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1t6dF06dm9pZCAwfSksZX0pfWZ1bmN0aW9uIEd0KHQsbil7Y29uc3R7ZmluZ2VycHJpbnQ6ZSxzcGFuOnIsYnJlYWRjcnVtYnM6byxzZGtQcm9jZXNzaW5nTWV0YWRhdGE6aX09bjshZnVuY3Rpb24odCxuKXtjb25zdHtleHRyYTplLHRhZ3M6cix1c2VyOm8sY29udGV4dHM6aSxsZXZlbDpzLHRyYW5zYWN0aW9uTmFtZTpjfT1uO09iamVjdC5rZXlzKGUpLmxlbmd0aCYmKHQuZXh0cmE9ey4uLmUsLi4udC5leHRyYX0pO09iamVjdC5rZXlzKHIpLmxlbmd0aCYmKHQudGFncz17Li4uciwuLi50LnRhZ3N9KTtPYmplY3Qua2V5cyhvKS5sZW5ndGgmJih0LnVzZXI9ey4uLm8sLi4udC51c2VyfSk7T2JqZWN0LmtleXMoaSkubGVuZ3RoJiYodC5jb250ZXh0cz17Li4uaSwuLi50LmNvbnRleHRzfSk7cyYmKHQubGV2ZWw9cyk7YyYmInRyYW5zYWN0aW9uIiE9PXQudHlwZSYmKHQudHJhbnNhY3Rpb249Yyl9KHQsbiksciYmZnVuY3Rpb24odCxuKXt0LmNvbnRleHRzPXt0cmFjZTpfdChuKSwuLi50LmNvbnRleHRzfSx0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YT17ZHluYW1pY1NhbXBsaW5nQ29udGV4dDpPdChuKSwuLi50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YX07Y29uc3QgZT1DdChuKSxyPUV0KGUpLmRlc2NyaXB0aW9uO3ImJiF0LnRyYW5zYWN0aW9uJiYidHJhbnNhY3Rpb24iPT09dC50eXBlJiYodC50cmFuc2FjdGlvbj1yKX0odCxyKSxmdW5jdGlvbih0LG4pe3QuZmluZ2VycHJpbnQ9dC5maW5nZXJwcmludD9BcnJheS5pc0FycmF5KHQuZmluZ2VycHJpbnQpP3QuZmluZ2VycHJpbnQ6W3QuZmluZ2VycHJpbnRdOltdLG4mJih0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQuY29uY2F0KG4pKTt0LmZpbmdlcnByaW50Lmxlbmd0aHx8ZGVsZXRlIHQuZmluZ2VycHJpbnR9KHQsZSksZnVuY3Rpb24odCxuKXtjb25zdCBlPVsuLi50LmJyZWFkY3J1bWJzfHxbXSwuLi5uXTt0LmJyZWFkY3J1bWJzPWUubGVuZ3RoP2U6dm9pZCAwfSh0LG8pLGZ1bmN0aW9uKHQsbil7dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9ey4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhLC4uLm59fSh0LGkpfWNsYXNzIEp0e2NvbnN0cnVjdG9yKHQpe3RoaXMuTD0wLHRoaXMuTT1bXSx0aGlzLkYodCl9dGhlbih0LG4pe3JldHVybiBuZXcgSnQoKGUscik9Pnt0aGlzLk0ucHVzaChbITEsbj0+e2lmKHQpdHJ5e2UodChuKSl9Y2F0Y2godCl7cih0KX1lbHNlIGUobil9LHQ9PntpZihuKXRyeXtlKG4odCkpfWNhdGNoKHQpe3IodCl9ZWxzZSByKHQpfV0pLHRoaXMuRygpfSl9Y2F0Y2godCl7cmV0dXJuIHRoaXMudGhlbih0PT50LHQpfWZpbmFsbHkodCl7cmV0dXJuIG5ldyBKdCgobixlKT0+e2xldCByLG87cmV0dXJuIHRoaXMudGhlbihuPT57bz0hMSxyPW4sdCYmdCgpfSxuPT57bz0hMCxyPW4sdCYmdCgpfSkudGhlbigoKT0+e28/ZShyKTpuKHIpfSl9KX1HKCl7aWYoMD09PXRoaXMuTClyZXR1cm47Y29uc3QgdD10aGlzLk0uc2xpY2UoKTt0aGlzLk09W10sdC5mb3JFYWNoKHQ9Pnt0WzBdfHwoMT09PXRoaXMuTCYmdFsxXSh0aGlzLkopLDI9PT10aGlzLkwmJnRbMl0odGhpcy5KKSx0WzBdPSEwKX0pfUYodCl7Y29uc3Qgbj0odCxuKT0+ezA9PT10aGlzLkwmJihqKG4pP24udGhlbihlLHIpOih0aGlzLkw9dCx0aGlzLko9bix0aGlzLkcoKSkpfSxlPXQ9PntuKDEsdCl9LHI9dD0+e24oMix0KX07dHJ5e3QoZSxyKX1jYXRjaCh0KXtyKHQpfX19Y29uc3QgV3Q9U3ltYm9sLmZvcigiU2VudHJ5QnVmZmVyRnVsbEVycm9yIik7ZnVuY3Rpb24gWXQodD0xMDApe2NvbnN0IG49bmV3IFNldDtmdW5jdGlvbiBlKHQpe24uZGVsZXRlKHQpfXJldHVybntnZXQgJCgpe3JldHVybiBBcnJheS5mcm9tKG4pfSxhZGQ6ZnVuY3Rpb24ocil7aWYoIShuLnNpemU8dCkpcmV0dXJuIG89V3QsbmV3IEp0KCh0LG4pPT57bihvKX0pO3ZhciBvO2NvbnN0IGk9cigpO3JldHVybiBuLmFkZChpKSxpLnRoZW4oKCk9PmUoaSksKCk9PmUoaSkpLGl9LGRyYWluOmZ1bmN0aW9uKHQpe2lmKCFuLnNpemUpcmV0dXJuIGU9ITAsbmV3IEp0KHQ9Pnt0KGUpfSk7dmFyIGU7Y29uc3Qgcj1Qcm9taXNlLmFsbFNldHRsZWQoQXJyYXkuZnJvbShuKSkudGhlbigoKT0+ITApO2lmKCF0KXJldHVybiByO2NvbnN0IG89W3IsbmV3IFByb21pc2Uobj0+e3JldHVybiJvYmplY3QiPT10eXBlb2YoZT1zZXRUaW1lb3V0KCgpPT5uKCExKSx0KSkmJiJmdW5jdGlvbiI9PXR5cGVvZiBlLnVucmVmJiZlLnVucmVmKCksZTt2YXIgZX0pXTtyZXR1cm4gUHJvbWlzZS5yYWNlKG8pfX19ZnVuY3Rpb24gSHQodCx7c3RhdHVzQ29kZTpuLGhlYWRlcnM6ZX0scj1QKCkpe2NvbnN0IG89ey4uLnR9LGk9ZT8uWyJ4LXNlbnRyeS1yYXRlLWxpbWl0cyJdLHM9ZT8uWyJyZXRyeS1hZnRlciJdO2lmKGkpZm9yKGNvbnN0IHQgb2YgaS50cmltKCkuc3BsaXQoIiwiKSl7Y29uc3RbbixlLCwsaV09dC5zcGxpdCgiOiIsNSkscz1wYXJzZUludChuLDEwKSxjPTFlMyooaXNOYU4ocyk/NjA6cyk7aWYoZSlmb3IoY29uc3QgdCBvZiBlLnNwbGl0KCI7IikpIm1ldHJpY19idWNrZXQiPT09dCYmaSYmIWkuc3BsaXQoIjsiKS5pbmNsdWRlcygiY3VzdG9tIil8fChvW3RdPXIrYyk7ZWxzZSBvLmFsbD1yK2N9ZWxzZSBzP28uYWxsPXIrZnVuY3Rpb24odCxuPVAoKSl7Y29uc3QgZT1wYXJzZUludChgJHt0fWAsMTApO2lmKCFpc05hTihlKSlyZXR1cm4gMWUzKmU7Y29uc3Qgcj1EYXRlLnBhcnNlKGAke3R9YCk7cmV0dXJuIGlzTmFOKHIpPzZlNDpyLW59KHMscik6NDI5PT09biYmKG8uYWxsPXIrNmU0KTtyZXR1cm4gb31mdW5jdGlvbiBLdCh0LG4sZT1ZdCh0LmJ1ZmZlclNpemV8fDY0KSl7bGV0IHI9e307cmV0dXJue3NlbmQ6ZnVuY3Rpb24odCl7Y29uc3Qgbz1bXTtpZihrdCh0LCh0LG4pPT57Y29uc3QgZT1CdChuKTsoZnVuY3Rpb24odCxuLGU9UCgpKXtyZXR1cm4gZnVuY3Rpb24odCxuKXtyZXR1cm4gdFtuXXx8dC5hbGx8fDB9KHQsbik+ZX0pKHIsZSl8fG8ucHVzaCh0KX0pLDA9PT1vLmxlbmd0aClyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtjb25zdCBpPVR0KHRbMF0sbykscz10PT57IWZ1bmN0aW9uKHQsbil7cmV0dXJuIGt0KHQsKHQsZSk9Pm4uaW5jbHVkZXMoZSkpfShpLFsiY2xpZW50X3JlcG9ydCJdKT9rdChpLCh0LG4pPT57fSk6aCYmdy53YXJuKGBEcm9wcGluZyBjbGllbnQgcmVwb3J0LiBXaWxsIG5vdCBzZW5kIG91dGNvbWVzIChyZWFzb246ICR7dH0pLmApfTtyZXR1cm4gZS5hZGQoKCk9Pm4oe2JvZHk6RHQoaSl9KS50aGVuKHQ9PjQxMz09PXQuc3RhdHVzQ29kZT8oaCYmdy5lcnJvcigiU2VudHJ5IHJlc3BvbmRlZCB3aXRoIHN0YXR1cyBjb2RlIDQxMy4gRW52ZWxvcGUgd2FzIGRpc2NhcmRlZCBkdWUgdG8gZXhjZWVkaW5nIHNpemUgbGltaXRzLiIpLHMoInNlbmRfZXJyb3IiKSx0KTooaCYmdm9pZCAwIT09dC5zdGF0dXNDb2RlJiYodC5zdGF0dXNDb2RlPDIwMHx8dC5zdGF0dXNDb2RlPj0zMDApJiZ3Lndhcm4oYFNlbnRyeSByZXNwb25kZWQgd2l0aCBzdGF0dXMgY29kZSAke3Quc3RhdHVzQ29kZX0gdG8gc2VudCBldmVudC5gKSxyPUh0KHIsdCksdCksdD0+e3Rocm93IHMoIm5ldHdvcmtfZXJyb3IiKSxoJiZ3LmVycm9yKCJFbmNvdW50ZXJlZCBlcnJvciBydW5uaW5nIHRyYW5zcG9ydCByZXF1ZXN0OiIsdCksdH0pKS50aGVuKHQ9PnQsdD0+e2lmKHQ9PT1XdClyZXR1cm4gaCYmdy5lcnJvcigiU2tpcHBlZCBzZW5kaW5nIGV2ZW50IGJlY2F1c2UgYnVmZmVyIGlzIGZ1bGwuIikscygicXVldWVfb3ZlcmZsb3ciKSxQcm9taXNlLnJlc29sdmUoe30pO3Rocm93IHR9KX0sZmx1c2g6dD0+ZS5kcmFpbih0KX19Y29uc3QgWnQ9L14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvO2Z1bmN0aW9uIHF0KHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7Y29uc3Qgbj10Lmxlbmd0aD4xMDI0P2A8dHJ1bmNhdGVkPiR7dC5zbGljZSgtMTAyNCl9YDp0LGU9WnQuZXhlYyhuKTtyZXR1cm4gZT9lLnNsaWNlKDEpOltdfSh0KSxlPW5bMF18fCIiO2xldCByPW5bMV07cmV0dXJuIGV8fHI/KHImJihyPXIuc2xpY2UoMCxyLmxlbmd0aC0xKSksZStyKToiLiJ9ZnVuY3Rpb24gVnQodCxuPSExKXtyZXR1cm4hKG58fHQmJiF0LnN0YXJ0c1dpdGgoIi8iKSYmIXQubWF0Y2goL15bQS1aXTovKSYmIXQuc3RhcnRzV2l0aCgiLiIpJiYhdC5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSkmJnZvaWQgMCE9PXQmJiF0LmluY2x1ZGVzKCJub2RlX21vZHVsZXMvIil9dmFyIFF0O2NvbnN0IFh0PVN5bWJvbCgiQWdlbnRCYXNlSW50ZXJuYWxTdGF0ZSIpO2NsYXNzIHRuIGV4dGVuZHMoUXQ9aS5BZ2VudCxRdCl7Y29uc3RydWN0b3IodCl7c3VwZXIodCksdGhpc1tYdF09e319aXNTZWN1cmVFbmRwb2ludCh0KXtpZih0KXtpZigiYm9vbGVhbiI9PXR5cGVvZiB0LnNlY3VyZUVuZHBvaW50KXJldHVybiB0LnNlY3VyZUVuZHBvaW50O2lmKCJzdHJpbmciPT10eXBlb2YgdC5wcm90b2NvbClyZXR1cm4iaHR0cHM6Ij09PXQucHJvdG9jb2x9Y29uc3R7c3RhY2s6bn09bmV3IEVycm9yO3JldHVybiJzdHJpbmciPT10eXBlb2YgbiYmbi5zcGxpdCgiXG4iKS5zb21lKHQ9Pi0xIT09dC5pbmRleE9mKCIoaHR0cHMuanM6Iil8fC0xIT09dC5pbmRleE9mKCJub2RlOmh0dHBzOiIpKX1jcmVhdGVTb2NrZXQodCxuLGUpe2NvbnN0IHI9ey4uLm4sc2VjdXJlRW5kcG9pbnQ6dGhpcy5pc1NlY3VyZUVuZHBvaW50KG4pfTtQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpPT50aGlzLmNvbm5lY3QodCxyKSkudGhlbihvPT57aWYobyBpbnN0YW5jZW9mIGkuQWdlbnQpcmV0dXJuIG8uYWRkUmVxdWVzdCh0LHIpO3RoaXNbWHRdLmN1cnJlbnRTb2NrZXQ9byxzdXBlci5jcmVhdGVTb2NrZXQodCxuLGUpfSxlKX1jcmVhdGVDb25uZWN0aW9uKCl7Y29uc3QgdD10aGlzW1h0XS5jdXJyZW50U29ja2V0O2lmKHRoaXNbWHRdLmN1cnJlbnRTb2NrZXQ9dm9pZCAwLCF0KXRocm93IG5ldyBFcnJvcigiTm8gc29ja2V0IHdhcyByZXR1cm5lZCBpbiB0aGUgYGNvbm5lY3QoKWAgZnVuY3Rpb24iKTtyZXR1cm4gdH1nZXQgZGVmYXVsdFBvcnQoKXtyZXR1cm4gdGhpc1tYdF0uZGVmYXVsdFBvcnQ/PygiaHR0cHM6Ij09PXRoaXMucHJvdG9jb2w/NDQzOjgwKX1zZXQgZGVmYXVsdFBvcnQodCl7dGhpc1tYdF0mJih0aGlzW1h0XS5kZWZhdWx0UG9ydD10KX1nZXQgcHJvdG9jb2woKXtyZXR1cm4gdGhpc1tYdF0ucHJvdG9jb2w/Pyh0aGlzLmlzU2VjdXJlRW5kcG9pbnQoKT8iaHR0cHM6IjoiaHR0cDoiKX1zZXQgcHJvdG9jb2wodCl7dGhpc1tYdF0mJih0aGlzW1h0XS5wcm90b2NvbD10KX19ZnVuY3Rpb24gbm4oLi4udCl7dy5sb2coIltodHRwcy1wcm94eS1hZ2VudDpwYXJzZS1wcm94eS1yZXNwb25zZV0iLC4uLnQpfWZ1bmN0aW9uIGVuKHQpe3JldHVybiBuZXcgUHJvbWlzZSgobixlKT0+e2xldCByPTA7Y29uc3Qgbz1bXTtmdW5jdGlvbiBpKCl7Y29uc3QgYz10LnJlYWQoKTtjP2Z1bmN0aW9uKGMpe28ucHVzaChjKSxyKz1jLmxlbmd0aDtjb25zdCB1PUJ1ZmZlci5jb25jYXQobyxyKSxhPXUuaW5kZXhPZigiXHJcblxyXG4iKTtpZigtMT09PWEpcmV0dXJuIG5uKCJoYXZlIG5vdCByZWNlaXZlZCBlbmQgb2YgSFRUUCBoZWFkZXJzIHlldC4uLiIpLHZvaWQgaSgpO2NvbnN0IGY9dS5zdWJhcnJheSgwLGEpLnRvU3RyaW5nKCJhc2NpaSIpLnNwbGl0KCJcclxuIiksaD1mLnNoaWZ0KCk7aWYoIWgpcmV0dXJuIHQuZGVzdHJveSgpLGUobmV3IEVycm9yKCJObyBoZWFkZXIgcmVjZWl2ZWQgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlIikpO2NvbnN0IHA9aC5zcGxpdCgiICIpLGQ9KyhwWzFdfHwwKSxsPXAuc2xpY2UoMikuam9pbigiICIpLGc9e307Zm9yKGNvbnN0IG4gb2YgZil7aWYoIW4pY29udGludWU7Y29uc3Qgcj1uLmluZGV4T2YoIjoiKTtpZigtMT09PXIpcmV0dXJuIHQuZGVzdHJveSgpLGUobmV3IEVycm9yKGBJbnZhbGlkIGhlYWRlciBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2U6ICIke259ImApKTtjb25zdCBvPW4uc2xpY2UoMCxyKS50b0xvd2VyQ2FzZSgpLGk9bi5zbGljZShyKzEpLnRyaW1TdGFydCgpLHM9Z1tvXTsic3RyaW5nIj09dHlwZW9mIHM/Z1tvXT1bcyxpXTpBcnJheS5pc0FycmF5KHMpP3MucHVzaChpKTpnW29dPWl9bm4oImdvdCBwcm94eSBzZXJ2ZXIgcmVzcG9uc2U6ICVvICVvIixoLGcpLHMoKSxuKHtjb25uZWN0OntzdGF0dXNDb2RlOmQsc3RhdHVzVGV4dDpsLGhlYWRlcnM6Z30sYnVmZmVyZWQ6dX0pfShjKTp0Lm9uY2UoInJlYWRhYmxlIixpKX1mdW5jdGlvbiBzKCl7dC5yZW1vdmVMaXN0ZW5lcigiZW5kIixjKSx0LnJlbW92ZUxpc3RlbmVyKCJlcnJvciIsdSksdC5yZW1vdmVMaXN0ZW5lcigicmVhZGFibGUiLGkpfWZ1bmN0aW9uIGMoKXtzKCksbm4oIm9uZW5kIiksZShuZXcgRXJyb3IoIlByb3h5IGNvbm5lY3Rpb24gZW5kZWQgYmVmb3JlIHJlY2VpdmluZyBDT05ORUNUIHJlc3BvbnNlIikpfWZ1bmN0aW9uIHUodCl7cygpLG5uKCJvbmVycm9yICVvIix0KSxlKHQpfXQub24oImVycm9yIix1KSx0Lm9uKCJlbmQiLGMpLGkoKX0pfWZ1bmN0aW9uIHJuKC4uLnQpe3cubG9nKCJbaHR0cHMtcHJveHktYWdlbnRdIiwuLi50KX1jbGFzcyBvbiBleHRlbmRzIHRue2NvbnN0cnVjdG9yKHQsbil7c3VwZXIobiksdGhpcy5vcHRpb25zPXt9LHRoaXMucHJveHk9InN0cmluZyI9PXR5cGVvZiB0P25ldyBVUkwodCk6dCx0aGlzLnByb3h5SGVhZGVycz1uPy5oZWFkZXJzPz97fSxybigiQ3JlYXRpbmcgbmV3IEh0dHBzUHJveHlBZ2VudCBpbnN0YW5jZTogJW8iLHRoaXMucHJveHkuaHJlZik7Y29uc3QgZT0odGhpcy5wcm94eS5ob3N0bmFtZXx8dGhpcy5wcm94eS5ob3N0KS5yZXBsYWNlKC9eXFt8XF0kL2csIiIpLHI9dGhpcy5wcm94eS5wb3J0P3BhcnNlSW50KHRoaXMucHJveHkucG9ydCwxMCk6Imh0dHBzOiI9PT10aGlzLnByb3h5LnByb3RvY29sPzQ0Mzo4MDt0aGlzLmNvbm5lY3RPcHRzPXtBTFBOUHJvdG9jb2xzOlsiaHR0cC8xLjEiXSwuLi5uP2NuKG4sImhlYWRlcnMiKTpudWxsLGhvc3Q6ZSxwb3J0OnJ9fWFzeW5jIGNvbm5lY3QodCxuKXtjb25zdHtwcm94eTplfT10aGlzO2lmKCFuLmhvc3QpdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gImhvc3QiIHByb3ZpZGVkJyk7bGV0IHI7aWYoImh0dHBzOiI9PT1lLnByb3RvY29sKXtybigiQ3JlYXRpbmcgYHRscy5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cyk7Y29uc3QgdD10aGlzLmNvbm5lY3RPcHRzLnNlcnZlcm5hbWV8fHRoaXMuY29ubmVjdE9wdHMuaG9zdDtyPWYuY29ubmVjdCh7Li4udGhpcy5jb25uZWN0T3B0cyxzZXJ2ZXJuYW1lOnQmJmEuaXNJUCh0KT92b2lkIDA6dH0pfWVsc2Ugcm4oIkNyZWF0aW5nIGBuZXQuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpLHI9YS5jb25uZWN0KHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IG89ImZ1bmN0aW9uIj09dHlwZW9mIHRoaXMucHJveHlIZWFkZXJzP3RoaXMucHJveHlIZWFkZXJzKCk6ey4uLnRoaXMucHJveHlIZWFkZXJzfSxpPWEuaXNJUHY2KG4uaG9zdCk/YFske24uaG9zdH1dYDpuLmhvc3Q7bGV0IHM9YENPTk5FQ1QgJHtpfToke24ucG9ydH0gSFRUUC8xLjFcclxuYDtpZihlLnVzZXJuYW1lfHxlLnBhc3N3b3JkKXtjb25zdCB0PWAke2RlY29kZVVSSUNvbXBvbmVudChlLnVzZXJuYW1lKX06JHtkZWNvZGVVUklDb21wb25lbnQoZS5wYXNzd29yZCl9YDtvWyJQcm94eS1BdXRob3JpemF0aW9uIl09YEJhc2ljICR7QnVmZmVyLmZyb20odCkudG9TdHJpbmcoImJhc2U2NCIpfWB9by5Ib3N0PWAke2l9OiR7bi5wb3J0fWAsb1siUHJveHktQ29ubmVjdGlvbiJdfHwob1siUHJveHktQ29ubmVjdGlvbiJdPXRoaXMua2VlcEFsaXZlPyJLZWVwLUFsaXZlIjoiY2xvc2UiKTtmb3IoY29uc3QgdCBvZiBPYmplY3Qua2V5cyhvKSlzKz1gJHt0fTogJHtvW3RdfVxyXG5gO2NvbnN0IGM9ZW4ocik7ci53cml0ZShgJHtzfVxyXG5gKTtjb25zdHtjb25uZWN0OnUsYnVmZmVyZWQ6aH09YXdhaXQgYztpZih0LmVtaXQoInByb3h5Q29ubmVjdCIsdSksdGhpcy5lbWl0KCJwcm94eUNvbm5lY3QiLHUsdCksMjAwPT09dS5zdGF0dXNDb2RlKXtpZih0Lm9uY2UoInNvY2tldCIsc24pLG4uc2VjdXJlRW5kcG9pbnQpe3JuKCJVcGdyYWRpbmcgc29ja2V0IGNvbm5lY3Rpb24gdG8gVExTIik7Y29uc3QgdD1uLnNlcnZlcm5hbWV8fG4uaG9zdDtyZXR1cm4gZi5jb25uZWN0KHsuLi5jbihuLCJob3N0IiwicGF0aCIsInBvcnQiKSxzb2NrZXQ6cixzZXJ2ZXJuYW1lOmEuaXNJUCh0KT92b2lkIDA6dH0pfXJldHVybiByfXIuZGVzdHJveSgpO2NvbnN0IHA9bmV3IGEuU29ja2V0KHt3cml0YWJsZTohMX0pO3JldHVybiBwLnJlYWRhYmxlPSEwLHQub25jZSgic29ja2V0Iix0PT57cm4oIlJlcGxheWluZyBwcm94eSBidWZmZXIgZm9yIGZhaWxlZCByZXF1ZXN0IiksdC5wdXNoKGgpLHQucHVzaChudWxsKX0pLHB9fWZ1bmN0aW9uIHNuKHQpe3QucmVzdW1lKCl9ZnVuY3Rpb24gY24odCwuLi5uKXtjb25zdCBlPXt9O2xldCByO2ZvcihyIGluIHQpbi5pbmNsdWRlcyhyKXx8KGVbcl09dFtyXSk7cmV0dXJuIGV9b24ucHJvdG9jb2xzPVsiaHR0cCIsImh0dHBzIl07ZnVuY3Rpb24gdW4odCl7cmV0dXJuIHQucmVwbGFjZSgvXltBLVpdOi8sIiIpLnJlcGxhY2UoL1xcL2csIi8iKX1jb25zdCBhbj1uO2xldCBmbixobj0wLHBuPXt9O2Z1bmN0aW9uIGRuKHQpe2FuLmRlYnVnJiZjb25zb2xlLmxvZyhgW0FOUiBXb3JrZXJdICR7dH1gKX12YXIgbG4sZ24sbW47Y29uc3QgeW49ZnVuY3Rpb24odCl7bGV0IG47dHJ5e249bmV3IFVSTCh0LnVybCl9Y2F0Y2gobil7cmV0dXJuIGIoKCk9Pntjb25zb2xlLndhcm4oIltAc2VudHJ5L25vZGVdOiBJbnZhbGlkIGRzbiBvciB0dW5uZWwgb3B0aW9uLCB3aWxsIG5vdCBzZW5kIGFueSBldmVudHMuIFRoZSB0dW5uZWwgb3B0aW9uIG11c3QgYmUgYSBmdWxsIFVSTCB3aGVuIHVzZWQuIil9KSxLdCh0LCgpPT5Qcm9taXNlLnJlc29sdmUoe30pKX1jb25zdCBlPSJodHRwczoiPT09bi5wcm90b2NvbCxyPWZ1bmN0aW9uKHQsbil7Y29uc3R7bm9fcHJveHk6ZX09cHJvY2Vzcy5lbnYscj1lPy5zcGxpdCgiLCIpLnNvbWUobj0+dC5ob3N0LmVuZHNXaXRoKG4pfHx0Lmhvc3RuYW1lLmVuZHNXaXRoKG4pKTtyZXR1cm4gcj92b2lkIDA6bn0obix0LnByb3h5fHwoZT9wcm9jZXNzLmVudi5odHRwc19wcm94eTp2b2lkIDApfHxwcm9jZXNzLmVudi5odHRwX3Byb3h5KSxvPWU/czppLGE9dm9pZCAwIT09dC5rZWVwQWxpdmUmJnQua2VlcEFsaXZlLGY9cj9uZXcgb24ocik6bmV3IG8uQWdlbnQoe2tlZXBBbGl2ZTphLG1heFNvY2tldHM6MzAsdGltZW91dDoyZTN9KSxoPWZ1bmN0aW9uKHQsbixlKXtjb25zdHtob3N0bmFtZTpyLHBhdGhuYW1lOm8scG9ydDppLHByb3RvY29sOnMsc2VhcmNoOmF9PW5ldyBVUkwodC51cmwpO3JldHVybiBmdW5jdGlvbihmKXtyZXR1cm4gbmV3IFByb21pc2UoKGgscCk9PntGdCgoKT0+e2xldCBkPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgYyh7cmVhZCgpe3RoaXMucHVzaCh0KSx0aGlzLnB1c2gobnVsbCl9fSl9KGYuYm9keSk7Y29uc3QgbD17Li4udC5oZWFkZXJzfTtmLmJvZHkubGVuZ3RoPjMyNzY4JiYobFsiY29udGVudC1lbmNvZGluZyJdPSJnemlwIixkPWQucGlwZSh1KCkpKTtjb25zdCBnPXIuc3RhcnRzV2l0aCgiWyIpLG09bi5yZXF1ZXN0KHttZXRob2Q6IlBPU1QiLGFnZW50OmUsaGVhZGVyczpsLGhvc3RuYW1lOmc/ci5zbGljZSgxLC0xKTpyLHBhdGg6YCR7b30ke2F9YCxwb3J0OmkscHJvdG9jb2w6cyxjYTp0LmNhQ2VydHN9LHQ9Pnt0Lm9uKCJkYXRhIiwoKT0+e30pLHQub24oImVuZCIsKCk9Pnt9KSx0LnNldEVuY29kaW5nKCJ1dGY4Iik7Y29uc3Qgbj10LmhlYWRlcnNbInJldHJ5LWFmdGVyIl0/P251bGwsZT10LmhlYWRlcnNbIngtc2VudHJ5LXJhdGUtbGltaXRzIl0/P251bGw7aCh7c3RhdHVzQ29kZTp0LnN0YXR1c0NvZGUsaGVhZGVyczp7InJldHJ5LWFmdGVyIjpuLCJ4LXNlbnRyeS1yYXRlLWxpbWl0cyI6QXJyYXkuaXNBcnJheShlKT9lWzBdfHxudWxsOmV9fSl9KTttLm9uKCJlcnJvciIscCksZC5waXBlKG0pfSl9KX19KHQsdC5odHRwTW9kdWxlPz9vLGYpO3JldHVybiBLdCh0LGgpfSh7dXJsOihsbj1hbi5kc24sZ249YW4udHVubmVsLG1uPWFuLnNka01ldGFkYXRhLnNkayxnbnx8YCR7ZnVuY3Rpb24odCl7cmV0dXJuYCR7ZnVuY3Rpb24odCl7Y29uc3Qgbj10LnByb3RvY29sP2Ake3QucHJvdG9jb2x9OmA6IiIsZT10LnBvcnQ/YDoke3QucG9ydH1gOiIiO3JldHVybmAke259Ly8ke3QuaG9zdH0ke2V9JHt0LnBhdGg/YC8ke3QucGF0aH1gOiIifS9hcGkvYH0odCl9JHt0LnByb2plY3RJZH0vZW52ZWxvcGUvYH0obG4pfT8ke2Z1bmN0aW9uKHQsbil7Y29uc3QgZT17c2VudHJ5X3ZlcnNpb246IjcifTtyZXR1cm4gdC5wdWJsaWNLZXkmJihlLnNlbnRyeV9rZXk9dC5wdWJsaWNLZXkpLG4mJihlLnNlbnRyeV9jbGllbnQ9YCR7bi5uYW1lfS8ke24udmVyc2lvbn1gKSxuZXcgVVJMU2VhcmNoUGFyYW1zKGUpLnRvU3RyaW5nKCl9KGxuLG1uKX1gKX0pO2FzeW5jIGZ1bmN0aW9uIGJuKCl7aWYoZm4pe2RuKCJTZW5kaW5nIGFibm9ybWFsIHNlc3Npb24iKSxLKGZuLHtzdGF0dXM6ImFibm9ybWFsIixhYm5vcm1hbF9tZWNoYW5pc206ImFucl9mb3JlZ3JvdW5kIixyZWxlYXNlOmFuLnJlbGVhc2UsZW52aXJvbm1lbnQ6YW4uZW52aXJvbm1lbnR9KTtjb25zdCB0PWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89THQoZSk7cmV0dXJuIFR0KHtzZW50X2F0Om5ldyBEYXRlKFAoKSkudG9JU09TdHJpbmcoKSwuLi5vJiZ7c2RrOm99LC4uLiEhciYmbiYme2RzbjpidChuKX19LFsiYWdncmVnYXRlcyJpbiB0P1t7dHlwZToic2Vzc2lvbnMifSx0XTpbe3R5cGU6InNlc3Npb24ifSx0LnRvSlNPTigpXV0pfShmbixhbi5kc24sYW4uc2RrTWV0YWRhdGEsYW4udHVubmVsKTtkbihKU09OLnN0cmluZ2lmeSh0KSksYXdhaXQgeW4uc2VuZCh0KTt0cnl7ZT8ucG9zdE1lc3NhZ2UoInNlc3Npb24tZW5kZWQiKX1jYXRjaHt9fX1mdW5jdGlvbiB2bih0KXtpZighdClyZXR1cm47Y29uc3Qgbj1mdW5jdGlvbih0KXtpZighdC5sZW5ndGgpcmV0dXJuW107Y29uc3Qgbj1BcnJheS5mcm9tKHQpO3JldHVybi9zZW50cnlXcmFwcGVkLy50ZXN0KEUobikuZnVuY3Rpb258fCIiKSYmbi5wb3AoKSxuLnJldmVyc2UoKSwkLnRlc3QoRShuKS5mdW5jdGlvbnx8IiIpJiYobi5wb3AoKSwkLnRlc3QoRShuKS5mdW5jdGlvbnx8IiIpJiZuLnBvcCgpKSxuLnNsaWNlKDAsNTApLm1hcCh0PT4oey4uLnQsZmlsZW5hbWU6dC5maWxlbmFtZXx8RShuKS5maWxlbmFtZSxmdW5jdGlvbjp0LmZ1bmN0aW9ufHwiPyJ9KSl9KHQpO2lmKGFuLmFwcFJvb3RQYXRoKWZvcihjb25zdCB0IG9mIG4pdC5maWxlbmFtZSYmKHQuZmlsZW5hbWU9TSh0LmZpbGVuYW1lLGFuLmFwcFJvb3RQYXRoKSk7cmV0dXJuIG59YXN5bmMgZnVuY3Rpb24gX24odCxuKXtpZihobj49YW4ubWF4QW5yRXZlbnRzKXJldHVybjtobis9MSxhd2FpdCBibigpLGRuKCJTZW5kaW5nIGV2ZW50Iik7Y29uc3QgZT17ZXZlbnRfaWQ6RygpLGNvbnRleHRzOmFuLmNvbnRleHRzLHJlbGVhc2U6YW4ucmVsZWFzZSxlbnZpcm9ubWVudDphbi5lbnZpcm9ubWVudCxkaXN0OmFuLmRpc3QscGxhdGZvcm06Im5vZGUiLGxldmVsOiJlcnJvciIsZXhjZXB0aW9uOnt2YWx1ZXM6W3t0eXBlOiJBcHBsaWNhdGlvbk5vdFJlc3BvbmRpbmciLHZhbHVlOmBBcHBsaWNhdGlvbiBOb3QgUmVzcG9uZGluZyBmb3IgYXQgbGVhc3QgJHthbi5hbnJUaHJlc2hvbGR9IG1zYCxzdGFja3RyYWNlOntmcmFtZXM6dm4odCl9LG1lY2hhbmlzbTp7dHlwZToiQU5SIn19XX0sdGFnczphbi5zdGF0aWNUYWdzfTtuJiZmdW5jdGlvbih0LG4pe2lmKEd0KHQsbiksIXQuY29udGV4dHM/LnRyYWNlKXtjb25zdHt0cmFjZUlkOmUscGFyZW50U3BhbklkOnIscHJvcGFnYXRpb25TcGFuSWQ6b309bi5wcm9wYWdhdGlvbkNvbnRleHQ7dC5jb250ZXh0cz17dHJhY2U6e3RyYWNlX2lkOmUsc3Bhbl9pZDpvfHxWKCkscGFyZW50X3NwYW5faWQ6cn0sLi4udC5jb250ZXh0c319fShlLG4pLGZ1bmN0aW9uKHQpe2lmKDA9PT1PYmplY3Qua2V5cyhwbikubGVuZ3RoKXJldHVybjtjb25zdCBuPWFuLmFwcFJvb3RQYXRoP3t9OnBuO2lmKGFuLmFwcFJvb3RQYXRoKWZvcihjb25zdFt0LGVdb2YgT2JqZWN0LmVudHJpZXMocG4pKW5bTSh0LGFuLmFwcFJvb3RQYXRoKV09ZTtjb25zdCBlPW5ldyBNYXA7Zm9yKGNvbnN0IHIgb2YgdC5leGNlcHRpb24/LnZhbHVlc3x8W10pZm9yKGNvbnN0IHQgb2Ygci5zdGFja3RyYWNlPy5mcmFtZXN8fFtdKXtjb25zdCByPXQuYWJzX3BhdGh8fHQuZmlsZW5hbWU7ciYmbltyXSYmZS5zZXQocixuW3JdKX1pZihlLnNpemU+MCl7Y29uc3Qgbj1bXTtmb3IoY29uc3RbdCxyXW9mIGUuZW50cmllcygpKW4ucHVzaCh7dHlwZToic291cmNlbWFwIixjb2RlX2ZpbGU6dCxkZWJ1Z19pZDpyfSk7dC5kZWJ1Z19tZXRhPXtpbWFnZXM6bn19fShlKTtjb25zdCByPU10KGUsYW4uZHNuLGFuLnNka01ldGFkYXRhLGFuLnR1bm5lbCk7ZG4oSlNPTi5zdHJpbmdpZnkocikpLGF3YWl0IHluLnNlbmQociksYXdhaXQgeW4uZmx1c2goMmUzKSxobj49YW4ubWF4QW5yRXZlbnRzJiZzZXRUaW1lb3V0KCgpPT57cHJvY2Vzcy5leGl0KDApfSw1ZTMpfWxldCBTbjtpZihkbigiU3RhcnRlZCIpLGFuLmNhcHR1cmVTdGFja1RyYWNlKXtkbigiQ29ubmVjdGluZyB0byBkZWJ1Z2dlciIpO2NvbnN0IG49bmV3IHQ7bi5jb25uZWN0VG9NYWluVGhyZWFkKCksZG4oIkNvbm5lY3RlZCB0byBkZWJ1Z2dlciIpO2NvbnN0IGU9bmV3IE1hcDtuLm9uKCJEZWJ1Z2dlci5zY3JpcHRQYXJzZWQiLHQ9PntlLnNldCh0LnBhcmFtcy5zY3JpcHRJZCx0LnBhcmFtcy51cmwpfSksbi5vbigiRGVidWdnZXIucGF1c2VkIix0PT57aWYoIm90aGVyIj09PXQucGFyYW1zLnJlYXNvbil0cnl7ZG4oIkRlYnVnZ2VyIHBhdXNlZCIpO2NvbnN0IGk9Wy4uLnQucGFyYW1zLmNhbGxGcmFtZXNdLHM9YW4uYXBwUm9vdFBhdGg/ZnVuY3Rpb24odD0ocHJvY2Vzcy5hcmd2WzFdP3F0KHByb2Nlc3MuYXJndlsxXSk6cHJvY2Vzcy5jd2QoKSksbj0iXFwiPT09byl7Y29uc3QgZT1uP3VuKHQpOnQ7cmV0dXJuIHQ9PntpZighdClyZXR1cm47Y29uc3Qgbz1uP3VuKHQpOnQ7bGV0e2RpcjppLGJhc2U6cyxleHQ6Y309ci5wYXJzZShvKTsiLmpzIiE9PWMmJiIubWpzIiE9PWMmJiIuY2pzIiE9PWN8fChzPXMuc2xpY2UoMCwtMSpjLmxlbmd0aCkpO2NvbnN0IHU9ZGVjb2RlVVJJQ29tcG9uZW50KHMpO2l8fChpPSIuIik7Y29uc3QgYT1pLmxhc3RJbmRleE9mKCIvbm9kZV9tb2R1bGVzIik7aWYoYT4tMSlyZXR1cm5gJHtpLnNsaWNlKGErMTQpLnJlcGxhY2UoL1wvL2csIi4iKX06JHt1fWA7aWYoaS5zdGFydHNXaXRoKGUpKXtjb25zdCB0PWkuc2xpY2UoZS5sZW5ndGgrMSkucmVwbGFjZSgvXC8vZywiLiIpO3JldHVybiB0P2Ake3R9OiR7dX1gOnV9cmV0dXJuIHV9fShhbi5hcHBSb290UGF0aCk6KCk9Pnt9LGM9aS5tYXAodD0+ZnVuY3Rpb24odCxuLGUpe2NvbnN0IHI9bj9uLnJlcGxhY2UoL15maWxlOlwvXC8vLCIiKTp2b2lkIDAsbz10LmxvY2F0aW9uLmNvbHVtbk51bWJlcj90LmxvY2F0aW9uLmNvbHVtbk51bWJlcisxOnZvaWQgMCxpPXQubG9jYXRpb24ubGluZU51bWJlcj90LmxvY2F0aW9uLmxpbmVOdW1iZXIrMTp2b2lkIDA7cmV0dXJue2ZpbGVuYW1lOnIsbW9kdWxlOmUociksZnVuY3Rpb246dC5mdW5jdGlvbk5hbWV8fCI/Iixjb2xubzpvLGxpbmVubzppLGluX2FwcDpyP1Z0KHIpOnZvaWQgMH19KHQsZS5nZXQodC5sb2NhdGlvbi5zY3JpcHRJZCkscykpLHU9c2V0VGltZW91dCgoKT0+e19uKGMpLnRoZW4obnVsbCwoKT0+e2RuKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuIil9KX0sNWUzKTtuLnBvc3QoIlJ1bnRpbWUuZXZhbHVhdGUiLHtleHByZXNzaW9uOiJnbG9iYWwuX19TRU5UUllfR0VUX1NDT1BFU19fKCk7IixzaWxlbnQ6ITAscmV0dXJuQnlWYWx1ZTohMH0sKHQsZSk9Pnt0JiZkbihgRXJyb3IgZXhlY3V0aW5nIHNjcmlwdDogJyR7dC5tZXNzYWdlfSdgKSxjbGVhclRpbWVvdXQodSk7Y29uc3Qgcj1lPy5yZXN1bHQ/ZS5yZXN1bHQudmFsdWU6dm9pZCAwO24ucG9zdCgiRGVidWdnZXIucmVzdW1lIiksbi5wb3N0KCJEZWJ1Z2dlci5kaXNhYmxlIiksX24oYyxyKS50aGVuKG51bGwsKCk9PntkbigiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSl9KX1jYXRjaCh0KXt0aHJvdyBuLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLG4ucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLHR9fSksU249KCk9Pnt0cnl7bi5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiLCgpPT57bi5wb3N0KCJEZWJ1Z2dlci5wYXVzZSIpfSl9Y2F0Y2h7fX19Y29uc3R7cG9sbDp3bn09ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz10KCk7bGV0IGk9ITEscz0hMDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCk9Pntjb25zdCB0PW8uZ2V0VGltZU1zKCk7ITE9PT1pJiZ0Pm4rZSYmKGk9ITAscyYmcigpKSx0PG4rZSYmKGk9ITEpfSwyMCkse3BvbGw6KCk9PntvLnJlc2V0KCl9LGVuYWJsZWQ6dD0+e3M9dH19fShmdW5jdGlvbigpe2xldCB0PXByb2Nlc3MuaHJ0aW1lKCk7cmV0dXJue2dldFRpbWVNczooKT0+e2NvbnN0W24sZV09cHJvY2Vzcy5ocnRpbWUodCk7cmV0dXJuIE1hdGguZmxvb3IoMWUzKm4rZS8xZTYpfSxyZXNldDooKT0+e3Q9cHJvY2Vzcy5ocnRpbWUoKX19fSxhbi5wb2xsSW50ZXJ2YWwsYW4uYW5yVGhyZXNob2xkLGZ1bmN0aW9uKCl7ZG4oIldhdGNoZG9nIHRpbWVvdXQiKSxTbj8oZG4oIlBhdXNpbmcgZGVidWdnZXIgdG8gY2FwdHVyZSBzdGFjayB0cmFjZSIpLFNuKCkpOihkbigiQ2FwdHVyaW5nIGV2ZW50IHdpdGhvdXQgYSBzdGFjayB0cmFjZSIpLF9uKCkudGhlbihudWxsLCgpPT57ZG4oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZCBvbiB3YXRjaGRvZyB0aW1lb3V0LiIpfSkpfSk7ZT8ub24oIm1lc3NhZ2UiLHQ9Pnt0LnNlc3Npb24mJihmbj1IKHQuc2Vzc2lvbikpLHQuZGVidWdJbWFnZXMmJihwbj10LmRlYnVnSW1hZ2VzKSx3bigpfSk7"; | ||
| const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZS1jb3JlIDEwLjY0LjAgKDU3MzZhMzgpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyB0fWZyb20ibm9kZTppbnNwZWN0b3IiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIG4scGFyZW50UG9ydCBhcyBlfWZyb20ibm9kZTp3b3JrZXJfdGhyZWFkcyI7aW1wb3J0e3Bvc2l4IGFzIHIsc2VwIGFzIG99ZnJvbSJub2RlOnBhdGgiO2ltcG9ydCphcyBpIGZyb20ibm9kZTpodHRwIjtpbXBvcnQqYXMgcyBmcm9tIm5vZGU6aHR0cHMiO2ltcG9ydHtSZWFkYWJsZSBhcyBjfWZyb20ibm9kZTpzdHJlYW0iO2ltcG9ydHtjcmVhdGVHemlwIGFzIHV9ZnJvbSJub2RlOnpsaWIiO2ltcG9ydCphcyBhIGZyb20ibm9kZTpuZXQiO2ltcG9ydCphcyBmIGZyb20ibm9kZTp0bHMiO2NvbnN0IGg9InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fLHA9Z2xvYmFsVGhpcyxkPSIxMC42NC4wIjtmdW5jdGlvbiBsKCl7cmV0dXJuIGcocCkscH1mdW5jdGlvbiBnKHQpe2NvbnN0IG49dC5fX1NFTlRSWV9fPXQuX19TRU5UUllfX3x8e307cmV0dXJuIG4udmVyc2lvbj1uLnZlcnNpb258fGQsbltkXT1uW2RdfHx7fX1mdW5jdGlvbiBtKHQsbixlPXApe2NvbnN0IHI9ZS5fX1NFTlRSWV9fPWUuX19TRU5UUllfX3x8e30sbz1yW2RdPXJbZF18fHt9O3JldHVybiBvW3RdfHwob1t0XT1uKCkpfWNvbnN0IHk9e307ZnVuY3Rpb24gYih0KXtpZighKCJjb25zb2xlImluIHApKXJldHVybiB0KCk7Y29uc3Qgbj1wLmNvbnNvbGUsZT17fSxyPU9iamVjdC5rZXlzKHkpO3IuZm9yRWFjaCh0PT57Y29uc3Qgcj15W3RdO2VbdF09blt0XSxuW3RdPXJ9KTt0cnl7cmV0dXJuIHQoKX1maW5hbGx5e3IuZm9yRWFjaCh0PT57blt0XT1lW3RdfSl9fWZ1bmN0aW9uIHYoKXtyZXR1cm4gUygpLmVuYWJsZWR9ZnVuY3Rpb24gXyh0LC4uLm4pe2gmJnYoKSYmYigoKT0+e3AuY29uc29sZVt0XShgU2VudHJ5IExvZ2dlciBbJHt0fV06YCwuLi5uKX0pfWZ1bmN0aW9uIFMoKXtyZXR1cm4gaD9tKCJsb2dnZXJTZXR0aW5ncyIsKCk9Pih7ZW5hYmxlZDohMX0pKTp7ZW5hYmxlZDohMX19Y29uc3Qgdz17ZW5hYmxlOmZ1bmN0aW9uKCl7UygpLmVuYWJsZWQ9ITB9LGRpc2FibGU6ZnVuY3Rpb24oKXtTKCkuZW5hYmxlZD0hMX0saXNFbmFibGVkOnYsbG9nOmZ1bmN0aW9uKC4uLnQpe18oImxvZyIsLi4udCl9LHdhcm46ZnVuY3Rpb24oLi4udCl7Xygid2FybiIsLi4udCl9LGVycm9yOmZ1bmN0aW9uKC4uLnQpe18oImVycm9yIiwuLi50KX19LCQ9L2NhcHR1cmVNZXNzYWdlfGNhcHR1cmVFeGNlcHRpb24vO2Z1bmN0aW9uIEUodCl7cmV0dXJuIHRbdC5sZW5ndGgtMV18fHt9fWNvbnN0IHg9Ijxhbm9ueW1vdXM+Ijtjb25zdCBOPU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7ZnVuY3Rpb24gQyh0LG4pe3JldHVybiBOLmNhbGwodCk9PT1gW29iamVjdCAke259XWB9ZnVuY3Rpb24gaih0KXtyZXR1cm4gQm9vbGVhbih0Py50aGVuJiYiZnVuY3Rpb24iPT10eXBlb2YgdC50aGVuKX1mdW5jdGlvbiBSKHQsbil7dHJ5e3JldHVybiB0IGluc3RhbmNlb2Ygbn1jYXRjaHtyZXR1cm4hMX19ZnVuY3Rpb24gQSh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2goTi5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBXZWJBc3NlbWJseS5FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBSKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uSSh0KX07aWYobj10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJlIobixFdmVudCkpe2NvbnN0e3R5cGU6bix0YXJnZXQ6ZSxjdXJyZW50VGFyZ2V0OnIsZGV0YWlsOm99PXQ7cmV0dXJue3R5cGU6bix0YXJnZXQ6ZSxjdXJyZW50VGFyZ2V0OnIsLi4ubz97ZGV0YWlsOm99Ont9LC4uLkkodCl9fXZhciBuO3JldHVybiB0fWZ1bmN0aW9uIEkodCl7cmV0dXJuIm9iamVjdCI9PXR5cGVvZiB0JiZudWxsIT09dD9PYmplY3QuZnJvbUVudHJpZXMoT2JqZWN0LmVudHJpZXModCkpOnt9fWxldCBPO2Z1bmN0aW9uIFQodCl7aWYodm9pZCAwIT09TylyZXR1cm4gTz9PKHQpOnQoKTtjb25zdCBuPVN5bWJvbC5mb3IoIl9fU0VOVFJZX1NBRkVfUkFORE9NX0lEX1dSQVBQRVJfXyIpLGU9cDtyZXR1cm4gbiBpbiBlJiYiZnVuY3Rpb24iPT10eXBlb2YgZVtuXT8oTz1lW25dLE8odCkpOihPPW51bGwsdCgpKX1mdW5jdGlvbiBrKCl7cmV0dXJuIFQoKCk9Pk1hdGgucmFuZG9tKCkpfWZ1bmN0aW9uIFAoKXtyZXR1cm4gVCgoKT0+RGF0ZS5ub3coKSl9Y29uc3QgRD1TeW1ib2wuZm9yKCJzZW50cnkuc2tpcE5vcm1hbGl6YXRpb24iKSxVPVN5bWJvbC5mb3IoInNlbnRyeS5vdmVycmlkZU5vcm1hbGl6YXRpb25EZXB0aCIpO2Z1bmN0aW9uIEIodCxuPTEwMCxlPTEvMCl7dHJ5e3JldHVybiBMKCIiLHQsbixlKX1jYXRjaCh0KXtyZXR1cm57RVJST1I6YCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke3R9KWB9fX1mdW5jdGlvbiBMKHQsbixlPTEvMCxyPTEvMCxvPWZ1bmN0aW9uKCl7Y29uc3QgdD1uZXcgV2Vha1NldDtmdW5jdGlvbiBuKG4pe3JldHVybiEhdC5oYXMobil8fCh0LmFkZChuKSwhMSl9ZnVuY3Rpb24gZShuKXt0LmRlbGV0ZShuKX1yZXR1cm5bbixlXX0oKSl7Y29uc3RbaSxzXT1vO2lmKG51bGw9PW58fFsiYm9vbGVhbiIsInN0cmluZyJdLmluY2x1ZGVzKHR5cGVvZiBuKXx8Im51bWJlciI9PXR5cGVvZiBuJiZOdW1iZXIuaXNGaW5pdGUobikpcmV0dXJuIG47Y29uc3QgYz1mdW5jdGlvbih0LG4pe3RyeXtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGdsb2JhbCYmbj09PWdsb2JhbClyZXR1cm4iW0dsb2JhbF0iO2lmKCJudW1iZXIiPT10eXBlb2YgbiYmIU51bWJlci5pc0Zpbml0ZShuKSlyZXR1cm5gWyR7bn1dYDtpZigiZnVuY3Rpb24iPT10eXBlb2YgbilyZXR1cm5gW0Z1bmN0aW9uOiAke2Z1bmN0aW9uKHQpe3RyeXtyZXR1cm4gdCYmImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQubmFtZXx8eH1jYXRjaHtyZXR1cm4geH19KG4pfV1gO2lmKCJzeW1ib2wiPT10eXBlb2YgbilyZXR1cm5gWyR7U3RyaW5nKG4pfV1gO2lmKCJiaWdpbnQiPT10eXBlb2YgbilyZXR1cm5gW0JpZ0ludDogJHtTdHJpbmcobil9XWA7Y29uc3QgdD1mdW5jdGlvbih0KXtjb25zdCBuPU9iamVjdC5nZXRQcm90b3R5cGVPZih0KTtyZXR1cm4gbj8uY29uc3RydWN0b3I/bi5jb25zdHJ1Y3Rvci5uYW1lOiJudWxsIHByb3RvdHlwZSJ9KG4pO3JldHVybmBbb2JqZWN0ICR7dH1dYH1jYXRjaCh0KXtyZXR1cm5gKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH19KDAsbik7aWYoIWMuc3RhcnRzV2l0aCgiW29iamVjdCAiKSlyZXR1cm4gYztpZihmdW5jdGlvbih0KXtyZXR1cm4gQm9vbGVhbih0W0RdKX0obikpcmV0dXJuIG47Y29uc3QgdT1mdW5jdGlvbih0KXtjb25zdCBuPXRbVV07cmV0dXJuIm51bWJlciI9PXR5cGVvZiBuP246dm9pZCAwfShuKSxhPXZvaWQgMCE9PXU/dTplO2lmKDA9PT1hKXJldHVybiBjLnJlcGxhY2UoIm9iamVjdCAiLCIiKTtpZihpKG4pKXJldHVybiJbQ2lyY3VsYXIgfl0iO2NvbnN0IGY9bjtpZihmJiYiZnVuY3Rpb24iPT10eXBlb2YgZi50b0pTT04pdHJ5e3JldHVybiBMKCIiLGYudG9KU09OKCksYS0xLHIsbyl9Y2F0Y2h7fWNvbnN0IGg9QXJyYXkuaXNBcnJheShuKT9bXTp7fTtsZXQgcD0wO2NvbnN0IGQ9QShuKTtmb3IoY29uc3QgdCBpbiBkKXtpZighT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGQsdCkpY29udGludWU7aWYocD49cil7aFt0XT0iW01heFByb3BlcnRpZXMgfl0iO2JyZWFrfWNvbnN0IG49ZFt0XTtoW3RdPUwodCxuLGEtMSxyLG8pLHArK31yZXR1cm4gcyhuKSxofWZ1bmN0aW9uIE0odCxuKXtjb25zdCBlPW4ucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL1t8XFx7fSgpW1xdXiQrKj8uXS9nLCJcXCQmIik7bGV0IHI9dDt0cnl7cj1kZWNvZGVVUkkodCl9Y2F0Y2h7fXJldHVybiByLnJlcGxhY2UoL1xcL2csIi8iKS5yZXBsYWNlKC93ZWJwYWNrOlwvPy9nLCIiKS5yZXBsYWNlKG5ldyBSZWdFeHAoYChmaWxlOi8vKT8vKiR7ZX0vKmAsImlnIiksImFwcDovLy8iKX1mdW5jdGlvbiB6KHQsbj0wKXtyZXR1cm4ic3RyaW5nIiE9dHlwZW9mIHR8fDA9PT1ufHx0Lmxlbmd0aDw9bj90OmAke3Quc2xpY2UoMCxuKX0uLi5gfWxldCBGO2Z1bmN0aW9uIEcodD1mdW5jdGlvbigpe2NvbnN0IHQ9cDtyZXR1cm4gdC5jcnlwdG98fHQubXNDcnlwdG99KCkpe3RyeXtpZih0Py5yYW5kb21VVUlEKXJldHVybiBUKCgpPT50LnJhbmRvbVVVSUQoKSkucmVwbGFjZSgvLS9nLCIiKX1jYXRjaHt9cmV0dXJuIEZ8fChGPSIxMDAwMDAwMDEwMDA0MDAwODAwMDEwMDAwMDAwMDAwMCIpLEYucmVwbGFjZSgvWzAxOF0vZyx0PT4odF4oMTYqaygpJjE1KT4+dC80KS50b1N0cmluZygxNikpfWZ1bmN0aW9uIEooKXtyZXR1cm4gUCgpLzFlM31sZXQgVztmdW5jdGlvbiBZKCl7cmV0dXJuKFc/PyhXPWZ1bmN0aW9uKCl7Y29uc3R7cGVyZm9ybWFuY2U6dH09cDtpZighdD8ubm93fHwhdC50aW1lT3JpZ2luKXJldHVybiBKO2NvbnN0IG49dC50aW1lT3JpZ2luO3JldHVybigpPT4obitUKCgpPT50Lm5vdygpKSkvMWUzfSgpKSkoKX1mdW5jdGlvbiBIKHQpe2NvbnN0IG49WSgpLGU9e3NpZDpHKCksaW5pdDohMCx0aW1lc3RhbXA6bixzdGFydGVkOm4sZHVyYXRpb246MCxzdGF0dXM6Im9rIixlcnJvcnM6MCxpZ25vcmVEdXJhdGlvbjohMSx0b0pTT046KCk9PmZ1bmN0aW9uKHQpe3JldHVybntzaWQ6YCR7dC5zaWR9YCxpbml0OnQuaW5pdCxzdGFydGVkOm5ldyBEYXRlKDFlMyp0LnN0YXJ0ZWQpLnRvSVNPU3RyaW5nKCksdGltZXN0YW1wOm5ldyBEYXRlKDFlMyp0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxzdGF0dXM6dC5zdGF0dXMsZXJyb3JzOnQuZXJyb3JzLGRpZDoibnVtYmVyIj09dHlwZW9mIHQuZGlkfHwic3RyaW5nIj09dHlwZW9mIHQuZGlkP2Ake3QuZGlkfWA6dm9pZCAwLGR1cmF0aW9uOnQuZHVyYXRpb24sYWJub3JtYWxfbWVjaGFuaXNtOnQuYWJub3JtYWxfbWVjaGFuaXNtLGF0dHJzOntyZWxlYXNlOnQucmVsZWFzZSxlbnZpcm9ubWVudDp0LmVudmlyb25tZW50LGlwX2FkZHJlc3M6dC5pcEFkZHJlc3MsdXNlcl9hZ2VudDp0LnVzZXJBZ2VudH19fShlKX07cmV0dXJuIHQmJksoZSx0KSxlfWZ1bmN0aW9uIEsodCxuPXt9KXtpZihuLnVzZXImJighdC5pcEFkZHJlc3MmJm4udXNlci5pcF9hZGRyZXNzJiYodC5pcEFkZHJlc3M9bi51c2VyLmlwX2FkZHJlc3MpLHQuZGlkfHxuLmRpZHx8KHQuZGlkPW4udXNlci5pZHx8bi51c2VyLmVtYWlsfHxuLnVzZXIudXNlcm5hbWUpKSx0LnRpbWVzdGFtcD1uLnRpbWVzdGFtcHx8WSgpLG4uYWJub3JtYWxfbWVjaGFuaXNtJiYodC5hYm5vcm1hbF9tZWNoYW5pc209bi5hYm5vcm1hbF9tZWNoYW5pc20pLG4uaWdub3JlRHVyYXRpb24mJih0Lmlnbm9yZUR1cmF0aW9uPW4uaWdub3JlRHVyYXRpb24pLG4uc2lkJiYodC5zaWQ9MzI9PT1uLnNpZC5sZW5ndGg/bi5zaWQ6RygpKSx2b2lkIDAhPT1uLmluaXQmJih0LmluaXQ9bi5pbml0KSwhdC5kaWQmJm4uZGlkJiYodC5kaWQ9YCR7bi5kaWR9YCksIm51bWJlciI9PXR5cGVvZiBuLnN0YXJ0ZWQmJih0LnN0YXJ0ZWQ9bi5zdGFydGVkKSx0Lmlnbm9yZUR1cmF0aW9uKXQuZHVyYXRpb249dm9pZCAwO2Vsc2UgaWYoIm51bWJlciI9PXR5cGVvZiBuLmR1cmF0aW9uKXQuZHVyYXRpb249bi5kdXJhdGlvbjtlbHNle2NvbnN0IG49dC50aW1lc3RhbXAtdC5zdGFydGVkO3QuZHVyYXRpb249bj49MD9uOjB9bi5yZWxlYXNlJiYodC5yZWxlYXNlPW4ucmVsZWFzZSksbi5lbnZpcm9ubWVudCYmKHQuZW52aXJvbm1lbnQ9bi5lbnZpcm9ubWVudCksIXQuaXBBZGRyZXNzJiZuLmlwQWRkcmVzcyYmKHQuaXBBZGRyZXNzPW4uaXBBZGRyZXNzKSwhdC51c2VyQWdlbnQmJm4udXNlckFnZW50JiYodC51c2VyQWdlbnQ9bi51c2VyQWdlbnQpLCJudW1iZXIiPT10eXBlb2Ygbi5lcnJvcnMmJih0LmVycm9ycz1uLmVycm9ycyksbi5zdGF0dXMmJih0LnN0YXR1cz1uLnN0YXR1cyl9ZnVuY3Rpb24gWih0LG4sZT0yKXtpZighbnx8Im9iamVjdCIhPXR5cGVvZiBufHxlPD0wKXJldHVybiBuO2lmKHQmJjA9PT1PYmplY3Qua2V5cyhuKS5sZW5ndGgpcmV0dXJuIHQ7Y29uc3Qgcj17Li4udH07Zm9yKGNvbnN0IHQgaW4gbilPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobix0KSYmKHJbdF09WihyW3RdLG5bdF0sZS0xKSk7cmV0dXJuIHJ9ZnVuY3Rpb24gcSgpe3JldHVybiBHKCl9ZnVuY3Rpb24gVigpe3JldHVybiBHKCkuc3Vic3RyaW5nKDE2KX1mdW5jdGlvbiBRKHQpe2lmKHQpe2lmKCJvYmplY3QiPT10eXBlb2YgdCYmImRlcmVmImluIHQmJiJmdW5jdGlvbiI9PXR5cGVvZiB0LmRlcmVmKXRyeXtyZXR1cm4gdC5kZXJlZigpfWNhdGNoe3JldHVybn1yZXR1cm4gdH19Y29uc3QgWD0iX3NlbnRyeVNwYW4iO2Z1bmN0aW9uIHR0KHQsbil7bj9mdW5jdGlvbih0LG4sZSl7dHJ5e09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LG4se3ZhbHVlOmUsd3JpdGFibGU6ITAsY29uZmlndXJhYmxlOiEwfSl9Y2F0Y2h7aCYmdy5sb2coYEZhaWxlZCB0byBhZGQgbm9uLWVudW1lcmFibGUgcHJvcGVydHkgIiR7U3RyaW5nKG4pfSIgdG8gb2JqZWN0YCx0KX19KHQsWCxmdW5jdGlvbih0KXt0cnl7Y29uc3Qgbj1wLldlYWtSZWY7aWYoImZ1bmN0aW9uIj09dHlwZW9mIG4pcmV0dXJuIG5ldyBuKHQpfWNhdGNoe31yZXR1cm4gdH0obikpOmRlbGV0ZSB0W1hdfWZ1bmN0aW9uIG50KHQpe3JldHVybiBRKHRbWF0pfWNsYXNzIGV0e2NvbnN0cnVjdG9yKCl7dGhpcy50PSExLHRoaXMubz1bXSx0aGlzLmk9W10sdGhpcy51PVtdLHRoaXMuaD1bXSx0aGlzLnA9e30sdGhpcy5sPXt9LHRoaXMubT17fSx0aGlzLnY9e30sdGhpcy5fPXt9LHRoaXMuUz17fSx0aGlzLk49e3RyYWNlSWQ6cSgpLHNhbXBsZVJhbmQ6aygpfX1jbG9uZSgpe2NvbnN0IHQ9bmV3IGV0O3JldHVybiB0LnU9Wy4uLnRoaXMudV0sdC5sPXsuLi50aGlzLmx9LHQubT17Li4udGhpcy5tfSx0LnY9ey4uLnRoaXMudn0sdC5fPXsuLi50aGlzLl99LHRoaXMuXy5mbGFncyYmKHQuXy5mbGFncz17dmFsdWVzOlsuLi50aGlzLl8uZmxhZ3MudmFsdWVzXX0pLHQucD10aGlzLnAsdC5DPXRoaXMuQyx0Lmo9dGhpcy5qLHQuUj10aGlzLlIsdC5BPXRoaXMuQSx0Lmk9Wy4uLnRoaXMuaV0sdC5oPVsuLi50aGlzLmhdLHQuUz17Li4udGhpcy5TfSx0Lk49ey4uLnRoaXMuTn0sdC5JPXRoaXMuSSx0Lk89dGhpcy5PLHQuVD10aGlzLlQsdHQodCxudCh0aGlzKSksdH1zZXRDbGllbnQodCl7dGhpcy5JPXR9c2V0TGFzdEV2ZW50SWQodCl7dGhpcy5PPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuSX1sYXN0RXZlbnRJZCgpe3JldHVybiB0aGlzLk99YWRkU2NvcGVMaXN0ZW5lcih0KXt0aGlzLm8ucHVzaCh0KX1hZGRFdmVudFByb2Nlc3Nvcih0KXtyZXR1cm4gdGhpcy5pLnB1c2godCksdGhpc31zZXRVc2VyKHQpe3JldHVybiB0aGlzLnA9dHx8e2VtYWlsOnZvaWQgMCxpZDp2b2lkIDAsaXBfYWRkcmVzczp2b2lkIDAsdXNlcm5hbWU6dm9pZCAwfSx0aGlzLmomJksodGhpcy5qLHt1c2VyOnR9KSx0aGlzLmsoKSx0aGlzfWdldFVzZXIoKXtyZXR1cm4gdGhpcy5wfXNldENvbnZlcnNhdGlvbklkKHQpe3JldHVybiB0aGlzLlQ9dHx8dm9pZCAwLHRoaXMuaygpLHRoaXN9c2V0VGFncyh0KXtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4udH0sdGhpcy5rKCksdGhpc31zZXRUYWcodCxuKXtyZXR1cm4gdGhpcy5zZXRUYWdzKHtbdF06bn0pfXNldEF0dHJpYnV0ZXModCl7cmV0dXJuIHRoaXMubT17Li4udGhpcy5tLC4uLnR9LHRoaXMuaygpLHRoaXN9c2V0QXR0cmlidXRlKHQsbil7cmV0dXJuIHRoaXMuc2V0QXR0cmlidXRlcyh7W3RdOm59KX1yZW1vdmVBdHRyaWJ1dGUodCl7cmV0dXJuIHQgaW4gdGhpcy5tJiYoZGVsZXRlIHRoaXMubVt0XSx0aGlzLmsoKSksdGhpc31zZXRFeHRyYXModCl7cmV0dXJuIHRoaXMudj17Li4udGhpcy52LC4uLnR9LHRoaXMuaygpLHRoaXN9c2V0RXh0cmEodCxuKXtyZXR1cm4gdGhpcy52PXsuLi50aGlzLnYsW3RdOm59LHRoaXMuaygpLHRoaXN9c2V0RmluZ2VycHJpbnQodCl7cmV0dXJuIHRoaXMuQT10LHRoaXMuaygpLHRoaXN9c2V0TGV2ZWwodCl7cmV0dXJuIHRoaXMuQz10LHRoaXMuaygpLHRoaXN9c2V0VHJhbnNhY3Rpb25OYW1lKHQpe3JldHVybiB0aGlzLlI9dCx0aGlzLmsoKSx0aGlzfXNldENvbnRleHQodCxuKXtyZXR1cm4gbnVsbD09PW4/ZGVsZXRlIHRoaXMuX1t0XTp0aGlzLl9bdF09bix0aGlzLmsoKSx0aGlzfXNldFNlc3Npb24odCl7cmV0dXJuIHQ/dGhpcy5qPXQ6ZGVsZXRlIHRoaXMuaix0aGlzLmsoKSx0aGlzfWdldFNlc3Npb24oKXtyZXR1cm4gdGhpcy5qfXVwZGF0ZSh0KXtpZighdClyZXR1cm4gdGhpcztjb25zdCBuPSJmdW5jdGlvbiI9PXR5cGVvZiB0P3QodGhpcyk6dCxlPW4gaW5zdGFuY2VvZiBldD9uLmdldFNjb3BlRGF0YSgpOkMobiwiT2JqZWN0Iik/dDp2b2lkIDA7Y29uc3R7dGFnczpyLGF0dHJpYnV0ZXM6byxleHRyYTppLHVzZXI6cyxjb250ZXh0czpjLGxldmVsOnUsZmluZ2VycHJpbnQ6YT1bXSxwcm9wYWdhdGlvbkNvbnRleHQ6Zixjb252ZXJzYXRpb25JZDpofT1lfHx7fTtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4ucn0sdGhpcy5tPXsuLi50aGlzLm0sLi4ub30sdGhpcy52PXsuLi50aGlzLnYsLi4uaX0sdGhpcy5fPXsuLi50aGlzLl8sLi4uY30scyYmT2JqZWN0LmtleXMocykubGVuZ3RoJiYodGhpcy5wPXMpLHUmJih0aGlzLkM9dSksYS5sZW5ndGgmJih0aGlzLkE9YSksZiYmKHRoaXMuTj1mKSxoJiYodGhpcy5UPWgpLHRoaXN9Y2xlYXIoKXtyZXR1cm4gdGhpcy51PVtdLHRoaXMubD17fSx0aGlzLm09e30sdGhpcy52PXt9LHRoaXMucD17fSx0aGlzLl89e30sdGhpcy5DPXZvaWQgMCx0aGlzLlI9dm9pZCAwLHRoaXMuQT12b2lkIDAsdGhpcy5qPXZvaWQgMCx0aGlzLlQ9dm9pZCAwLHR0KHRoaXMsdm9pZCAwKSx0aGlzLmg9W10sdGhpcy5zZXRQcm9wYWdhdGlvbkNvbnRleHQoe3RyYWNlSWQ6cSgpLHNhbXBsZVJhbmQ6aygpfSksdGhpcy5rKCksdGhpc31hZGRCcmVhZGNydW1iKHQsbil7Y29uc3QgZT0ibnVtYmVyIj09dHlwZW9mIG4/bjoxMDA7aWYoZTw9MClyZXR1cm4gdGhpcztjb25zdCByPXt0aW1lc3RhbXA6SigpLC4uLnQsbWVzc2FnZTp0Lm1lc3NhZ2U/eih0Lm1lc3NhZ2UsMjA0OCk6dC5tZXNzYWdlfTtyZXR1cm4gdGhpcy51LnB1c2gociksdGhpcy51Lmxlbmd0aD5lJiYodGhpcy51PXRoaXMudS5zbGljZSgtZSksdGhpcy5JPy5yZWNvcmREcm9wcGVkRXZlbnQoImJ1ZmZlcl9vdmVyZmxvdyIsImxvZ19pdGVtIikpLHRoaXMuaygpLHRoaXN9Z2V0TGFzdEJyZWFkY3J1bWIoKXtyZXR1cm4gdGhpcy51W3RoaXMudS5sZW5ndGgtMV19Y2xlYXJCcmVhZGNydW1icygpe3JldHVybiB0aGlzLnU9W10sdGhpcy5rKCksdGhpc31hZGRBdHRhY2htZW50KHQpe3JldHVybiB0aGlzLmgucHVzaCh0KSx0aGlzfWNsZWFyQXR0YWNobWVudHMoKXtyZXR1cm4gdGhpcy5oPVtdLHRoaXN9Z2V0U2NvcGVEYXRhKCl7cmV0dXJue2JyZWFkY3J1bWJzOnRoaXMudSxhdHRhY2htZW50czp0aGlzLmgsY29udGV4dHM6dGhpcy5fLHRhZ3M6dGhpcy5sLGF0dHJpYnV0ZXM6dGhpcy5tLGV4dHJhOnRoaXMudix1c2VyOnRoaXMucCxsZXZlbDp0aGlzLkMsZmluZ2VycHJpbnQ6dGhpcy5BfHxbXSxldmVudFByb2Nlc3NvcnM6dGhpcy5pLHByb3BhZ2F0aW9uQ29udGV4dDp0aGlzLk4sc2RrUHJvY2Vzc2luZ01ldGFkYXRhOnRoaXMuUyx0cmFuc2FjdGlvbk5hbWU6dGhpcy5SLHNwYW46bnQodGhpcyksY29udmVyc2F0aW9uSWQ6dGhpcy5UfX1zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEodCl7cmV0dXJuIHRoaXMuUz1aKHRoaXMuUyx0LDIpLHRoaXN9c2V0UHJvcGFnYXRpb25Db250ZXh0KHQpe3JldHVybiB0aGlzLk49dCx0aGlzfWdldFByb3BhZ2F0aW9uQ29udGV4dCgpe3JldHVybiB0aGlzLk59Y2FwdHVyZUV4Y2VwdGlvbih0LG4pe2NvbnN0IGU9bj8uZXZlbnRfaWR8fEcoKTtpZighdGhpcy5JKXJldHVybiBoJiZ3Lndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBleGNlcHRpb24hIiksZTtjb25zdCByPW5ldyBFcnJvcigiU2VudHJ5IHN5bnRoZXRpY0V4Y2VwdGlvbiIpO3JldHVybiB0aGlzLkkuY2FwdHVyZUV4Y2VwdGlvbih0LHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpyLC4uLm4sZXZlbnRfaWQ6ZX0sdGhpcyksZX1jYXB0dXJlTWVzc2FnZSh0LG4sZSl7Y29uc3Qgcj1lPy5ldmVudF9pZHx8RygpO2lmKCF0aGlzLkkpcmV0dXJuIGgmJncud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIG1lc3NhZ2UhIikscjtjb25zdCBvPWU/LnN5bnRoZXRpY0V4Y2VwdGlvbj8/bmV3IEVycm9yKHQpO3JldHVybiB0aGlzLkkuY2FwdHVyZU1lc3NhZ2UodCxuLHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpvLC4uLmUsZXZlbnRfaWQ6cn0sdGhpcykscn1jYXB0dXJlRXZlbnQodCxuKXtjb25zdCBlPXQuZXZlbnRfaWR8fG4/LmV2ZW50X2lkfHxHKCk7cmV0dXJuIHRoaXMuST8odGhpcy5JLmNhcHR1cmVFdmVudCh0LHsuLi5uLGV2ZW50X2lkOmV9LHRoaXMpLGUpOihoJiZ3Lndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBldmVudCEiKSxlKX1rKCl7dGhpcy50fHwodGhpcy50PSEwLHRoaXMuby5mb3JFYWNoKHQ9Pnt0KHRoaXMpfSksdGhpcy50PSExKX19Y29uc3QgcnQ9dD0+dCBpbnN0YW5jZW9mIFByb21pc2UmJiF0W290XSxvdD1TeW1ib2woImNoYWluZWQgUHJvbWlzZUxpa2UiKSxpdD0odCxuKT0+e2lmKCFuKXJldHVybiB0O2xldCBlPSExO2Zvcihjb25zdCByIGluIHQpe2lmKHIgaW4gbiljb250aW51ZTtlPSEwO2NvbnN0IG89dFtyXTsiZnVuY3Rpb24iPT10eXBlb2Ygbz9PYmplY3QuZGVmaW5lUHJvcGVydHkobixyLHt2YWx1ZTooLi4ubik9Pm8uYXBwbHkodCxuKSxlbnVtZXJhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMCx3cml0YWJsZTohMH0pOm5bcl09b31yZXR1cm4gZSYmT2JqZWN0LmFzc2lnbihuLHtbb3RdOiEwfSksbn07Y2xhc3Mgc3R7Y29uc3RydWN0b3IodCxuKXtsZXQgZSxyO2U9dHx8bmV3IGV0LHI9bnx8bmV3IGV0LHRoaXMuUD1be3Njb3BlOmV9XSx0aGlzLkQ9cn13aXRoU2NvcGUodCl7Y29uc3Qgbj10aGlzLlUoKTtsZXQgZTt0cnl7ZT10KG4pfWNhdGNoKHQpe3Rocm93IHRoaXMuQigpLHR9cmV0dXJuIGooZSk/KCh0LG4sZSk9Pntjb25zdCByPXQudGhlbih0PT4obih0KSx0KSx0PT57dGhyb3cgZSh0KSx0fSk7cmV0dXJuIHJ0KHIpJiZydCh0KT9yOml0KHQscil9KShlLCgpPT50aGlzLkIoKSwoKT0+dGhpcy5CKCkpOih0aGlzLkIoKSxlKX1nZXRDbGllbnQoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLmNsaWVudH1nZXRTY29wZSgpe3JldHVybiB0aGlzLmdldFN0YWNrVG9wKCkuc2NvcGV9Z2V0SXNvbGF0aW9uU2NvcGUoKXtyZXR1cm4gdGhpcy5EfWdldFN0YWNrVG9wKCl7cmV0dXJuIHRoaXMuUFt0aGlzLlAubGVuZ3RoLTFdfVUoKXtjb25zdCB0PXRoaXMuZ2V0U2NvcGUoKS5jbG9uZSgpO3JldHVybiB0aGlzLlAucHVzaCh7Y2xpZW50OnRoaXMuZ2V0Q2xpZW50KCksc2NvcGU6dH0pLHR9Qigpe3JldHVybiEodGhpcy5QLmxlbmd0aDw9MSkmJiEhdGhpcy5QLnBvcCgpfX1mdW5jdGlvbiBjdCgpe2NvbnN0IHQ9ZyhsKCkpO3JldHVybiB0LnN0YWNrPXQuc3RhY2t8fG5ldyBzdChtKCJkZWZhdWx0Q3VycmVudFNjb3BlIiwoKT0+bmV3IGV0KSxtKCJkZWZhdWx0SXNvbGF0aW9uU2NvcGUiLCgpPT5uZXcgZXQpKX1mdW5jdGlvbiB1dCh0KXtyZXR1cm4gY3QoKS53aXRoU2NvcGUodCl9ZnVuY3Rpb24gYXQodCxuKXtjb25zdCBlPWN0KCk7cmV0dXJuIGUud2l0aFNjb3BlKCgpPT4oZS5nZXRTdGFja1RvcCgpLnNjb3BlPXQsbih0KSkpfWZ1bmN0aW9uIGZ0KHQpe3JldHVybiBjdCgpLndpdGhTY29wZSgoKT0+dChjdCgpLmdldElzb2xhdGlvblNjb3BlKCkpKX1mdW5jdGlvbiBodCh0KXtjb25zdCBuPWcodCk7cmV0dXJuIG4uYWNzP24uYWNzOnt3aXRoSXNvbGF0aW9uU2NvcGU6ZnQsd2l0aFNjb3BlOnV0LHdpdGhTZXRTY29wZTphdCx3aXRoU2V0SXNvbGF0aW9uU2NvcGU6KHQsbik9PmZ0KG4pLGdldEN1cnJlbnRTY29wZTooKT0+Y3QoKS5nZXRTY29wZSgpLGdldElzb2xhdGlvblNjb3BlOigpPT5jdCgpLmdldElzb2xhdGlvblNjb3BlKCl9fWZ1bmN0aW9uIHB0KCl7cmV0dXJuIGh0KGwoKSkuZ2V0Q3VycmVudFNjb3BlKCkuZ2V0Q2xpZW50KCl9ZnVuY3Rpb24gZHQodCl7Y29uc3Qgbj10O3JldHVybntzY29wZTpuLl9zZW50cnlTY29wZSxpc29sYXRpb25TY29wZTpRKG4uX3NlbnRyeUlzb2xhdGlvblNjb3BlKX19Y29uc3QgbHQ9InNlbnRyeS0iO2Z1bmN0aW9uIGd0KHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7aWYoIXR8fChuPXQsIUMobiwiU3RyaW5nIikmJiFBcnJheS5pc0FycmF5KHQpKSlyZXR1cm47dmFyIG47aWYoQXJyYXkuaXNBcnJheSh0KSlyZXR1cm4gdC5yZWR1Y2UoKHQsbik9Pntjb25zdCBlPW10KG4pO3JldHVybiBPYmplY3QuZW50cmllcyhlKS5mb3JFYWNoKChbbixlXSk9Pnt0W25dPWV9KSx0fSx7fSk7cmV0dXJuIG10KHQpfSh0KTtpZighbilyZXR1cm47Y29uc3QgZT1PYmplY3QuZW50cmllcyhuKS5yZWR1Y2UoKHQsW24sZV0pPT57aWYobi5zdGFydHNXaXRoKGx0KSl7dFtuLnNsaWNlKDcpXT1lfXJldHVybiB0fSx7fSk7cmV0dXJuIE9iamVjdC5rZXlzKGUpLmxlbmd0aD4wP2U6dm9pZCAwfWZ1bmN0aW9uIG10KHQpe3JldHVybiB0LnNwbGl0KCIsIikubWFwKHQ9Pntjb25zdCBuPXQuaW5kZXhPZigiPSIpO2lmKC0xPT09bilyZXR1cm5bXTtyZXR1cm5bdC5zbGljZSgwLG4pLHQuc2xpY2UobisxKV0ubWFwKHQ9Pnt0cnl7cmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudCh0LnRyaW0oKSl9Y2F0Y2h7cmV0dXJufX0pfSkucmVkdWNlKCh0LFtuLGVdKT0+KG4mJmUmJih0W25dPWUpLHQpLHt9KX1jb25zdCB5dD0vXm8oXGQrKVwuLztmdW5jdGlvbiBidCh0LG49ITEpe2NvbnN0e2hvc3Q6ZSxwYXRoOnIscGFzczpvLHBvcnQ6aSxwcm9qZWN0SWQ6cyxwcm90b2NvbDpjLHB1YmxpY0tleTp1fT10O3JldHVybmAke2N9Oi8vJHt1fSR7biYmbz9gOiR7b31gOiIifUAke2V9JHtpP2A6JHtpfWA6IiJ9LyR7cj9gJHtyfS9gOnJ9JHtzfWB9ZnVuY3Rpb24gdnQodCl7Y29uc3Qgbj10LmdldE9wdGlvbnMoKSx7aG9zdDplfT10LmdldERzbigpfHx7fTtsZXQgcjtyZXR1cm4gbi5vcmdJZD9yPVN0cmluZyhuLm9yZ0lkKTplJiYocj1mdW5jdGlvbih0KXtjb25zdCBuPXQubWF0Y2goeXQpO3JldHVybiBuPy5bMV19KGUpKSxyfWZ1bmN0aW9uIF90KHQpe2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZSxpc1JlbW90ZTpyfT10LnNwYW5Db250ZXh0KCksbz1yP246RXQodCkucGFyZW50X3NwYW5faWQsaT1kdCh0KS5zY29wZTtyZXR1cm57cGFyZW50X3NwYW5faWQ6byxzcGFuX2lkOnI/aT8uZ2V0UHJvcGFnYXRpb25Db250ZXh0KCkucHJvcGFnYXRpb25TcGFuSWR8fFYoKTpuLHRyYWNlX2lkOmV9fWZ1bmN0aW9uIFN0KHQpe3JldHVybiB0JiZ0Lmxlbmd0aD4wP3QubWFwKCh7Y29udGV4dDp7c3BhbklkOnQsdHJhY2VJZDpuLHRyYWNlRmxhZ3M6ZSwuLi5yfSxhdHRyaWJ1dGVzOm99KT0+KHtzcGFuX2lkOnQsdHJhY2VfaWQ6bixzYW1wbGVkOjE9PT1lLGF0dHJpYnV0ZXM6bywuLi5yfSkpOnZvaWQgMH1mdW5jdGlvbiB3dCh0KXtyZXR1cm4ibnVtYmVyIj09dHlwZW9mIHQ/JHQodCk6QXJyYXkuaXNBcnJheSh0KT90WzBdK3RbMV0vMWU5OnQgaW5zdGFuY2VvZiBEYXRlPyR0KHQuZ2V0VGltZSgpKTpZKCl9ZnVuY3Rpb24gJHQodCl7cmV0dXJuIHQ+OTk5OTk5OTk5OT90LzFlMzp0fWZ1bmN0aW9uIEV0KHQpe2lmKGZ1bmN0aW9uKHQpe3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiB0LmdldFNwYW5KU09OfSh0KSlyZXR1cm4gdC5nZXRTcGFuSlNPTigpO2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZX09dC5zcGFuQ29udGV4dCgpO2lmKGZ1bmN0aW9uKHQpe2NvbnN0IG49dDtyZXR1cm4hIShuLmF0dHJpYnV0ZXMmJm4uc3RhcnRUaW1lJiZuLm5hbWUmJm4uZW5kVGltZSYmbi5zdGF0dXMpfSh0KSl7Y29uc3R7YXR0cmlidXRlczpyLHN0YXJ0VGltZTpvLG5hbWU6aSxlbmRUaW1lOnMsc3RhdHVzOmMsbGlua3M6dX09dDtyZXR1cm57c3Bhbl9pZDpuLHRyYWNlX2lkOmUsZGF0YTpyLGRlc2NyaXB0aW9uOmkscGFyZW50X3NwYW5faWQ6eHQodCksc3RhcnRfdGltZXN0YW1wOnd0KG8pLHRpbWVzdGFtcDp3dChzKXx8dm9pZCAwLHN0YXR1czpOdChjKSxvcDpyWyJzZW50cnkub3AiXSxvcmlnaW46clsic2VudHJ5Lm9yaWdpbiJdLGxpbmtzOlN0KHUpfX1yZXR1cm57c3Bhbl9pZDpuLHRyYWNlX2lkOmUsc3RhcnRfdGltZXN0YW1wOjAsZGF0YTp7fX19ZnVuY3Rpb24geHQodCl7cmV0dXJuInBhcmVudFNwYW5JZCJpbiB0P3QucGFyZW50U3BhbklkOiJwYXJlbnRTcGFuQ29udGV4dCJpbiB0P3QucGFyZW50U3BhbkNvbnRleHQ/LnNwYW5JZDp2b2lkIDB9ZnVuY3Rpb24gTnQodCl7aWYodCYmMCE9PXQuY29kZSlyZXR1cm4gMT09PXQuY29kZT8ib2siOnQubWVzc2FnZXx8ImludGVybmFsX2Vycm9yIn1jb25zdCBDdD1mdW5jdGlvbih0KXtyZXR1cm4gdC5fc2VudHJ5Um9vdFNwYW58fHR9O2Z1bmN0aW9uIGp0KHQpe2lmKCJib29sZWFuIj09dHlwZW9mIF9fU0VOVFJZX1RSQUNJTkdfXyYmIV9fU0VOVFJZX1RSQUNJTkdfXylyZXR1cm4hMTtjb25zdCBuPXR8fHB0KCk/LmdldE9wdGlvbnMoKTtyZXR1cm4hKCFufHxudWxsPT1uLnRyYWNlc1NhbXBsZVJhdGUmJiFuLnRyYWNlc1NhbXBsZXIpfWNvbnN0IFJ0PVN5bWJvbC5mb3IoInNlbnRyeS5ub25SZWNvcmRpbmdTcGFuIik7ZnVuY3Rpb24gQXQodCxuKXtjb25zdCBlPW4uZ2V0T3B0aW9ucygpLHtwdWJsaWNLZXk6cn09bi5nZXREc24oKXx8e30sbz17ZW52aXJvbm1lbnQ6ZS5lbnZpcm9ubWVudHx8InByb2R1Y3Rpb24iLHJlbGVhc2U6ZS5yZWxlYXNlLHB1YmxpY19rZXk6cix0cmFjZV9pZDp0LG9yZ19pZDp2dChuKX07cmV0dXJuIG4uZW1pdCgiY3JlYXRlRHNjIixvKSxvfWZ1bmN0aW9uIEl0KHQsbil7Y29uc3QgZT1uLmdldFByb3BhZ2F0aW9uQ29udGV4dCgpO3JldHVybiBlLmRzY3x8QXQoZS50cmFjZUlkLHQpfWZ1bmN0aW9uIE90KHQpe2NvbnN0IG49cHQoKTtpZighbilyZXR1cm57fTtjb25zdCBlPUN0KHQpLHI9RXQoZSksbz1yLmRhdGEsaT1lLnNwYW5Db250ZXh0KCkudHJhY2VTdGF0ZSxzPWk/LmdldCgic2VudHJ5LnNhbXBsZV9yYXRlIik/P29bInNlbnRyeS5zYW1wbGVfcmF0ZSJdPz9vWyJzZW50cnkucHJldmlvdXNfdHJhY2Vfc2FtcGxlX3JhdGUiXTtmdW5jdGlvbiBjKHQpe3JldHVybiJudW1iZXIiIT10eXBlb2YgcyYmInN0cmluZyIhPXR5cGVvZiBzfHwodC5zYW1wbGVfcmF0ZT1gJHtzfWApLHR9Y29uc3QgdT1lLl9mcm96ZW5Ec2M7aWYodSlyZXR1cm4gYyh1KTtpZihmdW5jdGlvbih0KXtyZXR1cm4hIXQmJiEwPT09dFtSdF19KGUpJiYhanQobi5nZXRPcHRpb25zKCkpKXtjb25zdCB0PWR0KGUpLnNjb3BlO2lmKHQpcmV0dXJuIGMoey4uLkl0KG4sdCl9KX1jb25zdCBhPWk/LmdldCgic2VudHJ5LmRzYyIpLGY9YSYmZ3QoYSk7aWYoZilyZXR1cm4gYyhmKTtjb25zdCBoPUF0KHQuc3BhbkNvbnRleHQoKS50cmFjZUlkLG4pLHA9b1sic2VudHJ5LnNvdXJjZSJdPz9vWyJzZW50cnkuc3Bhbi5zb3VyY2UiXSxkPXIuZGVzY3JpcHRpb247cmV0dXJuInVybCIhPT1wJiZkJiYoaC50cmFuc2FjdGlvbj1kKSxqdCgpJiYoaC5zYW1wbGVkPVN0cmluZyhmdW5jdGlvbih0KXtjb25zdHt0cmFjZUZsYWdzOm59PXQuc3BhbkNvbnRleHQoKTtyZXR1cm4gMT09PW59KGUpKSxoLnNhbXBsZV9yYW5kPWk/LmdldCgic2VudHJ5LnNhbXBsZV9yYW5kIik/P2R0KGUpLnNjb3BlPy5nZXRQcm9wYWdhdGlvbkNvbnRleHQoKS5zYW1wbGVSYW5kLnRvU3RyaW5nKCkpLGMoaCksbi5lbWl0KCJjcmVhdGVEc2MiLGgsZSksaH1mdW5jdGlvbiBUdCh0LG49W10pe3JldHVyblt0LG5dfWZ1bmN0aW9uIGt0KHQsbil7Y29uc3QgZT10WzFdO2Zvcihjb25zdCB0IG9mIGUpe2lmKG4odCx0WzBdLnR5cGUpKXJldHVybiEwfXJldHVybiExfWZ1bmN0aW9uIFB0KHQpe2NvbnN0IG49ZyhwKTtyZXR1cm4gbi5lbmNvZGVQb2x5ZmlsbD9uLmVuY29kZVBvbHlmaWxsKHQpOihuZXcgVGV4dEVuY29kZXIpLmVuY29kZSh0KX1mdW5jdGlvbiBEdCh0KXtjb25zdFtuLGVdPXQ7bGV0IHI9SlNPTi5zdHJpbmdpZnkobik7ZnVuY3Rpb24gbyh0KXsic3RyaW5nIj09dHlwZW9mIHI/cj0ic3RyaW5nIj09dHlwZW9mIHQ/cit0OltQdChyKSx0XTpyLnB1c2goInN0cmluZyI9PXR5cGVvZiB0P1B0KHQpOnQpfWZvcihjb25zdCB0IG9mIGUpe2NvbnN0W24sZV09dDtpZihvKGBcbiR7SlNPTi5zdHJpbmdpZnkobil9XG5gKSwic3RyaW5nIj09dHlwZW9mIGV8fGUgaW5zdGFuY2VvZiBVaW50OEFycmF5KW8oZSk7ZWxzZXtsZXQgdDt0cnl7dD1KU09OLnN0cmluZ2lmeShlKX1jYXRjaHt0PUpTT04uc3RyaW5naWZ5KEIoZSkpfW8odCl9fXJldHVybiJzdHJpbmciPT10eXBlb2Ygcj9yOmZ1bmN0aW9uKHQpe2NvbnN0IG49dC5yZWR1Y2UoKHQsbik9PnQrbi5sZW5ndGgsMCksZT1uZXcgVWludDhBcnJheShuKTtsZXQgcj0wO2Zvcihjb25zdCBuIG9mIHQpZS5zZXQobixyKSxyKz1uLmxlbmd0aDtyZXR1cm4gZX0ocil9Y29uc3QgVXQ9e3Nlc3Npb25zOiJzZXNzaW9uIixldmVudDoiZXJyb3IiLGNsaWVudF9yZXBvcnQ6ImludGVybmFsIix1c2VyX3JlcG9ydDoiZGVmYXVsdCIscHJvZmlsZV9jaHVuazoicHJvZmlsZSIscmVwbGF5X2V2ZW50OiJyZXBsYXkiLHJlcGxheV9yZWNvcmRpbmc6InJlcGxheSIsY2hlY2tfaW46Im1vbml0b3IiLHJhd19zZWN1cml0eToic2VjdXJpdHkiLGxvZzoibG9nX2l0ZW0iLHRyYWNlX21ldHJpYzoibWV0cmljIn07ZnVuY3Rpb24gQnQodCl7cmV0dXJuIGZ1bmN0aW9uKHQpe3JldHVybiB0IGluIFV0fSh0KT9VdFt0XTp0fWZ1bmN0aW9uIEx0KHQpe2lmKCF0Py5zZGspcmV0dXJuO2NvbnN0e25hbWU6bix2ZXJzaW9uOmV9PXQuc2RrO3JldHVybntuYW1lOm4sdmVyc2lvbjplfX1mdW5jdGlvbiBNdCh0LG4sZSxyKXtjb25zdCBvPUx0KGUpLGk9dC50eXBlJiYicmVwbGF5X2V2ZW50IiE9PXQudHlwZT90LnR5cGU6ImV2ZW50IjshZnVuY3Rpb24odCxuKXtpZighbilyZXR1cm4gdDtjb25zdCBlPXQuc2RrfHx7fTt0LnNkaz17Li4uZSxuYW1lOmUubmFtZXx8bi5uYW1lLHZlcnNpb246ZS52ZXJzaW9ufHxuLnZlcnNpb24saW50ZWdyYXRpb25zOlsuLi50LnNkaz8uaW50ZWdyYXRpb25zfHxbXSwuLi5uLmludGVncmF0aW9uc3x8W11dLHBhY2thZ2VzOlsuLi50LnNkaz8ucGFja2FnZXN8fFtdLC4uLm4ucGFja2FnZXN8fFtdXSxzZXR0aW5nczp0LnNkaz8uc2V0dGluZ3N8fG4uc2V0dGluZ3M/ey4uLnQuc2RrPy5zZXR0aW5ncywuLi5uLnNldHRpbmdzfTp2b2lkIDB9fSh0LGU/LnNkayk7Y29uc3Qgcz1mdW5jdGlvbih0LG4sZSxyKXtjb25zdCBvPXQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhPy5keW5hbWljU2FtcGxpbmdDb250ZXh0O3JldHVybntldmVudF9pZDp0LmV2ZW50X2lkLHNlbnRfYXQ6bmV3IERhdGUoUCgpKS50b0lTT1N0cmluZygpLC4uLm4mJntzZGs6bn0sLi4uISFlJiZyJiZ7ZHNuOmJ0KHIpfSwuLi5vJiZ7dHJhY2U6b319fSh0LG8scixuKTtkZWxldGUgdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE7cmV0dXJuIFR0KHMsW1t7dHlwZTppfSx0XV0pfWNvbnN0IHp0PSJfX1NFTlRSWV9TVVBQUkVTU19UUkFDSU5HX18iO2Z1bmN0aW9uIEZ0KHQpe2NvbnN0IG49aHQobCgpKTtyZXR1cm4gbi5zdXBwcmVzc1RyYWNpbmc/bi5zdXBwcmVzc1RyYWNpbmcodCk6ZnVuY3Rpb24oLi4udCl7Y29uc3Qgbj1odChsKCkpO2lmKDI9PT10Lmxlbmd0aCl7Y29uc3RbZSxyXT10O3JldHVybiBlP24ud2l0aFNldFNjb3BlKGUscik6bi53aXRoU2NvcGUocil9cmV0dXJuIG4ud2l0aFNjb3BlKHRbMF0pfShuPT57bi5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1t6dF06ITB9KTtjb25zdCBlPXQoKTtyZXR1cm4gbi5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1t6dF06dm9pZCAwfSksZX0pfWZ1bmN0aW9uIEd0KHQsbil7Y29uc3R7ZmluZ2VycHJpbnQ6ZSxzcGFuOnIsYnJlYWRjcnVtYnM6byxzZGtQcm9jZXNzaW5nTWV0YWRhdGE6aX09bjshZnVuY3Rpb24odCxuKXtjb25zdHtleHRyYTplLHRhZ3M6cix1c2VyOm8sY29udGV4dHM6aSxsZXZlbDpzLHRyYW5zYWN0aW9uTmFtZTpjfT1uO09iamVjdC5rZXlzKGUpLmxlbmd0aCYmKHQuZXh0cmE9ey4uLmUsLi4udC5leHRyYX0pO09iamVjdC5rZXlzKHIpLmxlbmd0aCYmKHQudGFncz17Li4uciwuLi50LnRhZ3N9KTtPYmplY3Qua2V5cyhvKS5sZW5ndGgmJih0LnVzZXI9ey4uLm8sLi4udC51c2VyfSk7T2JqZWN0LmtleXMoaSkubGVuZ3RoJiYodC5jb250ZXh0cz17Li4uaSwuLi50LmNvbnRleHRzfSk7cyYmKHQubGV2ZWw9cyk7YyYmInRyYW5zYWN0aW9uIiE9PXQudHlwZSYmKHQudHJhbnNhY3Rpb249Yyl9KHQsbiksciYmZnVuY3Rpb24odCxuKXt0LmNvbnRleHRzPXt0cmFjZTpfdChuKSwuLi50LmNvbnRleHRzfSx0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YT17ZHluYW1pY1NhbXBsaW5nQ29udGV4dDpPdChuKSwuLi50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YX07Y29uc3QgZT1DdChuKSxyPUV0KGUpLmRlc2NyaXB0aW9uO3ImJiF0LnRyYW5zYWN0aW9uJiYidHJhbnNhY3Rpb24iPT09dC50eXBlJiYodC50cmFuc2FjdGlvbj1yKX0odCxyKSxmdW5jdGlvbih0LG4pe3QuZmluZ2VycHJpbnQ9dC5maW5nZXJwcmludD9BcnJheS5pc0FycmF5KHQuZmluZ2VycHJpbnQpP3QuZmluZ2VycHJpbnQ6W3QuZmluZ2VycHJpbnRdOltdLG4mJih0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQuY29uY2F0KG4pKTt0LmZpbmdlcnByaW50Lmxlbmd0aHx8ZGVsZXRlIHQuZmluZ2VycHJpbnR9KHQsZSksZnVuY3Rpb24odCxuKXtjb25zdCBlPVsuLi50LmJyZWFkY3J1bWJzfHxbXSwuLi5uXTt0LmJyZWFkY3J1bWJzPWUubGVuZ3RoP2U6dm9pZCAwfSh0LG8pLGZ1bmN0aW9uKHQsbil7dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9ey4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhLC4uLm59fSh0LGkpfWNsYXNzIEp0e2NvbnN0cnVjdG9yKHQpe3RoaXMuTD0wLHRoaXMuTT1bXSx0aGlzLkYodCl9dGhlbih0LG4pe3JldHVybiBuZXcgSnQoKGUscik9Pnt0aGlzLk0ucHVzaChbITEsbj0+e2lmKHQpdHJ5e2UodChuKSl9Y2F0Y2godCl7cih0KX1lbHNlIGUobil9LHQ9PntpZihuKXRyeXtlKG4odCkpfWNhdGNoKHQpe3IodCl9ZWxzZSByKHQpfV0pLHRoaXMuRygpfSl9Y2F0Y2godCl7cmV0dXJuIHRoaXMudGhlbih0PT50LHQpfWZpbmFsbHkodCl7cmV0dXJuIG5ldyBKdCgobixlKT0+e2xldCByLG87cmV0dXJuIHRoaXMudGhlbihuPT57bz0hMSxyPW4sdCYmdCgpfSxuPT57bz0hMCxyPW4sdCYmdCgpfSkudGhlbigoKT0+e28/ZShyKTpuKHIpfSl9KX1HKCl7aWYoMD09PXRoaXMuTClyZXR1cm47Y29uc3QgdD10aGlzLk0uc2xpY2UoKTt0aGlzLk09W10sdC5mb3JFYWNoKHQ9Pnt0WzBdfHwoMT09PXRoaXMuTCYmdFsxXSh0aGlzLkopLDI9PT10aGlzLkwmJnRbMl0odGhpcy5KKSx0WzBdPSEwKX0pfUYodCl7Y29uc3Qgbj0odCxuKT0+ezA9PT10aGlzLkwmJihqKG4pP24udGhlbihlLHIpOih0aGlzLkw9dCx0aGlzLko9bix0aGlzLkcoKSkpfSxlPXQ9PntuKDEsdCl9LHI9dD0+e24oMix0KX07dHJ5e3QoZSxyKX1jYXRjaCh0KXtyKHQpfX19Y29uc3QgV3Q9U3ltYm9sLmZvcigiU2VudHJ5QnVmZmVyRnVsbEVycm9yIik7ZnVuY3Rpb24gWXQodD0xMDApe2NvbnN0IG49bmV3IFNldDtmdW5jdGlvbiBlKHQpe24uZGVsZXRlKHQpfXJldHVybntnZXQgJCgpe3JldHVybiBBcnJheS5mcm9tKG4pfSxhZGQ6ZnVuY3Rpb24ocil7aWYoIShuLnNpemU8dCkpcmV0dXJuIG89V3QsbmV3IEp0KCh0LG4pPT57bihvKX0pO3ZhciBvO2NvbnN0IGk9cigpO3JldHVybiBuLmFkZChpKSxpLnRoZW4oKCk9PmUoaSksKCk9PmUoaSkpLGl9LGRyYWluOmZ1bmN0aW9uKHQpe2lmKCFuLnNpemUpcmV0dXJuIGU9ITAsbmV3IEp0KHQ9Pnt0KGUpfSk7dmFyIGU7Y29uc3Qgcj1Qcm9taXNlLmFsbFNldHRsZWQoQXJyYXkuZnJvbShuKSkudGhlbigoKT0+ITApO2lmKCF0KXJldHVybiByO2NvbnN0IG89W3IsbmV3IFByb21pc2Uobj0+e3JldHVybiJvYmplY3QiPT10eXBlb2YoZT1zZXRUaW1lb3V0KCgpPT5uKCExKSx0KSkmJiJmdW5jdGlvbiI9PXR5cGVvZiBlLnVucmVmJiZlLnVucmVmKCksZTt2YXIgZX0pXTtyZXR1cm4gUHJvbWlzZS5yYWNlKG8pfX19ZnVuY3Rpb24gSHQodCx7c3RhdHVzQ29kZTpuLGhlYWRlcnM6ZX0scj1QKCkpe2NvbnN0IG89ey4uLnR9LGk9ZT8uWyJ4LXNlbnRyeS1yYXRlLWxpbWl0cyJdLHM9ZT8uWyJyZXRyeS1hZnRlciJdO2lmKGkpZm9yKGNvbnN0IHQgb2YgaS50cmltKCkuc3BsaXQoIiwiKSl7Y29uc3RbbixlLCwsaV09dC5zcGxpdCgiOiIsNSkscz1wYXJzZUludChuLDEwKSxjPTFlMyooaXNOYU4ocyk/NjA6cyk7aWYoZSlmb3IoY29uc3QgdCBvZiBlLnNwbGl0KCI7IikpIm1ldHJpY19idWNrZXQiPT09dCYmaSYmIWkuc3BsaXQoIjsiKS5pbmNsdWRlcygiY3VzdG9tIil8fChvW3RdPXIrYyk7ZWxzZSBvLmFsbD1yK2N9ZWxzZSBzP28uYWxsPXIrZnVuY3Rpb24odCxuPVAoKSl7Y29uc3QgZT1wYXJzZUludChgJHt0fWAsMTApO2lmKCFpc05hTihlKSlyZXR1cm4gMWUzKmU7Y29uc3Qgcj1EYXRlLnBhcnNlKGAke3R9YCk7cmV0dXJuIGlzTmFOKHIpPzZlNDpyLW59KHMscik6NDI5PT09biYmKG8uYWxsPXIrNmU0KTtyZXR1cm4gb31mdW5jdGlvbiBLdCh0LG4sZT1ZdCh0LmJ1ZmZlclNpemV8fDY0KSl7bGV0IHI9e307cmV0dXJue3NlbmQ6ZnVuY3Rpb24odCl7Y29uc3Qgbz1bXTtpZihrdCh0LCh0LG4pPT57Y29uc3QgZT1CdChuKTsoZnVuY3Rpb24odCxuLGU9UCgpKXtyZXR1cm4gZnVuY3Rpb24odCxuKXtyZXR1cm4gdFtuXXx8dC5hbGx8fDB9KHQsbik+ZX0pKHIsZSl8fG8ucHVzaCh0KX0pLDA9PT1vLmxlbmd0aClyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtjb25zdCBpPVR0KHRbMF0sbykscz10PT57IWZ1bmN0aW9uKHQsbil7cmV0dXJuIGt0KHQsKHQsZSk9Pm4uaW5jbHVkZXMoZSkpfShpLFsiY2xpZW50X3JlcG9ydCJdKT9rdChpLCh0LG4pPT57fSk6aCYmdy53YXJuKGBEcm9wcGluZyBjbGllbnQgcmVwb3J0LiBXaWxsIG5vdCBzZW5kIG91dGNvbWVzIChyZWFzb246ICR7dH0pLmApfTtyZXR1cm4gZS5hZGQoKCk9Pm4oe2JvZHk6RHQoaSl9KS50aGVuKHQ9PjQxMz09PXQuc3RhdHVzQ29kZT8oaCYmdy5lcnJvcigiU2VudHJ5IHJlc3BvbmRlZCB3aXRoIHN0YXR1cyBjb2RlIDQxMy4gRW52ZWxvcGUgd2FzIGRpc2NhcmRlZCBkdWUgdG8gZXhjZWVkaW5nIHNpemUgbGltaXRzLiIpLHMoInNlbmRfZXJyb3IiKSx0KTooaCYmdm9pZCAwIT09dC5zdGF0dXNDb2RlJiYodC5zdGF0dXNDb2RlPDIwMHx8dC5zdGF0dXNDb2RlPj0zMDApJiZ3Lndhcm4oYFNlbnRyeSByZXNwb25kZWQgd2l0aCBzdGF0dXMgY29kZSAke3Quc3RhdHVzQ29kZX0gdG8gc2VudCBldmVudC5gKSxyPUh0KHIsdCksdCksdD0+e3Rocm93IHMoIm5ldHdvcmtfZXJyb3IiKSxoJiZ3LmVycm9yKCJFbmNvdW50ZXJlZCBlcnJvciBydW5uaW5nIHRyYW5zcG9ydCByZXF1ZXN0OiIsdCksdH0pKS50aGVuKHQ9PnQsdD0+e2lmKHQ9PT1XdClyZXR1cm4gaCYmdy5lcnJvcigiU2tpcHBlZCBzZW5kaW5nIGV2ZW50IGJlY2F1c2UgYnVmZmVyIGlzIGZ1bGwuIikscygicXVldWVfb3ZlcmZsb3ciKSxQcm9taXNlLnJlc29sdmUoe30pO3Rocm93IHR9KX0sZmx1c2g6dD0+ZS5kcmFpbih0KX19Y29uc3QgWnQ9L14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvO2Z1bmN0aW9uIHF0KHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7Y29uc3Qgbj10Lmxlbmd0aD4xMDI0P2A8dHJ1bmNhdGVkPiR7dC5zbGljZSgtMTAyNCl9YDp0LGU9WnQuZXhlYyhuKTtyZXR1cm4gZT9lLnNsaWNlKDEpOltdfSh0KSxlPW5bMF18fCIiO2xldCByPW5bMV07cmV0dXJuIGV8fHI/KHImJihyPXIuc2xpY2UoMCxyLmxlbmd0aC0xKSksZStyKToiLiJ9ZnVuY3Rpb24gVnQodCxuPSExKXtyZXR1cm4hKG58fHQmJiF0LnN0YXJ0c1dpdGgoIi8iKSYmIXQubWF0Y2goL15bQS1aXTovKSYmIXQuc3RhcnRzV2l0aCgiLiIpJiYhdC5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSkmJnZvaWQgMCE9PXQmJiF0LmluY2x1ZGVzKCJub2RlX21vZHVsZXMvIil9dmFyIFF0O2NvbnN0IFh0PVN5bWJvbCgiQWdlbnRCYXNlSW50ZXJuYWxTdGF0ZSIpO2NsYXNzIHRuIGV4dGVuZHMoUXQ9aS5BZ2VudCxRdCl7Y29uc3RydWN0b3IodCl7c3VwZXIodCksdGhpc1tYdF09e319aXNTZWN1cmVFbmRwb2ludCh0KXtpZih0KXtpZigiYm9vbGVhbiI9PXR5cGVvZiB0LnNlY3VyZUVuZHBvaW50KXJldHVybiB0LnNlY3VyZUVuZHBvaW50O2lmKCJzdHJpbmciPT10eXBlb2YgdC5wcm90b2NvbClyZXR1cm4iaHR0cHM6Ij09PXQucHJvdG9jb2x9Y29uc3R7c3RhY2s6bn09bmV3IEVycm9yO3JldHVybiJzdHJpbmciPT10eXBlb2YgbiYmbi5zcGxpdCgiXG4iKS5zb21lKHQ9Pi0xIT09dC5pbmRleE9mKCIoaHR0cHMuanM6Iil8fC0xIT09dC5pbmRleE9mKCJub2RlOmh0dHBzOiIpKX1jcmVhdGVTb2NrZXQodCxuLGUpe2NvbnN0IHI9ey4uLm4sc2VjdXJlRW5kcG9pbnQ6dGhpcy5pc1NlY3VyZUVuZHBvaW50KG4pfTtQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpPT50aGlzLmNvbm5lY3QodCxyKSkudGhlbihvPT57aWYobyBpbnN0YW5jZW9mIGkuQWdlbnQpcmV0dXJuIG8uYWRkUmVxdWVzdCh0LHIpO3RoaXNbWHRdLmN1cnJlbnRTb2NrZXQ9byxzdXBlci5jcmVhdGVTb2NrZXQodCxuLGUpfSxlKX1jcmVhdGVDb25uZWN0aW9uKCl7Y29uc3QgdD10aGlzW1h0XS5jdXJyZW50U29ja2V0O2lmKHRoaXNbWHRdLmN1cnJlbnRTb2NrZXQ9dm9pZCAwLCF0KXRocm93IG5ldyBFcnJvcigiTm8gc29ja2V0IHdhcyByZXR1cm5lZCBpbiB0aGUgYGNvbm5lY3QoKWAgZnVuY3Rpb24iKTtyZXR1cm4gdH1nZXQgZGVmYXVsdFBvcnQoKXtyZXR1cm4gdGhpc1tYdF0uZGVmYXVsdFBvcnQ/PygiaHR0cHM6Ij09PXRoaXMucHJvdG9jb2w/NDQzOjgwKX1zZXQgZGVmYXVsdFBvcnQodCl7dGhpc1tYdF0mJih0aGlzW1h0XS5kZWZhdWx0UG9ydD10KX1nZXQgcHJvdG9jb2woKXtyZXR1cm4gdGhpc1tYdF0ucHJvdG9jb2w/Pyh0aGlzLmlzU2VjdXJlRW5kcG9pbnQoKT8iaHR0cHM6IjoiaHR0cDoiKX1zZXQgcHJvdG9jb2wodCl7dGhpc1tYdF0mJih0aGlzW1h0XS5wcm90b2NvbD10KX19ZnVuY3Rpb24gbm4oLi4udCl7dy5sb2coIltodHRwcy1wcm94eS1hZ2VudDpwYXJzZS1wcm94eS1yZXNwb25zZV0iLC4uLnQpfWZ1bmN0aW9uIGVuKHQpe3JldHVybiBuZXcgUHJvbWlzZSgobixlKT0+e2xldCByPTA7Y29uc3Qgbz1bXTtmdW5jdGlvbiBpKCl7Y29uc3QgYz10LnJlYWQoKTtjP2Z1bmN0aW9uKGMpe28ucHVzaChjKSxyKz1jLmxlbmd0aDtjb25zdCB1PUJ1ZmZlci5jb25jYXQobyxyKSxhPXUuaW5kZXhPZigiXHJcblxyXG4iKTtpZigtMT09PWEpcmV0dXJuIG5uKCJoYXZlIG5vdCByZWNlaXZlZCBlbmQgb2YgSFRUUCBoZWFkZXJzIHlldC4uLiIpLHZvaWQgaSgpO2NvbnN0IGY9dS5zdWJhcnJheSgwLGEpLnRvU3RyaW5nKCJhc2NpaSIpLnNwbGl0KCJcclxuIiksaD1mLnNoaWZ0KCk7aWYoIWgpcmV0dXJuIHQuZGVzdHJveSgpLGUobmV3IEVycm9yKCJObyBoZWFkZXIgcmVjZWl2ZWQgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlIikpO2NvbnN0IHA9aC5zcGxpdCgiICIpLGQ9KyhwWzFdfHwwKSxsPXAuc2xpY2UoMikuam9pbigiICIpLGc9e307Zm9yKGNvbnN0IG4gb2YgZil7aWYoIW4pY29udGludWU7Y29uc3Qgcj1uLmluZGV4T2YoIjoiKTtpZigtMT09PXIpcmV0dXJuIHQuZGVzdHJveSgpLGUobmV3IEVycm9yKGBJbnZhbGlkIGhlYWRlciBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2U6ICIke259ImApKTtjb25zdCBvPW4uc2xpY2UoMCxyKS50b0xvd2VyQ2FzZSgpLGk9bi5zbGljZShyKzEpLnRyaW1TdGFydCgpLHM9Z1tvXTsic3RyaW5nIj09dHlwZW9mIHM/Z1tvXT1bcyxpXTpBcnJheS5pc0FycmF5KHMpP3MucHVzaChpKTpnW29dPWl9bm4oImdvdCBwcm94eSBzZXJ2ZXIgcmVzcG9uc2U6ICVvICVvIixoLGcpLHMoKSxuKHtjb25uZWN0OntzdGF0dXNDb2RlOmQsc3RhdHVzVGV4dDpsLGhlYWRlcnM6Z30sYnVmZmVyZWQ6dX0pfShjKTp0Lm9uY2UoInJlYWRhYmxlIixpKX1mdW5jdGlvbiBzKCl7dC5yZW1vdmVMaXN0ZW5lcigiZW5kIixjKSx0LnJlbW92ZUxpc3RlbmVyKCJlcnJvciIsdSksdC5yZW1vdmVMaXN0ZW5lcigicmVhZGFibGUiLGkpfWZ1bmN0aW9uIGMoKXtzKCksbm4oIm9uZW5kIiksZShuZXcgRXJyb3IoIlByb3h5IGNvbm5lY3Rpb24gZW5kZWQgYmVmb3JlIHJlY2VpdmluZyBDT05ORUNUIHJlc3BvbnNlIikpfWZ1bmN0aW9uIHUodCl7cygpLG5uKCJvbmVycm9yICVvIix0KSxlKHQpfXQub24oImVycm9yIix1KSx0Lm9uKCJlbmQiLGMpLGkoKX0pfWZ1bmN0aW9uIHJuKC4uLnQpe3cubG9nKCJbaHR0cHMtcHJveHktYWdlbnRdIiwuLi50KX1jbGFzcyBvbiBleHRlbmRzIHRue2NvbnN0cnVjdG9yKHQsbil7c3VwZXIobiksdGhpcy5vcHRpb25zPXt9LHRoaXMucHJveHk9InN0cmluZyI9PXR5cGVvZiB0P25ldyBVUkwodCk6dCx0aGlzLnByb3h5SGVhZGVycz1uPy5oZWFkZXJzPz97fSxybigiQ3JlYXRpbmcgbmV3IEh0dHBzUHJveHlBZ2VudCBpbnN0YW5jZTogJW8iLHRoaXMucHJveHkuaHJlZik7Y29uc3QgZT0odGhpcy5wcm94eS5ob3N0bmFtZXx8dGhpcy5wcm94eS5ob3N0KS5yZXBsYWNlKC9eXFt8XF0kL2csIiIpLHI9dGhpcy5wcm94eS5wb3J0P3BhcnNlSW50KHRoaXMucHJveHkucG9ydCwxMCk6Imh0dHBzOiI9PT10aGlzLnByb3h5LnByb3RvY29sPzQ0Mzo4MDt0aGlzLmNvbm5lY3RPcHRzPXtBTFBOUHJvdG9jb2xzOlsiaHR0cC8xLjEiXSwuLi5uP2NuKG4sImhlYWRlcnMiKTpudWxsLGhvc3Q6ZSxwb3J0OnJ9fWFzeW5jIGNvbm5lY3QodCxuKXtjb25zdHtwcm94eTplfT10aGlzO2lmKCFuLmhvc3QpdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gImhvc3QiIHByb3ZpZGVkJyk7bGV0IHI7aWYoImh0dHBzOiI9PT1lLnByb3RvY29sKXtybigiQ3JlYXRpbmcgYHRscy5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cyk7Y29uc3QgdD10aGlzLmNvbm5lY3RPcHRzLnNlcnZlcm5hbWV8fHRoaXMuY29ubmVjdE9wdHMuaG9zdDtyPWYuY29ubmVjdCh7Li4udGhpcy5jb25uZWN0T3B0cyxzZXJ2ZXJuYW1lOnQmJmEuaXNJUCh0KT92b2lkIDA6dH0pfWVsc2Ugcm4oIkNyZWF0aW5nIGBuZXQuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpLHI9YS5jb25uZWN0KHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IG89ImZ1bmN0aW9uIj09dHlwZW9mIHRoaXMucHJveHlIZWFkZXJzP3RoaXMucHJveHlIZWFkZXJzKCk6ey4uLnRoaXMucHJveHlIZWFkZXJzfSxpPWEuaXNJUHY2KG4uaG9zdCk/YFske24uaG9zdH1dYDpuLmhvc3Q7bGV0IHM9YENPTk5FQ1QgJHtpfToke24ucG9ydH0gSFRUUC8xLjFcclxuYDtpZihlLnVzZXJuYW1lfHxlLnBhc3N3b3JkKXtjb25zdCB0PWAke2RlY29kZVVSSUNvbXBvbmVudChlLnVzZXJuYW1lKX06JHtkZWNvZGVVUklDb21wb25lbnQoZS5wYXNzd29yZCl9YDtvWyJQcm94eS1BdXRob3JpemF0aW9uIl09YEJhc2ljICR7QnVmZmVyLmZyb20odCkudG9TdHJpbmcoImJhc2U2NCIpfWB9by5Ib3N0PWAke2l9OiR7bi5wb3J0fWAsb1siUHJveHktQ29ubmVjdGlvbiJdfHwob1siUHJveHktQ29ubmVjdGlvbiJdPXRoaXMua2VlcEFsaXZlPyJLZWVwLUFsaXZlIjoiY2xvc2UiKTtmb3IoY29uc3QgdCBvZiBPYmplY3Qua2V5cyhvKSlzKz1gJHt0fTogJHtvW3RdfVxyXG5gO2NvbnN0IGM9ZW4ocik7ci53cml0ZShgJHtzfVxyXG5gKTtjb25zdHtjb25uZWN0OnUsYnVmZmVyZWQ6aH09YXdhaXQgYztpZih0LmVtaXQoInByb3h5Q29ubmVjdCIsdSksdGhpcy5lbWl0KCJwcm94eUNvbm5lY3QiLHUsdCksMjAwPT09dS5zdGF0dXNDb2RlKXtpZih0Lm9uY2UoInNvY2tldCIsc24pLG4uc2VjdXJlRW5kcG9pbnQpe3JuKCJVcGdyYWRpbmcgc29ja2V0IGNvbm5lY3Rpb24gdG8gVExTIik7Y29uc3QgdD1uLnNlcnZlcm5hbWV8fG4uaG9zdDtyZXR1cm4gZi5jb25uZWN0KHsuLi5jbihuLCJob3N0IiwicGF0aCIsInBvcnQiKSxzb2NrZXQ6cixzZXJ2ZXJuYW1lOmEuaXNJUCh0KT92b2lkIDA6dH0pfXJldHVybiByfXIuZGVzdHJveSgpO2NvbnN0IHA9bmV3IGEuU29ja2V0KHt3cml0YWJsZTohMX0pO3JldHVybiBwLnJlYWRhYmxlPSEwLHQub25jZSgic29ja2V0Iix0PT57cm4oIlJlcGxheWluZyBwcm94eSBidWZmZXIgZm9yIGZhaWxlZCByZXF1ZXN0IiksdC5wdXNoKGgpLHQucHVzaChudWxsKX0pLHB9fWZ1bmN0aW9uIHNuKHQpe3QucmVzdW1lKCl9ZnVuY3Rpb24gY24odCwuLi5uKXtjb25zdCBlPXt9O2xldCByO2ZvcihyIGluIHQpbi5pbmNsdWRlcyhyKXx8KGVbcl09dFtyXSk7cmV0dXJuIGV9b24ucHJvdG9jb2xzPVsiaHR0cCIsImh0dHBzIl07ZnVuY3Rpb24gdW4odCl7cmV0dXJuIHQucmVwbGFjZSgvXltBLVpdOi8sIiIpLnJlcGxhY2UoL1xcL2csIi8iKX1jb25zdCBhbj1uO2xldCBmbixobj0wLHBuPXt9O2Z1bmN0aW9uIGRuKHQpe2FuLmRlYnVnJiZjb25zb2xlLmxvZyhgW0FOUiBXb3JrZXJdICR7dH1gKX12YXIgbG4sZ24sbW47Y29uc3QgeW49ZnVuY3Rpb24odCl7bGV0IG47dHJ5e249bmV3IFVSTCh0LnVybCl9Y2F0Y2gobil7cmV0dXJuIGIoKCk9Pntjb25zb2xlLndhcm4oIltAc2VudHJ5L25vZGVdOiBJbnZhbGlkIGRzbiBvciB0dW5uZWwgb3B0aW9uLCB3aWxsIG5vdCBzZW5kIGFueSBldmVudHMuIFRoZSB0dW5uZWwgb3B0aW9uIG11c3QgYmUgYSBmdWxsIFVSTCB3aGVuIHVzZWQuIil9KSxLdCh0LCgpPT5Qcm9taXNlLnJlc29sdmUoe30pKX1jb25zdCBlPSJodHRwczoiPT09bi5wcm90b2NvbCxyPWZ1bmN0aW9uKHQsbil7Y29uc3R7bm9fcHJveHk6ZX09cHJvY2Vzcy5lbnYscj1lPy5zcGxpdCgiLCIpLnNvbWUobj0+dC5ob3N0LmVuZHNXaXRoKG4pfHx0Lmhvc3RuYW1lLmVuZHNXaXRoKG4pKTtyZXR1cm4gcj92b2lkIDA6bn0obix0LnByb3h5fHwoZT9wcm9jZXNzLmVudi5odHRwc19wcm94eTp2b2lkIDApfHxwcm9jZXNzLmVudi5odHRwX3Byb3h5KSxvPWU/czppLGE9dm9pZCAwIT09dC5rZWVwQWxpdmUmJnQua2VlcEFsaXZlLGY9cj9uZXcgb24ocik6bmV3IG8uQWdlbnQoe2tlZXBBbGl2ZTphLG1heFNvY2tldHM6MzAsdGltZW91dDoyZTN9KSxoPWZ1bmN0aW9uKHQsbixlKXtjb25zdHtob3N0bmFtZTpyLHBhdGhuYW1lOm8scG9ydDppLHByb3RvY29sOnMsc2VhcmNoOmF9PW5ldyBVUkwodC51cmwpO3JldHVybiBmdW5jdGlvbihmKXtyZXR1cm4gbmV3IFByb21pc2UoKGgscCk9PntGdCgoKT0+e2xldCBkPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgYyh7cmVhZCgpe3RoaXMucHVzaCh0KSx0aGlzLnB1c2gobnVsbCl9fSl9KGYuYm9keSk7Y29uc3QgbD17Li4udC5oZWFkZXJzfTtmLmJvZHkubGVuZ3RoPjMyNzY4JiYobFsiY29udGVudC1lbmNvZGluZyJdPSJnemlwIixkPWQucGlwZSh1KCkpKTtjb25zdCBnPXIuc3RhcnRzV2l0aCgiWyIpLG09bi5yZXF1ZXN0KHttZXRob2Q6IlBPU1QiLGFnZW50OmUsaGVhZGVyczpsLGhvc3RuYW1lOmc/ci5zbGljZSgxLC0xKTpyLHBhdGg6YCR7b30ke2F9YCxwb3J0OmkscHJvdG9jb2w6cyxjYTp0LmNhQ2VydHN9LHQ9Pnt0Lm9uKCJkYXRhIiwoKT0+e30pLHQub24oImVuZCIsKCk9Pnt9KSx0LnNldEVuY29kaW5nKCJ1dGY4Iik7Y29uc3Qgbj10LmhlYWRlcnNbInJldHJ5LWFmdGVyIl0/P251bGwsZT10LmhlYWRlcnNbIngtc2VudHJ5LXJhdGUtbGltaXRzIl0/P251bGw7aCh7c3RhdHVzQ29kZTp0LnN0YXR1c0NvZGUsaGVhZGVyczp7InJldHJ5LWFmdGVyIjpuLCJ4LXNlbnRyeS1yYXRlLWxpbWl0cyI6QXJyYXkuaXNBcnJheShlKT9lWzBdfHxudWxsOmV9fSl9KTttLm9uKCJlcnJvciIscCksZC5waXBlKG0pfSl9KX19KHQsdC5odHRwTW9kdWxlPz9vLGYpO3JldHVybiBLdCh0LGgpfSh7dXJsOihsbj1hbi5kc24sZ249YW4udHVubmVsLG1uPWFuLnNka01ldGFkYXRhLnNkayxnbnx8YCR7ZnVuY3Rpb24odCl7cmV0dXJuYCR7ZnVuY3Rpb24odCl7Y29uc3Qgbj10LnByb3RvY29sP2Ake3QucHJvdG9jb2x9OmA6IiIsZT10LnBvcnQ/YDoke3QucG9ydH1gOiIiO3JldHVybmAke259Ly8ke3QuaG9zdH0ke2V9JHt0LnBhdGg/YC8ke3QucGF0aH1gOiIifS9hcGkvYH0odCl9JHt0LnByb2plY3RJZH0vZW52ZWxvcGUvYH0obG4pfT8ke2Z1bmN0aW9uKHQsbil7Y29uc3QgZT17c2VudHJ5X3ZlcnNpb246IjcifTtyZXR1cm4gdC5wdWJsaWNLZXkmJihlLnNlbnRyeV9rZXk9dC5wdWJsaWNLZXkpLG4mJihlLnNlbnRyeV9jbGllbnQ9YCR7bi5uYW1lfS8ke24udmVyc2lvbn1gKSxuZXcgVVJMU2VhcmNoUGFyYW1zKGUpLnRvU3RyaW5nKCl9KGxuLG1uKX1gKX0pO2FzeW5jIGZ1bmN0aW9uIGJuKCl7aWYoZm4pe2RuKCJTZW5kaW5nIGFibm9ybWFsIHNlc3Npb24iKSxLKGZuLHtzdGF0dXM6ImFibm9ybWFsIixhYm5vcm1hbF9tZWNoYW5pc206ImFucl9mb3JlZ3JvdW5kIixyZWxlYXNlOmFuLnJlbGVhc2UsZW52aXJvbm1lbnQ6YW4uZW52aXJvbm1lbnR9KTtjb25zdCB0PWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89THQoZSk7cmV0dXJuIFR0KHtzZW50X2F0Om5ldyBEYXRlKFAoKSkudG9JU09TdHJpbmcoKSwuLi5vJiZ7c2RrOm99LC4uLiEhciYmbiYme2RzbjpidChuKX19LFsiYWdncmVnYXRlcyJpbiB0P1t7dHlwZToic2Vzc2lvbnMifSx0XTpbe3R5cGU6InNlc3Npb24ifSx0LnRvSlNPTigpXV0pfShmbixhbi5kc24sYW4uc2RrTWV0YWRhdGEsYW4udHVubmVsKTtkbihKU09OLnN0cmluZ2lmeSh0KSksYXdhaXQgeW4uc2VuZCh0KTt0cnl7ZT8ucG9zdE1lc3NhZ2UoInNlc3Npb24tZW5kZWQiKX1jYXRjaHt9fX1mdW5jdGlvbiB2bih0KXtpZighdClyZXR1cm47Y29uc3Qgbj1mdW5jdGlvbih0KXtpZighdC5sZW5ndGgpcmV0dXJuW107Y29uc3Qgbj1BcnJheS5mcm9tKHQpO3JldHVybi9zZW50cnlXcmFwcGVkLy50ZXN0KEUobikuZnVuY3Rpb258fCIiKSYmbi5wb3AoKSxuLnJldmVyc2UoKSwkLnRlc3QoRShuKS5mdW5jdGlvbnx8IiIpJiYobi5wb3AoKSwkLnRlc3QoRShuKS5mdW5jdGlvbnx8IiIpJiZuLnBvcCgpKSxuLnNsaWNlKDAsNTApLm1hcCh0PT4oey4uLnQsZmlsZW5hbWU6dC5maWxlbmFtZXx8RShuKS5maWxlbmFtZSxmdW5jdGlvbjp0LmZ1bmN0aW9ufHwiPyJ9KSl9KHQpO2lmKGFuLmFwcFJvb3RQYXRoKWZvcihjb25zdCB0IG9mIG4pdC5maWxlbmFtZSYmKHQuZmlsZW5hbWU9TSh0LmZpbGVuYW1lLGFuLmFwcFJvb3RQYXRoKSk7cmV0dXJuIG59YXN5bmMgZnVuY3Rpb24gX24odCxuKXtpZihobj49YW4ubWF4QW5yRXZlbnRzKXJldHVybjtobis9MSxhd2FpdCBibigpLGRuKCJTZW5kaW5nIGV2ZW50Iik7Y29uc3QgZT17ZXZlbnRfaWQ6RygpLGNvbnRleHRzOmFuLmNvbnRleHRzLHJlbGVhc2U6YW4ucmVsZWFzZSxlbnZpcm9ubWVudDphbi5lbnZpcm9ubWVudCxkaXN0OmFuLmRpc3QscGxhdGZvcm06Im5vZGUiLGxldmVsOiJlcnJvciIsZXhjZXB0aW9uOnt2YWx1ZXM6W3t0eXBlOiJBcHBsaWNhdGlvbk5vdFJlc3BvbmRpbmciLHZhbHVlOmBBcHBsaWNhdGlvbiBOb3QgUmVzcG9uZGluZyBmb3IgYXQgbGVhc3QgJHthbi5hbnJUaHJlc2hvbGR9IG1zYCxzdGFja3RyYWNlOntmcmFtZXM6dm4odCl9LG1lY2hhbmlzbTp7dHlwZToiQU5SIn19XX0sdGFnczphbi5zdGF0aWNUYWdzfTtuJiZmdW5jdGlvbih0LG4pe2lmKEd0KHQsbiksIXQuY29udGV4dHM/LnRyYWNlKXtjb25zdHt0cmFjZUlkOmUscGFyZW50U3BhbklkOnIscHJvcGFnYXRpb25TcGFuSWQ6b309bi5wcm9wYWdhdGlvbkNvbnRleHQ7dC5jb250ZXh0cz17dHJhY2U6e3RyYWNlX2lkOmUsc3Bhbl9pZDpvfHxWKCkscGFyZW50X3NwYW5faWQ6cn0sLi4udC5jb250ZXh0c319fShlLG4pLGZ1bmN0aW9uKHQpe2lmKDA9PT1PYmplY3Qua2V5cyhwbikubGVuZ3RoKXJldHVybjtjb25zdCBuPWFuLmFwcFJvb3RQYXRoP3t9OnBuO2lmKGFuLmFwcFJvb3RQYXRoKWZvcihjb25zdFt0LGVdb2YgT2JqZWN0LmVudHJpZXMocG4pKW5bTSh0LGFuLmFwcFJvb3RQYXRoKV09ZTtjb25zdCBlPW5ldyBNYXA7Zm9yKGNvbnN0IHIgb2YgdC5leGNlcHRpb24/LnZhbHVlc3x8W10pZm9yKGNvbnN0IHQgb2Ygci5zdGFja3RyYWNlPy5mcmFtZXN8fFtdKXtjb25zdCByPXQuYWJzX3BhdGh8fHQuZmlsZW5hbWU7ciYmbltyXSYmZS5zZXQocixuW3JdKX1pZihlLnNpemU+MCl7Y29uc3Qgbj1bXTtmb3IoY29uc3RbdCxyXW9mIGUuZW50cmllcygpKW4ucHVzaCh7dHlwZToic291cmNlbWFwIixjb2RlX2ZpbGU6dCxkZWJ1Z19pZDpyfSk7dC5kZWJ1Z19tZXRhPXtpbWFnZXM6bn19fShlKTtjb25zdCByPU10KGUsYW4uZHNuLGFuLnNka01ldGFkYXRhLGFuLnR1bm5lbCk7ZG4oSlNPTi5zdHJpbmdpZnkocikpLGF3YWl0IHluLnNlbmQociksYXdhaXQgeW4uZmx1c2goMmUzKSxobj49YW4ubWF4QW5yRXZlbnRzJiZzZXRUaW1lb3V0KCgpPT57cHJvY2Vzcy5leGl0KDApfSw1ZTMpfWxldCBTbjtpZihkbigiU3RhcnRlZCIpLGFuLmNhcHR1cmVTdGFja1RyYWNlKXtkbigiQ29ubmVjdGluZyB0byBkZWJ1Z2dlciIpO2NvbnN0IG49bmV3IHQ7bi5jb25uZWN0VG9NYWluVGhyZWFkKCksZG4oIkNvbm5lY3RlZCB0byBkZWJ1Z2dlciIpO2NvbnN0IGU9bmV3IE1hcDtuLm9uKCJEZWJ1Z2dlci5zY3JpcHRQYXJzZWQiLHQ9PntlLnNldCh0LnBhcmFtcy5zY3JpcHRJZCx0LnBhcmFtcy51cmwpfSksbi5vbigiRGVidWdnZXIucGF1c2VkIix0PT57aWYoIm90aGVyIj09PXQucGFyYW1zLnJlYXNvbil0cnl7ZG4oIkRlYnVnZ2VyIHBhdXNlZCIpO2NvbnN0IGk9Wy4uLnQucGFyYW1zLmNhbGxGcmFtZXNdLHM9YW4uYXBwUm9vdFBhdGg/ZnVuY3Rpb24odD0ocHJvY2Vzcy5hcmd2WzFdP3F0KHByb2Nlc3MuYXJndlsxXSk6cHJvY2Vzcy5jd2QoKSksbj0iXFwiPT09byl7Y29uc3QgZT1uP3VuKHQpOnQ7cmV0dXJuIHQ9PntpZighdClyZXR1cm47Y29uc3Qgbz1uP3VuKHQpOnQ7bGV0e2RpcjppLGJhc2U6cyxleHQ6Y309ci5wYXJzZShvKTsiLmpzIiE9PWMmJiIubWpzIiE9PWMmJiIuY2pzIiE9PWN8fChzPXMuc2xpY2UoMCwtMSpjLmxlbmd0aCkpO2NvbnN0IHU9ZGVjb2RlVVJJQ29tcG9uZW50KHMpO2l8fChpPSIuIik7Y29uc3QgYT1pLmxhc3RJbmRleE9mKCIvbm9kZV9tb2R1bGVzIik7aWYoYT4tMSlyZXR1cm5gJHtpLnNsaWNlKGErMTQpLnJlcGxhY2UoL1wvL2csIi4iKX06JHt1fWA7aWYoaS5zdGFydHNXaXRoKGUpKXtjb25zdCB0PWkuc2xpY2UoZS5sZW5ndGgrMSkucmVwbGFjZSgvXC8vZywiLiIpO3JldHVybiB0P2Ake3R9OiR7dX1gOnV9cmV0dXJuIHV9fShhbi5hcHBSb290UGF0aCk6KCk9Pnt9LGM9aS5tYXAodD0+ZnVuY3Rpb24odCxuLGUpe2NvbnN0IHI9bj9uLnJlcGxhY2UoL15maWxlOlwvXC8vLCIiKTp2b2lkIDAsbz10LmxvY2F0aW9uLmNvbHVtbk51bWJlcj90LmxvY2F0aW9uLmNvbHVtbk51bWJlcisxOnZvaWQgMCxpPXQubG9jYXRpb24ubGluZU51bWJlcj90LmxvY2F0aW9uLmxpbmVOdW1iZXIrMTp2b2lkIDA7cmV0dXJue2ZpbGVuYW1lOnIsbW9kdWxlOmUociksZnVuY3Rpb246dC5mdW5jdGlvbk5hbWV8fCI/Iixjb2xubzpvLGxpbmVubzppLGluX2FwcDpyP1Z0KHIpOnZvaWQgMH19KHQsZS5nZXQodC5sb2NhdGlvbi5zY3JpcHRJZCkscykpLHU9c2V0VGltZW91dCgoKT0+e19uKGMpLnRoZW4obnVsbCwoKT0+e2RuKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuIil9KX0sNWUzKTtuLnBvc3QoIlJ1bnRpbWUuZXZhbHVhdGUiLHtleHByZXNzaW9uOiJnbG9iYWwuX19TRU5UUllfR0VUX1NDT1BFU19fKCk7IixzaWxlbnQ6ITAscmV0dXJuQnlWYWx1ZTohMH0sKHQsZSk9Pnt0JiZkbihgRXJyb3IgZXhlY3V0aW5nIHNjcmlwdDogJyR7dC5tZXNzYWdlfSdgKSxjbGVhclRpbWVvdXQodSk7Y29uc3Qgcj1lPy5yZXN1bHQ/ZS5yZXN1bHQudmFsdWU6dm9pZCAwO24ucG9zdCgiRGVidWdnZXIucmVzdW1lIiksbi5wb3N0KCJEZWJ1Z2dlci5kaXNhYmxlIiksX24oYyxyKS50aGVuKG51bGwsKCk9PntkbigiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSl9KX1jYXRjaCh0KXt0aHJvdyBuLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLG4ucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLHR9fSksU249KCk9Pnt0cnl7bi5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiLCgpPT57bi5wb3N0KCJEZWJ1Z2dlci5wYXVzZSIpfSl9Y2F0Y2h7fX19Y29uc3R7cG9sbDp3bn09ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz10KCk7bGV0IGk9ITEscz0hMDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCk9Pntjb25zdCB0PW8uZ2V0VGltZU1zKCk7ITE9PT1pJiZ0Pm4rZSYmKGk9ITAscyYmcigpKSx0PG4rZSYmKGk9ITEpfSwyMCkse3BvbGw6KCk9PntvLnJlc2V0KCl9LGVuYWJsZWQ6dD0+e3M9dH19fShmdW5jdGlvbigpe2xldCB0PXByb2Nlc3MuaHJ0aW1lKCk7cmV0dXJue2dldFRpbWVNczooKT0+e2NvbnN0W24sZV09cHJvY2Vzcy5ocnRpbWUodCk7cmV0dXJuIE1hdGguZmxvb3IoMWUzKm4rZS8xZTYpfSxyZXNldDooKT0+e3Q9cHJvY2Vzcy5ocnRpbWUoKX19fSxhbi5wb2xsSW50ZXJ2YWwsYW4uYW5yVGhyZXNob2xkLGZ1bmN0aW9uKCl7ZG4oIldhdGNoZG9nIHRpbWVvdXQiKSxTbj8oZG4oIlBhdXNpbmcgZGVidWdnZXIgdG8gY2FwdHVyZSBzdGFjayB0cmFjZSIpLFNuKCkpOihkbigiQ2FwdHVyaW5nIGV2ZW50IHdpdGhvdXQgYSBzdGFjayB0cmFjZSIpLF9uKCkudGhlbihudWxsLCgpPT57ZG4oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZCBvbiB3YXRjaGRvZyB0aW1lb3V0LiIpfSkpfSk7ZT8ub24oIm1lc3NhZ2UiLHQ9Pnt0LnNlc3Npb24mJihmbj1IKHQuc2Vzc2lvbikpLHQuZGVidWdJbWFnZXMmJihwbj10LmRlYnVnSW1hZ2VzKSx3bigpfSk7"; | ||
| const DEFAULT_INTERVAL = 50; | ||
@@ -13,0 +13,0 @@ const DEFAULT_HANG_THRESHOLD = 5e3; |
@@ -79,6 +79,3 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| onSpanCreated?.(span, request, response); | ||
| const rpcMetadata = { | ||
| type: core$1.RPCType.HTTP, | ||
| span | ||
| }; | ||
| const rpcMetadata = { type: core$1.RPCType.HTTP, span }; | ||
| return api.context.with(core$1.setRPCMetadata(api.trace.setSpan(api.context.active(), span), rpcMetadata), () => { | ||
@@ -93,3 +90,3 @@ api.context.bind(api.context.active(), request); | ||
| isEnded = true; | ||
| const newAttributes = getIncomingRequestAttributesOnResponse(request, response); | ||
| const newAttributes = getIncomingRequestAttributesOnResponse(request, response, rpcMetadata); | ||
| span.setAttributes(newAttributes); | ||
@@ -120,7 +117,13 @@ span.setStatus(status); | ||
| if (typeof statusCode === "number") { | ||
| const shouldDrop = shouldFilterStatusCode(statusCode, ignoreStatusCodes); | ||
| if (shouldDrop) { | ||
| if (shouldFilterStatusCode(statusCode, ignoreStatusCodes)) { | ||
| debugBuild.DEBUG_BUILD && core.debug.log("Dropping transaction due to status code", statusCode); | ||
| return null; | ||
| } | ||
| event.contexts = { | ||
| ...event.contexts, | ||
| response: { | ||
| ...event.contexts?.response, | ||
| status_code: statusCode | ||
| } | ||
| }; | ||
| } | ||
@@ -207,3 +210,3 @@ } | ||
| } | ||
| function getIncomingRequestAttributesOnResponse(request, response) { | ||
| function getIncomingRequestAttributesOnResponse(request, response, rpcMetadata) { | ||
| const { socket } = request; | ||
@@ -217,3 +220,2 @@ const { statusCode, statusMessage } = response; | ||
| }; | ||
| const rpcMetadata = core$1.getRPCMetadata(api.context.active()); | ||
| if (socket) { | ||
@@ -220,0 +222,0 @@ const { localAddress, localPort, remoteAddress, remotePort } = socket; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"httpServerSpansIntegration.js","sources":["../../../../src/integrations/http/httpServerSpansIntegration.ts"],"sourcesContent":["import { errorMonitor } from 'node:events';\nimport type { IncomingHttpHeaders } from 'node:http';\nimport { context, SpanKind, trace } from '@opentelemetry/api';\nimport type { RPCMetadata } from '@opentelemetry/core';\nimport { getRPCMetadata, RPCType, setRPCMetadata } from '@opentelemetry/core';\nimport {\n HTTP_RESPONSE_STATUS_CODE,\n HTTP_ROUTE,\n HTTP_STATUS_CODE,\n NET_HOST_IP,\n NET_HOST_PORT,\n NET_PEER_IP,\n} from '@sentry/conventions/attributes';\nimport type {\n Event,\n HttpClientRequest,\n HttpIncomingMessage,\n HttpServerResponse,\n Integration,\n IntegrationFn,\n Span,\n SpanAttributes,\n SpanStatus,\n} from '@sentry/core';\nimport {\n debug,\n getIsolationScope,\n getSpanStatusFromHttpCode,\n httpHeadersToSpanAttributes,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_ERROR,\n stripUrlQueryAndFragment,\n isTracingSuppressed,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport type { NodeClient } from '../../sdk/client';\nimport { addStartSpanCallback } from './httpServerIntegration';\n\nconst INTEGRATION_NAME = 'Http.ServerSpans' as const;\n\n// Tree-shakable guard to remove all code related to tracing\ndeclare const __SENTRY_TRACING__: boolean;\n\nexport interface HttpServerSpansIntegrationOptions {\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: HttpIncomingMessage) => boolean;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with some 3xx and 4xx status codes are ignored (see @default).\n * Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.\n *\n * @default `[[401, 404], [301, 303], [305, 399]]`\n */\n ignoreStatusCodes?: (number | [number, number])[];\n\n /**\n * @deprecated This is deprecated in favor of `incomingRequestSpanHook`.\n */\n instrumentation?: {\n requestHook?: (span: Span, req: HttpClientRequest | HttpIncomingMessage) => void;\n responseHook?: (span: Span, response: HttpIncomingMessage | HttpServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: HttpClientRequest | HttpIncomingMessage,\n response: HttpIncomingMessage | HttpServerResponse,\n ) => void;\n };\n\n /**\n * A hook that can be used to mutate the span for incoming requests.\n * This is triggered after the span is created, but before it is recorded.\n */\n onSpanCreated?: (span: Span, request: HttpIncomingMessage, response: HttpServerResponse) => void;\n}\n\nconst _httpServerSpansIntegration = ((options: HttpServerSpansIntegrationOptions = {}) => {\n const ignoreStaticAssets = options.ignoreStaticAssets ?? true;\n const ignoreIncomingRequests = options.ignoreIncomingRequests;\n const ignoreStatusCodes = options.ignoreStatusCodes ?? [\n [401, 404],\n // 300 and 304 are possibly valid status codes we do not want to filter\n [301, 303],\n [305, 399],\n ];\n\n const { onSpanCreated } = options;\n // eslint-disable-next-line typescript/no-deprecated\n const { requestHook, responseHook, applyCustomAttributesOnSpan } = options.instrumentation ?? {};\n\n return {\n name: INTEGRATION_NAME,\n setup(client: NodeClient) {\n // If no tracing, we can just skip everything here\n if (typeof __SENTRY_TRACING__ !== 'undefined' && !__SENTRY_TRACING__) {\n return;\n }\n\n client.on('httpServerRequest', (_request, _response, normalizedRequest) => {\n // Type-casting this here because we do not want to put the node types into core\n const request = _request as HttpIncomingMessage;\n const response = _response as HttpServerResponse;\n\n const startSpan = (next: () => boolean): boolean => {\n if (\n shouldIgnoreSpansForIncomingRequest(request, {\n ignoreStaticAssets,\n ignoreIncomingRequests,\n })\n ) {\n DEBUG_BUILD && debug.log(INTEGRATION_NAME, 'Skipping span creation for incoming request', request.url);\n return next();\n }\n\n const fullUrl = normalizedRequest.url || request.url || '/';\n const urlObj = parseStringToURLObject(fullUrl);\n\n const headers = request.headers;\n const userAgent = headers['user-agent'];\n const ips = headers['x-forwarded-for'];\n const httpVersion = request.httpVersion;\n const host = headers.host as string | undefined;\n const hostname = host?.replace(/^(.*)(:[0-9]{1,5})/, '$1') || 'localhost';\n\n const tracer = client.tracer;\n const scheme = fullUrl.startsWith('https') ? 'https' : 'http';\n\n const method = normalizedRequest.method || request.method?.toUpperCase() || 'GET';\n const httpTargetWithoutQueryFragment = urlObj ? urlObj.pathname : stripUrlQueryAndFragment(fullUrl);\n const bestEffortTransactionName = `${method} ${httpTargetWithoutQueryFragment}`;\n\n // We use the plain tracer.startSpan here so we can pass the span kind\n const span = tracer.startSpan(bestEffortTransactionName, {\n kind: SpanKind.SERVER,\n attributes: {\n // Sentry specific attributes\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.http',\n 'sentry.http.prefetch': isKnownPrefetchRequest(request) || undefined,\n // Old Semantic Conventions attributes - added for compatibility with what `@opentelemetry/instrumentation-http` output before\n 'http.url': fullUrl,\n 'http.method': normalizedRequest.method,\n 'http.target': urlObj ? `${urlObj.pathname}${urlObj.search}` : httpTargetWithoutQueryFragment,\n 'http.host': host,\n 'net.host.name': hostname,\n 'http.client_ip': typeof ips === 'string' ? ips.split(',')[0] : undefined,\n 'http.user_agent': userAgent,\n 'http.scheme': scheme,\n 'http.flavor': httpVersion,\n 'net.transport': httpVersion?.toUpperCase() === 'QUIC' ? 'ip_udp' : 'ip_tcp',\n ...getRequestContentLengthAttribute(request),\n ...httpHeadersToSpanAttributes(normalizedRequest.headers || {}, client.getDataCollectionOptions()),\n },\n });\n\n // TODO v11: Remove the following three hooks, only onSpanCreated should remain\n requestHook?.(span, request);\n responseHook?.(span, response);\n applyCustomAttributesOnSpan?.(span, request, response);\n onSpanCreated?.(span, request, response);\n\n const rpcMetadata: RPCMetadata = {\n type: RPCType.HTTP,\n span,\n };\n\n return context.with(setRPCMetadata(trace.setSpan(context.active(), span), rpcMetadata), () => {\n context.bind(context.active(), request);\n context.bind(context.active(), response);\n\n // Ensure we only end the span once\n // E.g. error can be emitted before close is emitted\n let isEnded = false;\n function endSpan(status: SpanStatus): void {\n if (isEnded) {\n return;\n }\n\n isEnded = true;\n\n const newAttributes = getIncomingRequestAttributesOnResponse(request, response);\n span.setAttributes(newAttributes);\n span.setStatus(status);\n span.end();\n\n // Update the transaction name if the route has changed\n const route = newAttributes['http.route'];\n if (route) {\n getIsolationScope().setTransactionName(`${request.method?.toUpperCase() || 'GET'} ${route}`);\n }\n }\n\n response.on('close', () => {\n endSpan(getSpanStatusFromHttpCode(response.statusCode));\n });\n response.on(errorMonitor, () => {\n const httpStatus = getSpanStatusFromHttpCode(response.statusCode);\n // Ensure we def. have an error status here\n endSpan(httpStatus.code === SPAN_STATUS_ERROR ? httpStatus : { code: SPAN_STATUS_ERROR });\n });\n\n return next();\n });\n };\n\n addStartSpanCallback(request, startSpan);\n });\n },\n processEvent(event) {\n // Drop transaction if it has a status code that should be ignored\n if (event.type === 'transaction') {\n const statusCode = event.contexts?.trace?.data?.['http.response.status_code'];\n if (typeof statusCode === 'number') {\n const shouldDrop = shouldFilterStatusCode(statusCode, ignoreStatusCodes);\n if (shouldDrop) {\n DEBUG_BUILD && debug.log('Dropping transaction due to status code', statusCode);\n return null;\n }\n }\n }\n\n return event;\n },\n afterAllSetup(client) {\n if (!DEBUG_BUILD) {\n return;\n }\n\n if (client.getIntegrationByName('Http')) {\n debug.warn(\n 'It seems that you have manually added `httpServerSpansIntegration` while `httpIntegration` is also present. Make sure to remove `httpIntegration` when adding `httpServerSpansIntegration`.',\n );\n }\n\n if (!client.getIntegrationByName('Http.Server')) {\n debug.error(\n 'It seems that you have manually added `httpServerSpansIntegration` without adding `httpServerIntegration`. This is a requiement for spans to be created - please add the `httpServerIntegration` integration.',\n );\n }\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * This integration emits spans for incoming requests handled via the node `http` module.\n * It requires the `httpServerIntegration` to be present.\n */\nexport const httpServerSpansIntegration = _httpServerSpansIntegration as (\n options?: HttpServerSpansIntegrationOptions,\n) => Integration & {\n name: 'Http.ServerSpans';\n setup: (client: NodeClient) => void;\n processEvent: (event: Event) => Event | null;\n};\n\nfunction isKnownPrefetchRequest(req: HttpIncomingMessage): 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\n/**\n * Check if a request is for a common static asset that should be ignored by default.\n *\n * Only exported for tests.\n */\nexport function isStaticAssetRequest(urlPath: string): boolean {\n const path = stripUrlQueryAndFragment(urlPath);\n // Common static file extensions\n if (path.match(/\\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {\n return true;\n }\n\n // Common metadata files\n if (path.match(/^\\/(robots\\.txt|sitemap\\.xml|manifest\\.json|browserconfig\\.xml)$/)) {\n return true;\n }\n\n return false;\n}\n\nfunction shouldIgnoreSpansForIncomingRequest(\n request: HttpIncomingMessage,\n {\n ignoreStaticAssets,\n ignoreIncomingRequests,\n }: {\n ignoreStaticAssets?: boolean;\n ignoreIncomingRequests?: (urlPath: string, request: HttpIncomingMessage) => boolean;\n },\n): boolean {\n if (isTracingSuppressed()) {\n return true;\n }\n\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 spans\n if (method === 'OPTIONS' || method === 'HEAD' || !urlPath) {\n return true;\n }\n\n // Default static asset filtering\n if (ignoreStaticAssets && method === 'GET' && isStaticAssetRequest(urlPath)) {\n return true;\n }\n\n if (ignoreIncomingRequests?.(urlPath, request)) {\n return true;\n }\n\n return false;\n}\n\nfunction getRequestContentLengthAttribute(request: HttpIncomingMessage): SpanAttributes {\n const length = getContentLength(request.headers);\n if (length == null) {\n return {};\n }\n\n if (isCompressed(request.headers)) {\n return {\n ['http.request_content_length']: length,\n };\n } else {\n return {\n ['http.request_content_length_uncompressed']: length,\n };\n }\n}\n\nfunction getContentLength(headers: IncomingHttpHeaders): number | null {\n const contentLengthHeader = headers['content-length'];\n if (contentLengthHeader === undefined) return null;\n\n const contentLength = parseInt(contentLengthHeader, 10);\n if (isNaN(contentLength)) return null;\n\n return contentLength;\n}\n\nfunction isCompressed(headers: IncomingHttpHeaders): boolean {\n const encoding = headers['content-encoding'];\n\n return !!encoding && encoding !== 'identity';\n}\n\nfunction getIncomingRequestAttributesOnResponse(\n request: HttpIncomingMessage,\n response: HttpServerResponse,\n): SpanAttributes {\n // take socket from the request,\n // since it may be detached from the response object in keep-alive mode\n const { socket } = request;\n const { statusCode, statusMessage } = response;\n\n const newAttributes: SpanAttributes = {\n [HTTP_RESPONSE_STATUS_CODE]: statusCode,\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_STATUS_CODE]: statusCode,\n 'http.status_text': statusMessage?.toUpperCase(),\n };\n\n const rpcMetadata = getRPCMetadata(context.active());\n if (socket) {\n const { localAddress, localPort, remoteAddress, remotePort } = socket;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_HOST_IP] = localAddress;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_HOST_PORT] = localPort;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_PEER_IP] = remoteAddress;\n newAttributes['net.peer.port'] = remotePort;\n }\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[HTTP_STATUS_CODE] = statusCode;\n newAttributes['http.status_text'] = (statusMessage || '').toUpperCase();\n\n if (rpcMetadata?.type === RPCType.HTTP && rpcMetadata.route !== undefined) {\n const routeName = rpcMetadata.route;\n newAttributes[HTTP_ROUTE] = routeName;\n }\n\n return newAttributes;\n}\n\n/**\n * If the given status code should be filtered for the given list of status codes/ranges.\n */\nfunction shouldFilterStatusCode(statusCode: number, dropForStatusCodes: (number | [number, number])[]): boolean {\n return dropForStatusCodes.some(code => {\n if (typeof code === 'number') {\n return code === statusCode;\n }\n\n const [min, max] = code;\n return statusCode >= min && statusCode <= max;\n });\n}\n"],"names":["DEBUG_BUILD","debug","parseStringToURLObject","stripUrlQueryAndFragment","SpanKind","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","httpHeadersToSpanAttributes","RPCType","context","setRPCMetadata","trace","getIsolationScope","getSpanStatusFromHttpCode","errorMonitor","SPAN_STATUS_ERROR","addStartSpanCallback","isTracingSuppressed","HTTP_RESPONSE_STATUS_CODE","HTTP_STATUS_CODE","getRPCMetadata","NET_HOST_IP","NET_HOST_PORT","NET_PEER_IP","HTTP_ROUTE"],"mappings":"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"} | ||
| {"version":3,"file":"httpServerSpansIntegration.js","sources":["../../../../src/integrations/http/httpServerSpansIntegration.ts"],"sourcesContent":["import { errorMonitor } from 'node:events';\nimport type { IncomingHttpHeaders } from 'node:http';\nimport { context, SpanKind, trace } from '@opentelemetry/api';\nimport type { RPCMetadata } from '@opentelemetry/core';\nimport { RPCType, setRPCMetadata } from '@opentelemetry/core';\nimport {\n HTTP_RESPONSE_STATUS_CODE,\n HTTP_ROUTE,\n HTTP_STATUS_CODE,\n NET_HOST_IP,\n NET_HOST_PORT,\n NET_PEER_IP,\n} from '@sentry/conventions/attributes';\nimport type {\n Event,\n HttpClientRequest,\n HttpIncomingMessage,\n HttpServerResponse,\n Integration,\n IntegrationFn,\n Span,\n SpanAttributes,\n SpanStatus,\n} from '@sentry/core';\nimport {\n debug,\n getIsolationScope,\n getSpanStatusFromHttpCode,\n httpHeadersToSpanAttributes,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_ERROR,\n stripUrlQueryAndFragment,\n isTracingSuppressed,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport type { NodeClient } from '../../sdk/client';\nimport { addStartSpanCallback } from './httpServerIntegration';\n\nconst INTEGRATION_NAME = 'Http.ServerSpans' as const;\n\n// Tree-shakable guard to remove all code related to tracing\ndeclare const __SENTRY_TRACING__: boolean;\n\nexport interface HttpServerSpansIntegrationOptions {\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: HttpIncomingMessage) => boolean;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with some 3xx and 4xx status codes are ignored (see @default).\n * Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.\n *\n * @default `[[401, 404], [301, 303], [305, 399]]`\n */\n ignoreStatusCodes?: (number | [number, number])[];\n\n /**\n * @deprecated This is deprecated in favor of `incomingRequestSpanHook`.\n */\n instrumentation?: {\n requestHook?: (span: Span, req: HttpClientRequest | HttpIncomingMessage) => void;\n responseHook?: (span: Span, response: HttpIncomingMessage | HttpServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: HttpClientRequest | HttpIncomingMessage,\n response: HttpIncomingMessage | HttpServerResponse,\n ) => void;\n };\n\n /**\n * A hook that can be used to mutate the span for incoming requests.\n * This is triggered after the span is created, but before it is recorded.\n */\n onSpanCreated?: (span: Span, request: HttpIncomingMessage, response: HttpServerResponse) => void;\n}\n\nconst _httpServerSpansIntegration = ((options: HttpServerSpansIntegrationOptions = {}) => {\n const ignoreStaticAssets = options.ignoreStaticAssets ?? true;\n const ignoreIncomingRequests = options.ignoreIncomingRequests;\n const ignoreStatusCodes = options.ignoreStatusCodes ?? [\n [401, 404],\n // 300 and 304 are possibly valid status codes we do not want to filter\n [301, 303],\n [305, 399],\n ];\n\n const { onSpanCreated } = options;\n // eslint-disable-next-line typescript/no-deprecated\n const { requestHook, responseHook, applyCustomAttributesOnSpan } = options.instrumentation ?? {};\n\n return {\n name: INTEGRATION_NAME,\n setup(client: NodeClient) {\n // If no tracing, we can just skip everything here\n if (typeof __SENTRY_TRACING__ !== 'undefined' && !__SENTRY_TRACING__) {\n return;\n }\n\n client.on('httpServerRequest', (_request, _response, normalizedRequest) => {\n // Type-casting this here because we do not want to put the node types into core\n const request = _request as HttpIncomingMessage;\n const response = _response as HttpServerResponse;\n\n const startSpan = (next: () => boolean): boolean => {\n if (\n shouldIgnoreSpansForIncomingRequest(request, {\n ignoreStaticAssets,\n ignoreIncomingRequests,\n })\n ) {\n DEBUG_BUILD && debug.log(INTEGRATION_NAME, 'Skipping span creation for incoming request', request.url);\n return next();\n }\n\n const fullUrl = normalizedRequest.url || request.url || '/';\n const urlObj = parseStringToURLObject(fullUrl);\n\n const headers = request.headers;\n const userAgent = headers['user-agent'];\n const ips = headers['x-forwarded-for'];\n const httpVersion = request.httpVersion;\n const host = headers.host as string | undefined;\n const hostname = host?.replace(/^(.*)(:[0-9]{1,5})/, '$1') || 'localhost';\n\n const tracer = client.tracer;\n const scheme = fullUrl.startsWith('https') ? 'https' : 'http';\n\n const method = normalizedRequest.method || request.method?.toUpperCase() || 'GET';\n const httpTargetWithoutQueryFragment = urlObj ? urlObj.pathname : stripUrlQueryAndFragment(fullUrl);\n const bestEffortTransactionName = `${method} ${httpTargetWithoutQueryFragment}`;\n\n // We use the plain tracer.startSpan here so we can pass the span kind\n const span = tracer.startSpan(bestEffortTransactionName, {\n kind: SpanKind.SERVER,\n attributes: {\n // Sentry specific attributes\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.http',\n 'sentry.http.prefetch': isKnownPrefetchRequest(request) || undefined,\n // Old Semantic Conventions attributes - added for compatibility with what `@opentelemetry/instrumentation-http` output before\n 'http.url': fullUrl,\n 'http.method': normalizedRequest.method,\n 'http.target': urlObj ? `${urlObj.pathname}${urlObj.search}` : httpTargetWithoutQueryFragment,\n 'http.host': host,\n 'net.host.name': hostname,\n 'http.client_ip': typeof ips === 'string' ? ips.split(',')[0] : undefined,\n 'http.user_agent': userAgent,\n 'http.scheme': scheme,\n 'http.flavor': httpVersion,\n 'net.transport': httpVersion?.toUpperCase() === 'QUIC' ? 'ip_udp' : 'ip_tcp',\n ...getRequestContentLengthAttribute(request),\n ...httpHeadersToSpanAttributes(normalizedRequest.headers || {}, client.getDataCollectionOptions()),\n },\n });\n\n // TODO v11: Remove the following three hooks, only onSpanCreated should remain\n requestHook?.(span, request);\n responseHook?.(span, response);\n applyCustomAttributesOnSpan?.(span, request, response);\n onSpanCreated?.(span, request, response);\n\n const rpcMetadata: RPCMetadata = { type: RPCType.HTTP, span };\n\n return context.with(setRPCMetadata(trace.setSpan(context.active(), span), rpcMetadata), () => {\n context.bind(context.active(), request);\n context.bind(context.active(), response);\n\n // Ensure we only end the span once\n // E.g. error can be emitted before close is emitted\n let isEnded = false;\n function endSpan(status: SpanStatus): void {\n if (isEnded) {\n return;\n }\n\n isEnded = true;\n\n const newAttributes = getIncomingRequestAttributesOnResponse(request, response, rpcMetadata);\n span.setAttributes(newAttributes);\n span.setStatus(status);\n span.end();\n\n // Update the transaction name if the route has changed\n const route = newAttributes['http.route'];\n if (route) {\n getIsolationScope().setTransactionName(`${request.method?.toUpperCase() || 'GET'} ${route}`);\n }\n }\n\n response.on('close', () => {\n endSpan(getSpanStatusFromHttpCode(response.statusCode));\n });\n response.on(errorMonitor, () => {\n const httpStatus = getSpanStatusFromHttpCode(response.statusCode);\n // Ensure we def. have an error status here\n endSpan(httpStatus.code === SPAN_STATUS_ERROR ? httpStatus : { code: SPAN_STATUS_ERROR });\n });\n\n return next();\n });\n };\n\n addStartSpanCallback(request, startSpan);\n });\n },\n processEvent(event) {\n if (event.type === 'transaction') {\n const statusCode = event.contexts?.trace?.data?.['http.response.status_code'];\n if (typeof statusCode === 'number') {\n // Drop transaction if it has a status code that should be ignored\n if (shouldFilterStatusCode(statusCode, ignoreStatusCodes)) {\n DEBUG_BUILD && debug.log('Dropping transaction due to status code', statusCode);\n return null;\n }\n\n // Surface the HTTP status as the top-level `response` context. The OTel SDK span\n // exporter already does this on its path; doing it here covers transactions produced\n // by the `SentryTracerProvider`, which bypasses that exporter.\n event.contexts = {\n ...event.contexts,\n response: {\n ...event.contexts?.response,\n status_code: statusCode,\n },\n };\n }\n }\n\n return event;\n },\n afterAllSetup(client) {\n if (!DEBUG_BUILD) {\n return;\n }\n\n if (client.getIntegrationByName('Http')) {\n debug.warn(\n 'It seems that you have manually added `httpServerSpansIntegration` while `httpIntegration` is also present. Make sure to remove `httpIntegration` when adding `httpServerSpansIntegration`.',\n );\n }\n\n if (!client.getIntegrationByName('Http.Server')) {\n debug.error(\n 'It seems that you have manually added `httpServerSpansIntegration` without adding `httpServerIntegration`. This is a requiement for spans to be created - please add the `httpServerIntegration` integration.',\n );\n }\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * This integration emits spans for incoming requests handled via the node `http` module.\n * It requires the `httpServerIntegration` to be present.\n */\nexport const httpServerSpansIntegration = _httpServerSpansIntegration as (\n options?: HttpServerSpansIntegrationOptions,\n) => Integration & {\n name: 'Http.ServerSpans';\n setup: (client: NodeClient) => void;\n processEvent: (event: Event) => Event | null;\n};\n\nfunction isKnownPrefetchRequest(req: HttpIncomingMessage): 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\n/**\n * Check if a request is for a common static asset that should be ignored by default.\n *\n * Only exported for tests.\n */\nexport function isStaticAssetRequest(urlPath: string): boolean {\n const path = stripUrlQueryAndFragment(urlPath);\n // Common static file extensions\n if (path.match(/\\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {\n return true;\n }\n\n // Common metadata files\n if (path.match(/^\\/(robots\\.txt|sitemap\\.xml|manifest\\.json|browserconfig\\.xml)$/)) {\n return true;\n }\n\n return false;\n}\n\nfunction shouldIgnoreSpansForIncomingRequest(\n request: HttpIncomingMessage,\n {\n ignoreStaticAssets,\n ignoreIncomingRequests,\n }: {\n ignoreStaticAssets?: boolean;\n ignoreIncomingRequests?: (urlPath: string, request: HttpIncomingMessage) => boolean;\n },\n): boolean {\n if (isTracingSuppressed()) {\n return true;\n }\n\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 spans\n if (method === 'OPTIONS' || method === 'HEAD' || !urlPath) {\n return true;\n }\n\n // Default static asset filtering\n if (ignoreStaticAssets && method === 'GET' && isStaticAssetRequest(urlPath)) {\n return true;\n }\n\n if (ignoreIncomingRequests?.(urlPath, request)) {\n return true;\n }\n\n return false;\n}\n\nfunction getRequestContentLengthAttribute(request: HttpIncomingMessage): SpanAttributes {\n const length = getContentLength(request.headers);\n if (length == null) {\n return {};\n }\n\n if (isCompressed(request.headers)) {\n return {\n ['http.request_content_length']: length,\n };\n } else {\n return {\n ['http.request_content_length_uncompressed']: length,\n };\n }\n}\n\nfunction getContentLength(headers: IncomingHttpHeaders): number | null {\n const contentLengthHeader = headers['content-length'];\n if (contentLengthHeader === undefined) return null;\n\n const contentLength = parseInt(contentLengthHeader, 10);\n if (isNaN(contentLength)) return null;\n\n return contentLength;\n}\n\nfunction isCompressed(headers: IncomingHttpHeaders): boolean {\n const encoding = headers['content-encoding'];\n\n return !!encoding && encoding !== 'identity';\n}\n\nfunction getIncomingRequestAttributesOnResponse(\n request: HttpIncomingMessage,\n response: HttpServerResponse,\n rpcMetadata?: RPCMetadata,\n): SpanAttributes {\n // take socket from the request,\n // since it may be detached from the response object in keep-alive mode\n const { socket } = request;\n const { statusCode, statusMessage } = response;\n\n const newAttributes: SpanAttributes = {\n [HTTP_RESPONSE_STATUS_CODE]: statusCode,\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_STATUS_CODE]: statusCode,\n 'http.status_text': statusMessage?.toUpperCase(),\n };\n\n if (socket) {\n const { localAddress, localPort, remoteAddress, remotePort } = socket;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_HOST_IP] = localAddress;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_HOST_PORT] = localPort;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_PEER_IP] = remoteAddress;\n newAttributes['net.peer.port'] = remotePort;\n }\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[HTTP_STATUS_CODE] = statusCode;\n newAttributes['http.status_text'] = (statusMessage || '').toUpperCase();\n\n if (rpcMetadata?.type === RPCType.HTTP && rpcMetadata.route !== undefined) {\n const routeName = rpcMetadata.route;\n newAttributes[HTTP_ROUTE] = routeName;\n }\n\n return newAttributes;\n}\n\n/**\n * If the given status code should be filtered for the given list of status codes/ranges.\n */\nfunction shouldFilterStatusCode(statusCode: number, dropForStatusCodes: (number | [number, number])[]): boolean {\n return dropForStatusCodes.some(code => {\n if (typeof code === 'number') {\n return code === statusCode;\n }\n\n const [min, max] = code;\n return statusCode >= min && statusCode <= max;\n });\n}\n"],"names":["DEBUG_BUILD","debug","parseStringToURLObject","stripUrlQueryAndFragment","SpanKind","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","httpHeadersToSpanAttributes","RPCType","context","setRPCMetadata","trace","getIsolationScope","getSpanStatusFromHttpCode","errorMonitor","SPAN_STATUS_ERROR","addStartSpanCallback","isTracingSuppressed","HTTP_RESPONSE_STATUS_CODE","HTTP_STATUS_CODE","NET_HOST_IP","NET_HOST_PORT","NET_PEER_IP","HTTP_ROUTE"],"mappings":"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"} |
@@ -8,3 +8,3 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZS1jb3JlIDEwLjYzLjAgKDIzNjJlOWYpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyBlfWZyb20ibm9kZTppbnNwZWN0b3IvcHJvbWlzZXMiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIHR9ZnJvbSJub2RlOndvcmtlcl90aHJlYWRzIjtjb25zdCBuPWdsb2JhbFRoaXMsaT17fTtjb25zdCBvPSJfX1NFTlRSWV9FUlJPUl9MT0NBTF9WQVJJQUJMRVNfXyI7Y29uc3QgYT10O2Z1bmN0aW9uIHMoLi4uZSl7YS5kZWJ1ZyYmZnVuY3Rpb24oZSl7aWYoISgiY29uc29sZSJpbiBuKSlyZXR1cm4gZSgpO2NvbnN0IHQ9bi5jb25zb2xlLG89e30sYT1PYmplY3Qua2V5cyhpKTthLmZvckVhY2goZT0+e2NvbnN0IG49aVtlXTtvW2VdPXRbZV0sdFtlXT1ufSk7dHJ5e3JldHVybiBlKCl9ZmluYWxseXthLmZvckVhY2goZT0+e3RbZV09b1tlXX0pfX0oKCk9PmNvbnNvbGUubG9nKCJbTG9jYWxWYXJpYWJsZXMgV29ya2VyXSIsLi4uZSkpfWFzeW5jIGZ1bmN0aW9uIGMoZSx0LG4saSl7Y29uc3Qgbz1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pO2lbbl09by5yZXN1bHQuZmlsdGVyKGU9PiJsZW5ndGgiIT09ZS5uYW1lJiYhaXNOYU4ocGFyc2VJbnQoZS5uYW1lLDEwKSkpLnNvcnQoKGUsdCk9PnBhcnNlSW50KGUubmFtZSwxMCktcGFyc2VJbnQodC5uYW1lLDEwKSkubWFwKGU9PmUudmFsdWU/LnZhbHVlKX1hc3luYyBmdW5jdGlvbiByKGUsdCxuLGkpe2NvbnN0IG89YXdhaXQgZS5wb3N0KCJSdW50aW1lLmdldFByb3BlcnRpZXMiLHtvYmplY3RJZDp0LG93blByb3BlcnRpZXM6ITB9KTtpW25dPW8ucmVzdWx0Lm1hcChlPT5bZS5uYW1lLGUudmFsdWU/LnZhbHVlXSkucmVkdWNlKChlLFt0LG5dKT0+KGVbdF09bixlKSx7fSl9ZnVuY3Rpb24gdShlLHQpe2UudmFsdWUmJigidmFsdWUiaW4gZS52YWx1ZT92b2lkIDA9PT1lLnZhbHVlLnZhbHVlfHxudWxsPT09ZS52YWx1ZS52YWx1ZT90W2UubmFtZV09YDwke2UudmFsdWUudmFsdWV9PmA6dFtlLm5hbWVdPWUudmFsdWUudmFsdWU6ImRlc2NyaXB0aW9uImluIGUudmFsdWUmJiJmdW5jdGlvbiIhPT1lLnZhbHVlLnR5cGU/dFtlLm5hbWVdPWA8JHtlLnZhbHVlLmRlc2NyaXB0aW9ufT5gOiJ1bmRlZmluZWQiPT09ZS52YWx1ZS50eXBlJiYodFtlLm5hbWVdPSI8dW5kZWZpbmVkPiIpKX1hc3luYyBmdW5jdGlvbiBsKGUsdCl7Y29uc3Qgbj1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pLGk9e307Zm9yKGNvbnN0IHQgb2Ygbi5yZXN1bHQpaWYodC52YWx1ZT8ub2JqZWN0SWQmJiJBcnJheSI9PT10LnZhbHVlLmNsYXNzTmFtZSl7Y29uc3Qgbj10LnZhbHVlLm9iamVjdElkO2F3YWl0IGMoZSxuLHQubmFtZSxpKX1lbHNlIGlmKHQudmFsdWU/Lm9iamVjdElkJiYiT2JqZWN0Ij09PXQudmFsdWUuY2xhc3NOYW1lKXtjb25zdCBuPXQudmFsdWUub2JqZWN0SWQ7YXdhaXQgcihlLG4sdC5uYW1lLGkpfWVsc2UgdC52YWx1ZSYmdSh0LGkpO3JldHVybiBpfWxldCBmOyhhc3luYyBmdW5jdGlvbigpe2NvbnN0IHQ9bmV3IGU7dC5jb25uZWN0VG9NYWluVGhyZWFkKCkscygiQ29ubmVjdGVkIHRvIG1haW4gdGhyZWFkIik7bGV0IG49ITE7dC5vbigiRGVidWdnZXIucmVzdW1lZCIsKCk9PntuPSExfSksdC5vbigiRGVidWdnZXIucGF1c2VkIixlPT57bj0hMCxhc3luYyBmdW5jdGlvbihlLHtyZWFzb246dCxkYXRhOntvYmplY3RJZDpufSxjYWxsRnJhbWVzOml9KXtpZigiZXhjZXB0aW9uIiE9PXQmJiJwcm9taXNlUmVqZWN0aW9uIiE9PXQpcmV0dXJuO2lmKGY/LigpLG51bGw9PW4pcmV0dXJuO2NvbnN0IGE9W107Zm9yKGxldCB0PTA7dDxpLmxlbmd0aDt0Kyspe2NvbnN0e3Njb3BlQ2hhaW46bixmdW5jdGlvbk5hbWU6byx0aGlzOnN9PWlbdF0sYz1uLmZpbmQoZT0+ImxvY2FsIj09PWUudHlwZSkscj0iZ2xvYmFsIiE9PXMuY2xhc3NOYW1lJiZzLmNsYXNzTmFtZT9gJHtzLmNsYXNzTmFtZX0uJHtvfWA6bztpZih2b2lkIDA9PT1jPy5vYmplY3Qub2JqZWN0SWQpYVt0XT17ZnVuY3Rpb246cn07ZWxzZXtjb25zdCBuPWF3YWl0IGwoZSxjLm9iamVjdC5vYmplY3RJZCk7YVt0XT17ZnVuY3Rpb246cix2YXJzOm59fX1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuY2FsbEZ1bmN0aW9uT24iLHtmdW5jdGlvbkRlY2xhcmF0aW9uOmBmdW5jdGlvbigpIHsgdGhpcy4ke299ID0gdGhpcy4ke299IHx8ICR7SlNPTi5zdHJpbmdpZnkoYSl9OyB9YCxzaWxlbnQ6ITAsb2JqZWN0SWQ6bn0pLGF3YWl0IGUucG9zdCgiUnVudGltZS5yZWxlYXNlT2JqZWN0Iix7b2JqZWN0SWQ6bn0pfSh0LGUucGFyYW1zKS50aGVuKGFzeW5jKCk9PntuJiZhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpfSxhc3luYyBlPT57biYmYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKX0pfSksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiKTtjb25zdCBpPSExIT09YS5jYXB0dXJlQWxsRXhjZXB0aW9ucztpZihhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6aT8iYWxsIjoidW5jYXVnaHQifSksaSl7Y29uc3QgZT1hLm1heEV4Y2VwdGlvbnNQZXJTZWNvbmR8fDUwO2Y9ZnVuY3Rpb24oZSx0LG4pe2xldCBpPTAsbz01LGE9MDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCk9PnswPT09YT9pPmUmJihvKj0yLG4obyksbz44NjQwMCYmKG89ODY0MDApLGE9byk6KGEtPTEsMD09PWEmJnQoKSksaT0wfSwxZTMpLnVucmVmKCksKCk9PntpKz0xfX0oZSxhc3luYygpPT57cygiUmF0ZS1saW1pdCBsaWZ0ZWQuIiksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJhbGwifSl9LGFzeW5jIGU9PntzKGBSYXRlLWxpbWl0IGV4Y2VlZGVkLiBEaXNhYmxpbmcgY2FwdHVyaW5nIG9mIGNhdWdodCBleGNlcHRpb25zIGZvciAke2V9IHNlY29uZHMuYCksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJ1bmNhdWdodCJ9KX0pfX0pKCkuY2F0Y2goZT0+e3MoIkZhaWxlZCB0byBzdGFydCBkZWJ1Z2dlciIsZSl9KSxzZXRJbnRlcnZhbCgoKT0+e30sMWU0KTs="; | ||
| const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZS1jb3JlIDEwLjY0LjAgKDU3MzZhMzgpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyBlfWZyb20ibm9kZTppbnNwZWN0b3IvcHJvbWlzZXMiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIHR9ZnJvbSJub2RlOndvcmtlcl90aHJlYWRzIjtjb25zdCBuPWdsb2JhbFRoaXMsaT17fTtjb25zdCBvPSJfX1NFTlRSWV9FUlJPUl9MT0NBTF9WQVJJQUJMRVNfXyI7Y29uc3QgYT10O2Z1bmN0aW9uIHMoLi4uZSl7YS5kZWJ1ZyYmZnVuY3Rpb24oZSl7aWYoISgiY29uc29sZSJpbiBuKSlyZXR1cm4gZSgpO2NvbnN0IHQ9bi5jb25zb2xlLG89e30sYT1PYmplY3Qua2V5cyhpKTthLmZvckVhY2goZT0+e2NvbnN0IG49aVtlXTtvW2VdPXRbZV0sdFtlXT1ufSk7dHJ5e3JldHVybiBlKCl9ZmluYWxseXthLmZvckVhY2goZT0+e3RbZV09b1tlXX0pfX0oKCk9PmNvbnNvbGUubG9nKCJbTG9jYWxWYXJpYWJsZXMgV29ya2VyXSIsLi4uZSkpfWFzeW5jIGZ1bmN0aW9uIGMoZSx0LG4saSl7Y29uc3Qgbz1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pO2lbbl09by5yZXN1bHQuZmlsdGVyKGU9PiJsZW5ndGgiIT09ZS5uYW1lJiYhaXNOYU4ocGFyc2VJbnQoZS5uYW1lLDEwKSkpLnNvcnQoKGUsdCk9PnBhcnNlSW50KGUubmFtZSwxMCktcGFyc2VJbnQodC5uYW1lLDEwKSkubWFwKGU9PmUudmFsdWU/LnZhbHVlKX1hc3luYyBmdW5jdGlvbiByKGUsdCxuLGkpe2NvbnN0IG89YXdhaXQgZS5wb3N0KCJSdW50aW1lLmdldFByb3BlcnRpZXMiLHtvYmplY3RJZDp0LG93blByb3BlcnRpZXM6ITB9KTtpW25dPW8ucmVzdWx0Lm1hcChlPT5bZS5uYW1lLGUudmFsdWU/LnZhbHVlXSkucmVkdWNlKChlLFt0LG5dKT0+KGVbdF09bixlKSx7fSl9ZnVuY3Rpb24gdShlLHQpe2UudmFsdWUmJigidmFsdWUiaW4gZS52YWx1ZT92b2lkIDA9PT1lLnZhbHVlLnZhbHVlfHxudWxsPT09ZS52YWx1ZS52YWx1ZT90W2UubmFtZV09YDwke2UudmFsdWUudmFsdWV9PmA6dFtlLm5hbWVdPWUudmFsdWUudmFsdWU6ImRlc2NyaXB0aW9uImluIGUudmFsdWUmJiJmdW5jdGlvbiIhPT1lLnZhbHVlLnR5cGU/dFtlLm5hbWVdPWA8JHtlLnZhbHVlLmRlc2NyaXB0aW9ufT5gOiJ1bmRlZmluZWQiPT09ZS52YWx1ZS50eXBlJiYodFtlLm5hbWVdPSI8dW5kZWZpbmVkPiIpKX1hc3luYyBmdW5jdGlvbiBsKGUsdCl7Y29uc3Qgbj1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pLGk9e307Zm9yKGNvbnN0IHQgb2Ygbi5yZXN1bHQpaWYodC52YWx1ZT8ub2JqZWN0SWQmJiJBcnJheSI9PT10LnZhbHVlLmNsYXNzTmFtZSl7Y29uc3Qgbj10LnZhbHVlLm9iamVjdElkO2F3YWl0IGMoZSxuLHQubmFtZSxpKX1lbHNlIGlmKHQudmFsdWU/Lm9iamVjdElkJiYiT2JqZWN0Ij09PXQudmFsdWUuY2xhc3NOYW1lKXtjb25zdCBuPXQudmFsdWUub2JqZWN0SWQ7YXdhaXQgcihlLG4sdC5uYW1lLGkpfWVsc2UgdC52YWx1ZSYmdSh0LGkpO3JldHVybiBpfWxldCBmOyhhc3luYyBmdW5jdGlvbigpe2NvbnN0IHQ9bmV3IGU7dC5jb25uZWN0VG9NYWluVGhyZWFkKCkscygiQ29ubmVjdGVkIHRvIG1haW4gdGhyZWFkIik7bGV0IG49ITE7dC5vbigiRGVidWdnZXIucmVzdW1lZCIsKCk9PntuPSExfSksdC5vbigiRGVidWdnZXIucGF1c2VkIixlPT57bj0hMCxhc3luYyBmdW5jdGlvbihlLHtyZWFzb246dCxkYXRhOntvYmplY3RJZDpufSxjYWxsRnJhbWVzOml9KXtpZigiZXhjZXB0aW9uIiE9PXQmJiJwcm9taXNlUmVqZWN0aW9uIiE9PXQpcmV0dXJuO2lmKGY/LigpLG51bGw9PW4pcmV0dXJuO2NvbnN0IGE9W107Zm9yKGxldCB0PTA7dDxpLmxlbmd0aDt0Kyspe2NvbnN0e3Njb3BlQ2hhaW46bixmdW5jdGlvbk5hbWU6byx0aGlzOnN9PWlbdF0sYz1uLmZpbmQoZT0+ImxvY2FsIj09PWUudHlwZSkscj0iZ2xvYmFsIiE9PXMuY2xhc3NOYW1lJiZzLmNsYXNzTmFtZT9gJHtzLmNsYXNzTmFtZX0uJHtvfWA6bztpZih2b2lkIDA9PT1jPy5vYmplY3Qub2JqZWN0SWQpYVt0XT17ZnVuY3Rpb246cn07ZWxzZXtjb25zdCBuPWF3YWl0IGwoZSxjLm9iamVjdC5vYmplY3RJZCk7YVt0XT17ZnVuY3Rpb246cix2YXJzOm59fX1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuY2FsbEZ1bmN0aW9uT24iLHtmdW5jdGlvbkRlY2xhcmF0aW9uOmBmdW5jdGlvbigpIHsgdGhpcy4ke299ID0gdGhpcy4ke299IHx8ICR7SlNPTi5zdHJpbmdpZnkoYSl9OyB9YCxzaWxlbnQ6ITAsb2JqZWN0SWQ6bn0pLGF3YWl0IGUucG9zdCgiUnVudGltZS5yZWxlYXNlT2JqZWN0Iix7b2JqZWN0SWQ6bn0pfSh0LGUucGFyYW1zKS50aGVuKGFzeW5jKCk9PntuJiZhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpfSxhc3luYyBlPT57biYmYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKX0pfSksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiKTtjb25zdCBpPSExIT09YS5jYXB0dXJlQWxsRXhjZXB0aW9ucztpZihhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6aT8iYWxsIjoidW5jYXVnaHQifSksaSl7Y29uc3QgZT1hLm1heEV4Y2VwdGlvbnNQZXJTZWNvbmR8fDUwO2Y9ZnVuY3Rpb24oZSx0LG4pe2xldCBpPTAsbz01LGE9MDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCk9PnswPT09YT9pPmUmJihvKj0yLG4obyksbz44NjQwMCYmKG89ODY0MDApLGE9byk6KGEtPTEsMD09PWEmJnQoKSksaT0wfSwxZTMpLnVucmVmKCksKCk9PntpKz0xfX0oZSxhc3luYygpPT57cygiUmF0ZS1saW1pdCBsaWZ0ZWQuIiksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJhbGwifSl9LGFzeW5jIGU9PntzKGBSYXRlLWxpbWl0IGV4Y2VlZGVkLiBEaXNhYmxpbmcgY2FwdHVyaW5nIG9mIGNhdWdodCBleGNlcHRpb25zIGZvciAke2V9IHNlY29uZHMuYCksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJ1bmNhdWdodCJ9KX0pfX0pKCkuY2F0Y2goZT0+e3MoIkZhaWxlZCB0byBzdGFydCBkZWJ1Z2dlciIsZSl9KSxzZXRJbnRlcnZhbCgoKT0+e30sMWU0KTs="; | ||
| function log(...args) { | ||
@@ -11,0 +11,0 @@ core.debug.log("[LocalVariables]", ...args); |
@@ -6,3 +6,2 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const core = require('@sentry/core'); | ||
| require('../nodeVersion.js'); | ||
@@ -42,3 +41,3 @@ let moduleCache; | ||
| ...getModulesFromPackageJson(), | ||
| ...collectRequireModules() | ||
| ...collectRequireModules() | ||
| }; | ||
@@ -45,0 +44,0 @@ } |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"modules.js","sources":["../../../src/integrations/modules.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { GLOBAL_OBJ, type IntegrationFn } from '@sentry/core';\nimport { isCjs } from '../utils/detection';\n\ntype ModuleInfo = Record<string, string>;\n\nlet moduleCache: ModuleInfo | undefined;\n\nconst INTEGRATION_NAME = 'Modules' as const;\n\ndeclare const __SENTRY_SERVER_MODULES__: Record<string, string>;\n\n/**\n * Reads the modules injected at build time into `__SENTRY_SERVER_MODULES__` (e.g. by the Next.js SDK).\n *\n * Must be read lazily (per call), not captured at module-eval time: webpack replaces the token via\n * `DefinePlugin` (available immediately), but Turbopack assigns `globalThis.__SENTRY_SERVER_MODULES__`\n * at runtime, *after* this module's imports are hoisted and evaluated. A `const` capture would be\n * empty under Turbopack. See getsentry/sentry-javascript#19147.\n */\nfunction getServerModules(): Record<string, string> {\n // webpack: the token is replaced with a literal at build time.\n if (typeof __SENTRY_SERVER_MODULES__ !== 'undefined') {\n return __SENTRY_SERVER_MODULES__;\n }\n // Turbopack: the value is assigned onto the global object at runtime.\n return (\n (GLOBAL_OBJ as typeof GLOBAL_OBJ & { __SENTRY_SERVER_MODULES__?: Record<string, string> })\n .__SENTRY_SERVER_MODULES__ ?? {}\n );\n}\n\nconst _modulesIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n processEvent(event) {\n event.modules = {\n ...event.modules,\n ..._getModules(),\n };\n\n return event;\n },\n getModules: _getModules,\n };\n}) satisfies IntegrationFn;\n\n/**\n * Add node modules / packages to the event.\n * For this, multiple sources are used:\n * - They can be injected at build time into the __SENTRY_SERVER_MODULES__ variable (e.g. in Next.js)\n * - They are extracted from the dependencies & devDependencies in the package.json file\n * - They are extracted from the require.cache (CJS only)\n */\nexport const modulesIntegration = _modulesIntegration;\n\nfunction getRequireCachePaths(): string[] {\n try {\n return require.cache ? Object.keys(require.cache as Record<string, unknown>) : [];\n } catch {\n return [];\n }\n}\n\n/** Extract information about package.json modules */\nfunction collectModules(): ModuleInfo {\n return {\n ...getServerModules(),\n ...getModulesFromPackageJson(),\n ...(isCjs() ? collectRequireModules() : {}),\n };\n}\n\n/** Extract information about package.json modules from require.cache */\nfunction collectRequireModules(): ModuleInfo {\n const mainPaths = require.main?.paths || [];\n const paths = getRequireCachePaths();\n\n // We start with the modules from package.json (if possible)\n // These may be overwritten by more specific versions from the require.cache\n const infos: ModuleInfo = {};\n const seen = new Set<string>();\n\n paths.forEach(path => {\n let dir = path;\n\n /** Traverse directories upward in the search of package.json file */\n const updir = (): void | (() => void) => {\n const orig = dir;\n dir = dirname(orig);\n\n if (!dir || orig === dir || seen.has(orig)) {\n return undefined;\n }\n if (mainPaths.indexOf(dir) < 0) {\n return updir();\n }\n\n const pkgfile = join(orig, 'package.json');\n seen.add(orig);\n\n if (!existsSync(pkgfile)) {\n return updir();\n }\n\n try {\n const info = JSON.parse(readFileSync(pkgfile, 'utf8')) as {\n name: string;\n version: string;\n };\n infos[info.name] = info.version;\n } catch {\n // no-empty\n }\n };\n\n updir();\n });\n\n return infos;\n}\n\n/** Fetches the list of modules and the versions loaded by the entry file for your node.js app. */\nfunction _getModules(): ModuleInfo {\n if (!moduleCache) {\n moduleCache = collectModules();\n }\n return moduleCache;\n}\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nfunction getPackageJson(): PackageJson {\n try {\n const filePath = join(process.cwd(), 'package.json');\n const packageJson = JSON.parse(readFileSync(filePath, 'utf8')) as PackageJson;\n\n return packageJson;\n } catch {\n return {};\n }\n}\n\nfunction getModulesFromPackageJson(): ModuleInfo {\n const packageJson = getPackageJson();\n\n return {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n}\n"],"names":["GLOBAL_OBJ","dirname","join","existsSync","readFileSync"],"mappings":"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"} | ||
| {"version":3,"file":"modules.js","sources":["../../../src/integrations/modules.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { GLOBAL_OBJ, type IntegrationFn } from '@sentry/core';\n\ntype ModuleInfo = Record<string, string>;\n\nlet moduleCache: ModuleInfo | undefined;\n\nconst INTEGRATION_NAME = 'Modules' as const;\n\ndeclare const __SENTRY_SERVER_MODULES__: Record<string, string>;\n\n/**\n * Reads the modules injected at build time into `__SENTRY_SERVER_MODULES__` (e.g. by the Next.js SDK).\n *\n * Must be read lazily (per call), not captured at module-eval time: webpack replaces the token via\n * `DefinePlugin` (available immediately), but Turbopack assigns `globalThis.__SENTRY_SERVER_MODULES__`\n * at runtime, *after* this module's imports are hoisted and evaluated. A `const` capture would be\n * empty under Turbopack. See getsentry/sentry-javascript#19147.\n */\nfunction getServerModules(): Record<string, string> {\n // webpack: the token is replaced with a literal at build time.\n if (typeof __SENTRY_SERVER_MODULES__ !== 'undefined') {\n return __SENTRY_SERVER_MODULES__;\n }\n // Turbopack: the value is assigned onto the global object at runtime.\n return (\n (GLOBAL_OBJ as typeof GLOBAL_OBJ & { __SENTRY_SERVER_MODULES__?: Record<string, string> })\n .__SENTRY_SERVER_MODULES__ ?? {}\n );\n}\n\nconst _modulesIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n processEvent(event) {\n event.modules = {\n ...event.modules,\n ..._getModules(),\n };\n\n return event;\n },\n getModules: _getModules,\n };\n}) satisfies IntegrationFn;\n\n/**\n * Add node modules / packages to the event.\n * For this, multiple sources are used:\n * - They can be injected at build time into the __SENTRY_SERVER_MODULES__ variable (e.g. in Next.js)\n * - They are extracted from the dependencies & devDependencies in the package.json file\n * - They are extracted from the require.cache (CJS only)\n */\nexport const modulesIntegration = _modulesIntegration;\n\nfunction getRequireCachePaths(): string[] {\n try {\n return require.cache ? Object.keys(require.cache as Record<string, unknown>) : [];\n } catch {\n return [];\n }\n}\n\n/** Extract information about package.json modules */\nfunction collectModules(): ModuleInfo {\n return {\n ...getServerModules(),\n ...getModulesFromPackageJson(),\n /*! rollup-include-cjs-only */\n ...collectRequireModules(),\n /*! rollup-include-cjs-only-end */\n };\n}\n\n/** Extract information about package.json modules from require.cache */\nfunction collectRequireModules(): ModuleInfo {\n const mainPaths = require.main?.paths || [];\n const paths = getRequireCachePaths();\n\n // We start with the modules from package.json (if possible)\n // These may be overwritten by more specific versions from the require.cache\n const infos: ModuleInfo = {};\n const seen = new Set<string>();\n\n paths.forEach(path => {\n let dir = path;\n\n /** Traverse directories upward in the search of package.json file */\n const updir = (): void | (() => void) => {\n const orig = dir;\n dir = dirname(orig);\n\n if (!dir || orig === dir || seen.has(orig)) {\n return undefined;\n }\n if (mainPaths.indexOf(dir) < 0) {\n return updir();\n }\n\n const pkgfile = join(orig, 'package.json');\n seen.add(orig);\n\n if (!existsSync(pkgfile)) {\n return updir();\n }\n\n try {\n const info = JSON.parse(readFileSync(pkgfile, 'utf8')) as {\n name: string;\n version: string;\n };\n infos[info.name] = info.version;\n } catch {\n // no-empty\n }\n };\n\n updir();\n });\n\n return infos;\n}\n\n/** Fetches the list of modules and the versions loaded by the entry file for your node.js app. */\nfunction _getModules(): ModuleInfo {\n if (!moduleCache) {\n moduleCache = collectModules();\n }\n return moduleCache;\n}\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nfunction getPackageJson(): PackageJson {\n try {\n const filePath = join(process.cwd(), 'package.json');\n const packageJson = JSON.parse(readFileSync(filePath, 'utf8')) as PackageJson;\n\n return packageJson;\n } catch {\n return {};\n }\n}\n\nfunction getModulesFromPackageJson(): ModuleInfo {\n const packageJson = getPackageJson();\n\n return {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n}\n"],"names":["GLOBAL_OBJ","join","existsSync","readFileSync"],"mappings":";;;;;;AAMA,IAAI,WAAA;AAEJ,MAAM,gBAAA,GAAmB,SAAA;AAYzB,SAAS,gBAAA,GAA2C;AAElD,EAAA,IAAI,OAAO,8BAA8B,WAAA,EAAa;AACpD,IAAA,OAAO,yBAAA;AAAA,EACT;AAEA,EAAA,OACGA,eAAA,CACE,6BAA6B,EAAC;AAErC;AAEA,MAAM,uBAAuB,MAAM;AACjC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,aAAa,KAAA,EAAO;AAClB,MAAA,KAAA,CAAM,OAAA,GAAU;AAAA,QACd,GAAG,KAAA,CAAM,OAAA;AAAA,QACT,GAAG,WAAA;AAAY,OACjB;AAEA,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,UAAA,EAAY;AAAA,GACd;AACF,CAAA,CAAA;AASO,MAAM,kBAAA,GAAqB;AAElC,SAAS,oBAAA,GAAiC;AACxC,EAAA,IAAI;AACF,IAAA,OAAO,QAAQ,KAAA,GAAQ,MAAA,CAAO,KAAK,OAAA,CAAQ,KAAgC,IAAI,EAAC;AAAA,EAClF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAGA,SAAS,cAAA,GAA6B;AACpC,EAAA,OAAO;AAAA,IACL,GAAG,gBAAA,EAAiB;AAAA,IACpB,GAAG,yBAAA,EAA0B;AAAA,IAAA,GAAA,qBAAA;AAAA,GAAA;AAEJ;AAAA,SAE3B,qBAAA,GAAA;AACF,EAAA,MAAA,SAAA,GAAA,OAAA,CAAA,IAAA,EAAA,KAAA,IAAA,EAAA;AAGA,EAAA,MAAA,KAAS,GAAA,oBAAoC,EAAA;AAC3C,EAAA,MAAM,KAAA,GAAA,EAAA;AACN,EAAA,MAAM,uBAAQ,IAAA,GAAqB,EAAA;AAInC,EAAA,KAAA,CAAM,QAAoB,CAAC,IAAA,KAAA;AAC3B,IAAA,IAAM,GAAA,GAAA;AAEN,IAAA,cAAc,MAAA;AACZ,MAAA,MAAI,IAAM,GAAA,GAAA;AAGV,MAAA,GAAA,oBAAc,CAAA,IAA2B,CAAA;AACvC,MAAA,IAAA,CAAA,GAAM,IAAA,IAAO,KAAA,GAAA,IAAA,IAAA,CAAA,GAAA,CAAA,IAAA,CAAA,EAAA;AACb,QAAA,aAAc;AAEd,MAAA;AACE,MAAA,IAAA,SAAO,CAAA,OAAA,CAAA,GAAA,CAAA,GAAA,CAAA,EAAA;AAAA,QACT,OAAA,KAAA,EAAA;AACA,MAAA;AACE,MAAA,MAAA,OAAO,GAAMC,cAAA,CAAA,IAAA,EAAA,cAAA,CAAA;AAAA,MACf,IAAA,CAAA,GAAA,CAAA,IAAA,CAAA;AAEA,MAAA,IAAA,CAAAC,kBAAM,CAAU,OAAK,CAAA,EAAA;AACrB,QAAA,OAAS,KAAI,EAAA;AAEb,MAAA;AACE,MAAA,IAAA;AAAa,QACf,MAAA,IAAA,GAAA,IAAA,CAAA,KAAA,CAAAC,oBAAA,CAAA,OAAA,EAAA,MAAA,CAAA,CAAA;AAEA,QAAA,KAAI,CAAA,IAAA,CAAA,IAAA,CAAA,GAAA,IAAA,CAAA,OAAA;AACF,MAAA,CAAA,CAAA,MAAM;AAIN,MAAA;AAAwB,IAAA,CAAA;AAClB,IAAA,KAER,EAAA;AAAA,EAAA,CAAA,CACF;AAEA,EAAA,OAAA,KAAM;AAAA;AAGR,SAAO,WAAA,GAAA;AACT,EAAA,IAAA,CAAA,WAAA,EAAA;AAGA,IAAA,WAAS,GAAA,cAA0B,EAAA;AACjC,EAAA;AACE,EAAA,OAAA,WAAc;AAAe;AAE/B,SAAO,cAAA,GAAA;AACT,EAAA,IAAA;AAOA,IAAA,MAAS,QAAA,GAAAF,cAAA,CAA8B,OAAA,CAAA,GAAA,EAAA,EAAA,cAAA,CAAA;AACrC,IAAA,MAAI,WAAA,GAAA,IAAA,CAAA,KAAA,CAAAE,oBAAA,CAAA,QAAA,EAAA,MAAA,CAAA,CAAA;AACF,IAAA,OAAM,WAAW;AACjB,EAAA,CAAA,CAAA,MAAM;AAEN,IAAA,OAAO,EAAA;AAAA,EACT;AACE;AAAQ,SACV,yBAAA,GAAA;AACF,EAAA,MAAA,WAAA,GAAA,cAAA,EAAA;AAEA,EAAA,OAAS;AACP,IAAA,GAAA,wBAAoB;AAEpB,IAAA,GAAA,WAAO,CAAA;AAAA,GAAA;AACU;;;;"} |
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const core = require('@sentry/core'); | ||
| const instrument = require('../../otel/instrument.js'); | ||
| const SentryNodeFetchInstrumentation = require('./SentryNodeFetchInstrumentation.js'); | ||
| const undiciInstrumentation = require('./undici-instrumentation.js'); | ||
| const INTEGRATION_NAME = "NodeFetch"; | ||
| const instrumentSentryNodeFetch = instrument.generateInstrumentOnce( | ||
| `${INTEGRATION_NAME}.sentry`, | ||
| SentryNodeFetchInstrumentation.SentryNodeFetchInstrumentation, | ||
| (options) => { | ||
| return options; | ||
| } | ||
| ); | ||
| const _nativeNodeFetchIntegration = ((options = {}) => { | ||
@@ -19,3 +10,3 @@ return { | ||
| setupOnce() { | ||
| instrumentSentryNodeFetch(options); | ||
| undiciInstrumentation.instrumentUndici(options); | ||
| } | ||
@@ -22,0 +13,0 @@ }; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sources":["../../../../src/integrations/node-fetch/index.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration } from '@sentry/core';\nimport { generateInstrumentOnce } from '../../otel/instrument';\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 * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing fetch requests.\n *\n * @default `true`\n */\n tracePropagation?: 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 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' as const,\n setupOnce() {\n instrumentSentryNodeFetch(options);\n },\n };\n}) satisfies IntegrationFn;\n\nexport const nativeNodeFetchIntegration = defineIntegration(_nativeNodeFetchIntegration);\n"],"names":["generateInstrumentOnce","SentryNodeFetchInstrumentation","defineIntegration"],"mappings":";;;;;;AAKA,MAAM,gBAAA,GAAmB,WAAA;AAuBzB,MAAM,yBAAA,GAA4BA,iCAAA;AAAA,EAChC,GAAG,gBAAgB,CAAA,OAAA,CAAA;AAAA,EACnBC,6DAAA;AAAA,EACA,CAAC,OAAA,KAA8B;AAC7B,IAAA,OAAO,OAAA;AAAA,EACT;AACF,CAAA;AAEA,MAAM,2BAAA,IAA+B,CAAC,OAAA,GAA4B,EAAC,KAAM;AACvE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,WAAA;AAAA,IACN,SAAA,GAAY;AACV,MAAA,yBAAA,CAA0B,OAAO,CAAA;AAAA,IACnC;AAAA,GACF;AACF,CAAA,CAAA;AAEO,MAAM,0BAAA,GAA6BC,uBAAkB,2BAA2B;;;;"} | ||
| {"version":3,"file":"index.js","sources":["../../../../src/integrations/node-fetch/index.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration } from '@sentry/core';\nimport type { NodeFetchOptions } from './types';\nimport { instrumentUndici } from './undici-instrumentation';\n\nconst _nativeNodeFetchIntegration = ((options: NodeFetchOptions = {}) => {\n return {\n name: 'NodeFetch' as const,\n setupOnce() {\n instrumentUndici(options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Instrument outgoing fetch requests made through the native node `fetch` API.\n * This emits (depending on the integration options) spans and breadcrumbs, as well as injecting trace propagation headers into the request.\n */\nexport const nativeNodeFetchIntegration = defineIntegration(_nativeNodeFetchIntegration);\n"],"names":["instrumentUndici","defineIntegration"],"mappings":";;;;;AAKA,MAAM,2BAAA,IAA+B,CAAC,OAAA,GAA4B,EAAC,KAAM;AACvE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,WAAA;AAAA,IACN,SAAA,GAAY;AACV,MAAAA,sCAAA,CAAiB,OAAO,CAAA;AAAA,IAC1B;AAAA,GACF;AACF,CAAA,CAAA;AAMO,MAAM,0BAAA,GAA6BC,uBAAkB,2BAA2B;;;;"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"SentryNodeFetchInstrumentation.js","sources":["../../../../src/integrations/node-fetch/SentryNodeFetchInstrumentation.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase } from '@opentelemetry/instrumentation';\nimport { LRUMap, SDK_VERSION, isTracingSuppressed } from '@sentry/core';\nimport * as diagch from 'diagnostics_channel';\nimport { NODE_MAJOR, NODE_MINOR } from '../../nodeVersion';\nimport {\n addFetchRequestBreadcrumb,\n addTracePropagationHeadersToFetchRequest,\n getAbsoluteUrl,\n} from '../../utils/outgoingFetchRequest';\nimport type { UndiciRequest, UndiciResponse } from './types';\n\nexport type SentryNodeFetchInstrumentationOptions = InstrumentationConfig & {\n /**\n * Whether breadcrumbs should be recorded for requests.\n *\n * @default `true`\n */\n breadcrumbs?: boolean;\n\n /**\n * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing fetch requests.\n *\n * When set to `false`, Sentry will not inject any trace propagation headers, but will still create breadcrumbs\n * (if `breadcrumbs` is enabled). This is useful when `skipOpenTelemetrySetup: true` is configured and you want\n * to avoid duplicate trace headers being injected by both Sentry and OpenTelemetry's UndiciInstrumentation.\n *\n * @default `true`\n */\n tracePropagation?: boolean;\n\n /**\n * Do not capture breadcrumbs or inject headers for outgoing fetch requests to URLs where the given callback returns `true`.\n * The same option can be passed to the top-level httpIntegration where it controls both, breadcrumb and\n * span creation.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n */\n ignoreOutgoingRequests?: (url: string) => boolean;\n};\n\ninterface ListenerRecord {\n name: string;\n unsubscribe: () => void;\n}\n\n/**\n * This custom node-fetch instrumentation is used to instrument outgoing fetch requests.\n * It does not emit any spans.\n *\n * The reason this is isolated from the OpenTelemetry instrumentation is that users may overwrite this,\n * which would lead to Sentry not working as expected.\n *\n * This is heavily inspired & adapted from:\n * https://github.com/open-telemetry/opentelemetry-js-contrib/blob/28e209a9da36bc4e1f8c2b0db7360170ed46cb80/plugins/node/instrumentation-undici/src/undici.ts\n */\nexport class SentryNodeFetchInstrumentation extends InstrumentationBase<SentryNodeFetchInstrumentationOptions> {\n // Keep ref to avoid https://github.com/nodejs/node/issues/42170 bug and for\n // unsubscribing.\n private _channelSubs: Array<ListenerRecord>;\n private _propagationDecisionMap: LRUMap<string, boolean>;\n private _ignoreOutgoingRequestsMap: WeakMap<UndiciRequest, boolean>;\n\n public constructor(config: SentryNodeFetchInstrumentationOptions = {}) {\n super('@sentry/instrumentation-node-fetch', SDK_VERSION, config);\n this._channelSubs = [];\n this._propagationDecisionMap = new LRUMap<string, boolean>(100);\n this._ignoreOutgoingRequestsMap = new WeakMap<UndiciRequest, boolean>();\n }\n\n /** No need to instrument files/modules. */\n public init(): void {\n return undefined;\n }\n\n /** Disable the instrumentation. */\n public disable(): void {\n super.disable();\n this._channelSubs.forEach(sub => sub.unsubscribe());\n this._channelSubs = [];\n }\n\n /** Enable the instrumentation. */\n public enable(): void {\n // \"enabled\" handling is currently a bit messy with InstrumentationBase.\n // If constructed with `{enabled: false}`, this `.enable()` is still called,\n // and `this.getConfig().enabled !== this.isEnabled()`, creating confusion.\n //\n // For now, this class will setup for instrumenting if `.enable()` is\n // called, but use `this.getConfig().enabled` to determine if\n // instrumentation should be generated. This covers the more likely common\n // case of config being given a construction time, rather than later via\n // `instance.enable()`, `.disable()`, or `.setConfig()` calls.\n super.enable();\n\n // This method is called by the super-class constructor before ours is\n // called. So we need to ensure the property is initalized.\n this._channelSubs = this._channelSubs || [];\n\n // Avoid to duplicate subscriptions\n if (this._channelSubs.length > 0) {\n return;\n }\n\n this._subscribeToChannel('undici:request:create', this._onRequestCreated.bind(this));\n this._subscribeToChannel('undici:request:headers', this._onResponseHeaders.bind(this));\n }\n\n /**\n * This method is called when a request is created.\n * You can still mutate the request here before it is sent.\n */\n private _onRequestCreated({ request }: { request: UndiciRequest }): void {\n const config = this.getConfig();\n const enabled = config.enabled !== false;\n\n if (!enabled) {\n return;\n }\n\n const shouldIgnore = this._shouldIgnoreOutgoingRequest(request);\n // We store this decisision for later so we do not need to re-evaluate it\n // Additionally, the active context is not correct in _onResponseHeaders, so we need to make sure it is evaluated here\n this._ignoreOutgoingRequestsMap.set(request, shouldIgnore);\n\n if (shouldIgnore) {\n return;\n }\n\n if (config.tracePropagation !== false) {\n addTracePropagationHeadersToFetchRequest(request, this._propagationDecisionMap);\n }\n }\n\n /**\n * This method is called when a response is received.\n */\n private _onResponseHeaders({ request, response }: { request: UndiciRequest; response: UndiciResponse }): void {\n const config = this.getConfig();\n const enabled = config.enabled !== false;\n\n if (!enabled) {\n return;\n }\n\n const _breadcrumbs = config.breadcrumbs;\n const breadCrumbsEnabled = typeof _breadcrumbs === 'undefined' ? true : _breadcrumbs;\n\n const shouldIgnore = this._ignoreOutgoingRequestsMap.get(request);\n\n if (breadCrumbsEnabled && !shouldIgnore) {\n addFetchRequestBreadcrumb(request, response);\n }\n }\n\n /** Subscribe to a diagnostics channel. */\n private _subscribeToChannel(\n diagnosticChannel: string,\n onMessage: (message: unknown, name: string | symbol) => void,\n ): void {\n // `diagnostics_channel` had a ref counting bug until v18.19.0.\n // https://github.com/nodejs/node/pull/47520\n const useNewSubscribe = NODE_MAJOR > 18 || (NODE_MAJOR === 18 && NODE_MINOR >= 19);\n\n let unsubscribe: () => void;\n if (useNewSubscribe) {\n diagch.subscribe?.(diagnosticChannel, onMessage);\n unsubscribe = () => diagch.unsubscribe?.(diagnosticChannel, onMessage);\n } else {\n const channel = diagch.channel(diagnosticChannel);\n channel.subscribe(onMessage);\n unsubscribe = () => channel.unsubscribe(onMessage);\n }\n\n this._channelSubs.push({\n name: diagnosticChannel,\n unsubscribe,\n });\n }\n\n /**\n * Check if the given outgoing request should be ignored.\n */\n private _shouldIgnoreOutgoingRequest(request: UndiciRequest): boolean {\n if (isTracingSuppressed()) {\n return true;\n }\n\n // Add trace propagation headers\n const url = getAbsoluteUrl(request.origin, request.path);\n const ignoreOutgoingRequests = this.getConfig().ignoreOutgoingRequests;\n\n if (typeof ignoreOutgoingRequests !== 'function' || !url) {\n return false;\n }\n\n return ignoreOutgoingRequests(url);\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","LRUMap","addTracePropagationHeadersToFetchRequest","addFetchRequestBreadcrumb","NODE_MAJOR","NODE_MINOR","isTracingSuppressed","getAbsoluteUrl"],"mappings":"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"} | ||
| {"version":3,"file":"SentryNodeFetchInstrumentation.js","sources":["../../../../src/integrations/node-fetch/SentryNodeFetchInstrumentation.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase } from '@opentelemetry/instrumentation';\nimport { LRUMap, SDK_VERSION, isTracingSuppressed } from '@sentry/core';\nimport * as diagch from 'diagnostics_channel';\nimport { NODE_MAJOR, NODE_MINOR } from '../../nodeVersion';\nimport {\n addFetchRequestBreadcrumb,\n addTracePropagationHeadersToFetchRequest,\n getAbsoluteUrl,\n} from '../../utils/outgoingFetchRequest';\nimport type { UndiciRequest, UndiciResponse } from './types';\n\nexport type SentryNodeFetchInstrumentationOptions = InstrumentationConfig & {\n /**\n * Whether breadcrumbs should be recorded for requests.\n *\n * @default `true`\n */\n breadcrumbs?: boolean;\n\n /**\n * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing fetch requests.\n *\n * When set to `false`, Sentry will not inject any trace propagation headers, but will still create breadcrumbs\n * (if `breadcrumbs` is enabled). This is useful when `skipOpenTelemetrySetup: true` is configured and you want\n * to avoid duplicate trace headers being injected by both Sentry and OpenTelemetry's UndiciInstrumentation.\n *\n * @default `true`\n */\n tracePropagation?: boolean;\n\n /**\n * Do not capture breadcrumbs or inject headers for outgoing fetch requests to URLs where the given callback returns `true`.\n * The same option can be passed to the top-level httpIntegration where it controls both, breadcrumb and\n * span creation.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n */\n ignoreOutgoingRequests?: (url: string) => boolean;\n};\n\ninterface ListenerRecord {\n name: string;\n unsubscribe: () => void;\n}\n\n/**\n * This custom node-fetch instrumentation is used to instrument outgoing fetch requests.\n * It does not emit any spans.\n *\n * The reason this is isolated from the OpenTelemetry instrumentation is that users may overwrite this,\n * which would lead to Sentry not working as expected.\n *\n * This is heavily inspired & adapted from:\n * https://github.com/open-telemetry/opentelemetry-js-contrib/blob/28e209a9da36bc4e1f8c2b0db7360170ed46cb80/plugins/node/instrumentation-undici/src/undici.ts\n *\n * @deprecated This class is no longer used internally and will be removed in a future major version. Use `nativeNodeFetchIntegration` instead.\n */\nexport class SentryNodeFetchInstrumentation extends InstrumentationBase<SentryNodeFetchInstrumentationOptions> {\n // Keep ref to avoid https://github.com/nodejs/node/issues/42170 bug and for\n // unsubscribing.\n private _channelSubs: Array<ListenerRecord>;\n private _propagationDecisionMap: LRUMap<string, boolean>;\n private _ignoreOutgoingRequestsMap: WeakMap<UndiciRequest, boolean>;\n\n public constructor(config: SentryNodeFetchInstrumentationOptions = {}) {\n super('@sentry/instrumentation-node-fetch', SDK_VERSION, config);\n this._channelSubs = [];\n this._propagationDecisionMap = new LRUMap<string, boolean>(100);\n this._ignoreOutgoingRequestsMap = new WeakMap<UndiciRequest, boolean>();\n }\n\n /** No need to instrument files/modules. */\n public init(): void {\n return undefined;\n }\n\n /** Disable the instrumentation. */\n public disable(): void {\n super.disable();\n this._channelSubs.forEach(sub => sub.unsubscribe());\n this._channelSubs = [];\n }\n\n /** Enable the instrumentation. */\n public enable(): void {\n // \"enabled\" handling is currently a bit messy with InstrumentationBase.\n // If constructed with `{enabled: false}`, this `.enable()` is still called,\n // and `this.getConfig().enabled !== this.isEnabled()`, creating confusion.\n //\n // For now, this class will setup for instrumenting if `.enable()` is\n // called, but use `this.getConfig().enabled` to determine if\n // instrumentation should be generated. This covers the more likely common\n // case of config being given a construction time, rather than later via\n // `instance.enable()`, `.disable()`, or `.setConfig()` calls.\n super.enable();\n\n // This method is called by the super-class constructor before ours is\n // called. So we need to ensure the property is initalized.\n this._channelSubs = this._channelSubs || [];\n\n // Avoid to duplicate subscriptions\n if (this._channelSubs.length > 0) {\n return;\n }\n\n this._subscribeToChannel('undici:request:create', this._onRequestCreated.bind(this));\n this._subscribeToChannel('undici:request:headers', this._onResponseHeaders.bind(this));\n }\n\n /**\n * This method is called when a request is created.\n * You can still mutate the request here before it is sent.\n */\n private _onRequestCreated({ request }: { request: UndiciRequest }): void {\n const config = this.getConfig();\n const enabled = config.enabled !== false;\n\n if (!enabled) {\n return;\n }\n\n const shouldIgnore = this._shouldIgnoreOutgoingRequest(request);\n // We store this decisision for later so we do not need to re-evaluate it\n // Additionally, the active context is not correct in _onResponseHeaders, so we need to make sure it is evaluated here\n this._ignoreOutgoingRequestsMap.set(request, shouldIgnore);\n\n if (shouldIgnore) {\n return;\n }\n\n if (config.tracePropagation !== false) {\n addTracePropagationHeadersToFetchRequest(request, this._propagationDecisionMap);\n }\n }\n\n /**\n * This method is called when a response is received.\n */\n private _onResponseHeaders({ request, response }: { request: UndiciRequest; response: UndiciResponse }): void {\n const config = this.getConfig();\n const enabled = config.enabled !== false;\n\n if (!enabled) {\n return;\n }\n\n const _breadcrumbs = config.breadcrumbs;\n const breadCrumbsEnabled = typeof _breadcrumbs === 'undefined' ? true : _breadcrumbs;\n\n const shouldIgnore = this._ignoreOutgoingRequestsMap.get(request);\n\n if (breadCrumbsEnabled && !shouldIgnore) {\n addFetchRequestBreadcrumb(request, response);\n }\n }\n\n /** Subscribe to a diagnostics channel. */\n private _subscribeToChannel(\n diagnosticChannel: string,\n onMessage: (message: unknown, name: string | symbol) => void,\n ): void {\n // `diagnostics_channel` had a ref counting bug until v18.19.0.\n // https://github.com/nodejs/node/pull/47520\n const useNewSubscribe = NODE_MAJOR > 18 || (NODE_MAJOR === 18 && NODE_MINOR >= 19);\n\n let unsubscribe: () => void;\n if (useNewSubscribe) {\n diagch.subscribe?.(diagnosticChannel, onMessage);\n unsubscribe = () => diagch.unsubscribe?.(diagnosticChannel, onMessage);\n } else {\n const channel = diagch.channel(diagnosticChannel);\n channel.subscribe(onMessage);\n unsubscribe = () => channel.unsubscribe(onMessage);\n }\n\n this._channelSubs.push({\n name: diagnosticChannel,\n unsubscribe,\n });\n }\n\n /**\n * Check if the given outgoing request should be ignored.\n */\n private _shouldIgnoreOutgoingRequest(request: UndiciRequest): boolean {\n if (isTracingSuppressed()) {\n return true;\n }\n\n // Add trace propagation headers\n const url = getAbsoluteUrl(request.origin, request.path);\n const ignoreOutgoingRequests = this.getConfig().ignoreOutgoingRequests;\n\n if (typeof ignoreOutgoingRequests !== 'function' || !url) {\n return false;\n }\n\n return ignoreOutgoingRequests(url);\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","LRUMap","addTracePropagationHeadersToFetchRequest","addFetchRequestBreadcrumb","NODE_MAJOR","NODE_MINOR","isTracingSuppressed","getAbsoluteUrl"],"mappings":"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"} |
@@ -26,3 +26,2 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const esmLoader = require('../sdk/esmLoader.js'); | ||
| const detection = require('../utils/detection.js'); | ||
| const createMissingInstrumentationContext = require('../utils/createMissingInstrumentationContext.js'); | ||
@@ -63,3 +62,2 @@ const http = require('../transports/http.js'); | ||
| exports.initializeEsmLoader = esmLoader.initializeEsmLoader; | ||
| exports.isCjs = detection.isCjs; | ||
| exports.createMissingInstrumentationContext = createMissingInstrumentationContext.createMissingInstrumentationContext; | ||
@@ -66,0 +64,0 @@ exports.makeNodeTransport = http.makeNodeTransport; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"} | ||
| {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"} |
@@ -18,3 +18,2 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const http = require('../transports/http.js'); | ||
| require('../nodeVersion.js'); | ||
| const spotlight$1 = require('../utils/spotlight.js'); | ||
@@ -81,3 +80,3 @@ const asyncLocalStorageStrategy = require('./asyncLocalStorageStrategy.js'); | ||
| client$1.init(); | ||
| core.debug.log(`SDK initialized from ${"CommonJS" } (light mode)`); | ||
| core.debug.log(`SDK initialized from CommonJS (light mode)`); | ||
| client$1.startClientReportTracking(); | ||
@@ -84,0 +83,0 @@ updateScopeFromEnvVariables(); |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"sdk.js","sources":["../../../src/light/sdk.ts"],"sourcesContent":["import type { Integration, Options } from '@sentry/core';\nimport {\n applySdkMetadata,\n consoleSandbox,\n debug,\n envToBool,\n eventFiltersIntegration,\n functionToStringIntegration,\n getCurrentScope,\n getIntegrationsToSetup,\n linkedErrorsIntegration,\n propagationContextFromHeaders,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { childProcessIntegration } from '../integrations/childProcess';\nimport { nodeContextIntegration } from '../integrations/context';\nimport { contextLinesIntegration } from '../integrations/contextlines';\nimport { localVariablesIntegration } from '../integrations/local-variables';\nimport { modulesIntegration } from '../integrations/modules';\nimport { onUncaughtExceptionIntegration } from '../integrations/onuncaughtexception';\nimport { onUnhandledRejectionIntegration } from '../integrations/onunhandledrejection';\nimport { processSessionIntegration } from '../integrations/processSession';\nimport { INTEGRATION_NAME as SPOTLIGHT_INTEGRATION_NAME, spotlightIntegration } from '../integrations/spotlight';\nimport { consoleIntegration } from '../integrations/console';\nimport { systemErrorIntegration } from '../integrations/systemError';\nimport { defaultStackParser, getSentryRelease } from '../sdk/api';\nimport { makeNodeTransport } from '../transports';\nimport type { NodeClientOptions, NodeOptions } from '../types';\nimport { isCjs } from '../utils/detection';\nimport { getSpotlightConfig } from '../utils/spotlight';\nimport { setAsyncLocalStorageAsyncContextStrategy } from './asyncLocalStorageStrategy';\nimport { LightNodeClient } from './client';\nimport { httpIntegration } from './integrations/httpIntegration';\nimport { nativeNodeFetchIntegration } from './integrations/nativeNodeFetchIntegration';\n\n/**\n * Get default integrations for the Light Node-Core SDK.\n */\nexport function getDefaultIntegrations(): Integration[] {\n return [\n // Common\n eventFiltersIntegration(),\n functionToStringIntegration(),\n linkedErrorsIntegration(),\n requestDataIntegration(),\n systemErrorIntegration(),\n // Native Wrappers\n consoleIntegration(),\n httpIntegration(),\n nativeNodeFetchIntegration(),\n // Global Handlers\n onUncaughtExceptionIntegration(),\n onUnhandledRejectionIntegration(),\n // Event Info\n contextLinesIntegration(),\n localVariablesIntegration(),\n nodeContextIntegration(),\n childProcessIntegration(),\n processSessionIntegration(),\n modulesIntegration(),\n ];\n}\n\n/**\n * Initialize Sentry for Node in light mode (without OpenTelemetry).\n */\nexport function init(options: NodeOptions | undefined = {}): LightNodeClient | undefined {\n return _init(options, getDefaultIntegrations);\n}\n\n/**\n * Initialize Sentry for Node in light mode, without any integrations added by default.\n */\nexport function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): LightNodeClient {\n return _init(options, () => []);\n}\n\n/**\n * Initialize Sentry for Node in light mode.\n */\nfunction _init(\n _options: NodeOptions | undefined = {},\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): LightNodeClient {\n const options = getClientOptions(_options, getDefaultIntegrationsImpl);\n\n if (options.debug === true) {\n if (DEBUG_BUILD) {\n debug.enable();\n } else {\n // use `console.warn` rather than `debug.warn` since by non-debug bundles have all `debug.x` statements stripped\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.');\n });\n }\n }\n\n // Use AsyncLocalStorage-based context strategy instead of OpenTelemetry\n setAsyncLocalStorageAsyncContextStrategy();\n\n const scope = getCurrentScope();\n scope.update(options.initialScope);\n\n if (options.spotlight && !options.integrations.some(({ name }) => name === SPOTLIGHT_INTEGRATION_NAME)) {\n options.integrations.push(\n spotlightIntegration({\n sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined,\n }),\n );\n }\n\n applySdkMetadata(options, 'node-light', ['node-core']);\n\n const client = new LightNodeClient(options);\n // The client is on the current scope, from where it generally is inherited\n getCurrentScope().setClient(client);\n\n client.init();\n\n debug.log(`SDK initialized from ${isCjs() ? 'CommonJS' : 'ESM'} (light mode)`);\n\n client.startClientReportTracking();\n\n updateScopeFromEnvVariables();\n\n // Ensure we flush events when vercel functions are ended\n // See: https://vercel.com/docs/functions/functions-api-reference#sigterm-signal\n if (process.env.VERCEL) {\n process.on('SIGTERM', async () => {\n // We have 500ms for processing here, so we try to make sure to have enough time to send the events\n await client.flush(200);\n });\n }\n\n return client;\n}\n\nfunction getClientOptions(\n options: NodeOptions,\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClientOptions {\n const release = getRelease(options.release);\n const spotlight = getSpotlightConfig(options.spotlight);\n const tracesSampleRate = getTracesSampleRate(options.tracesSampleRate);\n\n const mergedOptions = {\n ...options,\n dsn: options.dsn ?? process.env.SENTRY_DSN,\n environment: options.environment ?? process.env.SENTRY_ENVIRONMENT,\n sendClientReports: options.sendClientReports ?? true,\n transport: options.transport ?? makeNodeTransport,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n release,\n tracesSampleRate,\n spotlight,\n debug: envToBool(options.debug ?? process.env.SENTRY_DEBUG),\n };\n\n const integrations = options.integrations;\n const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(mergedOptions);\n\n const resolvedIntegrations = getIntegrationsToSetup({\n defaultIntegrations,\n integrations,\n });\n\n return {\n ...mergedOptions,\n integrations: resolvedIntegrations,\n };\n}\n\nfunction getRelease(release: NodeOptions['release']): string | undefined {\n if (release !== undefined) {\n return release;\n }\n\n const detectedRelease = getSentryRelease();\n if (detectedRelease !== undefined) {\n return detectedRelease;\n }\n\n return undefined;\n}\n\nfunction getTracesSampleRate(tracesSampleRate: NodeOptions['tracesSampleRate']): number | undefined {\n if (tracesSampleRate !== undefined) {\n return tracesSampleRate;\n }\n\n const sampleRateFromEnv = process.env.SENTRY_TRACES_SAMPLE_RATE;\n if (!sampleRateFromEnv) {\n return undefined;\n }\n\n const parsed = parseFloat(sampleRateFromEnv);\n return isFinite(parsed) ? parsed : undefined;\n}\n\n/**\n * Update scope and propagation context based on environmental variables.\n *\n * See https://github.com/getsentry/rfcs/blob/main/text/0071-continue-trace-over-process-boundaries.md\n * for more details.\n */\nfunction updateScopeFromEnvVariables(): void {\n if (envToBool(process.env.SENTRY_USE_ENVIRONMENT) !== false) {\n const sentryTraceEnv = process.env.SENTRY_TRACE;\n const baggageEnv = process.env.SENTRY_BAGGAGE;\n const propagationContext = propagationContextFromHeaders(sentryTraceEnv, baggageEnv);\n getCurrentScope().setPropagationContext(propagationContext);\n }\n}\n"],"names":["eventFiltersIntegration","functionToStringIntegration","linkedErrorsIntegration","requestDataIntegration","systemErrorIntegration","consoleIntegration","httpIntegration","nativeNodeFetchIntegration","onUncaughtExceptionIntegration","onUnhandledRejectionIntegration","contextLinesIntegration","localVariablesIntegration","nodeContextIntegration","childProcessIntegration","processSessionIntegration","modulesIntegration","DEBUG_BUILD","debug","consoleSandbox","setAsyncLocalStorageAsyncContextStrategy","getCurrentScope","SPOTLIGHT_INTEGRATION_NAME","spotlightIntegration","applySdkMetadata","client","LightNodeClient","getSpotlightConfig","makeNodeTransport","stackParserFromStackParserOptions","defaultStackParser","envToBool","getIntegrationsToSetup","getSentryRelease","propagationContextFromHeaders"],"mappings":"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"} | ||
| {"version":3,"file":"sdk.js","sources":["../../../src/light/sdk.ts"],"sourcesContent":["import type { Integration, Options } from '@sentry/core';\nimport {\n applySdkMetadata,\n consoleSandbox,\n debug,\n envToBool,\n eventFiltersIntegration,\n functionToStringIntegration,\n getCurrentScope,\n getIntegrationsToSetup,\n linkedErrorsIntegration,\n propagationContextFromHeaders,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { childProcessIntegration } from '../integrations/childProcess';\nimport { nodeContextIntegration } from '../integrations/context';\nimport { contextLinesIntegration } from '../integrations/contextlines';\nimport { localVariablesIntegration } from '../integrations/local-variables';\nimport { modulesIntegration } from '../integrations/modules';\nimport { onUncaughtExceptionIntegration } from '../integrations/onuncaughtexception';\nimport { onUnhandledRejectionIntegration } from '../integrations/onunhandledrejection';\nimport { processSessionIntegration } from '../integrations/processSession';\nimport { INTEGRATION_NAME as SPOTLIGHT_INTEGRATION_NAME, spotlightIntegration } from '../integrations/spotlight';\nimport { consoleIntegration } from '../integrations/console';\nimport { systemErrorIntegration } from '../integrations/systemError';\nimport { defaultStackParser, getSentryRelease } from '../sdk/api';\nimport { makeNodeTransport } from '../transports';\nimport type { NodeClientOptions, NodeOptions } from '../types';\nimport { getSpotlightConfig } from '../utils/spotlight';\nimport { setAsyncLocalStorageAsyncContextStrategy } from './asyncLocalStorageStrategy';\nimport { LightNodeClient } from './client';\nimport { httpIntegration } from './integrations/httpIntegration';\nimport { nativeNodeFetchIntegration } from './integrations/nativeNodeFetchIntegration';\n\n/**\n * Get default integrations for the Light Node-Core SDK.\n */\nexport function getDefaultIntegrations(): Integration[] {\n return [\n // Common\n eventFiltersIntegration(),\n functionToStringIntegration(),\n linkedErrorsIntegration(),\n requestDataIntegration(),\n systemErrorIntegration(),\n // Native Wrappers\n consoleIntegration(),\n httpIntegration(),\n nativeNodeFetchIntegration(),\n // Global Handlers\n onUncaughtExceptionIntegration(),\n onUnhandledRejectionIntegration(),\n // Event Info\n contextLinesIntegration(),\n localVariablesIntegration(),\n nodeContextIntegration(),\n childProcessIntegration(),\n processSessionIntegration(),\n modulesIntegration(),\n ];\n}\n\n/**\n * Initialize Sentry for Node in light mode (without OpenTelemetry).\n */\nexport function init(options: NodeOptions | undefined = {}): LightNodeClient | undefined {\n return _init(options, getDefaultIntegrations);\n}\n\n/**\n * Initialize Sentry for Node in light mode, without any integrations added by default.\n */\nexport function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): LightNodeClient {\n return _init(options, () => []);\n}\n\n/**\n * Initialize Sentry for Node in light mode.\n */\nfunction _init(\n _options: NodeOptions | undefined = {},\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): LightNodeClient {\n const options = getClientOptions(_options, getDefaultIntegrationsImpl);\n\n if (options.debug === true) {\n if (DEBUG_BUILD) {\n debug.enable();\n } else {\n // use `console.warn` rather than `debug.warn` since by non-debug bundles have all `debug.x` statements stripped\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.');\n });\n }\n }\n\n // Use AsyncLocalStorage-based context strategy instead of OpenTelemetry\n setAsyncLocalStorageAsyncContextStrategy();\n\n const scope = getCurrentScope();\n scope.update(options.initialScope);\n\n if (options.spotlight && !options.integrations.some(({ name }) => name === SPOTLIGHT_INTEGRATION_NAME)) {\n options.integrations.push(\n spotlightIntegration({\n sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined,\n }),\n );\n }\n\n applySdkMetadata(options, 'node-light', ['node-core']);\n\n const client = new LightNodeClient(options);\n // The client is on the current scope, from where it generally is inherited\n getCurrentScope().setClient(client);\n\n client.init();\n\n /*! rollup-include-cjs-only */\n debug.log(`SDK initialized from CommonJS (light mode)`);\n /*! rollup-include-cjs-only-end */\n /*! rollup-include-esm-only */\n debug.log(`SDK initialized from ESM (light mode)`);\n /*! rollup-include-esm-only-end */\n\n client.startClientReportTracking();\n\n updateScopeFromEnvVariables();\n\n // Ensure we flush events when vercel functions are ended\n // See: https://vercel.com/docs/functions/functions-api-reference#sigterm-signal\n if (process.env.VERCEL) {\n process.on('SIGTERM', async () => {\n // We have 500ms for processing here, so we try to make sure to have enough time to send the events\n await client.flush(200);\n });\n }\n\n return client;\n}\n\nfunction getClientOptions(\n options: NodeOptions,\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClientOptions {\n const release = getRelease(options.release);\n const spotlight = getSpotlightConfig(options.spotlight);\n const tracesSampleRate = getTracesSampleRate(options.tracesSampleRate);\n\n const mergedOptions = {\n ...options,\n dsn: options.dsn ?? process.env.SENTRY_DSN,\n environment: options.environment ?? process.env.SENTRY_ENVIRONMENT,\n sendClientReports: options.sendClientReports ?? true,\n transport: options.transport ?? makeNodeTransport,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n release,\n tracesSampleRate,\n spotlight,\n debug: envToBool(options.debug ?? process.env.SENTRY_DEBUG),\n };\n\n const integrations = options.integrations;\n const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(mergedOptions);\n\n const resolvedIntegrations = getIntegrationsToSetup({\n defaultIntegrations,\n integrations,\n });\n\n return {\n ...mergedOptions,\n integrations: resolvedIntegrations,\n };\n}\n\nfunction getRelease(release: NodeOptions['release']): string | undefined {\n if (release !== undefined) {\n return release;\n }\n\n const detectedRelease = getSentryRelease();\n if (detectedRelease !== undefined) {\n return detectedRelease;\n }\n\n return undefined;\n}\n\nfunction getTracesSampleRate(tracesSampleRate: NodeOptions['tracesSampleRate']): number | undefined {\n if (tracesSampleRate !== undefined) {\n return tracesSampleRate;\n }\n\n const sampleRateFromEnv = process.env.SENTRY_TRACES_SAMPLE_RATE;\n if (!sampleRateFromEnv) {\n return undefined;\n }\n\n const parsed = parseFloat(sampleRateFromEnv);\n return isFinite(parsed) ? parsed : undefined;\n}\n\n/**\n * Update scope and propagation context based on environmental variables.\n *\n * See https://github.com/getsentry/rfcs/blob/main/text/0071-continue-trace-over-process-boundaries.md\n * for more details.\n */\nfunction updateScopeFromEnvVariables(): void {\n if (envToBool(process.env.SENTRY_USE_ENVIRONMENT) !== false) {\n const sentryTraceEnv = process.env.SENTRY_TRACE;\n const baggageEnv = process.env.SENTRY_BAGGAGE;\n const propagationContext = propagationContextFromHeaders(sentryTraceEnv, baggageEnv);\n getCurrentScope().setPropagationContext(propagationContext);\n }\n}\n"],"names":["eventFiltersIntegration","functionToStringIntegration","linkedErrorsIntegration","requestDataIntegration","systemErrorIntegration","consoleIntegration","httpIntegration","nativeNodeFetchIntegration","onUncaughtExceptionIntegration","onUnhandledRejectionIntegration","contextLinesIntegration","localVariablesIntegration","nodeContextIntegration","childProcessIntegration","processSessionIntegration","modulesIntegration","DEBUG_BUILD","debug","consoleSandbox","setAsyncLocalStorageAsyncContextStrategy","getCurrentScope","SPOTLIGHT_INTEGRATION_NAME","spotlightIntegration","applySdkMetadata","client","LightNodeClient","getSpotlightConfig","makeNodeTransport","stackParserFromStackParserOptions","defaultStackParser","envToBool","getIntegrationsToSetup","getSentryRelease","propagationContextFromHeaders"],"mappings":"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"} |
@@ -44,2 +44,3 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| } | ||
| core._INTERNAL_setDeferSegmentSpanCapture(this); | ||
| } | ||
@@ -46,0 +47,0 @@ /** Get the OTEL tracer. */ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"client.js","sources":["../../../src/sdk/client.ts"],"sourcesContent":["import * as os from 'node:os';\nimport type { Tracer } from '@opentelemetry/api';\nimport { trace } from '@opentelemetry/api';\nimport { registerInstrumentations } from '@opentelemetry/instrumentation';\nimport type { BasicTracerProvider } from '@opentelemetry/sdk-trace-base';\nimport type { DynamicSamplingContext, Scope, ServerRuntimeClientOptions, TraceContext } from '@sentry/core';\nimport {\n _INTERNAL_clearAiProviderSkips,\n _INTERNAL_flushLogsBuffer,\n applySdkMetadata,\n debug,\n SDK_VERSION,\n ServerRuntimeClient,\n} from '@sentry/core';\nimport { type AsyncLocalStorageLookup, getTraceContextForScope } from '@sentry/opentelemetry';\nimport { isMainThread, threadId } from 'worker_threads';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { NodeClientOptions } from '../types';\n\nconst DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS = 60_000; // 60s was chosen arbitrarily\n\n/** A client for using Sentry with Node & OpenTelemetry. */\nexport class NodeClient extends ServerRuntimeClient<NodeClientOptions> {\n public traceProvider: BasicTracerProvider | undefined;\n public asyncLocalStorageLookup: AsyncLocalStorageLookup | undefined;\n\n private _tracer: Tracer | undefined;\n private _clientReportInterval: NodeJS.Timeout | undefined;\n private _clientReportOnExitFlushListener: (() => void) | undefined;\n private _logOnExitFlushListener: (() => void) | undefined;\n\n public constructor(options: NodeClientOptions) {\n const serverName =\n options.includeServerName === false\n ? undefined\n : options.serverName || global.process.env.SENTRY_NAME || os.hostname();\n\n const clientOptions: ServerRuntimeClientOptions = {\n ...options,\n platform: 'node',\n // Use provided runtime or default to 'node' with current process version\n runtime: options.runtime || { name: 'node', version: global.process.version },\n serverName,\n };\n\n if (options.openTelemetryInstrumentations) {\n registerInstrumentations({\n instrumentations: options.openTelemetryInstrumentations,\n });\n }\n\n applySdkMetadata(clientOptions, 'node');\n\n debug.log(`Initializing Sentry: process: ${process.pid}, thread: ${isMainThread ? 'main' : `worker-${threadId}`}.`);\n\n super(clientOptions);\n\n if (this.getOptions().enableLogs) {\n this._logOnExitFlushListener = () => {\n _INTERNAL_flushLogsBuffer(this);\n };\n\n if (serverName) {\n this.on('beforeCaptureLog', log => {\n log.attributes = {\n ...log.attributes,\n 'server.address': serverName,\n };\n });\n }\n\n process.on('beforeExit', this._logOnExitFlushListener);\n }\n }\n\n /** Get the OTEL tracer. */\n public get tracer(): Tracer {\n if (this._tracer) {\n return this._tracer;\n }\n\n const name = '@sentry/node';\n const version = SDK_VERSION;\n const tracer = trace.getTracer(name, version);\n this._tracer = tracer;\n\n return tracer;\n }\n\n /** @inheritDoc */\n // @ts-expect-error - PromiseLike is a subset of Promise\n public async flush(timeout?: number): PromiseLike<boolean> {\n await this.traceProvider?.forceFlush();\n\n if (this.getOptions().sendClientReports) {\n this._flushOutcomes();\n }\n\n return super.flush(timeout);\n }\n\n /** @inheritDoc */\n // @ts-expect-error - PromiseLike is a subset of Promise\n public async close(timeout?: number | undefined): PromiseLike<boolean> {\n if (this._clientReportInterval) {\n clearInterval(this._clientReportInterval);\n }\n\n if (this._clientReportOnExitFlushListener) {\n process.off('beforeExit', this._clientReportOnExitFlushListener);\n }\n\n if (this._logOnExitFlushListener) {\n process.off('beforeExit', this._logOnExitFlushListener);\n }\n\n const allEventsSent = await super.close(timeout);\n if (this.traceProvider) {\n await this.traceProvider.shutdown();\n }\n\n return allEventsSent;\n }\n\n /**\n * Will start tracking client reports for this client.\n *\n * NOTICE: This method will create an interval that is periodically called and attach a `process.on('beforeExit')`\n * hook. To clean up these resources, call `.close()` when you no longer intend to use the client. Not doing so will\n * result in a memory leak.\n */\n // The reason client reports need to be manually activated with this method instead of just enabling them in a\n // constructor, is that if users periodically and unboundedly create new clients, we will create more and more\n // intervals and beforeExit listeners, thus leaking memory. In these situations, users are required to call\n // `client.close()` in order to dispose of the acquired resources.\n // We assume that calling this method in Sentry.init() is a sensible default, because calling Sentry.init() over and\n // over again would also result in memory leaks.\n // Note: We have experimented with using `FinalizationRegisty` to clear the interval when the client is garbage\n // collected, but it did not work, because the cleanup function never got called.\n public startClientReportTracking(): void {\n const clientOptions = this.getOptions();\n if (clientOptions.sendClientReports) {\n this._clientReportOnExitFlushListener = () => {\n this._flushOutcomes();\n };\n\n this._clientReportInterval = setInterval(() => {\n DEBUG_BUILD && debug.log('Flushing client reports based on interval.');\n this._flushOutcomes();\n }, clientOptions.clientReportFlushInterval ?? DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS)\n // Unref is critical for not preventing the process from exiting because the interval is active.\n .unref();\n\n process.on('beforeExit', this._clientReportOnExitFlushListener);\n }\n }\n\n /** @inheritDoc */\n protected _setupIntegrations(): void {\n // Clear AI provider skip registrations before setting up integrations\n // This ensures a clean state between different client initializations\n // (e.g., when LangChain skips OpenAI in one client, but a subsequent client uses OpenAI standalone)\n _INTERNAL_clearAiProviderSkips();\n super._setupIntegrations();\n }\n\n /** Custom implementation for OTEL, so we can handle scope-span linking. */\n protected _getTraceInfoFromScope(\n scope: Scope | undefined,\n ): [dynamicSamplingContext: Partial<DynamicSamplingContext> | undefined, traceContext: TraceContext | undefined] {\n if (!scope) {\n return [undefined, undefined];\n }\n\n return getTraceContextForScope(this, scope);\n }\n}\n"],"names":["ServerRuntimeClient","registerInstrumentations","applySdkMetadata","debug","isMainThread","threadId","_INTERNAL_flushLogsBuffer","SDK_VERSION","trace","DEBUG_BUILD","_INTERNAL_clearAiProviderSkips","getTraceContextForScope"],"mappings":";;;;;;;;;;AAmBA,MAAM,uCAAA,GAA0C,GAAA;AAGzC,MAAM,mBAAmBA,wBAAA,CAAuC;AAAA,EAS9D,YAAY,OAAA,EAA4B;AAC7C,IAAA,MAAM,UAAA,GACJ,OAAA,CAAQ,iBAAA,KAAsB,KAAA,GAC1B,MAAA,GACA,OAAA,CAAQ,UAAA,IAAc,MAAA,CAAO,OAAA,CAAQ,GAAA,CAAI,WAAA,IAAe,EAAA,CAAG,QAAA,EAAS;AAE1E,IAAA,MAAM,aAAA,GAA4C;AAAA,MAChD,GAAG,OAAA;AAAA,MACH,QAAA,EAAU,MAAA;AAAA;AAAA,MAEV,OAAA,EAAS,QAAQ,OAAA,IAAW,EAAE,MAAM,MAAA,EAAQ,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,OAAA,EAAQ;AAAA,MAC5E;AAAA,KACF;AAEA,IAAA,IAAI,QAAQ,6BAAA,EAA+B;AACzC,MAAAC,wCAAA,CAAyB;AAAA,QACvB,kBAAkB,OAAA,CAAQ;AAAA,OAC3B,CAAA;AAAA,IACH;AAEA,IAAAC,qBAAA,CAAiB,eAAe,MAAM,CAAA;AAEtC,IAAAC,UAAA,CAAM,GAAA,CAAI,CAAA,8BAAA,EAAiC,OAAA,CAAQ,GAAG,CAAA,UAAA,EAAaC,8BAAe,MAAA,GAAS,CAAA,OAAA,EAAUC,uBAAQ,CAAA,CAAE,CAAA,CAAA,CAAG,CAAA;AAElH,IAAA,KAAA,CAAM,aAAa,CAAA;AAEnB,IAAA,IAAI,IAAA,CAAK,UAAA,EAAW,CAAE,UAAA,EAAY;AAChC,MAAA,IAAA,CAAK,0BAA0B,MAAM;AACnC,QAAAC,8BAAA,CAA0B,IAAI,CAAA;AAAA,MAChC,CAAA;AAEA,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,IAAA,CAAK,EAAA,CAAG,oBAAoB,CAAA,GAAA,KAAO;AACjC,UAAA,GAAA,CAAI,UAAA,GAAa;AAAA,YACf,GAAG,GAAA,CAAI,UAAA;AAAA,YACP,gBAAA,EAAkB;AAAA,WACpB;AAAA,QACF,CAAC,CAAA;AAAA,MACH;AAEA,MAAA,OAAA,CAAQ,EAAA,CAAG,YAAA,EAAc,IAAA,CAAK,uBAAuB,CAAA;AAAA,IACvD;AAAA,EACF;AAAA;AAAA,EAGA,IAAW,MAAA,GAAiB;AAC1B,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,OAAO,IAAA,CAAK,OAAA;AAAA,IACd;AAEA,IAAA,MAAM,IAAA,GAAO,cAAA;AACb,IAAA,MAAM,OAAA,GAAUC,gBAAA;AAChB,IAAA,MAAM,MAAA,GAASC,SAAA,CAAM,SAAA,CAAU,IAAA,EAAM,OAAO,CAAA;AAC5C,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AAEf,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA,EAIA,MAAa,MAAM,OAAA,EAAwC;AACzD,IAAA,MAAM,IAAA,CAAK,eAAe,UAAA,EAAW;AAErC,IAAA,IAAI,IAAA,CAAK,UAAA,EAAW,CAAE,iBAAA,EAAmB;AACvC,MAAA,IAAA,CAAK,cAAA,EAAe;AAAA,IACtB;AAEA,IAAA,OAAO,KAAA,CAAM,MAAM,OAAO,CAAA;AAAA,EAC5B;AAAA;AAAA;AAAA,EAIA,MAAa,MAAM,OAAA,EAAoD;AACrE,IAAA,IAAI,KAAK,qBAAA,EAAuB;AAC9B,MAAA,aAAA,CAAc,KAAK,qBAAqB,CAAA;AAAA,IAC1C;AAEA,IAAA,IAAI,KAAK,gCAAA,EAAkC;AACzC,MAAA,OAAA,CAAQ,GAAA,CAAI,YAAA,EAAc,IAAA,CAAK,gCAAgC,CAAA;AAAA,IACjE;AAEA,IAAA,IAAI,KAAK,uBAAA,EAAyB;AAChC,MAAA,OAAA,CAAQ,GAAA,CAAI,YAAA,EAAc,IAAA,CAAK,uBAAuB,CAAA;AAAA,IACxD;AAEA,IAAA,MAAM,aAAA,GAAgB,MAAM,KAAA,CAAM,KAAA,CAAM,OAAO,CAAA;AAC/C,IAAA,IAAI,KAAK,aAAA,EAAe;AACtB,MAAA,MAAM,IAAA,CAAK,cAAc,QAAA,EAAS;AAAA,IACpC;AAEA,IAAA,OAAO,aAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBO,yBAAA,GAAkC;AACvC,IAAA,MAAM,aAAA,GAAgB,KAAK,UAAA,EAAW;AACtC,IAAA,IAAI,cAAc,iBAAA,EAAmB;AACnC,MAAA,IAAA,CAAK,mCAAmC,MAAM;AAC5C,QAAA,IAAA,CAAK,cAAA,EAAe;AAAA,MACtB,CAAA;AAEA,MAAA,IAAA,CAAK,qBAAA,GAAwB,YAAY,MAAM;AAC7C,QAAAC,sBAAA,IAAeN,UAAA,CAAM,IAAI,4CAA4C,CAAA;AACrE,QAAA,IAAA,CAAK,cAAA,EAAe;AAAA,MACtB,CAAA,EAAG,aAAA,CAAc,yBAAA,IAA6B,uCAAuC,EAElF,KAAA,EAAM;AAET,MAAA,OAAA,CAAQ,EAAA,CAAG,YAAA,EAAc,IAAA,CAAK,gCAAgC,CAAA;AAAA,IAChE;AAAA,EACF;AAAA;AAAA,EAGU,kBAAA,GAA2B;AAInC,IAAAO,mCAAA,EAA+B;AAC/B,IAAA,KAAA,CAAM,kBAAA,EAAmB;AAAA,EAC3B;AAAA;AAAA,EAGU,uBACR,KAAA,EAC+G;AAC/G,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAO,CAAC,QAAW,MAAS,CAAA;AAAA,IAC9B;AAEA,IAAA,OAAOC,qCAAA,CAAwB,MAAM,KAAK,CAAA;AAAA,EAC5C;AACF;;;;"} | ||
| {"version":3,"file":"client.js","sources":["../../../src/sdk/client.ts"],"sourcesContent":["import * as os from 'node:os';\nimport type { Tracer } from '@opentelemetry/api';\nimport { trace } from '@opentelemetry/api';\nimport { registerInstrumentations } from '@opentelemetry/instrumentation';\nimport type { DynamicSamplingContext, Scope, ServerRuntimeClientOptions, TraceContext } from '@sentry/core';\nimport {\n _INTERNAL_clearAiProviderSkips,\n _INTERNAL_flushLogsBuffer,\n _INTERNAL_setDeferSegmentSpanCapture,\n applySdkMetadata,\n debug,\n SDK_VERSION,\n ServerRuntimeClient,\n} from '@sentry/core';\nimport {\n type AsyncLocalStorageLookup,\n getTraceContextForScope,\n type OpenTelemetryTracerProvider,\n} from '@sentry/opentelemetry';\nimport { isMainThread, threadId } from 'worker_threads';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { NodeClientOptions } from '../types';\n\nconst DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS = 60_000; // 60s was chosen arbitrarily\n\n/** A client for using Sentry with Node & OpenTelemetry. */\nexport class NodeClient extends ServerRuntimeClient<NodeClientOptions> {\n public traceProvider: OpenTelemetryTracerProvider | undefined;\n public asyncLocalStorageLookup: AsyncLocalStorageLookup | undefined;\n\n private _tracer: Tracer | undefined;\n private _clientReportInterval: NodeJS.Timeout | undefined;\n private _clientReportOnExitFlushListener: (() => void) | undefined;\n private _logOnExitFlushListener: (() => void) | undefined;\n\n public constructor(options: NodeClientOptions) {\n const serverName =\n options.includeServerName === false\n ? undefined\n : options.serverName || global.process.env.SENTRY_NAME || os.hostname();\n\n const clientOptions: ServerRuntimeClientOptions = {\n ...options,\n platform: 'node',\n // Use provided runtime or default to 'node' with current process version\n runtime: options.runtime || { name: 'node', version: global.process.version },\n serverName,\n };\n\n if (options.openTelemetryInstrumentations) {\n registerInstrumentations({\n instrumentations: options.openTelemetryInstrumentations,\n });\n }\n\n applySdkMetadata(clientOptions, 'node');\n\n debug.log(`Initializing Sentry: process: ${process.pid}, thread: ${isMainThread ? 'main' : `worker-${threadId}`}.`);\n\n super(clientOptions);\n\n if (this.getOptions().enableLogs) {\n this._logOnExitFlushListener = () => {\n _INTERNAL_flushLogsBuffer(this);\n };\n\n if (serverName) {\n this.on('beforeCaptureLog', log => {\n log.attributes = {\n ...log.attributes,\n 'server.address': serverName,\n };\n });\n }\n\n process.on('beforeExit', this._logOnExitFlushListener);\n }\n\n // Enable deferred segment-span transaction capture here, in the constructor, rather than in\n // `initOtel`. Every client runs its constructor exactly once, whereas `initOtel` only runs on\n // `Sentry.init()` and only fully wires up the first client (a second `init` loses the\n // `setGlobalTracerProvider` race and bails early, and a manually constructed `NodeClient` never\n // runs `initOtel` at all). Anchoring on the constructor means every client — first, second, or\n // manual — defers correctly. It's unconditional and cheap: clients on the OpenTelemetry SDK\n // provider path produce OTel spans that never reach `SentrySpan`, so the strategy is simply never\n // consulted for them.\n _INTERNAL_setDeferSegmentSpanCapture(this);\n }\n\n /** Get the OTEL tracer. */\n public get tracer(): Tracer {\n if (this._tracer) {\n return this._tracer;\n }\n\n const name = '@sentry/node';\n const version = SDK_VERSION;\n const tracer = trace.getTracer(name, version);\n this._tracer = tracer;\n\n return tracer;\n }\n\n /** @inheritDoc */\n // @ts-expect-error - PromiseLike is a subset of Promise\n public async flush(timeout?: number): PromiseLike<boolean> {\n await this.traceProvider?.forceFlush();\n\n if (this.getOptions().sendClientReports) {\n this._flushOutcomes();\n }\n\n return super.flush(timeout);\n }\n\n /** @inheritDoc */\n // @ts-expect-error - PromiseLike is a subset of Promise\n public async close(timeout?: number | undefined): PromiseLike<boolean> {\n if (this._clientReportInterval) {\n clearInterval(this._clientReportInterval);\n }\n\n if (this._clientReportOnExitFlushListener) {\n process.off('beforeExit', this._clientReportOnExitFlushListener);\n }\n\n if (this._logOnExitFlushListener) {\n process.off('beforeExit', this._logOnExitFlushListener);\n }\n\n const allEventsSent = await super.close(timeout);\n if (this.traceProvider) {\n await this.traceProvider.shutdown();\n }\n\n return allEventsSent;\n }\n\n /**\n * Will start tracking client reports for this client.\n *\n * NOTICE: This method will create an interval that is periodically called and attach a `process.on('beforeExit')`\n * hook. To clean up these resources, call `.close()` when you no longer intend to use the client. Not doing so will\n * result in a memory leak.\n */\n // The reason client reports need to be manually activated with this method instead of just enabling them in a\n // constructor, is that if users periodically and unboundedly create new clients, we will create more and more\n // intervals and beforeExit listeners, thus leaking memory. In these situations, users are required to call\n // `client.close()` in order to dispose of the acquired resources.\n // We assume that calling this method in Sentry.init() is a sensible default, because calling Sentry.init() over and\n // over again would also result in memory leaks.\n // Note: We have experimented with using `FinalizationRegisty` to clear the interval when the client is garbage\n // collected, but it did not work, because the cleanup function never got called.\n public startClientReportTracking(): void {\n const clientOptions = this.getOptions();\n if (clientOptions.sendClientReports) {\n this._clientReportOnExitFlushListener = () => {\n this._flushOutcomes();\n };\n\n this._clientReportInterval = setInterval(() => {\n DEBUG_BUILD && debug.log('Flushing client reports based on interval.');\n this._flushOutcomes();\n }, clientOptions.clientReportFlushInterval ?? DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS)\n // Unref is critical for not preventing the process from exiting because the interval is active.\n .unref();\n\n process.on('beforeExit', this._clientReportOnExitFlushListener);\n }\n }\n\n /** @inheritDoc */\n protected _setupIntegrations(): void {\n // Clear AI provider skip registrations before setting up integrations\n // This ensures a clean state between different client initializations\n // (e.g., when LangChain skips OpenAI in one client, but a subsequent client uses OpenAI standalone)\n _INTERNAL_clearAiProviderSkips();\n super._setupIntegrations();\n }\n\n /** Custom implementation for OTEL, so we can handle scope-span linking. */\n protected _getTraceInfoFromScope(\n scope: Scope | undefined,\n ): [dynamicSamplingContext: Partial<DynamicSamplingContext> | undefined, traceContext: TraceContext | undefined] {\n if (!scope) {\n return [undefined, undefined];\n }\n\n return getTraceContextForScope(this, scope);\n }\n}\n"],"names":["ServerRuntimeClient","registerInstrumentations","applySdkMetadata","debug","isMainThread","threadId","_INTERNAL_flushLogsBuffer","_INTERNAL_setDeferSegmentSpanCapture","SDK_VERSION","trace","DEBUG_BUILD","_INTERNAL_clearAiProviderSkips","getTraceContextForScope"],"mappings":"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"} |
@@ -20,3 +20,2 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const http = require('../transports/http.js'); | ||
| require('../nodeVersion.js'); | ||
| const spotlight$1 = require('../utils/spotlight.js'); | ||
@@ -88,3 +87,3 @@ const api = require('./api.js'); | ||
| client$1.init(); | ||
| core.debug.log(`SDK initialized from ${"CommonJS" }`); | ||
| core.debug.log(`SDK initialized from CommonJS`); | ||
| client$1.startClientReportTracking(); | ||
@@ -107,3 +106,4 @@ updateScopeFromEnvVariables(); | ||
| const required = ["SentryContextManager", "SentryPropagator"]; | ||
| if (core.hasSpansEnabled()) { | ||
| const hasSentryTracerProvider = setup.includes("SentryTracerProvider"); | ||
| if (core.hasSpansEnabled() && !hasSentryTracerProvider) { | ||
| required.push("SentrySpanProcessor"); | ||
@@ -118,3 +118,3 @@ } | ||
| } | ||
| if (!setup.includes("SentrySampler")) { | ||
| if (!hasSentryTracerProvider && !setup.includes("SentrySampler")) { | ||
| core.debug.warn( | ||
@@ -121,0 +121,0 @@ "You have to set up the SentrySampler. Without this, the OpenTelemetry & Sentry integration may still work, but sample rates set for the Sentry SDK will not be respected. If you use a custom sampler, make sure to use `wrapSamplingDecision`." |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sources":["../../../src/sdk/index.ts"],"sourcesContent":["import type { Integration, Options } from '@sentry/core';\nimport {\n applySdkMetadata,\n consoleSandbox,\n conversationIdIntegration,\n debug,\n envToBool,\n functionToStringIntegration,\n getCurrentScope,\n getIntegrationsToSetup,\n hasSpansEnabled,\n inboundFiltersIntegration,\n linkedErrorsIntegration,\n propagationContextFromHeaders,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport {\n enhanceDscWithOpenTelemetryRootSpanName,\n openTelemetrySetupCheck,\n setOpenTelemetryContextAsyncContextStrategy,\n setupEventContextTrace,\n} from '@sentry/opentelemetry';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { childProcessIntegration } from '../integrations/childProcess';\nimport { nodeContextIntegration } from '../integrations/context';\nimport { contextLinesIntegration } from '../integrations/contextlines';\nimport { httpIntegration } from '../integrations/http';\nimport { localVariablesIntegration } from '../integrations/local-variables';\nimport { modulesIntegration } from '../integrations/modules';\nimport { nativeNodeFetchIntegration } from '../integrations/node-fetch';\nimport { onUncaughtExceptionIntegration } from '../integrations/onuncaughtexception';\nimport { onUnhandledRejectionIntegration } from '../integrations/onunhandledrejection';\nimport { processSessionIntegration } from '../integrations/processSession';\nimport { INTEGRATION_NAME as SPOTLIGHT_INTEGRATION_NAME, spotlightIntegration } from '../integrations/spotlight';\nimport { consoleIntegration } from '../integrations/console';\nimport { systemErrorIntegration } from '../integrations/systemError';\nimport { makeNodeTransport } from '../transports';\nimport type { NodeClientOptions, NodeOptions } from '../types';\nimport { isCjs } from '../utils/detection';\nimport { getSpotlightConfig } from '../utils/spotlight';\nimport { defaultStackParser, getSentryRelease } from './api';\nimport { NodeClient } from './client';\nimport { initializeEsmLoader } from './esmLoader';\n\n/**\n * Get default integrations for the Node-Core SDK.\n */\nexport function getDefaultIntegrations(): Integration[] {\n return [\n // Common\n // TODO(v11): Replace with `eventFiltersIntegration` once we remove the deprecated `inboundFiltersIntegration`\n // eslint-disable-next-line typescript/no-deprecated\n inboundFiltersIntegration(),\n functionToStringIntegration(),\n linkedErrorsIntegration(),\n requestDataIntegration(),\n systemErrorIntegration(),\n conversationIdIntegration(),\n // Native Wrappers\n consoleIntegration(),\n httpIntegration(),\n nativeNodeFetchIntegration(),\n // Global Handlers\n onUncaughtExceptionIntegration(),\n onUnhandledRejectionIntegration(),\n // Event Info\n contextLinesIntegration(),\n localVariablesIntegration(),\n nodeContextIntegration(),\n childProcessIntegration(),\n processSessionIntegration(),\n modulesIntegration(),\n ];\n}\n\n/**\n * Initialize Sentry for Node.\n */\nexport function init(options: NodeOptions | undefined = {}): NodeClient | undefined {\n return _init(options, getDefaultIntegrations);\n}\n\n/**\n * Initialize Sentry for Node, without any integrations added by default.\n */\nexport function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): NodeClient {\n return _init(options, () => []);\n}\n\n/**\n * Initialize Sentry for Node, without performance instrumentation.\n */\nfunction _init(\n _options: NodeOptions | undefined = {},\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClient {\n const options = getClientOptions(_options, getDefaultIntegrationsImpl);\n\n if (options.debug === true) {\n if (DEBUG_BUILD) {\n debug.enable();\n } else {\n // use `console.warn` rather than `debug.warn` since by non-debug bundles have all `debug.x` statements stripped\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.');\n });\n }\n }\n\n if (options.registerEsmLoaderHooks !== false) {\n initializeEsmLoader();\n }\n\n setOpenTelemetryContextAsyncContextStrategy(options);\n\n const scope = getCurrentScope();\n scope.update(options.initialScope);\n\n if (options.spotlight && !options.integrations.some(({ name }) => name === SPOTLIGHT_INTEGRATION_NAME)) {\n options.integrations.push(\n spotlightIntegration({\n sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined,\n }),\n );\n }\n\n applySdkMetadata(options, 'node-core');\n\n const client = new NodeClient(options);\n // The client is on the current scope, from where it generally is inherited\n getCurrentScope().setClient(client);\n\n client.init();\n\n debug.log(`SDK initialized from ${isCjs() ? 'CommonJS' : 'ESM'}`);\n\n client.startClientReportTracking();\n\n updateScopeFromEnvVariables();\n\n enhanceDscWithOpenTelemetryRootSpanName(client);\n setupEventContextTrace(client);\n\n // Ensure we flush events when vercel functions are ended\n // See: https://vercel.com/docs/functions/functions-api-reference#sigterm-signal\n if (process.env.VERCEL) {\n process.on('SIGTERM', async () => {\n // We have 500ms for processing here, so we try to make sure to have enough time to send the events\n await client.flush(200);\n });\n }\n\n return client;\n}\n\n/**\n * Validate that your OpenTelemetry setup is correct.\n */\nexport function validateOpenTelemetrySetup(): void {\n if (!DEBUG_BUILD) {\n return;\n }\n\n const setup = openTelemetrySetupCheck();\n\n const required: ReturnType<typeof openTelemetrySetupCheck> = ['SentryContextManager', 'SentryPropagator'];\n\n if (hasSpansEnabled()) {\n required.push('SentrySpanProcessor');\n }\n\n for (const k of required) {\n if (!setup.includes(k)) {\n debug.error(\n `You have to set up the ${k}. Without this, the OpenTelemetry & Sentry integration will not work properly.`,\n );\n }\n }\n\n if (!setup.includes('SentrySampler')) {\n debug.warn(\n 'You have to set up the SentrySampler. Without this, the OpenTelemetry & Sentry integration may still work, but sample rates set for the Sentry SDK will not be respected. If you use a custom sampler, make sure to use `wrapSamplingDecision`.',\n );\n }\n}\n\nfunction getClientOptions(\n options: NodeOptions,\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClientOptions {\n const release = getRelease(options.release);\n\n const spotlight = getSpotlightConfig(options.spotlight);\n\n const tracesSampleRate = getTracesSampleRate(options.tracesSampleRate);\n\n const mergedOptions = {\n ...options,\n dsn: options.dsn ?? process.env.SENTRY_DSN,\n environment: options.environment ?? process.env.SENTRY_ENVIRONMENT,\n sendClientReports: options.sendClientReports ?? true,\n transport: options.transport ?? makeNodeTransport,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n release,\n tracesSampleRate,\n spotlight,\n debug: envToBool(options.debug ?? process.env.SENTRY_DEBUG),\n };\n\n const integrations = options.integrations;\n const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(mergedOptions);\n\n const resolvedIntegrations = getIntegrationsToSetup({\n defaultIntegrations,\n integrations,\n });\n\n return {\n ...mergedOptions,\n integrations: resolvedIntegrations,\n };\n}\n\nfunction getRelease(release: NodeOptions['release']): string | undefined {\n if (release !== undefined) {\n return release;\n }\n\n const detectedRelease = getSentryRelease();\n if (detectedRelease !== undefined) {\n return detectedRelease;\n }\n\n return undefined;\n}\n\nfunction getTracesSampleRate(tracesSampleRate: NodeOptions['tracesSampleRate']): number | undefined {\n if (tracesSampleRate !== undefined) {\n return tracesSampleRate;\n }\n\n const sampleRateFromEnv = process.env.SENTRY_TRACES_SAMPLE_RATE;\n if (!sampleRateFromEnv) {\n return undefined;\n }\n\n const parsed = parseFloat(sampleRateFromEnv);\n return isFinite(parsed) ? parsed : undefined;\n}\n\n/**\n * Update scope and propagation context based on environmental variables.\n *\n * See https://github.com/getsentry/rfcs/blob/main/text/0071-continue-trace-over-process-boundaries.md\n * for more details.\n */\nfunction updateScopeFromEnvVariables(): void {\n if (envToBool(process.env.SENTRY_USE_ENVIRONMENT) !== false) {\n const sentryTraceEnv = process.env.SENTRY_TRACE;\n const baggageEnv = process.env.SENTRY_BAGGAGE;\n const propagationContext = propagationContextFromHeaders(sentryTraceEnv, baggageEnv);\n getCurrentScope().setPropagationContext(propagationContext);\n }\n}\n"],"names":["inboundFiltersIntegration","functionToStringIntegration","linkedErrorsIntegration","requestDataIntegration","systemErrorIntegration","conversationIdIntegration","consoleIntegration","httpIntegration","nativeNodeFetchIntegration","onUncaughtExceptionIntegration","onUnhandledRejectionIntegration","contextLinesIntegration","localVariablesIntegration","nodeContextIntegration","childProcessIntegration","processSessionIntegration","modulesIntegration","DEBUG_BUILD","debug","consoleSandbox","initializeEsmLoader","setOpenTelemetryContextAsyncContextStrategy","getCurrentScope","SPOTLIGHT_INTEGRATION_NAME","spotlightIntegration","applySdkMetadata","client","NodeClient","enhanceDscWithOpenTelemetryRootSpanName","setupEventContextTrace","openTelemetrySetupCheck","hasSpansEnabled","getSpotlightConfig","makeNodeTransport","stackParserFromStackParserOptions","defaultStackParser","envToBool","getIntegrationsToSetup","getSentryRelease","propagationContextFromHeaders"],"mappings":"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"} | ||
| {"version":3,"file":"index.js","sources":["../../../src/sdk/index.ts"],"sourcesContent":["import type { Integration, Options } from '@sentry/core';\nimport {\n applySdkMetadata,\n consoleSandbox,\n conversationIdIntegration,\n debug,\n envToBool,\n functionToStringIntegration,\n getCurrentScope,\n getIntegrationsToSetup,\n hasSpansEnabled,\n inboundFiltersIntegration,\n linkedErrorsIntegration,\n propagationContextFromHeaders,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport {\n enhanceDscWithOpenTelemetryRootSpanName,\n openTelemetrySetupCheck,\n setOpenTelemetryContextAsyncContextStrategy,\n setupEventContextTrace,\n} from '@sentry/opentelemetry';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { childProcessIntegration } from '../integrations/childProcess';\nimport { nodeContextIntegration } from '../integrations/context';\nimport { contextLinesIntegration } from '../integrations/contextlines';\nimport { httpIntegration } from '../integrations/http';\nimport { localVariablesIntegration } from '../integrations/local-variables';\nimport { modulesIntegration } from '../integrations/modules';\nimport { nativeNodeFetchIntegration } from '../integrations/node-fetch';\nimport { onUncaughtExceptionIntegration } from '../integrations/onuncaughtexception';\nimport { onUnhandledRejectionIntegration } from '../integrations/onunhandledrejection';\nimport { processSessionIntegration } from '../integrations/processSession';\nimport { INTEGRATION_NAME as SPOTLIGHT_INTEGRATION_NAME, spotlightIntegration } from '../integrations/spotlight';\nimport { consoleIntegration } from '../integrations/console';\nimport { systemErrorIntegration } from '../integrations/systemError';\nimport { makeNodeTransport } from '../transports';\nimport type { NodeClientOptions, NodeOptions } from '../types';\nimport { getSpotlightConfig } from '../utils/spotlight';\nimport { defaultStackParser, getSentryRelease } from './api';\nimport { NodeClient } from './client';\nimport { initializeEsmLoader } from './esmLoader';\n\n/**\n * Get default integrations for the Node-Core SDK.\n */\nexport function getDefaultIntegrations(): Integration[] {\n return [\n // Common\n // TODO(v11): Replace with `eventFiltersIntegration` once we remove the deprecated `inboundFiltersIntegration`\n // eslint-disable-next-line typescript/no-deprecated\n inboundFiltersIntegration(),\n functionToStringIntegration(),\n linkedErrorsIntegration(),\n requestDataIntegration(),\n systemErrorIntegration(),\n conversationIdIntegration(),\n // Native Wrappers\n consoleIntegration(),\n httpIntegration(),\n nativeNodeFetchIntegration(),\n // Global Handlers\n onUncaughtExceptionIntegration(),\n onUnhandledRejectionIntegration(),\n // Event Info\n contextLinesIntegration(),\n localVariablesIntegration(),\n nodeContextIntegration(),\n childProcessIntegration(),\n processSessionIntegration(),\n modulesIntegration(),\n ];\n}\n\n/**\n * Initialize Sentry for Node.\n */\nexport function init(options: NodeOptions | undefined = {}): NodeClient | undefined {\n return _init(options, getDefaultIntegrations);\n}\n\n/**\n * Initialize Sentry for Node, without any integrations added by default.\n */\nexport function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): NodeClient {\n return _init(options, () => []);\n}\n\n/**\n * Initialize Sentry for Node, without performance instrumentation.\n */\nfunction _init(\n _options: NodeOptions | undefined = {},\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClient {\n const options = getClientOptions(_options, getDefaultIntegrationsImpl);\n\n if (options.debug === true) {\n if (DEBUG_BUILD) {\n debug.enable();\n } else {\n // use `console.warn` rather than `debug.warn` since by non-debug bundles have all `debug.x` statements stripped\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.');\n });\n }\n }\n\n if (options.registerEsmLoaderHooks !== false) {\n initializeEsmLoader();\n }\n\n setOpenTelemetryContextAsyncContextStrategy(options);\n\n const scope = getCurrentScope();\n scope.update(options.initialScope);\n\n if (options.spotlight && !options.integrations.some(({ name }) => name === SPOTLIGHT_INTEGRATION_NAME)) {\n options.integrations.push(\n spotlightIntegration({\n sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined,\n }),\n );\n }\n\n applySdkMetadata(options, 'node-core');\n\n const client = new NodeClient(options);\n // The client is on the current scope, from where it generally is inherited\n getCurrentScope().setClient(client);\n\n client.init();\n\n /*! rollup-include-cjs-only */\n debug.log(`SDK initialized from CommonJS`);\n /*! rollup-include-cjs-only-end */\n /*! rollup-include-esm-only */\n debug.log(`SDK initialized from ESM`);\n /*! rollup-include-esm-only-end */\n\n client.startClientReportTracking();\n\n updateScopeFromEnvVariables();\n\n enhanceDscWithOpenTelemetryRootSpanName(client);\n setupEventContextTrace(client);\n\n // Ensure we flush events when vercel functions are ended\n // See: https://vercel.com/docs/functions/functions-api-reference#sigterm-signal\n if (process.env.VERCEL) {\n process.on('SIGTERM', async () => {\n // We have 500ms for processing here, so we try to make sure to have enough time to send the events\n await client.flush(200);\n });\n }\n\n return client;\n}\n\n/**\n * Validate that your OpenTelemetry setup is correct.\n */\nexport function validateOpenTelemetrySetup(): void {\n if (!DEBUG_BUILD) {\n return;\n }\n\n const setup = openTelemetrySetupCheck();\n\n const required: ReturnType<typeof openTelemetrySetupCheck> = ['SentryContextManager', 'SentryPropagator'];\n\n const hasSentryTracerProvider = setup.includes('SentryTracerProvider');\n\n if (hasSpansEnabled() && !hasSentryTracerProvider) {\n required.push('SentrySpanProcessor');\n }\n\n for (const k of required) {\n if (!setup.includes(k)) {\n debug.error(\n `You have to set up the ${k}. Without this, the OpenTelemetry & Sentry integration will not work properly.`,\n );\n }\n }\n\n if (!hasSentryTracerProvider && !setup.includes('SentrySampler')) {\n debug.warn(\n 'You have to set up the SentrySampler. Without this, the OpenTelemetry & Sentry integration may still work, but sample rates set for the Sentry SDK will not be respected. If you use a custom sampler, make sure to use `wrapSamplingDecision`.',\n );\n }\n}\n\nfunction getClientOptions(\n options: NodeOptions,\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClientOptions {\n const release = getRelease(options.release);\n\n const spotlight = getSpotlightConfig(options.spotlight);\n\n const tracesSampleRate = getTracesSampleRate(options.tracesSampleRate);\n\n const mergedOptions = {\n ...options,\n dsn: options.dsn ?? process.env.SENTRY_DSN,\n environment: options.environment ?? process.env.SENTRY_ENVIRONMENT,\n sendClientReports: options.sendClientReports ?? true,\n transport: options.transport ?? makeNodeTransport,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n release,\n tracesSampleRate,\n spotlight,\n debug: envToBool(options.debug ?? process.env.SENTRY_DEBUG),\n };\n\n const integrations = options.integrations;\n const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(mergedOptions);\n\n const resolvedIntegrations = getIntegrationsToSetup({\n defaultIntegrations,\n integrations,\n });\n\n return {\n ...mergedOptions,\n integrations: resolvedIntegrations,\n };\n}\n\nfunction getRelease(release: NodeOptions['release']): string | undefined {\n if (release !== undefined) {\n return release;\n }\n\n const detectedRelease = getSentryRelease();\n if (detectedRelease !== undefined) {\n return detectedRelease;\n }\n\n return undefined;\n}\n\nfunction getTracesSampleRate(tracesSampleRate: NodeOptions['tracesSampleRate']): number | undefined {\n if (tracesSampleRate !== undefined) {\n return tracesSampleRate;\n }\n\n const sampleRateFromEnv = process.env.SENTRY_TRACES_SAMPLE_RATE;\n if (!sampleRateFromEnv) {\n return undefined;\n }\n\n const parsed = parseFloat(sampleRateFromEnv);\n return isFinite(parsed) ? parsed : undefined;\n}\n\n/**\n * Update scope and propagation context based on environmental variables.\n *\n * See https://github.com/getsentry/rfcs/blob/main/text/0071-continue-trace-over-process-boundaries.md\n * for more details.\n */\nfunction updateScopeFromEnvVariables(): void {\n if (envToBool(process.env.SENTRY_USE_ENVIRONMENT) !== false) {\n const sentryTraceEnv = process.env.SENTRY_TRACE;\n const baggageEnv = process.env.SENTRY_BAGGAGE;\n const propagationContext = propagationContextFromHeaders(sentryTraceEnv, baggageEnv);\n getCurrentScope().setPropagationContext(propagationContext);\n }\n}\n"],"names":["inboundFiltersIntegration","functionToStringIntegration","linkedErrorsIntegration","requestDataIntegration","systemErrorIntegration","conversationIdIntegration","consoleIntegration","httpIntegration","nativeNodeFetchIntegration","onUncaughtExceptionIntegration","onUnhandledRejectionIntegration","contextLinesIntegration","localVariablesIntegration","nodeContextIntegration","childProcessIntegration","processSessionIntegration","modulesIntegration","DEBUG_BUILD","debug","consoleSandbox","initializeEsmLoader","setOpenTelemetryContextAsyncContextStrategy","getCurrentScope","SPOTLIGHT_INTEGRATION_NAME","spotlightIntegration","applySdkMetadata","client","NodeClient","enhanceDscWithOpenTelemetryRootSpanName","setupEventContextTrace","openTelemetrySetupCheck","hasSpansEnabled","getSpotlightConfig","makeNodeTransport","stackParserFromStackParserOptions","defaultStackParser","envToBool","getIntegrationsToSetup","getSentryRelease","propagationContextFromHeaders"],"mappings":"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"} |
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const detection = require('./detection.js'); | ||
| const createMissingInstrumentationContext = (pkg) => { | ||
| let isCjs; | ||
| isCjs = true; | ||
| return { | ||
| package: pkg, | ||
| "javascript.is_cjs": isCjs | ||
| }; | ||
| }; | ||
| const createMissingInstrumentationContext = (pkg) => ({ | ||
| package: pkg, | ||
| "javascript.is_cjs": detection.isCjs() | ||
| }); | ||
| exports.createMissingInstrumentationContext = createMissingInstrumentationContext; | ||
| //# sourceMappingURL=createMissingInstrumentationContext.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"createMissingInstrumentationContext.js","sources":["../../../src/utils/createMissingInstrumentationContext.ts"],"sourcesContent":["import type { MissingInstrumentationContext } from '@sentry/core';\nimport { isCjs } from './detection';\n\nexport const createMissingInstrumentationContext = (pkg: string): MissingInstrumentationContext => ({\n package: pkg,\n 'javascript.is_cjs': isCjs(),\n});\n"],"names":["isCjs"],"mappings":";;;;AAGO,MAAM,mCAAA,GAAsC,CAAC,GAAA,MAAgD;AAAA,EAClG,OAAA,EAAS,GAAA;AAAA,EACT,qBAAqBA,eAAA;AACvB,CAAA;;;;"} | ||
| {"version":3,"file":"createMissingInstrumentationContext.js","sources":["../../../src/utils/createMissingInstrumentationContext.ts"],"sourcesContent":["import type { MissingInstrumentationContext } from '@sentry/core';\n\nexport const createMissingInstrumentationContext = (pkg: string): MissingInstrumentationContext => {\n let isCjs: boolean;\n /*! rollup-include-cjs-only */\n isCjs = true;\n /*! rollup-include-cjs-only-end */\n /*! rollup-include-esm-only */\n isCjs = false;\n /*! rollup-include-esm-only-end */\n\n return {\n package: pkg,\n 'javascript.is_cjs': isCjs,\n };\n};\n"],"names":[],"mappings":";;AAEO,MAAM,mCAAA,GAAsC,CAAC,GAAA,KAA+C;AACjG,EAAA,IAAI,KAAA;AAAA,EACJ,KAAA,GAAA,IAAA;AACA,EAAA,OAAA;AAAQ,IACR,OAAA,EAAA,GAAA;AAAA,IACA,mBAAA,EAAA;AACA,GAAA;AAAQ;;;;"} |
@@ -6,5 +6,2 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| function isCjs() { | ||
| return true; | ||
| } | ||
| function supportsEsmLoaderHooks() { | ||
@@ -16,4 +13,3 @@ { | ||
| exports.isCjs = isCjs; | ||
| exports.supportsEsmLoaderHooks = supportsEsmLoaderHooks; | ||
| //# sourceMappingURL=detection.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"detection.js","sources":["../../../src/utils/detection.ts"],"sourcesContent":["import { consoleSandbox } from '@sentry/core';\nimport { NODE_MAJOR, NODE_MINOR } from '../nodeVersion';\n\n/** Detect CommonJS. */\nexport function isCjs(): boolean {\n /*! rollup-include-cjs-only */\n return true;\n /*! rollup-include-cjs-only-end */\n\n /*! rollup-include-esm-only */\n return false;\n /*! rollup-include-esm-only-end */\n}\n\nlet hasWarnedAboutNodeVersion: boolean | undefined;\n\n/**\n * Check if the current Node.js version supports module.register\n */\nexport function supportsEsmLoaderHooks(): boolean {\n if (isCjs()) {\n return false;\n }\n\n if (NODE_MAJOR >= 21 || (NODE_MAJOR === 20 && NODE_MINOR >= 6) || (NODE_MAJOR === 18 && NODE_MINOR >= 19)) {\n return true;\n }\n\n if (!hasWarnedAboutNodeVersion) {\n hasWarnedAboutNodeVersion = true;\n\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] You are using Node.js v${process.versions.node} in ESM mode (\"import syntax\"). The Sentry Node.js SDK is not compatible with ESM in Node.js versions before 18.19.0 or before 20.6.0. Please either build your application with CommonJS (\"require() syntax\"), or upgrade your Node.js version.`,\n );\n });\n }\n\n return false;\n}\n"],"names":[],"mappings":";;;;;AAIO,SAAS,KAAA,GAAiB;AAAA,EAC/B,OAAA,IAAA;AACA,EAAA;AAGA,SAAA,sBAAA,GAAA;AACA,EAAO;AAAA,IACP,OAAA,KAAA;AACF,EAAA;AAqBc;;;;;"} | ||
| {"version":3,"file":"detection.js","sources":["../../../src/utils/detection.ts"],"sourcesContent":["import { consoleSandbox } from '@sentry/core';\nimport { NODE_MAJOR, NODE_MINOR } from '../nodeVersion';\n\nfunction isCjs(): boolean {\n /*! rollup-include-cjs-only */\n return true;\n /*! rollup-include-cjs-only-end */\n\n /*! rollup-include-esm-only */\n return false;\n /*! rollup-include-esm-only-end */\n}\n\nlet hasWarnedAboutNodeVersion: boolean | undefined;\n\n/**\n * Check if the current Node.js version supports module.register\n */\nexport function supportsEsmLoaderHooks(): boolean {\n if (isCjs()) {\n return false;\n }\n\n if (NODE_MAJOR >= 21 || (NODE_MAJOR === 20 && NODE_MINOR >= 6) || (NODE_MAJOR === 18 && NODE_MINOR >= 19)) {\n return true;\n }\n\n if (!hasWarnedAboutNodeVersion) {\n hasWarnedAboutNodeVersion = true;\n\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] You are using Node.js v${process.versions.node} in ESM mode (\"import syntax\"). The Sentry Node.js SDK is not compatible with ESM in Node.js versions before 18.19.0 or before 20.6.0. Please either build your application with CommonJS (\"require() syntax\"), or upgrade your Node.js version.`,\n );\n });\n }\n\n return false;\n}\n"],"names":[],"mappings":";;;;;AAQE,SAAA,sBAAA,GAAA;AACA,EAAO;AAAA,IACP,OAAA,KAAA;AACF,EAAA;AAqBc;;;;"} |
@@ -6,3 +6,2 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const createMissingInstrumentationContext = require('./createMissingInstrumentationContext.js'); | ||
| require('../nodeVersion.js'); | ||
@@ -13,8 +12,6 @@ function ensureIsWrapped(maybeWrappedFunction, name) { | ||
| core.consoleSandbox(() => { | ||
| { | ||
| console.warn( | ||
| `[Sentry] ${name} is not instrumented. This is likely because you required/imported ${name} before calling \`Sentry.init()\`.` | ||
| ); | ||
| } | ||
| }); | ||
| console.warn( | ||
| `[Sentry] ${name} is not instrumented. This is likely because you required/imported ${name} before calling \`Sentry.init()\`.` | ||
| ); | ||
| }); | ||
| core.getGlobalScope().setContext("missing_instrumentation", createMissingInstrumentationContext.createMissingInstrumentationContext(name)); | ||
@@ -21,0 +18,0 @@ } |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"ensureIsWrapped.js","sources":["../../../src/utils/ensureIsWrapped.ts"],"sourcesContent":["import { isWrapped } from '@opentelemetry/instrumentation';\nimport {\n consoleSandbox,\n getClient,\n getOriginalFunction,\n getGlobalScope,\n hasSpansEnabled,\n isEnabled,\n type WrappedFunction,\n} from '@sentry/core';\nimport type { NodeClient } from '../sdk/client';\nimport { createMissingInstrumentationContext } from './createMissingInstrumentationContext';\nimport { isCjs } from './detection';\n\n/**\n * Checks and warns if a framework isn't wrapped by opentelemetry.\n */\nexport function ensureIsWrapped(\n maybeWrappedFunction: unknown,\n name: 'express' | 'connect' | 'fastify' | 'hapi' | 'koa' | 'hono',\n): void {\n const clientOptions = getClient<NodeClient>()?.getOptions();\n if (\n !clientOptions?.disableInstrumentationWarnings &&\n !(\n isWrapped(maybeWrappedFunction) ||\n typeof getOriginalFunction(maybeWrappedFunction as WrappedFunction) === 'function'\n ) &&\n isEnabled() &&\n hasSpansEnabled(clientOptions)\n ) {\n consoleSandbox(() => {\n if (isCjs()) {\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] ${name} is not instrumented. This is likely because you required/imported ${name} before calling \\`Sentry.init()\\`.`,\n );\n } else {\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] ${name} is not instrumented. Please make sure to initialize Sentry in a separate file that you \\`--import\\` when running node, see: https://docs.sentry.io/platforms/javascript/guides/${name}/install/esm/.`,\n );\n }\n });\n\n getGlobalScope().setContext('missing_instrumentation', createMissingInstrumentationContext(name));\n }\n}\n"],"names":["getClient","isWrapped","getOriginalFunction","isEnabled","hasSpansEnabled","consoleSandbox","getGlobalScope","createMissingInstrumentationContext"],"mappings":";;;;;;;AAiBO,SAAS,eAAA,CACd,sBACA,IAAA,EACM;AACN,EAAA,MAAM,aAAA,GAAgBA,cAAA,EAAsB,EAAG,UAAA,EAAW;AAC1D,EAAA,IACE,CAAC,aAAA,EAAe,8BAAA,IAChB,EACEC,yBAAA,CAAU,oBAAoB,CAAA,IAC9B,OAAOC,wBAAA,CAAoB,oBAAuC,MAAM,UAAA,CAAA,IAE1EC,cAAA,EAAU,IACVC,oBAAA,CAAgB,aAAa,CAAA,EAC7B;AACA,IAAAC,mBAAA,CAAe,MAAM;AACnB,MAAa;AAEX,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN,CAAA,SAAA,EAAY,IAAI,CAAA,mEAAA,EAAsE,IAAI,CAAA,kCAAA;AAAA,SAC5F;AAAA,MACF;AAKA,IACF,CAAC,CAAA;AAED,IAAAC,mBAAA,EAAe,CAAE,UAAA,CAAW,yBAAA,EAA2BC,uEAAA,CAAoC,IAAI,CAAC,CAAA;AAAA,EAClG;AACF;;;;"} | ||
| {"version":3,"file":"ensureIsWrapped.js","sources":["../../../src/utils/ensureIsWrapped.ts"],"sourcesContent":["import { isWrapped } from '@opentelemetry/instrumentation';\nimport {\n consoleSandbox,\n getClient,\n getOriginalFunction,\n getGlobalScope,\n hasSpansEnabled,\n isEnabled,\n type WrappedFunction,\n} from '@sentry/core';\nimport type { NodeClient } from '../sdk/client';\nimport { createMissingInstrumentationContext } from './createMissingInstrumentationContext';\n\n/**\n * Checks and warns if a framework isn't wrapped by opentelemetry.\n */\nexport function ensureIsWrapped(\n maybeWrappedFunction: unknown,\n name: 'express' | 'connect' | 'fastify' | 'hapi' | 'koa' | 'hono',\n): void {\n const clientOptions = getClient<NodeClient>()?.getOptions();\n if (\n !clientOptions?.disableInstrumentationWarnings &&\n !(\n isWrapped(maybeWrappedFunction) ||\n typeof getOriginalFunction(maybeWrappedFunction as WrappedFunction) === 'function'\n ) &&\n isEnabled() &&\n hasSpansEnabled(clientOptions)\n ) {\n consoleSandbox(() => {\n /*! rollup-include-cjs-only */\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] ${name} is not instrumented. This is likely because you required/imported ${name} before calling \\`Sentry.init()\\`.`,\n );\n /*! rollup-include-cjs-only-end */\n\n /*! rollup-include-esm-only */\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] ${name} is not instrumented. Please make sure to initialize Sentry in a separate file that you \\`--import\\` when running node, see: https://docs.sentry.io/platforms/javascript/guides/${name}/install/esm/.`,\n );\n /*! rollup-include-esm-only-end */\n });\n\n getGlobalScope().setContext('missing_instrumentation', createMissingInstrumentationContext(name));\n }\n}\n"],"names":["getClient","isWrapped","getOriginalFunction","isEnabled","hasSpansEnabled","consoleSandbox","getGlobalScope","createMissingInstrumentationContext"],"mappings":";;;;;;AAgBO,SAAS,eAAA,CACd,sBACA,IAAA,EACM;AACN,EAAA,MAAM,aAAA,GAAgBA,cAAA,EAAsB,EAAG,UAAA,EAAW;AAC1D,EAAA,IACE,CAAC,aAAA,EAAe,8BAAA,IAChB,EACEC,yBAAA,CAAU,oBAAoB,CAAA,IAC9B,OAAOC,wBAAA,CAAoB,oBAAuC,MAAM,UAAA,CAAA,IAE1EC,cAAA,EAAU,IACVC,oBAAA,CAAgB,aAAa,CAAA,EAC7B;AACA,IAAAC,mBAAA,CAAe,MAAM;AAAA,MACnB,OAAA,CAAA,IAAA;AAEA,QAAA,CAAA,SAAQ,EAAA,IAAA,CAAA,mEAAA,EAAA,IAAA,CAAA,kCAAA;AAAA,OAAA;AACoF,MAC5F,CAAA,CAAA;AAAA,IAAAC,mBACA,EAAA,CAAA,UAAA,CAAA,yBAAA,EAAAC,uEAAA,CAAA,IAAA,CAAA,CAAA;AAAA,EAAA;AAIA;;;;"} |
@@ -8,6 +8,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const W3C_TRACEPARENT_HEADER = "traceparent"; | ||
| function addTracePropagationHeadersToFetchRequest(request, propagationDecisionMap) { | ||
| function addTracePropagationHeadersToFetchRequest(request, propagationDecisionMap, span) { | ||
| const url = getAbsoluteUrl(request.origin, request.path); | ||
| const { tracePropagationTargets, propagateTraceparent } = core.getClient()?.getOptions() || {}; | ||
| const addedHeaders = core.shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap) ? core.getTraceData({ propagateTraceparent }) : void 0; | ||
| if (!core.shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)) { | ||
| return; | ||
| } | ||
| const addedHeaders = span ? core.withActiveSpan(span, () => core.getTraceData({ propagateTraceparent })) : core.getTraceData({ propagateTraceparent }); | ||
| if (!addedHeaders) { | ||
@@ -14,0 +17,0 @@ return; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"outgoingFetchRequest.js","sources":["../../../src/utils/outgoingFetchRequest.ts"],"sourcesContent":["import type { LRUMap, SanitizedRequestData } from '@sentry/core';\nimport {\n addBreadcrumb,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getSanitizedUrlString,\n getTraceData,\n parseUrl,\n shouldPropagateTraceForUrl,\n mergeBaggageHeaders,\n} from '@sentry/core';\nimport type { UndiciRequest, UndiciResponse } from '../integrations/node-fetch/types';\nimport { debug } from '@sentry/core';\nconst SENTRY_TRACE_HEADER = 'sentry-trace';\nconst SENTRY_BAGGAGE_HEADER = 'baggage';\nconst W3C_TRACEPARENT_HEADER = 'traceparent';\n/**\n * Add trace propagation headers to an outgoing fetch/undici request.\n *\n * Checks if the request URL matches trace propagation targets,\n * then injects sentry-trace, traceparent, and baggage headers.\n */\n// eslint-disable-next-line complexity\nexport function addTracePropagationHeadersToFetchRequest(\n request: UndiciRequest,\n propagationDecisionMap: LRUMap<string, boolean>,\n): void {\n const url = getAbsoluteUrl(request.origin, request.path);\n\n // Manually add the trace headers, if it applies\n // Note: We do not use `propagation.inject()` here, because our propagator relies on an active span\n // Which we do not have in this case\n // The propagator _may_ overwrite this, but this should be fine as it is the same data\n const { tracePropagationTargets, propagateTraceparent } = getClient()?.getOptions() || {};\n const addedHeaders = shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)\n ? getTraceData({ propagateTraceparent })\n : undefined;\n\n if (!addedHeaders) {\n return;\n }\n\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = addedHeaders;\n\n // Undici can expose headers either as a raw string (v5-style) or as a flat array of pairs (v6-style).\n // In the array form, even indices are header names and odd indices are values; in undici v6 a value\n // may be `string | string[]` when a header has multiple values. The helpers below (_deduplicateArrayHeader,\n // push, etc.) expect each value slot to be a single string, so we normalize array headers first.\n const requestHeaders: string[] = Array.isArray(request.headers)\n ? normalizeUndiciHeaderPairs(request.headers)\n : stringToArrayHeaders(request.headers);\n\n // OTel's UndiciInstrumentation calls propagation.inject() which unconditionally\n // appends headers to the request. When the user also sets headers via getTraceData(),\n // this results in duplicate sentry-trace and baggage (and optionally traceparent) entries.\n // We clean these up before applying our own logic.\n _deduplicateArrayHeader(requestHeaders, SENTRY_TRACE_HEADER);\n _deduplicateArrayHeader(requestHeaders, SENTRY_BAGGAGE_HEADER);\n if (propagateTraceparent) {\n _deduplicateArrayHeader(requestHeaders, W3C_TRACEPARENT_HEADER);\n }\n\n // We do not want to overwrite existing headers here\n // If the core UndiciInstrumentation is registered, it will already have set the headers\n // We do not want to add any then\n const hasExistingSentryTraceHeader = _findExistingHeaderIndex(requestHeaders, SENTRY_TRACE_HEADER) !== -1;\n\n // We do not want to set any headers if we already have an existing sentry-trace header.\n // sentry-trace is still the source of truth, otherwise we risk mixing up baggage and sentry-trace values.\n if (!hasExistingSentryTraceHeader) {\n if (sentryTrace) {\n requestHeaders.push(SENTRY_TRACE_HEADER, sentryTrace);\n }\n\n if (traceparent && _findExistingHeaderIndex(requestHeaders, 'traceparent') === -1) {\n requestHeaders.push('traceparent', traceparent);\n }\n\n // For baggage, we make sure to merge this into a possibly existing header\n const existingBaggageIndex = _findExistingHeaderIndex(requestHeaders, SENTRY_BAGGAGE_HEADER);\n if (baggage && existingBaggageIndex === -1) {\n requestHeaders.push(SENTRY_BAGGAGE_HEADER, baggage);\n } else if (baggage) {\n // headers in format [key_0, value_0, key_1, value_1, ...], hence the +1 here\n const existingBaggageValue = requestHeaders[existingBaggageIndex + 1];\n const merged = mergeBaggageHeaders(existingBaggageValue, baggage);\n if (merged) {\n requestHeaders[existingBaggageIndex + 1] = merged;\n }\n }\n }\n\n if (Array.isArray(request.headers)) {\n // Replace contents in place so we keep the same array reference undici/fetch still holds.\n // `requestHeaders` is already normalized (string pairs only); splice writes them back.\n request.headers.splice(0, request.headers.length, ...requestHeaders);\n } else {\n request.headers = arrayToStringHeaders(requestHeaders);\n }\n}\n\n/**\n * Convert undici’s header array into `[name, value, name, value, ...]` where every value is a string.\n *\n * Undici v6 uses this shape: `[k1, v1, k2, v2, ...]`. Types allow each `v` to be `string | string[]` when\n * that header has multiple values. Sentry’s dedupe/merge helpers expect one string per value slot, so\n * multi-value arrays are joined with `', '`. Missing value slots become `''`.\n */\nfunction normalizeUndiciHeaderPairs(headers: (string | string[])[]): string[] {\n const out: string[] = [];\n for (let i = 0; i < headers.length; i++) {\n const entry = headers[i];\n if (i % 2 === 0) {\n // Header name (should always be a string; coerce defensively).\n out.push(typeof entry === 'string' ? entry : String(entry));\n } else {\n // Header value: flatten `string[]` to a single string for downstream string-only helpers.\n out.push(Array.isArray(entry) ? entry.join(', ') : (entry ?? ''));\n }\n }\n return out;\n}\n\nfunction stringToArrayHeaders(requestHeaders: string): string[] {\n const headersArray = requestHeaders.split('\\r\\n');\n const headers: string[] = [];\n for (const header of headersArray) {\n try {\n const colonIndex = header.indexOf(':');\n if (colonIndex === -1) {\n continue;\n }\n const key = header.slice(0, colonIndex).trim();\n const value = header.slice(colonIndex + 1).trim();\n if (key) {\n headers.push(key, value);\n }\n } catch {\n debug.warn(`Failed to convert string request header to array header: ${header}`);\n }\n }\n return headers;\n}\n\nfunction arrayToStringHeaders(headers: string[]): string {\n const headerPairs: string[] = [];\n\n for (let i = 0; i < headers.length; i += 2) {\n const key = headers[i];\n const value = headers[i + 1];\n if (!key || value == null) {\n // skip falsy keys but only null/undefined values\n continue;\n }\n headerPairs.push(`${key}: ${value}`);\n }\n\n if (!headerPairs.length) {\n return '';\n }\n\n return headerPairs.join('\\r\\n').concat('\\r\\n');\n}\n\n/**\n * For a given header name, if there are multiple entries in the [key, value, key, value, ...] array,\n * keep the first entry and remove the rest.\n * For baggage, values are merged to preserve all entries but to dedupe sentry- values, and always\n * keep the first occurrence of them\n */\nfunction _deduplicateArrayHeader(headers: string[], headerName: string): void {\n let firstIndex = -1;\n for (let i = 0; i < headers.length; i += 2) {\n if (headers[i] !== headerName) {\n continue;\n }\n\n if (firstIndex === -1) {\n firstIndex = i;\n continue;\n }\n\n const firstHeaderValue = headers[firstIndex + 1];\n if (headerName === SENTRY_BAGGAGE_HEADER && firstHeaderValue) {\n // mergeBaggageHeaders always takes sentry- values from the new baggage (2nd param) and merges\n // it with the existing one (1st param). Here, we want to keep the first header's existing\n // sentry- values in favor of the new ones. Hence we swap the parameters.\n const merged = mergeBaggageHeaders(headers[i + 1], firstHeaderValue);\n if (merged) {\n headers[firstIndex + 1] = merged;\n }\n }\n headers.splice(i, 2);\n i -= 2;\n }\n}\n\n/**\n * Find the index of an existing header in an array of headers.\n * Only take even indices, because headers are in format [key_0, value_0, key_1, value_1, ...]\n * otherwise we could match a header _value_ with @param name\n */\nfunction _findExistingHeaderIndex(headers: string[], name: string): number {\n return headers.findIndex((header, i) => i % 2 === 0 && header === name);\n}\n\n/** Add a breadcrumb for an outgoing fetch/undici request. */\nexport function addFetchRequestBreadcrumb(request: UndiciRequest, response: UndiciResponse): void {\n const data = getBreadcrumbData(request);\n\n const statusCode = response.statusCode;\n const level = getBreadcrumbLogLevelFromHttpStatusCode(statusCode);\n\n addBreadcrumb(\n {\n category: 'http',\n data: {\n status_code: statusCode,\n ...data,\n },\n type: 'http',\n level,\n },\n {\n event: 'response',\n request,\n response,\n },\n );\n}\n\nfunction getBreadcrumbData(request: UndiciRequest): Partial<SanitizedRequestData> {\n try {\n const url = getAbsoluteUrl(request.origin, request.path);\n const parsedUrl = parseUrl(url);\n\n const data: Partial<SanitizedRequestData> = {\n url: getSanitizedUrlString(parsedUrl),\n 'http.method': request.method || 'GET',\n };\n\n if (parsedUrl.search) {\n data['http.query'] = parsedUrl.search;\n }\n if (parsedUrl.hash) {\n data['http.fragment'] = parsedUrl.hash;\n }\n\n return data;\n } catch {\n return {};\n }\n}\n\n/** Get the absolute URL from an origin and path. */\nexport function getAbsoluteUrl(origin: string, path: string = '/'): string {\n try {\n const url = new URL(path, origin);\n return url.toString();\n } catch {\n // fallback: Construct it on our own\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}`;\n }\n\n return `${url}${path}`;\n }\n}\n"],"names":["getClient","shouldPropagateTraceForUrl","getTraceData","mergeBaggageHeaders","debug","getBreadcrumbLogLevelFromHttpStatusCode","addBreadcrumb","parseUrl","getSanitizedUrlString"],"mappings":"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"} | ||
| {"version":3,"file":"outgoingFetchRequest.js","sources":["../../../src/utils/outgoingFetchRequest.ts"],"sourcesContent":["import type { LRUMap, SanitizedRequestData, Span } from '@sentry/core';\nimport {\n addBreadcrumb,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getSanitizedUrlString,\n getTraceData,\n parseUrl,\n shouldPropagateTraceForUrl,\n mergeBaggageHeaders,\n withActiveSpan,\n} from '@sentry/core';\nimport type { UndiciRequest, UndiciResponse } from '../integrations/node-fetch/types';\nimport { debug } from '@sentry/core';\nconst SENTRY_TRACE_HEADER = 'sentry-trace';\nconst SENTRY_BAGGAGE_HEADER = 'baggage';\nconst W3C_TRACEPARENT_HEADER = 'traceparent';\n/**\n * Add trace propagation headers to an outgoing fetch/undici request.\n *\n * Checks if the request URL matches trace propagation targets,\n * then injects sentry-trace, traceparent, and baggage headers.\n *\n * When a `span` is passed (the outgoing `http.client` span), its trace data is propagated so downstream\n * services are parented to that span. Without a span, the active scope's trace data is used.\n *\n * Existing trace headers (e.g. set manually by the user via `getTraceData()`) always take precedence and\n * are de-duplicated rather than overwritten, so we never emit two `sentry-trace`/`baggage` entries.\n */\n// eslint-disable-next-line complexity\nexport function addTracePropagationHeadersToFetchRequest(\n request: UndiciRequest,\n propagationDecisionMap: LRUMap<string, boolean>,\n span?: Span,\n): void {\n const url = getAbsoluteUrl(request.origin, request.path);\n\n // Manually add the trace headers, if it applies\n // Note: We do not use `propagation.inject()` here, because our propagator relies on an active span\n // Which we do not have in this case\n // The propagator _may_ overwrite this, but this should be fine as it is the same data\n const { tracePropagationTargets, propagateTraceparent } = getClient()?.getOptions() || {};\n\n if (!shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)) {\n return;\n }\n\n // When a span is provided, make it active so the propagated headers reference it (and not the parent\n // span). Passing `{ span }` to `getTraceData()` is not enough: for an inactive span it resolves to the\n // span's captured scope, whose active span is still the parent.\n const addedHeaders = span\n ? withActiveSpan(span, () => getTraceData({ propagateTraceparent }))\n : getTraceData({ propagateTraceparent });\n\n if (!addedHeaders) {\n return;\n }\n\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = addedHeaders;\n\n // Undici can expose headers either as a raw string (v5-style) or as a flat array of pairs (v6-style).\n // In the array form, even indices are header names and odd indices are values; in undici v6 a value\n // may be `string | string[]` when a header has multiple values. The helpers below (_deduplicateArrayHeader,\n // push, etc.) expect each value slot to be a single string, so we normalize array headers first.\n const requestHeaders: string[] = Array.isArray(request.headers)\n ? normalizeUndiciHeaderPairs(request.headers)\n : stringToArrayHeaders(request.headers);\n\n // OTel's UndiciInstrumentation calls propagation.inject() which unconditionally\n // appends headers to the request. When the user also sets headers via getTraceData(),\n // this results in duplicate sentry-trace and baggage (and optionally traceparent) entries.\n // We clean these up before applying our own logic.\n _deduplicateArrayHeader(requestHeaders, SENTRY_TRACE_HEADER);\n _deduplicateArrayHeader(requestHeaders, SENTRY_BAGGAGE_HEADER);\n if (propagateTraceparent) {\n _deduplicateArrayHeader(requestHeaders, W3C_TRACEPARENT_HEADER);\n }\n\n // We do not want to overwrite existing headers here\n // If the core UndiciInstrumentation is registered, it will already have set the headers\n // We do not want to add any then\n const hasExistingSentryTraceHeader = _findExistingHeaderIndex(requestHeaders, SENTRY_TRACE_HEADER) !== -1;\n\n // We do not want to set any headers if we already have an existing sentry-trace header.\n // sentry-trace is still the source of truth, otherwise we risk mixing up baggage and sentry-trace values.\n if (!hasExistingSentryTraceHeader) {\n if (sentryTrace) {\n requestHeaders.push(SENTRY_TRACE_HEADER, sentryTrace);\n }\n\n if (traceparent && _findExistingHeaderIndex(requestHeaders, 'traceparent') === -1) {\n requestHeaders.push('traceparent', traceparent);\n }\n\n // For baggage, we make sure to merge this into a possibly existing header\n const existingBaggageIndex = _findExistingHeaderIndex(requestHeaders, SENTRY_BAGGAGE_HEADER);\n if (baggage && existingBaggageIndex === -1) {\n requestHeaders.push(SENTRY_BAGGAGE_HEADER, baggage);\n } else if (baggage) {\n // headers in format [key_0, value_0, key_1, value_1, ...], hence the +1 here\n const existingBaggageValue = requestHeaders[existingBaggageIndex + 1];\n const merged = mergeBaggageHeaders(existingBaggageValue, baggage);\n if (merged) {\n requestHeaders[existingBaggageIndex + 1] = merged;\n }\n }\n }\n\n if (Array.isArray(request.headers)) {\n // Replace contents in place so we keep the same array reference undici/fetch still holds.\n // `requestHeaders` is already normalized (string pairs only); splice writes them back.\n request.headers.splice(0, request.headers.length, ...requestHeaders);\n } else {\n request.headers = arrayToStringHeaders(requestHeaders);\n }\n}\n\n/**\n * Convert undici’s header array into `[name, value, name, value, ...]` where every value is a string.\n *\n * Undici v6 uses this shape: `[k1, v1, k2, v2, ...]`. Types allow each `v` to be `string | string[]` when\n * that header has multiple values. Sentry’s dedupe/merge helpers expect one string per value slot, so\n * multi-value arrays are joined with `', '`. Missing value slots become `''`.\n */\nfunction normalizeUndiciHeaderPairs(headers: (string | string[])[]): string[] {\n const out: string[] = [];\n for (let i = 0; i < headers.length; i++) {\n const entry = headers[i];\n if (i % 2 === 0) {\n // Header name (should always be a string; coerce defensively).\n out.push(typeof entry === 'string' ? entry : String(entry));\n } else {\n // Header value: flatten `string[]` to a single string for downstream string-only helpers.\n out.push(Array.isArray(entry) ? entry.join(', ') : (entry ?? ''));\n }\n }\n return out;\n}\n\nfunction stringToArrayHeaders(requestHeaders: string): string[] {\n const headersArray = requestHeaders.split('\\r\\n');\n const headers: string[] = [];\n for (const header of headersArray) {\n try {\n const colonIndex = header.indexOf(':');\n if (colonIndex === -1) {\n continue;\n }\n const key = header.slice(0, colonIndex).trim();\n const value = header.slice(colonIndex + 1).trim();\n if (key) {\n headers.push(key, value);\n }\n } catch {\n debug.warn(`Failed to convert string request header to array header: ${header}`);\n }\n }\n return headers;\n}\n\nfunction arrayToStringHeaders(headers: string[]): string {\n const headerPairs: string[] = [];\n\n for (let i = 0; i < headers.length; i += 2) {\n const key = headers[i];\n const value = headers[i + 1];\n if (!key || value == null) {\n // skip falsy keys but only null/undefined values\n continue;\n }\n headerPairs.push(`${key}: ${value}`);\n }\n\n if (!headerPairs.length) {\n return '';\n }\n\n return headerPairs.join('\\r\\n').concat('\\r\\n');\n}\n\n/**\n * For a given header name, if there are multiple entries in the [key, value, key, value, ...] array,\n * keep the first entry and remove the rest.\n * For baggage, values are merged to preserve all entries but to dedupe sentry- values, and always\n * keep the first occurrence of them\n */\nfunction _deduplicateArrayHeader(headers: string[], headerName: string): void {\n let firstIndex = -1;\n for (let i = 0; i < headers.length; i += 2) {\n if (headers[i] !== headerName) {\n continue;\n }\n\n if (firstIndex === -1) {\n firstIndex = i;\n continue;\n }\n\n const firstHeaderValue = headers[firstIndex + 1];\n if (headerName === SENTRY_BAGGAGE_HEADER && firstHeaderValue) {\n // mergeBaggageHeaders always takes sentry- values from the new baggage (2nd param) and merges\n // it with the existing one (1st param). Here, we want to keep the first header's existing\n // sentry- values in favor of the new ones. Hence we swap the parameters.\n const merged = mergeBaggageHeaders(headers[i + 1], firstHeaderValue);\n if (merged) {\n headers[firstIndex + 1] = merged;\n }\n }\n headers.splice(i, 2);\n i -= 2;\n }\n}\n\n/**\n * Find the index of an existing header in an array of headers.\n * Only take even indices, because headers are in format [key_0, value_0, key_1, value_1, ...]\n * otherwise we could match a header _value_ with @param name\n */\nfunction _findExistingHeaderIndex(headers: string[], name: string): number {\n return headers.findIndex((header, i) => i % 2 === 0 && header === name);\n}\n\n/** Add a breadcrumb for an outgoing fetch/undici request. */\nexport function addFetchRequestBreadcrumb(request: UndiciRequest, response: UndiciResponse): void {\n const data = getBreadcrumbData(request);\n\n const statusCode = response.statusCode;\n const level = getBreadcrumbLogLevelFromHttpStatusCode(statusCode);\n\n addBreadcrumb(\n {\n category: 'http',\n data: {\n status_code: statusCode,\n ...data,\n },\n type: 'http',\n level,\n },\n {\n event: 'response',\n request,\n response,\n },\n );\n}\n\nfunction getBreadcrumbData(request: UndiciRequest): Partial<SanitizedRequestData> {\n try {\n const url = getAbsoluteUrl(request.origin, request.path);\n const parsedUrl = parseUrl(url);\n\n const data: Partial<SanitizedRequestData> = {\n url: getSanitizedUrlString(parsedUrl),\n 'http.method': request.method || 'GET',\n };\n\n if (parsedUrl.search) {\n data['http.query'] = parsedUrl.search;\n }\n if (parsedUrl.hash) {\n data['http.fragment'] = parsedUrl.hash;\n }\n\n return data;\n } catch {\n return {};\n }\n}\n\n/** Get the absolute URL from an origin and path. */\nexport function getAbsoluteUrl(origin: string, path: string = '/'): string {\n try {\n const url = new URL(path, origin);\n return url.toString();\n } catch {\n // fallback: Construct it on our own\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}`;\n }\n\n return `${url}${path}`;\n }\n}\n"],"names":["getClient","shouldPropagateTraceForUrl","withActiveSpan","getTraceData","mergeBaggageHeaders","debug","getBreadcrumbLogLevelFromHttpStatusCode","addBreadcrumb","parseUrl","getSanitizedUrlString"],"mappings":"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"} |
@@ -6,2 +6,3 @@ export { httpIntegration } from './integrations/http/index.js'; | ||
| export { nativeNodeFetchIntegration } from './integrations/node-fetch/index.js'; | ||
| export { instrumentUndici } from './integrations/node-fetch/undici-instrumentation.js'; | ||
| export { SentryNodeFetchInstrumentation } from './integrations/node-fetch/SentryNodeFetchInstrumentation.js'; | ||
@@ -38,3 +39,2 @@ export { SentryContextManager } from './otel/contextManager.js'; | ||
| export { initializeEsmLoader } from './sdk/esmLoader.js'; | ||
| export { isCjs } from './utils/detection.js'; | ||
| export { createMissingInstrumentationContext } from './utils/createMissingInstrumentationContext.js'; | ||
@@ -41,0 +41,0 @@ export { makeNodeTransport } from './transports/http.js'; |
@@ -8,3 +8,3 @@ import { types } from 'node:util'; | ||
| const { isPromise } = types; | ||
| const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZS1jb3JlIDEwLjYzLjAgKDIzNjJlOWYpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyB0fWZyb20ibm9kZTppbnNwZWN0b3IiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIG4scGFyZW50UG9ydCBhcyBlfWZyb20ibm9kZTp3b3JrZXJfdGhyZWFkcyI7aW1wb3J0e3Bvc2l4IGFzIHIsc2VwIGFzIG99ZnJvbSJub2RlOnBhdGgiO2ltcG9ydCphcyBpIGZyb20ibm9kZTpodHRwIjtpbXBvcnQqYXMgcyBmcm9tIm5vZGU6aHR0cHMiO2ltcG9ydHtSZWFkYWJsZSBhcyBjfWZyb20ibm9kZTpzdHJlYW0iO2ltcG9ydHtjcmVhdGVHemlwIGFzIHV9ZnJvbSJub2RlOnpsaWIiO2ltcG9ydCphcyBhIGZyb20ibm9kZTpuZXQiO2ltcG9ydCphcyBmIGZyb20ibm9kZTp0bHMiO2NvbnN0IGg9InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fLHA9Z2xvYmFsVGhpcyxkPSIxMC42My4wIjtmdW5jdGlvbiBsKCl7cmV0dXJuIGcocCkscH1mdW5jdGlvbiBnKHQpe2NvbnN0IG49dC5fX1NFTlRSWV9fPXQuX19TRU5UUllfX3x8e307cmV0dXJuIG4udmVyc2lvbj1uLnZlcnNpb258fGQsbltkXT1uW2RdfHx7fX1mdW5jdGlvbiBtKHQsbixlPXApe2NvbnN0IHI9ZS5fX1NFTlRSWV9fPWUuX19TRU5UUllfX3x8e30sbz1yW2RdPXJbZF18fHt9O3JldHVybiBvW3RdfHwob1t0XT1uKCkpfWNvbnN0IHk9e307ZnVuY3Rpb24gYih0KXtpZighKCJjb25zb2xlImluIHApKXJldHVybiB0KCk7Y29uc3Qgbj1wLmNvbnNvbGUsZT17fSxyPU9iamVjdC5rZXlzKHkpO3IuZm9yRWFjaCh0PT57Y29uc3Qgcj15W3RdO2VbdF09blt0XSxuW3RdPXJ9KTt0cnl7cmV0dXJuIHQoKX1maW5hbGx5e3IuZm9yRWFjaCh0PT57blt0XT1lW3RdfSl9fWZ1bmN0aW9uIHYoKXtyZXR1cm4gUygpLmVuYWJsZWR9ZnVuY3Rpb24gXyh0LC4uLm4pe2gmJnYoKSYmYigoKT0+e3AuY29uc29sZVt0XShgU2VudHJ5IExvZ2dlciBbJHt0fV06YCwuLi5uKX0pfWZ1bmN0aW9uIFMoKXtyZXR1cm4gaD9tKCJsb2dnZXJTZXR0aW5ncyIsKCk9Pih7ZW5hYmxlZDohMX0pKTp7ZW5hYmxlZDohMX19Y29uc3Qgdz17ZW5hYmxlOmZ1bmN0aW9uKCl7UygpLmVuYWJsZWQ9ITB9LGRpc2FibGU6ZnVuY3Rpb24oKXtTKCkuZW5hYmxlZD0hMX0saXNFbmFibGVkOnYsbG9nOmZ1bmN0aW9uKC4uLnQpe18oImxvZyIsLi4udCl9LHdhcm46ZnVuY3Rpb24oLi4udCl7Xygid2FybiIsLi4udCl9LGVycm9yOmZ1bmN0aW9uKC4uLnQpe18oImVycm9yIiwuLi50KX19LCQ9L2NhcHR1cmVNZXNzYWdlfGNhcHR1cmVFeGNlcHRpb24vO2Z1bmN0aW9uIEUodCl7cmV0dXJuIHRbdC5sZW5ndGgtMV18fHt9fWNvbnN0IHg9Ijxhbm9ueW1vdXM+Ijtjb25zdCBOPU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7ZnVuY3Rpb24gQyh0LG4pe3JldHVybiBOLmNhbGwodCk9PT1gW29iamVjdCAke259XWB9ZnVuY3Rpb24gaih0KXtyZXR1cm4gQm9vbGVhbih0Py50aGVuJiYiZnVuY3Rpb24iPT10eXBlb2YgdC50aGVuKX1mdW5jdGlvbiBSKHQsbil7dHJ5e3JldHVybiB0IGluc3RhbmNlb2Ygbn1jYXRjaHtyZXR1cm4hMX19ZnVuY3Rpb24gQSh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2goTi5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBXZWJBc3NlbWJseS5FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBSKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uSSh0KX07aWYobj10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJlIobixFdmVudCkpe2NvbnN0e3R5cGU6bix0YXJnZXQ6ZSxjdXJyZW50VGFyZ2V0OnIsZGV0YWlsOm99PXQ7cmV0dXJue3R5cGU6bix0YXJnZXQ6ZSxjdXJyZW50VGFyZ2V0OnIsLi4ubz97ZGV0YWlsOm99Ont9LC4uLkkodCl9fXZhciBuO3JldHVybiB0fWZ1bmN0aW9uIEkodCl7cmV0dXJuIm9iamVjdCI9PXR5cGVvZiB0JiZudWxsIT09dD9PYmplY3QuZnJvbUVudHJpZXMoT2JqZWN0LmVudHJpZXModCkpOnt9fWxldCBPO2Z1bmN0aW9uIFQodCl7aWYodm9pZCAwIT09TylyZXR1cm4gTz9PKHQpOnQoKTtjb25zdCBuPVN5bWJvbC5mb3IoIl9fU0VOVFJZX1NBRkVfUkFORE9NX0lEX1dSQVBQRVJfXyIpLGU9cDtyZXR1cm4gbiBpbiBlJiYiZnVuY3Rpb24iPT10eXBlb2YgZVtuXT8oTz1lW25dLE8odCkpOihPPW51bGwsdCgpKX1mdW5jdGlvbiBrKCl7cmV0dXJuIFQoKCk9Pk1hdGgucmFuZG9tKCkpfWZ1bmN0aW9uIFAoKXtyZXR1cm4gVCgoKT0+RGF0ZS5ub3coKSl9Y29uc3QgRD1TeW1ib2wuZm9yKCJzZW50cnkuc2tpcE5vcm1hbGl6YXRpb24iKSxVPVN5bWJvbC5mb3IoInNlbnRyeS5vdmVycmlkZU5vcm1hbGl6YXRpb25EZXB0aCIpO2Z1bmN0aW9uIEIodCxuPTEwMCxlPTEvMCl7dHJ5e3JldHVybiBMKCIiLHQsbixlKX1jYXRjaCh0KXtyZXR1cm57RVJST1I6YCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke3R9KWB9fX1mdW5jdGlvbiBMKHQsbixlPTEvMCxyPTEvMCxvPWZ1bmN0aW9uKCl7Y29uc3QgdD1uZXcgV2Vha1NldDtmdW5jdGlvbiBuKG4pe3JldHVybiEhdC5oYXMobil8fCh0LmFkZChuKSwhMSl9ZnVuY3Rpb24gZShuKXt0LmRlbGV0ZShuKX1yZXR1cm5bbixlXX0oKSl7Y29uc3RbaSxzXT1vO2lmKG51bGw9PW58fFsiYm9vbGVhbiIsInN0cmluZyJdLmluY2x1ZGVzKHR5cGVvZiBuKXx8Im51bWJlciI9PXR5cGVvZiBuJiZOdW1iZXIuaXNGaW5pdGUobikpcmV0dXJuIG47Y29uc3QgYz1mdW5jdGlvbih0LG4pe3RyeXtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGdsb2JhbCYmbj09PWdsb2JhbClyZXR1cm4iW0dsb2JhbF0iO2lmKCJudW1iZXIiPT10eXBlb2YgbiYmIU51bWJlci5pc0Zpbml0ZShuKSlyZXR1cm5gWyR7bn1dYDtpZigiZnVuY3Rpb24iPT10eXBlb2YgbilyZXR1cm5gW0Z1bmN0aW9uOiAke2Z1bmN0aW9uKHQpe3RyeXtyZXR1cm4gdCYmImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQubmFtZXx8eH1jYXRjaHtyZXR1cm4geH19KG4pfV1gO2lmKCJzeW1ib2wiPT10eXBlb2YgbilyZXR1cm5gWyR7U3RyaW5nKG4pfV1gO2lmKCJiaWdpbnQiPT10eXBlb2YgbilyZXR1cm5gW0JpZ0ludDogJHtTdHJpbmcobil9XWA7Y29uc3QgdD1mdW5jdGlvbih0KXtjb25zdCBuPU9iamVjdC5nZXRQcm90b3R5cGVPZih0KTtyZXR1cm4gbj8uY29uc3RydWN0b3I/bi5jb25zdHJ1Y3Rvci5uYW1lOiJudWxsIHByb3RvdHlwZSJ9KG4pO3JldHVybmBbb2JqZWN0ICR7dH1dYH1jYXRjaCh0KXtyZXR1cm5gKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH19KDAsbik7aWYoIWMuc3RhcnRzV2l0aCgiW29iamVjdCAiKSlyZXR1cm4gYztpZihmdW5jdGlvbih0KXtyZXR1cm4gQm9vbGVhbih0W0RdKX0obikpcmV0dXJuIG47Y29uc3QgdT1mdW5jdGlvbih0KXtjb25zdCBuPXRbVV07cmV0dXJuIm51bWJlciI9PXR5cGVvZiBuP246dm9pZCAwfShuKSxhPXZvaWQgMCE9PXU/dTplO2lmKDA9PT1hKXJldHVybiBjLnJlcGxhY2UoIm9iamVjdCAiLCIiKTtpZihpKG4pKXJldHVybiJbQ2lyY3VsYXIgfl0iO2NvbnN0IGY9bjtpZihmJiYiZnVuY3Rpb24iPT10eXBlb2YgZi50b0pTT04pdHJ5e3JldHVybiBMKCIiLGYudG9KU09OKCksYS0xLHIsbyl9Y2F0Y2h7fWNvbnN0IGg9QXJyYXkuaXNBcnJheShuKT9bXTp7fTtsZXQgcD0wO2NvbnN0IGQ9QShuKTtmb3IoY29uc3QgdCBpbiBkKXtpZighT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGQsdCkpY29udGludWU7aWYocD49cil7aFt0XT0iW01heFByb3BlcnRpZXMgfl0iO2JyZWFrfWNvbnN0IG49ZFt0XTtoW3RdPUwodCxuLGEtMSxyLG8pLHArK31yZXR1cm4gcyhuKSxofWZ1bmN0aW9uIE0odCxuKXtjb25zdCBlPW4ucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL1t8XFx7fSgpW1xdXiQrKj8uXS9nLCJcXCQmIik7bGV0IHI9dDt0cnl7cj1kZWNvZGVVUkkodCl9Y2F0Y2h7fXJldHVybiByLnJlcGxhY2UoL1xcL2csIi8iKS5yZXBsYWNlKC93ZWJwYWNrOlwvPy9nLCIiKS5yZXBsYWNlKG5ldyBSZWdFeHAoYChmaWxlOi8vKT8vKiR7ZX0vKmAsImlnIiksImFwcDovLy8iKX1mdW5jdGlvbiB6KHQsbj0wKXtyZXR1cm4ic3RyaW5nIiE9dHlwZW9mIHR8fDA9PT1ufHx0Lmxlbmd0aDw9bj90OmAke3Quc2xpY2UoMCxuKX0uLi5gfWxldCBGO2Z1bmN0aW9uIEcodD1mdW5jdGlvbigpe2NvbnN0IHQ9cDtyZXR1cm4gdC5jcnlwdG98fHQubXNDcnlwdG99KCkpe3RyeXtpZih0Py5yYW5kb21VVUlEKXJldHVybiBUKCgpPT50LnJhbmRvbVVVSUQoKSkucmVwbGFjZSgvLS9nLCIiKX1jYXRjaHt9cmV0dXJuIEZ8fChGPSIxMDAwMDAwMDEwMDA0MDAwODAwMDEwMDAwMDAwMDAwMCIpLEYucmVwbGFjZSgvWzAxOF0vZyx0PT4odF4oMTYqaygpJjE1KT4+dC80KS50b1N0cmluZygxNikpfWZ1bmN0aW9uIEooKXtyZXR1cm4gUCgpLzFlM31sZXQgVztmdW5jdGlvbiBZKCl7cmV0dXJuKFc/PyhXPWZ1bmN0aW9uKCl7Y29uc3R7cGVyZm9ybWFuY2U6dH09cDtpZighdD8ubm93fHwhdC50aW1lT3JpZ2luKXJldHVybiBKO2NvbnN0IG49dC50aW1lT3JpZ2luO3JldHVybigpPT4obitUKCgpPT50Lm5vdygpKSkvMWUzfSgpKSkoKX1mdW5jdGlvbiBIKHQpe2NvbnN0IG49WSgpLGU9e3NpZDpHKCksaW5pdDohMCx0aW1lc3RhbXA6bixzdGFydGVkOm4sZHVyYXRpb246MCxzdGF0dXM6Im9rIixlcnJvcnM6MCxpZ25vcmVEdXJhdGlvbjohMSx0b0pTT046KCk9PmZ1bmN0aW9uKHQpe3JldHVybntzaWQ6YCR7dC5zaWR9YCxpbml0OnQuaW5pdCxzdGFydGVkOm5ldyBEYXRlKDFlMyp0LnN0YXJ0ZWQpLnRvSVNPU3RyaW5nKCksdGltZXN0YW1wOm5ldyBEYXRlKDFlMyp0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxzdGF0dXM6dC5zdGF0dXMsZXJyb3JzOnQuZXJyb3JzLGRpZDoibnVtYmVyIj09dHlwZW9mIHQuZGlkfHwic3RyaW5nIj09dHlwZW9mIHQuZGlkP2Ake3QuZGlkfWA6dm9pZCAwLGR1cmF0aW9uOnQuZHVyYXRpb24sYWJub3JtYWxfbWVjaGFuaXNtOnQuYWJub3JtYWxfbWVjaGFuaXNtLGF0dHJzOntyZWxlYXNlOnQucmVsZWFzZSxlbnZpcm9ubWVudDp0LmVudmlyb25tZW50LGlwX2FkZHJlc3M6dC5pcEFkZHJlc3MsdXNlcl9hZ2VudDp0LnVzZXJBZ2VudH19fShlKX07cmV0dXJuIHQmJksoZSx0KSxlfWZ1bmN0aW9uIEsodCxuPXt9KXtpZihuLnVzZXImJighdC5pcEFkZHJlc3MmJm4udXNlci5pcF9hZGRyZXNzJiYodC5pcEFkZHJlc3M9bi51c2VyLmlwX2FkZHJlc3MpLHQuZGlkfHxuLmRpZHx8KHQuZGlkPW4udXNlci5pZHx8bi51c2VyLmVtYWlsfHxuLnVzZXIudXNlcm5hbWUpKSx0LnRpbWVzdGFtcD1uLnRpbWVzdGFtcHx8WSgpLG4uYWJub3JtYWxfbWVjaGFuaXNtJiYodC5hYm5vcm1hbF9tZWNoYW5pc209bi5hYm5vcm1hbF9tZWNoYW5pc20pLG4uaWdub3JlRHVyYXRpb24mJih0Lmlnbm9yZUR1cmF0aW9uPW4uaWdub3JlRHVyYXRpb24pLG4uc2lkJiYodC5zaWQ9MzI9PT1uLnNpZC5sZW5ndGg/bi5zaWQ6RygpKSx2b2lkIDAhPT1uLmluaXQmJih0LmluaXQ9bi5pbml0KSwhdC5kaWQmJm4uZGlkJiYodC5kaWQ9YCR7bi5kaWR9YCksIm51bWJlciI9PXR5cGVvZiBuLnN0YXJ0ZWQmJih0LnN0YXJ0ZWQ9bi5zdGFydGVkKSx0Lmlnbm9yZUR1cmF0aW9uKXQuZHVyYXRpb249dm9pZCAwO2Vsc2UgaWYoIm51bWJlciI9PXR5cGVvZiBuLmR1cmF0aW9uKXQuZHVyYXRpb249bi5kdXJhdGlvbjtlbHNle2NvbnN0IG49dC50aW1lc3RhbXAtdC5zdGFydGVkO3QuZHVyYXRpb249bj49MD9uOjB9bi5yZWxlYXNlJiYodC5yZWxlYXNlPW4ucmVsZWFzZSksbi5lbnZpcm9ubWVudCYmKHQuZW52aXJvbm1lbnQ9bi5lbnZpcm9ubWVudCksIXQuaXBBZGRyZXNzJiZuLmlwQWRkcmVzcyYmKHQuaXBBZGRyZXNzPW4uaXBBZGRyZXNzKSwhdC51c2VyQWdlbnQmJm4udXNlckFnZW50JiYodC51c2VyQWdlbnQ9bi51c2VyQWdlbnQpLCJudW1iZXIiPT10eXBlb2Ygbi5lcnJvcnMmJih0LmVycm9ycz1uLmVycm9ycyksbi5zdGF0dXMmJih0LnN0YXR1cz1uLnN0YXR1cyl9ZnVuY3Rpb24gWih0LG4sZT0yKXtpZighbnx8Im9iamVjdCIhPXR5cGVvZiBufHxlPD0wKXJldHVybiBuO2lmKHQmJjA9PT1PYmplY3Qua2V5cyhuKS5sZW5ndGgpcmV0dXJuIHQ7Y29uc3Qgcj17Li4udH07Zm9yKGNvbnN0IHQgaW4gbilPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobix0KSYmKHJbdF09WihyW3RdLG5bdF0sZS0xKSk7cmV0dXJuIHJ9ZnVuY3Rpb24gcSgpe3JldHVybiBHKCl9ZnVuY3Rpb24gVigpe3JldHVybiBHKCkuc3Vic3RyaW5nKDE2KX1mdW5jdGlvbiBRKHQpe2lmKHQpe2lmKCJvYmplY3QiPT10eXBlb2YgdCYmImRlcmVmImluIHQmJiJmdW5jdGlvbiI9PXR5cGVvZiB0LmRlcmVmKXRyeXtyZXR1cm4gdC5kZXJlZigpfWNhdGNoe3JldHVybn1yZXR1cm4gdH19Y29uc3QgWD0iX3NlbnRyeVNwYW4iO2Z1bmN0aW9uIHR0KHQsbil7bj9mdW5jdGlvbih0LG4sZSl7dHJ5e09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LG4se3ZhbHVlOmUsd3JpdGFibGU6ITAsY29uZmlndXJhYmxlOiEwfSl9Y2F0Y2h7aCYmdy5sb2coYEZhaWxlZCB0byBhZGQgbm9uLWVudW1lcmFibGUgcHJvcGVydHkgIiR7U3RyaW5nKG4pfSIgdG8gb2JqZWN0YCx0KX19KHQsWCxmdW5jdGlvbih0KXt0cnl7Y29uc3Qgbj1wLldlYWtSZWY7aWYoImZ1bmN0aW9uIj09dHlwZW9mIG4pcmV0dXJuIG5ldyBuKHQpfWNhdGNoe31yZXR1cm4gdH0obikpOmRlbGV0ZSB0W1hdfWZ1bmN0aW9uIG50KHQpe3JldHVybiBRKHRbWF0pfWNsYXNzIGV0e2NvbnN0cnVjdG9yKCl7dGhpcy50PSExLHRoaXMubz1bXSx0aGlzLmk9W10sdGhpcy51PVtdLHRoaXMuaD1bXSx0aGlzLnA9e30sdGhpcy5sPXt9LHRoaXMubT17fSx0aGlzLnY9e30sdGhpcy5fPXt9LHRoaXMuUz17fSx0aGlzLk49e3RyYWNlSWQ6cSgpLHNhbXBsZVJhbmQ6aygpfX1jbG9uZSgpe2NvbnN0IHQ9bmV3IGV0O3JldHVybiB0LnU9Wy4uLnRoaXMudV0sdC5sPXsuLi50aGlzLmx9LHQubT17Li4udGhpcy5tfSx0LnY9ey4uLnRoaXMudn0sdC5fPXsuLi50aGlzLl99LHRoaXMuXy5mbGFncyYmKHQuXy5mbGFncz17dmFsdWVzOlsuLi50aGlzLl8uZmxhZ3MudmFsdWVzXX0pLHQucD10aGlzLnAsdC5DPXRoaXMuQyx0Lmo9dGhpcy5qLHQuUj10aGlzLlIsdC5BPXRoaXMuQSx0Lmk9Wy4uLnRoaXMuaV0sdC5oPVsuLi50aGlzLmhdLHQuUz17Li4udGhpcy5TfSx0Lk49ey4uLnRoaXMuTn0sdC5JPXRoaXMuSSx0Lk89dGhpcy5PLHQuVD10aGlzLlQsdHQodCxudCh0aGlzKSksdH1zZXRDbGllbnQodCl7dGhpcy5JPXR9c2V0TGFzdEV2ZW50SWQodCl7dGhpcy5PPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuSX1sYXN0RXZlbnRJZCgpe3JldHVybiB0aGlzLk99YWRkU2NvcGVMaXN0ZW5lcih0KXt0aGlzLm8ucHVzaCh0KX1hZGRFdmVudFByb2Nlc3Nvcih0KXtyZXR1cm4gdGhpcy5pLnB1c2godCksdGhpc31zZXRVc2VyKHQpe3JldHVybiB0aGlzLnA9dHx8e2VtYWlsOnZvaWQgMCxpZDp2b2lkIDAsaXBfYWRkcmVzczp2b2lkIDAsdXNlcm5hbWU6dm9pZCAwfSx0aGlzLmomJksodGhpcy5qLHt1c2VyOnR9KSx0aGlzLmsoKSx0aGlzfWdldFVzZXIoKXtyZXR1cm4gdGhpcy5wfXNldENvbnZlcnNhdGlvbklkKHQpe3JldHVybiB0aGlzLlQ9dHx8dm9pZCAwLHRoaXMuaygpLHRoaXN9c2V0VGFncyh0KXtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4udH0sdGhpcy5rKCksdGhpc31zZXRUYWcodCxuKXtyZXR1cm4gdGhpcy5zZXRUYWdzKHtbdF06bn0pfXNldEF0dHJpYnV0ZXModCl7cmV0dXJuIHRoaXMubT17Li4udGhpcy5tLC4uLnR9LHRoaXMuaygpLHRoaXN9c2V0QXR0cmlidXRlKHQsbil7cmV0dXJuIHRoaXMuc2V0QXR0cmlidXRlcyh7W3RdOm59KX1yZW1vdmVBdHRyaWJ1dGUodCl7cmV0dXJuIHQgaW4gdGhpcy5tJiYoZGVsZXRlIHRoaXMubVt0XSx0aGlzLmsoKSksdGhpc31zZXRFeHRyYXModCl7cmV0dXJuIHRoaXMudj17Li4udGhpcy52LC4uLnR9LHRoaXMuaygpLHRoaXN9c2V0RXh0cmEodCxuKXtyZXR1cm4gdGhpcy52PXsuLi50aGlzLnYsW3RdOm59LHRoaXMuaygpLHRoaXN9c2V0RmluZ2VycHJpbnQodCl7cmV0dXJuIHRoaXMuQT10LHRoaXMuaygpLHRoaXN9c2V0TGV2ZWwodCl7cmV0dXJuIHRoaXMuQz10LHRoaXMuaygpLHRoaXN9c2V0VHJhbnNhY3Rpb25OYW1lKHQpe3JldHVybiB0aGlzLlI9dCx0aGlzLmsoKSx0aGlzfXNldENvbnRleHQodCxuKXtyZXR1cm4gbnVsbD09PW4/ZGVsZXRlIHRoaXMuX1t0XTp0aGlzLl9bdF09bix0aGlzLmsoKSx0aGlzfXNldFNlc3Npb24odCl7cmV0dXJuIHQ/dGhpcy5qPXQ6ZGVsZXRlIHRoaXMuaix0aGlzLmsoKSx0aGlzfWdldFNlc3Npb24oKXtyZXR1cm4gdGhpcy5qfXVwZGF0ZSh0KXtpZighdClyZXR1cm4gdGhpcztjb25zdCBuPSJmdW5jdGlvbiI9PXR5cGVvZiB0P3QodGhpcyk6dCxlPW4gaW5zdGFuY2VvZiBldD9uLmdldFNjb3BlRGF0YSgpOkMobiwiT2JqZWN0Iik/dDp2b2lkIDA7Y29uc3R7dGFnczpyLGF0dHJpYnV0ZXM6byxleHRyYTppLHVzZXI6cyxjb250ZXh0czpjLGxldmVsOnUsZmluZ2VycHJpbnQ6YT1bXSxwcm9wYWdhdGlvbkNvbnRleHQ6Zixjb252ZXJzYXRpb25JZDpofT1lfHx7fTtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4ucn0sdGhpcy5tPXsuLi50aGlzLm0sLi4ub30sdGhpcy52PXsuLi50aGlzLnYsLi4uaX0sdGhpcy5fPXsuLi50aGlzLl8sLi4uY30scyYmT2JqZWN0LmtleXMocykubGVuZ3RoJiYodGhpcy5wPXMpLHUmJih0aGlzLkM9dSksYS5sZW5ndGgmJih0aGlzLkE9YSksZiYmKHRoaXMuTj1mKSxoJiYodGhpcy5UPWgpLHRoaXN9Y2xlYXIoKXtyZXR1cm4gdGhpcy51PVtdLHRoaXMubD17fSx0aGlzLm09e30sdGhpcy52PXt9LHRoaXMucD17fSx0aGlzLl89e30sdGhpcy5DPXZvaWQgMCx0aGlzLlI9dm9pZCAwLHRoaXMuQT12b2lkIDAsdGhpcy5qPXZvaWQgMCx0aGlzLlQ9dm9pZCAwLHR0KHRoaXMsdm9pZCAwKSx0aGlzLmg9W10sdGhpcy5zZXRQcm9wYWdhdGlvbkNvbnRleHQoe3RyYWNlSWQ6cSgpLHNhbXBsZVJhbmQ6aygpfSksdGhpcy5rKCksdGhpc31hZGRCcmVhZGNydW1iKHQsbil7Y29uc3QgZT0ibnVtYmVyIj09dHlwZW9mIG4/bjoxMDA7aWYoZTw9MClyZXR1cm4gdGhpcztjb25zdCByPXt0aW1lc3RhbXA6SigpLC4uLnQsbWVzc2FnZTp0Lm1lc3NhZ2U/eih0Lm1lc3NhZ2UsMjA0OCk6dC5tZXNzYWdlfTtyZXR1cm4gdGhpcy51LnB1c2gociksdGhpcy51Lmxlbmd0aD5lJiYodGhpcy51PXRoaXMudS5zbGljZSgtZSksdGhpcy5JPy5yZWNvcmREcm9wcGVkRXZlbnQoImJ1ZmZlcl9vdmVyZmxvdyIsImxvZ19pdGVtIikpLHRoaXMuaygpLHRoaXN9Z2V0TGFzdEJyZWFkY3J1bWIoKXtyZXR1cm4gdGhpcy51W3RoaXMudS5sZW5ndGgtMV19Y2xlYXJCcmVhZGNydW1icygpe3JldHVybiB0aGlzLnU9W10sdGhpcy5rKCksdGhpc31hZGRBdHRhY2htZW50KHQpe3JldHVybiB0aGlzLmgucHVzaCh0KSx0aGlzfWNsZWFyQXR0YWNobWVudHMoKXtyZXR1cm4gdGhpcy5oPVtdLHRoaXN9Z2V0U2NvcGVEYXRhKCl7cmV0dXJue2JyZWFkY3J1bWJzOnRoaXMudSxhdHRhY2htZW50czp0aGlzLmgsY29udGV4dHM6dGhpcy5fLHRhZ3M6dGhpcy5sLGF0dHJpYnV0ZXM6dGhpcy5tLGV4dHJhOnRoaXMudix1c2VyOnRoaXMucCxsZXZlbDp0aGlzLkMsZmluZ2VycHJpbnQ6dGhpcy5BfHxbXSxldmVudFByb2Nlc3NvcnM6dGhpcy5pLHByb3BhZ2F0aW9uQ29udGV4dDp0aGlzLk4sc2RrUHJvY2Vzc2luZ01ldGFkYXRhOnRoaXMuUyx0cmFuc2FjdGlvbk5hbWU6dGhpcy5SLHNwYW46bnQodGhpcyksY29udmVyc2F0aW9uSWQ6dGhpcy5UfX1zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEodCl7cmV0dXJuIHRoaXMuUz1aKHRoaXMuUyx0LDIpLHRoaXN9c2V0UHJvcGFnYXRpb25Db250ZXh0KHQpe3JldHVybiB0aGlzLk49dCx0aGlzfWdldFByb3BhZ2F0aW9uQ29udGV4dCgpe3JldHVybiB0aGlzLk59Y2FwdHVyZUV4Y2VwdGlvbih0LG4pe2NvbnN0IGU9bj8uZXZlbnRfaWR8fEcoKTtpZighdGhpcy5JKXJldHVybiBoJiZ3Lndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBleGNlcHRpb24hIiksZTtjb25zdCByPW5ldyBFcnJvcigiU2VudHJ5IHN5bnRoZXRpY0V4Y2VwdGlvbiIpO3JldHVybiB0aGlzLkkuY2FwdHVyZUV4Y2VwdGlvbih0LHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpyLC4uLm4sZXZlbnRfaWQ6ZX0sdGhpcyksZX1jYXB0dXJlTWVzc2FnZSh0LG4sZSl7Y29uc3Qgcj1lPy5ldmVudF9pZHx8RygpO2lmKCF0aGlzLkkpcmV0dXJuIGgmJncud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIG1lc3NhZ2UhIikscjtjb25zdCBvPWU/LnN5bnRoZXRpY0V4Y2VwdGlvbj8/bmV3IEVycm9yKHQpO3JldHVybiB0aGlzLkkuY2FwdHVyZU1lc3NhZ2UodCxuLHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpvLC4uLmUsZXZlbnRfaWQ6cn0sdGhpcykscn1jYXB0dXJlRXZlbnQodCxuKXtjb25zdCBlPXQuZXZlbnRfaWR8fG4/LmV2ZW50X2lkfHxHKCk7cmV0dXJuIHRoaXMuST8odGhpcy5JLmNhcHR1cmVFdmVudCh0LHsuLi5uLGV2ZW50X2lkOmV9LHRoaXMpLGUpOihoJiZ3Lndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBldmVudCEiKSxlKX1rKCl7dGhpcy50fHwodGhpcy50PSEwLHRoaXMuby5mb3JFYWNoKHQ9Pnt0KHRoaXMpfSksdGhpcy50PSExKX19Y29uc3QgcnQ9dD0+dCBpbnN0YW5jZW9mIFByb21pc2UmJiF0W290XSxvdD1TeW1ib2woImNoYWluZWQgUHJvbWlzZUxpa2UiKSxpdD0odCxuKT0+e2lmKCFuKXJldHVybiB0O2xldCBlPSExO2Zvcihjb25zdCByIGluIHQpe2lmKHIgaW4gbiljb250aW51ZTtlPSEwO2NvbnN0IG89dFtyXTsiZnVuY3Rpb24iPT10eXBlb2Ygbz9PYmplY3QuZGVmaW5lUHJvcGVydHkobixyLHt2YWx1ZTooLi4ubik9Pm8uYXBwbHkodCxuKSxlbnVtZXJhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMCx3cml0YWJsZTohMH0pOm5bcl09b31yZXR1cm4gZSYmT2JqZWN0LmFzc2lnbihuLHtbb3RdOiEwfSksbn07Y2xhc3Mgc3R7Y29uc3RydWN0b3IodCxuKXtsZXQgZSxyO2U9dHx8bmV3IGV0LHI9bnx8bmV3IGV0LHRoaXMuUD1be3Njb3BlOmV9XSx0aGlzLkQ9cn13aXRoU2NvcGUodCl7Y29uc3Qgbj10aGlzLlUoKTtsZXQgZTt0cnl7ZT10KG4pfWNhdGNoKHQpe3Rocm93IHRoaXMuQigpLHR9cmV0dXJuIGooZSk/KCh0LG4sZSk9Pntjb25zdCByPXQudGhlbih0PT4obih0KSx0KSx0PT57dGhyb3cgZSh0KSx0fSk7cmV0dXJuIHJ0KHIpJiZydCh0KT9yOml0KHQscil9KShlLCgpPT50aGlzLkIoKSwoKT0+dGhpcy5CKCkpOih0aGlzLkIoKSxlKX1nZXRDbGllbnQoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLmNsaWVudH1nZXRTY29wZSgpe3JldHVybiB0aGlzLmdldFN0YWNrVG9wKCkuc2NvcGV9Z2V0SXNvbGF0aW9uU2NvcGUoKXtyZXR1cm4gdGhpcy5EfWdldFN0YWNrVG9wKCl7cmV0dXJuIHRoaXMuUFt0aGlzLlAubGVuZ3RoLTFdfVUoKXtjb25zdCB0PXRoaXMuZ2V0U2NvcGUoKS5jbG9uZSgpO3JldHVybiB0aGlzLlAucHVzaCh7Y2xpZW50OnRoaXMuZ2V0Q2xpZW50KCksc2NvcGU6dH0pLHR9Qigpe3JldHVybiEodGhpcy5QLmxlbmd0aDw9MSkmJiEhdGhpcy5QLnBvcCgpfX1mdW5jdGlvbiBjdCgpe2NvbnN0IHQ9ZyhsKCkpO3JldHVybiB0LnN0YWNrPXQuc3RhY2t8fG5ldyBzdChtKCJkZWZhdWx0Q3VycmVudFNjb3BlIiwoKT0+bmV3IGV0KSxtKCJkZWZhdWx0SXNvbGF0aW9uU2NvcGUiLCgpPT5uZXcgZXQpKX1mdW5jdGlvbiB1dCh0KXtyZXR1cm4gY3QoKS53aXRoU2NvcGUodCl9ZnVuY3Rpb24gYXQodCxuKXtjb25zdCBlPWN0KCk7cmV0dXJuIGUud2l0aFNjb3BlKCgpPT4oZS5nZXRTdGFja1RvcCgpLnNjb3BlPXQsbih0KSkpfWZ1bmN0aW9uIGZ0KHQpe3JldHVybiBjdCgpLndpdGhTY29wZSgoKT0+dChjdCgpLmdldElzb2xhdGlvblNjb3BlKCkpKX1mdW5jdGlvbiBodCh0KXtjb25zdCBuPWcodCk7cmV0dXJuIG4uYWNzP24uYWNzOnt3aXRoSXNvbGF0aW9uU2NvcGU6ZnQsd2l0aFNjb3BlOnV0LHdpdGhTZXRTY29wZTphdCx3aXRoU2V0SXNvbGF0aW9uU2NvcGU6KHQsbik9PmZ0KG4pLGdldEN1cnJlbnRTY29wZTooKT0+Y3QoKS5nZXRTY29wZSgpLGdldElzb2xhdGlvblNjb3BlOigpPT5jdCgpLmdldElzb2xhdGlvblNjb3BlKCl9fWZ1bmN0aW9uIHB0KCl7cmV0dXJuIGh0KGwoKSkuZ2V0Q3VycmVudFNjb3BlKCkuZ2V0Q2xpZW50KCl9ZnVuY3Rpb24gZHQodCl7Y29uc3Qgbj10O3JldHVybntzY29wZTpuLl9zZW50cnlTY29wZSxpc29sYXRpb25TY29wZTpRKG4uX3NlbnRyeUlzb2xhdGlvblNjb3BlKX19Y29uc3QgbHQ9InNlbnRyeS0iO2Z1bmN0aW9uIGd0KHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7aWYoIXR8fChuPXQsIUMobiwiU3RyaW5nIikmJiFBcnJheS5pc0FycmF5KHQpKSlyZXR1cm47dmFyIG47aWYoQXJyYXkuaXNBcnJheSh0KSlyZXR1cm4gdC5yZWR1Y2UoKHQsbik9Pntjb25zdCBlPW10KG4pO3JldHVybiBPYmplY3QuZW50cmllcyhlKS5mb3JFYWNoKChbbixlXSk9Pnt0W25dPWV9KSx0fSx7fSk7cmV0dXJuIG10KHQpfSh0KTtpZighbilyZXR1cm47Y29uc3QgZT1PYmplY3QuZW50cmllcyhuKS5yZWR1Y2UoKHQsW24sZV0pPT57aWYobi5zdGFydHNXaXRoKGx0KSl7dFtuLnNsaWNlKDcpXT1lfXJldHVybiB0fSx7fSk7cmV0dXJuIE9iamVjdC5rZXlzKGUpLmxlbmd0aD4wP2U6dm9pZCAwfWZ1bmN0aW9uIG10KHQpe3JldHVybiB0LnNwbGl0KCIsIikubWFwKHQ9Pntjb25zdCBuPXQuaW5kZXhPZigiPSIpO2lmKC0xPT09bilyZXR1cm5bXTtyZXR1cm5bdC5zbGljZSgwLG4pLHQuc2xpY2UobisxKV0ubWFwKHQ9Pnt0cnl7cmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudCh0LnRyaW0oKSl9Y2F0Y2h7cmV0dXJufX0pfSkucmVkdWNlKCh0LFtuLGVdKT0+KG4mJmUmJih0W25dPWUpLHQpLHt9KX1jb25zdCB5dD0vXm8oXGQrKVwuLztmdW5jdGlvbiBidCh0LG49ITEpe2NvbnN0e2hvc3Q6ZSxwYXRoOnIscGFzczpvLHBvcnQ6aSxwcm9qZWN0SWQ6cyxwcm90b2NvbDpjLHB1YmxpY0tleTp1fT10O3JldHVybmAke2N9Oi8vJHt1fSR7biYmbz9gOiR7b31gOiIifUAke2V9JHtpP2A6JHtpfWA6IiJ9LyR7cj9gJHtyfS9gOnJ9JHtzfWB9ZnVuY3Rpb24gdnQodCl7Y29uc3Qgbj10LmdldE9wdGlvbnMoKSx7aG9zdDplfT10LmdldERzbigpfHx7fTtsZXQgcjtyZXR1cm4gbi5vcmdJZD9yPVN0cmluZyhuLm9yZ0lkKTplJiYocj1mdW5jdGlvbih0KXtjb25zdCBuPXQubWF0Y2goeXQpO3JldHVybiBuPy5bMV19KGUpKSxyfWZ1bmN0aW9uIF90KHQpe2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZSxpc1JlbW90ZTpyfT10LnNwYW5Db250ZXh0KCksbz1yP246RXQodCkucGFyZW50X3NwYW5faWQsaT1kdCh0KS5zY29wZTtyZXR1cm57cGFyZW50X3NwYW5faWQ6byxzcGFuX2lkOnI/aT8uZ2V0UHJvcGFnYXRpb25Db250ZXh0KCkucHJvcGFnYXRpb25TcGFuSWR8fFYoKTpuLHRyYWNlX2lkOmV9fWZ1bmN0aW9uIFN0KHQpe3JldHVybiB0JiZ0Lmxlbmd0aD4wP3QubWFwKCh7Y29udGV4dDp7c3BhbklkOnQsdHJhY2VJZDpuLHRyYWNlRmxhZ3M6ZSwuLi5yfSxhdHRyaWJ1dGVzOm99KT0+KHtzcGFuX2lkOnQsdHJhY2VfaWQ6bixzYW1wbGVkOjE9PT1lLGF0dHJpYnV0ZXM6bywuLi5yfSkpOnZvaWQgMH1mdW5jdGlvbiB3dCh0KXtyZXR1cm4ibnVtYmVyIj09dHlwZW9mIHQ/JHQodCk6QXJyYXkuaXNBcnJheSh0KT90WzBdK3RbMV0vMWU5OnQgaW5zdGFuY2VvZiBEYXRlPyR0KHQuZ2V0VGltZSgpKTpZKCl9ZnVuY3Rpb24gJHQodCl7cmV0dXJuIHQ+OTk5OTk5OTk5OT90LzFlMzp0fWZ1bmN0aW9uIEV0KHQpe2lmKGZ1bmN0aW9uKHQpe3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiB0LmdldFNwYW5KU09OfSh0KSlyZXR1cm4gdC5nZXRTcGFuSlNPTigpO2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZX09dC5zcGFuQ29udGV4dCgpO2lmKGZ1bmN0aW9uKHQpe2NvbnN0IG49dDtyZXR1cm4hIShuLmF0dHJpYnV0ZXMmJm4uc3RhcnRUaW1lJiZuLm5hbWUmJm4uZW5kVGltZSYmbi5zdGF0dXMpfSh0KSl7Y29uc3R7YXR0cmlidXRlczpyLHN0YXJ0VGltZTpvLG5hbWU6aSxlbmRUaW1lOnMsc3RhdHVzOmMsbGlua3M6dX09dDtyZXR1cm57c3Bhbl9pZDpuLHRyYWNlX2lkOmUsZGF0YTpyLGRlc2NyaXB0aW9uOmkscGFyZW50X3NwYW5faWQ6eHQodCksc3RhcnRfdGltZXN0YW1wOnd0KG8pLHRpbWVzdGFtcDp3dChzKXx8dm9pZCAwLHN0YXR1czpOdChjKSxvcDpyWyJzZW50cnkub3AiXSxvcmlnaW46clsic2VudHJ5Lm9yaWdpbiJdLGxpbmtzOlN0KHUpfX1yZXR1cm57c3Bhbl9pZDpuLHRyYWNlX2lkOmUsc3RhcnRfdGltZXN0YW1wOjAsZGF0YTp7fX19ZnVuY3Rpb24geHQodCl7cmV0dXJuInBhcmVudFNwYW5JZCJpbiB0P3QucGFyZW50U3BhbklkOiJwYXJlbnRTcGFuQ29udGV4dCJpbiB0P3QucGFyZW50U3BhbkNvbnRleHQ/LnNwYW5JZDp2b2lkIDB9ZnVuY3Rpb24gTnQodCl7aWYodCYmMCE9PXQuY29kZSlyZXR1cm4gMT09PXQuY29kZT8ib2siOnQubWVzc2FnZXx8ImludGVybmFsX2Vycm9yIn1jb25zdCBDdD1mdW5jdGlvbih0KXtyZXR1cm4gdC5fc2VudHJ5Um9vdFNwYW58fHR9O2Z1bmN0aW9uIGp0KHQpe2lmKCJib29sZWFuIj09dHlwZW9mIF9fU0VOVFJZX1RSQUNJTkdfXyYmIV9fU0VOVFJZX1RSQUNJTkdfXylyZXR1cm4hMTtjb25zdCBuPXR8fHB0KCk/LmdldE9wdGlvbnMoKTtyZXR1cm4hKCFufHxudWxsPT1uLnRyYWNlc1NhbXBsZVJhdGUmJiFuLnRyYWNlc1NhbXBsZXIpfWNvbnN0IFJ0PVN5bWJvbC5mb3IoInNlbnRyeS5ub25SZWNvcmRpbmdTcGFuIik7ZnVuY3Rpb24gQXQodCxuKXtjb25zdCBlPW4uZ2V0T3B0aW9ucygpLHtwdWJsaWNLZXk6cn09bi5nZXREc24oKXx8e30sbz17ZW52aXJvbm1lbnQ6ZS5lbnZpcm9ubWVudHx8InByb2R1Y3Rpb24iLHJlbGVhc2U6ZS5yZWxlYXNlLHB1YmxpY19rZXk6cix0cmFjZV9pZDp0LG9yZ19pZDp2dChuKX07cmV0dXJuIG4uZW1pdCgiY3JlYXRlRHNjIixvKSxvfWZ1bmN0aW9uIEl0KHQsbil7Y29uc3QgZT1uLmdldFByb3BhZ2F0aW9uQ29udGV4dCgpO3JldHVybiBlLmRzY3x8QXQoZS50cmFjZUlkLHQpfWZ1bmN0aW9uIE90KHQpe2NvbnN0IG49cHQoKTtpZighbilyZXR1cm57fTtjb25zdCBlPUN0KHQpLHI9RXQoZSksbz1yLmRhdGEsaT1lLnNwYW5Db250ZXh0KCkudHJhY2VTdGF0ZSxzPWk/LmdldCgic2VudHJ5LnNhbXBsZV9yYXRlIik/P29bInNlbnRyeS5zYW1wbGVfcmF0ZSJdPz9vWyJzZW50cnkucHJldmlvdXNfdHJhY2Vfc2FtcGxlX3JhdGUiXTtmdW5jdGlvbiBjKHQpe3JldHVybiJudW1iZXIiIT10eXBlb2YgcyYmInN0cmluZyIhPXR5cGVvZiBzfHwodC5zYW1wbGVfcmF0ZT1gJHtzfWApLHR9Y29uc3QgdT1lLl9mcm96ZW5Ec2M7aWYodSlyZXR1cm4gYyh1KTtpZihmdW5jdGlvbih0KXtyZXR1cm4hIXQmJiEwPT09dFtSdF19KGUpJiYhanQobi5nZXRPcHRpb25zKCkpKXtjb25zdCB0PWR0KGUpLnNjb3BlO2lmKHQpcmV0dXJuIGMoey4uLkl0KG4sdCl9KX1jb25zdCBhPWk/LmdldCgic2VudHJ5LmRzYyIpLGY9YSYmZ3QoYSk7aWYoZilyZXR1cm4gYyhmKTtjb25zdCBoPUF0KHQuc3BhbkNvbnRleHQoKS50cmFjZUlkLG4pLHA9b1sic2VudHJ5LnNvdXJjZSJdPz9vWyJzZW50cnkuc3Bhbi5zb3VyY2UiXSxkPXIuZGVzY3JpcHRpb247cmV0dXJuInVybCIhPT1wJiZkJiYoaC50cmFuc2FjdGlvbj1kKSxqdCgpJiYoaC5zYW1wbGVkPVN0cmluZyhmdW5jdGlvbih0KXtjb25zdHt0cmFjZUZsYWdzOm59PXQuc3BhbkNvbnRleHQoKTtyZXR1cm4gMT09PW59KGUpKSxoLnNhbXBsZV9yYW5kPWk/LmdldCgic2VudHJ5LnNhbXBsZV9yYW5kIik/P2R0KGUpLnNjb3BlPy5nZXRQcm9wYWdhdGlvbkNvbnRleHQoKS5zYW1wbGVSYW5kLnRvU3RyaW5nKCkpLGMoaCksbi5lbWl0KCJjcmVhdGVEc2MiLGgsZSksaH1mdW5jdGlvbiBUdCh0LG49W10pe3JldHVyblt0LG5dfWZ1bmN0aW9uIGt0KHQsbil7Y29uc3QgZT10WzFdO2Zvcihjb25zdCB0IG9mIGUpe2lmKG4odCx0WzBdLnR5cGUpKXJldHVybiEwfXJldHVybiExfWZ1bmN0aW9uIFB0KHQpe2NvbnN0IG49ZyhwKTtyZXR1cm4gbi5lbmNvZGVQb2x5ZmlsbD9uLmVuY29kZVBvbHlmaWxsKHQpOihuZXcgVGV4dEVuY29kZXIpLmVuY29kZSh0KX1mdW5jdGlvbiBEdCh0KXtjb25zdFtuLGVdPXQ7bGV0IHI9SlNPTi5zdHJpbmdpZnkobik7ZnVuY3Rpb24gbyh0KXsic3RyaW5nIj09dHlwZW9mIHI/cj0ic3RyaW5nIj09dHlwZW9mIHQ/cit0OltQdChyKSx0XTpyLnB1c2goInN0cmluZyI9PXR5cGVvZiB0P1B0KHQpOnQpfWZvcihjb25zdCB0IG9mIGUpe2NvbnN0W24sZV09dDtpZihvKGBcbiR7SlNPTi5zdHJpbmdpZnkobil9XG5gKSwic3RyaW5nIj09dHlwZW9mIGV8fGUgaW5zdGFuY2VvZiBVaW50OEFycmF5KW8oZSk7ZWxzZXtsZXQgdDt0cnl7dD1KU09OLnN0cmluZ2lmeShlKX1jYXRjaHt0PUpTT04uc3RyaW5naWZ5KEIoZSkpfW8odCl9fXJldHVybiJzdHJpbmciPT10eXBlb2Ygcj9yOmZ1bmN0aW9uKHQpe2NvbnN0IG49dC5yZWR1Y2UoKHQsbik9PnQrbi5sZW5ndGgsMCksZT1uZXcgVWludDhBcnJheShuKTtsZXQgcj0wO2Zvcihjb25zdCBuIG9mIHQpZS5zZXQobixyKSxyKz1uLmxlbmd0aDtyZXR1cm4gZX0ocil9Y29uc3QgVXQ9e3Nlc3Npb25zOiJzZXNzaW9uIixldmVudDoiZXJyb3IiLGNsaWVudF9yZXBvcnQ6ImludGVybmFsIix1c2VyX3JlcG9ydDoiZGVmYXVsdCIscHJvZmlsZV9jaHVuazoicHJvZmlsZSIscmVwbGF5X2V2ZW50OiJyZXBsYXkiLHJlcGxheV9yZWNvcmRpbmc6InJlcGxheSIsY2hlY2tfaW46Im1vbml0b3IiLHJhd19zZWN1cml0eToic2VjdXJpdHkiLGxvZzoibG9nX2l0ZW0iLHRyYWNlX21ldHJpYzoibWV0cmljIn07ZnVuY3Rpb24gQnQodCl7cmV0dXJuIGZ1bmN0aW9uKHQpe3JldHVybiB0IGluIFV0fSh0KT9VdFt0XTp0fWZ1bmN0aW9uIEx0KHQpe2lmKCF0Py5zZGspcmV0dXJuO2NvbnN0e25hbWU6bix2ZXJzaW9uOmV9PXQuc2RrO3JldHVybntuYW1lOm4sdmVyc2lvbjplfX1mdW5jdGlvbiBNdCh0LG4sZSxyKXtjb25zdCBvPUx0KGUpLGk9dC50eXBlJiYicmVwbGF5X2V2ZW50IiE9PXQudHlwZT90LnR5cGU6ImV2ZW50IjshZnVuY3Rpb24odCxuKXtpZighbilyZXR1cm4gdDtjb25zdCBlPXQuc2RrfHx7fTt0LnNkaz17Li4uZSxuYW1lOmUubmFtZXx8bi5uYW1lLHZlcnNpb246ZS52ZXJzaW9ufHxuLnZlcnNpb24saW50ZWdyYXRpb25zOlsuLi50LnNkaz8uaW50ZWdyYXRpb25zfHxbXSwuLi5uLmludGVncmF0aW9uc3x8W11dLHBhY2thZ2VzOlsuLi50LnNkaz8ucGFja2FnZXN8fFtdLC4uLm4ucGFja2FnZXN8fFtdXSxzZXR0aW5nczp0LnNkaz8uc2V0dGluZ3N8fG4uc2V0dGluZ3M/ey4uLnQuc2RrPy5zZXR0aW5ncywuLi5uLnNldHRpbmdzfTp2b2lkIDB9fSh0LGU/LnNkayk7Y29uc3Qgcz1mdW5jdGlvbih0LG4sZSxyKXtjb25zdCBvPXQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhPy5keW5hbWljU2FtcGxpbmdDb250ZXh0O3JldHVybntldmVudF9pZDp0LmV2ZW50X2lkLHNlbnRfYXQ6bmV3IERhdGUoUCgpKS50b0lTT1N0cmluZygpLC4uLm4mJntzZGs6bn0sLi4uISFlJiZyJiZ7ZHNuOmJ0KHIpfSwuLi5vJiZ7dHJhY2U6b319fSh0LG8scixuKTtkZWxldGUgdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE7cmV0dXJuIFR0KHMsW1t7dHlwZTppfSx0XV0pfWNvbnN0IHp0PSJfX1NFTlRSWV9TVVBQUkVTU19UUkFDSU5HX18iO2Z1bmN0aW9uIEZ0KHQpe2NvbnN0IG49aHQobCgpKTtyZXR1cm4gbi5zdXBwcmVzc1RyYWNpbmc/bi5zdXBwcmVzc1RyYWNpbmcodCk6ZnVuY3Rpb24oLi4udCl7Y29uc3Qgbj1odChsKCkpO2lmKDI9PT10Lmxlbmd0aCl7Y29uc3RbZSxyXT10O3JldHVybiBlP24ud2l0aFNldFNjb3BlKGUscik6bi53aXRoU2NvcGUocil9cmV0dXJuIG4ud2l0aFNjb3BlKHRbMF0pfShuPT57bi5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1t6dF06ITB9KTtjb25zdCBlPXQoKTtyZXR1cm4gbi5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1t6dF06dm9pZCAwfSksZX0pfWZ1bmN0aW9uIEd0KHQsbil7Y29uc3R7ZmluZ2VycHJpbnQ6ZSxzcGFuOnIsYnJlYWRjcnVtYnM6byxzZGtQcm9jZXNzaW5nTWV0YWRhdGE6aX09bjshZnVuY3Rpb24odCxuKXtjb25zdHtleHRyYTplLHRhZ3M6cix1c2VyOm8sY29udGV4dHM6aSxsZXZlbDpzLHRyYW5zYWN0aW9uTmFtZTpjfT1uO09iamVjdC5rZXlzKGUpLmxlbmd0aCYmKHQuZXh0cmE9ey4uLmUsLi4udC5leHRyYX0pO09iamVjdC5rZXlzKHIpLmxlbmd0aCYmKHQudGFncz17Li4uciwuLi50LnRhZ3N9KTtPYmplY3Qua2V5cyhvKS5sZW5ndGgmJih0LnVzZXI9ey4uLm8sLi4udC51c2VyfSk7T2JqZWN0LmtleXMoaSkubGVuZ3RoJiYodC5jb250ZXh0cz17Li4uaSwuLi50LmNvbnRleHRzfSk7cyYmKHQubGV2ZWw9cyk7YyYmInRyYW5zYWN0aW9uIiE9PXQudHlwZSYmKHQudHJhbnNhY3Rpb249Yyl9KHQsbiksciYmZnVuY3Rpb24odCxuKXt0LmNvbnRleHRzPXt0cmFjZTpfdChuKSwuLi50LmNvbnRleHRzfSx0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YT17ZHluYW1pY1NhbXBsaW5nQ29udGV4dDpPdChuKSwuLi50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YX07Y29uc3QgZT1DdChuKSxyPUV0KGUpLmRlc2NyaXB0aW9uO3ImJiF0LnRyYW5zYWN0aW9uJiYidHJhbnNhY3Rpb24iPT09dC50eXBlJiYodC50cmFuc2FjdGlvbj1yKX0odCxyKSxmdW5jdGlvbih0LG4pe3QuZmluZ2VycHJpbnQ9dC5maW5nZXJwcmludD9BcnJheS5pc0FycmF5KHQuZmluZ2VycHJpbnQpP3QuZmluZ2VycHJpbnQ6W3QuZmluZ2VycHJpbnRdOltdLG4mJih0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQuY29uY2F0KG4pKTt0LmZpbmdlcnByaW50Lmxlbmd0aHx8ZGVsZXRlIHQuZmluZ2VycHJpbnR9KHQsZSksZnVuY3Rpb24odCxuKXtjb25zdCBlPVsuLi50LmJyZWFkY3J1bWJzfHxbXSwuLi5uXTt0LmJyZWFkY3J1bWJzPWUubGVuZ3RoP2U6dm9pZCAwfSh0LG8pLGZ1bmN0aW9uKHQsbil7dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9ey4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhLC4uLm59fSh0LGkpfWNsYXNzIEp0e2NvbnN0cnVjdG9yKHQpe3RoaXMuTD0wLHRoaXMuTT1bXSx0aGlzLkYodCl9dGhlbih0LG4pe3JldHVybiBuZXcgSnQoKGUscik9Pnt0aGlzLk0ucHVzaChbITEsbj0+e2lmKHQpdHJ5e2UodChuKSl9Y2F0Y2godCl7cih0KX1lbHNlIGUobil9LHQ9PntpZihuKXRyeXtlKG4odCkpfWNhdGNoKHQpe3IodCl9ZWxzZSByKHQpfV0pLHRoaXMuRygpfSl9Y2F0Y2godCl7cmV0dXJuIHRoaXMudGhlbih0PT50LHQpfWZpbmFsbHkodCl7cmV0dXJuIG5ldyBKdCgobixlKT0+e2xldCByLG87cmV0dXJuIHRoaXMudGhlbihuPT57bz0hMSxyPW4sdCYmdCgpfSxuPT57bz0hMCxyPW4sdCYmdCgpfSkudGhlbigoKT0+e28/ZShyKTpuKHIpfSl9KX1HKCl7aWYoMD09PXRoaXMuTClyZXR1cm47Y29uc3QgdD10aGlzLk0uc2xpY2UoKTt0aGlzLk09W10sdC5mb3JFYWNoKHQ9Pnt0WzBdfHwoMT09PXRoaXMuTCYmdFsxXSh0aGlzLkopLDI9PT10aGlzLkwmJnRbMl0odGhpcy5KKSx0WzBdPSEwKX0pfUYodCl7Y29uc3Qgbj0odCxuKT0+ezA9PT10aGlzLkwmJihqKG4pP24udGhlbihlLHIpOih0aGlzLkw9dCx0aGlzLko9bix0aGlzLkcoKSkpfSxlPXQ9PntuKDEsdCl9LHI9dD0+e24oMix0KX07dHJ5e3QoZSxyKX1jYXRjaCh0KXtyKHQpfX19Y29uc3QgV3Q9U3ltYm9sLmZvcigiU2VudHJ5QnVmZmVyRnVsbEVycm9yIik7ZnVuY3Rpb24gWXQodD0xMDApe2NvbnN0IG49bmV3IFNldDtmdW5jdGlvbiBlKHQpe24uZGVsZXRlKHQpfXJldHVybntnZXQgJCgpe3JldHVybiBBcnJheS5mcm9tKG4pfSxhZGQ6ZnVuY3Rpb24ocil7aWYoIShuLnNpemU8dCkpcmV0dXJuIG89V3QsbmV3IEp0KCh0LG4pPT57bihvKX0pO3ZhciBvO2NvbnN0IGk9cigpO3JldHVybiBuLmFkZChpKSxpLnRoZW4oKCk9PmUoaSksKCk9PmUoaSkpLGl9LGRyYWluOmZ1bmN0aW9uKHQpe2lmKCFuLnNpemUpcmV0dXJuIGU9ITAsbmV3IEp0KHQ9Pnt0KGUpfSk7dmFyIGU7Y29uc3Qgcj1Qcm9taXNlLmFsbFNldHRsZWQoQXJyYXkuZnJvbShuKSkudGhlbigoKT0+ITApO2lmKCF0KXJldHVybiByO2NvbnN0IG89W3IsbmV3IFByb21pc2Uobj0+e3JldHVybiJvYmplY3QiPT10eXBlb2YoZT1zZXRUaW1lb3V0KCgpPT5uKCExKSx0KSkmJiJmdW5jdGlvbiI9PXR5cGVvZiBlLnVucmVmJiZlLnVucmVmKCksZTt2YXIgZX0pXTtyZXR1cm4gUHJvbWlzZS5yYWNlKG8pfX19ZnVuY3Rpb24gSHQodCx7c3RhdHVzQ29kZTpuLGhlYWRlcnM6ZX0scj1QKCkpe2NvbnN0IG89ey4uLnR9LGk9ZT8uWyJ4LXNlbnRyeS1yYXRlLWxpbWl0cyJdLHM9ZT8uWyJyZXRyeS1hZnRlciJdO2lmKGkpZm9yKGNvbnN0IHQgb2YgaS50cmltKCkuc3BsaXQoIiwiKSl7Y29uc3RbbixlLCwsaV09dC5zcGxpdCgiOiIsNSkscz1wYXJzZUludChuLDEwKSxjPTFlMyooaXNOYU4ocyk/NjA6cyk7aWYoZSlmb3IoY29uc3QgdCBvZiBlLnNwbGl0KCI7IikpIm1ldHJpY19idWNrZXQiPT09dCYmaSYmIWkuc3BsaXQoIjsiKS5pbmNsdWRlcygiY3VzdG9tIil8fChvW3RdPXIrYyk7ZWxzZSBvLmFsbD1yK2N9ZWxzZSBzP28uYWxsPXIrZnVuY3Rpb24odCxuPVAoKSl7Y29uc3QgZT1wYXJzZUludChgJHt0fWAsMTApO2lmKCFpc05hTihlKSlyZXR1cm4gMWUzKmU7Y29uc3Qgcj1EYXRlLnBhcnNlKGAke3R9YCk7cmV0dXJuIGlzTmFOKHIpPzZlNDpyLW59KHMscik6NDI5PT09biYmKG8uYWxsPXIrNmU0KTtyZXR1cm4gb31mdW5jdGlvbiBLdCh0LG4sZT1ZdCh0LmJ1ZmZlclNpemV8fDY0KSl7bGV0IHI9e307cmV0dXJue3NlbmQ6ZnVuY3Rpb24odCl7Y29uc3Qgbz1bXTtpZihrdCh0LCh0LG4pPT57Y29uc3QgZT1CdChuKTsoZnVuY3Rpb24odCxuLGU9UCgpKXtyZXR1cm4gZnVuY3Rpb24odCxuKXtyZXR1cm4gdFtuXXx8dC5hbGx8fDB9KHQsbik+ZX0pKHIsZSl8fG8ucHVzaCh0KX0pLDA9PT1vLmxlbmd0aClyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtjb25zdCBpPVR0KHRbMF0sbykscz10PT57IWZ1bmN0aW9uKHQsbil7cmV0dXJuIGt0KHQsKHQsZSk9Pm4uaW5jbHVkZXMoZSkpfShpLFsiY2xpZW50X3JlcG9ydCJdKT9rdChpLCh0LG4pPT57fSk6aCYmdy53YXJuKGBEcm9wcGluZyBjbGllbnQgcmVwb3J0LiBXaWxsIG5vdCBzZW5kIG91dGNvbWVzIChyZWFzb246ICR7dH0pLmApfTtyZXR1cm4gZS5hZGQoKCk9Pm4oe2JvZHk6RHQoaSl9KS50aGVuKHQ9PjQxMz09PXQuc3RhdHVzQ29kZT8oaCYmdy5lcnJvcigiU2VudHJ5IHJlc3BvbmRlZCB3aXRoIHN0YXR1cyBjb2RlIDQxMy4gRW52ZWxvcGUgd2FzIGRpc2NhcmRlZCBkdWUgdG8gZXhjZWVkaW5nIHNpemUgbGltaXRzLiIpLHMoInNlbmRfZXJyb3IiKSx0KTooaCYmdm9pZCAwIT09dC5zdGF0dXNDb2RlJiYodC5zdGF0dXNDb2RlPDIwMHx8dC5zdGF0dXNDb2RlPj0zMDApJiZ3Lndhcm4oYFNlbnRyeSByZXNwb25kZWQgd2l0aCBzdGF0dXMgY29kZSAke3Quc3RhdHVzQ29kZX0gdG8gc2VudCBldmVudC5gKSxyPUh0KHIsdCksdCksdD0+e3Rocm93IHMoIm5ldHdvcmtfZXJyb3IiKSxoJiZ3LmVycm9yKCJFbmNvdW50ZXJlZCBlcnJvciBydW5uaW5nIHRyYW5zcG9ydCByZXF1ZXN0OiIsdCksdH0pKS50aGVuKHQ9PnQsdD0+e2lmKHQ9PT1XdClyZXR1cm4gaCYmdy5lcnJvcigiU2tpcHBlZCBzZW5kaW5nIGV2ZW50IGJlY2F1c2UgYnVmZmVyIGlzIGZ1bGwuIikscygicXVldWVfb3ZlcmZsb3ciKSxQcm9taXNlLnJlc29sdmUoe30pO3Rocm93IHR9KX0sZmx1c2g6dD0+ZS5kcmFpbih0KX19Y29uc3QgWnQ9L14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvO2Z1bmN0aW9uIHF0KHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7Y29uc3Qgbj10Lmxlbmd0aD4xMDI0P2A8dHJ1bmNhdGVkPiR7dC5zbGljZSgtMTAyNCl9YDp0LGU9WnQuZXhlYyhuKTtyZXR1cm4gZT9lLnNsaWNlKDEpOltdfSh0KSxlPW5bMF18fCIiO2xldCByPW5bMV07cmV0dXJuIGV8fHI/KHImJihyPXIuc2xpY2UoMCxyLmxlbmd0aC0xKSksZStyKToiLiJ9ZnVuY3Rpb24gVnQodCxuPSExKXtyZXR1cm4hKG58fHQmJiF0LnN0YXJ0c1dpdGgoIi8iKSYmIXQubWF0Y2goL15bQS1aXTovKSYmIXQuc3RhcnRzV2l0aCgiLiIpJiYhdC5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSkmJnZvaWQgMCE9PXQmJiF0LmluY2x1ZGVzKCJub2RlX21vZHVsZXMvIil9dmFyIFF0O2NvbnN0IFh0PVN5bWJvbCgiQWdlbnRCYXNlSW50ZXJuYWxTdGF0ZSIpO2NsYXNzIHRuIGV4dGVuZHMoUXQ9aS5BZ2VudCxRdCl7Y29uc3RydWN0b3IodCl7c3VwZXIodCksdGhpc1tYdF09e319aXNTZWN1cmVFbmRwb2ludCh0KXtpZih0KXtpZigiYm9vbGVhbiI9PXR5cGVvZiB0LnNlY3VyZUVuZHBvaW50KXJldHVybiB0LnNlY3VyZUVuZHBvaW50O2lmKCJzdHJpbmciPT10eXBlb2YgdC5wcm90b2NvbClyZXR1cm4iaHR0cHM6Ij09PXQucHJvdG9jb2x9Y29uc3R7c3RhY2s6bn09bmV3IEVycm9yO3JldHVybiJzdHJpbmciPT10eXBlb2YgbiYmbi5zcGxpdCgiXG4iKS5zb21lKHQ9Pi0xIT09dC5pbmRleE9mKCIoaHR0cHMuanM6Iil8fC0xIT09dC5pbmRleE9mKCJub2RlOmh0dHBzOiIpKX1jcmVhdGVTb2NrZXQodCxuLGUpe2NvbnN0IHI9ey4uLm4sc2VjdXJlRW5kcG9pbnQ6dGhpcy5pc1NlY3VyZUVuZHBvaW50KG4pfTtQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpPT50aGlzLmNvbm5lY3QodCxyKSkudGhlbihvPT57aWYobyBpbnN0YW5jZW9mIGkuQWdlbnQpcmV0dXJuIG8uYWRkUmVxdWVzdCh0LHIpO3RoaXNbWHRdLmN1cnJlbnRTb2NrZXQ9byxzdXBlci5jcmVhdGVTb2NrZXQodCxuLGUpfSxlKX1jcmVhdGVDb25uZWN0aW9uKCl7Y29uc3QgdD10aGlzW1h0XS5jdXJyZW50U29ja2V0O2lmKHRoaXNbWHRdLmN1cnJlbnRTb2NrZXQ9dm9pZCAwLCF0KXRocm93IG5ldyBFcnJvcigiTm8gc29ja2V0IHdhcyByZXR1cm5lZCBpbiB0aGUgYGNvbm5lY3QoKWAgZnVuY3Rpb24iKTtyZXR1cm4gdH1nZXQgZGVmYXVsdFBvcnQoKXtyZXR1cm4gdGhpc1tYdF0uZGVmYXVsdFBvcnQ/PygiaHR0cHM6Ij09PXRoaXMucHJvdG9jb2w/NDQzOjgwKX1zZXQgZGVmYXVsdFBvcnQodCl7dGhpc1tYdF0mJih0aGlzW1h0XS5kZWZhdWx0UG9ydD10KX1nZXQgcHJvdG9jb2woKXtyZXR1cm4gdGhpc1tYdF0ucHJvdG9jb2w/Pyh0aGlzLmlzU2VjdXJlRW5kcG9pbnQoKT8iaHR0cHM6IjoiaHR0cDoiKX1zZXQgcHJvdG9jb2wodCl7dGhpc1tYdF0mJih0aGlzW1h0XS5wcm90b2NvbD10KX19ZnVuY3Rpb24gbm4oLi4udCl7dy5sb2coIltodHRwcy1wcm94eS1hZ2VudDpwYXJzZS1wcm94eS1yZXNwb25zZV0iLC4uLnQpfWZ1bmN0aW9uIGVuKHQpe3JldHVybiBuZXcgUHJvbWlzZSgobixlKT0+e2xldCByPTA7Y29uc3Qgbz1bXTtmdW5jdGlvbiBpKCl7Y29uc3QgYz10LnJlYWQoKTtjP2Z1bmN0aW9uKGMpe28ucHVzaChjKSxyKz1jLmxlbmd0aDtjb25zdCB1PUJ1ZmZlci5jb25jYXQobyxyKSxhPXUuaW5kZXhPZigiXHJcblxyXG4iKTtpZigtMT09PWEpcmV0dXJuIG5uKCJoYXZlIG5vdCByZWNlaXZlZCBlbmQgb2YgSFRUUCBoZWFkZXJzIHlldC4uLiIpLHZvaWQgaSgpO2NvbnN0IGY9dS5zdWJhcnJheSgwLGEpLnRvU3RyaW5nKCJhc2NpaSIpLnNwbGl0KCJcclxuIiksaD1mLnNoaWZ0KCk7aWYoIWgpcmV0dXJuIHQuZGVzdHJveSgpLGUobmV3IEVycm9yKCJObyBoZWFkZXIgcmVjZWl2ZWQgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlIikpO2NvbnN0IHA9aC5zcGxpdCgiICIpLGQ9KyhwWzFdfHwwKSxsPXAuc2xpY2UoMikuam9pbigiICIpLGc9e307Zm9yKGNvbnN0IG4gb2YgZil7aWYoIW4pY29udGludWU7Y29uc3Qgcj1uLmluZGV4T2YoIjoiKTtpZigtMT09PXIpcmV0dXJuIHQuZGVzdHJveSgpLGUobmV3IEVycm9yKGBJbnZhbGlkIGhlYWRlciBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2U6ICIke259ImApKTtjb25zdCBvPW4uc2xpY2UoMCxyKS50b0xvd2VyQ2FzZSgpLGk9bi5zbGljZShyKzEpLnRyaW1TdGFydCgpLHM9Z1tvXTsic3RyaW5nIj09dHlwZW9mIHM/Z1tvXT1bcyxpXTpBcnJheS5pc0FycmF5KHMpP3MucHVzaChpKTpnW29dPWl9bm4oImdvdCBwcm94eSBzZXJ2ZXIgcmVzcG9uc2U6ICVvICVvIixoLGcpLHMoKSxuKHtjb25uZWN0OntzdGF0dXNDb2RlOmQsc3RhdHVzVGV4dDpsLGhlYWRlcnM6Z30sYnVmZmVyZWQ6dX0pfShjKTp0Lm9uY2UoInJlYWRhYmxlIixpKX1mdW5jdGlvbiBzKCl7dC5yZW1vdmVMaXN0ZW5lcigiZW5kIixjKSx0LnJlbW92ZUxpc3RlbmVyKCJlcnJvciIsdSksdC5yZW1vdmVMaXN0ZW5lcigicmVhZGFibGUiLGkpfWZ1bmN0aW9uIGMoKXtzKCksbm4oIm9uZW5kIiksZShuZXcgRXJyb3IoIlByb3h5IGNvbm5lY3Rpb24gZW5kZWQgYmVmb3JlIHJlY2VpdmluZyBDT05ORUNUIHJlc3BvbnNlIikpfWZ1bmN0aW9uIHUodCl7cygpLG5uKCJvbmVycm9yICVvIix0KSxlKHQpfXQub24oImVycm9yIix1KSx0Lm9uKCJlbmQiLGMpLGkoKX0pfWZ1bmN0aW9uIHJuKC4uLnQpe3cubG9nKCJbaHR0cHMtcHJveHktYWdlbnRdIiwuLi50KX1jbGFzcyBvbiBleHRlbmRzIHRue2NvbnN0cnVjdG9yKHQsbil7c3VwZXIobiksdGhpcy5vcHRpb25zPXt9LHRoaXMucHJveHk9InN0cmluZyI9PXR5cGVvZiB0P25ldyBVUkwodCk6dCx0aGlzLnByb3h5SGVhZGVycz1uPy5oZWFkZXJzPz97fSxybigiQ3JlYXRpbmcgbmV3IEh0dHBzUHJveHlBZ2VudCBpbnN0YW5jZTogJW8iLHRoaXMucHJveHkuaHJlZik7Y29uc3QgZT0odGhpcy5wcm94eS5ob3N0bmFtZXx8dGhpcy5wcm94eS5ob3N0KS5yZXBsYWNlKC9eXFt8XF0kL2csIiIpLHI9dGhpcy5wcm94eS5wb3J0P3BhcnNlSW50KHRoaXMucHJveHkucG9ydCwxMCk6Imh0dHBzOiI9PT10aGlzLnByb3h5LnByb3RvY29sPzQ0Mzo4MDt0aGlzLmNvbm5lY3RPcHRzPXtBTFBOUHJvdG9jb2xzOlsiaHR0cC8xLjEiXSwuLi5uP2NuKG4sImhlYWRlcnMiKTpudWxsLGhvc3Q6ZSxwb3J0OnJ9fWFzeW5jIGNvbm5lY3QodCxuKXtjb25zdHtwcm94eTplfT10aGlzO2lmKCFuLmhvc3QpdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gImhvc3QiIHByb3ZpZGVkJyk7bGV0IHI7aWYoImh0dHBzOiI9PT1lLnByb3RvY29sKXtybigiQ3JlYXRpbmcgYHRscy5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cyk7Y29uc3QgdD10aGlzLmNvbm5lY3RPcHRzLnNlcnZlcm5hbWV8fHRoaXMuY29ubmVjdE9wdHMuaG9zdDtyPWYuY29ubmVjdCh7Li4udGhpcy5jb25uZWN0T3B0cyxzZXJ2ZXJuYW1lOnQmJmEuaXNJUCh0KT92b2lkIDA6dH0pfWVsc2Ugcm4oIkNyZWF0aW5nIGBuZXQuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpLHI9YS5jb25uZWN0KHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IG89ImZ1bmN0aW9uIj09dHlwZW9mIHRoaXMucHJveHlIZWFkZXJzP3RoaXMucHJveHlIZWFkZXJzKCk6ey4uLnRoaXMucHJveHlIZWFkZXJzfSxpPWEuaXNJUHY2KG4uaG9zdCk/YFske24uaG9zdH1dYDpuLmhvc3Q7bGV0IHM9YENPTk5FQ1QgJHtpfToke24ucG9ydH0gSFRUUC8xLjFcclxuYDtpZihlLnVzZXJuYW1lfHxlLnBhc3N3b3JkKXtjb25zdCB0PWAke2RlY29kZVVSSUNvbXBvbmVudChlLnVzZXJuYW1lKX06JHtkZWNvZGVVUklDb21wb25lbnQoZS5wYXNzd29yZCl9YDtvWyJQcm94eS1BdXRob3JpemF0aW9uIl09YEJhc2ljICR7QnVmZmVyLmZyb20odCkudG9TdHJpbmcoImJhc2U2NCIpfWB9by5Ib3N0PWAke2l9OiR7bi5wb3J0fWAsb1siUHJveHktQ29ubmVjdGlvbiJdfHwob1siUHJveHktQ29ubmVjdGlvbiJdPXRoaXMua2VlcEFsaXZlPyJLZWVwLUFsaXZlIjoiY2xvc2UiKTtmb3IoY29uc3QgdCBvZiBPYmplY3Qua2V5cyhvKSlzKz1gJHt0fTogJHtvW3RdfVxyXG5gO2NvbnN0IGM9ZW4ocik7ci53cml0ZShgJHtzfVxyXG5gKTtjb25zdHtjb25uZWN0OnUsYnVmZmVyZWQ6aH09YXdhaXQgYztpZih0LmVtaXQoInByb3h5Q29ubmVjdCIsdSksdGhpcy5lbWl0KCJwcm94eUNvbm5lY3QiLHUsdCksMjAwPT09dS5zdGF0dXNDb2RlKXtpZih0Lm9uY2UoInNvY2tldCIsc24pLG4uc2VjdXJlRW5kcG9pbnQpe3JuKCJVcGdyYWRpbmcgc29ja2V0IGNvbm5lY3Rpb24gdG8gVExTIik7Y29uc3QgdD1uLnNlcnZlcm5hbWV8fG4uaG9zdDtyZXR1cm4gZi5jb25uZWN0KHsuLi5jbihuLCJob3N0IiwicGF0aCIsInBvcnQiKSxzb2NrZXQ6cixzZXJ2ZXJuYW1lOmEuaXNJUCh0KT92b2lkIDA6dH0pfXJldHVybiByfXIuZGVzdHJveSgpO2NvbnN0IHA9bmV3IGEuU29ja2V0KHt3cml0YWJsZTohMX0pO3JldHVybiBwLnJlYWRhYmxlPSEwLHQub25jZSgic29ja2V0Iix0PT57cm4oIlJlcGxheWluZyBwcm94eSBidWZmZXIgZm9yIGZhaWxlZCByZXF1ZXN0IiksdC5wdXNoKGgpLHQucHVzaChudWxsKX0pLHB9fWZ1bmN0aW9uIHNuKHQpe3QucmVzdW1lKCl9ZnVuY3Rpb24gY24odCwuLi5uKXtjb25zdCBlPXt9O2xldCByO2ZvcihyIGluIHQpbi5pbmNsdWRlcyhyKXx8KGVbcl09dFtyXSk7cmV0dXJuIGV9b24ucHJvdG9jb2xzPVsiaHR0cCIsImh0dHBzIl07ZnVuY3Rpb24gdW4odCl7cmV0dXJuIHQucmVwbGFjZSgvXltBLVpdOi8sIiIpLnJlcGxhY2UoL1xcL2csIi8iKX1jb25zdCBhbj1uO2xldCBmbixobj0wLHBuPXt9O2Z1bmN0aW9uIGRuKHQpe2FuLmRlYnVnJiZjb25zb2xlLmxvZyhgW0FOUiBXb3JrZXJdICR7dH1gKX12YXIgbG4sZ24sbW47Y29uc3QgeW49ZnVuY3Rpb24odCl7bGV0IG47dHJ5e249bmV3IFVSTCh0LnVybCl9Y2F0Y2gobil7cmV0dXJuIGIoKCk9Pntjb25zb2xlLndhcm4oIltAc2VudHJ5L25vZGVdOiBJbnZhbGlkIGRzbiBvciB0dW5uZWwgb3B0aW9uLCB3aWxsIG5vdCBzZW5kIGFueSBldmVudHMuIFRoZSB0dW5uZWwgb3B0aW9uIG11c3QgYmUgYSBmdWxsIFVSTCB3aGVuIHVzZWQuIil9KSxLdCh0LCgpPT5Qcm9taXNlLnJlc29sdmUoe30pKX1jb25zdCBlPSJodHRwczoiPT09bi5wcm90b2NvbCxyPWZ1bmN0aW9uKHQsbil7Y29uc3R7bm9fcHJveHk6ZX09cHJvY2Vzcy5lbnYscj1lPy5zcGxpdCgiLCIpLnNvbWUobj0+dC5ob3N0LmVuZHNXaXRoKG4pfHx0Lmhvc3RuYW1lLmVuZHNXaXRoKG4pKTtyZXR1cm4gcj92b2lkIDA6bn0obix0LnByb3h5fHwoZT9wcm9jZXNzLmVudi5odHRwc19wcm94eTp2b2lkIDApfHxwcm9jZXNzLmVudi5odHRwX3Byb3h5KSxvPWU/czppLGE9dm9pZCAwIT09dC5rZWVwQWxpdmUmJnQua2VlcEFsaXZlLGY9cj9uZXcgb24ocik6bmV3IG8uQWdlbnQoe2tlZXBBbGl2ZTphLG1heFNvY2tldHM6MzAsdGltZW91dDoyZTN9KSxoPWZ1bmN0aW9uKHQsbixlKXtjb25zdHtob3N0bmFtZTpyLHBhdGhuYW1lOm8scG9ydDppLHByb3RvY29sOnMsc2VhcmNoOmF9PW5ldyBVUkwodC51cmwpO3JldHVybiBmdW5jdGlvbihmKXtyZXR1cm4gbmV3IFByb21pc2UoKGgscCk9PntGdCgoKT0+e2xldCBkPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgYyh7cmVhZCgpe3RoaXMucHVzaCh0KSx0aGlzLnB1c2gobnVsbCl9fSl9KGYuYm9keSk7Y29uc3QgbD17Li4udC5oZWFkZXJzfTtmLmJvZHkubGVuZ3RoPjMyNzY4JiYobFsiY29udGVudC1lbmNvZGluZyJdPSJnemlwIixkPWQucGlwZSh1KCkpKTtjb25zdCBnPXIuc3RhcnRzV2l0aCgiWyIpLG09bi5yZXF1ZXN0KHttZXRob2Q6IlBPU1QiLGFnZW50OmUsaGVhZGVyczpsLGhvc3RuYW1lOmc/ci5zbGljZSgxLC0xKTpyLHBhdGg6YCR7b30ke2F9YCxwb3J0OmkscHJvdG9jb2w6cyxjYTp0LmNhQ2VydHN9LHQ9Pnt0Lm9uKCJkYXRhIiwoKT0+e30pLHQub24oImVuZCIsKCk9Pnt9KSx0LnNldEVuY29kaW5nKCJ1dGY4Iik7Y29uc3Qgbj10LmhlYWRlcnNbInJldHJ5LWFmdGVyIl0/P251bGwsZT10LmhlYWRlcnNbIngtc2VudHJ5LXJhdGUtbGltaXRzIl0/P251bGw7aCh7c3RhdHVzQ29kZTp0LnN0YXR1c0NvZGUsaGVhZGVyczp7InJldHJ5LWFmdGVyIjpuLCJ4LXNlbnRyeS1yYXRlLWxpbWl0cyI6QXJyYXkuaXNBcnJheShlKT9lWzBdfHxudWxsOmV9fSl9KTttLm9uKCJlcnJvciIscCksZC5waXBlKG0pfSl9KX19KHQsdC5odHRwTW9kdWxlPz9vLGYpO3JldHVybiBLdCh0LGgpfSh7dXJsOihsbj1hbi5kc24sZ249YW4udHVubmVsLG1uPWFuLnNka01ldGFkYXRhLnNkayxnbnx8YCR7ZnVuY3Rpb24odCl7cmV0dXJuYCR7ZnVuY3Rpb24odCl7Y29uc3Qgbj10LnByb3RvY29sP2Ake3QucHJvdG9jb2x9OmA6IiIsZT10LnBvcnQ/YDoke3QucG9ydH1gOiIiO3JldHVybmAke259Ly8ke3QuaG9zdH0ke2V9JHt0LnBhdGg/YC8ke3QucGF0aH1gOiIifS9hcGkvYH0odCl9JHt0LnByb2plY3RJZH0vZW52ZWxvcGUvYH0obG4pfT8ke2Z1bmN0aW9uKHQsbil7Y29uc3QgZT17c2VudHJ5X3ZlcnNpb246IjcifTtyZXR1cm4gdC5wdWJsaWNLZXkmJihlLnNlbnRyeV9rZXk9dC5wdWJsaWNLZXkpLG4mJihlLnNlbnRyeV9jbGllbnQ9YCR7bi5uYW1lfS8ke24udmVyc2lvbn1gKSxuZXcgVVJMU2VhcmNoUGFyYW1zKGUpLnRvU3RyaW5nKCl9KGxuLG1uKX1gKX0pO2FzeW5jIGZ1bmN0aW9uIGJuKCl7aWYoZm4pe2RuKCJTZW5kaW5nIGFibm9ybWFsIHNlc3Npb24iKSxLKGZuLHtzdGF0dXM6ImFibm9ybWFsIixhYm5vcm1hbF9tZWNoYW5pc206ImFucl9mb3JlZ3JvdW5kIixyZWxlYXNlOmFuLnJlbGVhc2UsZW52aXJvbm1lbnQ6YW4uZW52aXJvbm1lbnR9KTtjb25zdCB0PWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89THQoZSk7cmV0dXJuIFR0KHtzZW50X2F0Om5ldyBEYXRlKFAoKSkudG9JU09TdHJpbmcoKSwuLi5vJiZ7c2RrOm99LC4uLiEhciYmbiYme2RzbjpidChuKX19LFsiYWdncmVnYXRlcyJpbiB0P1t7dHlwZToic2Vzc2lvbnMifSx0XTpbe3R5cGU6InNlc3Npb24ifSx0LnRvSlNPTigpXV0pfShmbixhbi5kc24sYW4uc2RrTWV0YWRhdGEsYW4udHVubmVsKTtkbihKU09OLnN0cmluZ2lmeSh0KSksYXdhaXQgeW4uc2VuZCh0KTt0cnl7ZT8ucG9zdE1lc3NhZ2UoInNlc3Npb24tZW5kZWQiKX1jYXRjaHt9fX1mdW5jdGlvbiB2bih0KXtpZighdClyZXR1cm47Y29uc3Qgbj1mdW5jdGlvbih0KXtpZighdC5sZW5ndGgpcmV0dXJuW107Y29uc3Qgbj1BcnJheS5mcm9tKHQpO3JldHVybi9zZW50cnlXcmFwcGVkLy50ZXN0KEUobikuZnVuY3Rpb258fCIiKSYmbi5wb3AoKSxuLnJldmVyc2UoKSwkLnRlc3QoRShuKS5mdW5jdGlvbnx8IiIpJiYobi5wb3AoKSwkLnRlc3QoRShuKS5mdW5jdGlvbnx8IiIpJiZuLnBvcCgpKSxuLnNsaWNlKDAsNTApLm1hcCh0PT4oey4uLnQsZmlsZW5hbWU6dC5maWxlbmFtZXx8RShuKS5maWxlbmFtZSxmdW5jdGlvbjp0LmZ1bmN0aW9ufHwiPyJ9KSl9KHQpO2lmKGFuLmFwcFJvb3RQYXRoKWZvcihjb25zdCB0IG9mIG4pdC5maWxlbmFtZSYmKHQuZmlsZW5hbWU9TSh0LmZpbGVuYW1lLGFuLmFwcFJvb3RQYXRoKSk7cmV0dXJuIG59YXN5bmMgZnVuY3Rpb24gX24odCxuKXtpZihobj49YW4ubWF4QW5yRXZlbnRzKXJldHVybjtobis9MSxhd2FpdCBibigpLGRuKCJTZW5kaW5nIGV2ZW50Iik7Y29uc3QgZT17ZXZlbnRfaWQ6RygpLGNvbnRleHRzOmFuLmNvbnRleHRzLHJlbGVhc2U6YW4ucmVsZWFzZSxlbnZpcm9ubWVudDphbi5lbnZpcm9ubWVudCxkaXN0OmFuLmRpc3QscGxhdGZvcm06Im5vZGUiLGxldmVsOiJlcnJvciIsZXhjZXB0aW9uOnt2YWx1ZXM6W3t0eXBlOiJBcHBsaWNhdGlvbk5vdFJlc3BvbmRpbmciLHZhbHVlOmBBcHBsaWNhdGlvbiBOb3QgUmVzcG9uZGluZyBmb3IgYXQgbGVhc3QgJHthbi5hbnJUaHJlc2hvbGR9IG1zYCxzdGFja3RyYWNlOntmcmFtZXM6dm4odCl9LG1lY2hhbmlzbTp7dHlwZToiQU5SIn19XX0sdGFnczphbi5zdGF0aWNUYWdzfTtuJiZmdW5jdGlvbih0LG4pe2lmKEd0KHQsbiksIXQuY29udGV4dHM/LnRyYWNlKXtjb25zdHt0cmFjZUlkOmUscGFyZW50U3BhbklkOnIscHJvcGFnYXRpb25TcGFuSWQ6b309bi5wcm9wYWdhdGlvbkNvbnRleHQ7dC5jb250ZXh0cz17dHJhY2U6e3RyYWNlX2lkOmUsc3Bhbl9pZDpvfHxWKCkscGFyZW50X3NwYW5faWQ6cn0sLi4udC5jb250ZXh0c319fShlLG4pLGZ1bmN0aW9uKHQpe2lmKDA9PT1PYmplY3Qua2V5cyhwbikubGVuZ3RoKXJldHVybjtjb25zdCBuPWFuLmFwcFJvb3RQYXRoP3t9OnBuO2lmKGFuLmFwcFJvb3RQYXRoKWZvcihjb25zdFt0LGVdb2YgT2JqZWN0LmVudHJpZXMocG4pKW5bTSh0LGFuLmFwcFJvb3RQYXRoKV09ZTtjb25zdCBlPW5ldyBNYXA7Zm9yKGNvbnN0IHIgb2YgdC5leGNlcHRpb24/LnZhbHVlc3x8W10pZm9yKGNvbnN0IHQgb2Ygci5zdGFja3RyYWNlPy5mcmFtZXN8fFtdKXtjb25zdCByPXQuYWJzX3BhdGh8fHQuZmlsZW5hbWU7ciYmbltyXSYmZS5zZXQocixuW3JdKX1pZihlLnNpemU+MCl7Y29uc3Qgbj1bXTtmb3IoY29uc3RbdCxyXW9mIGUuZW50cmllcygpKW4ucHVzaCh7dHlwZToic291cmNlbWFwIixjb2RlX2ZpbGU6dCxkZWJ1Z19pZDpyfSk7dC5kZWJ1Z19tZXRhPXtpbWFnZXM6bn19fShlKTtjb25zdCByPU10KGUsYW4uZHNuLGFuLnNka01ldGFkYXRhLGFuLnR1bm5lbCk7ZG4oSlNPTi5zdHJpbmdpZnkocikpLGF3YWl0IHluLnNlbmQociksYXdhaXQgeW4uZmx1c2goMmUzKSxobj49YW4ubWF4QW5yRXZlbnRzJiZzZXRUaW1lb3V0KCgpPT57cHJvY2Vzcy5leGl0KDApfSw1ZTMpfWxldCBTbjtpZihkbigiU3RhcnRlZCIpLGFuLmNhcHR1cmVTdGFja1RyYWNlKXtkbigiQ29ubmVjdGluZyB0byBkZWJ1Z2dlciIpO2NvbnN0IG49bmV3IHQ7bi5jb25uZWN0VG9NYWluVGhyZWFkKCksZG4oIkNvbm5lY3RlZCB0byBkZWJ1Z2dlciIpO2NvbnN0IGU9bmV3IE1hcDtuLm9uKCJEZWJ1Z2dlci5zY3JpcHRQYXJzZWQiLHQ9PntlLnNldCh0LnBhcmFtcy5zY3JpcHRJZCx0LnBhcmFtcy51cmwpfSksbi5vbigiRGVidWdnZXIucGF1c2VkIix0PT57aWYoIm90aGVyIj09PXQucGFyYW1zLnJlYXNvbil0cnl7ZG4oIkRlYnVnZ2VyIHBhdXNlZCIpO2NvbnN0IGk9Wy4uLnQucGFyYW1zLmNhbGxGcmFtZXNdLHM9YW4uYXBwUm9vdFBhdGg/ZnVuY3Rpb24odD0ocHJvY2Vzcy5hcmd2WzFdP3F0KHByb2Nlc3MuYXJndlsxXSk6cHJvY2Vzcy5jd2QoKSksbj0iXFwiPT09byl7Y29uc3QgZT1uP3VuKHQpOnQ7cmV0dXJuIHQ9PntpZighdClyZXR1cm47Y29uc3Qgbz1uP3VuKHQpOnQ7bGV0e2RpcjppLGJhc2U6cyxleHQ6Y309ci5wYXJzZShvKTsiLmpzIiE9PWMmJiIubWpzIiE9PWMmJiIuY2pzIiE9PWN8fChzPXMuc2xpY2UoMCwtMSpjLmxlbmd0aCkpO2NvbnN0IHU9ZGVjb2RlVVJJQ29tcG9uZW50KHMpO2l8fChpPSIuIik7Y29uc3QgYT1pLmxhc3RJbmRleE9mKCIvbm9kZV9tb2R1bGVzIik7aWYoYT4tMSlyZXR1cm5gJHtpLnNsaWNlKGErMTQpLnJlcGxhY2UoL1wvL2csIi4iKX06JHt1fWA7aWYoaS5zdGFydHNXaXRoKGUpKXtjb25zdCB0PWkuc2xpY2UoZS5sZW5ndGgrMSkucmVwbGFjZSgvXC8vZywiLiIpO3JldHVybiB0P2Ake3R9OiR7dX1gOnV9cmV0dXJuIHV9fShhbi5hcHBSb290UGF0aCk6KCk9Pnt9LGM9aS5tYXAodD0+ZnVuY3Rpb24odCxuLGUpe2NvbnN0IHI9bj9uLnJlcGxhY2UoL15maWxlOlwvXC8vLCIiKTp2b2lkIDAsbz10LmxvY2F0aW9uLmNvbHVtbk51bWJlcj90LmxvY2F0aW9uLmNvbHVtbk51bWJlcisxOnZvaWQgMCxpPXQubG9jYXRpb24ubGluZU51bWJlcj90LmxvY2F0aW9uLmxpbmVOdW1iZXIrMTp2b2lkIDA7cmV0dXJue2ZpbGVuYW1lOnIsbW9kdWxlOmUociksZnVuY3Rpb246dC5mdW5jdGlvbk5hbWV8fCI/Iixjb2xubzpvLGxpbmVubzppLGluX2FwcDpyP1Z0KHIpOnZvaWQgMH19KHQsZS5nZXQodC5sb2NhdGlvbi5zY3JpcHRJZCkscykpLHU9c2V0VGltZW91dCgoKT0+e19uKGMpLnRoZW4obnVsbCwoKT0+e2RuKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuIil9KX0sNWUzKTtuLnBvc3QoIlJ1bnRpbWUuZXZhbHVhdGUiLHtleHByZXNzaW9uOiJnbG9iYWwuX19TRU5UUllfR0VUX1NDT1BFU19fKCk7IixzaWxlbnQ6ITAscmV0dXJuQnlWYWx1ZTohMH0sKHQsZSk9Pnt0JiZkbihgRXJyb3IgZXhlY3V0aW5nIHNjcmlwdDogJyR7dC5tZXNzYWdlfSdgKSxjbGVhclRpbWVvdXQodSk7Y29uc3Qgcj1lPy5yZXN1bHQ/ZS5yZXN1bHQudmFsdWU6dm9pZCAwO24ucG9zdCgiRGVidWdnZXIucmVzdW1lIiksbi5wb3N0KCJEZWJ1Z2dlci5kaXNhYmxlIiksX24oYyxyKS50aGVuKG51bGwsKCk9PntkbigiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSl9KX1jYXRjaCh0KXt0aHJvdyBuLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLG4ucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLHR9fSksU249KCk9Pnt0cnl7bi5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiLCgpPT57bi5wb3N0KCJEZWJ1Z2dlci5wYXVzZSIpfSl9Y2F0Y2h7fX19Y29uc3R7cG9sbDp3bn09ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz10KCk7bGV0IGk9ITEscz0hMDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCk9Pntjb25zdCB0PW8uZ2V0VGltZU1zKCk7ITE9PT1pJiZ0Pm4rZSYmKGk9ITAscyYmcigpKSx0PG4rZSYmKGk9ITEpfSwyMCkse3BvbGw6KCk9PntvLnJlc2V0KCl9LGVuYWJsZWQ6dD0+e3M9dH19fShmdW5jdGlvbigpe2xldCB0PXByb2Nlc3MuaHJ0aW1lKCk7cmV0dXJue2dldFRpbWVNczooKT0+e2NvbnN0W24sZV09cHJvY2Vzcy5ocnRpbWUodCk7cmV0dXJuIE1hdGguZmxvb3IoMWUzKm4rZS8xZTYpfSxyZXNldDooKT0+e3Q9cHJvY2Vzcy5ocnRpbWUoKX19fSxhbi5wb2xsSW50ZXJ2YWwsYW4uYW5yVGhyZXNob2xkLGZ1bmN0aW9uKCl7ZG4oIldhdGNoZG9nIHRpbWVvdXQiKSxTbj8oZG4oIlBhdXNpbmcgZGVidWdnZXIgdG8gY2FwdHVyZSBzdGFjayB0cmFjZSIpLFNuKCkpOihkbigiQ2FwdHVyaW5nIGV2ZW50IHdpdGhvdXQgYSBzdGFjayB0cmFjZSIpLF9uKCkudGhlbihudWxsLCgpPT57ZG4oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZCBvbiB3YXRjaGRvZyB0aW1lb3V0LiIpfSkpfSk7ZT8ub24oIm1lc3NhZ2UiLHQ9Pnt0LnNlc3Npb24mJihmbj1IKHQuc2Vzc2lvbikpLHQuZGVidWdJbWFnZXMmJihwbj10LmRlYnVnSW1hZ2VzKSx3bigpfSk7"; | ||
| const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZS1jb3JlIDEwLjY0LjAgKDU3MzZhMzgpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyB0fWZyb20ibm9kZTppbnNwZWN0b3IiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIG4scGFyZW50UG9ydCBhcyBlfWZyb20ibm9kZTp3b3JrZXJfdGhyZWFkcyI7aW1wb3J0e3Bvc2l4IGFzIHIsc2VwIGFzIG99ZnJvbSJub2RlOnBhdGgiO2ltcG9ydCphcyBpIGZyb20ibm9kZTpodHRwIjtpbXBvcnQqYXMgcyBmcm9tIm5vZGU6aHR0cHMiO2ltcG9ydHtSZWFkYWJsZSBhcyBjfWZyb20ibm9kZTpzdHJlYW0iO2ltcG9ydHtjcmVhdGVHemlwIGFzIHV9ZnJvbSJub2RlOnpsaWIiO2ltcG9ydCphcyBhIGZyb20ibm9kZTpuZXQiO2ltcG9ydCphcyBmIGZyb20ibm9kZTp0bHMiO2NvbnN0IGg9InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fLHA9Z2xvYmFsVGhpcyxkPSIxMC42NC4wIjtmdW5jdGlvbiBsKCl7cmV0dXJuIGcocCkscH1mdW5jdGlvbiBnKHQpe2NvbnN0IG49dC5fX1NFTlRSWV9fPXQuX19TRU5UUllfX3x8e307cmV0dXJuIG4udmVyc2lvbj1uLnZlcnNpb258fGQsbltkXT1uW2RdfHx7fX1mdW5jdGlvbiBtKHQsbixlPXApe2NvbnN0IHI9ZS5fX1NFTlRSWV9fPWUuX19TRU5UUllfX3x8e30sbz1yW2RdPXJbZF18fHt9O3JldHVybiBvW3RdfHwob1t0XT1uKCkpfWNvbnN0IHk9e307ZnVuY3Rpb24gYih0KXtpZighKCJjb25zb2xlImluIHApKXJldHVybiB0KCk7Y29uc3Qgbj1wLmNvbnNvbGUsZT17fSxyPU9iamVjdC5rZXlzKHkpO3IuZm9yRWFjaCh0PT57Y29uc3Qgcj15W3RdO2VbdF09blt0XSxuW3RdPXJ9KTt0cnl7cmV0dXJuIHQoKX1maW5hbGx5e3IuZm9yRWFjaCh0PT57blt0XT1lW3RdfSl9fWZ1bmN0aW9uIHYoKXtyZXR1cm4gUygpLmVuYWJsZWR9ZnVuY3Rpb24gXyh0LC4uLm4pe2gmJnYoKSYmYigoKT0+e3AuY29uc29sZVt0XShgU2VudHJ5IExvZ2dlciBbJHt0fV06YCwuLi5uKX0pfWZ1bmN0aW9uIFMoKXtyZXR1cm4gaD9tKCJsb2dnZXJTZXR0aW5ncyIsKCk9Pih7ZW5hYmxlZDohMX0pKTp7ZW5hYmxlZDohMX19Y29uc3Qgdz17ZW5hYmxlOmZ1bmN0aW9uKCl7UygpLmVuYWJsZWQ9ITB9LGRpc2FibGU6ZnVuY3Rpb24oKXtTKCkuZW5hYmxlZD0hMX0saXNFbmFibGVkOnYsbG9nOmZ1bmN0aW9uKC4uLnQpe18oImxvZyIsLi4udCl9LHdhcm46ZnVuY3Rpb24oLi4udCl7Xygid2FybiIsLi4udCl9LGVycm9yOmZ1bmN0aW9uKC4uLnQpe18oImVycm9yIiwuLi50KX19LCQ9L2NhcHR1cmVNZXNzYWdlfGNhcHR1cmVFeGNlcHRpb24vO2Z1bmN0aW9uIEUodCl7cmV0dXJuIHRbdC5sZW5ndGgtMV18fHt9fWNvbnN0IHg9Ijxhbm9ueW1vdXM+Ijtjb25zdCBOPU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7ZnVuY3Rpb24gQyh0LG4pe3JldHVybiBOLmNhbGwodCk9PT1gW29iamVjdCAke259XWB9ZnVuY3Rpb24gaih0KXtyZXR1cm4gQm9vbGVhbih0Py50aGVuJiYiZnVuY3Rpb24iPT10eXBlb2YgdC50aGVuKX1mdW5jdGlvbiBSKHQsbil7dHJ5e3JldHVybiB0IGluc3RhbmNlb2Ygbn1jYXRjaHtyZXR1cm4hMX19ZnVuY3Rpb24gQSh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2goTi5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBXZWJBc3NlbWJseS5FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBSKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uSSh0KX07aWYobj10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJlIobixFdmVudCkpe2NvbnN0e3R5cGU6bix0YXJnZXQ6ZSxjdXJyZW50VGFyZ2V0OnIsZGV0YWlsOm99PXQ7cmV0dXJue3R5cGU6bix0YXJnZXQ6ZSxjdXJyZW50VGFyZ2V0OnIsLi4ubz97ZGV0YWlsOm99Ont9LC4uLkkodCl9fXZhciBuO3JldHVybiB0fWZ1bmN0aW9uIEkodCl7cmV0dXJuIm9iamVjdCI9PXR5cGVvZiB0JiZudWxsIT09dD9PYmplY3QuZnJvbUVudHJpZXMoT2JqZWN0LmVudHJpZXModCkpOnt9fWxldCBPO2Z1bmN0aW9uIFQodCl7aWYodm9pZCAwIT09TylyZXR1cm4gTz9PKHQpOnQoKTtjb25zdCBuPVN5bWJvbC5mb3IoIl9fU0VOVFJZX1NBRkVfUkFORE9NX0lEX1dSQVBQRVJfXyIpLGU9cDtyZXR1cm4gbiBpbiBlJiYiZnVuY3Rpb24iPT10eXBlb2YgZVtuXT8oTz1lW25dLE8odCkpOihPPW51bGwsdCgpKX1mdW5jdGlvbiBrKCl7cmV0dXJuIFQoKCk9Pk1hdGgucmFuZG9tKCkpfWZ1bmN0aW9uIFAoKXtyZXR1cm4gVCgoKT0+RGF0ZS5ub3coKSl9Y29uc3QgRD1TeW1ib2wuZm9yKCJzZW50cnkuc2tpcE5vcm1hbGl6YXRpb24iKSxVPVN5bWJvbC5mb3IoInNlbnRyeS5vdmVycmlkZU5vcm1hbGl6YXRpb25EZXB0aCIpO2Z1bmN0aW9uIEIodCxuPTEwMCxlPTEvMCl7dHJ5e3JldHVybiBMKCIiLHQsbixlKX1jYXRjaCh0KXtyZXR1cm57RVJST1I6YCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke3R9KWB9fX1mdW5jdGlvbiBMKHQsbixlPTEvMCxyPTEvMCxvPWZ1bmN0aW9uKCl7Y29uc3QgdD1uZXcgV2Vha1NldDtmdW5jdGlvbiBuKG4pe3JldHVybiEhdC5oYXMobil8fCh0LmFkZChuKSwhMSl9ZnVuY3Rpb24gZShuKXt0LmRlbGV0ZShuKX1yZXR1cm5bbixlXX0oKSl7Y29uc3RbaSxzXT1vO2lmKG51bGw9PW58fFsiYm9vbGVhbiIsInN0cmluZyJdLmluY2x1ZGVzKHR5cGVvZiBuKXx8Im51bWJlciI9PXR5cGVvZiBuJiZOdW1iZXIuaXNGaW5pdGUobikpcmV0dXJuIG47Y29uc3QgYz1mdW5jdGlvbih0LG4pe3RyeXtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGdsb2JhbCYmbj09PWdsb2JhbClyZXR1cm4iW0dsb2JhbF0iO2lmKCJudW1iZXIiPT10eXBlb2YgbiYmIU51bWJlci5pc0Zpbml0ZShuKSlyZXR1cm5gWyR7bn1dYDtpZigiZnVuY3Rpb24iPT10eXBlb2YgbilyZXR1cm5gW0Z1bmN0aW9uOiAke2Z1bmN0aW9uKHQpe3RyeXtyZXR1cm4gdCYmImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQubmFtZXx8eH1jYXRjaHtyZXR1cm4geH19KG4pfV1gO2lmKCJzeW1ib2wiPT10eXBlb2YgbilyZXR1cm5gWyR7U3RyaW5nKG4pfV1gO2lmKCJiaWdpbnQiPT10eXBlb2YgbilyZXR1cm5gW0JpZ0ludDogJHtTdHJpbmcobil9XWA7Y29uc3QgdD1mdW5jdGlvbih0KXtjb25zdCBuPU9iamVjdC5nZXRQcm90b3R5cGVPZih0KTtyZXR1cm4gbj8uY29uc3RydWN0b3I/bi5jb25zdHJ1Y3Rvci5uYW1lOiJudWxsIHByb3RvdHlwZSJ9KG4pO3JldHVybmBbb2JqZWN0ICR7dH1dYH1jYXRjaCh0KXtyZXR1cm5gKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH19KDAsbik7aWYoIWMuc3RhcnRzV2l0aCgiW29iamVjdCAiKSlyZXR1cm4gYztpZihmdW5jdGlvbih0KXtyZXR1cm4gQm9vbGVhbih0W0RdKX0obikpcmV0dXJuIG47Y29uc3QgdT1mdW5jdGlvbih0KXtjb25zdCBuPXRbVV07cmV0dXJuIm51bWJlciI9PXR5cGVvZiBuP246dm9pZCAwfShuKSxhPXZvaWQgMCE9PXU/dTplO2lmKDA9PT1hKXJldHVybiBjLnJlcGxhY2UoIm9iamVjdCAiLCIiKTtpZihpKG4pKXJldHVybiJbQ2lyY3VsYXIgfl0iO2NvbnN0IGY9bjtpZihmJiYiZnVuY3Rpb24iPT10eXBlb2YgZi50b0pTT04pdHJ5e3JldHVybiBMKCIiLGYudG9KU09OKCksYS0xLHIsbyl9Y2F0Y2h7fWNvbnN0IGg9QXJyYXkuaXNBcnJheShuKT9bXTp7fTtsZXQgcD0wO2NvbnN0IGQ9QShuKTtmb3IoY29uc3QgdCBpbiBkKXtpZighT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGQsdCkpY29udGludWU7aWYocD49cil7aFt0XT0iW01heFByb3BlcnRpZXMgfl0iO2JyZWFrfWNvbnN0IG49ZFt0XTtoW3RdPUwodCxuLGEtMSxyLG8pLHArK31yZXR1cm4gcyhuKSxofWZ1bmN0aW9uIE0odCxuKXtjb25zdCBlPW4ucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL1t8XFx7fSgpW1xdXiQrKj8uXS9nLCJcXCQmIik7bGV0IHI9dDt0cnl7cj1kZWNvZGVVUkkodCl9Y2F0Y2h7fXJldHVybiByLnJlcGxhY2UoL1xcL2csIi8iKS5yZXBsYWNlKC93ZWJwYWNrOlwvPy9nLCIiKS5yZXBsYWNlKG5ldyBSZWdFeHAoYChmaWxlOi8vKT8vKiR7ZX0vKmAsImlnIiksImFwcDovLy8iKX1mdW5jdGlvbiB6KHQsbj0wKXtyZXR1cm4ic3RyaW5nIiE9dHlwZW9mIHR8fDA9PT1ufHx0Lmxlbmd0aDw9bj90OmAke3Quc2xpY2UoMCxuKX0uLi5gfWxldCBGO2Z1bmN0aW9uIEcodD1mdW5jdGlvbigpe2NvbnN0IHQ9cDtyZXR1cm4gdC5jcnlwdG98fHQubXNDcnlwdG99KCkpe3RyeXtpZih0Py5yYW5kb21VVUlEKXJldHVybiBUKCgpPT50LnJhbmRvbVVVSUQoKSkucmVwbGFjZSgvLS9nLCIiKX1jYXRjaHt9cmV0dXJuIEZ8fChGPSIxMDAwMDAwMDEwMDA0MDAwODAwMDEwMDAwMDAwMDAwMCIpLEYucmVwbGFjZSgvWzAxOF0vZyx0PT4odF4oMTYqaygpJjE1KT4+dC80KS50b1N0cmluZygxNikpfWZ1bmN0aW9uIEooKXtyZXR1cm4gUCgpLzFlM31sZXQgVztmdW5jdGlvbiBZKCl7cmV0dXJuKFc/PyhXPWZ1bmN0aW9uKCl7Y29uc3R7cGVyZm9ybWFuY2U6dH09cDtpZighdD8ubm93fHwhdC50aW1lT3JpZ2luKXJldHVybiBKO2NvbnN0IG49dC50aW1lT3JpZ2luO3JldHVybigpPT4obitUKCgpPT50Lm5vdygpKSkvMWUzfSgpKSkoKX1mdW5jdGlvbiBIKHQpe2NvbnN0IG49WSgpLGU9e3NpZDpHKCksaW5pdDohMCx0aW1lc3RhbXA6bixzdGFydGVkOm4sZHVyYXRpb246MCxzdGF0dXM6Im9rIixlcnJvcnM6MCxpZ25vcmVEdXJhdGlvbjohMSx0b0pTT046KCk9PmZ1bmN0aW9uKHQpe3JldHVybntzaWQ6YCR7dC5zaWR9YCxpbml0OnQuaW5pdCxzdGFydGVkOm5ldyBEYXRlKDFlMyp0LnN0YXJ0ZWQpLnRvSVNPU3RyaW5nKCksdGltZXN0YW1wOm5ldyBEYXRlKDFlMyp0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxzdGF0dXM6dC5zdGF0dXMsZXJyb3JzOnQuZXJyb3JzLGRpZDoibnVtYmVyIj09dHlwZW9mIHQuZGlkfHwic3RyaW5nIj09dHlwZW9mIHQuZGlkP2Ake3QuZGlkfWA6dm9pZCAwLGR1cmF0aW9uOnQuZHVyYXRpb24sYWJub3JtYWxfbWVjaGFuaXNtOnQuYWJub3JtYWxfbWVjaGFuaXNtLGF0dHJzOntyZWxlYXNlOnQucmVsZWFzZSxlbnZpcm9ubWVudDp0LmVudmlyb25tZW50LGlwX2FkZHJlc3M6dC5pcEFkZHJlc3MsdXNlcl9hZ2VudDp0LnVzZXJBZ2VudH19fShlKX07cmV0dXJuIHQmJksoZSx0KSxlfWZ1bmN0aW9uIEsodCxuPXt9KXtpZihuLnVzZXImJighdC5pcEFkZHJlc3MmJm4udXNlci5pcF9hZGRyZXNzJiYodC5pcEFkZHJlc3M9bi51c2VyLmlwX2FkZHJlc3MpLHQuZGlkfHxuLmRpZHx8KHQuZGlkPW4udXNlci5pZHx8bi51c2VyLmVtYWlsfHxuLnVzZXIudXNlcm5hbWUpKSx0LnRpbWVzdGFtcD1uLnRpbWVzdGFtcHx8WSgpLG4uYWJub3JtYWxfbWVjaGFuaXNtJiYodC5hYm5vcm1hbF9tZWNoYW5pc209bi5hYm5vcm1hbF9tZWNoYW5pc20pLG4uaWdub3JlRHVyYXRpb24mJih0Lmlnbm9yZUR1cmF0aW9uPW4uaWdub3JlRHVyYXRpb24pLG4uc2lkJiYodC5zaWQ9MzI9PT1uLnNpZC5sZW5ndGg/bi5zaWQ6RygpKSx2b2lkIDAhPT1uLmluaXQmJih0LmluaXQ9bi5pbml0KSwhdC5kaWQmJm4uZGlkJiYodC5kaWQ9YCR7bi5kaWR9YCksIm51bWJlciI9PXR5cGVvZiBuLnN0YXJ0ZWQmJih0LnN0YXJ0ZWQ9bi5zdGFydGVkKSx0Lmlnbm9yZUR1cmF0aW9uKXQuZHVyYXRpb249dm9pZCAwO2Vsc2UgaWYoIm51bWJlciI9PXR5cGVvZiBuLmR1cmF0aW9uKXQuZHVyYXRpb249bi5kdXJhdGlvbjtlbHNle2NvbnN0IG49dC50aW1lc3RhbXAtdC5zdGFydGVkO3QuZHVyYXRpb249bj49MD9uOjB9bi5yZWxlYXNlJiYodC5yZWxlYXNlPW4ucmVsZWFzZSksbi5lbnZpcm9ubWVudCYmKHQuZW52aXJvbm1lbnQ9bi5lbnZpcm9ubWVudCksIXQuaXBBZGRyZXNzJiZuLmlwQWRkcmVzcyYmKHQuaXBBZGRyZXNzPW4uaXBBZGRyZXNzKSwhdC51c2VyQWdlbnQmJm4udXNlckFnZW50JiYodC51c2VyQWdlbnQ9bi51c2VyQWdlbnQpLCJudW1iZXIiPT10eXBlb2Ygbi5lcnJvcnMmJih0LmVycm9ycz1uLmVycm9ycyksbi5zdGF0dXMmJih0LnN0YXR1cz1uLnN0YXR1cyl9ZnVuY3Rpb24gWih0LG4sZT0yKXtpZighbnx8Im9iamVjdCIhPXR5cGVvZiBufHxlPD0wKXJldHVybiBuO2lmKHQmJjA9PT1PYmplY3Qua2V5cyhuKS5sZW5ndGgpcmV0dXJuIHQ7Y29uc3Qgcj17Li4udH07Zm9yKGNvbnN0IHQgaW4gbilPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobix0KSYmKHJbdF09WihyW3RdLG5bdF0sZS0xKSk7cmV0dXJuIHJ9ZnVuY3Rpb24gcSgpe3JldHVybiBHKCl9ZnVuY3Rpb24gVigpe3JldHVybiBHKCkuc3Vic3RyaW5nKDE2KX1mdW5jdGlvbiBRKHQpe2lmKHQpe2lmKCJvYmplY3QiPT10eXBlb2YgdCYmImRlcmVmImluIHQmJiJmdW5jdGlvbiI9PXR5cGVvZiB0LmRlcmVmKXRyeXtyZXR1cm4gdC5kZXJlZigpfWNhdGNoe3JldHVybn1yZXR1cm4gdH19Y29uc3QgWD0iX3NlbnRyeVNwYW4iO2Z1bmN0aW9uIHR0KHQsbil7bj9mdW5jdGlvbih0LG4sZSl7dHJ5e09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LG4se3ZhbHVlOmUsd3JpdGFibGU6ITAsY29uZmlndXJhYmxlOiEwfSl9Y2F0Y2h7aCYmdy5sb2coYEZhaWxlZCB0byBhZGQgbm9uLWVudW1lcmFibGUgcHJvcGVydHkgIiR7U3RyaW5nKG4pfSIgdG8gb2JqZWN0YCx0KX19KHQsWCxmdW5jdGlvbih0KXt0cnl7Y29uc3Qgbj1wLldlYWtSZWY7aWYoImZ1bmN0aW9uIj09dHlwZW9mIG4pcmV0dXJuIG5ldyBuKHQpfWNhdGNoe31yZXR1cm4gdH0obikpOmRlbGV0ZSB0W1hdfWZ1bmN0aW9uIG50KHQpe3JldHVybiBRKHRbWF0pfWNsYXNzIGV0e2NvbnN0cnVjdG9yKCl7dGhpcy50PSExLHRoaXMubz1bXSx0aGlzLmk9W10sdGhpcy51PVtdLHRoaXMuaD1bXSx0aGlzLnA9e30sdGhpcy5sPXt9LHRoaXMubT17fSx0aGlzLnY9e30sdGhpcy5fPXt9LHRoaXMuUz17fSx0aGlzLk49e3RyYWNlSWQ6cSgpLHNhbXBsZVJhbmQ6aygpfX1jbG9uZSgpe2NvbnN0IHQ9bmV3IGV0O3JldHVybiB0LnU9Wy4uLnRoaXMudV0sdC5sPXsuLi50aGlzLmx9LHQubT17Li4udGhpcy5tfSx0LnY9ey4uLnRoaXMudn0sdC5fPXsuLi50aGlzLl99LHRoaXMuXy5mbGFncyYmKHQuXy5mbGFncz17dmFsdWVzOlsuLi50aGlzLl8uZmxhZ3MudmFsdWVzXX0pLHQucD10aGlzLnAsdC5DPXRoaXMuQyx0Lmo9dGhpcy5qLHQuUj10aGlzLlIsdC5BPXRoaXMuQSx0Lmk9Wy4uLnRoaXMuaV0sdC5oPVsuLi50aGlzLmhdLHQuUz17Li4udGhpcy5TfSx0Lk49ey4uLnRoaXMuTn0sdC5JPXRoaXMuSSx0Lk89dGhpcy5PLHQuVD10aGlzLlQsdHQodCxudCh0aGlzKSksdH1zZXRDbGllbnQodCl7dGhpcy5JPXR9c2V0TGFzdEV2ZW50SWQodCl7dGhpcy5PPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuSX1sYXN0RXZlbnRJZCgpe3JldHVybiB0aGlzLk99YWRkU2NvcGVMaXN0ZW5lcih0KXt0aGlzLm8ucHVzaCh0KX1hZGRFdmVudFByb2Nlc3Nvcih0KXtyZXR1cm4gdGhpcy5pLnB1c2godCksdGhpc31zZXRVc2VyKHQpe3JldHVybiB0aGlzLnA9dHx8e2VtYWlsOnZvaWQgMCxpZDp2b2lkIDAsaXBfYWRkcmVzczp2b2lkIDAsdXNlcm5hbWU6dm9pZCAwfSx0aGlzLmomJksodGhpcy5qLHt1c2VyOnR9KSx0aGlzLmsoKSx0aGlzfWdldFVzZXIoKXtyZXR1cm4gdGhpcy5wfXNldENvbnZlcnNhdGlvbklkKHQpe3JldHVybiB0aGlzLlQ9dHx8dm9pZCAwLHRoaXMuaygpLHRoaXN9c2V0VGFncyh0KXtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4udH0sdGhpcy5rKCksdGhpc31zZXRUYWcodCxuKXtyZXR1cm4gdGhpcy5zZXRUYWdzKHtbdF06bn0pfXNldEF0dHJpYnV0ZXModCl7cmV0dXJuIHRoaXMubT17Li4udGhpcy5tLC4uLnR9LHRoaXMuaygpLHRoaXN9c2V0QXR0cmlidXRlKHQsbil7cmV0dXJuIHRoaXMuc2V0QXR0cmlidXRlcyh7W3RdOm59KX1yZW1vdmVBdHRyaWJ1dGUodCl7cmV0dXJuIHQgaW4gdGhpcy5tJiYoZGVsZXRlIHRoaXMubVt0XSx0aGlzLmsoKSksdGhpc31zZXRFeHRyYXModCl7cmV0dXJuIHRoaXMudj17Li4udGhpcy52LC4uLnR9LHRoaXMuaygpLHRoaXN9c2V0RXh0cmEodCxuKXtyZXR1cm4gdGhpcy52PXsuLi50aGlzLnYsW3RdOm59LHRoaXMuaygpLHRoaXN9c2V0RmluZ2VycHJpbnQodCl7cmV0dXJuIHRoaXMuQT10LHRoaXMuaygpLHRoaXN9c2V0TGV2ZWwodCl7cmV0dXJuIHRoaXMuQz10LHRoaXMuaygpLHRoaXN9c2V0VHJhbnNhY3Rpb25OYW1lKHQpe3JldHVybiB0aGlzLlI9dCx0aGlzLmsoKSx0aGlzfXNldENvbnRleHQodCxuKXtyZXR1cm4gbnVsbD09PW4/ZGVsZXRlIHRoaXMuX1t0XTp0aGlzLl9bdF09bix0aGlzLmsoKSx0aGlzfXNldFNlc3Npb24odCl7cmV0dXJuIHQ/dGhpcy5qPXQ6ZGVsZXRlIHRoaXMuaix0aGlzLmsoKSx0aGlzfWdldFNlc3Npb24oKXtyZXR1cm4gdGhpcy5qfXVwZGF0ZSh0KXtpZighdClyZXR1cm4gdGhpcztjb25zdCBuPSJmdW5jdGlvbiI9PXR5cGVvZiB0P3QodGhpcyk6dCxlPW4gaW5zdGFuY2VvZiBldD9uLmdldFNjb3BlRGF0YSgpOkMobiwiT2JqZWN0Iik/dDp2b2lkIDA7Y29uc3R7dGFnczpyLGF0dHJpYnV0ZXM6byxleHRyYTppLHVzZXI6cyxjb250ZXh0czpjLGxldmVsOnUsZmluZ2VycHJpbnQ6YT1bXSxwcm9wYWdhdGlvbkNvbnRleHQ6Zixjb252ZXJzYXRpb25JZDpofT1lfHx7fTtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4ucn0sdGhpcy5tPXsuLi50aGlzLm0sLi4ub30sdGhpcy52PXsuLi50aGlzLnYsLi4uaX0sdGhpcy5fPXsuLi50aGlzLl8sLi4uY30scyYmT2JqZWN0LmtleXMocykubGVuZ3RoJiYodGhpcy5wPXMpLHUmJih0aGlzLkM9dSksYS5sZW5ndGgmJih0aGlzLkE9YSksZiYmKHRoaXMuTj1mKSxoJiYodGhpcy5UPWgpLHRoaXN9Y2xlYXIoKXtyZXR1cm4gdGhpcy51PVtdLHRoaXMubD17fSx0aGlzLm09e30sdGhpcy52PXt9LHRoaXMucD17fSx0aGlzLl89e30sdGhpcy5DPXZvaWQgMCx0aGlzLlI9dm9pZCAwLHRoaXMuQT12b2lkIDAsdGhpcy5qPXZvaWQgMCx0aGlzLlQ9dm9pZCAwLHR0KHRoaXMsdm9pZCAwKSx0aGlzLmg9W10sdGhpcy5zZXRQcm9wYWdhdGlvbkNvbnRleHQoe3RyYWNlSWQ6cSgpLHNhbXBsZVJhbmQ6aygpfSksdGhpcy5rKCksdGhpc31hZGRCcmVhZGNydW1iKHQsbil7Y29uc3QgZT0ibnVtYmVyIj09dHlwZW9mIG4/bjoxMDA7aWYoZTw9MClyZXR1cm4gdGhpcztjb25zdCByPXt0aW1lc3RhbXA6SigpLC4uLnQsbWVzc2FnZTp0Lm1lc3NhZ2U/eih0Lm1lc3NhZ2UsMjA0OCk6dC5tZXNzYWdlfTtyZXR1cm4gdGhpcy51LnB1c2gociksdGhpcy51Lmxlbmd0aD5lJiYodGhpcy51PXRoaXMudS5zbGljZSgtZSksdGhpcy5JPy5yZWNvcmREcm9wcGVkRXZlbnQoImJ1ZmZlcl9vdmVyZmxvdyIsImxvZ19pdGVtIikpLHRoaXMuaygpLHRoaXN9Z2V0TGFzdEJyZWFkY3J1bWIoKXtyZXR1cm4gdGhpcy51W3RoaXMudS5sZW5ndGgtMV19Y2xlYXJCcmVhZGNydW1icygpe3JldHVybiB0aGlzLnU9W10sdGhpcy5rKCksdGhpc31hZGRBdHRhY2htZW50KHQpe3JldHVybiB0aGlzLmgucHVzaCh0KSx0aGlzfWNsZWFyQXR0YWNobWVudHMoKXtyZXR1cm4gdGhpcy5oPVtdLHRoaXN9Z2V0U2NvcGVEYXRhKCl7cmV0dXJue2JyZWFkY3J1bWJzOnRoaXMudSxhdHRhY2htZW50czp0aGlzLmgsY29udGV4dHM6dGhpcy5fLHRhZ3M6dGhpcy5sLGF0dHJpYnV0ZXM6dGhpcy5tLGV4dHJhOnRoaXMudix1c2VyOnRoaXMucCxsZXZlbDp0aGlzLkMsZmluZ2VycHJpbnQ6dGhpcy5BfHxbXSxldmVudFByb2Nlc3NvcnM6dGhpcy5pLHByb3BhZ2F0aW9uQ29udGV4dDp0aGlzLk4sc2RrUHJvY2Vzc2luZ01ldGFkYXRhOnRoaXMuUyx0cmFuc2FjdGlvbk5hbWU6dGhpcy5SLHNwYW46bnQodGhpcyksY29udmVyc2F0aW9uSWQ6dGhpcy5UfX1zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEodCl7cmV0dXJuIHRoaXMuUz1aKHRoaXMuUyx0LDIpLHRoaXN9c2V0UHJvcGFnYXRpb25Db250ZXh0KHQpe3JldHVybiB0aGlzLk49dCx0aGlzfWdldFByb3BhZ2F0aW9uQ29udGV4dCgpe3JldHVybiB0aGlzLk59Y2FwdHVyZUV4Y2VwdGlvbih0LG4pe2NvbnN0IGU9bj8uZXZlbnRfaWR8fEcoKTtpZighdGhpcy5JKXJldHVybiBoJiZ3Lndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBleGNlcHRpb24hIiksZTtjb25zdCByPW5ldyBFcnJvcigiU2VudHJ5IHN5bnRoZXRpY0V4Y2VwdGlvbiIpO3JldHVybiB0aGlzLkkuY2FwdHVyZUV4Y2VwdGlvbih0LHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpyLC4uLm4sZXZlbnRfaWQ6ZX0sdGhpcyksZX1jYXB0dXJlTWVzc2FnZSh0LG4sZSl7Y29uc3Qgcj1lPy5ldmVudF9pZHx8RygpO2lmKCF0aGlzLkkpcmV0dXJuIGgmJncud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIG1lc3NhZ2UhIikscjtjb25zdCBvPWU/LnN5bnRoZXRpY0V4Y2VwdGlvbj8/bmV3IEVycm9yKHQpO3JldHVybiB0aGlzLkkuY2FwdHVyZU1lc3NhZ2UodCxuLHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpvLC4uLmUsZXZlbnRfaWQ6cn0sdGhpcykscn1jYXB0dXJlRXZlbnQodCxuKXtjb25zdCBlPXQuZXZlbnRfaWR8fG4/LmV2ZW50X2lkfHxHKCk7cmV0dXJuIHRoaXMuST8odGhpcy5JLmNhcHR1cmVFdmVudCh0LHsuLi5uLGV2ZW50X2lkOmV9LHRoaXMpLGUpOihoJiZ3Lndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBldmVudCEiKSxlKX1rKCl7dGhpcy50fHwodGhpcy50PSEwLHRoaXMuby5mb3JFYWNoKHQ9Pnt0KHRoaXMpfSksdGhpcy50PSExKX19Y29uc3QgcnQ9dD0+dCBpbnN0YW5jZW9mIFByb21pc2UmJiF0W290XSxvdD1TeW1ib2woImNoYWluZWQgUHJvbWlzZUxpa2UiKSxpdD0odCxuKT0+e2lmKCFuKXJldHVybiB0O2xldCBlPSExO2Zvcihjb25zdCByIGluIHQpe2lmKHIgaW4gbiljb250aW51ZTtlPSEwO2NvbnN0IG89dFtyXTsiZnVuY3Rpb24iPT10eXBlb2Ygbz9PYmplY3QuZGVmaW5lUHJvcGVydHkobixyLHt2YWx1ZTooLi4ubik9Pm8uYXBwbHkodCxuKSxlbnVtZXJhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMCx3cml0YWJsZTohMH0pOm5bcl09b31yZXR1cm4gZSYmT2JqZWN0LmFzc2lnbihuLHtbb3RdOiEwfSksbn07Y2xhc3Mgc3R7Y29uc3RydWN0b3IodCxuKXtsZXQgZSxyO2U9dHx8bmV3IGV0LHI9bnx8bmV3IGV0LHRoaXMuUD1be3Njb3BlOmV9XSx0aGlzLkQ9cn13aXRoU2NvcGUodCl7Y29uc3Qgbj10aGlzLlUoKTtsZXQgZTt0cnl7ZT10KG4pfWNhdGNoKHQpe3Rocm93IHRoaXMuQigpLHR9cmV0dXJuIGooZSk/KCh0LG4sZSk9Pntjb25zdCByPXQudGhlbih0PT4obih0KSx0KSx0PT57dGhyb3cgZSh0KSx0fSk7cmV0dXJuIHJ0KHIpJiZydCh0KT9yOml0KHQscil9KShlLCgpPT50aGlzLkIoKSwoKT0+dGhpcy5CKCkpOih0aGlzLkIoKSxlKX1nZXRDbGllbnQoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLmNsaWVudH1nZXRTY29wZSgpe3JldHVybiB0aGlzLmdldFN0YWNrVG9wKCkuc2NvcGV9Z2V0SXNvbGF0aW9uU2NvcGUoKXtyZXR1cm4gdGhpcy5EfWdldFN0YWNrVG9wKCl7cmV0dXJuIHRoaXMuUFt0aGlzLlAubGVuZ3RoLTFdfVUoKXtjb25zdCB0PXRoaXMuZ2V0U2NvcGUoKS5jbG9uZSgpO3JldHVybiB0aGlzLlAucHVzaCh7Y2xpZW50OnRoaXMuZ2V0Q2xpZW50KCksc2NvcGU6dH0pLHR9Qigpe3JldHVybiEodGhpcy5QLmxlbmd0aDw9MSkmJiEhdGhpcy5QLnBvcCgpfX1mdW5jdGlvbiBjdCgpe2NvbnN0IHQ9ZyhsKCkpO3JldHVybiB0LnN0YWNrPXQuc3RhY2t8fG5ldyBzdChtKCJkZWZhdWx0Q3VycmVudFNjb3BlIiwoKT0+bmV3IGV0KSxtKCJkZWZhdWx0SXNvbGF0aW9uU2NvcGUiLCgpPT5uZXcgZXQpKX1mdW5jdGlvbiB1dCh0KXtyZXR1cm4gY3QoKS53aXRoU2NvcGUodCl9ZnVuY3Rpb24gYXQodCxuKXtjb25zdCBlPWN0KCk7cmV0dXJuIGUud2l0aFNjb3BlKCgpPT4oZS5nZXRTdGFja1RvcCgpLnNjb3BlPXQsbih0KSkpfWZ1bmN0aW9uIGZ0KHQpe3JldHVybiBjdCgpLndpdGhTY29wZSgoKT0+dChjdCgpLmdldElzb2xhdGlvblNjb3BlKCkpKX1mdW5jdGlvbiBodCh0KXtjb25zdCBuPWcodCk7cmV0dXJuIG4uYWNzP24uYWNzOnt3aXRoSXNvbGF0aW9uU2NvcGU6ZnQsd2l0aFNjb3BlOnV0LHdpdGhTZXRTY29wZTphdCx3aXRoU2V0SXNvbGF0aW9uU2NvcGU6KHQsbik9PmZ0KG4pLGdldEN1cnJlbnRTY29wZTooKT0+Y3QoKS5nZXRTY29wZSgpLGdldElzb2xhdGlvblNjb3BlOigpPT5jdCgpLmdldElzb2xhdGlvblNjb3BlKCl9fWZ1bmN0aW9uIHB0KCl7cmV0dXJuIGh0KGwoKSkuZ2V0Q3VycmVudFNjb3BlKCkuZ2V0Q2xpZW50KCl9ZnVuY3Rpb24gZHQodCl7Y29uc3Qgbj10O3JldHVybntzY29wZTpuLl9zZW50cnlTY29wZSxpc29sYXRpb25TY29wZTpRKG4uX3NlbnRyeUlzb2xhdGlvblNjb3BlKX19Y29uc3QgbHQ9InNlbnRyeS0iO2Z1bmN0aW9uIGd0KHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7aWYoIXR8fChuPXQsIUMobiwiU3RyaW5nIikmJiFBcnJheS5pc0FycmF5KHQpKSlyZXR1cm47dmFyIG47aWYoQXJyYXkuaXNBcnJheSh0KSlyZXR1cm4gdC5yZWR1Y2UoKHQsbik9Pntjb25zdCBlPW10KG4pO3JldHVybiBPYmplY3QuZW50cmllcyhlKS5mb3JFYWNoKChbbixlXSk9Pnt0W25dPWV9KSx0fSx7fSk7cmV0dXJuIG10KHQpfSh0KTtpZighbilyZXR1cm47Y29uc3QgZT1PYmplY3QuZW50cmllcyhuKS5yZWR1Y2UoKHQsW24sZV0pPT57aWYobi5zdGFydHNXaXRoKGx0KSl7dFtuLnNsaWNlKDcpXT1lfXJldHVybiB0fSx7fSk7cmV0dXJuIE9iamVjdC5rZXlzKGUpLmxlbmd0aD4wP2U6dm9pZCAwfWZ1bmN0aW9uIG10KHQpe3JldHVybiB0LnNwbGl0KCIsIikubWFwKHQ9Pntjb25zdCBuPXQuaW5kZXhPZigiPSIpO2lmKC0xPT09bilyZXR1cm5bXTtyZXR1cm5bdC5zbGljZSgwLG4pLHQuc2xpY2UobisxKV0ubWFwKHQ9Pnt0cnl7cmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudCh0LnRyaW0oKSl9Y2F0Y2h7cmV0dXJufX0pfSkucmVkdWNlKCh0LFtuLGVdKT0+KG4mJmUmJih0W25dPWUpLHQpLHt9KX1jb25zdCB5dD0vXm8oXGQrKVwuLztmdW5jdGlvbiBidCh0LG49ITEpe2NvbnN0e2hvc3Q6ZSxwYXRoOnIscGFzczpvLHBvcnQ6aSxwcm9qZWN0SWQ6cyxwcm90b2NvbDpjLHB1YmxpY0tleTp1fT10O3JldHVybmAke2N9Oi8vJHt1fSR7biYmbz9gOiR7b31gOiIifUAke2V9JHtpP2A6JHtpfWA6IiJ9LyR7cj9gJHtyfS9gOnJ9JHtzfWB9ZnVuY3Rpb24gdnQodCl7Y29uc3Qgbj10LmdldE9wdGlvbnMoKSx7aG9zdDplfT10LmdldERzbigpfHx7fTtsZXQgcjtyZXR1cm4gbi5vcmdJZD9yPVN0cmluZyhuLm9yZ0lkKTplJiYocj1mdW5jdGlvbih0KXtjb25zdCBuPXQubWF0Y2goeXQpO3JldHVybiBuPy5bMV19KGUpKSxyfWZ1bmN0aW9uIF90KHQpe2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZSxpc1JlbW90ZTpyfT10LnNwYW5Db250ZXh0KCksbz1yP246RXQodCkucGFyZW50X3NwYW5faWQsaT1kdCh0KS5zY29wZTtyZXR1cm57cGFyZW50X3NwYW5faWQ6byxzcGFuX2lkOnI/aT8uZ2V0UHJvcGFnYXRpb25Db250ZXh0KCkucHJvcGFnYXRpb25TcGFuSWR8fFYoKTpuLHRyYWNlX2lkOmV9fWZ1bmN0aW9uIFN0KHQpe3JldHVybiB0JiZ0Lmxlbmd0aD4wP3QubWFwKCh7Y29udGV4dDp7c3BhbklkOnQsdHJhY2VJZDpuLHRyYWNlRmxhZ3M6ZSwuLi5yfSxhdHRyaWJ1dGVzOm99KT0+KHtzcGFuX2lkOnQsdHJhY2VfaWQ6bixzYW1wbGVkOjE9PT1lLGF0dHJpYnV0ZXM6bywuLi5yfSkpOnZvaWQgMH1mdW5jdGlvbiB3dCh0KXtyZXR1cm4ibnVtYmVyIj09dHlwZW9mIHQ/JHQodCk6QXJyYXkuaXNBcnJheSh0KT90WzBdK3RbMV0vMWU5OnQgaW5zdGFuY2VvZiBEYXRlPyR0KHQuZ2V0VGltZSgpKTpZKCl9ZnVuY3Rpb24gJHQodCl7cmV0dXJuIHQ+OTk5OTk5OTk5OT90LzFlMzp0fWZ1bmN0aW9uIEV0KHQpe2lmKGZ1bmN0aW9uKHQpe3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiB0LmdldFNwYW5KU09OfSh0KSlyZXR1cm4gdC5nZXRTcGFuSlNPTigpO2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZX09dC5zcGFuQ29udGV4dCgpO2lmKGZ1bmN0aW9uKHQpe2NvbnN0IG49dDtyZXR1cm4hIShuLmF0dHJpYnV0ZXMmJm4uc3RhcnRUaW1lJiZuLm5hbWUmJm4uZW5kVGltZSYmbi5zdGF0dXMpfSh0KSl7Y29uc3R7YXR0cmlidXRlczpyLHN0YXJ0VGltZTpvLG5hbWU6aSxlbmRUaW1lOnMsc3RhdHVzOmMsbGlua3M6dX09dDtyZXR1cm57c3Bhbl9pZDpuLHRyYWNlX2lkOmUsZGF0YTpyLGRlc2NyaXB0aW9uOmkscGFyZW50X3NwYW5faWQ6eHQodCksc3RhcnRfdGltZXN0YW1wOnd0KG8pLHRpbWVzdGFtcDp3dChzKXx8dm9pZCAwLHN0YXR1czpOdChjKSxvcDpyWyJzZW50cnkub3AiXSxvcmlnaW46clsic2VudHJ5Lm9yaWdpbiJdLGxpbmtzOlN0KHUpfX1yZXR1cm57c3Bhbl9pZDpuLHRyYWNlX2lkOmUsc3RhcnRfdGltZXN0YW1wOjAsZGF0YTp7fX19ZnVuY3Rpb24geHQodCl7cmV0dXJuInBhcmVudFNwYW5JZCJpbiB0P3QucGFyZW50U3BhbklkOiJwYXJlbnRTcGFuQ29udGV4dCJpbiB0P3QucGFyZW50U3BhbkNvbnRleHQ/LnNwYW5JZDp2b2lkIDB9ZnVuY3Rpb24gTnQodCl7aWYodCYmMCE9PXQuY29kZSlyZXR1cm4gMT09PXQuY29kZT8ib2siOnQubWVzc2FnZXx8ImludGVybmFsX2Vycm9yIn1jb25zdCBDdD1mdW5jdGlvbih0KXtyZXR1cm4gdC5fc2VudHJ5Um9vdFNwYW58fHR9O2Z1bmN0aW9uIGp0KHQpe2lmKCJib29sZWFuIj09dHlwZW9mIF9fU0VOVFJZX1RSQUNJTkdfXyYmIV9fU0VOVFJZX1RSQUNJTkdfXylyZXR1cm4hMTtjb25zdCBuPXR8fHB0KCk/LmdldE9wdGlvbnMoKTtyZXR1cm4hKCFufHxudWxsPT1uLnRyYWNlc1NhbXBsZVJhdGUmJiFuLnRyYWNlc1NhbXBsZXIpfWNvbnN0IFJ0PVN5bWJvbC5mb3IoInNlbnRyeS5ub25SZWNvcmRpbmdTcGFuIik7ZnVuY3Rpb24gQXQodCxuKXtjb25zdCBlPW4uZ2V0T3B0aW9ucygpLHtwdWJsaWNLZXk6cn09bi5nZXREc24oKXx8e30sbz17ZW52aXJvbm1lbnQ6ZS5lbnZpcm9ubWVudHx8InByb2R1Y3Rpb24iLHJlbGVhc2U6ZS5yZWxlYXNlLHB1YmxpY19rZXk6cix0cmFjZV9pZDp0LG9yZ19pZDp2dChuKX07cmV0dXJuIG4uZW1pdCgiY3JlYXRlRHNjIixvKSxvfWZ1bmN0aW9uIEl0KHQsbil7Y29uc3QgZT1uLmdldFByb3BhZ2F0aW9uQ29udGV4dCgpO3JldHVybiBlLmRzY3x8QXQoZS50cmFjZUlkLHQpfWZ1bmN0aW9uIE90KHQpe2NvbnN0IG49cHQoKTtpZighbilyZXR1cm57fTtjb25zdCBlPUN0KHQpLHI9RXQoZSksbz1yLmRhdGEsaT1lLnNwYW5Db250ZXh0KCkudHJhY2VTdGF0ZSxzPWk/LmdldCgic2VudHJ5LnNhbXBsZV9yYXRlIik/P29bInNlbnRyeS5zYW1wbGVfcmF0ZSJdPz9vWyJzZW50cnkucHJldmlvdXNfdHJhY2Vfc2FtcGxlX3JhdGUiXTtmdW5jdGlvbiBjKHQpe3JldHVybiJudW1iZXIiIT10eXBlb2YgcyYmInN0cmluZyIhPXR5cGVvZiBzfHwodC5zYW1wbGVfcmF0ZT1gJHtzfWApLHR9Y29uc3QgdT1lLl9mcm96ZW5Ec2M7aWYodSlyZXR1cm4gYyh1KTtpZihmdW5jdGlvbih0KXtyZXR1cm4hIXQmJiEwPT09dFtSdF19KGUpJiYhanQobi5nZXRPcHRpb25zKCkpKXtjb25zdCB0PWR0KGUpLnNjb3BlO2lmKHQpcmV0dXJuIGMoey4uLkl0KG4sdCl9KX1jb25zdCBhPWk/LmdldCgic2VudHJ5LmRzYyIpLGY9YSYmZ3QoYSk7aWYoZilyZXR1cm4gYyhmKTtjb25zdCBoPUF0KHQuc3BhbkNvbnRleHQoKS50cmFjZUlkLG4pLHA9b1sic2VudHJ5LnNvdXJjZSJdPz9vWyJzZW50cnkuc3Bhbi5zb3VyY2UiXSxkPXIuZGVzY3JpcHRpb247cmV0dXJuInVybCIhPT1wJiZkJiYoaC50cmFuc2FjdGlvbj1kKSxqdCgpJiYoaC5zYW1wbGVkPVN0cmluZyhmdW5jdGlvbih0KXtjb25zdHt0cmFjZUZsYWdzOm59PXQuc3BhbkNvbnRleHQoKTtyZXR1cm4gMT09PW59KGUpKSxoLnNhbXBsZV9yYW5kPWk/LmdldCgic2VudHJ5LnNhbXBsZV9yYW5kIik/P2R0KGUpLnNjb3BlPy5nZXRQcm9wYWdhdGlvbkNvbnRleHQoKS5zYW1wbGVSYW5kLnRvU3RyaW5nKCkpLGMoaCksbi5lbWl0KCJjcmVhdGVEc2MiLGgsZSksaH1mdW5jdGlvbiBUdCh0LG49W10pe3JldHVyblt0LG5dfWZ1bmN0aW9uIGt0KHQsbil7Y29uc3QgZT10WzFdO2Zvcihjb25zdCB0IG9mIGUpe2lmKG4odCx0WzBdLnR5cGUpKXJldHVybiEwfXJldHVybiExfWZ1bmN0aW9uIFB0KHQpe2NvbnN0IG49ZyhwKTtyZXR1cm4gbi5lbmNvZGVQb2x5ZmlsbD9uLmVuY29kZVBvbHlmaWxsKHQpOihuZXcgVGV4dEVuY29kZXIpLmVuY29kZSh0KX1mdW5jdGlvbiBEdCh0KXtjb25zdFtuLGVdPXQ7bGV0IHI9SlNPTi5zdHJpbmdpZnkobik7ZnVuY3Rpb24gbyh0KXsic3RyaW5nIj09dHlwZW9mIHI/cj0ic3RyaW5nIj09dHlwZW9mIHQ/cit0OltQdChyKSx0XTpyLnB1c2goInN0cmluZyI9PXR5cGVvZiB0P1B0KHQpOnQpfWZvcihjb25zdCB0IG9mIGUpe2NvbnN0W24sZV09dDtpZihvKGBcbiR7SlNPTi5zdHJpbmdpZnkobil9XG5gKSwic3RyaW5nIj09dHlwZW9mIGV8fGUgaW5zdGFuY2VvZiBVaW50OEFycmF5KW8oZSk7ZWxzZXtsZXQgdDt0cnl7dD1KU09OLnN0cmluZ2lmeShlKX1jYXRjaHt0PUpTT04uc3RyaW5naWZ5KEIoZSkpfW8odCl9fXJldHVybiJzdHJpbmciPT10eXBlb2Ygcj9yOmZ1bmN0aW9uKHQpe2NvbnN0IG49dC5yZWR1Y2UoKHQsbik9PnQrbi5sZW5ndGgsMCksZT1uZXcgVWludDhBcnJheShuKTtsZXQgcj0wO2Zvcihjb25zdCBuIG9mIHQpZS5zZXQobixyKSxyKz1uLmxlbmd0aDtyZXR1cm4gZX0ocil9Y29uc3QgVXQ9e3Nlc3Npb25zOiJzZXNzaW9uIixldmVudDoiZXJyb3IiLGNsaWVudF9yZXBvcnQ6ImludGVybmFsIix1c2VyX3JlcG9ydDoiZGVmYXVsdCIscHJvZmlsZV9jaHVuazoicHJvZmlsZSIscmVwbGF5X2V2ZW50OiJyZXBsYXkiLHJlcGxheV9yZWNvcmRpbmc6InJlcGxheSIsY2hlY2tfaW46Im1vbml0b3IiLHJhd19zZWN1cml0eToic2VjdXJpdHkiLGxvZzoibG9nX2l0ZW0iLHRyYWNlX21ldHJpYzoibWV0cmljIn07ZnVuY3Rpb24gQnQodCl7cmV0dXJuIGZ1bmN0aW9uKHQpe3JldHVybiB0IGluIFV0fSh0KT9VdFt0XTp0fWZ1bmN0aW9uIEx0KHQpe2lmKCF0Py5zZGspcmV0dXJuO2NvbnN0e25hbWU6bix2ZXJzaW9uOmV9PXQuc2RrO3JldHVybntuYW1lOm4sdmVyc2lvbjplfX1mdW5jdGlvbiBNdCh0LG4sZSxyKXtjb25zdCBvPUx0KGUpLGk9dC50eXBlJiYicmVwbGF5X2V2ZW50IiE9PXQudHlwZT90LnR5cGU6ImV2ZW50IjshZnVuY3Rpb24odCxuKXtpZighbilyZXR1cm4gdDtjb25zdCBlPXQuc2RrfHx7fTt0LnNkaz17Li4uZSxuYW1lOmUubmFtZXx8bi5uYW1lLHZlcnNpb246ZS52ZXJzaW9ufHxuLnZlcnNpb24saW50ZWdyYXRpb25zOlsuLi50LnNkaz8uaW50ZWdyYXRpb25zfHxbXSwuLi5uLmludGVncmF0aW9uc3x8W11dLHBhY2thZ2VzOlsuLi50LnNkaz8ucGFja2FnZXN8fFtdLC4uLm4ucGFja2FnZXN8fFtdXSxzZXR0aW5nczp0LnNkaz8uc2V0dGluZ3N8fG4uc2V0dGluZ3M/ey4uLnQuc2RrPy5zZXR0aW5ncywuLi5uLnNldHRpbmdzfTp2b2lkIDB9fSh0LGU/LnNkayk7Y29uc3Qgcz1mdW5jdGlvbih0LG4sZSxyKXtjb25zdCBvPXQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhPy5keW5hbWljU2FtcGxpbmdDb250ZXh0O3JldHVybntldmVudF9pZDp0LmV2ZW50X2lkLHNlbnRfYXQ6bmV3IERhdGUoUCgpKS50b0lTT1N0cmluZygpLC4uLm4mJntzZGs6bn0sLi4uISFlJiZyJiZ7ZHNuOmJ0KHIpfSwuLi5vJiZ7dHJhY2U6b319fSh0LG8scixuKTtkZWxldGUgdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE7cmV0dXJuIFR0KHMsW1t7dHlwZTppfSx0XV0pfWNvbnN0IHp0PSJfX1NFTlRSWV9TVVBQUkVTU19UUkFDSU5HX18iO2Z1bmN0aW9uIEZ0KHQpe2NvbnN0IG49aHQobCgpKTtyZXR1cm4gbi5zdXBwcmVzc1RyYWNpbmc/bi5zdXBwcmVzc1RyYWNpbmcodCk6ZnVuY3Rpb24oLi4udCl7Y29uc3Qgbj1odChsKCkpO2lmKDI9PT10Lmxlbmd0aCl7Y29uc3RbZSxyXT10O3JldHVybiBlP24ud2l0aFNldFNjb3BlKGUscik6bi53aXRoU2NvcGUocil9cmV0dXJuIG4ud2l0aFNjb3BlKHRbMF0pfShuPT57bi5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1t6dF06ITB9KTtjb25zdCBlPXQoKTtyZXR1cm4gbi5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1t6dF06dm9pZCAwfSksZX0pfWZ1bmN0aW9uIEd0KHQsbil7Y29uc3R7ZmluZ2VycHJpbnQ6ZSxzcGFuOnIsYnJlYWRjcnVtYnM6byxzZGtQcm9jZXNzaW5nTWV0YWRhdGE6aX09bjshZnVuY3Rpb24odCxuKXtjb25zdHtleHRyYTplLHRhZ3M6cix1c2VyOm8sY29udGV4dHM6aSxsZXZlbDpzLHRyYW5zYWN0aW9uTmFtZTpjfT1uO09iamVjdC5rZXlzKGUpLmxlbmd0aCYmKHQuZXh0cmE9ey4uLmUsLi4udC5leHRyYX0pO09iamVjdC5rZXlzKHIpLmxlbmd0aCYmKHQudGFncz17Li4uciwuLi50LnRhZ3N9KTtPYmplY3Qua2V5cyhvKS5sZW5ndGgmJih0LnVzZXI9ey4uLm8sLi4udC51c2VyfSk7T2JqZWN0LmtleXMoaSkubGVuZ3RoJiYodC5jb250ZXh0cz17Li4uaSwuLi50LmNvbnRleHRzfSk7cyYmKHQubGV2ZWw9cyk7YyYmInRyYW5zYWN0aW9uIiE9PXQudHlwZSYmKHQudHJhbnNhY3Rpb249Yyl9KHQsbiksciYmZnVuY3Rpb24odCxuKXt0LmNvbnRleHRzPXt0cmFjZTpfdChuKSwuLi50LmNvbnRleHRzfSx0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YT17ZHluYW1pY1NhbXBsaW5nQ29udGV4dDpPdChuKSwuLi50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YX07Y29uc3QgZT1DdChuKSxyPUV0KGUpLmRlc2NyaXB0aW9uO3ImJiF0LnRyYW5zYWN0aW9uJiYidHJhbnNhY3Rpb24iPT09dC50eXBlJiYodC50cmFuc2FjdGlvbj1yKX0odCxyKSxmdW5jdGlvbih0LG4pe3QuZmluZ2VycHJpbnQ9dC5maW5nZXJwcmludD9BcnJheS5pc0FycmF5KHQuZmluZ2VycHJpbnQpP3QuZmluZ2VycHJpbnQ6W3QuZmluZ2VycHJpbnRdOltdLG4mJih0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQuY29uY2F0KG4pKTt0LmZpbmdlcnByaW50Lmxlbmd0aHx8ZGVsZXRlIHQuZmluZ2VycHJpbnR9KHQsZSksZnVuY3Rpb24odCxuKXtjb25zdCBlPVsuLi50LmJyZWFkY3J1bWJzfHxbXSwuLi5uXTt0LmJyZWFkY3J1bWJzPWUubGVuZ3RoP2U6dm9pZCAwfSh0LG8pLGZ1bmN0aW9uKHQsbil7dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9ey4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhLC4uLm59fSh0LGkpfWNsYXNzIEp0e2NvbnN0cnVjdG9yKHQpe3RoaXMuTD0wLHRoaXMuTT1bXSx0aGlzLkYodCl9dGhlbih0LG4pe3JldHVybiBuZXcgSnQoKGUscik9Pnt0aGlzLk0ucHVzaChbITEsbj0+e2lmKHQpdHJ5e2UodChuKSl9Y2F0Y2godCl7cih0KX1lbHNlIGUobil9LHQ9PntpZihuKXRyeXtlKG4odCkpfWNhdGNoKHQpe3IodCl9ZWxzZSByKHQpfV0pLHRoaXMuRygpfSl9Y2F0Y2godCl7cmV0dXJuIHRoaXMudGhlbih0PT50LHQpfWZpbmFsbHkodCl7cmV0dXJuIG5ldyBKdCgobixlKT0+e2xldCByLG87cmV0dXJuIHRoaXMudGhlbihuPT57bz0hMSxyPW4sdCYmdCgpfSxuPT57bz0hMCxyPW4sdCYmdCgpfSkudGhlbigoKT0+e28/ZShyKTpuKHIpfSl9KX1HKCl7aWYoMD09PXRoaXMuTClyZXR1cm47Y29uc3QgdD10aGlzLk0uc2xpY2UoKTt0aGlzLk09W10sdC5mb3JFYWNoKHQ9Pnt0WzBdfHwoMT09PXRoaXMuTCYmdFsxXSh0aGlzLkopLDI9PT10aGlzLkwmJnRbMl0odGhpcy5KKSx0WzBdPSEwKX0pfUYodCl7Y29uc3Qgbj0odCxuKT0+ezA9PT10aGlzLkwmJihqKG4pP24udGhlbihlLHIpOih0aGlzLkw9dCx0aGlzLko9bix0aGlzLkcoKSkpfSxlPXQ9PntuKDEsdCl9LHI9dD0+e24oMix0KX07dHJ5e3QoZSxyKX1jYXRjaCh0KXtyKHQpfX19Y29uc3QgV3Q9U3ltYm9sLmZvcigiU2VudHJ5QnVmZmVyRnVsbEVycm9yIik7ZnVuY3Rpb24gWXQodD0xMDApe2NvbnN0IG49bmV3IFNldDtmdW5jdGlvbiBlKHQpe24uZGVsZXRlKHQpfXJldHVybntnZXQgJCgpe3JldHVybiBBcnJheS5mcm9tKG4pfSxhZGQ6ZnVuY3Rpb24ocil7aWYoIShuLnNpemU8dCkpcmV0dXJuIG89V3QsbmV3IEp0KCh0LG4pPT57bihvKX0pO3ZhciBvO2NvbnN0IGk9cigpO3JldHVybiBuLmFkZChpKSxpLnRoZW4oKCk9PmUoaSksKCk9PmUoaSkpLGl9LGRyYWluOmZ1bmN0aW9uKHQpe2lmKCFuLnNpemUpcmV0dXJuIGU9ITAsbmV3IEp0KHQ9Pnt0KGUpfSk7dmFyIGU7Y29uc3Qgcj1Qcm9taXNlLmFsbFNldHRsZWQoQXJyYXkuZnJvbShuKSkudGhlbigoKT0+ITApO2lmKCF0KXJldHVybiByO2NvbnN0IG89W3IsbmV3IFByb21pc2Uobj0+e3JldHVybiJvYmplY3QiPT10eXBlb2YoZT1zZXRUaW1lb3V0KCgpPT5uKCExKSx0KSkmJiJmdW5jdGlvbiI9PXR5cGVvZiBlLnVucmVmJiZlLnVucmVmKCksZTt2YXIgZX0pXTtyZXR1cm4gUHJvbWlzZS5yYWNlKG8pfX19ZnVuY3Rpb24gSHQodCx7c3RhdHVzQ29kZTpuLGhlYWRlcnM6ZX0scj1QKCkpe2NvbnN0IG89ey4uLnR9LGk9ZT8uWyJ4LXNlbnRyeS1yYXRlLWxpbWl0cyJdLHM9ZT8uWyJyZXRyeS1hZnRlciJdO2lmKGkpZm9yKGNvbnN0IHQgb2YgaS50cmltKCkuc3BsaXQoIiwiKSl7Y29uc3RbbixlLCwsaV09dC5zcGxpdCgiOiIsNSkscz1wYXJzZUludChuLDEwKSxjPTFlMyooaXNOYU4ocyk/NjA6cyk7aWYoZSlmb3IoY29uc3QgdCBvZiBlLnNwbGl0KCI7IikpIm1ldHJpY19idWNrZXQiPT09dCYmaSYmIWkuc3BsaXQoIjsiKS5pbmNsdWRlcygiY3VzdG9tIil8fChvW3RdPXIrYyk7ZWxzZSBvLmFsbD1yK2N9ZWxzZSBzP28uYWxsPXIrZnVuY3Rpb24odCxuPVAoKSl7Y29uc3QgZT1wYXJzZUludChgJHt0fWAsMTApO2lmKCFpc05hTihlKSlyZXR1cm4gMWUzKmU7Y29uc3Qgcj1EYXRlLnBhcnNlKGAke3R9YCk7cmV0dXJuIGlzTmFOKHIpPzZlNDpyLW59KHMscik6NDI5PT09biYmKG8uYWxsPXIrNmU0KTtyZXR1cm4gb31mdW5jdGlvbiBLdCh0LG4sZT1ZdCh0LmJ1ZmZlclNpemV8fDY0KSl7bGV0IHI9e307cmV0dXJue3NlbmQ6ZnVuY3Rpb24odCl7Y29uc3Qgbz1bXTtpZihrdCh0LCh0LG4pPT57Y29uc3QgZT1CdChuKTsoZnVuY3Rpb24odCxuLGU9UCgpKXtyZXR1cm4gZnVuY3Rpb24odCxuKXtyZXR1cm4gdFtuXXx8dC5hbGx8fDB9KHQsbik+ZX0pKHIsZSl8fG8ucHVzaCh0KX0pLDA9PT1vLmxlbmd0aClyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtjb25zdCBpPVR0KHRbMF0sbykscz10PT57IWZ1bmN0aW9uKHQsbil7cmV0dXJuIGt0KHQsKHQsZSk9Pm4uaW5jbHVkZXMoZSkpfShpLFsiY2xpZW50X3JlcG9ydCJdKT9rdChpLCh0LG4pPT57fSk6aCYmdy53YXJuKGBEcm9wcGluZyBjbGllbnQgcmVwb3J0LiBXaWxsIG5vdCBzZW5kIG91dGNvbWVzIChyZWFzb246ICR7dH0pLmApfTtyZXR1cm4gZS5hZGQoKCk9Pm4oe2JvZHk6RHQoaSl9KS50aGVuKHQ9PjQxMz09PXQuc3RhdHVzQ29kZT8oaCYmdy5lcnJvcigiU2VudHJ5IHJlc3BvbmRlZCB3aXRoIHN0YXR1cyBjb2RlIDQxMy4gRW52ZWxvcGUgd2FzIGRpc2NhcmRlZCBkdWUgdG8gZXhjZWVkaW5nIHNpemUgbGltaXRzLiIpLHMoInNlbmRfZXJyb3IiKSx0KTooaCYmdm9pZCAwIT09dC5zdGF0dXNDb2RlJiYodC5zdGF0dXNDb2RlPDIwMHx8dC5zdGF0dXNDb2RlPj0zMDApJiZ3Lndhcm4oYFNlbnRyeSByZXNwb25kZWQgd2l0aCBzdGF0dXMgY29kZSAke3Quc3RhdHVzQ29kZX0gdG8gc2VudCBldmVudC5gKSxyPUh0KHIsdCksdCksdD0+e3Rocm93IHMoIm5ldHdvcmtfZXJyb3IiKSxoJiZ3LmVycm9yKCJFbmNvdW50ZXJlZCBlcnJvciBydW5uaW5nIHRyYW5zcG9ydCByZXF1ZXN0OiIsdCksdH0pKS50aGVuKHQ9PnQsdD0+e2lmKHQ9PT1XdClyZXR1cm4gaCYmdy5lcnJvcigiU2tpcHBlZCBzZW5kaW5nIGV2ZW50IGJlY2F1c2UgYnVmZmVyIGlzIGZ1bGwuIikscygicXVldWVfb3ZlcmZsb3ciKSxQcm9taXNlLnJlc29sdmUoe30pO3Rocm93IHR9KX0sZmx1c2g6dD0+ZS5kcmFpbih0KX19Y29uc3QgWnQ9L14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvO2Z1bmN0aW9uIHF0KHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7Y29uc3Qgbj10Lmxlbmd0aD4xMDI0P2A8dHJ1bmNhdGVkPiR7dC5zbGljZSgtMTAyNCl9YDp0LGU9WnQuZXhlYyhuKTtyZXR1cm4gZT9lLnNsaWNlKDEpOltdfSh0KSxlPW5bMF18fCIiO2xldCByPW5bMV07cmV0dXJuIGV8fHI/KHImJihyPXIuc2xpY2UoMCxyLmxlbmd0aC0xKSksZStyKToiLiJ9ZnVuY3Rpb24gVnQodCxuPSExKXtyZXR1cm4hKG58fHQmJiF0LnN0YXJ0c1dpdGgoIi8iKSYmIXQubWF0Y2goL15bQS1aXTovKSYmIXQuc3RhcnRzV2l0aCgiLiIpJiYhdC5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSkmJnZvaWQgMCE9PXQmJiF0LmluY2x1ZGVzKCJub2RlX21vZHVsZXMvIil9dmFyIFF0O2NvbnN0IFh0PVN5bWJvbCgiQWdlbnRCYXNlSW50ZXJuYWxTdGF0ZSIpO2NsYXNzIHRuIGV4dGVuZHMoUXQ9aS5BZ2VudCxRdCl7Y29uc3RydWN0b3IodCl7c3VwZXIodCksdGhpc1tYdF09e319aXNTZWN1cmVFbmRwb2ludCh0KXtpZih0KXtpZigiYm9vbGVhbiI9PXR5cGVvZiB0LnNlY3VyZUVuZHBvaW50KXJldHVybiB0LnNlY3VyZUVuZHBvaW50O2lmKCJzdHJpbmciPT10eXBlb2YgdC5wcm90b2NvbClyZXR1cm4iaHR0cHM6Ij09PXQucHJvdG9jb2x9Y29uc3R7c3RhY2s6bn09bmV3IEVycm9yO3JldHVybiJzdHJpbmciPT10eXBlb2YgbiYmbi5zcGxpdCgiXG4iKS5zb21lKHQ9Pi0xIT09dC5pbmRleE9mKCIoaHR0cHMuanM6Iil8fC0xIT09dC5pbmRleE9mKCJub2RlOmh0dHBzOiIpKX1jcmVhdGVTb2NrZXQodCxuLGUpe2NvbnN0IHI9ey4uLm4sc2VjdXJlRW5kcG9pbnQ6dGhpcy5pc1NlY3VyZUVuZHBvaW50KG4pfTtQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpPT50aGlzLmNvbm5lY3QodCxyKSkudGhlbihvPT57aWYobyBpbnN0YW5jZW9mIGkuQWdlbnQpcmV0dXJuIG8uYWRkUmVxdWVzdCh0LHIpO3RoaXNbWHRdLmN1cnJlbnRTb2NrZXQ9byxzdXBlci5jcmVhdGVTb2NrZXQodCxuLGUpfSxlKX1jcmVhdGVDb25uZWN0aW9uKCl7Y29uc3QgdD10aGlzW1h0XS5jdXJyZW50U29ja2V0O2lmKHRoaXNbWHRdLmN1cnJlbnRTb2NrZXQ9dm9pZCAwLCF0KXRocm93IG5ldyBFcnJvcigiTm8gc29ja2V0IHdhcyByZXR1cm5lZCBpbiB0aGUgYGNvbm5lY3QoKWAgZnVuY3Rpb24iKTtyZXR1cm4gdH1nZXQgZGVmYXVsdFBvcnQoKXtyZXR1cm4gdGhpc1tYdF0uZGVmYXVsdFBvcnQ/PygiaHR0cHM6Ij09PXRoaXMucHJvdG9jb2w/NDQzOjgwKX1zZXQgZGVmYXVsdFBvcnQodCl7dGhpc1tYdF0mJih0aGlzW1h0XS5kZWZhdWx0UG9ydD10KX1nZXQgcHJvdG9jb2woKXtyZXR1cm4gdGhpc1tYdF0ucHJvdG9jb2w/Pyh0aGlzLmlzU2VjdXJlRW5kcG9pbnQoKT8iaHR0cHM6IjoiaHR0cDoiKX1zZXQgcHJvdG9jb2wodCl7dGhpc1tYdF0mJih0aGlzW1h0XS5wcm90b2NvbD10KX19ZnVuY3Rpb24gbm4oLi4udCl7dy5sb2coIltodHRwcy1wcm94eS1hZ2VudDpwYXJzZS1wcm94eS1yZXNwb25zZV0iLC4uLnQpfWZ1bmN0aW9uIGVuKHQpe3JldHVybiBuZXcgUHJvbWlzZSgobixlKT0+e2xldCByPTA7Y29uc3Qgbz1bXTtmdW5jdGlvbiBpKCl7Y29uc3QgYz10LnJlYWQoKTtjP2Z1bmN0aW9uKGMpe28ucHVzaChjKSxyKz1jLmxlbmd0aDtjb25zdCB1PUJ1ZmZlci5jb25jYXQobyxyKSxhPXUuaW5kZXhPZigiXHJcblxyXG4iKTtpZigtMT09PWEpcmV0dXJuIG5uKCJoYXZlIG5vdCByZWNlaXZlZCBlbmQgb2YgSFRUUCBoZWFkZXJzIHlldC4uLiIpLHZvaWQgaSgpO2NvbnN0IGY9dS5zdWJhcnJheSgwLGEpLnRvU3RyaW5nKCJhc2NpaSIpLnNwbGl0KCJcclxuIiksaD1mLnNoaWZ0KCk7aWYoIWgpcmV0dXJuIHQuZGVzdHJveSgpLGUobmV3IEVycm9yKCJObyBoZWFkZXIgcmVjZWl2ZWQgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlIikpO2NvbnN0IHA9aC5zcGxpdCgiICIpLGQ9KyhwWzFdfHwwKSxsPXAuc2xpY2UoMikuam9pbigiICIpLGc9e307Zm9yKGNvbnN0IG4gb2YgZil7aWYoIW4pY29udGludWU7Y29uc3Qgcj1uLmluZGV4T2YoIjoiKTtpZigtMT09PXIpcmV0dXJuIHQuZGVzdHJveSgpLGUobmV3IEVycm9yKGBJbnZhbGlkIGhlYWRlciBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2U6ICIke259ImApKTtjb25zdCBvPW4uc2xpY2UoMCxyKS50b0xvd2VyQ2FzZSgpLGk9bi5zbGljZShyKzEpLnRyaW1TdGFydCgpLHM9Z1tvXTsic3RyaW5nIj09dHlwZW9mIHM/Z1tvXT1bcyxpXTpBcnJheS5pc0FycmF5KHMpP3MucHVzaChpKTpnW29dPWl9bm4oImdvdCBwcm94eSBzZXJ2ZXIgcmVzcG9uc2U6ICVvICVvIixoLGcpLHMoKSxuKHtjb25uZWN0OntzdGF0dXNDb2RlOmQsc3RhdHVzVGV4dDpsLGhlYWRlcnM6Z30sYnVmZmVyZWQ6dX0pfShjKTp0Lm9uY2UoInJlYWRhYmxlIixpKX1mdW5jdGlvbiBzKCl7dC5yZW1vdmVMaXN0ZW5lcigiZW5kIixjKSx0LnJlbW92ZUxpc3RlbmVyKCJlcnJvciIsdSksdC5yZW1vdmVMaXN0ZW5lcigicmVhZGFibGUiLGkpfWZ1bmN0aW9uIGMoKXtzKCksbm4oIm9uZW5kIiksZShuZXcgRXJyb3IoIlByb3h5IGNvbm5lY3Rpb24gZW5kZWQgYmVmb3JlIHJlY2VpdmluZyBDT05ORUNUIHJlc3BvbnNlIikpfWZ1bmN0aW9uIHUodCl7cygpLG5uKCJvbmVycm9yICVvIix0KSxlKHQpfXQub24oImVycm9yIix1KSx0Lm9uKCJlbmQiLGMpLGkoKX0pfWZ1bmN0aW9uIHJuKC4uLnQpe3cubG9nKCJbaHR0cHMtcHJveHktYWdlbnRdIiwuLi50KX1jbGFzcyBvbiBleHRlbmRzIHRue2NvbnN0cnVjdG9yKHQsbil7c3VwZXIobiksdGhpcy5vcHRpb25zPXt9LHRoaXMucHJveHk9InN0cmluZyI9PXR5cGVvZiB0P25ldyBVUkwodCk6dCx0aGlzLnByb3h5SGVhZGVycz1uPy5oZWFkZXJzPz97fSxybigiQ3JlYXRpbmcgbmV3IEh0dHBzUHJveHlBZ2VudCBpbnN0YW5jZTogJW8iLHRoaXMucHJveHkuaHJlZik7Y29uc3QgZT0odGhpcy5wcm94eS5ob3N0bmFtZXx8dGhpcy5wcm94eS5ob3N0KS5yZXBsYWNlKC9eXFt8XF0kL2csIiIpLHI9dGhpcy5wcm94eS5wb3J0P3BhcnNlSW50KHRoaXMucHJveHkucG9ydCwxMCk6Imh0dHBzOiI9PT10aGlzLnByb3h5LnByb3RvY29sPzQ0Mzo4MDt0aGlzLmNvbm5lY3RPcHRzPXtBTFBOUHJvdG9jb2xzOlsiaHR0cC8xLjEiXSwuLi5uP2NuKG4sImhlYWRlcnMiKTpudWxsLGhvc3Q6ZSxwb3J0OnJ9fWFzeW5jIGNvbm5lY3QodCxuKXtjb25zdHtwcm94eTplfT10aGlzO2lmKCFuLmhvc3QpdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gImhvc3QiIHByb3ZpZGVkJyk7bGV0IHI7aWYoImh0dHBzOiI9PT1lLnByb3RvY29sKXtybigiQ3JlYXRpbmcgYHRscy5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cyk7Y29uc3QgdD10aGlzLmNvbm5lY3RPcHRzLnNlcnZlcm5hbWV8fHRoaXMuY29ubmVjdE9wdHMuaG9zdDtyPWYuY29ubmVjdCh7Li4udGhpcy5jb25uZWN0T3B0cyxzZXJ2ZXJuYW1lOnQmJmEuaXNJUCh0KT92b2lkIDA6dH0pfWVsc2Ugcm4oIkNyZWF0aW5nIGBuZXQuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpLHI9YS5jb25uZWN0KHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IG89ImZ1bmN0aW9uIj09dHlwZW9mIHRoaXMucHJveHlIZWFkZXJzP3RoaXMucHJveHlIZWFkZXJzKCk6ey4uLnRoaXMucHJveHlIZWFkZXJzfSxpPWEuaXNJUHY2KG4uaG9zdCk/YFske24uaG9zdH1dYDpuLmhvc3Q7bGV0IHM9YENPTk5FQ1QgJHtpfToke24ucG9ydH0gSFRUUC8xLjFcclxuYDtpZihlLnVzZXJuYW1lfHxlLnBhc3N3b3JkKXtjb25zdCB0PWAke2RlY29kZVVSSUNvbXBvbmVudChlLnVzZXJuYW1lKX06JHtkZWNvZGVVUklDb21wb25lbnQoZS5wYXNzd29yZCl9YDtvWyJQcm94eS1BdXRob3JpemF0aW9uIl09YEJhc2ljICR7QnVmZmVyLmZyb20odCkudG9TdHJpbmcoImJhc2U2NCIpfWB9by5Ib3N0PWAke2l9OiR7bi5wb3J0fWAsb1siUHJveHktQ29ubmVjdGlvbiJdfHwob1siUHJveHktQ29ubmVjdGlvbiJdPXRoaXMua2VlcEFsaXZlPyJLZWVwLUFsaXZlIjoiY2xvc2UiKTtmb3IoY29uc3QgdCBvZiBPYmplY3Qua2V5cyhvKSlzKz1gJHt0fTogJHtvW3RdfVxyXG5gO2NvbnN0IGM9ZW4ocik7ci53cml0ZShgJHtzfVxyXG5gKTtjb25zdHtjb25uZWN0OnUsYnVmZmVyZWQ6aH09YXdhaXQgYztpZih0LmVtaXQoInByb3h5Q29ubmVjdCIsdSksdGhpcy5lbWl0KCJwcm94eUNvbm5lY3QiLHUsdCksMjAwPT09dS5zdGF0dXNDb2RlKXtpZih0Lm9uY2UoInNvY2tldCIsc24pLG4uc2VjdXJlRW5kcG9pbnQpe3JuKCJVcGdyYWRpbmcgc29ja2V0IGNvbm5lY3Rpb24gdG8gVExTIik7Y29uc3QgdD1uLnNlcnZlcm5hbWV8fG4uaG9zdDtyZXR1cm4gZi5jb25uZWN0KHsuLi5jbihuLCJob3N0IiwicGF0aCIsInBvcnQiKSxzb2NrZXQ6cixzZXJ2ZXJuYW1lOmEuaXNJUCh0KT92b2lkIDA6dH0pfXJldHVybiByfXIuZGVzdHJveSgpO2NvbnN0IHA9bmV3IGEuU29ja2V0KHt3cml0YWJsZTohMX0pO3JldHVybiBwLnJlYWRhYmxlPSEwLHQub25jZSgic29ja2V0Iix0PT57cm4oIlJlcGxheWluZyBwcm94eSBidWZmZXIgZm9yIGZhaWxlZCByZXF1ZXN0IiksdC5wdXNoKGgpLHQucHVzaChudWxsKX0pLHB9fWZ1bmN0aW9uIHNuKHQpe3QucmVzdW1lKCl9ZnVuY3Rpb24gY24odCwuLi5uKXtjb25zdCBlPXt9O2xldCByO2ZvcihyIGluIHQpbi5pbmNsdWRlcyhyKXx8KGVbcl09dFtyXSk7cmV0dXJuIGV9b24ucHJvdG9jb2xzPVsiaHR0cCIsImh0dHBzIl07ZnVuY3Rpb24gdW4odCl7cmV0dXJuIHQucmVwbGFjZSgvXltBLVpdOi8sIiIpLnJlcGxhY2UoL1xcL2csIi8iKX1jb25zdCBhbj1uO2xldCBmbixobj0wLHBuPXt9O2Z1bmN0aW9uIGRuKHQpe2FuLmRlYnVnJiZjb25zb2xlLmxvZyhgW0FOUiBXb3JrZXJdICR7dH1gKX12YXIgbG4sZ24sbW47Y29uc3QgeW49ZnVuY3Rpb24odCl7bGV0IG47dHJ5e249bmV3IFVSTCh0LnVybCl9Y2F0Y2gobil7cmV0dXJuIGIoKCk9Pntjb25zb2xlLndhcm4oIltAc2VudHJ5L25vZGVdOiBJbnZhbGlkIGRzbiBvciB0dW5uZWwgb3B0aW9uLCB3aWxsIG5vdCBzZW5kIGFueSBldmVudHMuIFRoZSB0dW5uZWwgb3B0aW9uIG11c3QgYmUgYSBmdWxsIFVSTCB3aGVuIHVzZWQuIil9KSxLdCh0LCgpPT5Qcm9taXNlLnJlc29sdmUoe30pKX1jb25zdCBlPSJodHRwczoiPT09bi5wcm90b2NvbCxyPWZ1bmN0aW9uKHQsbil7Y29uc3R7bm9fcHJveHk6ZX09cHJvY2Vzcy5lbnYscj1lPy5zcGxpdCgiLCIpLnNvbWUobj0+dC5ob3N0LmVuZHNXaXRoKG4pfHx0Lmhvc3RuYW1lLmVuZHNXaXRoKG4pKTtyZXR1cm4gcj92b2lkIDA6bn0obix0LnByb3h5fHwoZT9wcm9jZXNzLmVudi5odHRwc19wcm94eTp2b2lkIDApfHxwcm9jZXNzLmVudi5odHRwX3Byb3h5KSxvPWU/czppLGE9dm9pZCAwIT09dC5rZWVwQWxpdmUmJnQua2VlcEFsaXZlLGY9cj9uZXcgb24ocik6bmV3IG8uQWdlbnQoe2tlZXBBbGl2ZTphLG1heFNvY2tldHM6MzAsdGltZW91dDoyZTN9KSxoPWZ1bmN0aW9uKHQsbixlKXtjb25zdHtob3N0bmFtZTpyLHBhdGhuYW1lOm8scG9ydDppLHByb3RvY29sOnMsc2VhcmNoOmF9PW5ldyBVUkwodC51cmwpO3JldHVybiBmdW5jdGlvbihmKXtyZXR1cm4gbmV3IFByb21pc2UoKGgscCk9PntGdCgoKT0+e2xldCBkPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgYyh7cmVhZCgpe3RoaXMucHVzaCh0KSx0aGlzLnB1c2gobnVsbCl9fSl9KGYuYm9keSk7Y29uc3QgbD17Li4udC5oZWFkZXJzfTtmLmJvZHkubGVuZ3RoPjMyNzY4JiYobFsiY29udGVudC1lbmNvZGluZyJdPSJnemlwIixkPWQucGlwZSh1KCkpKTtjb25zdCBnPXIuc3RhcnRzV2l0aCgiWyIpLG09bi5yZXF1ZXN0KHttZXRob2Q6IlBPU1QiLGFnZW50OmUsaGVhZGVyczpsLGhvc3RuYW1lOmc/ci5zbGljZSgxLC0xKTpyLHBhdGg6YCR7b30ke2F9YCxwb3J0OmkscHJvdG9jb2w6cyxjYTp0LmNhQ2VydHN9LHQ9Pnt0Lm9uKCJkYXRhIiwoKT0+e30pLHQub24oImVuZCIsKCk9Pnt9KSx0LnNldEVuY29kaW5nKCJ1dGY4Iik7Y29uc3Qgbj10LmhlYWRlcnNbInJldHJ5LWFmdGVyIl0/P251bGwsZT10LmhlYWRlcnNbIngtc2VudHJ5LXJhdGUtbGltaXRzIl0/P251bGw7aCh7c3RhdHVzQ29kZTp0LnN0YXR1c0NvZGUsaGVhZGVyczp7InJldHJ5LWFmdGVyIjpuLCJ4LXNlbnRyeS1yYXRlLWxpbWl0cyI6QXJyYXkuaXNBcnJheShlKT9lWzBdfHxudWxsOmV9fSl9KTttLm9uKCJlcnJvciIscCksZC5waXBlKG0pfSl9KX19KHQsdC5odHRwTW9kdWxlPz9vLGYpO3JldHVybiBLdCh0LGgpfSh7dXJsOihsbj1hbi5kc24sZ249YW4udHVubmVsLG1uPWFuLnNka01ldGFkYXRhLnNkayxnbnx8YCR7ZnVuY3Rpb24odCl7cmV0dXJuYCR7ZnVuY3Rpb24odCl7Y29uc3Qgbj10LnByb3RvY29sP2Ake3QucHJvdG9jb2x9OmA6IiIsZT10LnBvcnQ/YDoke3QucG9ydH1gOiIiO3JldHVybmAke259Ly8ke3QuaG9zdH0ke2V9JHt0LnBhdGg/YC8ke3QucGF0aH1gOiIifS9hcGkvYH0odCl9JHt0LnByb2plY3RJZH0vZW52ZWxvcGUvYH0obG4pfT8ke2Z1bmN0aW9uKHQsbil7Y29uc3QgZT17c2VudHJ5X3ZlcnNpb246IjcifTtyZXR1cm4gdC5wdWJsaWNLZXkmJihlLnNlbnRyeV9rZXk9dC5wdWJsaWNLZXkpLG4mJihlLnNlbnRyeV9jbGllbnQ9YCR7bi5uYW1lfS8ke24udmVyc2lvbn1gKSxuZXcgVVJMU2VhcmNoUGFyYW1zKGUpLnRvU3RyaW5nKCl9KGxuLG1uKX1gKX0pO2FzeW5jIGZ1bmN0aW9uIGJuKCl7aWYoZm4pe2RuKCJTZW5kaW5nIGFibm9ybWFsIHNlc3Npb24iKSxLKGZuLHtzdGF0dXM6ImFibm9ybWFsIixhYm5vcm1hbF9tZWNoYW5pc206ImFucl9mb3JlZ3JvdW5kIixyZWxlYXNlOmFuLnJlbGVhc2UsZW52aXJvbm1lbnQ6YW4uZW52aXJvbm1lbnR9KTtjb25zdCB0PWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89THQoZSk7cmV0dXJuIFR0KHtzZW50X2F0Om5ldyBEYXRlKFAoKSkudG9JU09TdHJpbmcoKSwuLi5vJiZ7c2RrOm99LC4uLiEhciYmbiYme2RzbjpidChuKX19LFsiYWdncmVnYXRlcyJpbiB0P1t7dHlwZToic2Vzc2lvbnMifSx0XTpbe3R5cGU6InNlc3Npb24ifSx0LnRvSlNPTigpXV0pfShmbixhbi5kc24sYW4uc2RrTWV0YWRhdGEsYW4udHVubmVsKTtkbihKU09OLnN0cmluZ2lmeSh0KSksYXdhaXQgeW4uc2VuZCh0KTt0cnl7ZT8ucG9zdE1lc3NhZ2UoInNlc3Npb24tZW5kZWQiKX1jYXRjaHt9fX1mdW5jdGlvbiB2bih0KXtpZighdClyZXR1cm47Y29uc3Qgbj1mdW5jdGlvbih0KXtpZighdC5sZW5ndGgpcmV0dXJuW107Y29uc3Qgbj1BcnJheS5mcm9tKHQpO3JldHVybi9zZW50cnlXcmFwcGVkLy50ZXN0KEUobikuZnVuY3Rpb258fCIiKSYmbi5wb3AoKSxuLnJldmVyc2UoKSwkLnRlc3QoRShuKS5mdW5jdGlvbnx8IiIpJiYobi5wb3AoKSwkLnRlc3QoRShuKS5mdW5jdGlvbnx8IiIpJiZuLnBvcCgpKSxuLnNsaWNlKDAsNTApLm1hcCh0PT4oey4uLnQsZmlsZW5hbWU6dC5maWxlbmFtZXx8RShuKS5maWxlbmFtZSxmdW5jdGlvbjp0LmZ1bmN0aW9ufHwiPyJ9KSl9KHQpO2lmKGFuLmFwcFJvb3RQYXRoKWZvcihjb25zdCB0IG9mIG4pdC5maWxlbmFtZSYmKHQuZmlsZW5hbWU9TSh0LmZpbGVuYW1lLGFuLmFwcFJvb3RQYXRoKSk7cmV0dXJuIG59YXN5bmMgZnVuY3Rpb24gX24odCxuKXtpZihobj49YW4ubWF4QW5yRXZlbnRzKXJldHVybjtobis9MSxhd2FpdCBibigpLGRuKCJTZW5kaW5nIGV2ZW50Iik7Y29uc3QgZT17ZXZlbnRfaWQ6RygpLGNvbnRleHRzOmFuLmNvbnRleHRzLHJlbGVhc2U6YW4ucmVsZWFzZSxlbnZpcm9ubWVudDphbi5lbnZpcm9ubWVudCxkaXN0OmFuLmRpc3QscGxhdGZvcm06Im5vZGUiLGxldmVsOiJlcnJvciIsZXhjZXB0aW9uOnt2YWx1ZXM6W3t0eXBlOiJBcHBsaWNhdGlvbk5vdFJlc3BvbmRpbmciLHZhbHVlOmBBcHBsaWNhdGlvbiBOb3QgUmVzcG9uZGluZyBmb3IgYXQgbGVhc3QgJHthbi5hbnJUaHJlc2hvbGR9IG1zYCxzdGFja3RyYWNlOntmcmFtZXM6dm4odCl9LG1lY2hhbmlzbTp7dHlwZToiQU5SIn19XX0sdGFnczphbi5zdGF0aWNUYWdzfTtuJiZmdW5jdGlvbih0LG4pe2lmKEd0KHQsbiksIXQuY29udGV4dHM/LnRyYWNlKXtjb25zdHt0cmFjZUlkOmUscGFyZW50U3BhbklkOnIscHJvcGFnYXRpb25TcGFuSWQ6b309bi5wcm9wYWdhdGlvbkNvbnRleHQ7dC5jb250ZXh0cz17dHJhY2U6e3RyYWNlX2lkOmUsc3Bhbl9pZDpvfHxWKCkscGFyZW50X3NwYW5faWQ6cn0sLi4udC5jb250ZXh0c319fShlLG4pLGZ1bmN0aW9uKHQpe2lmKDA9PT1PYmplY3Qua2V5cyhwbikubGVuZ3RoKXJldHVybjtjb25zdCBuPWFuLmFwcFJvb3RQYXRoP3t9OnBuO2lmKGFuLmFwcFJvb3RQYXRoKWZvcihjb25zdFt0LGVdb2YgT2JqZWN0LmVudHJpZXMocG4pKW5bTSh0LGFuLmFwcFJvb3RQYXRoKV09ZTtjb25zdCBlPW5ldyBNYXA7Zm9yKGNvbnN0IHIgb2YgdC5leGNlcHRpb24/LnZhbHVlc3x8W10pZm9yKGNvbnN0IHQgb2Ygci5zdGFja3RyYWNlPy5mcmFtZXN8fFtdKXtjb25zdCByPXQuYWJzX3BhdGh8fHQuZmlsZW5hbWU7ciYmbltyXSYmZS5zZXQocixuW3JdKX1pZihlLnNpemU+MCl7Y29uc3Qgbj1bXTtmb3IoY29uc3RbdCxyXW9mIGUuZW50cmllcygpKW4ucHVzaCh7dHlwZToic291cmNlbWFwIixjb2RlX2ZpbGU6dCxkZWJ1Z19pZDpyfSk7dC5kZWJ1Z19tZXRhPXtpbWFnZXM6bn19fShlKTtjb25zdCByPU10KGUsYW4uZHNuLGFuLnNka01ldGFkYXRhLGFuLnR1bm5lbCk7ZG4oSlNPTi5zdHJpbmdpZnkocikpLGF3YWl0IHluLnNlbmQociksYXdhaXQgeW4uZmx1c2goMmUzKSxobj49YW4ubWF4QW5yRXZlbnRzJiZzZXRUaW1lb3V0KCgpPT57cHJvY2Vzcy5leGl0KDApfSw1ZTMpfWxldCBTbjtpZihkbigiU3RhcnRlZCIpLGFuLmNhcHR1cmVTdGFja1RyYWNlKXtkbigiQ29ubmVjdGluZyB0byBkZWJ1Z2dlciIpO2NvbnN0IG49bmV3IHQ7bi5jb25uZWN0VG9NYWluVGhyZWFkKCksZG4oIkNvbm5lY3RlZCB0byBkZWJ1Z2dlciIpO2NvbnN0IGU9bmV3IE1hcDtuLm9uKCJEZWJ1Z2dlci5zY3JpcHRQYXJzZWQiLHQ9PntlLnNldCh0LnBhcmFtcy5zY3JpcHRJZCx0LnBhcmFtcy51cmwpfSksbi5vbigiRGVidWdnZXIucGF1c2VkIix0PT57aWYoIm90aGVyIj09PXQucGFyYW1zLnJlYXNvbil0cnl7ZG4oIkRlYnVnZ2VyIHBhdXNlZCIpO2NvbnN0IGk9Wy4uLnQucGFyYW1zLmNhbGxGcmFtZXNdLHM9YW4uYXBwUm9vdFBhdGg/ZnVuY3Rpb24odD0ocHJvY2Vzcy5hcmd2WzFdP3F0KHByb2Nlc3MuYXJndlsxXSk6cHJvY2Vzcy5jd2QoKSksbj0iXFwiPT09byl7Y29uc3QgZT1uP3VuKHQpOnQ7cmV0dXJuIHQ9PntpZighdClyZXR1cm47Y29uc3Qgbz1uP3VuKHQpOnQ7bGV0e2RpcjppLGJhc2U6cyxleHQ6Y309ci5wYXJzZShvKTsiLmpzIiE9PWMmJiIubWpzIiE9PWMmJiIuY2pzIiE9PWN8fChzPXMuc2xpY2UoMCwtMSpjLmxlbmd0aCkpO2NvbnN0IHU9ZGVjb2RlVVJJQ29tcG9uZW50KHMpO2l8fChpPSIuIik7Y29uc3QgYT1pLmxhc3RJbmRleE9mKCIvbm9kZV9tb2R1bGVzIik7aWYoYT4tMSlyZXR1cm5gJHtpLnNsaWNlKGErMTQpLnJlcGxhY2UoL1wvL2csIi4iKX06JHt1fWA7aWYoaS5zdGFydHNXaXRoKGUpKXtjb25zdCB0PWkuc2xpY2UoZS5sZW5ndGgrMSkucmVwbGFjZSgvXC8vZywiLiIpO3JldHVybiB0P2Ake3R9OiR7dX1gOnV9cmV0dXJuIHV9fShhbi5hcHBSb290UGF0aCk6KCk9Pnt9LGM9aS5tYXAodD0+ZnVuY3Rpb24odCxuLGUpe2NvbnN0IHI9bj9uLnJlcGxhY2UoL15maWxlOlwvXC8vLCIiKTp2b2lkIDAsbz10LmxvY2F0aW9uLmNvbHVtbk51bWJlcj90LmxvY2F0aW9uLmNvbHVtbk51bWJlcisxOnZvaWQgMCxpPXQubG9jYXRpb24ubGluZU51bWJlcj90LmxvY2F0aW9uLmxpbmVOdW1iZXIrMTp2b2lkIDA7cmV0dXJue2ZpbGVuYW1lOnIsbW9kdWxlOmUociksZnVuY3Rpb246dC5mdW5jdGlvbk5hbWV8fCI/Iixjb2xubzpvLGxpbmVubzppLGluX2FwcDpyP1Z0KHIpOnZvaWQgMH19KHQsZS5nZXQodC5sb2NhdGlvbi5zY3JpcHRJZCkscykpLHU9c2V0VGltZW91dCgoKT0+e19uKGMpLnRoZW4obnVsbCwoKT0+e2RuKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuIil9KX0sNWUzKTtuLnBvc3QoIlJ1bnRpbWUuZXZhbHVhdGUiLHtleHByZXNzaW9uOiJnbG9iYWwuX19TRU5UUllfR0VUX1NDT1BFU19fKCk7IixzaWxlbnQ6ITAscmV0dXJuQnlWYWx1ZTohMH0sKHQsZSk9Pnt0JiZkbihgRXJyb3IgZXhlY3V0aW5nIHNjcmlwdDogJyR7dC5tZXNzYWdlfSdgKSxjbGVhclRpbWVvdXQodSk7Y29uc3Qgcj1lPy5yZXN1bHQ/ZS5yZXN1bHQudmFsdWU6dm9pZCAwO24ucG9zdCgiRGVidWdnZXIucmVzdW1lIiksbi5wb3N0KCJEZWJ1Z2dlci5kaXNhYmxlIiksX24oYyxyKS50aGVuKG51bGwsKCk9PntkbigiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSl9KX1jYXRjaCh0KXt0aHJvdyBuLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLG4ucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLHR9fSksU249KCk9Pnt0cnl7bi5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiLCgpPT57bi5wb3N0KCJEZWJ1Z2dlci5wYXVzZSIpfSl9Y2F0Y2h7fX19Y29uc3R7cG9sbDp3bn09ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz10KCk7bGV0IGk9ITEscz0hMDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCk9Pntjb25zdCB0PW8uZ2V0VGltZU1zKCk7ITE9PT1pJiZ0Pm4rZSYmKGk9ITAscyYmcigpKSx0PG4rZSYmKGk9ITEpfSwyMCkse3BvbGw6KCk9PntvLnJlc2V0KCl9LGVuYWJsZWQ6dD0+e3M9dH19fShmdW5jdGlvbigpe2xldCB0PXByb2Nlc3MuaHJ0aW1lKCk7cmV0dXJue2dldFRpbWVNczooKT0+e2NvbnN0W24sZV09cHJvY2Vzcy5ocnRpbWUodCk7cmV0dXJuIE1hdGguZmxvb3IoMWUzKm4rZS8xZTYpfSxyZXNldDooKT0+e3Q9cHJvY2Vzcy5ocnRpbWUoKX19fSxhbi5wb2xsSW50ZXJ2YWwsYW4uYW5yVGhyZXNob2xkLGZ1bmN0aW9uKCl7ZG4oIldhdGNoZG9nIHRpbWVvdXQiKSxTbj8oZG4oIlBhdXNpbmcgZGVidWdnZXIgdG8gY2FwdHVyZSBzdGFjayB0cmFjZSIpLFNuKCkpOihkbigiQ2FwdHVyaW5nIGV2ZW50IHdpdGhvdXQgYSBzdGFjayB0cmFjZSIpLF9uKCkudGhlbihudWxsLCgpPT57ZG4oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZCBvbiB3YXRjaGRvZyB0aW1lb3V0LiIpfSkpfSk7ZT8ub24oIm1lc3NhZ2UiLHQ9Pnt0LnNlc3Npb24mJihmbj1IKHQuc2Vzc2lvbikpLHQuZGVidWdJbWFnZXMmJihwbj10LmRlYnVnSW1hZ2VzKSx3bigpfSk7"; | ||
| const DEFAULT_INTERVAL = 50; | ||
@@ -11,0 +11,0 @@ const DEFAULT_HANG_THRESHOLD = 5e3; |
@@ -1,2 +0,2 @@ | ||
| /*! @sentry/node-core 10.63.0 (2362e9f) | https://github.com/getsentry/sentry-javascript */ | ||
| import{Session as t}from"node:inspector";import{workerData as n,parentPort as e}from"node:worker_threads";import{posix as r,sep as o}from"node:path";import*as i from"node:http";import*as s from"node:https";import{Readable as c}from"node:stream";import{createGzip as u}from"node:zlib";import*as a from"node:net";import*as f from"node:tls";const h="undefined"==typeof __SENTRY_DEBUG__||__SENTRY_DEBUG__,p=globalThis,d="10.63.0";function l(){return g(p),p}function g(t){const n=t.__SENTRY__=t.__SENTRY__||{};return n.version=n.version||d,n[d]=n[d]||{}}function m(t,n,e=p){const r=e.__SENTRY__=e.__SENTRY__||{},o=r[d]=r[d]||{};return o[t]||(o[t]=n())}const y={};function b(t){if(!("console"in p))return t();const n=p.console,e={},r=Object.keys(y);r.forEach(t=>{const r=y[t];e[t]=n[t],n[t]=r});try{return t()}finally{r.forEach(t=>{n[t]=e[t]})}}function v(){return S().enabled}function _(t,...n){h&&v()&&b(()=>{p.console[t](`Sentry Logger [${t}]:`,...n)})}function S(){return h?m("loggerSettings",()=>({enabled:!1})):{enabled:!1}}const w={enable:function(){S().enabled=!0},disable:function(){S().enabled=!1},isEnabled:v,log:function(...t){_("log",...t)},warn:function(...t){_("warn",...t)},error:function(...t){_("error",...t)}},$=/captureMessage|captureException/;function E(t){return t[t.length-1]||{}}const x="<anonymous>";const N=Object.prototype.toString;function C(t,n){return N.call(t)===`[object ${n}]`}function j(t){return Boolean(t?.then&&"function"==typeof t.then)}function R(t,n){try{return t instanceof n}catch{return!1}}function A(t){if(function(t){switch(N.call(t)){case"[object Error]":case"[object Exception]":case"[object DOMException]":case"[object WebAssembly.Exception]":return!0;default:return R(t,Error)}}(t))return{message:t.message,name:t.name,stack:t.stack,...I(t)};if(n=t,"undefined"!=typeof Event&&R(n,Event)){const{type:n,target:e,currentTarget:r,detail:o}=t;return{type:n,target:e,currentTarget:r,...o?{detail:o}:{},...I(t)}}var n;return t}function I(t){return"object"==typeof t&&null!==t?Object.fromEntries(Object.entries(t)):{}}let O;function T(t){if(void 0!==O)return O?O(t):t();const n=Symbol.for("__SENTRY_SAFE_RANDOM_ID_WRAPPER__"),e=p;return n in e&&"function"==typeof e[n]?(O=e[n],O(t)):(O=null,t())}function k(){return T(()=>Math.random())}function P(){return T(()=>Date.now())}const D=Symbol.for("sentry.skipNormalization"),U=Symbol.for("sentry.overrideNormalizationDepth");function B(t,n=100,e=1/0){try{return L("",t,n,e)}catch(t){return{ERROR:`**non-serializable** (${t})`}}}function L(t,n,e=1/0,r=1/0,o=function(){const t=new WeakSet;function n(n){return!!t.has(n)||(t.add(n),!1)}function e(n){t.delete(n)}return[n,e]}()){const[i,s]=o;if(null==n||["boolean","string"].includes(typeof n)||"number"==typeof n&&Number.isFinite(n))return n;const c=function(t,n){try{if("undefined"!=typeof global&&n===global)return"[Global]";if("number"==typeof n&&!Number.isFinite(n))return`[${n}]`;if("function"==typeof n)return`[Function: ${function(t){try{return t&&"function"==typeof t&&t.name||x}catch{return x}}(n)}]`;if("symbol"==typeof n)return`[${String(n)}]`;if("bigint"==typeof n)return`[BigInt: ${String(n)}]`;const t=function(t){const n=Object.getPrototypeOf(t);return n?.constructor?n.constructor.name:"null prototype"}(n);return`[object ${t}]`}catch(t){return`**non-serializable** (${t})`}}(0,n);if(!c.startsWith("[object "))return c;if(function(t){return Boolean(t[D])}(n))return n;const u=function(t){const n=t[U];return"number"==typeof n?n:void 0}(n),a=void 0!==u?u:e;if(0===a)return c.replace("object ","");if(i(n))return"[Circular ~]";const f=n;if(f&&"function"==typeof f.toJSON)try{return L("",f.toJSON(),a-1,r,o)}catch{}const h=Array.isArray(n)?[]:{};let p=0;const d=A(n);for(const t in d){if(!Object.prototype.hasOwnProperty.call(d,t))continue;if(p>=r){h[t]="[MaxProperties ~]";break}const n=d[t];h[t]=L(t,n,a-1,r,o),p++}return s(n),h}function M(t,n){const e=n.replace(/\\/g,"/").replace(/[|\\{}()[\]^$+*?.]/g,"\\$&");let r=t;try{r=decodeURI(t)}catch{}return r.replace(/\\/g,"/").replace(/webpack:\/?/g,"").replace(new RegExp(`(file://)?/*${e}/*`,"ig"),"app:///")}function z(t,n=0){return"string"!=typeof t||0===n||t.length<=n?t:`${t.slice(0,n)}...`}let F;function G(t=function(){const t=p;return t.crypto||t.msCrypto}()){try{if(t?.randomUUID)return T(()=>t.randomUUID()).replace(/-/g,"")}catch{}return F||(F="10000000100040008000100000000000"),F.replace(/[018]/g,t=>(t^(16*k()&15)>>t/4).toString(16))}function J(){return P()/1e3}let W;function Y(){return(W??(W=function(){const{performance:t}=p;if(!t?.now||!t.timeOrigin)return J;const n=t.timeOrigin;return()=>(n+T(()=>t.now()))/1e3}()))()}function H(t){const n=Y(),e={sid:G(),init:!0,timestamp:n,started:n,duration:0,status:"ok",errors:0,ignoreDuration:!1,toJSON:()=>function(t){return{sid:`${t.sid}`,init:t.init,started:new Date(1e3*t.started).toISOString(),timestamp:new Date(1e3*t.timestamp).toISOString(),status:t.status,errors:t.errors,did:"number"==typeof t.did||"string"==typeof t.did?`${t.did}`:void 0,duration:t.duration,abnormal_mechanism:t.abnormal_mechanism,attrs:{release:t.release,environment:t.environment,ip_address:t.ipAddress,user_agent:t.userAgent}}}(e)};return t&&K(e,t),e}function K(t,n={}){if(n.user&&(!t.ipAddress&&n.user.ip_address&&(t.ipAddress=n.user.ip_address),t.did||n.did||(t.did=n.user.id||n.user.email||n.user.username)),t.timestamp=n.timestamp||Y(),n.abnormal_mechanism&&(t.abnormal_mechanism=n.abnormal_mechanism),n.ignoreDuration&&(t.ignoreDuration=n.ignoreDuration),n.sid&&(t.sid=32===n.sid.length?n.sid:G()),void 0!==n.init&&(t.init=n.init),!t.did&&n.did&&(t.did=`${n.did}`),"number"==typeof n.started&&(t.started=n.started),t.ignoreDuration)t.duration=void 0;else if("number"==typeof n.duration)t.duration=n.duration;else{const n=t.timestamp-t.started;t.duration=n>=0?n:0}n.release&&(t.release=n.release),n.environment&&(t.environment=n.environment),!t.ipAddress&&n.ipAddress&&(t.ipAddress=n.ipAddress),!t.userAgent&&n.userAgent&&(t.userAgent=n.userAgent),"number"==typeof n.errors&&(t.errors=n.errors),n.status&&(t.status=n.status)}function Z(t,n,e=2){if(!n||"object"!=typeof n||e<=0)return n;if(t&&0===Object.keys(n).length)return t;const r={...t};for(const t in n)Object.prototype.hasOwnProperty.call(n,t)&&(r[t]=Z(r[t],n[t],e-1));return r}function q(){return G()}function V(){return G().substring(16)}function Q(t){if(t){if("object"==typeof t&&"deref"in t&&"function"==typeof t.deref)try{return t.deref()}catch{return}return t}}const X="_sentrySpan";function tt(t,n){n?function(t,n,e){try{Object.defineProperty(t,n,{value:e,writable:!0,configurable:!0})}catch{h&&w.log(`Failed to add non-enumerable property "${String(n)}" to object`,t)}}(t,X,function(t){try{const n=p.WeakRef;if("function"==typeof n)return new n(t)}catch{}return t}(n)):delete t[X]}function nt(t){return Q(t[X])}class et{constructor(){this.t=!1,this.o=[],this.i=[],this.u=[],this.h=[],this.p={},this.l={},this.m={},this.v={},this._={},this.S={},this.N={traceId:q(),sampleRand:k()}}clone(){const t=new et;return t.u=[...this.u],t.l={...this.l},t.m={...this.m},t.v={...this.v},t._={...this._},this._.flags&&(t._.flags={values:[...this._.flags.values]}),t.p=this.p,t.C=this.C,t.j=this.j,t.R=this.R,t.A=this.A,t.i=[...this.i],t.h=[...this.h],t.S={...this.S},t.N={...this.N},t.I=this.I,t.O=this.O,t.T=this.T,tt(t,nt(this)),t}setClient(t){this.I=t}setLastEventId(t){this.O=t}getClient(){return this.I}lastEventId(){return this.O}addScopeListener(t){this.o.push(t)}addEventProcessor(t){return this.i.push(t),this}setUser(t){return this.p=t||{email:void 0,id:void 0,ip_address:void 0,username:void 0},this.j&&K(this.j,{user:t}),this.k(),this}getUser(){return this.p}setConversationId(t){return this.T=t||void 0,this.k(),this}setTags(t){return this.l={...this.l,...t},this.k(),this}setTag(t,n){return this.setTags({[t]:n})}setAttributes(t){return this.m={...this.m,...t},this.k(),this}setAttribute(t,n){return this.setAttributes({[t]:n})}removeAttribute(t){return t in this.m&&(delete this.m[t],this.k()),this}setExtras(t){return this.v={...this.v,...t},this.k(),this}setExtra(t,n){return this.v={...this.v,[t]:n},this.k(),this}setFingerprint(t){return this.A=t,this.k(),this}setLevel(t){return this.C=t,this.k(),this}setTransactionName(t){return this.R=t,this.k(),this}setContext(t,n){return null===n?delete this._[t]:this._[t]=n,this.k(),this}setSession(t){return t?this.j=t:delete this.j,this.k(),this}getSession(){return this.j}update(t){if(!t)return this;const n="function"==typeof t?t(this):t,e=n instanceof et?n.getScopeData():C(n,"Object")?t:void 0;const{tags:r,attributes:o,extra:i,user:s,contexts:c,level:u,fingerprint:a=[],propagationContext:f,conversationId:h}=e||{};return this.l={...this.l,...r},this.m={...this.m,...o},this.v={...this.v,...i},this._={...this._,...c},s&&Object.keys(s).length&&(this.p=s),u&&(this.C=u),a.length&&(this.A=a),f&&(this.N=f),h&&(this.T=h),this}clear(){return this.u=[],this.l={},this.m={},this.v={},this.p={},this._={},this.C=void 0,this.R=void 0,this.A=void 0,this.j=void 0,this.T=void 0,tt(this,void 0),this.h=[],this.setPropagationContext({traceId:q(),sampleRand:k()}),this.k(),this}addBreadcrumb(t,n){const e="number"==typeof n?n:100;if(e<=0)return this;const r={timestamp:J(),...t,message:t.message?z(t.message,2048):t.message};return this.u.push(r),this.u.length>e&&(this.u=this.u.slice(-e),this.I?.recordDroppedEvent("buffer_overflow","log_item")),this.k(),this}getLastBreadcrumb(){return this.u[this.u.length-1]}clearBreadcrumbs(){return this.u=[],this.k(),this}addAttachment(t){return this.h.push(t),this}clearAttachments(){return this.h=[],this}getScopeData(){return{breadcrumbs:this.u,attachments:this.h,contexts:this._,tags:this.l,attributes:this.m,extra:this.v,user:this.p,level:this.C,fingerprint:this.A||[],eventProcessors:this.i,propagationContext:this.N,sdkProcessingMetadata:this.S,transactionName:this.R,span:nt(this),conversationId:this.T}}setSDKProcessingMetadata(t){return this.S=Z(this.S,t,2),this}setPropagationContext(t){return this.N=t,this}getPropagationContext(){return this.N}captureException(t,n){const e=n?.event_id||G();if(!this.I)return h&&w.warn("No client configured on scope - will not capture exception!"),e;const r=new Error("Sentry syntheticException");return this.I.captureException(t,{originalException:t,syntheticException:r,...n,event_id:e},this),e}captureMessage(t,n,e){const r=e?.event_id||G();if(!this.I)return h&&w.warn("No client configured on scope - will not capture message!"),r;const o=e?.syntheticException??new Error(t);return this.I.captureMessage(t,n,{originalException:t,syntheticException:o,...e,event_id:r},this),r}captureEvent(t,n){const e=t.event_id||n?.event_id||G();return this.I?(this.I.captureEvent(t,{...n,event_id:e},this),e):(h&&w.warn("No client configured on scope - will not capture event!"),e)}k(){this.t||(this.t=!0,this.o.forEach(t=>{t(this)}),this.t=!1)}}const rt=t=>t instanceof Promise&&!t[ot],ot=Symbol("chained PromiseLike"),it=(t,n)=>{if(!n)return t;let e=!1;for(const r in t){if(r in n)continue;e=!0;const o=t[r];"function"==typeof o?Object.defineProperty(n,r,{value:(...n)=>o.apply(t,n),enumerable:!0,configurable:!0,writable:!0}):n[r]=o}return e&&Object.assign(n,{[ot]:!0}),n};class st{constructor(t,n){let e,r;e=t||new et,r=n||new et,this.P=[{scope:e}],this.D=r}withScope(t){const n=this.U();let e;try{e=t(n)}catch(t){throw this.B(),t}return j(e)?((t,n,e)=>{const r=t.then(t=>(n(t),t),t=>{throw e(t),t});return rt(r)&&rt(t)?r:it(t,r)})(e,()=>this.B(),()=>this.B()):(this.B(),e)}getClient(){return this.getStackTop().client}getScope(){return this.getStackTop().scope}getIsolationScope(){return this.D}getStackTop(){return this.P[this.P.length-1]}U(){const t=this.getScope().clone();return this.P.push({client:this.getClient(),scope:t}),t}B(){return!(this.P.length<=1)&&!!this.P.pop()}}function ct(){const t=g(l());return t.stack=t.stack||new st(m("defaultCurrentScope",()=>new et),m("defaultIsolationScope",()=>new et))}function ut(t){return ct().withScope(t)}function at(t,n){const e=ct();return e.withScope(()=>(e.getStackTop().scope=t,n(t)))}function ft(t){return ct().withScope(()=>t(ct().getIsolationScope()))}function ht(t){const n=g(t);return n.acs?n.acs:{withIsolationScope:ft,withScope:ut,withSetScope:at,withSetIsolationScope:(t,n)=>ft(n),getCurrentScope:()=>ct().getScope(),getIsolationScope:()=>ct().getIsolationScope()}}function pt(){return ht(l()).getCurrentScope().getClient()}function dt(t){const n=t;return{scope:n._sentryScope,isolationScope:Q(n._sentryIsolationScope)}}const lt="sentry-";function gt(t){const n=function(t){if(!t||(n=t,!C(n,"String")&&!Array.isArray(t)))return;var n;if(Array.isArray(t))return t.reduce((t,n)=>{const e=mt(n);return Object.entries(e).forEach(([n,e])=>{t[n]=e}),t},{});return mt(t)}(t);if(!n)return;const e=Object.entries(n).reduce((t,[n,e])=>{if(n.startsWith(lt)){t[n.slice(7)]=e}return t},{});return Object.keys(e).length>0?e:void 0}function mt(t){return t.split(",").map(t=>{const n=t.indexOf("=");if(-1===n)return[];return[t.slice(0,n),t.slice(n+1)].map(t=>{try{return decodeURIComponent(t.trim())}catch{return}})}).reduce((t,[n,e])=>(n&&e&&(t[n]=e),t),{})}const yt=/^o(\d+)\./;function bt(t,n=!1){const{host:e,path:r,pass:o,port:i,projectId:s,protocol:c,publicKey:u}=t;return`${c}://${u}${n&&o?`:${o}`:""}@${e}${i?`:${i}`:""}/${r?`${r}/`:r}${s}`}function vt(t){const n=t.getOptions(),{host:e}=t.getDsn()||{};let r;return n.orgId?r=String(n.orgId):e&&(r=function(t){const n=t.match(yt);return n?.[1]}(e)),r}function _t(t){const{spanId:n,traceId:e,isRemote:r}=t.spanContext(),o=r?n:Et(t).parent_span_id,i=dt(t).scope;return{parent_span_id:o,span_id:r?i?.getPropagationContext().propagationSpanId||V():n,trace_id:e}}function St(t){return t&&t.length>0?t.map(({context:{spanId:t,traceId:n,traceFlags:e,...r},attributes:o})=>({span_id:t,trace_id:n,sampled:1===e,attributes:o,...r})):void 0}function wt(t){return"number"==typeof t?$t(t):Array.isArray(t)?t[0]+t[1]/1e9:t instanceof Date?$t(t.getTime()):Y()}function $t(t){return t>9999999999?t/1e3:t}function Et(t){if(function(t){return"function"==typeof t.getSpanJSON}(t))return t.getSpanJSON();const{spanId:n,traceId:e}=t.spanContext();if(function(t){const n=t;return!!(n.attributes&&n.startTime&&n.name&&n.endTime&&n.status)}(t)){const{attributes:r,startTime:o,name:i,endTime:s,status:c,links:u}=t;return{span_id:n,trace_id:e,data:r,description:i,parent_span_id:xt(t),start_timestamp:wt(o),timestamp:wt(s)||void 0,status:Nt(c),op:r["sentry.op"],origin:r["sentry.origin"],links:St(u)}}return{span_id:n,trace_id:e,start_timestamp:0,data:{}}}function xt(t){return"parentSpanId"in t?t.parentSpanId:"parentSpanContext"in t?t.parentSpanContext?.spanId:void 0}function Nt(t){if(t&&0!==t.code)return 1===t.code?"ok":t.message||"internal_error"}const Ct=function(t){return t._sentryRootSpan||t};function jt(t){if("boolean"==typeof __SENTRY_TRACING__&&!__SENTRY_TRACING__)return!1;const n=t||pt()?.getOptions();return!(!n||null==n.tracesSampleRate&&!n.tracesSampler)}const Rt=Symbol.for("sentry.nonRecordingSpan");function At(t,n){const e=n.getOptions(),{publicKey:r}=n.getDsn()||{},o={environment:e.environment||"production",release:e.release,public_key:r,trace_id:t,org_id:vt(n)};return n.emit("createDsc",o),o}function It(t,n){const e=n.getPropagationContext();return e.dsc||At(e.traceId,t)}function Ot(t){const n=pt();if(!n)return{};const e=Ct(t),r=Et(e),o=r.data,i=e.spanContext().traceState,s=i?.get("sentry.sample_rate")??o["sentry.sample_rate"]??o["sentry.previous_trace_sample_rate"];function c(t){return"number"!=typeof s&&"string"!=typeof s||(t.sample_rate=`${s}`),t}const u=e._frozenDsc;if(u)return c(u);if(function(t){return!!t&&!0===t[Rt]}(e)&&!jt(n.getOptions())){const t=dt(e).scope;if(t)return c({...It(n,t)})}const a=i?.get("sentry.dsc"),f=a&>(a);if(f)return c(f);const h=At(t.spanContext().traceId,n),p=o["sentry.source"]??o["sentry.span.source"],d=r.description;return"url"!==p&&d&&(h.transaction=d),jt()&&(h.sampled=String(function(t){const{traceFlags:n}=t.spanContext();return 1===n}(e)),h.sample_rand=i?.get("sentry.sample_rand")??dt(e).scope?.getPropagationContext().sampleRand.toString()),c(h),n.emit("createDsc",h,e),h}function Tt(t,n=[]){return[t,n]}function kt(t,n){const e=t[1];for(const t of e){if(n(t,t[0].type))return!0}return!1}function Pt(t){const n=g(p);return n.encodePolyfill?n.encodePolyfill(t):(new TextEncoder).encode(t)}function Dt(t){const[n,e]=t;let r=JSON.stringify(n);function o(t){"string"==typeof r?r="string"==typeof t?r+t:[Pt(r),t]:r.push("string"==typeof t?Pt(t):t)}for(const t of e){const[n,e]=t;if(o(`\n${JSON.stringify(n)}\n`),"string"==typeof e||e instanceof Uint8Array)o(e);else{let t;try{t=JSON.stringify(e)}catch{t=JSON.stringify(B(e))}o(t)}}return"string"==typeof r?r:function(t){const n=t.reduce((t,n)=>t+n.length,0),e=new Uint8Array(n);let r=0;for(const n of t)e.set(n,r),r+=n.length;return e}(r)}const Ut={sessions:"session",event:"error",client_report:"internal",user_report:"default",profile_chunk:"profile",replay_event:"replay",replay_recording:"replay",check_in:"monitor",raw_security:"security",log:"log_item",trace_metric:"metric"};function Bt(t){return function(t){return t in Ut}(t)?Ut[t]:t}function Lt(t){if(!t?.sdk)return;const{name:n,version:e}=t.sdk;return{name:n,version:e}}function Mt(t,n,e,r){const o=Lt(e),i=t.type&&"replay_event"!==t.type?t.type:"event";!function(t,n){if(!n)return t;const e=t.sdk||{};t.sdk={...e,name:e.name||n.name,version:e.version||n.version,integrations:[...t.sdk?.integrations||[],...n.integrations||[]],packages:[...t.sdk?.packages||[],...n.packages||[]],settings:t.sdk?.settings||n.settings?{...t.sdk?.settings,...n.settings}:void 0}}(t,e?.sdk);const s=function(t,n,e,r){const o=t.sdkProcessingMetadata?.dynamicSamplingContext;return{event_id:t.event_id,sent_at:new Date(P()).toISOString(),...n&&{sdk:n},...!!e&&r&&{dsn:bt(r)},...o&&{trace:o}}}(t,o,r,n);delete t.sdkProcessingMetadata;return Tt(s,[[{type:i},t]])}const zt="__SENTRY_SUPPRESS_TRACING__";function Ft(t){const n=ht(l());return n.suppressTracing?n.suppressTracing(t):function(...t){const n=ht(l());if(2===t.length){const[e,r]=t;return e?n.withSetScope(e,r):n.withScope(r)}return n.withScope(t[0])}(n=>{n.setSDKProcessingMetadata({[zt]:!0});const e=t();return n.setSDKProcessingMetadata({[zt]:void 0}),e})}function Gt(t,n){const{fingerprint:e,span:r,breadcrumbs:o,sdkProcessingMetadata:i}=n;!function(t,n){const{extra:e,tags:r,user:o,contexts:i,level:s,transactionName:c}=n;Object.keys(e).length&&(t.extra={...e,...t.extra});Object.keys(r).length&&(t.tags={...r,...t.tags});Object.keys(o).length&&(t.user={...o,...t.user});Object.keys(i).length&&(t.contexts={...i,...t.contexts});s&&(t.level=s);c&&"transaction"!==t.type&&(t.transaction=c)}(t,n),r&&function(t,n){t.contexts={trace:_t(n),...t.contexts},t.sdkProcessingMetadata={dynamicSamplingContext:Ot(n),...t.sdkProcessingMetadata};const e=Ct(n),r=Et(e).description;r&&!t.transaction&&"transaction"===t.type&&(t.transaction=r)}(t,r),function(t,n){t.fingerprint=t.fingerprint?Array.isArray(t.fingerprint)?t.fingerprint:[t.fingerprint]:[],n&&(t.fingerprint=t.fingerprint.concat(n));t.fingerprint.length||delete t.fingerprint}(t,e),function(t,n){const e=[...t.breadcrumbs||[],...n];t.breadcrumbs=e.length?e:void 0}(t,o),function(t,n){t.sdkProcessingMetadata={...t.sdkProcessingMetadata,...n}}(t,i)}class Jt{constructor(t){this.L=0,this.M=[],this.F(t)}then(t,n){return new Jt((e,r)=>{this.M.push([!1,n=>{if(t)try{e(t(n))}catch(t){r(t)}else e(n)},t=>{if(n)try{e(n(t))}catch(t){r(t)}else r(t)}]),this.G()})}catch(t){return this.then(t=>t,t)}finally(t){return new Jt((n,e)=>{let r,o;return this.then(n=>{o=!1,r=n,t&&t()},n=>{o=!0,r=n,t&&t()}).then(()=>{o?e(r):n(r)})})}G(){if(0===this.L)return;const t=this.M.slice();this.M=[],t.forEach(t=>{t[0]||(1===this.L&&t[1](this.J),2===this.L&&t[2](this.J),t[0]=!0)})}F(t){const n=(t,n)=>{0===this.L&&(j(n)?n.then(e,r):(this.L=t,this.J=n,this.G()))},e=t=>{n(1,t)},r=t=>{n(2,t)};try{t(e,r)}catch(t){r(t)}}}const Wt=Symbol.for("SentryBufferFullError");function Yt(t=100){const n=new Set;function e(t){n.delete(t)}return{get $(){return Array.from(n)},add:function(r){if(!(n.size<t))return o=Wt,new Jt((t,n)=>{n(o)});var o;const i=r();return n.add(i),i.then(()=>e(i),()=>e(i)),i},drain:function(t){if(!n.size)return e=!0,new Jt(t=>{t(e)});var e;const r=Promise.allSettled(Array.from(n)).then(()=>!0);if(!t)return r;const o=[r,new Promise(n=>{return"object"==typeof(e=setTimeout(()=>n(!1),t))&&"function"==typeof e.unref&&e.unref(),e;var e})];return Promise.race(o)}}}function Ht(t,{statusCode:n,headers:e},r=P()){const o={...t},i=e?.["x-sentry-rate-limits"],s=e?.["retry-after"];if(i)for(const t of i.trim().split(",")){const[n,e,,,i]=t.split(":",5),s=parseInt(n,10),c=1e3*(isNaN(s)?60:s);if(e)for(const t of e.split(";"))"metric_bucket"===t&&i&&!i.split(";").includes("custom")||(o[t]=r+c);else o.all=r+c}else s?o.all=r+function(t,n=P()){const e=parseInt(`${t}`,10);if(!isNaN(e))return 1e3*e;const r=Date.parse(`${t}`);return isNaN(r)?6e4:r-n}(s,r):429===n&&(o.all=r+6e4);return o}function Kt(t,n,e=Yt(t.bufferSize||64)){let r={};return{send:function(t){const o=[];if(kt(t,(t,n)=>{const e=Bt(n);(function(t,n,e=P()){return function(t,n){return t[n]||t.all||0}(t,n)>e})(r,e)||o.push(t)}),0===o.length)return Promise.resolve({});const i=Tt(t[0],o),s=t=>{!function(t,n){return kt(t,(t,e)=>n.includes(e))}(i,["client_report"])?kt(i,(t,n)=>{}):h&&w.warn(`Dropping client report. Will not send outcomes (reason: ${t}).`)};return e.add(()=>n({body:Dt(i)}).then(t=>413===t.statusCode?(h&&w.error("Sentry responded with status code 413. Envelope was discarded due to exceeding size limits."),s("send_error"),t):(h&&void 0!==t.statusCode&&(t.statusCode<200||t.statusCode>=300)&&w.warn(`Sentry responded with status code ${t.statusCode} to sent event.`),r=Ht(r,t),t),t=>{throw s("network_error"),h&&w.error("Encountered error running transport request:",t),t})).then(t=>t,t=>{if(t===Wt)return h&&w.error("Skipped sending event because buffer is full."),s("queue_overflow"),Promise.resolve({});throw t})},flush:t=>e.drain(t)}}const Zt=/^(\S+:\\|\/?)([\s\S]*?)((?:\.{1,2}|[^/\\]+?|)(\.[^./\\]*|))(?:[/\\]*)$/;function qt(t){const n=function(t){const n=t.length>1024?`<truncated>${t.slice(-1024)}`:t,e=Zt.exec(n);return e?e.slice(1):[]}(t),e=n[0]||"";let r=n[1];return e||r?(r&&(r=r.slice(0,r.length-1)),e+r):"."}function Vt(t,n=!1){return!(n||t&&!t.startsWith("/")&&!t.match(/^[A-Z]:/)&&!t.startsWith(".")&&!t.match(/^[a-zA-Z]([a-zA-Z0-9.\-+])*:\/\//))&&void 0!==t&&!t.includes("node_modules/")}var Qt;const Xt=Symbol("AgentBaseInternalState");class tn extends(Qt=i.Agent,Qt){constructor(t){super(t),this[Xt]={}}isSecureEndpoint(t){if(t){if("boolean"==typeof t.secureEndpoint)return t.secureEndpoint;if("string"==typeof t.protocol)return"https:"===t.protocol}const{stack:n}=new Error;return"string"==typeof n&&n.split("\n").some(t=>-1!==t.indexOf("(https.js:")||-1!==t.indexOf("node:https:"))}createSocket(t,n,e){const r={...n,secureEndpoint:this.isSecureEndpoint(n)};Promise.resolve().then(()=>this.connect(t,r)).then(o=>{if(o instanceof i.Agent)return o.addRequest(t,r);this[Xt].currentSocket=o,super.createSocket(t,n,e)},e)}createConnection(){const t=this[Xt].currentSocket;if(this[Xt].currentSocket=void 0,!t)throw new Error("No socket was returned in the `connect()` function");return t}get defaultPort(){return this[Xt].defaultPort??("https:"===this.protocol?443:80)}set defaultPort(t){this[Xt]&&(this[Xt].defaultPort=t)}get protocol(){return this[Xt].protocol??(this.isSecureEndpoint()?"https:":"http:")}set protocol(t){this[Xt]&&(this[Xt].protocol=t)}}function nn(...t){w.log("[https-proxy-agent:parse-proxy-response]",...t)}function en(t){return new Promise((n,e)=>{let r=0;const o=[];function i(){const c=t.read();c?function(c){o.push(c),r+=c.length;const u=Buffer.concat(o,r),a=u.indexOf("\r\n\r\n");if(-1===a)return nn("have not received end of HTTP headers yet..."),void i();const f=u.subarray(0,a).toString("ascii").split("\r\n"),h=f.shift();if(!h)return t.destroy(),e(new Error("No header received from proxy CONNECT response"));const p=h.split(" "),d=+(p[1]||0),l=p.slice(2).join(" "),g={};for(const n of f){if(!n)continue;const r=n.indexOf(":");if(-1===r)return t.destroy(),e(new Error(`Invalid header from proxy CONNECT response: "${n}"`));const o=n.slice(0,r).toLowerCase(),i=n.slice(r+1).trimStart(),s=g[o];"string"==typeof s?g[o]=[s,i]:Array.isArray(s)?s.push(i):g[o]=i}nn("got proxy server response: %o %o",h,g),s(),n({connect:{statusCode:d,statusText:l,headers:g},buffered:u})}(c):t.once("readable",i)}function s(){t.removeListener("end",c),t.removeListener("error",u),t.removeListener("readable",i)}function c(){s(),nn("onend"),e(new Error("Proxy connection ended before receiving CONNECT response"))}function u(t){s(),nn("onerror %o",t),e(t)}t.on("error",u),t.on("end",c),i()})}function rn(...t){w.log("[https-proxy-agent]",...t)}class on extends tn{constructor(t,n){super(n),this.options={},this.proxy="string"==typeof t?new URL(t):t,this.proxyHeaders=n?.headers??{},rn("Creating new HttpsProxyAgent instance: %o",this.proxy.href);const e=(this.proxy.hostname||this.proxy.host).replace(/^\[|\]$/g,""),r=this.proxy.port?parseInt(this.proxy.port,10):"https:"===this.proxy.protocol?443:80;this.connectOpts={ALPNProtocols:["http/1.1"],...n?cn(n,"headers"):null,host:e,port:r}}async connect(t,n){const{proxy:e}=this;if(!n.host)throw new TypeError('No "host" provided');let r;if("https:"===e.protocol){rn("Creating `tls.Socket`: %o",this.connectOpts);const t=this.connectOpts.servername||this.connectOpts.host;r=f.connect({...this.connectOpts,servername:t&&a.isIP(t)?void 0:t})}else rn("Creating `net.Socket`: %o",this.connectOpts),r=a.connect(this.connectOpts);const o="function"==typeof this.proxyHeaders?this.proxyHeaders():{...this.proxyHeaders},i=a.isIPv6(n.host)?`[${n.host}]`:n.host;let s=`CONNECT ${i}:${n.port} HTTP/1.1\r\n`;if(e.username||e.password){const t=`${decodeURIComponent(e.username)}:${decodeURIComponent(e.password)}`;o["Proxy-Authorization"]=`Basic ${Buffer.from(t).toString("base64")}`}o.Host=`${i}:${n.port}`,o["Proxy-Connection"]||(o["Proxy-Connection"]=this.keepAlive?"Keep-Alive":"close");for(const t of Object.keys(o))s+=`${t}: ${o[t]}\r\n`;const c=en(r);r.write(`${s}\r\n`);const{connect:u,buffered:h}=await c;if(t.emit("proxyConnect",u),this.emit("proxyConnect",u,t),200===u.statusCode){if(t.once("socket",sn),n.secureEndpoint){rn("Upgrading socket connection to TLS");const t=n.servername||n.host;return f.connect({...cn(n,"host","path","port"),socket:r,servername:a.isIP(t)?void 0:t})}return r}r.destroy();const p=new a.Socket({writable:!1});return p.readable=!0,t.once("socket",t=>{rn("Replaying proxy buffer for failed request"),t.push(h),t.push(null)}),p}}function sn(t){t.resume()}function cn(t,...n){const e={};let r;for(r in t)n.includes(r)||(e[r]=t[r]);return e}on.protocols=["http","https"];function un(t){return t.replace(/^[A-Z]:/,"").replace(/\\/g,"/")}const an=n;let fn,hn=0,pn={};function dn(t){an.debug&&console.log(`[ANR Worker] ${t}`)}var ln,gn,mn;const yn=function(t){let n;try{n=new URL(t.url)}catch(n){return b(()=>{console.warn("[@sentry/node]: Invalid dsn or tunnel option, will not send any events. The tunnel option must be a full URL when used.")}),Kt(t,()=>Promise.resolve({}))}const e="https:"===n.protocol,r=function(t,n){const{no_proxy:e}=process.env,r=e?.split(",").some(n=>t.host.endsWith(n)||t.hostname.endsWith(n));return r?void 0:n}(n,t.proxy||(e?process.env.https_proxy:void 0)||process.env.http_proxy),o=e?s:i,a=void 0!==t.keepAlive&&t.keepAlive,f=r?new on(r):new o.Agent({keepAlive:a,maxSockets:30,timeout:2e3}),h=function(t,n,e){const{hostname:r,pathname:o,port:i,protocol:s,search:a}=new URL(t.url);return function(f){return new Promise((h,p)=>{Ft(()=>{let d=function(t){return new c({read(){this.push(t),this.push(null)}})}(f.body);const l={...t.headers};f.body.length>32768&&(l["content-encoding"]="gzip",d=d.pipe(u()));const g=r.startsWith("["),m=n.request({method:"POST",agent:e,headers:l,hostname:g?r.slice(1,-1):r,path:`${o}${a}`,port:i,protocol:s,ca:t.caCerts},t=>{t.on("data",()=>{}),t.on("end",()=>{}),t.setEncoding("utf8");const n=t.headers["retry-after"]??null,e=t.headers["x-sentry-rate-limits"]??null;h({statusCode:t.statusCode,headers:{"retry-after":n,"x-sentry-rate-limits":Array.isArray(e)?e[0]||null:e}})});m.on("error",p),d.pipe(m)})})}}(t,t.httpModule??o,f);return Kt(t,h)}({url:(ln=an.dsn,gn=an.tunnel,mn=an.sdkMetadata.sdk,gn||`${function(t){return`${function(t){const n=t.protocol?`${t.protocol}:`:"",e=t.port?`:${t.port}`:"";return`${n}//${t.host}${e}${t.path?`/${t.path}`:""}/api/`}(t)}${t.projectId}/envelope/`}(ln)}?${function(t,n){const e={sentry_version:"7"};return t.publicKey&&(e.sentry_key=t.publicKey),n&&(e.sentry_client=`${n.name}/${n.version}`),new URLSearchParams(e).toString()}(ln,mn)}`)});async function bn(){if(fn){dn("Sending abnormal session"),K(fn,{status:"abnormal",abnormal_mechanism:"anr_foreground",release:an.release,environment:an.environment});const t=function(t,n,e,r){const o=Lt(e);return Tt({sent_at:new Date(P()).toISOString(),...o&&{sdk:o},...!!r&&n&&{dsn:bt(n)}},["aggregates"in t?[{type:"sessions"},t]:[{type:"session"},t.toJSON()]])}(fn,an.dsn,an.sdkMetadata,an.tunnel);dn(JSON.stringify(t)),await yn.send(t);try{e?.postMessage("session-ended")}catch{}}}function vn(t){if(!t)return;const n=function(t){if(!t.length)return[];const n=Array.from(t);return/sentryWrapped/.test(E(n).function||"")&&n.pop(),n.reverse(),$.test(E(n).function||"")&&(n.pop(),$.test(E(n).function||"")&&n.pop()),n.slice(0,50).map(t=>({...t,filename:t.filename||E(n).filename,function:t.function||"?"}))}(t);if(an.appRootPath)for(const t of n)t.filename&&(t.filename=M(t.filename,an.appRootPath));return n}async function _n(t,n){if(hn>=an.maxAnrEvents)return;hn+=1,await bn(),dn("Sending event");const e={event_id:G(),contexts:an.contexts,release:an.release,environment:an.environment,dist:an.dist,platform:"node",level:"error",exception:{values:[{type:"ApplicationNotResponding",value:`Application Not Responding for at least ${an.anrThreshold} ms`,stacktrace:{frames:vn(t)},mechanism:{type:"ANR"}}]},tags:an.staticTags};n&&function(t,n){if(Gt(t,n),!t.contexts?.trace){const{traceId:e,parentSpanId:r,propagationSpanId:o}=n.propagationContext;t.contexts={trace:{trace_id:e,span_id:o||V(),parent_span_id:r},...t.contexts}}}(e,n),function(t){if(0===Object.keys(pn).length)return;const n=an.appRootPath?{}:pn;if(an.appRootPath)for(const[t,e]of Object.entries(pn))n[M(t,an.appRootPath)]=e;const e=new Map;for(const r of t.exception?.values||[])for(const t of r.stacktrace?.frames||[]){const r=t.abs_path||t.filename;r&&n[r]&&e.set(r,n[r])}if(e.size>0){const n=[];for(const[t,r]of e.entries())n.push({type:"sourcemap",code_file:t,debug_id:r});t.debug_meta={images:n}}}(e);const r=Mt(e,an.dsn,an.sdkMetadata,an.tunnel);dn(JSON.stringify(r)),await yn.send(r),await yn.flush(2e3),hn>=an.maxAnrEvents&&setTimeout(()=>{process.exit(0)},5e3)}let Sn;if(dn("Started"),an.captureStackTrace){dn("Connecting to debugger");const n=new t;n.connectToMainThread(),dn("Connected to debugger");const e=new Map;n.on("Debugger.scriptParsed",t=>{e.set(t.params.scriptId,t.params.url)}),n.on("Debugger.paused",t=>{if("other"===t.params.reason)try{dn("Debugger paused");const i=[...t.params.callFrames],s=an.appRootPath?function(t=(process.argv[1]?qt(process.argv[1]):process.cwd()),n="\\"===o){const e=n?un(t):t;return t=>{if(!t)return;const o=n?un(t):t;let{dir:i,base:s,ext:c}=r.parse(o);".js"!==c&&".mjs"!==c&&".cjs"!==c||(s=s.slice(0,-1*c.length));const u=decodeURIComponent(s);i||(i=".");const a=i.lastIndexOf("/node_modules");if(a>-1)return`${i.slice(a+14).replace(/\//g,".")}:${u}`;if(i.startsWith(e)){const t=i.slice(e.length+1).replace(/\//g,".");return t?`${t}:${u}`:u}return u}}(an.appRootPath):()=>{},c=i.map(t=>function(t,n,e){const r=n?n.replace(/^file:\/\//,""):void 0,o=t.location.columnNumber?t.location.columnNumber+1:void 0,i=t.location.lineNumber?t.location.lineNumber+1:void 0;return{filename:r,module:e(r),function:t.functionName||"?",colno:o,lineno:i,in_app:r?Vt(r):void 0}}(t,e.get(t.location.scriptId),s)),u=setTimeout(()=>{_n(c).then(null,()=>{dn("Sending ANR event failed.")})},5e3);n.post("Runtime.evaluate",{expression:"global.__SENTRY_GET_SCOPES__();",silent:!0,returnByValue:!0},(t,e)=>{t&&dn(`Error executing script: '${t.message}'`),clearTimeout(u);const r=e?.result?e.result.value:void 0;n.post("Debugger.resume"),n.post("Debugger.disable"),_n(c,r).then(null,()=>{dn("Sending ANR event failed.")})})}catch(t){throw n.post("Debugger.resume"),n.post("Debugger.disable"),t}}),Sn=()=>{try{n.post("Debugger.enable",()=>{n.post("Debugger.pause")})}catch{}}}const{poll:wn}=function(t,n,e,r){const o=t();let i=!1,s=!0;return setInterval(()=>{const t=o.getTimeMs();!1===i&&t>n+e&&(i=!0,s&&r()),t<n+e&&(i=!1)},20),{poll:()=>{o.reset()},enabled:t=>{s=t}}}(function(){let t=process.hrtime();return{getTimeMs:()=>{const[n,e]=process.hrtime(t);return Math.floor(1e3*n+e/1e6)},reset:()=>{t=process.hrtime()}}},an.pollInterval,an.anrThreshold,function(){dn("Watchdog timeout"),Sn?(dn("Pausing debugger to capture stack trace"),Sn()):(dn("Capturing event without a stack trace"),_n().then(null,()=>{dn("Sending ANR event failed on watchdog timeout.")}))});e?.on("message",t=>{t.session&&(fn=H(t.session)),t.debugImages&&(pn=t.debugImages),wn()}); | ||
| /*! @sentry/node-core 10.64.0 (5736a38) | https://github.com/getsentry/sentry-javascript */ | ||
| import{Session as t}from"node:inspector";import{workerData as n,parentPort as e}from"node:worker_threads";import{posix as r,sep as o}from"node:path";import*as i from"node:http";import*as s from"node:https";import{Readable as c}from"node:stream";import{createGzip as u}from"node:zlib";import*as a from"node:net";import*as f from"node:tls";const h="undefined"==typeof __SENTRY_DEBUG__||__SENTRY_DEBUG__,p=globalThis,d="10.64.0";function l(){return g(p),p}function g(t){const n=t.__SENTRY__=t.__SENTRY__||{};return n.version=n.version||d,n[d]=n[d]||{}}function m(t,n,e=p){const r=e.__SENTRY__=e.__SENTRY__||{},o=r[d]=r[d]||{};return o[t]||(o[t]=n())}const y={};function b(t){if(!("console"in p))return t();const n=p.console,e={},r=Object.keys(y);r.forEach(t=>{const r=y[t];e[t]=n[t],n[t]=r});try{return t()}finally{r.forEach(t=>{n[t]=e[t]})}}function v(){return S().enabled}function _(t,...n){h&&v()&&b(()=>{p.console[t](`Sentry Logger [${t}]:`,...n)})}function S(){return h?m("loggerSettings",()=>({enabled:!1})):{enabled:!1}}const w={enable:function(){S().enabled=!0},disable:function(){S().enabled=!1},isEnabled:v,log:function(...t){_("log",...t)},warn:function(...t){_("warn",...t)},error:function(...t){_("error",...t)}},$=/captureMessage|captureException/;function E(t){return t[t.length-1]||{}}const x="<anonymous>";const N=Object.prototype.toString;function C(t,n){return N.call(t)===`[object ${n}]`}function j(t){return Boolean(t?.then&&"function"==typeof t.then)}function R(t,n){try{return t instanceof n}catch{return!1}}function A(t){if(function(t){switch(N.call(t)){case"[object Error]":case"[object Exception]":case"[object DOMException]":case"[object WebAssembly.Exception]":return!0;default:return R(t,Error)}}(t))return{message:t.message,name:t.name,stack:t.stack,...I(t)};if(n=t,"undefined"!=typeof Event&&R(n,Event)){const{type:n,target:e,currentTarget:r,detail:o}=t;return{type:n,target:e,currentTarget:r,...o?{detail:o}:{},...I(t)}}var n;return t}function I(t){return"object"==typeof t&&null!==t?Object.fromEntries(Object.entries(t)):{}}let O;function T(t){if(void 0!==O)return O?O(t):t();const n=Symbol.for("__SENTRY_SAFE_RANDOM_ID_WRAPPER__"),e=p;return n in e&&"function"==typeof e[n]?(O=e[n],O(t)):(O=null,t())}function k(){return T(()=>Math.random())}function P(){return T(()=>Date.now())}const D=Symbol.for("sentry.skipNormalization"),U=Symbol.for("sentry.overrideNormalizationDepth");function B(t,n=100,e=1/0){try{return L("",t,n,e)}catch(t){return{ERROR:`**non-serializable** (${t})`}}}function L(t,n,e=1/0,r=1/0,o=function(){const t=new WeakSet;function n(n){return!!t.has(n)||(t.add(n),!1)}function e(n){t.delete(n)}return[n,e]}()){const[i,s]=o;if(null==n||["boolean","string"].includes(typeof n)||"number"==typeof n&&Number.isFinite(n))return n;const c=function(t,n){try{if("undefined"!=typeof global&&n===global)return"[Global]";if("number"==typeof n&&!Number.isFinite(n))return`[${n}]`;if("function"==typeof n)return`[Function: ${function(t){try{return t&&"function"==typeof t&&t.name||x}catch{return x}}(n)}]`;if("symbol"==typeof n)return`[${String(n)}]`;if("bigint"==typeof n)return`[BigInt: ${String(n)}]`;const t=function(t){const n=Object.getPrototypeOf(t);return n?.constructor?n.constructor.name:"null prototype"}(n);return`[object ${t}]`}catch(t){return`**non-serializable** (${t})`}}(0,n);if(!c.startsWith("[object "))return c;if(function(t){return Boolean(t[D])}(n))return n;const u=function(t){const n=t[U];return"number"==typeof n?n:void 0}(n),a=void 0!==u?u:e;if(0===a)return c.replace("object ","");if(i(n))return"[Circular ~]";const f=n;if(f&&"function"==typeof f.toJSON)try{return L("",f.toJSON(),a-1,r,o)}catch{}const h=Array.isArray(n)?[]:{};let p=0;const d=A(n);for(const t in d){if(!Object.prototype.hasOwnProperty.call(d,t))continue;if(p>=r){h[t]="[MaxProperties ~]";break}const n=d[t];h[t]=L(t,n,a-1,r,o),p++}return s(n),h}function M(t,n){const e=n.replace(/\\/g,"/").replace(/[|\\{}()[\]^$+*?.]/g,"\\$&");let r=t;try{r=decodeURI(t)}catch{}return r.replace(/\\/g,"/").replace(/webpack:\/?/g,"").replace(new RegExp(`(file://)?/*${e}/*`,"ig"),"app:///")}function z(t,n=0){return"string"!=typeof t||0===n||t.length<=n?t:`${t.slice(0,n)}...`}let F;function G(t=function(){const t=p;return t.crypto||t.msCrypto}()){try{if(t?.randomUUID)return T(()=>t.randomUUID()).replace(/-/g,"")}catch{}return F||(F="10000000100040008000100000000000"),F.replace(/[018]/g,t=>(t^(16*k()&15)>>t/4).toString(16))}function J(){return P()/1e3}let W;function Y(){return(W??(W=function(){const{performance:t}=p;if(!t?.now||!t.timeOrigin)return J;const n=t.timeOrigin;return()=>(n+T(()=>t.now()))/1e3}()))()}function H(t){const n=Y(),e={sid:G(),init:!0,timestamp:n,started:n,duration:0,status:"ok",errors:0,ignoreDuration:!1,toJSON:()=>function(t){return{sid:`${t.sid}`,init:t.init,started:new Date(1e3*t.started).toISOString(),timestamp:new Date(1e3*t.timestamp).toISOString(),status:t.status,errors:t.errors,did:"number"==typeof t.did||"string"==typeof t.did?`${t.did}`:void 0,duration:t.duration,abnormal_mechanism:t.abnormal_mechanism,attrs:{release:t.release,environment:t.environment,ip_address:t.ipAddress,user_agent:t.userAgent}}}(e)};return t&&K(e,t),e}function K(t,n={}){if(n.user&&(!t.ipAddress&&n.user.ip_address&&(t.ipAddress=n.user.ip_address),t.did||n.did||(t.did=n.user.id||n.user.email||n.user.username)),t.timestamp=n.timestamp||Y(),n.abnormal_mechanism&&(t.abnormal_mechanism=n.abnormal_mechanism),n.ignoreDuration&&(t.ignoreDuration=n.ignoreDuration),n.sid&&(t.sid=32===n.sid.length?n.sid:G()),void 0!==n.init&&(t.init=n.init),!t.did&&n.did&&(t.did=`${n.did}`),"number"==typeof n.started&&(t.started=n.started),t.ignoreDuration)t.duration=void 0;else if("number"==typeof n.duration)t.duration=n.duration;else{const n=t.timestamp-t.started;t.duration=n>=0?n:0}n.release&&(t.release=n.release),n.environment&&(t.environment=n.environment),!t.ipAddress&&n.ipAddress&&(t.ipAddress=n.ipAddress),!t.userAgent&&n.userAgent&&(t.userAgent=n.userAgent),"number"==typeof n.errors&&(t.errors=n.errors),n.status&&(t.status=n.status)}function Z(t,n,e=2){if(!n||"object"!=typeof n||e<=0)return n;if(t&&0===Object.keys(n).length)return t;const r={...t};for(const t in n)Object.prototype.hasOwnProperty.call(n,t)&&(r[t]=Z(r[t],n[t],e-1));return r}function q(){return G()}function V(){return G().substring(16)}function Q(t){if(t){if("object"==typeof t&&"deref"in t&&"function"==typeof t.deref)try{return t.deref()}catch{return}return t}}const X="_sentrySpan";function tt(t,n){n?function(t,n,e){try{Object.defineProperty(t,n,{value:e,writable:!0,configurable:!0})}catch{h&&w.log(`Failed to add non-enumerable property "${String(n)}" to object`,t)}}(t,X,function(t){try{const n=p.WeakRef;if("function"==typeof n)return new n(t)}catch{}return t}(n)):delete t[X]}function nt(t){return Q(t[X])}class et{constructor(){this.t=!1,this.o=[],this.i=[],this.u=[],this.h=[],this.p={},this.l={},this.m={},this.v={},this._={},this.S={},this.N={traceId:q(),sampleRand:k()}}clone(){const t=new et;return t.u=[...this.u],t.l={...this.l},t.m={...this.m},t.v={...this.v},t._={...this._},this._.flags&&(t._.flags={values:[...this._.flags.values]}),t.p=this.p,t.C=this.C,t.j=this.j,t.R=this.R,t.A=this.A,t.i=[...this.i],t.h=[...this.h],t.S={...this.S},t.N={...this.N},t.I=this.I,t.O=this.O,t.T=this.T,tt(t,nt(this)),t}setClient(t){this.I=t}setLastEventId(t){this.O=t}getClient(){return this.I}lastEventId(){return this.O}addScopeListener(t){this.o.push(t)}addEventProcessor(t){return this.i.push(t),this}setUser(t){return this.p=t||{email:void 0,id:void 0,ip_address:void 0,username:void 0},this.j&&K(this.j,{user:t}),this.k(),this}getUser(){return this.p}setConversationId(t){return this.T=t||void 0,this.k(),this}setTags(t){return this.l={...this.l,...t},this.k(),this}setTag(t,n){return this.setTags({[t]:n})}setAttributes(t){return this.m={...this.m,...t},this.k(),this}setAttribute(t,n){return this.setAttributes({[t]:n})}removeAttribute(t){return t in this.m&&(delete this.m[t],this.k()),this}setExtras(t){return this.v={...this.v,...t},this.k(),this}setExtra(t,n){return this.v={...this.v,[t]:n},this.k(),this}setFingerprint(t){return this.A=t,this.k(),this}setLevel(t){return this.C=t,this.k(),this}setTransactionName(t){return this.R=t,this.k(),this}setContext(t,n){return null===n?delete this._[t]:this._[t]=n,this.k(),this}setSession(t){return t?this.j=t:delete this.j,this.k(),this}getSession(){return this.j}update(t){if(!t)return this;const n="function"==typeof t?t(this):t,e=n instanceof et?n.getScopeData():C(n,"Object")?t:void 0;const{tags:r,attributes:o,extra:i,user:s,contexts:c,level:u,fingerprint:a=[],propagationContext:f,conversationId:h}=e||{};return this.l={...this.l,...r},this.m={...this.m,...o},this.v={...this.v,...i},this._={...this._,...c},s&&Object.keys(s).length&&(this.p=s),u&&(this.C=u),a.length&&(this.A=a),f&&(this.N=f),h&&(this.T=h),this}clear(){return this.u=[],this.l={},this.m={},this.v={},this.p={},this._={},this.C=void 0,this.R=void 0,this.A=void 0,this.j=void 0,this.T=void 0,tt(this,void 0),this.h=[],this.setPropagationContext({traceId:q(),sampleRand:k()}),this.k(),this}addBreadcrumb(t,n){const e="number"==typeof n?n:100;if(e<=0)return this;const r={timestamp:J(),...t,message:t.message?z(t.message,2048):t.message};return this.u.push(r),this.u.length>e&&(this.u=this.u.slice(-e),this.I?.recordDroppedEvent("buffer_overflow","log_item")),this.k(),this}getLastBreadcrumb(){return this.u[this.u.length-1]}clearBreadcrumbs(){return this.u=[],this.k(),this}addAttachment(t){return this.h.push(t),this}clearAttachments(){return this.h=[],this}getScopeData(){return{breadcrumbs:this.u,attachments:this.h,contexts:this._,tags:this.l,attributes:this.m,extra:this.v,user:this.p,level:this.C,fingerprint:this.A||[],eventProcessors:this.i,propagationContext:this.N,sdkProcessingMetadata:this.S,transactionName:this.R,span:nt(this),conversationId:this.T}}setSDKProcessingMetadata(t){return this.S=Z(this.S,t,2),this}setPropagationContext(t){return this.N=t,this}getPropagationContext(){return this.N}captureException(t,n){const e=n?.event_id||G();if(!this.I)return h&&w.warn("No client configured on scope - will not capture exception!"),e;const r=new Error("Sentry syntheticException");return this.I.captureException(t,{originalException:t,syntheticException:r,...n,event_id:e},this),e}captureMessage(t,n,e){const r=e?.event_id||G();if(!this.I)return h&&w.warn("No client configured on scope - will not capture message!"),r;const o=e?.syntheticException??new Error(t);return this.I.captureMessage(t,n,{originalException:t,syntheticException:o,...e,event_id:r},this),r}captureEvent(t,n){const e=t.event_id||n?.event_id||G();return this.I?(this.I.captureEvent(t,{...n,event_id:e},this),e):(h&&w.warn("No client configured on scope - will not capture event!"),e)}k(){this.t||(this.t=!0,this.o.forEach(t=>{t(this)}),this.t=!1)}}const rt=t=>t instanceof Promise&&!t[ot],ot=Symbol("chained PromiseLike"),it=(t,n)=>{if(!n)return t;let e=!1;for(const r in t){if(r in n)continue;e=!0;const o=t[r];"function"==typeof o?Object.defineProperty(n,r,{value:(...n)=>o.apply(t,n),enumerable:!0,configurable:!0,writable:!0}):n[r]=o}return e&&Object.assign(n,{[ot]:!0}),n};class st{constructor(t,n){let e,r;e=t||new et,r=n||new et,this.P=[{scope:e}],this.D=r}withScope(t){const n=this.U();let e;try{e=t(n)}catch(t){throw this.B(),t}return j(e)?((t,n,e)=>{const r=t.then(t=>(n(t),t),t=>{throw e(t),t});return rt(r)&&rt(t)?r:it(t,r)})(e,()=>this.B(),()=>this.B()):(this.B(),e)}getClient(){return this.getStackTop().client}getScope(){return this.getStackTop().scope}getIsolationScope(){return this.D}getStackTop(){return this.P[this.P.length-1]}U(){const t=this.getScope().clone();return this.P.push({client:this.getClient(),scope:t}),t}B(){return!(this.P.length<=1)&&!!this.P.pop()}}function ct(){const t=g(l());return t.stack=t.stack||new st(m("defaultCurrentScope",()=>new et),m("defaultIsolationScope",()=>new et))}function ut(t){return ct().withScope(t)}function at(t,n){const e=ct();return e.withScope(()=>(e.getStackTop().scope=t,n(t)))}function ft(t){return ct().withScope(()=>t(ct().getIsolationScope()))}function ht(t){const n=g(t);return n.acs?n.acs:{withIsolationScope:ft,withScope:ut,withSetScope:at,withSetIsolationScope:(t,n)=>ft(n),getCurrentScope:()=>ct().getScope(),getIsolationScope:()=>ct().getIsolationScope()}}function pt(){return ht(l()).getCurrentScope().getClient()}function dt(t){const n=t;return{scope:n._sentryScope,isolationScope:Q(n._sentryIsolationScope)}}const lt="sentry-";function gt(t){const n=function(t){if(!t||(n=t,!C(n,"String")&&!Array.isArray(t)))return;var n;if(Array.isArray(t))return t.reduce((t,n)=>{const e=mt(n);return Object.entries(e).forEach(([n,e])=>{t[n]=e}),t},{});return mt(t)}(t);if(!n)return;const e=Object.entries(n).reduce((t,[n,e])=>{if(n.startsWith(lt)){t[n.slice(7)]=e}return t},{});return Object.keys(e).length>0?e:void 0}function mt(t){return t.split(",").map(t=>{const n=t.indexOf("=");if(-1===n)return[];return[t.slice(0,n),t.slice(n+1)].map(t=>{try{return decodeURIComponent(t.trim())}catch{return}})}).reduce((t,[n,e])=>(n&&e&&(t[n]=e),t),{})}const yt=/^o(\d+)\./;function bt(t,n=!1){const{host:e,path:r,pass:o,port:i,projectId:s,protocol:c,publicKey:u}=t;return`${c}://${u}${n&&o?`:${o}`:""}@${e}${i?`:${i}`:""}/${r?`${r}/`:r}${s}`}function vt(t){const n=t.getOptions(),{host:e}=t.getDsn()||{};let r;return n.orgId?r=String(n.orgId):e&&(r=function(t){const n=t.match(yt);return n?.[1]}(e)),r}function _t(t){const{spanId:n,traceId:e,isRemote:r}=t.spanContext(),o=r?n:Et(t).parent_span_id,i=dt(t).scope;return{parent_span_id:o,span_id:r?i?.getPropagationContext().propagationSpanId||V():n,trace_id:e}}function St(t){return t&&t.length>0?t.map(({context:{spanId:t,traceId:n,traceFlags:e,...r},attributes:o})=>({span_id:t,trace_id:n,sampled:1===e,attributes:o,...r})):void 0}function wt(t){return"number"==typeof t?$t(t):Array.isArray(t)?t[0]+t[1]/1e9:t instanceof Date?$t(t.getTime()):Y()}function $t(t){return t>9999999999?t/1e3:t}function Et(t){if(function(t){return"function"==typeof t.getSpanJSON}(t))return t.getSpanJSON();const{spanId:n,traceId:e}=t.spanContext();if(function(t){const n=t;return!!(n.attributes&&n.startTime&&n.name&&n.endTime&&n.status)}(t)){const{attributes:r,startTime:o,name:i,endTime:s,status:c,links:u}=t;return{span_id:n,trace_id:e,data:r,description:i,parent_span_id:xt(t),start_timestamp:wt(o),timestamp:wt(s)||void 0,status:Nt(c),op:r["sentry.op"],origin:r["sentry.origin"],links:St(u)}}return{span_id:n,trace_id:e,start_timestamp:0,data:{}}}function xt(t){return"parentSpanId"in t?t.parentSpanId:"parentSpanContext"in t?t.parentSpanContext?.spanId:void 0}function Nt(t){if(t&&0!==t.code)return 1===t.code?"ok":t.message||"internal_error"}const Ct=function(t){return t._sentryRootSpan||t};function jt(t){if("boolean"==typeof __SENTRY_TRACING__&&!__SENTRY_TRACING__)return!1;const n=t||pt()?.getOptions();return!(!n||null==n.tracesSampleRate&&!n.tracesSampler)}const Rt=Symbol.for("sentry.nonRecordingSpan");function At(t,n){const e=n.getOptions(),{publicKey:r}=n.getDsn()||{},o={environment:e.environment||"production",release:e.release,public_key:r,trace_id:t,org_id:vt(n)};return n.emit("createDsc",o),o}function It(t,n){const e=n.getPropagationContext();return e.dsc||At(e.traceId,t)}function Ot(t){const n=pt();if(!n)return{};const e=Ct(t),r=Et(e),o=r.data,i=e.spanContext().traceState,s=i?.get("sentry.sample_rate")??o["sentry.sample_rate"]??o["sentry.previous_trace_sample_rate"];function c(t){return"number"!=typeof s&&"string"!=typeof s||(t.sample_rate=`${s}`),t}const u=e._frozenDsc;if(u)return c(u);if(function(t){return!!t&&!0===t[Rt]}(e)&&!jt(n.getOptions())){const t=dt(e).scope;if(t)return c({...It(n,t)})}const a=i?.get("sentry.dsc"),f=a&>(a);if(f)return c(f);const h=At(t.spanContext().traceId,n),p=o["sentry.source"]??o["sentry.span.source"],d=r.description;return"url"!==p&&d&&(h.transaction=d),jt()&&(h.sampled=String(function(t){const{traceFlags:n}=t.spanContext();return 1===n}(e)),h.sample_rand=i?.get("sentry.sample_rand")??dt(e).scope?.getPropagationContext().sampleRand.toString()),c(h),n.emit("createDsc",h,e),h}function Tt(t,n=[]){return[t,n]}function kt(t,n){const e=t[1];for(const t of e){if(n(t,t[0].type))return!0}return!1}function Pt(t){const n=g(p);return n.encodePolyfill?n.encodePolyfill(t):(new TextEncoder).encode(t)}function Dt(t){const[n,e]=t;let r=JSON.stringify(n);function o(t){"string"==typeof r?r="string"==typeof t?r+t:[Pt(r),t]:r.push("string"==typeof t?Pt(t):t)}for(const t of e){const[n,e]=t;if(o(`\n${JSON.stringify(n)}\n`),"string"==typeof e||e instanceof Uint8Array)o(e);else{let t;try{t=JSON.stringify(e)}catch{t=JSON.stringify(B(e))}o(t)}}return"string"==typeof r?r:function(t){const n=t.reduce((t,n)=>t+n.length,0),e=new Uint8Array(n);let r=0;for(const n of t)e.set(n,r),r+=n.length;return e}(r)}const Ut={sessions:"session",event:"error",client_report:"internal",user_report:"default",profile_chunk:"profile",replay_event:"replay",replay_recording:"replay",check_in:"monitor",raw_security:"security",log:"log_item",trace_metric:"metric"};function Bt(t){return function(t){return t in Ut}(t)?Ut[t]:t}function Lt(t){if(!t?.sdk)return;const{name:n,version:e}=t.sdk;return{name:n,version:e}}function Mt(t,n,e,r){const o=Lt(e),i=t.type&&"replay_event"!==t.type?t.type:"event";!function(t,n){if(!n)return t;const e=t.sdk||{};t.sdk={...e,name:e.name||n.name,version:e.version||n.version,integrations:[...t.sdk?.integrations||[],...n.integrations||[]],packages:[...t.sdk?.packages||[],...n.packages||[]],settings:t.sdk?.settings||n.settings?{...t.sdk?.settings,...n.settings}:void 0}}(t,e?.sdk);const s=function(t,n,e,r){const o=t.sdkProcessingMetadata?.dynamicSamplingContext;return{event_id:t.event_id,sent_at:new Date(P()).toISOString(),...n&&{sdk:n},...!!e&&r&&{dsn:bt(r)},...o&&{trace:o}}}(t,o,r,n);delete t.sdkProcessingMetadata;return Tt(s,[[{type:i},t]])}const zt="__SENTRY_SUPPRESS_TRACING__";function Ft(t){const n=ht(l());return n.suppressTracing?n.suppressTracing(t):function(...t){const n=ht(l());if(2===t.length){const[e,r]=t;return e?n.withSetScope(e,r):n.withScope(r)}return n.withScope(t[0])}(n=>{n.setSDKProcessingMetadata({[zt]:!0});const e=t();return n.setSDKProcessingMetadata({[zt]:void 0}),e})}function Gt(t,n){const{fingerprint:e,span:r,breadcrumbs:o,sdkProcessingMetadata:i}=n;!function(t,n){const{extra:e,tags:r,user:o,contexts:i,level:s,transactionName:c}=n;Object.keys(e).length&&(t.extra={...e,...t.extra});Object.keys(r).length&&(t.tags={...r,...t.tags});Object.keys(o).length&&(t.user={...o,...t.user});Object.keys(i).length&&(t.contexts={...i,...t.contexts});s&&(t.level=s);c&&"transaction"!==t.type&&(t.transaction=c)}(t,n),r&&function(t,n){t.contexts={trace:_t(n),...t.contexts},t.sdkProcessingMetadata={dynamicSamplingContext:Ot(n),...t.sdkProcessingMetadata};const e=Ct(n),r=Et(e).description;r&&!t.transaction&&"transaction"===t.type&&(t.transaction=r)}(t,r),function(t,n){t.fingerprint=t.fingerprint?Array.isArray(t.fingerprint)?t.fingerprint:[t.fingerprint]:[],n&&(t.fingerprint=t.fingerprint.concat(n));t.fingerprint.length||delete t.fingerprint}(t,e),function(t,n){const e=[...t.breadcrumbs||[],...n];t.breadcrumbs=e.length?e:void 0}(t,o),function(t,n){t.sdkProcessingMetadata={...t.sdkProcessingMetadata,...n}}(t,i)}class Jt{constructor(t){this.L=0,this.M=[],this.F(t)}then(t,n){return new Jt((e,r)=>{this.M.push([!1,n=>{if(t)try{e(t(n))}catch(t){r(t)}else e(n)},t=>{if(n)try{e(n(t))}catch(t){r(t)}else r(t)}]),this.G()})}catch(t){return this.then(t=>t,t)}finally(t){return new Jt((n,e)=>{let r,o;return this.then(n=>{o=!1,r=n,t&&t()},n=>{o=!0,r=n,t&&t()}).then(()=>{o?e(r):n(r)})})}G(){if(0===this.L)return;const t=this.M.slice();this.M=[],t.forEach(t=>{t[0]||(1===this.L&&t[1](this.J),2===this.L&&t[2](this.J),t[0]=!0)})}F(t){const n=(t,n)=>{0===this.L&&(j(n)?n.then(e,r):(this.L=t,this.J=n,this.G()))},e=t=>{n(1,t)},r=t=>{n(2,t)};try{t(e,r)}catch(t){r(t)}}}const Wt=Symbol.for("SentryBufferFullError");function Yt(t=100){const n=new Set;function e(t){n.delete(t)}return{get $(){return Array.from(n)},add:function(r){if(!(n.size<t))return o=Wt,new Jt((t,n)=>{n(o)});var o;const i=r();return n.add(i),i.then(()=>e(i),()=>e(i)),i},drain:function(t){if(!n.size)return e=!0,new Jt(t=>{t(e)});var e;const r=Promise.allSettled(Array.from(n)).then(()=>!0);if(!t)return r;const o=[r,new Promise(n=>{return"object"==typeof(e=setTimeout(()=>n(!1),t))&&"function"==typeof e.unref&&e.unref(),e;var e})];return Promise.race(o)}}}function Ht(t,{statusCode:n,headers:e},r=P()){const o={...t},i=e?.["x-sentry-rate-limits"],s=e?.["retry-after"];if(i)for(const t of i.trim().split(",")){const[n,e,,,i]=t.split(":",5),s=parseInt(n,10),c=1e3*(isNaN(s)?60:s);if(e)for(const t of e.split(";"))"metric_bucket"===t&&i&&!i.split(";").includes("custom")||(o[t]=r+c);else o.all=r+c}else s?o.all=r+function(t,n=P()){const e=parseInt(`${t}`,10);if(!isNaN(e))return 1e3*e;const r=Date.parse(`${t}`);return isNaN(r)?6e4:r-n}(s,r):429===n&&(o.all=r+6e4);return o}function Kt(t,n,e=Yt(t.bufferSize||64)){let r={};return{send:function(t){const o=[];if(kt(t,(t,n)=>{const e=Bt(n);(function(t,n,e=P()){return function(t,n){return t[n]||t.all||0}(t,n)>e})(r,e)||o.push(t)}),0===o.length)return Promise.resolve({});const i=Tt(t[0],o),s=t=>{!function(t,n){return kt(t,(t,e)=>n.includes(e))}(i,["client_report"])?kt(i,(t,n)=>{}):h&&w.warn(`Dropping client report. Will not send outcomes (reason: ${t}).`)};return e.add(()=>n({body:Dt(i)}).then(t=>413===t.statusCode?(h&&w.error("Sentry responded with status code 413. Envelope was discarded due to exceeding size limits."),s("send_error"),t):(h&&void 0!==t.statusCode&&(t.statusCode<200||t.statusCode>=300)&&w.warn(`Sentry responded with status code ${t.statusCode} to sent event.`),r=Ht(r,t),t),t=>{throw s("network_error"),h&&w.error("Encountered error running transport request:",t),t})).then(t=>t,t=>{if(t===Wt)return h&&w.error("Skipped sending event because buffer is full."),s("queue_overflow"),Promise.resolve({});throw t})},flush:t=>e.drain(t)}}const Zt=/^(\S+:\\|\/?)([\s\S]*?)((?:\.{1,2}|[^/\\]+?|)(\.[^./\\]*|))(?:[/\\]*)$/;function qt(t){const n=function(t){const n=t.length>1024?`<truncated>${t.slice(-1024)}`:t,e=Zt.exec(n);return e?e.slice(1):[]}(t),e=n[0]||"";let r=n[1];return e||r?(r&&(r=r.slice(0,r.length-1)),e+r):"."}function Vt(t,n=!1){return!(n||t&&!t.startsWith("/")&&!t.match(/^[A-Z]:/)&&!t.startsWith(".")&&!t.match(/^[a-zA-Z]([a-zA-Z0-9.\-+])*:\/\//))&&void 0!==t&&!t.includes("node_modules/")}var Qt;const Xt=Symbol("AgentBaseInternalState");class tn extends(Qt=i.Agent,Qt){constructor(t){super(t),this[Xt]={}}isSecureEndpoint(t){if(t){if("boolean"==typeof t.secureEndpoint)return t.secureEndpoint;if("string"==typeof t.protocol)return"https:"===t.protocol}const{stack:n}=new Error;return"string"==typeof n&&n.split("\n").some(t=>-1!==t.indexOf("(https.js:")||-1!==t.indexOf("node:https:"))}createSocket(t,n,e){const r={...n,secureEndpoint:this.isSecureEndpoint(n)};Promise.resolve().then(()=>this.connect(t,r)).then(o=>{if(o instanceof i.Agent)return o.addRequest(t,r);this[Xt].currentSocket=o,super.createSocket(t,n,e)},e)}createConnection(){const t=this[Xt].currentSocket;if(this[Xt].currentSocket=void 0,!t)throw new Error("No socket was returned in the `connect()` function");return t}get defaultPort(){return this[Xt].defaultPort??("https:"===this.protocol?443:80)}set defaultPort(t){this[Xt]&&(this[Xt].defaultPort=t)}get protocol(){return this[Xt].protocol??(this.isSecureEndpoint()?"https:":"http:")}set protocol(t){this[Xt]&&(this[Xt].protocol=t)}}function nn(...t){w.log("[https-proxy-agent:parse-proxy-response]",...t)}function en(t){return new Promise((n,e)=>{let r=0;const o=[];function i(){const c=t.read();c?function(c){o.push(c),r+=c.length;const u=Buffer.concat(o,r),a=u.indexOf("\r\n\r\n");if(-1===a)return nn("have not received end of HTTP headers yet..."),void i();const f=u.subarray(0,a).toString("ascii").split("\r\n"),h=f.shift();if(!h)return t.destroy(),e(new Error("No header received from proxy CONNECT response"));const p=h.split(" "),d=+(p[1]||0),l=p.slice(2).join(" "),g={};for(const n of f){if(!n)continue;const r=n.indexOf(":");if(-1===r)return t.destroy(),e(new Error(`Invalid header from proxy CONNECT response: "${n}"`));const o=n.slice(0,r).toLowerCase(),i=n.slice(r+1).trimStart(),s=g[o];"string"==typeof s?g[o]=[s,i]:Array.isArray(s)?s.push(i):g[o]=i}nn("got proxy server response: %o %o",h,g),s(),n({connect:{statusCode:d,statusText:l,headers:g},buffered:u})}(c):t.once("readable",i)}function s(){t.removeListener("end",c),t.removeListener("error",u),t.removeListener("readable",i)}function c(){s(),nn("onend"),e(new Error("Proxy connection ended before receiving CONNECT response"))}function u(t){s(),nn("onerror %o",t),e(t)}t.on("error",u),t.on("end",c),i()})}function rn(...t){w.log("[https-proxy-agent]",...t)}class on extends tn{constructor(t,n){super(n),this.options={},this.proxy="string"==typeof t?new URL(t):t,this.proxyHeaders=n?.headers??{},rn("Creating new HttpsProxyAgent instance: %o",this.proxy.href);const e=(this.proxy.hostname||this.proxy.host).replace(/^\[|\]$/g,""),r=this.proxy.port?parseInt(this.proxy.port,10):"https:"===this.proxy.protocol?443:80;this.connectOpts={ALPNProtocols:["http/1.1"],...n?cn(n,"headers"):null,host:e,port:r}}async connect(t,n){const{proxy:e}=this;if(!n.host)throw new TypeError('No "host" provided');let r;if("https:"===e.protocol){rn("Creating `tls.Socket`: %o",this.connectOpts);const t=this.connectOpts.servername||this.connectOpts.host;r=f.connect({...this.connectOpts,servername:t&&a.isIP(t)?void 0:t})}else rn("Creating `net.Socket`: %o",this.connectOpts),r=a.connect(this.connectOpts);const o="function"==typeof this.proxyHeaders?this.proxyHeaders():{...this.proxyHeaders},i=a.isIPv6(n.host)?`[${n.host}]`:n.host;let s=`CONNECT ${i}:${n.port} HTTP/1.1\r\n`;if(e.username||e.password){const t=`${decodeURIComponent(e.username)}:${decodeURIComponent(e.password)}`;o["Proxy-Authorization"]=`Basic ${Buffer.from(t).toString("base64")}`}o.Host=`${i}:${n.port}`,o["Proxy-Connection"]||(o["Proxy-Connection"]=this.keepAlive?"Keep-Alive":"close");for(const t of Object.keys(o))s+=`${t}: ${o[t]}\r\n`;const c=en(r);r.write(`${s}\r\n`);const{connect:u,buffered:h}=await c;if(t.emit("proxyConnect",u),this.emit("proxyConnect",u,t),200===u.statusCode){if(t.once("socket",sn),n.secureEndpoint){rn("Upgrading socket connection to TLS");const t=n.servername||n.host;return f.connect({...cn(n,"host","path","port"),socket:r,servername:a.isIP(t)?void 0:t})}return r}r.destroy();const p=new a.Socket({writable:!1});return p.readable=!0,t.once("socket",t=>{rn("Replaying proxy buffer for failed request"),t.push(h),t.push(null)}),p}}function sn(t){t.resume()}function cn(t,...n){const e={};let r;for(r in t)n.includes(r)||(e[r]=t[r]);return e}on.protocols=["http","https"];function un(t){return t.replace(/^[A-Z]:/,"").replace(/\\/g,"/")}const an=n;let fn,hn=0,pn={};function dn(t){an.debug&&console.log(`[ANR Worker] ${t}`)}var ln,gn,mn;const yn=function(t){let n;try{n=new URL(t.url)}catch(n){return b(()=>{console.warn("[@sentry/node]: Invalid dsn or tunnel option, will not send any events. The tunnel option must be a full URL when used.")}),Kt(t,()=>Promise.resolve({}))}const e="https:"===n.protocol,r=function(t,n){const{no_proxy:e}=process.env,r=e?.split(",").some(n=>t.host.endsWith(n)||t.hostname.endsWith(n));return r?void 0:n}(n,t.proxy||(e?process.env.https_proxy:void 0)||process.env.http_proxy),o=e?s:i,a=void 0!==t.keepAlive&&t.keepAlive,f=r?new on(r):new o.Agent({keepAlive:a,maxSockets:30,timeout:2e3}),h=function(t,n,e){const{hostname:r,pathname:o,port:i,protocol:s,search:a}=new URL(t.url);return function(f){return new Promise((h,p)=>{Ft(()=>{let d=function(t){return new c({read(){this.push(t),this.push(null)}})}(f.body);const l={...t.headers};f.body.length>32768&&(l["content-encoding"]="gzip",d=d.pipe(u()));const g=r.startsWith("["),m=n.request({method:"POST",agent:e,headers:l,hostname:g?r.slice(1,-1):r,path:`${o}${a}`,port:i,protocol:s,ca:t.caCerts},t=>{t.on("data",()=>{}),t.on("end",()=>{}),t.setEncoding("utf8");const n=t.headers["retry-after"]??null,e=t.headers["x-sentry-rate-limits"]??null;h({statusCode:t.statusCode,headers:{"retry-after":n,"x-sentry-rate-limits":Array.isArray(e)?e[0]||null:e}})});m.on("error",p),d.pipe(m)})})}}(t,t.httpModule??o,f);return Kt(t,h)}({url:(ln=an.dsn,gn=an.tunnel,mn=an.sdkMetadata.sdk,gn||`${function(t){return`${function(t){const n=t.protocol?`${t.protocol}:`:"",e=t.port?`:${t.port}`:"";return`${n}//${t.host}${e}${t.path?`/${t.path}`:""}/api/`}(t)}${t.projectId}/envelope/`}(ln)}?${function(t,n){const e={sentry_version:"7"};return t.publicKey&&(e.sentry_key=t.publicKey),n&&(e.sentry_client=`${n.name}/${n.version}`),new URLSearchParams(e).toString()}(ln,mn)}`)});async function bn(){if(fn){dn("Sending abnormal session"),K(fn,{status:"abnormal",abnormal_mechanism:"anr_foreground",release:an.release,environment:an.environment});const t=function(t,n,e,r){const o=Lt(e);return Tt({sent_at:new Date(P()).toISOString(),...o&&{sdk:o},...!!r&&n&&{dsn:bt(n)}},["aggregates"in t?[{type:"sessions"},t]:[{type:"session"},t.toJSON()]])}(fn,an.dsn,an.sdkMetadata,an.tunnel);dn(JSON.stringify(t)),await yn.send(t);try{e?.postMessage("session-ended")}catch{}}}function vn(t){if(!t)return;const n=function(t){if(!t.length)return[];const n=Array.from(t);return/sentryWrapped/.test(E(n).function||"")&&n.pop(),n.reverse(),$.test(E(n).function||"")&&(n.pop(),$.test(E(n).function||"")&&n.pop()),n.slice(0,50).map(t=>({...t,filename:t.filename||E(n).filename,function:t.function||"?"}))}(t);if(an.appRootPath)for(const t of n)t.filename&&(t.filename=M(t.filename,an.appRootPath));return n}async function _n(t,n){if(hn>=an.maxAnrEvents)return;hn+=1,await bn(),dn("Sending event");const e={event_id:G(),contexts:an.contexts,release:an.release,environment:an.environment,dist:an.dist,platform:"node",level:"error",exception:{values:[{type:"ApplicationNotResponding",value:`Application Not Responding for at least ${an.anrThreshold} ms`,stacktrace:{frames:vn(t)},mechanism:{type:"ANR"}}]},tags:an.staticTags};n&&function(t,n){if(Gt(t,n),!t.contexts?.trace){const{traceId:e,parentSpanId:r,propagationSpanId:o}=n.propagationContext;t.contexts={trace:{trace_id:e,span_id:o||V(),parent_span_id:r},...t.contexts}}}(e,n),function(t){if(0===Object.keys(pn).length)return;const n=an.appRootPath?{}:pn;if(an.appRootPath)for(const[t,e]of Object.entries(pn))n[M(t,an.appRootPath)]=e;const e=new Map;for(const r of t.exception?.values||[])for(const t of r.stacktrace?.frames||[]){const r=t.abs_path||t.filename;r&&n[r]&&e.set(r,n[r])}if(e.size>0){const n=[];for(const[t,r]of e.entries())n.push({type:"sourcemap",code_file:t,debug_id:r});t.debug_meta={images:n}}}(e);const r=Mt(e,an.dsn,an.sdkMetadata,an.tunnel);dn(JSON.stringify(r)),await yn.send(r),await yn.flush(2e3),hn>=an.maxAnrEvents&&setTimeout(()=>{process.exit(0)},5e3)}let Sn;if(dn("Started"),an.captureStackTrace){dn("Connecting to debugger");const n=new t;n.connectToMainThread(),dn("Connected to debugger");const e=new Map;n.on("Debugger.scriptParsed",t=>{e.set(t.params.scriptId,t.params.url)}),n.on("Debugger.paused",t=>{if("other"===t.params.reason)try{dn("Debugger paused");const i=[...t.params.callFrames],s=an.appRootPath?function(t=(process.argv[1]?qt(process.argv[1]):process.cwd()),n="\\"===o){const e=n?un(t):t;return t=>{if(!t)return;const o=n?un(t):t;let{dir:i,base:s,ext:c}=r.parse(o);".js"!==c&&".mjs"!==c&&".cjs"!==c||(s=s.slice(0,-1*c.length));const u=decodeURIComponent(s);i||(i=".");const a=i.lastIndexOf("/node_modules");if(a>-1)return`${i.slice(a+14).replace(/\//g,".")}:${u}`;if(i.startsWith(e)){const t=i.slice(e.length+1).replace(/\//g,".");return t?`${t}:${u}`:u}return u}}(an.appRootPath):()=>{},c=i.map(t=>function(t,n,e){const r=n?n.replace(/^file:\/\//,""):void 0,o=t.location.columnNumber?t.location.columnNumber+1:void 0,i=t.location.lineNumber?t.location.lineNumber+1:void 0;return{filename:r,module:e(r),function:t.functionName||"?",colno:o,lineno:i,in_app:r?Vt(r):void 0}}(t,e.get(t.location.scriptId),s)),u=setTimeout(()=>{_n(c).then(null,()=>{dn("Sending ANR event failed.")})},5e3);n.post("Runtime.evaluate",{expression:"global.__SENTRY_GET_SCOPES__();",silent:!0,returnByValue:!0},(t,e)=>{t&&dn(`Error executing script: '${t.message}'`),clearTimeout(u);const r=e?.result?e.result.value:void 0;n.post("Debugger.resume"),n.post("Debugger.disable"),_n(c,r).then(null,()=>{dn("Sending ANR event failed.")})})}catch(t){throw n.post("Debugger.resume"),n.post("Debugger.disable"),t}}),Sn=()=>{try{n.post("Debugger.enable",()=>{n.post("Debugger.pause")})}catch{}}}const{poll:wn}=function(t,n,e,r){const o=t();let i=!1,s=!0;return setInterval(()=>{const t=o.getTimeMs();!1===i&&t>n+e&&(i=!0,s&&r()),t<n+e&&(i=!1)},20),{poll:()=>{o.reset()},enabled:t=>{s=t}}}(function(){let t=process.hrtime();return{getTimeMs:()=>{const[n,e]=process.hrtime(t);return Math.floor(1e3*n+e/1e6)},reset:()=>{t=process.hrtime()}}},an.pollInterval,an.anrThreshold,function(){dn("Watchdog timeout"),Sn?(dn("Pausing debugger to capture stack trace"),Sn()):(dn("Capturing event without a stack trace"),_n().then(null,()=>{dn("Sending ANR event failed on watchdog timeout.")}))});e?.on("message",t=>{t.session&&(fn=H(t.session)),t.debugImages&&(pn=t.debugImages),wn()}); |
| import { errorMonitor } from 'node:events'; | ||
| import { SpanKind, context, trace } from '@opentelemetry/api'; | ||
| import { RPCType, setRPCMetadata, getRPCMetadata } from '@opentelemetry/core'; | ||
| import { RPCType, setRPCMetadata } from '@opentelemetry/core'; | ||
| import { NET_HOST_IP, NET_HOST_PORT, NET_PEER_IP, HTTP_STATUS_CODE, HTTP_ROUTE, HTTP_RESPONSE_STATUS_CODE } from '@sentry/conventions/attributes'; | ||
@@ -77,6 +77,3 @@ import { debug, parseStringToURLObject, stripUrlQueryAndFragment, httpHeadersToSpanAttributes, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, getSpanStatusFromHttpCode, SPAN_STATUS_ERROR, isTracingSuppressed, getIsolationScope } from '@sentry/core'; | ||
| onSpanCreated?.(span, request, response); | ||
| const rpcMetadata = { | ||
| type: RPCType.HTTP, | ||
| span | ||
| }; | ||
| const rpcMetadata = { type: RPCType.HTTP, span }; | ||
| return context.with(setRPCMetadata(trace.setSpan(context.active(), span), rpcMetadata), () => { | ||
@@ -91,3 +88,3 @@ context.bind(context.active(), request); | ||
| isEnded = true; | ||
| const newAttributes = getIncomingRequestAttributesOnResponse(request, response); | ||
| const newAttributes = getIncomingRequestAttributesOnResponse(request, response, rpcMetadata); | ||
| span.setAttributes(newAttributes); | ||
@@ -118,7 +115,13 @@ span.setStatus(status); | ||
| if (typeof statusCode === "number") { | ||
| const shouldDrop = shouldFilterStatusCode(statusCode, ignoreStatusCodes); | ||
| if (shouldDrop) { | ||
| if (shouldFilterStatusCode(statusCode, ignoreStatusCodes)) { | ||
| DEBUG_BUILD && debug.log("Dropping transaction due to status code", statusCode); | ||
| return null; | ||
| } | ||
| event.contexts = { | ||
| ...event.contexts, | ||
| response: { | ||
| ...event.contexts?.response, | ||
| status_code: statusCode | ||
| } | ||
| }; | ||
| } | ||
@@ -205,3 +208,3 @@ } | ||
| } | ||
| function getIncomingRequestAttributesOnResponse(request, response) { | ||
| function getIncomingRequestAttributesOnResponse(request, response, rpcMetadata) { | ||
| const { socket } = request; | ||
@@ -215,3 +218,2 @@ const { statusCode, statusMessage } = response; | ||
| }; | ||
| const rpcMetadata = getRPCMetadata(context.active()); | ||
| if (socket) { | ||
@@ -218,0 +220,0 @@ const { localAddress, localPort, remoteAddress, remotePort } = socket; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"httpServerSpansIntegration.js","sources":["../../../../src/integrations/http/httpServerSpansIntegration.ts"],"sourcesContent":["import { errorMonitor } from 'node:events';\nimport type { IncomingHttpHeaders } from 'node:http';\nimport { context, SpanKind, trace } from '@opentelemetry/api';\nimport type { RPCMetadata } from '@opentelemetry/core';\nimport { getRPCMetadata, RPCType, setRPCMetadata } from '@opentelemetry/core';\nimport {\n HTTP_RESPONSE_STATUS_CODE,\n HTTP_ROUTE,\n HTTP_STATUS_CODE,\n NET_HOST_IP,\n NET_HOST_PORT,\n NET_PEER_IP,\n} from '@sentry/conventions/attributes';\nimport type {\n Event,\n HttpClientRequest,\n HttpIncomingMessage,\n HttpServerResponse,\n Integration,\n IntegrationFn,\n Span,\n SpanAttributes,\n SpanStatus,\n} from '@sentry/core';\nimport {\n debug,\n getIsolationScope,\n getSpanStatusFromHttpCode,\n httpHeadersToSpanAttributes,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_ERROR,\n stripUrlQueryAndFragment,\n isTracingSuppressed,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport type { NodeClient } from '../../sdk/client';\nimport { addStartSpanCallback } from './httpServerIntegration';\n\nconst INTEGRATION_NAME = 'Http.ServerSpans' as const;\n\n// Tree-shakable guard to remove all code related to tracing\ndeclare const __SENTRY_TRACING__: boolean;\n\nexport interface HttpServerSpansIntegrationOptions {\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: HttpIncomingMessage) => boolean;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with some 3xx and 4xx status codes are ignored (see @default).\n * Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.\n *\n * @default `[[401, 404], [301, 303], [305, 399]]`\n */\n ignoreStatusCodes?: (number | [number, number])[];\n\n /**\n * @deprecated This is deprecated in favor of `incomingRequestSpanHook`.\n */\n instrumentation?: {\n requestHook?: (span: Span, req: HttpClientRequest | HttpIncomingMessage) => void;\n responseHook?: (span: Span, response: HttpIncomingMessage | HttpServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: HttpClientRequest | HttpIncomingMessage,\n response: HttpIncomingMessage | HttpServerResponse,\n ) => void;\n };\n\n /**\n * A hook that can be used to mutate the span for incoming requests.\n * This is triggered after the span is created, but before it is recorded.\n */\n onSpanCreated?: (span: Span, request: HttpIncomingMessage, response: HttpServerResponse) => void;\n}\n\nconst _httpServerSpansIntegration = ((options: HttpServerSpansIntegrationOptions = {}) => {\n const ignoreStaticAssets = options.ignoreStaticAssets ?? true;\n const ignoreIncomingRequests = options.ignoreIncomingRequests;\n const ignoreStatusCodes = options.ignoreStatusCodes ?? [\n [401, 404],\n // 300 and 304 are possibly valid status codes we do not want to filter\n [301, 303],\n [305, 399],\n ];\n\n const { onSpanCreated } = options;\n // eslint-disable-next-line typescript/no-deprecated\n const { requestHook, responseHook, applyCustomAttributesOnSpan } = options.instrumentation ?? {};\n\n return {\n name: INTEGRATION_NAME,\n setup(client: NodeClient) {\n // If no tracing, we can just skip everything here\n if (typeof __SENTRY_TRACING__ !== 'undefined' && !__SENTRY_TRACING__) {\n return;\n }\n\n client.on('httpServerRequest', (_request, _response, normalizedRequest) => {\n // Type-casting this here because we do not want to put the node types into core\n const request = _request as HttpIncomingMessage;\n const response = _response as HttpServerResponse;\n\n const startSpan = (next: () => boolean): boolean => {\n if (\n shouldIgnoreSpansForIncomingRequest(request, {\n ignoreStaticAssets,\n ignoreIncomingRequests,\n })\n ) {\n DEBUG_BUILD && debug.log(INTEGRATION_NAME, 'Skipping span creation for incoming request', request.url);\n return next();\n }\n\n const fullUrl = normalizedRequest.url || request.url || '/';\n const urlObj = parseStringToURLObject(fullUrl);\n\n const headers = request.headers;\n const userAgent = headers['user-agent'];\n const ips = headers['x-forwarded-for'];\n const httpVersion = request.httpVersion;\n const host = headers.host as string | undefined;\n const hostname = host?.replace(/^(.*)(:[0-9]{1,5})/, '$1') || 'localhost';\n\n const tracer = client.tracer;\n const scheme = fullUrl.startsWith('https') ? 'https' : 'http';\n\n const method = normalizedRequest.method || request.method?.toUpperCase() || 'GET';\n const httpTargetWithoutQueryFragment = urlObj ? urlObj.pathname : stripUrlQueryAndFragment(fullUrl);\n const bestEffortTransactionName = `${method} ${httpTargetWithoutQueryFragment}`;\n\n // We use the plain tracer.startSpan here so we can pass the span kind\n const span = tracer.startSpan(bestEffortTransactionName, {\n kind: SpanKind.SERVER,\n attributes: {\n // Sentry specific attributes\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.http',\n 'sentry.http.prefetch': isKnownPrefetchRequest(request) || undefined,\n // Old Semantic Conventions attributes - added for compatibility with what `@opentelemetry/instrumentation-http` output before\n 'http.url': fullUrl,\n 'http.method': normalizedRequest.method,\n 'http.target': urlObj ? `${urlObj.pathname}${urlObj.search}` : httpTargetWithoutQueryFragment,\n 'http.host': host,\n 'net.host.name': hostname,\n 'http.client_ip': typeof ips === 'string' ? ips.split(',')[0] : undefined,\n 'http.user_agent': userAgent,\n 'http.scheme': scheme,\n 'http.flavor': httpVersion,\n 'net.transport': httpVersion?.toUpperCase() === 'QUIC' ? 'ip_udp' : 'ip_tcp',\n ...getRequestContentLengthAttribute(request),\n ...httpHeadersToSpanAttributes(normalizedRequest.headers || {}, client.getDataCollectionOptions()),\n },\n });\n\n // TODO v11: Remove the following three hooks, only onSpanCreated should remain\n requestHook?.(span, request);\n responseHook?.(span, response);\n applyCustomAttributesOnSpan?.(span, request, response);\n onSpanCreated?.(span, request, response);\n\n const rpcMetadata: RPCMetadata = {\n type: RPCType.HTTP,\n span,\n };\n\n return context.with(setRPCMetadata(trace.setSpan(context.active(), span), rpcMetadata), () => {\n context.bind(context.active(), request);\n context.bind(context.active(), response);\n\n // Ensure we only end the span once\n // E.g. error can be emitted before close is emitted\n let isEnded = false;\n function endSpan(status: SpanStatus): void {\n if (isEnded) {\n return;\n }\n\n isEnded = true;\n\n const newAttributes = getIncomingRequestAttributesOnResponse(request, response);\n span.setAttributes(newAttributes);\n span.setStatus(status);\n span.end();\n\n // Update the transaction name if the route has changed\n const route = newAttributes['http.route'];\n if (route) {\n getIsolationScope().setTransactionName(`${request.method?.toUpperCase() || 'GET'} ${route}`);\n }\n }\n\n response.on('close', () => {\n endSpan(getSpanStatusFromHttpCode(response.statusCode));\n });\n response.on(errorMonitor, () => {\n const httpStatus = getSpanStatusFromHttpCode(response.statusCode);\n // Ensure we def. have an error status here\n endSpan(httpStatus.code === SPAN_STATUS_ERROR ? httpStatus : { code: SPAN_STATUS_ERROR });\n });\n\n return next();\n });\n };\n\n addStartSpanCallback(request, startSpan);\n });\n },\n processEvent(event) {\n // Drop transaction if it has a status code that should be ignored\n if (event.type === 'transaction') {\n const statusCode = event.contexts?.trace?.data?.['http.response.status_code'];\n if (typeof statusCode === 'number') {\n const shouldDrop = shouldFilterStatusCode(statusCode, ignoreStatusCodes);\n if (shouldDrop) {\n DEBUG_BUILD && debug.log('Dropping transaction due to status code', statusCode);\n return null;\n }\n }\n }\n\n return event;\n },\n afterAllSetup(client) {\n if (!DEBUG_BUILD) {\n return;\n }\n\n if (client.getIntegrationByName('Http')) {\n debug.warn(\n 'It seems that you have manually added `httpServerSpansIntegration` while `httpIntegration` is also present. Make sure to remove `httpIntegration` when adding `httpServerSpansIntegration`.',\n );\n }\n\n if (!client.getIntegrationByName('Http.Server')) {\n debug.error(\n 'It seems that you have manually added `httpServerSpansIntegration` without adding `httpServerIntegration`. This is a requiement for spans to be created - please add the `httpServerIntegration` integration.',\n );\n }\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * This integration emits spans for incoming requests handled via the node `http` module.\n * It requires the `httpServerIntegration` to be present.\n */\nexport const httpServerSpansIntegration = _httpServerSpansIntegration as (\n options?: HttpServerSpansIntegrationOptions,\n) => Integration & {\n name: 'Http.ServerSpans';\n setup: (client: NodeClient) => void;\n processEvent: (event: Event) => Event | null;\n};\n\nfunction isKnownPrefetchRequest(req: HttpIncomingMessage): 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\n/**\n * Check if a request is for a common static asset that should be ignored by default.\n *\n * Only exported for tests.\n */\nexport function isStaticAssetRequest(urlPath: string): boolean {\n const path = stripUrlQueryAndFragment(urlPath);\n // Common static file extensions\n if (path.match(/\\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {\n return true;\n }\n\n // Common metadata files\n if (path.match(/^\\/(robots\\.txt|sitemap\\.xml|manifest\\.json|browserconfig\\.xml)$/)) {\n return true;\n }\n\n return false;\n}\n\nfunction shouldIgnoreSpansForIncomingRequest(\n request: HttpIncomingMessage,\n {\n ignoreStaticAssets,\n ignoreIncomingRequests,\n }: {\n ignoreStaticAssets?: boolean;\n ignoreIncomingRequests?: (urlPath: string, request: HttpIncomingMessage) => boolean;\n },\n): boolean {\n if (isTracingSuppressed()) {\n return true;\n }\n\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 spans\n if (method === 'OPTIONS' || method === 'HEAD' || !urlPath) {\n return true;\n }\n\n // Default static asset filtering\n if (ignoreStaticAssets && method === 'GET' && isStaticAssetRequest(urlPath)) {\n return true;\n }\n\n if (ignoreIncomingRequests?.(urlPath, request)) {\n return true;\n }\n\n return false;\n}\n\nfunction getRequestContentLengthAttribute(request: HttpIncomingMessage): SpanAttributes {\n const length = getContentLength(request.headers);\n if (length == null) {\n return {};\n }\n\n if (isCompressed(request.headers)) {\n return {\n ['http.request_content_length']: length,\n };\n } else {\n return {\n ['http.request_content_length_uncompressed']: length,\n };\n }\n}\n\nfunction getContentLength(headers: IncomingHttpHeaders): number | null {\n const contentLengthHeader = headers['content-length'];\n if (contentLengthHeader === undefined) return null;\n\n const contentLength = parseInt(contentLengthHeader, 10);\n if (isNaN(contentLength)) return null;\n\n return contentLength;\n}\n\nfunction isCompressed(headers: IncomingHttpHeaders): boolean {\n const encoding = headers['content-encoding'];\n\n return !!encoding && encoding !== 'identity';\n}\n\nfunction getIncomingRequestAttributesOnResponse(\n request: HttpIncomingMessage,\n response: HttpServerResponse,\n): SpanAttributes {\n // take socket from the request,\n // since it may be detached from the response object in keep-alive mode\n const { socket } = request;\n const { statusCode, statusMessage } = response;\n\n const newAttributes: SpanAttributes = {\n [HTTP_RESPONSE_STATUS_CODE]: statusCode,\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_STATUS_CODE]: statusCode,\n 'http.status_text': statusMessage?.toUpperCase(),\n };\n\n const rpcMetadata = getRPCMetadata(context.active());\n if (socket) {\n const { localAddress, localPort, remoteAddress, remotePort } = socket;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_HOST_IP] = localAddress;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_HOST_PORT] = localPort;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_PEER_IP] = remoteAddress;\n newAttributes['net.peer.port'] = remotePort;\n }\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[HTTP_STATUS_CODE] = statusCode;\n newAttributes['http.status_text'] = (statusMessage || '').toUpperCase();\n\n if (rpcMetadata?.type === RPCType.HTTP && rpcMetadata.route !== undefined) {\n const routeName = rpcMetadata.route;\n newAttributes[HTTP_ROUTE] = routeName;\n }\n\n return newAttributes;\n}\n\n/**\n * If the given status code should be filtered for the given list of status codes/ranges.\n */\nfunction shouldFilterStatusCode(statusCode: number, dropForStatusCodes: (number | [number, number])[]): boolean {\n return dropForStatusCodes.some(code => {\n if (typeof code === 'number') {\n return code === statusCode;\n }\n\n const [min, max] = code;\n return statusCode >= min && statusCode <= max;\n });\n}\n"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"httpServerSpansIntegration.js","sources":["../../../../src/integrations/http/httpServerSpansIntegration.ts"],"sourcesContent":["import { errorMonitor } from 'node:events';\nimport type { IncomingHttpHeaders } from 'node:http';\nimport { context, SpanKind, trace } from '@opentelemetry/api';\nimport type { RPCMetadata } from '@opentelemetry/core';\nimport { RPCType, setRPCMetadata } from '@opentelemetry/core';\nimport {\n HTTP_RESPONSE_STATUS_CODE,\n HTTP_ROUTE,\n HTTP_STATUS_CODE,\n NET_HOST_IP,\n NET_HOST_PORT,\n NET_PEER_IP,\n} from '@sentry/conventions/attributes';\nimport type {\n Event,\n HttpClientRequest,\n HttpIncomingMessage,\n HttpServerResponse,\n Integration,\n IntegrationFn,\n Span,\n SpanAttributes,\n SpanStatus,\n} from '@sentry/core';\nimport {\n debug,\n getIsolationScope,\n getSpanStatusFromHttpCode,\n httpHeadersToSpanAttributes,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_ERROR,\n stripUrlQueryAndFragment,\n isTracingSuppressed,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport type { NodeClient } from '../../sdk/client';\nimport { addStartSpanCallback } from './httpServerIntegration';\n\nconst INTEGRATION_NAME = 'Http.ServerSpans' as const;\n\n// Tree-shakable guard to remove all code related to tracing\ndeclare const __SENTRY_TRACING__: boolean;\n\nexport interface HttpServerSpansIntegrationOptions {\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: HttpIncomingMessage) => boolean;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with some 3xx and 4xx status codes are ignored (see @default).\n * Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.\n *\n * @default `[[401, 404], [301, 303], [305, 399]]`\n */\n ignoreStatusCodes?: (number | [number, number])[];\n\n /**\n * @deprecated This is deprecated in favor of `incomingRequestSpanHook`.\n */\n instrumentation?: {\n requestHook?: (span: Span, req: HttpClientRequest | HttpIncomingMessage) => void;\n responseHook?: (span: Span, response: HttpIncomingMessage | HttpServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: HttpClientRequest | HttpIncomingMessage,\n response: HttpIncomingMessage | HttpServerResponse,\n ) => void;\n };\n\n /**\n * A hook that can be used to mutate the span for incoming requests.\n * This is triggered after the span is created, but before it is recorded.\n */\n onSpanCreated?: (span: Span, request: HttpIncomingMessage, response: HttpServerResponse) => void;\n}\n\nconst _httpServerSpansIntegration = ((options: HttpServerSpansIntegrationOptions = {}) => {\n const ignoreStaticAssets = options.ignoreStaticAssets ?? true;\n const ignoreIncomingRequests = options.ignoreIncomingRequests;\n const ignoreStatusCodes = options.ignoreStatusCodes ?? [\n [401, 404],\n // 300 and 304 are possibly valid status codes we do not want to filter\n [301, 303],\n [305, 399],\n ];\n\n const { onSpanCreated } = options;\n // eslint-disable-next-line typescript/no-deprecated\n const { requestHook, responseHook, applyCustomAttributesOnSpan } = options.instrumentation ?? {};\n\n return {\n name: INTEGRATION_NAME,\n setup(client: NodeClient) {\n // If no tracing, we can just skip everything here\n if (typeof __SENTRY_TRACING__ !== 'undefined' && !__SENTRY_TRACING__) {\n return;\n }\n\n client.on('httpServerRequest', (_request, _response, normalizedRequest) => {\n // Type-casting this here because we do not want to put the node types into core\n const request = _request as HttpIncomingMessage;\n const response = _response as HttpServerResponse;\n\n const startSpan = (next: () => boolean): boolean => {\n if (\n shouldIgnoreSpansForIncomingRequest(request, {\n ignoreStaticAssets,\n ignoreIncomingRequests,\n })\n ) {\n DEBUG_BUILD && debug.log(INTEGRATION_NAME, 'Skipping span creation for incoming request', request.url);\n return next();\n }\n\n const fullUrl = normalizedRequest.url || request.url || '/';\n const urlObj = parseStringToURLObject(fullUrl);\n\n const headers = request.headers;\n const userAgent = headers['user-agent'];\n const ips = headers['x-forwarded-for'];\n const httpVersion = request.httpVersion;\n const host = headers.host as string | undefined;\n const hostname = host?.replace(/^(.*)(:[0-9]{1,5})/, '$1') || 'localhost';\n\n const tracer = client.tracer;\n const scheme = fullUrl.startsWith('https') ? 'https' : 'http';\n\n const method = normalizedRequest.method || request.method?.toUpperCase() || 'GET';\n const httpTargetWithoutQueryFragment = urlObj ? urlObj.pathname : stripUrlQueryAndFragment(fullUrl);\n const bestEffortTransactionName = `${method} ${httpTargetWithoutQueryFragment}`;\n\n // We use the plain tracer.startSpan here so we can pass the span kind\n const span = tracer.startSpan(bestEffortTransactionName, {\n kind: SpanKind.SERVER,\n attributes: {\n // Sentry specific attributes\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.http',\n 'sentry.http.prefetch': isKnownPrefetchRequest(request) || undefined,\n // Old Semantic Conventions attributes - added for compatibility with what `@opentelemetry/instrumentation-http` output before\n 'http.url': fullUrl,\n 'http.method': normalizedRequest.method,\n 'http.target': urlObj ? `${urlObj.pathname}${urlObj.search}` : httpTargetWithoutQueryFragment,\n 'http.host': host,\n 'net.host.name': hostname,\n 'http.client_ip': typeof ips === 'string' ? ips.split(',')[0] : undefined,\n 'http.user_agent': userAgent,\n 'http.scheme': scheme,\n 'http.flavor': httpVersion,\n 'net.transport': httpVersion?.toUpperCase() === 'QUIC' ? 'ip_udp' : 'ip_tcp',\n ...getRequestContentLengthAttribute(request),\n ...httpHeadersToSpanAttributes(normalizedRequest.headers || {}, client.getDataCollectionOptions()),\n },\n });\n\n // TODO v11: Remove the following three hooks, only onSpanCreated should remain\n requestHook?.(span, request);\n responseHook?.(span, response);\n applyCustomAttributesOnSpan?.(span, request, response);\n onSpanCreated?.(span, request, response);\n\n const rpcMetadata: RPCMetadata = { type: RPCType.HTTP, span };\n\n return context.with(setRPCMetadata(trace.setSpan(context.active(), span), rpcMetadata), () => {\n context.bind(context.active(), request);\n context.bind(context.active(), response);\n\n // Ensure we only end the span once\n // E.g. error can be emitted before close is emitted\n let isEnded = false;\n function endSpan(status: SpanStatus): void {\n if (isEnded) {\n return;\n }\n\n isEnded = true;\n\n const newAttributes = getIncomingRequestAttributesOnResponse(request, response, rpcMetadata);\n span.setAttributes(newAttributes);\n span.setStatus(status);\n span.end();\n\n // Update the transaction name if the route has changed\n const route = newAttributes['http.route'];\n if (route) {\n getIsolationScope().setTransactionName(`${request.method?.toUpperCase() || 'GET'} ${route}`);\n }\n }\n\n response.on('close', () => {\n endSpan(getSpanStatusFromHttpCode(response.statusCode));\n });\n response.on(errorMonitor, () => {\n const httpStatus = getSpanStatusFromHttpCode(response.statusCode);\n // Ensure we def. have an error status here\n endSpan(httpStatus.code === SPAN_STATUS_ERROR ? httpStatus : { code: SPAN_STATUS_ERROR });\n });\n\n return next();\n });\n };\n\n addStartSpanCallback(request, startSpan);\n });\n },\n processEvent(event) {\n if (event.type === 'transaction') {\n const statusCode = event.contexts?.trace?.data?.['http.response.status_code'];\n if (typeof statusCode === 'number') {\n // Drop transaction if it has a status code that should be ignored\n if (shouldFilterStatusCode(statusCode, ignoreStatusCodes)) {\n DEBUG_BUILD && debug.log('Dropping transaction due to status code', statusCode);\n return null;\n }\n\n // Surface the HTTP status as the top-level `response` context. The OTel SDK span\n // exporter already does this on its path; doing it here covers transactions produced\n // by the `SentryTracerProvider`, which bypasses that exporter.\n event.contexts = {\n ...event.contexts,\n response: {\n ...event.contexts?.response,\n status_code: statusCode,\n },\n };\n }\n }\n\n return event;\n },\n afterAllSetup(client) {\n if (!DEBUG_BUILD) {\n return;\n }\n\n if (client.getIntegrationByName('Http')) {\n debug.warn(\n 'It seems that you have manually added `httpServerSpansIntegration` while `httpIntegration` is also present. Make sure to remove `httpIntegration` when adding `httpServerSpansIntegration`.',\n );\n }\n\n if (!client.getIntegrationByName('Http.Server')) {\n debug.error(\n 'It seems that you have manually added `httpServerSpansIntegration` without adding `httpServerIntegration`. This is a requiement for spans to be created - please add the `httpServerIntegration` integration.',\n );\n }\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * This integration emits spans for incoming requests handled via the node `http` module.\n * It requires the `httpServerIntegration` to be present.\n */\nexport const httpServerSpansIntegration = _httpServerSpansIntegration as (\n options?: HttpServerSpansIntegrationOptions,\n) => Integration & {\n name: 'Http.ServerSpans';\n setup: (client: NodeClient) => void;\n processEvent: (event: Event) => Event | null;\n};\n\nfunction isKnownPrefetchRequest(req: HttpIncomingMessage): 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\n/**\n * Check if a request is for a common static asset that should be ignored by default.\n *\n * Only exported for tests.\n */\nexport function isStaticAssetRequest(urlPath: string): boolean {\n const path = stripUrlQueryAndFragment(urlPath);\n // Common static file extensions\n if (path.match(/\\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {\n return true;\n }\n\n // Common metadata files\n if (path.match(/^\\/(robots\\.txt|sitemap\\.xml|manifest\\.json|browserconfig\\.xml)$/)) {\n return true;\n }\n\n return false;\n}\n\nfunction shouldIgnoreSpansForIncomingRequest(\n request: HttpIncomingMessage,\n {\n ignoreStaticAssets,\n ignoreIncomingRequests,\n }: {\n ignoreStaticAssets?: boolean;\n ignoreIncomingRequests?: (urlPath: string, request: HttpIncomingMessage) => boolean;\n },\n): boolean {\n if (isTracingSuppressed()) {\n return true;\n }\n\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 spans\n if (method === 'OPTIONS' || method === 'HEAD' || !urlPath) {\n return true;\n }\n\n // Default static asset filtering\n if (ignoreStaticAssets && method === 'GET' && isStaticAssetRequest(urlPath)) {\n return true;\n }\n\n if (ignoreIncomingRequests?.(urlPath, request)) {\n return true;\n }\n\n return false;\n}\n\nfunction getRequestContentLengthAttribute(request: HttpIncomingMessage): SpanAttributes {\n const length = getContentLength(request.headers);\n if (length == null) {\n return {};\n }\n\n if (isCompressed(request.headers)) {\n return {\n ['http.request_content_length']: length,\n };\n } else {\n return {\n ['http.request_content_length_uncompressed']: length,\n };\n }\n}\n\nfunction getContentLength(headers: IncomingHttpHeaders): number | null {\n const contentLengthHeader = headers['content-length'];\n if (contentLengthHeader === undefined) return null;\n\n const contentLength = parseInt(contentLengthHeader, 10);\n if (isNaN(contentLength)) return null;\n\n return contentLength;\n}\n\nfunction isCompressed(headers: IncomingHttpHeaders): boolean {\n const encoding = headers['content-encoding'];\n\n return !!encoding && encoding !== 'identity';\n}\n\nfunction getIncomingRequestAttributesOnResponse(\n request: HttpIncomingMessage,\n response: HttpServerResponse,\n rpcMetadata?: RPCMetadata,\n): SpanAttributes {\n // take socket from the request,\n // since it may be detached from the response object in keep-alive mode\n const { socket } = request;\n const { statusCode, statusMessage } = response;\n\n const newAttributes: SpanAttributes = {\n [HTTP_RESPONSE_STATUS_CODE]: statusCode,\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_STATUS_CODE]: statusCode,\n 'http.status_text': statusMessage?.toUpperCase(),\n };\n\n if (socket) {\n const { localAddress, localPort, remoteAddress, remotePort } = socket;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_HOST_IP] = localAddress;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_HOST_PORT] = localPort;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_PEER_IP] = remoteAddress;\n newAttributes['net.peer.port'] = remotePort;\n }\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[HTTP_STATUS_CODE] = statusCode;\n newAttributes['http.status_text'] = (statusMessage || '').toUpperCase();\n\n if (rpcMetadata?.type === RPCType.HTTP && rpcMetadata.route !== undefined) {\n const routeName = rpcMetadata.route;\n newAttributes[HTTP_ROUTE] = routeName;\n }\n\n return newAttributes;\n}\n\n/**\n * If the given status code should be filtered for the given list of status codes/ranges.\n */\nfunction shouldFilterStatusCode(statusCode: number, dropForStatusCodes: (number | [number, number])[]): boolean {\n return dropForStatusCodes.some(code => {\n if (typeof code === 'number') {\n return code === statusCode;\n }\n\n const [min, max] = code;\n return statusCode >= min && statusCode <= max;\n });\n}\n"],"names":[],"mappings":"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"} |
@@ -6,3 +6,3 @@ import { Worker } from 'node:worker_threads'; | ||
| const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZS1jb3JlIDEwLjYzLjAgKDIzNjJlOWYpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyBlfWZyb20ibm9kZTppbnNwZWN0b3IvcHJvbWlzZXMiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIHR9ZnJvbSJub2RlOndvcmtlcl90aHJlYWRzIjtjb25zdCBuPWdsb2JhbFRoaXMsaT17fTtjb25zdCBvPSJfX1NFTlRSWV9FUlJPUl9MT0NBTF9WQVJJQUJMRVNfXyI7Y29uc3QgYT10O2Z1bmN0aW9uIHMoLi4uZSl7YS5kZWJ1ZyYmZnVuY3Rpb24oZSl7aWYoISgiY29uc29sZSJpbiBuKSlyZXR1cm4gZSgpO2NvbnN0IHQ9bi5jb25zb2xlLG89e30sYT1PYmplY3Qua2V5cyhpKTthLmZvckVhY2goZT0+e2NvbnN0IG49aVtlXTtvW2VdPXRbZV0sdFtlXT1ufSk7dHJ5e3JldHVybiBlKCl9ZmluYWxseXthLmZvckVhY2goZT0+e3RbZV09b1tlXX0pfX0oKCk9PmNvbnNvbGUubG9nKCJbTG9jYWxWYXJpYWJsZXMgV29ya2VyXSIsLi4uZSkpfWFzeW5jIGZ1bmN0aW9uIGMoZSx0LG4saSl7Y29uc3Qgbz1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pO2lbbl09by5yZXN1bHQuZmlsdGVyKGU9PiJsZW5ndGgiIT09ZS5uYW1lJiYhaXNOYU4ocGFyc2VJbnQoZS5uYW1lLDEwKSkpLnNvcnQoKGUsdCk9PnBhcnNlSW50KGUubmFtZSwxMCktcGFyc2VJbnQodC5uYW1lLDEwKSkubWFwKGU9PmUudmFsdWU/LnZhbHVlKX1hc3luYyBmdW5jdGlvbiByKGUsdCxuLGkpe2NvbnN0IG89YXdhaXQgZS5wb3N0KCJSdW50aW1lLmdldFByb3BlcnRpZXMiLHtvYmplY3RJZDp0LG93blByb3BlcnRpZXM6ITB9KTtpW25dPW8ucmVzdWx0Lm1hcChlPT5bZS5uYW1lLGUudmFsdWU/LnZhbHVlXSkucmVkdWNlKChlLFt0LG5dKT0+KGVbdF09bixlKSx7fSl9ZnVuY3Rpb24gdShlLHQpe2UudmFsdWUmJigidmFsdWUiaW4gZS52YWx1ZT92b2lkIDA9PT1lLnZhbHVlLnZhbHVlfHxudWxsPT09ZS52YWx1ZS52YWx1ZT90W2UubmFtZV09YDwke2UudmFsdWUudmFsdWV9PmA6dFtlLm5hbWVdPWUudmFsdWUudmFsdWU6ImRlc2NyaXB0aW9uImluIGUudmFsdWUmJiJmdW5jdGlvbiIhPT1lLnZhbHVlLnR5cGU/dFtlLm5hbWVdPWA8JHtlLnZhbHVlLmRlc2NyaXB0aW9ufT5gOiJ1bmRlZmluZWQiPT09ZS52YWx1ZS50eXBlJiYodFtlLm5hbWVdPSI8dW5kZWZpbmVkPiIpKX1hc3luYyBmdW5jdGlvbiBsKGUsdCl7Y29uc3Qgbj1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pLGk9e307Zm9yKGNvbnN0IHQgb2Ygbi5yZXN1bHQpaWYodC52YWx1ZT8ub2JqZWN0SWQmJiJBcnJheSI9PT10LnZhbHVlLmNsYXNzTmFtZSl7Y29uc3Qgbj10LnZhbHVlLm9iamVjdElkO2F3YWl0IGMoZSxuLHQubmFtZSxpKX1lbHNlIGlmKHQudmFsdWU/Lm9iamVjdElkJiYiT2JqZWN0Ij09PXQudmFsdWUuY2xhc3NOYW1lKXtjb25zdCBuPXQudmFsdWUub2JqZWN0SWQ7YXdhaXQgcihlLG4sdC5uYW1lLGkpfWVsc2UgdC52YWx1ZSYmdSh0LGkpO3JldHVybiBpfWxldCBmOyhhc3luYyBmdW5jdGlvbigpe2NvbnN0IHQ9bmV3IGU7dC5jb25uZWN0VG9NYWluVGhyZWFkKCkscygiQ29ubmVjdGVkIHRvIG1haW4gdGhyZWFkIik7bGV0IG49ITE7dC5vbigiRGVidWdnZXIucmVzdW1lZCIsKCk9PntuPSExfSksdC5vbigiRGVidWdnZXIucGF1c2VkIixlPT57bj0hMCxhc3luYyBmdW5jdGlvbihlLHtyZWFzb246dCxkYXRhOntvYmplY3RJZDpufSxjYWxsRnJhbWVzOml9KXtpZigiZXhjZXB0aW9uIiE9PXQmJiJwcm9taXNlUmVqZWN0aW9uIiE9PXQpcmV0dXJuO2lmKGY/LigpLG51bGw9PW4pcmV0dXJuO2NvbnN0IGE9W107Zm9yKGxldCB0PTA7dDxpLmxlbmd0aDt0Kyspe2NvbnN0e3Njb3BlQ2hhaW46bixmdW5jdGlvbk5hbWU6byx0aGlzOnN9PWlbdF0sYz1uLmZpbmQoZT0+ImxvY2FsIj09PWUudHlwZSkscj0iZ2xvYmFsIiE9PXMuY2xhc3NOYW1lJiZzLmNsYXNzTmFtZT9gJHtzLmNsYXNzTmFtZX0uJHtvfWA6bztpZih2b2lkIDA9PT1jPy5vYmplY3Qub2JqZWN0SWQpYVt0XT17ZnVuY3Rpb246cn07ZWxzZXtjb25zdCBuPWF3YWl0IGwoZSxjLm9iamVjdC5vYmplY3RJZCk7YVt0XT17ZnVuY3Rpb246cix2YXJzOm59fX1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuY2FsbEZ1bmN0aW9uT24iLHtmdW5jdGlvbkRlY2xhcmF0aW9uOmBmdW5jdGlvbigpIHsgdGhpcy4ke299ID0gdGhpcy4ke299IHx8ICR7SlNPTi5zdHJpbmdpZnkoYSl9OyB9YCxzaWxlbnQ6ITAsb2JqZWN0SWQ6bn0pLGF3YWl0IGUucG9zdCgiUnVudGltZS5yZWxlYXNlT2JqZWN0Iix7b2JqZWN0SWQ6bn0pfSh0LGUucGFyYW1zKS50aGVuKGFzeW5jKCk9PntuJiZhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpfSxhc3luYyBlPT57biYmYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKX0pfSksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiKTtjb25zdCBpPSExIT09YS5jYXB0dXJlQWxsRXhjZXB0aW9ucztpZihhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6aT8iYWxsIjoidW5jYXVnaHQifSksaSl7Y29uc3QgZT1hLm1heEV4Y2VwdGlvbnNQZXJTZWNvbmR8fDUwO2Y9ZnVuY3Rpb24oZSx0LG4pe2xldCBpPTAsbz01LGE9MDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCk9PnswPT09YT9pPmUmJihvKj0yLG4obyksbz44NjQwMCYmKG89ODY0MDApLGE9byk6KGEtPTEsMD09PWEmJnQoKSksaT0wfSwxZTMpLnVucmVmKCksKCk9PntpKz0xfX0oZSxhc3luYygpPT57cygiUmF0ZS1saW1pdCBsaWZ0ZWQuIiksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJhbGwifSl9LGFzeW5jIGU9PntzKGBSYXRlLWxpbWl0IGV4Y2VlZGVkLiBEaXNhYmxpbmcgY2FwdHVyaW5nIG9mIGNhdWdodCBleGNlcHRpb25zIGZvciAke2V9IHNlY29uZHMuYCksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJ1bmNhdWdodCJ9KX0pfX0pKCkuY2F0Y2goZT0+e3MoIkZhaWxlZCB0byBzdGFydCBkZWJ1Z2dlciIsZSl9KSxzZXRJbnRlcnZhbCgoKT0+e30sMWU0KTs="; | ||
| const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZS1jb3JlIDEwLjY0LjAgKDU3MzZhMzgpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyBlfWZyb20ibm9kZTppbnNwZWN0b3IvcHJvbWlzZXMiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIHR9ZnJvbSJub2RlOndvcmtlcl90aHJlYWRzIjtjb25zdCBuPWdsb2JhbFRoaXMsaT17fTtjb25zdCBvPSJfX1NFTlRSWV9FUlJPUl9MT0NBTF9WQVJJQUJMRVNfXyI7Y29uc3QgYT10O2Z1bmN0aW9uIHMoLi4uZSl7YS5kZWJ1ZyYmZnVuY3Rpb24oZSl7aWYoISgiY29uc29sZSJpbiBuKSlyZXR1cm4gZSgpO2NvbnN0IHQ9bi5jb25zb2xlLG89e30sYT1PYmplY3Qua2V5cyhpKTthLmZvckVhY2goZT0+e2NvbnN0IG49aVtlXTtvW2VdPXRbZV0sdFtlXT1ufSk7dHJ5e3JldHVybiBlKCl9ZmluYWxseXthLmZvckVhY2goZT0+e3RbZV09b1tlXX0pfX0oKCk9PmNvbnNvbGUubG9nKCJbTG9jYWxWYXJpYWJsZXMgV29ya2VyXSIsLi4uZSkpfWFzeW5jIGZ1bmN0aW9uIGMoZSx0LG4saSl7Y29uc3Qgbz1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pO2lbbl09by5yZXN1bHQuZmlsdGVyKGU9PiJsZW5ndGgiIT09ZS5uYW1lJiYhaXNOYU4ocGFyc2VJbnQoZS5uYW1lLDEwKSkpLnNvcnQoKGUsdCk9PnBhcnNlSW50KGUubmFtZSwxMCktcGFyc2VJbnQodC5uYW1lLDEwKSkubWFwKGU9PmUudmFsdWU/LnZhbHVlKX1hc3luYyBmdW5jdGlvbiByKGUsdCxuLGkpe2NvbnN0IG89YXdhaXQgZS5wb3N0KCJSdW50aW1lLmdldFByb3BlcnRpZXMiLHtvYmplY3RJZDp0LG93blByb3BlcnRpZXM6ITB9KTtpW25dPW8ucmVzdWx0Lm1hcChlPT5bZS5uYW1lLGUudmFsdWU/LnZhbHVlXSkucmVkdWNlKChlLFt0LG5dKT0+KGVbdF09bixlKSx7fSl9ZnVuY3Rpb24gdShlLHQpe2UudmFsdWUmJigidmFsdWUiaW4gZS52YWx1ZT92b2lkIDA9PT1lLnZhbHVlLnZhbHVlfHxudWxsPT09ZS52YWx1ZS52YWx1ZT90W2UubmFtZV09YDwke2UudmFsdWUudmFsdWV9PmA6dFtlLm5hbWVdPWUudmFsdWUudmFsdWU6ImRlc2NyaXB0aW9uImluIGUudmFsdWUmJiJmdW5jdGlvbiIhPT1lLnZhbHVlLnR5cGU/dFtlLm5hbWVdPWA8JHtlLnZhbHVlLmRlc2NyaXB0aW9ufT5gOiJ1bmRlZmluZWQiPT09ZS52YWx1ZS50eXBlJiYodFtlLm5hbWVdPSI8dW5kZWZpbmVkPiIpKX1hc3luYyBmdW5jdGlvbiBsKGUsdCl7Y29uc3Qgbj1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pLGk9e307Zm9yKGNvbnN0IHQgb2Ygbi5yZXN1bHQpaWYodC52YWx1ZT8ub2JqZWN0SWQmJiJBcnJheSI9PT10LnZhbHVlLmNsYXNzTmFtZSl7Y29uc3Qgbj10LnZhbHVlLm9iamVjdElkO2F3YWl0IGMoZSxuLHQubmFtZSxpKX1lbHNlIGlmKHQudmFsdWU/Lm9iamVjdElkJiYiT2JqZWN0Ij09PXQudmFsdWUuY2xhc3NOYW1lKXtjb25zdCBuPXQudmFsdWUub2JqZWN0SWQ7YXdhaXQgcihlLG4sdC5uYW1lLGkpfWVsc2UgdC52YWx1ZSYmdSh0LGkpO3JldHVybiBpfWxldCBmOyhhc3luYyBmdW5jdGlvbigpe2NvbnN0IHQ9bmV3IGU7dC5jb25uZWN0VG9NYWluVGhyZWFkKCkscygiQ29ubmVjdGVkIHRvIG1haW4gdGhyZWFkIik7bGV0IG49ITE7dC5vbigiRGVidWdnZXIucmVzdW1lZCIsKCk9PntuPSExfSksdC5vbigiRGVidWdnZXIucGF1c2VkIixlPT57bj0hMCxhc3luYyBmdW5jdGlvbihlLHtyZWFzb246dCxkYXRhOntvYmplY3RJZDpufSxjYWxsRnJhbWVzOml9KXtpZigiZXhjZXB0aW9uIiE9PXQmJiJwcm9taXNlUmVqZWN0aW9uIiE9PXQpcmV0dXJuO2lmKGY/LigpLG51bGw9PW4pcmV0dXJuO2NvbnN0IGE9W107Zm9yKGxldCB0PTA7dDxpLmxlbmd0aDt0Kyspe2NvbnN0e3Njb3BlQ2hhaW46bixmdW5jdGlvbk5hbWU6byx0aGlzOnN9PWlbdF0sYz1uLmZpbmQoZT0+ImxvY2FsIj09PWUudHlwZSkscj0iZ2xvYmFsIiE9PXMuY2xhc3NOYW1lJiZzLmNsYXNzTmFtZT9gJHtzLmNsYXNzTmFtZX0uJHtvfWA6bztpZih2b2lkIDA9PT1jPy5vYmplY3Qub2JqZWN0SWQpYVt0XT17ZnVuY3Rpb246cn07ZWxzZXtjb25zdCBuPWF3YWl0IGwoZSxjLm9iamVjdC5vYmplY3RJZCk7YVt0XT17ZnVuY3Rpb246cix2YXJzOm59fX1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuY2FsbEZ1bmN0aW9uT24iLHtmdW5jdGlvbkRlY2xhcmF0aW9uOmBmdW5jdGlvbigpIHsgdGhpcy4ke299ID0gdGhpcy4ke299IHx8ICR7SlNPTi5zdHJpbmdpZnkoYSl9OyB9YCxzaWxlbnQ6ITAsb2JqZWN0SWQ6bn0pLGF3YWl0IGUucG9zdCgiUnVudGltZS5yZWxlYXNlT2JqZWN0Iix7b2JqZWN0SWQ6bn0pfSh0LGUucGFyYW1zKS50aGVuKGFzeW5jKCk9PntuJiZhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpfSxhc3luYyBlPT57biYmYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKX0pfSksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiKTtjb25zdCBpPSExIT09YS5jYXB0dXJlQWxsRXhjZXB0aW9ucztpZihhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6aT8iYWxsIjoidW5jYXVnaHQifSksaSl7Y29uc3QgZT1hLm1heEV4Y2VwdGlvbnNQZXJTZWNvbmR8fDUwO2Y9ZnVuY3Rpb24oZSx0LG4pe2xldCBpPTAsbz01LGE9MDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCk9PnswPT09YT9pPmUmJihvKj0yLG4obyksbz44NjQwMCYmKG89ODY0MDApLGE9byk6KGEtPTEsMD09PWEmJnQoKSksaT0wfSwxZTMpLnVucmVmKCksKCk9PntpKz0xfX0oZSxhc3luYygpPT57cygiUmF0ZS1saW1pdCBsaWZ0ZWQuIiksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJhbGwifSl9LGFzeW5jIGU9PntzKGBSYXRlLWxpbWl0IGV4Y2VlZGVkLiBEaXNhYmxpbmcgY2FwdHVyaW5nIG9mIGNhdWdodCBleGNlcHRpb25zIGZvciAke2V9IHNlY29uZHMuYCksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJ1bmNhdWdodCJ9KX0pfX0pKCkuY2F0Y2goZT0+e3MoIkZhaWxlZCB0byBzdGFydCBkZWJ1Z2dlciIsZSl9KSxzZXRJbnRlcnZhbCgoKT0+e30sMWU0KTs="; | ||
| function log(...args) { | ||
@@ -9,0 +9,0 @@ debug.log("[LocalVariables]", ...args); |
@@ -1,2 +0,2 @@ | ||
| /*! @sentry/node-core 10.63.0 (2362e9f) | https://github.com/getsentry/sentry-javascript */ | ||
| /*! @sentry/node-core 10.64.0 (5736a38) | https://github.com/getsentry/sentry-javascript */ | ||
| import{Session as e}from"node:inspector/promises";import{workerData as t}from"node:worker_threads";const n=globalThis,i={};const o="__SENTRY_ERROR_LOCAL_VARIABLES__";const a=t;function s(...e){a.debug&&function(e){if(!("console"in n))return e();const t=n.console,o={},a=Object.keys(i);a.forEach(e=>{const n=i[e];o[e]=t[e],t[e]=n});try{return e()}finally{a.forEach(e=>{t[e]=o[e]})}}(()=>console.log("[LocalVariables Worker]",...e))}async function c(e,t,n,i){const o=await e.post("Runtime.getProperties",{objectId:t,ownProperties:!0});i[n]=o.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 r(e,t,n,i){const o=await e.post("Runtime.getProperties",{objectId:t,ownProperties:!0});i[n]=o.result.map(e=>[e.name,e.value?.value]).reduce((e,[t,n])=>(e[t]=n,e),{})}function u(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 l(e,t){const n=await e.post("Runtime.getProperties",{objectId:t,ownProperties:!0}),i={};for(const t of n.result)if(t.value?.objectId&&"Array"===t.value.className){const n=t.value.objectId;await c(e,n,t.name,i)}else if(t.value?.objectId&&"Object"===t.value.className){const n=t.value.objectId;await r(e,n,t.name,i)}else t.value&&u(t,i);return i}let f;(async function(){const t=new e;t.connectToMainThread(),s("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:i}){if("exception"!==t&&"promiseRejection"!==t)return;if(f?.(),null==n)return;const a=[];for(let t=0;t<i.length;t++){const{scopeChain:n,functionName:o,this:s}=i[t],c=n.find(e=>"local"===e.type),r="global"!==s.className&&s.className?`${s.className}.${o}`:o;if(void 0===c?.object.objectId)a[t]={function:r};else{const n=await l(e,c.object.objectId);a[t]={function:r,vars:n}}}await e.post("Runtime.callFunctionOn",{functionDeclaration:`function() { this.${o} = this.${o} || ${JSON.stringify(a)}; }`,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 i=!1!==a.captureAllExceptions;if(await t.post("Debugger.setPauseOnExceptions",{state:i?"all":"uncaught"}),i){const e=a.maxExceptionsPerSecond||50;f=function(e,t,n){let i=0,o=5,a=0;return setInterval(()=>{0===a?i>e&&(o*=2,n(o),o>86400&&(o=86400),a=o):(a-=1,0===a&&t()),i=0},1e3).unref(),()=>{i+=1}}(e,async()=>{s("Rate-limit lifted."),await t.post("Debugger.setPauseOnExceptions",{state:"all"})},async e=>{s(`Rate-limit exceeded. Disabling capturing of caught exceptions for ${e} seconds.`),await t.post("Debugger.setPauseOnExceptions",{state:"uncaught"})})}})().catch(e=>{s("Failed to start debugger",e)}),setInterval(()=>{},1e4); |
| import { readFileSync } from 'node:fs'; | ||
| import { join } from 'node:path'; | ||
| import { GLOBAL_OBJ } from '@sentry/core'; | ||
| import '../nodeVersion.js'; | ||
@@ -32,4 +31,3 @@ let moduleCache; | ||
| ...getModulesFromPackageJson(), | ||
| ...{} | ||
| }; | ||
| }; | ||
| } | ||
@@ -36,0 +34,0 @@ function _getModules() { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"modules.js","sources":["../../../src/integrations/modules.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { GLOBAL_OBJ, type IntegrationFn } from '@sentry/core';\nimport { isCjs } from '../utils/detection';\n\ntype ModuleInfo = Record<string, string>;\n\nlet moduleCache: ModuleInfo | undefined;\n\nconst INTEGRATION_NAME = 'Modules' as const;\n\ndeclare const __SENTRY_SERVER_MODULES__: Record<string, string>;\n\n/**\n * Reads the modules injected at build time into `__SENTRY_SERVER_MODULES__` (e.g. by the Next.js SDK).\n *\n * Must be read lazily (per call), not captured at module-eval time: webpack replaces the token via\n * `DefinePlugin` (available immediately), but Turbopack assigns `globalThis.__SENTRY_SERVER_MODULES__`\n * at runtime, *after* this module's imports are hoisted and evaluated. A `const` capture would be\n * empty under Turbopack. See getsentry/sentry-javascript#19147.\n */\nfunction getServerModules(): Record<string, string> {\n // webpack: the token is replaced with a literal at build time.\n if (typeof __SENTRY_SERVER_MODULES__ !== 'undefined') {\n return __SENTRY_SERVER_MODULES__;\n }\n // Turbopack: the value is assigned onto the global object at runtime.\n return (\n (GLOBAL_OBJ as typeof GLOBAL_OBJ & { __SENTRY_SERVER_MODULES__?: Record<string, string> })\n .__SENTRY_SERVER_MODULES__ ?? {}\n );\n}\n\nconst _modulesIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n processEvent(event) {\n event.modules = {\n ...event.modules,\n ..._getModules(),\n };\n\n return event;\n },\n getModules: _getModules,\n };\n}) satisfies IntegrationFn;\n\n/**\n * Add node modules / packages to the event.\n * For this, multiple sources are used:\n * - They can be injected at build time into the __SENTRY_SERVER_MODULES__ variable (e.g. in Next.js)\n * - They are extracted from the dependencies & devDependencies in the package.json file\n * - They are extracted from the require.cache (CJS only)\n */\nexport const modulesIntegration = _modulesIntegration;\n\nfunction getRequireCachePaths(): string[] {\n try {\n return require.cache ? Object.keys(require.cache as Record<string, unknown>) : [];\n } catch {\n return [];\n }\n}\n\n/** Extract information about package.json modules */\nfunction collectModules(): ModuleInfo {\n return {\n ...getServerModules(),\n ...getModulesFromPackageJson(),\n ...(isCjs() ? collectRequireModules() : {}),\n };\n}\n\n/** Extract information about package.json modules from require.cache */\nfunction collectRequireModules(): ModuleInfo {\n const mainPaths = require.main?.paths || [];\n const paths = getRequireCachePaths();\n\n // We start with the modules from package.json (if possible)\n // These may be overwritten by more specific versions from the require.cache\n const infos: ModuleInfo = {};\n const seen = new Set<string>();\n\n paths.forEach(path => {\n let dir = path;\n\n /** Traverse directories upward in the search of package.json file */\n const updir = (): void | (() => void) => {\n const orig = dir;\n dir = dirname(orig);\n\n if (!dir || orig === dir || seen.has(orig)) {\n return undefined;\n }\n if (mainPaths.indexOf(dir) < 0) {\n return updir();\n }\n\n const pkgfile = join(orig, 'package.json');\n seen.add(orig);\n\n if (!existsSync(pkgfile)) {\n return updir();\n }\n\n try {\n const info = JSON.parse(readFileSync(pkgfile, 'utf8')) as {\n name: string;\n version: string;\n };\n infos[info.name] = info.version;\n } catch {\n // no-empty\n }\n };\n\n updir();\n });\n\n return infos;\n}\n\n/** Fetches the list of modules and the versions loaded by the entry file for your node.js app. */\nfunction _getModules(): ModuleInfo {\n if (!moduleCache) {\n moduleCache = collectModules();\n }\n return moduleCache;\n}\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nfunction getPackageJson(): PackageJson {\n try {\n const filePath = join(process.cwd(), 'package.json');\n const packageJson = JSON.parse(readFileSync(filePath, 'utf8')) as PackageJson;\n\n return packageJson;\n } catch {\n return {};\n }\n}\n\nfunction getModulesFromPackageJson(): ModuleInfo {\n const packageJson = getPackageJson();\n\n return {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n}\n"],"names":[],"mappings":";;;;;AAOA,IAAI,WAAA;AAEJ,MAAM,gBAAA,GAAmB,SAAA;AAYzB,SAAS,gBAAA,GAA2C;AAElD,EAAA,IAAI,OAAO,8BAA8B,WAAA,EAAa;AACpD,IAAA,OAAO,yBAAA;AAAA,EACT;AAEA,EAAA,OACG,UAAA,CACE,6BAA6B,EAAC;AAErC;AAEA,MAAM,uBAAuB,MAAM;AACjC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,aAAa,KAAA,EAAO;AAClB,MAAA,KAAA,CAAM,OAAA,GAAU;AAAA,QACd,GAAG,KAAA,CAAM,OAAA;AAAA,QACT,GAAG,WAAA;AAAY,OACjB;AAEA,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,UAAA,EAAY;AAAA,GACd;AACF,CAAA,CAAA;AASO,MAAM,kBAAA,GAAqB;AAWlC,SAAS,cAAA,GAA6B;AACpC,EAAA,OAAO;AAAA,IACL,GAAG,gBAAA,EAAiB;AAAA,IACpB,GAAG,yBAAA,EAA0B;AAAA,IAC7B,GAAwC;AAAC,GAC3C;AACF;AAoDA,SAAS,WAAA,GAA0B;AACjC,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,WAAA,GAAc,cAAA,EAAe;AAAA,EAC/B;AACA,EAAA,OAAO,WAAA;AACT;AAOA,SAAS,cAAA,GAA8B;AACrC,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,cAAc,CAAA;AACnD,IAAA,MAAM,cAAc,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,QAAA,EAAU,MAAM,CAAC,CAAA;AAE7D,IAAA,OAAO,WAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAEA,SAAS,yBAAA,GAAwC;AAC/C,EAAA,MAAM,cAAc,cAAA,EAAe;AAEnC,EAAA,OAAO;AAAA,IACL,GAAG,WAAA,CAAY,YAAA;AAAA,IACf,GAAG,WAAA,CAAY;AAAA,GACjB;AACF;;;;"} | ||
| {"version":3,"file":"modules.js","sources":["../../../src/integrations/modules.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { GLOBAL_OBJ, type IntegrationFn } from '@sentry/core';\n\ntype ModuleInfo = Record<string, string>;\n\nlet moduleCache: ModuleInfo | undefined;\n\nconst INTEGRATION_NAME = 'Modules' as const;\n\ndeclare const __SENTRY_SERVER_MODULES__: Record<string, string>;\n\n/**\n * Reads the modules injected at build time into `__SENTRY_SERVER_MODULES__` (e.g. by the Next.js SDK).\n *\n * Must be read lazily (per call), not captured at module-eval time: webpack replaces the token via\n * `DefinePlugin` (available immediately), but Turbopack assigns `globalThis.__SENTRY_SERVER_MODULES__`\n * at runtime, *after* this module's imports are hoisted and evaluated. A `const` capture would be\n * empty under Turbopack. See getsentry/sentry-javascript#19147.\n */\nfunction getServerModules(): Record<string, string> {\n // webpack: the token is replaced with a literal at build time.\n if (typeof __SENTRY_SERVER_MODULES__ !== 'undefined') {\n return __SENTRY_SERVER_MODULES__;\n }\n // Turbopack: the value is assigned onto the global object at runtime.\n return (\n (GLOBAL_OBJ as typeof GLOBAL_OBJ & { __SENTRY_SERVER_MODULES__?: Record<string, string> })\n .__SENTRY_SERVER_MODULES__ ?? {}\n );\n}\n\nconst _modulesIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n processEvent(event) {\n event.modules = {\n ...event.modules,\n ..._getModules(),\n };\n\n return event;\n },\n getModules: _getModules,\n };\n}) satisfies IntegrationFn;\n\n/**\n * Add node modules / packages to the event.\n * For this, multiple sources are used:\n * - They can be injected at build time into the __SENTRY_SERVER_MODULES__ variable (e.g. in Next.js)\n * - They are extracted from the dependencies & devDependencies in the package.json file\n * - They are extracted from the require.cache (CJS only)\n */\nexport const modulesIntegration = _modulesIntegration;\n\nfunction getRequireCachePaths(): string[] {\n try {\n return require.cache ? Object.keys(require.cache as Record<string, unknown>) : [];\n } catch {\n return [];\n }\n}\n\n/** Extract information about package.json modules */\nfunction collectModules(): ModuleInfo {\n return {\n ...getServerModules(),\n ...getModulesFromPackageJson(),\n /*! rollup-include-cjs-only */\n ...collectRequireModules(),\n /*! rollup-include-cjs-only-end */\n };\n}\n\n/** Extract information about package.json modules from require.cache */\nfunction collectRequireModules(): ModuleInfo {\n const mainPaths = require.main?.paths || [];\n const paths = getRequireCachePaths();\n\n // We start with the modules from package.json (if possible)\n // These may be overwritten by more specific versions from the require.cache\n const infos: ModuleInfo = {};\n const seen = new Set<string>();\n\n paths.forEach(path => {\n let dir = path;\n\n /** Traverse directories upward in the search of package.json file */\n const updir = (): void | (() => void) => {\n const orig = dir;\n dir = dirname(orig);\n\n if (!dir || orig === dir || seen.has(orig)) {\n return undefined;\n }\n if (mainPaths.indexOf(dir) < 0) {\n return updir();\n }\n\n const pkgfile = join(orig, 'package.json');\n seen.add(orig);\n\n if (!existsSync(pkgfile)) {\n return updir();\n }\n\n try {\n const info = JSON.parse(readFileSync(pkgfile, 'utf8')) as {\n name: string;\n version: string;\n };\n infos[info.name] = info.version;\n } catch {\n // no-empty\n }\n };\n\n updir();\n });\n\n return infos;\n}\n\n/** Fetches the list of modules and the versions loaded by the entry file for your node.js app. */\nfunction _getModules(): ModuleInfo {\n if (!moduleCache) {\n moduleCache = collectModules();\n }\n return moduleCache;\n}\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nfunction getPackageJson(): PackageJson {\n try {\n const filePath = join(process.cwd(), 'package.json');\n const packageJson = JSON.parse(readFileSync(filePath, 'utf8')) as PackageJson;\n\n return packageJson;\n } catch {\n return {};\n }\n}\n\nfunction getModulesFromPackageJson(): ModuleInfo {\n const packageJson = getPackageJson();\n\n return {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n}\n"],"names":[],"mappings":";;;;AAMA,IAAI,WAAA;AAEJ,MAAM,gBAAA,GAAmB,SAAA;AAYzB,SAAS,gBAAA,GAA2C;AAElD,EAAA,IAAI,OAAO,8BAA8B,WAAA,EAAa;AACpD,IAAA,OAAO,yBAAA;AAAA,EACT;AAEA,EAAA,OACG,UAAA,CACE,6BAA6B,EAAC;AAErC;AAEA,MAAM,uBAAuB,MAAM;AACjC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,aAAa,KAAA,EAAO;AAClB,MAAA,KAAA,CAAM,OAAA,GAAU;AAAA,QACd,GAAG,KAAA,CAAM,OAAA;AAAA,QACT,GAAG,WAAA;AAAY,OACjB;AAEA,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,UAAA,EAAY;AAAA,GACd;AACF,CAAA,CAAA;AASO,MAAM,kBAAA,GAAqB;AAWlC,SAAS,cAAA,GAA6B;AACpC,EAAA,OAAO;AAAA,IACL,GAAG,gBAAA,EAAiB;AAAA,IACpB,GAAG,yBAAA,EAA0B;AAAA,KAAA;AAAA;AAkDvB,SACP,WAAA,GAAA;AAED,EAAA,IAAA,CAAA,WAAO,EAAA;AACT,IAAA,WAAA,GAAA,cAAA,EAAA;AAGA,EAAA;AACE,EAAA,OAAK,WAAa;AAChB;AAA6B,SAC/B,cAAA,GAAA;AACA,EAAA,IAAA;AACF,IAAA,MAAA,QAAA,GAAA,IAAA,CAAA,OAAA,CAAA,GAAA,EAAA,EAAA,cAAA,CAAA;AAOA,IAAA,MAAS,WAAA,GAAA,IAA8B,CAAA,KAAA,CAAA,YAAA,CAAA,QAAA,EAAA,MAAA,CAAA,CAAA;AACrC,IAAA,OAAI,WAAA;AACF,EAAA,CAAA,CAAA,MAAM;AACN,IAAA;AAEA,EAAA;AAAO;AAEP,SAAA,yBAAQ,GAAA;AAAA,EACV,MAAA,WAAA,GAAA,cAAA,EAAA;AACF,EAAA,OAAA;AAEA,IAAA,GAAA,WAAS,CAAA,YAAA;AACP,IAAA,GAAA;AAEA,GAAA;AAAO;;;;"} |
| import { defineIntegration } from '@sentry/core'; | ||
| import { generateInstrumentOnce } from '../../otel/instrument.js'; | ||
| import { SentryNodeFetchInstrumentation } from './SentryNodeFetchInstrumentation.js'; | ||
| import { instrumentUndici } from './undici-instrumentation.js'; | ||
| const INTEGRATION_NAME = "NodeFetch"; | ||
| const instrumentSentryNodeFetch = generateInstrumentOnce( | ||
| `${INTEGRATION_NAME}.sentry`, | ||
| SentryNodeFetchInstrumentation, | ||
| (options) => { | ||
| return options; | ||
| } | ||
| ); | ||
| const _nativeNodeFetchIntegration = ((options = {}) => { | ||
@@ -17,3 +8,3 @@ return { | ||
| setupOnce() { | ||
| instrumentSentryNodeFetch(options); | ||
| instrumentUndici(options); | ||
| } | ||
@@ -20,0 +11,0 @@ }; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sources":["../../../../src/integrations/node-fetch/index.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration } from '@sentry/core';\nimport { generateInstrumentOnce } from '../../otel/instrument';\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 * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing fetch requests.\n *\n * @default `true`\n */\n tracePropagation?: 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 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' as const,\n setupOnce() {\n instrumentSentryNodeFetch(options);\n },\n };\n}) satisfies IntegrationFn;\n\nexport const nativeNodeFetchIntegration = defineIntegration(_nativeNodeFetchIntegration);\n"],"names":[],"mappings":";;;;AAKA,MAAM,gBAAA,GAAmB,WAAA;AAuBzB,MAAM,yBAAA,GAA4B,sBAAA;AAAA,EAChC,GAAG,gBAAgB,CAAA,OAAA,CAAA;AAAA,EACnB,8BAAA;AAAA,EACA,CAAC,OAAA,KAA8B;AAC7B,IAAA,OAAO,OAAA;AAAA,EACT;AACF,CAAA;AAEA,MAAM,2BAAA,IAA+B,CAAC,OAAA,GAA4B,EAAC,KAAM;AACvE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,WAAA;AAAA,IACN,SAAA,GAAY;AACV,MAAA,yBAAA,CAA0B,OAAO,CAAA;AAAA,IACnC;AAAA,GACF;AACF,CAAA,CAAA;AAEO,MAAM,0BAAA,GAA6B,kBAAkB,2BAA2B;;;;"} | ||
| {"version":3,"file":"index.js","sources":["../../../../src/integrations/node-fetch/index.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration } from '@sentry/core';\nimport type { NodeFetchOptions } from './types';\nimport { instrumentUndici } from './undici-instrumentation';\n\nconst _nativeNodeFetchIntegration = ((options: NodeFetchOptions = {}) => {\n return {\n name: 'NodeFetch' as const,\n setupOnce() {\n instrumentUndici(options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Instrument outgoing fetch requests made through the native node `fetch` API.\n * This emits (depending on the integration options) spans and breadcrumbs, as well as injecting trace propagation headers into the request.\n */\nexport const nativeNodeFetchIntegration = defineIntegration(_nativeNodeFetchIntegration);\n"],"names":[],"mappings":";;;AAKA,MAAM,2BAAA,IAA+B,CAAC,OAAA,GAA4B,EAAC,KAAM;AACvE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,WAAA;AAAA,IACN,SAAA,GAAY;AACV,MAAA,gBAAA,CAAiB,OAAO,CAAA;AAAA,IAC1B;AAAA,GACF;AACF,CAAA,CAAA;AAMO,MAAM,0BAAA,GAA6B,kBAAkB,2BAA2B;;;;"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"SentryNodeFetchInstrumentation.js","sources":["../../../../src/integrations/node-fetch/SentryNodeFetchInstrumentation.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase } from '@opentelemetry/instrumentation';\nimport { LRUMap, SDK_VERSION, isTracingSuppressed } from '@sentry/core';\nimport * as diagch from 'diagnostics_channel';\nimport { NODE_MAJOR, NODE_MINOR } from '../../nodeVersion';\nimport {\n addFetchRequestBreadcrumb,\n addTracePropagationHeadersToFetchRequest,\n getAbsoluteUrl,\n} from '../../utils/outgoingFetchRequest';\nimport type { UndiciRequest, UndiciResponse } from './types';\n\nexport type SentryNodeFetchInstrumentationOptions = InstrumentationConfig & {\n /**\n * Whether breadcrumbs should be recorded for requests.\n *\n * @default `true`\n */\n breadcrumbs?: boolean;\n\n /**\n * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing fetch requests.\n *\n * When set to `false`, Sentry will not inject any trace propagation headers, but will still create breadcrumbs\n * (if `breadcrumbs` is enabled). This is useful when `skipOpenTelemetrySetup: true` is configured and you want\n * to avoid duplicate trace headers being injected by both Sentry and OpenTelemetry's UndiciInstrumentation.\n *\n * @default `true`\n */\n tracePropagation?: boolean;\n\n /**\n * Do not capture breadcrumbs or inject headers for outgoing fetch requests to URLs where the given callback returns `true`.\n * The same option can be passed to the top-level httpIntegration where it controls both, breadcrumb and\n * span creation.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n */\n ignoreOutgoingRequests?: (url: string) => boolean;\n};\n\ninterface ListenerRecord {\n name: string;\n unsubscribe: () => void;\n}\n\n/**\n * This custom node-fetch instrumentation is used to instrument outgoing fetch requests.\n * It does not emit any spans.\n *\n * The reason this is isolated from the OpenTelemetry instrumentation is that users may overwrite this,\n * which would lead to Sentry not working as expected.\n *\n * This is heavily inspired & adapted from:\n * https://github.com/open-telemetry/opentelemetry-js-contrib/blob/28e209a9da36bc4e1f8c2b0db7360170ed46cb80/plugins/node/instrumentation-undici/src/undici.ts\n */\nexport class SentryNodeFetchInstrumentation extends InstrumentationBase<SentryNodeFetchInstrumentationOptions> {\n // Keep ref to avoid https://github.com/nodejs/node/issues/42170 bug and for\n // unsubscribing.\n private _channelSubs: Array<ListenerRecord>;\n private _propagationDecisionMap: LRUMap<string, boolean>;\n private _ignoreOutgoingRequestsMap: WeakMap<UndiciRequest, boolean>;\n\n public constructor(config: SentryNodeFetchInstrumentationOptions = {}) {\n super('@sentry/instrumentation-node-fetch', SDK_VERSION, config);\n this._channelSubs = [];\n this._propagationDecisionMap = new LRUMap<string, boolean>(100);\n this._ignoreOutgoingRequestsMap = new WeakMap<UndiciRequest, boolean>();\n }\n\n /** No need to instrument files/modules. */\n public init(): void {\n return undefined;\n }\n\n /** Disable the instrumentation. */\n public disable(): void {\n super.disable();\n this._channelSubs.forEach(sub => sub.unsubscribe());\n this._channelSubs = [];\n }\n\n /** Enable the instrumentation. */\n public enable(): void {\n // \"enabled\" handling is currently a bit messy with InstrumentationBase.\n // If constructed with `{enabled: false}`, this `.enable()` is still called,\n // and `this.getConfig().enabled !== this.isEnabled()`, creating confusion.\n //\n // For now, this class will setup for instrumenting if `.enable()` is\n // called, but use `this.getConfig().enabled` to determine if\n // instrumentation should be generated. This covers the more likely common\n // case of config being given a construction time, rather than later via\n // `instance.enable()`, `.disable()`, or `.setConfig()` calls.\n super.enable();\n\n // This method is called by the super-class constructor before ours is\n // called. So we need to ensure the property is initalized.\n this._channelSubs = this._channelSubs || [];\n\n // Avoid to duplicate subscriptions\n if (this._channelSubs.length > 0) {\n return;\n }\n\n this._subscribeToChannel('undici:request:create', this._onRequestCreated.bind(this));\n this._subscribeToChannel('undici:request:headers', this._onResponseHeaders.bind(this));\n }\n\n /**\n * This method is called when a request is created.\n * You can still mutate the request here before it is sent.\n */\n private _onRequestCreated({ request }: { request: UndiciRequest }): void {\n const config = this.getConfig();\n const enabled = config.enabled !== false;\n\n if (!enabled) {\n return;\n }\n\n const shouldIgnore = this._shouldIgnoreOutgoingRequest(request);\n // We store this decisision for later so we do not need to re-evaluate it\n // Additionally, the active context is not correct in _onResponseHeaders, so we need to make sure it is evaluated here\n this._ignoreOutgoingRequestsMap.set(request, shouldIgnore);\n\n if (shouldIgnore) {\n return;\n }\n\n if (config.tracePropagation !== false) {\n addTracePropagationHeadersToFetchRequest(request, this._propagationDecisionMap);\n }\n }\n\n /**\n * This method is called when a response is received.\n */\n private _onResponseHeaders({ request, response }: { request: UndiciRequest; response: UndiciResponse }): void {\n const config = this.getConfig();\n const enabled = config.enabled !== false;\n\n if (!enabled) {\n return;\n }\n\n const _breadcrumbs = config.breadcrumbs;\n const breadCrumbsEnabled = typeof _breadcrumbs === 'undefined' ? true : _breadcrumbs;\n\n const shouldIgnore = this._ignoreOutgoingRequestsMap.get(request);\n\n if (breadCrumbsEnabled && !shouldIgnore) {\n addFetchRequestBreadcrumb(request, response);\n }\n }\n\n /** Subscribe to a diagnostics channel. */\n private _subscribeToChannel(\n diagnosticChannel: string,\n onMessage: (message: unknown, name: string | symbol) => void,\n ): void {\n // `diagnostics_channel` had a ref counting bug until v18.19.0.\n // https://github.com/nodejs/node/pull/47520\n const useNewSubscribe = NODE_MAJOR > 18 || (NODE_MAJOR === 18 && NODE_MINOR >= 19);\n\n let unsubscribe: () => void;\n if (useNewSubscribe) {\n diagch.subscribe?.(diagnosticChannel, onMessage);\n unsubscribe = () => diagch.unsubscribe?.(diagnosticChannel, onMessage);\n } else {\n const channel = diagch.channel(diagnosticChannel);\n channel.subscribe(onMessage);\n unsubscribe = () => channel.unsubscribe(onMessage);\n }\n\n this._channelSubs.push({\n name: diagnosticChannel,\n unsubscribe,\n });\n }\n\n /**\n * Check if the given outgoing request should be ignored.\n */\n private _shouldIgnoreOutgoingRequest(request: UndiciRequest): boolean {\n if (isTracingSuppressed()) {\n return true;\n }\n\n // Add trace propagation headers\n const url = getAbsoluteUrl(request.origin, request.path);\n const ignoreOutgoingRequests = this.getConfig().ignoreOutgoingRequests;\n\n if (typeof ignoreOutgoingRequests !== 'function' || !url) {\n return false;\n }\n\n return ignoreOutgoingRequests(url);\n }\n}\n"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"SentryNodeFetchInstrumentation.js","sources":["../../../../src/integrations/node-fetch/SentryNodeFetchInstrumentation.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase } from '@opentelemetry/instrumentation';\nimport { LRUMap, SDK_VERSION, isTracingSuppressed } from '@sentry/core';\nimport * as diagch from 'diagnostics_channel';\nimport { NODE_MAJOR, NODE_MINOR } from '../../nodeVersion';\nimport {\n addFetchRequestBreadcrumb,\n addTracePropagationHeadersToFetchRequest,\n getAbsoluteUrl,\n} from '../../utils/outgoingFetchRequest';\nimport type { UndiciRequest, UndiciResponse } from './types';\n\nexport type SentryNodeFetchInstrumentationOptions = InstrumentationConfig & {\n /**\n * Whether breadcrumbs should be recorded for requests.\n *\n * @default `true`\n */\n breadcrumbs?: boolean;\n\n /**\n * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing fetch requests.\n *\n * When set to `false`, Sentry will not inject any trace propagation headers, but will still create breadcrumbs\n * (if `breadcrumbs` is enabled). This is useful when `skipOpenTelemetrySetup: true` is configured and you want\n * to avoid duplicate trace headers being injected by both Sentry and OpenTelemetry's UndiciInstrumentation.\n *\n * @default `true`\n */\n tracePropagation?: boolean;\n\n /**\n * Do not capture breadcrumbs or inject headers for outgoing fetch requests to URLs where the given callback returns `true`.\n * The same option can be passed to the top-level httpIntegration where it controls both, breadcrumb and\n * span creation.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n */\n ignoreOutgoingRequests?: (url: string) => boolean;\n};\n\ninterface ListenerRecord {\n name: string;\n unsubscribe: () => void;\n}\n\n/**\n * This custom node-fetch instrumentation is used to instrument outgoing fetch requests.\n * It does not emit any spans.\n *\n * The reason this is isolated from the OpenTelemetry instrumentation is that users may overwrite this,\n * which would lead to Sentry not working as expected.\n *\n * This is heavily inspired & adapted from:\n * https://github.com/open-telemetry/opentelemetry-js-contrib/blob/28e209a9da36bc4e1f8c2b0db7360170ed46cb80/plugins/node/instrumentation-undici/src/undici.ts\n *\n * @deprecated This class is no longer used internally and will be removed in a future major version. Use `nativeNodeFetchIntegration` instead.\n */\nexport class SentryNodeFetchInstrumentation extends InstrumentationBase<SentryNodeFetchInstrumentationOptions> {\n // Keep ref to avoid https://github.com/nodejs/node/issues/42170 bug and for\n // unsubscribing.\n private _channelSubs: Array<ListenerRecord>;\n private _propagationDecisionMap: LRUMap<string, boolean>;\n private _ignoreOutgoingRequestsMap: WeakMap<UndiciRequest, boolean>;\n\n public constructor(config: SentryNodeFetchInstrumentationOptions = {}) {\n super('@sentry/instrumentation-node-fetch', SDK_VERSION, config);\n this._channelSubs = [];\n this._propagationDecisionMap = new LRUMap<string, boolean>(100);\n this._ignoreOutgoingRequestsMap = new WeakMap<UndiciRequest, boolean>();\n }\n\n /** No need to instrument files/modules. */\n public init(): void {\n return undefined;\n }\n\n /** Disable the instrumentation. */\n public disable(): void {\n super.disable();\n this._channelSubs.forEach(sub => sub.unsubscribe());\n this._channelSubs = [];\n }\n\n /** Enable the instrumentation. */\n public enable(): void {\n // \"enabled\" handling is currently a bit messy with InstrumentationBase.\n // If constructed with `{enabled: false}`, this `.enable()` is still called,\n // and `this.getConfig().enabled !== this.isEnabled()`, creating confusion.\n //\n // For now, this class will setup for instrumenting if `.enable()` is\n // called, but use `this.getConfig().enabled` to determine if\n // instrumentation should be generated. This covers the more likely common\n // case of config being given a construction time, rather than later via\n // `instance.enable()`, `.disable()`, or `.setConfig()` calls.\n super.enable();\n\n // This method is called by the super-class constructor before ours is\n // called. So we need to ensure the property is initalized.\n this._channelSubs = this._channelSubs || [];\n\n // Avoid to duplicate subscriptions\n if (this._channelSubs.length > 0) {\n return;\n }\n\n this._subscribeToChannel('undici:request:create', this._onRequestCreated.bind(this));\n this._subscribeToChannel('undici:request:headers', this._onResponseHeaders.bind(this));\n }\n\n /**\n * This method is called when a request is created.\n * You can still mutate the request here before it is sent.\n */\n private _onRequestCreated({ request }: { request: UndiciRequest }): void {\n const config = this.getConfig();\n const enabled = config.enabled !== false;\n\n if (!enabled) {\n return;\n }\n\n const shouldIgnore = this._shouldIgnoreOutgoingRequest(request);\n // We store this decisision for later so we do not need to re-evaluate it\n // Additionally, the active context is not correct in _onResponseHeaders, so we need to make sure it is evaluated here\n this._ignoreOutgoingRequestsMap.set(request, shouldIgnore);\n\n if (shouldIgnore) {\n return;\n }\n\n if (config.tracePropagation !== false) {\n addTracePropagationHeadersToFetchRequest(request, this._propagationDecisionMap);\n }\n }\n\n /**\n * This method is called when a response is received.\n */\n private _onResponseHeaders({ request, response }: { request: UndiciRequest; response: UndiciResponse }): void {\n const config = this.getConfig();\n const enabled = config.enabled !== false;\n\n if (!enabled) {\n return;\n }\n\n const _breadcrumbs = config.breadcrumbs;\n const breadCrumbsEnabled = typeof _breadcrumbs === 'undefined' ? true : _breadcrumbs;\n\n const shouldIgnore = this._ignoreOutgoingRequestsMap.get(request);\n\n if (breadCrumbsEnabled && !shouldIgnore) {\n addFetchRequestBreadcrumb(request, response);\n }\n }\n\n /** Subscribe to a diagnostics channel. */\n private _subscribeToChannel(\n diagnosticChannel: string,\n onMessage: (message: unknown, name: string | symbol) => void,\n ): void {\n // `diagnostics_channel` had a ref counting bug until v18.19.0.\n // https://github.com/nodejs/node/pull/47520\n const useNewSubscribe = NODE_MAJOR > 18 || (NODE_MAJOR === 18 && NODE_MINOR >= 19);\n\n let unsubscribe: () => void;\n if (useNewSubscribe) {\n diagch.subscribe?.(diagnosticChannel, onMessage);\n unsubscribe = () => diagch.unsubscribe?.(diagnosticChannel, onMessage);\n } else {\n const channel = diagch.channel(diagnosticChannel);\n channel.subscribe(onMessage);\n unsubscribe = () => channel.unsubscribe(onMessage);\n }\n\n this._channelSubs.push({\n name: diagnosticChannel,\n unsubscribe,\n });\n }\n\n /**\n * Check if the given outgoing request should be ignored.\n */\n private _shouldIgnoreOutgoingRequest(request: UndiciRequest): boolean {\n if (isTracingSuppressed()) {\n return true;\n }\n\n // Add trace propagation headers\n const url = getAbsoluteUrl(request.origin, request.path);\n const ignoreOutgoingRequests = this.getConfig().ignoreOutgoingRequests;\n\n if (typeof ignoreOutgoingRequests !== 'function' || !url) {\n return false;\n }\n\n return ignoreOutgoingRequests(url);\n }\n}\n"],"names":[],"mappings":"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"} |
@@ -25,3 +25,2 @@ export { LightNodeClient } from './client.js'; | ||
| export { initializeEsmLoader } from '../sdk/esmLoader.js'; | ||
| export { isCjs } from '../utils/detection.js'; | ||
| export { createMissingInstrumentationContext } from '../utils/createMissingInstrumentationContext.js'; | ||
@@ -28,0 +27,0 @@ export { makeNodeTransport } from '../transports/http.js'; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;"} | ||
| {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;"} |
@@ -16,3 +16,2 @@ import { eventFiltersIntegration, functionToStringIntegration, linkedErrorsIntegration, requestDataIntegration, debug, consoleSandbox, getCurrentScope, applySdkMetadata, envToBool, stackParserFromStackParserOptions, getIntegrationsToSetup, propagationContextFromHeaders } from '@sentry/core'; | ||
| import { makeNodeTransport } from '../transports/http.js'; | ||
| import '../nodeVersion.js'; | ||
| import { getSpotlightConfig } from '../utils/spotlight.js'; | ||
@@ -79,3 +78,3 @@ import { setAsyncLocalStorageAsyncContextStrategy } from './asyncLocalStorageStrategy.js'; | ||
| client.init(); | ||
| debug.log(`SDK initialized from ${"ESM"} (light mode)`); | ||
| debug.log(`SDK initialized from ESM (light mode)`); | ||
| client.startClientReportTracking(); | ||
@@ -82,0 +81,0 @@ updateScopeFromEnvVariables(); |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"sdk.js","sources":["../../../src/light/sdk.ts"],"sourcesContent":["import type { Integration, Options } from '@sentry/core';\nimport {\n applySdkMetadata,\n consoleSandbox,\n debug,\n envToBool,\n eventFiltersIntegration,\n functionToStringIntegration,\n getCurrentScope,\n getIntegrationsToSetup,\n linkedErrorsIntegration,\n propagationContextFromHeaders,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { childProcessIntegration } from '../integrations/childProcess';\nimport { nodeContextIntegration } from '../integrations/context';\nimport { contextLinesIntegration } from '../integrations/contextlines';\nimport { localVariablesIntegration } from '../integrations/local-variables';\nimport { modulesIntegration } from '../integrations/modules';\nimport { onUncaughtExceptionIntegration } from '../integrations/onuncaughtexception';\nimport { onUnhandledRejectionIntegration } from '../integrations/onunhandledrejection';\nimport { processSessionIntegration } from '../integrations/processSession';\nimport { INTEGRATION_NAME as SPOTLIGHT_INTEGRATION_NAME, spotlightIntegration } from '../integrations/spotlight';\nimport { consoleIntegration } from '../integrations/console';\nimport { systemErrorIntegration } from '../integrations/systemError';\nimport { defaultStackParser, getSentryRelease } from '../sdk/api';\nimport { makeNodeTransport } from '../transports';\nimport type { NodeClientOptions, NodeOptions } from '../types';\nimport { isCjs } from '../utils/detection';\nimport { getSpotlightConfig } from '../utils/spotlight';\nimport { setAsyncLocalStorageAsyncContextStrategy } from './asyncLocalStorageStrategy';\nimport { LightNodeClient } from './client';\nimport { httpIntegration } from './integrations/httpIntegration';\nimport { nativeNodeFetchIntegration } from './integrations/nativeNodeFetchIntegration';\n\n/**\n * Get default integrations for the Light Node-Core SDK.\n */\nexport function getDefaultIntegrations(): Integration[] {\n return [\n // Common\n eventFiltersIntegration(),\n functionToStringIntegration(),\n linkedErrorsIntegration(),\n requestDataIntegration(),\n systemErrorIntegration(),\n // Native Wrappers\n consoleIntegration(),\n httpIntegration(),\n nativeNodeFetchIntegration(),\n // Global Handlers\n onUncaughtExceptionIntegration(),\n onUnhandledRejectionIntegration(),\n // Event Info\n contextLinesIntegration(),\n localVariablesIntegration(),\n nodeContextIntegration(),\n childProcessIntegration(),\n processSessionIntegration(),\n modulesIntegration(),\n ];\n}\n\n/**\n * Initialize Sentry for Node in light mode (without OpenTelemetry).\n */\nexport function init(options: NodeOptions | undefined = {}): LightNodeClient | undefined {\n return _init(options, getDefaultIntegrations);\n}\n\n/**\n * Initialize Sentry for Node in light mode, without any integrations added by default.\n */\nexport function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): LightNodeClient {\n return _init(options, () => []);\n}\n\n/**\n * Initialize Sentry for Node in light mode.\n */\nfunction _init(\n _options: NodeOptions | undefined = {},\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): LightNodeClient {\n const options = getClientOptions(_options, getDefaultIntegrationsImpl);\n\n if (options.debug === true) {\n if (DEBUG_BUILD) {\n debug.enable();\n } else {\n // use `console.warn` rather than `debug.warn` since by non-debug bundles have all `debug.x` statements stripped\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.');\n });\n }\n }\n\n // Use AsyncLocalStorage-based context strategy instead of OpenTelemetry\n setAsyncLocalStorageAsyncContextStrategy();\n\n const scope = getCurrentScope();\n scope.update(options.initialScope);\n\n if (options.spotlight && !options.integrations.some(({ name }) => name === SPOTLIGHT_INTEGRATION_NAME)) {\n options.integrations.push(\n spotlightIntegration({\n sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined,\n }),\n );\n }\n\n applySdkMetadata(options, 'node-light', ['node-core']);\n\n const client = new LightNodeClient(options);\n // The client is on the current scope, from where it generally is inherited\n getCurrentScope().setClient(client);\n\n client.init();\n\n debug.log(`SDK initialized from ${isCjs() ? 'CommonJS' : 'ESM'} (light mode)`);\n\n client.startClientReportTracking();\n\n updateScopeFromEnvVariables();\n\n // Ensure we flush events when vercel functions are ended\n // See: https://vercel.com/docs/functions/functions-api-reference#sigterm-signal\n if (process.env.VERCEL) {\n process.on('SIGTERM', async () => {\n // We have 500ms for processing here, so we try to make sure to have enough time to send the events\n await client.flush(200);\n });\n }\n\n return client;\n}\n\nfunction getClientOptions(\n options: NodeOptions,\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClientOptions {\n const release = getRelease(options.release);\n const spotlight = getSpotlightConfig(options.spotlight);\n const tracesSampleRate = getTracesSampleRate(options.tracesSampleRate);\n\n const mergedOptions = {\n ...options,\n dsn: options.dsn ?? process.env.SENTRY_DSN,\n environment: options.environment ?? process.env.SENTRY_ENVIRONMENT,\n sendClientReports: options.sendClientReports ?? true,\n transport: options.transport ?? makeNodeTransport,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n release,\n tracesSampleRate,\n spotlight,\n debug: envToBool(options.debug ?? process.env.SENTRY_DEBUG),\n };\n\n const integrations = options.integrations;\n const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(mergedOptions);\n\n const resolvedIntegrations = getIntegrationsToSetup({\n defaultIntegrations,\n integrations,\n });\n\n return {\n ...mergedOptions,\n integrations: resolvedIntegrations,\n };\n}\n\nfunction getRelease(release: NodeOptions['release']): string | undefined {\n if (release !== undefined) {\n return release;\n }\n\n const detectedRelease = getSentryRelease();\n if (detectedRelease !== undefined) {\n return detectedRelease;\n }\n\n return undefined;\n}\n\nfunction getTracesSampleRate(tracesSampleRate: NodeOptions['tracesSampleRate']): number | undefined {\n if (tracesSampleRate !== undefined) {\n return tracesSampleRate;\n }\n\n const sampleRateFromEnv = process.env.SENTRY_TRACES_SAMPLE_RATE;\n if (!sampleRateFromEnv) {\n return undefined;\n }\n\n const parsed = parseFloat(sampleRateFromEnv);\n return isFinite(parsed) ? parsed : undefined;\n}\n\n/**\n * Update scope and propagation context based on environmental variables.\n *\n * See https://github.com/getsentry/rfcs/blob/main/text/0071-continue-trace-over-process-boundaries.md\n * for more details.\n */\nfunction updateScopeFromEnvVariables(): void {\n if (envToBool(process.env.SENTRY_USE_ENVIRONMENT) !== false) {\n const sentryTraceEnv = process.env.SENTRY_TRACE;\n const baggageEnv = process.env.SENTRY_BAGGAGE;\n const propagationContext = propagationContextFromHeaders(sentryTraceEnv, baggageEnv);\n getCurrentScope().setPropagationContext(propagationContext);\n }\n}\n"],"names":["SPOTLIGHT_INTEGRATION_NAME"],"mappings":"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"} | ||
| {"version":3,"file":"sdk.js","sources":["../../../src/light/sdk.ts"],"sourcesContent":["import type { Integration, Options } from '@sentry/core';\nimport {\n applySdkMetadata,\n consoleSandbox,\n debug,\n envToBool,\n eventFiltersIntegration,\n functionToStringIntegration,\n getCurrentScope,\n getIntegrationsToSetup,\n linkedErrorsIntegration,\n propagationContextFromHeaders,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { childProcessIntegration } from '../integrations/childProcess';\nimport { nodeContextIntegration } from '../integrations/context';\nimport { contextLinesIntegration } from '../integrations/contextlines';\nimport { localVariablesIntegration } from '../integrations/local-variables';\nimport { modulesIntegration } from '../integrations/modules';\nimport { onUncaughtExceptionIntegration } from '../integrations/onuncaughtexception';\nimport { onUnhandledRejectionIntegration } from '../integrations/onunhandledrejection';\nimport { processSessionIntegration } from '../integrations/processSession';\nimport { INTEGRATION_NAME as SPOTLIGHT_INTEGRATION_NAME, spotlightIntegration } from '../integrations/spotlight';\nimport { consoleIntegration } from '../integrations/console';\nimport { systemErrorIntegration } from '../integrations/systemError';\nimport { defaultStackParser, getSentryRelease } from '../sdk/api';\nimport { makeNodeTransport } from '../transports';\nimport type { NodeClientOptions, NodeOptions } from '../types';\nimport { getSpotlightConfig } from '../utils/spotlight';\nimport { setAsyncLocalStorageAsyncContextStrategy } from './asyncLocalStorageStrategy';\nimport { LightNodeClient } from './client';\nimport { httpIntegration } from './integrations/httpIntegration';\nimport { nativeNodeFetchIntegration } from './integrations/nativeNodeFetchIntegration';\n\n/**\n * Get default integrations for the Light Node-Core SDK.\n */\nexport function getDefaultIntegrations(): Integration[] {\n return [\n // Common\n eventFiltersIntegration(),\n functionToStringIntegration(),\n linkedErrorsIntegration(),\n requestDataIntegration(),\n systemErrorIntegration(),\n // Native Wrappers\n consoleIntegration(),\n httpIntegration(),\n nativeNodeFetchIntegration(),\n // Global Handlers\n onUncaughtExceptionIntegration(),\n onUnhandledRejectionIntegration(),\n // Event Info\n contextLinesIntegration(),\n localVariablesIntegration(),\n nodeContextIntegration(),\n childProcessIntegration(),\n processSessionIntegration(),\n modulesIntegration(),\n ];\n}\n\n/**\n * Initialize Sentry for Node in light mode (without OpenTelemetry).\n */\nexport function init(options: NodeOptions | undefined = {}): LightNodeClient | undefined {\n return _init(options, getDefaultIntegrations);\n}\n\n/**\n * Initialize Sentry for Node in light mode, without any integrations added by default.\n */\nexport function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): LightNodeClient {\n return _init(options, () => []);\n}\n\n/**\n * Initialize Sentry for Node in light mode.\n */\nfunction _init(\n _options: NodeOptions | undefined = {},\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): LightNodeClient {\n const options = getClientOptions(_options, getDefaultIntegrationsImpl);\n\n if (options.debug === true) {\n if (DEBUG_BUILD) {\n debug.enable();\n } else {\n // use `console.warn` rather than `debug.warn` since by non-debug bundles have all `debug.x` statements stripped\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.');\n });\n }\n }\n\n // Use AsyncLocalStorage-based context strategy instead of OpenTelemetry\n setAsyncLocalStorageAsyncContextStrategy();\n\n const scope = getCurrentScope();\n scope.update(options.initialScope);\n\n if (options.spotlight && !options.integrations.some(({ name }) => name === SPOTLIGHT_INTEGRATION_NAME)) {\n options.integrations.push(\n spotlightIntegration({\n sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined,\n }),\n );\n }\n\n applySdkMetadata(options, 'node-light', ['node-core']);\n\n const client = new LightNodeClient(options);\n // The client is on the current scope, from where it generally is inherited\n getCurrentScope().setClient(client);\n\n client.init();\n\n /*! rollup-include-cjs-only */\n debug.log(`SDK initialized from CommonJS (light mode)`);\n /*! rollup-include-cjs-only-end */\n /*! rollup-include-esm-only */\n debug.log(`SDK initialized from ESM (light mode)`);\n /*! rollup-include-esm-only-end */\n\n client.startClientReportTracking();\n\n updateScopeFromEnvVariables();\n\n // Ensure we flush events when vercel functions are ended\n // See: https://vercel.com/docs/functions/functions-api-reference#sigterm-signal\n if (process.env.VERCEL) {\n process.on('SIGTERM', async () => {\n // We have 500ms for processing here, so we try to make sure to have enough time to send the events\n await client.flush(200);\n });\n }\n\n return client;\n}\n\nfunction getClientOptions(\n options: NodeOptions,\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClientOptions {\n const release = getRelease(options.release);\n const spotlight = getSpotlightConfig(options.spotlight);\n const tracesSampleRate = getTracesSampleRate(options.tracesSampleRate);\n\n const mergedOptions = {\n ...options,\n dsn: options.dsn ?? process.env.SENTRY_DSN,\n environment: options.environment ?? process.env.SENTRY_ENVIRONMENT,\n sendClientReports: options.sendClientReports ?? true,\n transport: options.transport ?? makeNodeTransport,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n release,\n tracesSampleRate,\n spotlight,\n debug: envToBool(options.debug ?? process.env.SENTRY_DEBUG),\n };\n\n const integrations = options.integrations;\n const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(mergedOptions);\n\n const resolvedIntegrations = getIntegrationsToSetup({\n defaultIntegrations,\n integrations,\n });\n\n return {\n ...mergedOptions,\n integrations: resolvedIntegrations,\n };\n}\n\nfunction getRelease(release: NodeOptions['release']): string | undefined {\n if (release !== undefined) {\n return release;\n }\n\n const detectedRelease = getSentryRelease();\n if (detectedRelease !== undefined) {\n return detectedRelease;\n }\n\n return undefined;\n}\n\nfunction getTracesSampleRate(tracesSampleRate: NodeOptions['tracesSampleRate']): number | undefined {\n if (tracesSampleRate !== undefined) {\n return tracesSampleRate;\n }\n\n const sampleRateFromEnv = process.env.SENTRY_TRACES_SAMPLE_RATE;\n if (!sampleRateFromEnv) {\n return undefined;\n }\n\n const parsed = parseFloat(sampleRateFromEnv);\n return isFinite(parsed) ? parsed : undefined;\n}\n\n/**\n * Update scope and propagation context based on environmental variables.\n *\n * See https://github.com/getsentry/rfcs/blob/main/text/0071-continue-trace-over-process-boundaries.md\n * for more details.\n */\nfunction updateScopeFromEnvVariables(): void {\n if (envToBool(process.env.SENTRY_USE_ENVIRONMENT) !== false) {\n const sentryTraceEnv = process.env.SENTRY_TRACE;\n const baggageEnv = process.env.SENTRY_BAGGAGE;\n const propagationContext = propagationContextFromHeaders(sentryTraceEnv, baggageEnv);\n getCurrentScope().setPropagationContext(propagationContext);\n }\n}\n"],"names":["SPOTLIGHT_INTEGRATION_NAME"],"mappings":"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"} |
@@ -1,1 +0,1 @@ | ||
| {"type":"module","version":"10.63.0","sideEffects":false} | ||
| {"type":"module","version":"10.64.0","sideEffects":false} |
| import * as os from 'node:os'; | ||
| import { trace } from '@opentelemetry/api'; | ||
| import { registerInstrumentations } from '@opentelemetry/instrumentation'; | ||
| import { ServerRuntimeClient, applySdkMetadata, debug, _INTERNAL_flushLogsBuffer, SDK_VERSION, _INTERNAL_clearAiProviderSkips } from '@sentry/core'; | ||
| import { ServerRuntimeClient, applySdkMetadata, debug, _INTERNAL_flushLogsBuffer, _INTERNAL_setDeferSegmentSpanCapture, SDK_VERSION, _INTERNAL_clearAiProviderSkips } from '@sentry/core'; | ||
| import { getTraceContextForScope } from '@sentry/opentelemetry'; | ||
@@ -42,2 +42,3 @@ import { threadId, isMainThread } from 'worker_threads'; | ||
| } | ||
| _INTERNAL_setDeferSegmentSpanCapture(this); | ||
| } | ||
@@ -44,0 +45,0 @@ /** Get the OTEL tracer. */ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"client.js","sources":["../../../src/sdk/client.ts"],"sourcesContent":["import * as os from 'node:os';\nimport type { Tracer } from '@opentelemetry/api';\nimport { trace } from '@opentelemetry/api';\nimport { registerInstrumentations } from '@opentelemetry/instrumentation';\nimport type { BasicTracerProvider } from '@opentelemetry/sdk-trace-base';\nimport type { DynamicSamplingContext, Scope, ServerRuntimeClientOptions, TraceContext } from '@sentry/core';\nimport {\n _INTERNAL_clearAiProviderSkips,\n _INTERNAL_flushLogsBuffer,\n applySdkMetadata,\n debug,\n SDK_VERSION,\n ServerRuntimeClient,\n} from '@sentry/core';\nimport { type AsyncLocalStorageLookup, getTraceContextForScope } from '@sentry/opentelemetry';\nimport { isMainThread, threadId } from 'worker_threads';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { NodeClientOptions } from '../types';\n\nconst DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS = 60_000; // 60s was chosen arbitrarily\n\n/** A client for using Sentry with Node & OpenTelemetry. */\nexport class NodeClient extends ServerRuntimeClient<NodeClientOptions> {\n public traceProvider: BasicTracerProvider | undefined;\n public asyncLocalStorageLookup: AsyncLocalStorageLookup | undefined;\n\n private _tracer: Tracer | undefined;\n private _clientReportInterval: NodeJS.Timeout | undefined;\n private _clientReportOnExitFlushListener: (() => void) | undefined;\n private _logOnExitFlushListener: (() => void) | undefined;\n\n public constructor(options: NodeClientOptions) {\n const serverName =\n options.includeServerName === false\n ? undefined\n : options.serverName || global.process.env.SENTRY_NAME || os.hostname();\n\n const clientOptions: ServerRuntimeClientOptions = {\n ...options,\n platform: 'node',\n // Use provided runtime or default to 'node' with current process version\n runtime: options.runtime || { name: 'node', version: global.process.version },\n serverName,\n };\n\n if (options.openTelemetryInstrumentations) {\n registerInstrumentations({\n instrumentations: options.openTelemetryInstrumentations,\n });\n }\n\n applySdkMetadata(clientOptions, 'node');\n\n debug.log(`Initializing Sentry: process: ${process.pid}, thread: ${isMainThread ? 'main' : `worker-${threadId}`}.`);\n\n super(clientOptions);\n\n if (this.getOptions().enableLogs) {\n this._logOnExitFlushListener = () => {\n _INTERNAL_flushLogsBuffer(this);\n };\n\n if (serverName) {\n this.on('beforeCaptureLog', log => {\n log.attributes = {\n ...log.attributes,\n 'server.address': serverName,\n };\n });\n }\n\n process.on('beforeExit', this._logOnExitFlushListener);\n }\n }\n\n /** Get the OTEL tracer. */\n public get tracer(): Tracer {\n if (this._tracer) {\n return this._tracer;\n }\n\n const name = '@sentry/node';\n const version = SDK_VERSION;\n const tracer = trace.getTracer(name, version);\n this._tracer = tracer;\n\n return tracer;\n }\n\n /** @inheritDoc */\n // @ts-expect-error - PromiseLike is a subset of Promise\n public async flush(timeout?: number): PromiseLike<boolean> {\n await this.traceProvider?.forceFlush();\n\n if (this.getOptions().sendClientReports) {\n this._flushOutcomes();\n }\n\n return super.flush(timeout);\n }\n\n /** @inheritDoc */\n // @ts-expect-error - PromiseLike is a subset of Promise\n public async close(timeout?: number | undefined): PromiseLike<boolean> {\n if (this._clientReportInterval) {\n clearInterval(this._clientReportInterval);\n }\n\n if (this._clientReportOnExitFlushListener) {\n process.off('beforeExit', this._clientReportOnExitFlushListener);\n }\n\n if (this._logOnExitFlushListener) {\n process.off('beforeExit', this._logOnExitFlushListener);\n }\n\n const allEventsSent = await super.close(timeout);\n if (this.traceProvider) {\n await this.traceProvider.shutdown();\n }\n\n return allEventsSent;\n }\n\n /**\n * Will start tracking client reports for this client.\n *\n * NOTICE: This method will create an interval that is periodically called and attach a `process.on('beforeExit')`\n * hook. To clean up these resources, call `.close()` when you no longer intend to use the client. Not doing so will\n * result in a memory leak.\n */\n // The reason client reports need to be manually activated with this method instead of just enabling them in a\n // constructor, is that if users periodically and unboundedly create new clients, we will create more and more\n // intervals and beforeExit listeners, thus leaking memory. In these situations, users are required to call\n // `client.close()` in order to dispose of the acquired resources.\n // We assume that calling this method in Sentry.init() is a sensible default, because calling Sentry.init() over and\n // over again would also result in memory leaks.\n // Note: We have experimented with using `FinalizationRegisty` to clear the interval when the client is garbage\n // collected, but it did not work, because the cleanup function never got called.\n public startClientReportTracking(): void {\n const clientOptions = this.getOptions();\n if (clientOptions.sendClientReports) {\n this._clientReportOnExitFlushListener = () => {\n this._flushOutcomes();\n };\n\n this._clientReportInterval = setInterval(() => {\n DEBUG_BUILD && debug.log('Flushing client reports based on interval.');\n this._flushOutcomes();\n }, clientOptions.clientReportFlushInterval ?? DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS)\n // Unref is critical for not preventing the process from exiting because the interval is active.\n .unref();\n\n process.on('beforeExit', this._clientReportOnExitFlushListener);\n }\n }\n\n /** @inheritDoc */\n protected _setupIntegrations(): void {\n // Clear AI provider skip registrations before setting up integrations\n // This ensures a clean state between different client initializations\n // (e.g., when LangChain skips OpenAI in one client, but a subsequent client uses OpenAI standalone)\n _INTERNAL_clearAiProviderSkips();\n super._setupIntegrations();\n }\n\n /** Custom implementation for OTEL, so we can handle scope-span linking. */\n protected _getTraceInfoFromScope(\n scope: Scope | undefined,\n ): [dynamicSamplingContext: Partial<DynamicSamplingContext> | undefined, traceContext: TraceContext | undefined] {\n if (!scope) {\n return [undefined, undefined];\n }\n\n return getTraceContextForScope(this, scope);\n }\n}\n"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"client.js","sources":["../../../src/sdk/client.ts"],"sourcesContent":["import * as os from 'node:os';\nimport type { Tracer } from '@opentelemetry/api';\nimport { trace } from '@opentelemetry/api';\nimport { registerInstrumentations } from '@opentelemetry/instrumentation';\nimport type { DynamicSamplingContext, Scope, ServerRuntimeClientOptions, TraceContext } from '@sentry/core';\nimport {\n _INTERNAL_clearAiProviderSkips,\n _INTERNAL_flushLogsBuffer,\n _INTERNAL_setDeferSegmentSpanCapture,\n applySdkMetadata,\n debug,\n SDK_VERSION,\n ServerRuntimeClient,\n} from '@sentry/core';\nimport {\n type AsyncLocalStorageLookup,\n getTraceContextForScope,\n type OpenTelemetryTracerProvider,\n} from '@sentry/opentelemetry';\nimport { isMainThread, threadId } from 'worker_threads';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { NodeClientOptions } from '../types';\n\nconst DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS = 60_000; // 60s was chosen arbitrarily\n\n/** A client for using Sentry with Node & OpenTelemetry. */\nexport class NodeClient extends ServerRuntimeClient<NodeClientOptions> {\n public traceProvider: OpenTelemetryTracerProvider | undefined;\n public asyncLocalStorageLookup: AsyncLocalStorageLookup | undefined;\n\n private _tracer: Tracer | undefined;\n private _clientReportInterval: NodeJS.Timeout | undefined;\n private _clientReportOnExitFlushListener: (() => void) | undefined;\n private _logOnExitFlushListener: (() => void) | undefined;\n\n public constructor(options: NodeClientOptions) {\n const serverName =\n options.includeServerName === false\n ? undefined\n : options.serverName || global.process.env.SENTRY_NAME || os.hostname();\n\n const clientOptions: ServerRuntimeClientOptions = {\n ...options,\n platform: 'node',\n // Use provided runtime or default to 'node' with current process version\n runtime: options.runtime || { name: 'node', version: global.process.version },\n serverName,\n };\n\n if (options.openTelemetryInstrumentations) {\n registerInstrumentations({\n instrumentations: options.openTelemetryInstrumentations,\n });\n }\n\n applySdkMetadata(clientOptions, 'node');\n\n debug.log(`Initializing Sentry: process: ${process.pid}, thread: ${isMainThread ? 'main' : `worker-${threadId}`}.`);\n\n super(clientOptions);\n\n if (this.getOptions().enableLogs) {\n this._logOnExitFlushListener = () => {\n _INTERNAL_flushLogsBuffer(this);\n };\n\n if (serverName) {\n this.on('beforeCaptureLog', log => {\n log.attributes = {\n ...log.attributes,\n 'server.address': serverName,\n };\n });\n }\n\n process.on('beforeExit', this._logOnExitFlushListener);\n }\n\n // Enable deferred segment-span transaction capture here, in the constructor, rather than in\n // `initOtel`. Every client runs its constructor exactly once, whereas `initOtel` only runs on\n // `Sentry.init()` and only fully wires up the first client (a second `init` loses the\n // `setGlobalTracerProvider` race and bails early, and a manually constructed `NodeClient` never\n // runs `initOtel` at all). Anchoring on the constructor means every client — first, second, or\n // manual — defers correctly. It's unconditional and cheap: clients on the OpenTelemetry SDK\n // provider path produce OTel spans that never reach `SentrySpan`, so the strategy is simply never\n // consulted for them.\n _INTERNAL_setDeferSegmentSpanCapture(this);\n }\n\n /** Get the OTEL tracer. */\n public get tracer(): Tracer {\n if (this._tracer) {\n return this._tracer;\n }\n\n const name = '@sentry/node';\n const version = SDK_VERSION;\n const tracer = trace.getTracer(name, version);\n this._tracer = tracer;\n\n return tracer;\n }\n\n /** @inheritDoc */\n // @ts-expect-error - PromiseLike is a subset of Promise\n public async flush(timeout?: number): PromiseLike<boolean> {\n await this.traceProvider?.forceFlush();\n\n if (this.getOptions().sendClientReports) {\n this._flushOutcomes();\n }\n\n return super.flush(timeout);\n }\n\n /** @inheritDoc */\n // @ts-expect-error - PromiseLike is a subset of Promise\n public async close(timeout?: number | undefined): PromiseLike<boolean> {\n if (this._clientReportInterval) {\n clearInterval(this._clientReportInterval);\n }\n\n if (this._clientReportOnExitFlushListener) {\n process.off('beforeExit', this._clientReportOnExitFlushListener);\n }\n\n if (this._logOnExitFlushListener) {\n process.off('beforeExit', this._logOnExitFlushListener);\n }\n\n const allEventsSent = await super.close(timeout);\n if (this.traceProvider) {\n await this.traceProvider.shutdown();\n }\n\n return allEventsSent;\n }\n\n /**\n * Will start tracking client reports for this client.\n *\n * NOTICE: This method will create an interval that is periodically called and attach a `process.on('beforeExit')`\n * hook. To clean up these resources, call `.close()` when you no longer intend to use the client. Not doing so will\n * result in a memory leak.\n */\n // The reason client reports need to be manually activated with this method instead of just enabling them in a\n // constructor, is that if users periodically and unboundedly create new clients, we will create more and more\n // intervals and beforeExit listeners, thus leaking memory. In these situations, users are required to call\n // `client.close()` in order to dispose of the acquired resources.\n // We assume that calling this method in Sentry.init() is a sensible default, because calling Sentry.init() over and\n // over again would also result in memory leaks.\n // Note: We have experimented with using `FinalizationRegisty` to clear the interval when the client is garbage\n // collected, but it did not work, because the cleanup function never got called.\n public startClientReportTracking(): void {\n const clientOptions = this.getOptions();\n if (clientOptions.sendClientReports) {\n this._clientReportOnExitFlushListener = () => {\n this._flushOutcomes();\n };\n\n this._clientReportInterval = setInterval(() => {\n DEBUG_BUILD && debug.log('Flushing client reports based on interval.');\n this._flushOutcomes();\n }, clientOptions.clientReportFlushInterval ?? DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS)\n // Unref is critical for not preventing the process from exiting because the interval is active.\n .unref();\n\n process.on('beforeExit', this._clientReportOnExitFlushListener);\n }\n }\n\n /** @inheritDoc */\n protected _setupIntegrations(): void {\n // Clear AI provider skip registrations before setting up integrations\n // This ensures a clean state between different client initializations\n // (e.g., when LangChain skips OpenAI in one client, but a subsequent client uses OpenAI standalone)\n _INTERNAL_clearAiProviderSkips();\n super._setupIntegrations();\n }\n\n /** Custom implementation for OTEL, so we can handle scope-span linking. */\n protected _getTraceInfoFromScope(\n scope: Scope | undefined,\n ): [dynamicSamplingContext: Partial<DynamicSamplingContext> | undefined, traceContext: TraceContext | undefined] {\n if (!scope) {\n return [undefined, undefined];\n }\n\n return getTraceContextForScope(this, scope);\n }\n}\n"],"names":[],"mappings":"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"} |
@@ -18,3 +18,2 @@ import { debug, consoleSandbox, getCurrentScope, applySdkMetadata, envToBool, stackParserFromStackParserOptions, getIntegrationsToSetup, propagationContextFromHeaders, inboundFiltersIntegration, functionToStringIntegration, linkedErrorsIntegration, requestDataIntegration, conversationIdIntegration, hasSpansEnabled } from '@sentry/core'; | ||
| import { makeNodeTransport } from '../transports/http.js'; | ||
| import '../nodeVersion.js'; | ||
| import { getSpotlightConfig } from '../utils/spotlight.js'; | ||
@@ -86,3 +85,3 @@ import { defaultStackParser, getSentryRelease } from './api.js'; | ||
| client.init(); | ||
| debug.log(`SDK initialized from ${"ESM"}`); | ||
| debug.log(`SDK initialized from ESM`); | ||
| client.startClientReportTracking(); | ||
@@ -105,3 +104,4 @@ updateScopeFromEnvVariables(); | ||
| const required = ["SentryContextManager", "SentryPropagator"]; | ||
| if (hasSpansEnabled()) { | ||
| const hasSentryTracerProvider = setup.includes("SentryTracerProvider"); | ||
| if (hasSpansEnabled() && !hasSentryTracerProvider) { | ||
| required.push("SentrySpanProcessor"); | ||
@@ -116,3 +116,3 @@ } | ||
| } | ||
| if (!setup.includes("SentrySampler")) { | ||
| if (!hasSentryTracerProvider && !setup.includes("SentrySampler")) { | ||
| debug.warn( | ||
@@ -119,0 +119,0 @@ "You have to set up the SentrySampler. Without this, the OpenTelemetry & Sentry integration may still work, but sample rates set for the Sentry SDK will not be respected. If you use a custom sampler, make sure to use `wrapSamplingDecision`." |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sources":["../../../src/sdk/index.ts"],"sourcesContent":["import type { Integration, Options } from '@sentry/core';\nimport {\n applySdkMetadata,\n consoleSandbox,\n conversationIdIntegration,\n debug,\n envToBool,\n functionToStringIntegration,\n getCurrentScope,\n getIntegrationsToSetup,\n hasSpansEnabled,\n inboundFiltersIntegration,\n linkedErrorsIntegration,\n propagationContextFromHeaders,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport {\n enhanceDscWithOpenTelemetryRootSpanName,\n openTelemetrySetupCheck,\n setOpenTelemetryContextAsyncContextStrategy,\n setupEventContextTrace,\n} from '@sentry/opentelemetry';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { childProcessIntegration } from '../integrations/childProcess';\nimport { nodeContextIntegration } from '../integrations/context';\nimport { contextLinesIntegration } from '../integrations/contextlines';\nimport { httpIntegration } from '../integrations/http';\nimport { localVariablesIntegration } from '../integrations/local-variables';\nimport { modulesIntegration } from '../integrations/modules';\nimport { nativeNodeFetchIntegration } from '../integrations/node-fetch';\nimport { onUncaughtExceptionIntegration } from '../integrations/onuncaughtexception';\nimport { onUnhandledRejectionIntegration } from '../integrations/onunhandledrejection';\nimport { processSessionIntegration } from '../integrations/processSession';\nimport { INTEGRATION_NAME as SPOTLIGHT_INTEGRATION_NAME, spotlightIntegration } from '../integrations/spotlight';\nimport { consoleIntegration } from '../integrations/console';\nimport { systemErrorIntegration } from '../integrations/systemError';\nimport { makeNodeTransport } from '../transports';\nimport type { NodeClientOptions, NodeOptions } from '../types';\nimport { isCjs } from '../utils/detection';\nimport { getSpotlightConfig } from '../utils/spotlight';\nimport { defaultStackParser, getSentryRelease } from './api';\nimport { NodeClient } from './client';\nimport { initializeEsmLoader } from './esmLoader';\n\n/**\n * Get default integrations for the Node-Core SDK.\n */\nexport function getDefaultIntegrations(): Integration[] {\n return [\n // Common\n // TODO(v11): Replace with `eventFiltersIntegration` once we remove the deprecated `inboundFiltersIntegration`\n // eslint-disable-next-line typescript/no-deprecated\n inboundFiltersIntegration(),\n functionToStringIntegration(),\n linkedErrorsIntegration(),\n requestDataIntegration(),\n systemErrorIntegration(),\n conversationIdIntegration(),\n // Native Wrappers\n consoleIntegration(),\n httpIntegration(),\n nativeNodeFetchIntegration(),\n // Global Handlers\n onUncaughtExceptionIntegration(),\n onUnhandledRejectionIntegration(),\n // Event Info\n contextLinesIntegration(),\n localVariablesIntegration(),\n nodeContextIntegration(),\n childProcessIntegration(),\n processSessionIntegration(),\n modulesIntegration(),\n ];\n}\n\n/**\n * Initialize Sentry for Node.\n */\nexport function init(options: NodeOptions | undefined = {}): NodeClient | undefined {\n return _init(options, getDefaultIntegrations);\n}\n\n/**\n * Initialize Sentry for Node, without any integrations added by default.\n */\nexport function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): NodeClient {\n return _init(options, () => []);\n}\n\n/**\n * Initialize Sentry for Node, without performance instrumentation.\n */\nfunction _init(\n _options: NodeOptions | undefined = {},\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClient {\n const options = getClientOptions(_options, getDefaultIntegrationsImpl);\n\n if (options.debug === true) {\n if (DEBUG_BUILD) {\n debug.enable();\n } else {\n // use `console.warn` rather than `debug.warn` since by non-debug bundles have all `debug.x` statements stripped\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.');\n });\n }\n }\n\n if (options.registerEsmLoaderHooks !== false) {\n initializeEsmLoader();\n }\n\n setOpenTelemetryContextAsyncContextStrategy(options);\n\n const scope = getCurrentScope();\n scope.update(options.initialScope);\n\n if (options.spotlight && !options.integrations.some(({ name }) => name === SPOTLIGHT_INTEGRATION_NAME)) {\n options.integrations.push(\n spotlightIntegration({\n sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined,\n }),\n );\n }\n\n applySdkMetadata(options, 'node-core');\n\n const client = new NodeClient(options);\n // The client is on the current scope, from where it generally is inherited\n getCurrentScope().setClient(client);\n\n client.init();\n\n debug.log(`SDK initialized from ${isCjs() ? 'CommonJS' : 'ESM'}`);\n\n client.startClientReportTracking();\n\n updateScopeFromEnvVariables();\n\n enhanceDscWithOpenTelemetryRootSpanName(client);\n setupEventContextTrace(client);\n\n // Ensure we flush events when vercel functions are ended\n // See: https://vercel.com/docs/functions/functions-api-reference#sigterm-signal\n if (process.env.VERCEL) {\n process.on('SIGTERM', async () => {\n // We have 500ms for processing here, so we try to make sure to have enough time to send the events\n await client.flush(200);\n });\n }\n\n return client;\n}\n\n/**\n * Validate that your OpenTelemetry setup is correct.\n */\nexport function validateOpenTelemetrySetup(): void {\n if (!DEBUG_BUILD) {\n return;\n }\n\n const setup = openTelemetrySetupCheck();\n\n const required: ReturnType<typeof openTelemetrySetupCheck> = ['SentryContextManager', 'SentryPropagator'];\n\n if (hasSpansEnabled()) {\n required.push('SentrySpanProcessor');\n }\n\n for (const k of required) {\n if (!setup.includes(k)) {\n debug.error(\n `You have to set up the ${k}. Without this, the OpenTelemetry & Sentry integration will not work properly.`,\n );\n }\n }\n\n if (!setup.includes('SentrySampler')) {\n debug.warn(\n 'You have to set up the SentrySampler. Without this, the OpenTelemetry & Sentry integration may still work, but sample rates set for the Sentry SDK will not be respected. If you use a custom sampler, make sure to use `wrapSamplingDecision`.',\n );\n }\n}\n\nfunction getClientOptions(\n options: NodeOptions,\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClientOptions {\n const release = getRelease(options.release);\n\n const spotlight = getSpotlightConfig(options.spotlight);\n\n const tracesSampleRate = getTracesSampleRate(options.tracesSampleRate);\n\n const mergedOptions = {\n ...options,\n dsn: options.dsn ?? process.env.SENTRY_DSN,\n environment: options.environment ?? process.env.SENTRY_ENVIRONMENT,\n sendClientReports: options.sendClientReports ?? true,\n transport: options.transport ?? makeNodeTransport,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n release,\n tracesSampleRate,\n spotlight,\n debug: envToBool(options.debug ?? process.env.SENTRY_DEBUG),\n };\n\n const integrations = options.integrations;\n const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(mergedOptions);\n\n const resolvedIntegrations = getIntegrationsToSetup({\n defaultIntegrations,\n integrations,\n });\n\n return {\n ...mergedOptions,\n integrations: resolvedIntegrations,\n };\n}\n\nfunction getRelease(release: NodeOptions['release']): string | undefined {\n if (release !== undefined) {\n return release;\n }\n\n const detectedRelease = getSentryRelease();\n if (detectedRelease !== undefined) {\n return detectedRelease;\n }\n\n return undefined;\n}\n\nfunction getTracesSampleRate(tracesSampleRate: NodeOptions['tracesSampleRate']): number | undefined {\n if (tracesSampleRate !== undefined) {\n return tracesSampleRate;\n }\n\n const sampleRateFromEnv = process.env.SENTRY_TRACES_SAMPLE_RATE;\n if (!sampleRateFromEnv) {\n return undefined;\n }\n\n const parsed = parseFloat(sampleRateFromEnv);\n return isFinite(parsed) ? parsed : undefined;\n}\n\n/**\n * Update scope and propagation context based on environmental variables.\n *\n * See https://github.com/getsentry/rfcs/blob/main/text/0071-continue-trace-over-process-boundaries.md\n * for more details.\n */\nfunction updateScopeFromEnvVariables(): void {\n if (envToBool(process.env.SENTRY_USE_ENVIRONMENT) !== false) {\n const sentryTraceEnv = process.env.SENTRY_TRACE;\n const baggageEnv = process.env.SENTRY_BAGGAGE;\n const propagationContext = propagationContextFromHeaders(sentryTraceEnv, baggageEnv);\n getCurrentScope().setPropagationContext(propagationContext);\n }\n}\n"],"names":["SPOTLIGHT_INTEGRATION_NAME"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAgDO,SAAS,sBAAA,GAAwC;AACtD,EAAA,OAAO;AAAA;AAAA;AAAA;AAAA,IAIL,yBAAA,EAA0B;AAAA,IAC1B,2BAAA,EAA4B;AAAA,IAC5B,uBAAA,EAAwB;AAAA,IACxB,sBAAA,EAAuB;AAAA,IACvB,sBAAA,EAAuB;AAAA,IACvB,yBAAA,EAA0B;AAAA;AAAA,IAE1B,kBAAA,EAAmB;AAAA,IACnB,eAAA,EAAgB;AAAA,IAChB,0BAAA,EAA2B;AAAA;AAAA,IAE3B,8BAAA,EAA+B;AAAA,IAC/B,+BAAA,EAAgC;AAAA;AAAA,IAEhC,uBAAA,EAAwB;AAAA,IACxB,yBAAA,EAA0B;AAAA,IAC1B,sBAAA,EAAuB;AAAA,IACvB,uBAAA,EAAwB;AAAA,IACxB,yBAAA,EAA0B;AAAA,IAC1B,kBAAA;AAAmB,GACrB;AACF;AAKO,SAAS,IAAA,CAAK,OAAA,GAAmC,EAAC,EAA2B;AAClF,EAAA,OAAO,KAAA,CAAM,SAAS,sBAAsB,CAAA;AAC9C;AAKO,SAAS,8BAAA,CAA+B,OAAA,GAAmC,EAAC,EAAe;AAChG,EAAA,OAAO,KAAA,CAAM,OAAA,EAAS,MAAM,EAAE,CAAA;AAChC;AAKA,SAAS,KAAA,CACP,QAAA,GAAoC,EAAC,EACrC,0BAAA,EACY;AACZ,EAAA,MAAM,OAAA,GAAU,gBAAA,CAAiB,QAAA,EAAU,0BAA0B,CAAA;AAErE,EAAA,IAAI,OAAA,CAAQ,UAAU,IAAA,EAAM;AAC1B,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,KAAA,CAAM,MAAA,EAAO;AAAA,IACf,CAAA,MAAO;AAEL,MAAA,cAAA,CAAe,MAAM;AAEnB,QAAA,OAAA,CAAQ,KAAK,8EAA8E,CAAA;AAAA,MAC7F,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,CAAQ,2BAA2B,KAAA,EAAO;AAC5C,IAAA,mBAAA,EAAoB;AAAA,EACtB;AAEA,EAAA,2CAAA,CAA4C,OAAO,CAAA;AAEnD,EAAA,MAAM,QAAQ,eAAA,EAAgB;AAC9B,EAAA,KAAA,CAAM,MAAA,CAAO,QAAQ,YAAY,CAAA;AAEjC,EAAA,IAAI,OAAA,CAAQ,SAAA,IAAa,CAAC,OAAA,CAAQ,YAAA,CAAa,IAAA,CAAK,CAAC,EAAE,IAAA,EAAK,KAAM,IAAA,KAASA,gBAA0B,CAAA,EAAG;AACtG,IAAA,OAAA,CAAQ,YAAA,CAAa,IAAA;AAAA,MACnB,oBAAA,CAAqB;AAAA,QACnB,YAAY,OAAO,OAAA,CAAQ,SAAA,KAAc,QAAA,GAAW,QAAQ,SAAA,GAAY;AAAA,OACzE;AAAA,KACH;AAAA,EACF;AAEA,EAAA,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAErC,EAAA,MAAM,MAAA,GAAS,IAAI,UAAA,CAAW,OAAO,CAAA;AAErC,EAAA,eAAA,EAAgB,CAAE,UAAU,MAAM,CAAA;AAElC,EAAA,MAAA,CAAO,IAAA,EAAK;AAEZ,EAAA,KAAA,CAAM,IAAI,CAAA,qBAAA,EAA+C,KAAK,CAAA,CAAE,CAAA;AAEhE,EAAA,MAAA,CAAO,yBAAA,EAA0B;AAEjC,EAAA,2BAAA,EAA4B;AAE5B,EAAA,uCAAA,CAAwC,MAAM,CAAA;AAC9C,EAAA,sBAAA,CAAuB,MAAM,CAAA;AAI7B,EAAA,IAAI,OAAA,CAAQ,IAAI,MAAA,EAAQ;AACtB,IAAA,OAAA,CAAQ,EAAA,CAAG,WAAW,YAAY;AAEhC,MAAA,MAAM,MAAA,CAAO,MAAM,GAAG,CAAA;AAAA,IACxB,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,MAAA;AACT;AAKO,SAAS,0BAAA,GAAmC;AACjD,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,QAAQ,uBAAA,EAAwB;AAEtC,EAAA,MAAM,QAAA,GAAuD,CAAC,sBAAA,EAAwB,kBAAkB,CAAA;AAExG,EAAA,IAAI,iBAAgB,EAAG;AACrB,IAAA,QAAA,CAAS,KAAK,qBAAqB,CAAA;AAAA,EACrC;AAEA,EAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,IAAA,IAAI,CAAC,KAAA,CAAM,QAAA,CAAS,CAAC,CAAA,EAAG;AACtB,MAAA,KAAA,CAAM,KAAA;AAAA,QACJ,0BAA0B,CAAC,CAAA,8EAAA;AAAA,OAC7B;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,KAAA,CAAM,QAAA,CAAS,eAAe,CAAA,EAAG;AACpC,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ;AAAA,KACF;AAAA,EACF;AACF;AAEA,SAAS,gBAAA,CACP,SACA,0BAAA,EACmB;AACnB,EAAA,MAAM,OAAA,GAAU,UAAA,CAAW,OAAA,CAAQ,OAAO,CAAA;AAE1C,EAAA,MAAM,SAAA,GAAY,kBAAA,CAAmB,OAAA,CAAQ,SAAS,CAAA;AAEtD,EAAA,MAAM,gBAAA,GAAmB,mBAAA,CAAoB,OAAA,CAAQ,gBAAgB,CAAA;AAErE,EAAA,MAAM,aAAA,GAAgB;AAAA,IACpB,GAAG,OAAA;AAAA,IACH,GAAA,EAAK,OAAA,CAAQ,GAAA,IAAO,OAAA,CAAQ,GAAA,CAAI,UAAA;AAAA,IAChC,WAAA,EAAa,OAAA,CAAQ,WAAA,IAAe,OAAA,CAAQ,GAAA,CAAI,kBAAA;AAAA,IAChD,iBAAA,EAAmB,QAAQ,iBAAA,IAAqB,IAAA;AAAA,IAChD,SAAA,EAAW,QAAQ,SAAA,IAAa,iBAAA;AAAA,IAChC,WAAA,EAAa,iCAAA,CAAkC,OAAA,CAAQ,WAAA,IAAe,kBAAkB,CAAA;AAAA,IACxF,OAAA;AAAA,IACA,gBAAA;AAAA,IACA,SAAA;AAAA,IACA,OAAO,SAAA,CAAU,OAAA,CAAQ,KAAA,IAAS,OAAA,CAAQ,IAAI,YAAY;AAAA,GAC5D;AAEA,EAAA,MAAM,eAAe,OAAA,CAAQ,YAAA;AAC7B,EAAA,MAAM,mBAAA,GAAsB,OAAA,CAAQ,mBAAA,IAAuB,0BAAA,CAA2B,aAAa,CAAA;AAEnG,EAAA,MAAM,uBAAuB,sBAAA,CAAuB;AAAA,IAClD,mBAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,OAAO;AAAA,IACL,GAAG,aAAA;AAAA,IACH,YAAA,EAAc;AAAA,GAChB;AACF;AAEA,SAAS,WAAW,OAAA,EAAqD;AACvE,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,OAAO,OAAA;AAAA,EACT;AAEA,EAAA,MAAM,kBAAkB,gBAAA,EAAiB;AACzC,EAAA,IAAI,oBAAoB,MAAA,EAAW;AACjC,IAAA,OAAO,eAAA;AAAA,EACT;AAEA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,oBAAoB,gBAAA,EAAuE;AAClG,EAAA,IAAI,qBAAqB,MAAA,EAAW;AAClC,IAAA,OAAO,gBAAA;AAAA,EACT;AAEA,EAAA,MAAM,iBAAA,GAAoB,QAAQ,GAAA,CAAI,yBAAA;AACtC,EAAA,IAAI,CAAC,iBAAA,EAAmB;AACtB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,MAAA,GAAS,WAAW,iBAAiB,CAAA;AAC3C,EAAA,OAAO,QAAA,CAAS,MAAM,CAAA,GAAI,MAAA,GAAS,MAAA;AACrC;AAQA,SAAS,2BAAA,GAAoC;AAC3C,EAAA,IAAI,SAAA,CAAU,OAAA,CAAQ,GAAA,CAAI,sBAAsB,MAAM,KAAA,EAAO;AAC3D,IAAA,MAAM,cAAA,GAAiB,QAAQ,GAAA,CAAI,YAAA;AACnC,IAAA,MAAM,UAAA,GAAa,QAAQ,GAAA,CAAI,cAAA;AAC/B,IAAA,MAAM,kBAAA,GAAqB,6BAAA,CAA8B,cAAA,EAAgB,UAAU,CAAA;AACnF,IAAA,eAAA,EAAgB,CAAE,sBAAsB,kBAAkB,CAAA;AAAA,EAC5D;AACF;;;;"} | ||
| {"version":3,"file":"index.js","sources":["../../../src/sdk/index.ts"],"sourcesContent":["import type { Integration, Options } from '@sentry/core';\nimport {\n applySdkMetadata,\n consoleSandbox,\n conversationIdIntegration,\n debug,\n envToBool,\n functionToStringIntegration,\n getCurrentScope,\n getIntegrationsToSetup,\n hasSpansEnabled,\n inboundFiltersIntegration,\n linkedErrorsIntegration,\n propagationContextFromHeaders,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport {\n enhanceDscWithOpenTelemetryRootSpanName,\n openTelemetrySetupCheck,\n setOpenTelemetryContextAsyncContextStrategy,\n setupEventContextTrace,\n} from '@sentry/opentelemetry';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { childProcessIntegration } from '../integrations/childProcess';\nimport { nodeContextIntegration } from '../integrations/context';\nimport { contextLinesIntegration } from '../integrations/contextlines';\nimport { httpIntegration } from '../integrations/http';\nimport { localVariablesIntegration } from '../integrations/local-variables';\nimport { modulesIntegration } from '../integrations/modules';\nimport { nativeNodeFetchIntegration } from '../integrations/node-fetch';\nimport { onUncaughtExceptionIntegration } from '../integrations/onuncaughtexception';\nimport { onUnhandledRejectionIntegration } from '../integrations/onunhandledrejection';\nimport { processSessionIntegration } from '../integrations/processSession';\nimport { INTEGRATION_NAME as SPOTLIGHT_INTEGRATION_NAME, spotlightIntegration } from '../integrations/spotlight';\nimport { consoleIntegration } from '../integrations/console';\nimport { systemErrorIntegration } from '../integrations/systemError';\nimport { makeNodeTransport } from '../transports';\nimport type { NodeClientOptions, NodeOptions } from '../types';\nimport { getSpotlightConfig } from '../utils/spotlight';\nimport { defaultStackParser, getSentryRelease } from './api';\nimport { NodeClient } from './client';\nimport { initializeEsmLoader } from './esmLoader';\n\n/**\n * Get default integrations for the Node-Core SDK.\n */\nexport function getDefaultIntegrations(): Integration[] {\n return [\n // Common\n // TODO(v11): Replace with `eventFiltersIntegration` once we remove the deprecated `inboundFiltersIntegration`\n // eslint-disable-next-line typescript/no-deprecated\n inboundFiltersIntegration(),\n functionToStringIntegration(),\n linkedErrorsIntegration(),\n requestDataIntegration(),\n systemErrorIntegration(),\n conversationIdIntegration(),\n // Native Wrappers\n consoleIntegration(),\n httpIntegration(),\n nativeNodeFetchIntegration(),\n // Global Handlers\n onUncaughtExceptionIntegration(),\n onUnhandledRejectionIntegration(),\n // Event Info\n contextLinesIntegration(),\n localVariablesIntegration(),\n nodeContextIntegration(),\n childProcessIntegration(),\n processSessionIntegration(),\n modulesIntegration(),\n ];\n}\n\n/**\n * Initialize Sentry for Node.\n */\nexport function init(options: NodeOptions | undefined = {}): NodeClient | undefined {\n return _init(options, getDefaultIntegrations);\n}\n\n/**\n * Initialize Sentry for Node, without any integrations added by default.\n */\nexport function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): NodeClient {\n return _init(options, () => []);\n}\n\n/**\n * Initialize Sentry for Node, without performance instrumentation.\n */\nfunction _init(\n _options: NodeOptions | undefined = {},\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClient {\n const options = getClientOptions(_options, getDefaultIntegrationsImpl);\n\n if (options.debug === true) {\n if (DEBUG_BUILD) {\n debug.enable();\n } else {\n // use `console.warn` rather than `debug.warn` since by non-debug bundles have all `debug.x` statements stripped\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.');\n });\n }\n }\n\n if (options.registerEsmLoaderHooks !== false) {\n initializeEsmLoader();\n }\n\n setOpenTelemetryContextAsyncContextStrategy(options);\n\n const scope = getCurrentScope();\n scope.update(options.initialScope);\n\n if (options.spotlight && !options.integrations.some(({ name }) => name === SPOTLIGHT_INTEGRATION_NAME)) {\n options.integrations.push(\n spotlightIntegration({\n sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined,\n }),\n );\n }\n\n applySdkMetadata(options, 'node-core');\n\n const client = new NodeClient(options);\n // The client is on the current scope, from where it generally is inherited\n getCurrentScope().setClient(client);\n\n client.init();\n\n /*! rollup-include-cjs-only */\n debug.log(`SDK initialized from CommonJS`);\n /*! rollup-include-cjs-only-end */\n /*! rollup-include-esm-only */\n debug.log(`SDK initialized from ESM`);\n /*! rollup-include-esm-only-end */\n\n client.startClientReportTracking();\n\n updateScopeFromEnvVariables();\n\n enhanceDscWithOpenTelemetryRootSpanName(client);\n setupEventContextTrace(client);\n\n // Ensure we flush events when vercel functions are ended\n // See: https://vercel.com/docs/functions/functions-api-reference#sigterm-signal\n if (process.env.VERCEL) {\n process.on('SIGTERM', async () => {\n // We have 500ms for processing here, so we try to make sure to have enough time to send the events\n await client.flush(200);\n });\n }\n\n return client;\n}\n\n/**\n * Validate that your OpenTelemetry setup is correct.\n */\nexport function validateOpenTelemetrySetup(): void {\n if (!DEBUG_BUILD) {\n return;\n }\n\n const setup = openTelemetrySetupCheck();\n\n const required: ReturnType<typeof openTelemetrySetupCheck> = ['SentryContextManager', 'SentryPropagator'];\n\n const hasSentryTracerProvider = setup.includes('SentryTracerProvider');\n\n if (hasSpansEnabled() && !hasSentryTracerProvider) {\n required.push('SentrySpanProcessor');\n }\n\n for (const k of required) {\n if (!setup.includes(k)) {\n debug.error(\n `You have to set up the ${k}. Without this, the OpenTelemetry & Sentry integration will not work properly.`,\n );\n }\n }\n\n if (!hasSentryTracerProvider && !setup.includes('SentrySampler')) {\n debug.warn(\n 'You have to set up the SentrySampler. Without this, the OpenTelemetry & Sentry integration may still work, but sample rates set for the Sentry SDK will not be respected. If you use a custom sampler, make sure to use `wrapSamplingDecision`.',\n );\n }\n}\n\nfunction getClientOptions(\n options: NodeOptions,\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClientOptions {\n const release = getRelease(options.release);\n\n const spotlight = getSpotlightConfig(options.spotlight);\n\n const tracesSampleRate = getTracesSampleRate(options.tracesSampleRate);\n\n const mergedOptions = {\n ...options,\n dsn: options.dsn ?? process.env.SENTRY_DSN,\n environment: options.environment ?? process.env.SENTRY_ENVIRONMENT,\n sendClientReports: options.sendClientReports ?? true,\n transport: options.transport ?? makeNodeTransport,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n release,\n tracesSampleRate,\n spotlight,\n debug: envToBool(options.debug ?? process.env.SENTRY_DEBUG),\n };\n\n const integrations = options.integrations;\n const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(mergedOptions);\n\n const resolvedIntegrations = getIntegrationsToSetup({\n defaultIntegrations,\n integrations,\n });\n\n return {\n ...mergedOptions,\n integrations: resolvedIntegrations,\n };\n}\n\nfunction getRelease(release: NodeOptions['release']): string | undefined {\n if (release !== undefined) {\n return release;\n }\n\n const detectedRelease = getSentryRelease();\n if (detectedRelease !== undefined) {\n return detectedRelease;\n }\n\n return undefined;\n}\n\nfunction getTracesSampleRate(tracesSampleRate: NodeOptions['tracesSampleRate']): number | undefined {\n if (tracesSampleRate !== undefined) {\n return tracesSampleRate;\n }\n\n const sampleRateFromEnv = process.env.SENTRY_TRACES_SAMPLE_RATE;\n if (!sampleRateFromEnv) {\n return undefined;\n }\n\n const parsed = parseFloat(sampleRateFromEnv);\n return isFinite(parsed) ? parsed : undefined;\n}\n\n/**\n * Update scope and propagation context based on environmental variables.\n *\n * See https://github.com/getsentry/rfcs/blob/main/text/0071-continue-trace-over-process-boundaries.md\n * for more details.\n */\nfunction updateScopeFromEnvVariables(): void {\n if (envToBool(process.env.SENTRY_USE_ENVIRONMENT) !== false) {\n const sentryTraceEnv = process.env.SENTRY_TRACE;\n const baggageEnv = process.env.SENTRY_BAGGAGE;\n const propagationContext = propagationContextFromHeaders(sentryTraceEnv, baggageEnv);\n getCurrentScope().setPropagationContext(propagationContext);\n }\n}\n"],"names":["SPOTLIGHT_INTEGRATION_NAME"],"mappings":"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"} |
@@ -1,9 +0,11 @@ | ||
| import { isCjs } from './detection.js'; | ||
| const createMissingInstrumentationContext = (pkg) => { | ||
| let isCjs; | ||
| isCjs = false; | ||
| return { | ||
| package: pkg, | ||
| "javascript.is_cjs": isCjs | ||
| }; | ||
| }; | ||
| const createMissingInstrumentationContext = (pkg) => ({ | ||
| package: pkg, | ||
| "javascript.is_cjs": isCjs() | ||
| }); | ||
| export { createMissingInstrumentationContext }; | ||
| //# sourceMappingURL=createMissingInstrumentationContext.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"createMissingInstrumentationContext.js","sources":["../../../src/utils/createMissingInstrumentationContext.ts"],"sourcesContent":["import type { MissingInstrumentationContext } from '@sentry/core';\nimport { isCjs } from './detection';\n\nexport const createMissingInstrumentationContext = (pkg: string): MissingInstrumentationContext => ({\n package: pkg,\n 'javascript.is_cjs': isCjs(),\n});\n"],"names":[],"mappings":";;AAGO,MAAM,mCAAA,GAAsC,CAAC,GAAA,MAAgD;AAAA,EAClG,OAAA,EAAS,GAAA;AAAA,EACT,qBAAqB,KAAA;AACvB,CAAA;;;;"} | ||
| {"version":3,"file":"createMissingInstrumentationContext.js","sources":["../../../src/utils/createMissingInstrumentationContext.ts"],"sourcesContent":["import type { MissingInstrumentationContext } from '@sentry/core';\n\nexport const createMissingInstrumentationContext = (pkg: string): MissingInstrumentationContext => {\n let isCjs: boolean;\n /*! rollup-include-cjs-only */\n isCjs = true;\n /*! rollup-include-cjs-only-end */\n /*! rollup-include-esm-only */\n isCjs = false;\n /*! rollup-include-esm-only-end */\n\n return {\n package: pkg,\n 'javascript.is_cjs': isCjs,\n };\n};\n"],"names":[],"mappings":"AAEO,MAAM,mCAAA,GAAsC,CAAC,GAAA,KAA+C;AACjG,EAAA,IAAI,KAAA;AAAA,EACJ,KAAA,GAAA,KAAA;AACA,EAAA,OAAA;AAAQ,IACR,OAAA,EAAA,GAAA;AAAA,IACA,mBAAA,EAAA;AACA,GAAA;AAAQ;;;;"} |
| import { consoleSandbox } from '@sentry/core'; | ||
| import { NODE_MAJOR, NODE_MINOR } from '../nodeVersion.js'; | ||
| function isCjs() { | ||
| return false; | ||
| } | ||
| let hasWarnedAboutNodeVersion; | ||
@@ -23,3 +20,3 @@ function supportsEsmLoaderHooks() { | ||
| export { isCjs, supportsEsmLoaderHooks }; | ||
| export { supportsEsmLoaderHooks }; | ||
| //# sourceMappingURL=detection.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"detection.js","sources":["../../../src/utils/detection.ts"],"sourcesContent":["import { consoleSandbox } from '@sentry/core';\nimport { NODE_MAJOR, NODE_MINOR } from '../nodeVersion';\n\n/** Detect CommonJS. */\nexport function isCjs(): boolean {\n /*! rollup-include-cjs-only */\n return true;\n /*! rollup-include-cjs-only-end */\n\n /*! rollup-include-esm-only */\n return false;\n /*! rollup-include-esm-only-end */\n}\n\nlet hasWarnedAboutNodeVersion: boolean | undefined;\n\n/**\n * Check if the current Node.js version supports module.register\n */\nexport function supportsEsmLoaderHooks(): boolean {\n if (isCjs()) {\n return false;\n }\n\n if (NODE_MAJOR >= 21 || (NODE_MAJOR === 20 && NODE_MINOR >= 6) || (NODE_MAJOR === 18 && NODE_MINOR >= 19)) {\n return true;\n }\n\n if (!hasWarnedAboutNodeVersion) {\n hasWarnedAboutNodeVersion = true;\n\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] You are using Node.js v${process.versions.node} in ESM mode (\"import syntax\"). The Sentry Node.js SDK is not compatible with ESM in Node.js versions before 18.19.0 or before 20.6.0. Please either build your application with CommonJS (\"require() syntax\"), or upgrade your Node.js version.`,\n );\n });\n }\n\n return false;\n}\n"],"names":[],"mappings":";;;AAIO,SAAS,KAAA,GAAiB;AAAA,EAC/B,OAAA,KAAA;AACA;AAAO,IACP,yBAAA;AAEA,SAAA,sBAAA,GAAA;AAKF,EAAA,IAAI,UAAA,IAAA,EAAA,IAAA,UAAA,KAAA,EAAA,IAAA,UAAA,IAAA,CAAA,IAAA,UAAA,KAAA,EAAA,IAAA,UAAA,IAAA,EAAA,EAAA;AAKG,IAAA,OAAA,IAAA;AACL,EAAA;AACE,EAAA,IAAA,CAAA,yBAAO,EAAA;AAAA,IACT,yBAAA,GAAA,IAAA;AAEA,IAAA,cAAI,CAAA;AACF,MAAA,OAAO,CAAA,IAAA;AAAA,QACT,CAAA,gCAAA,EAAA,OAAA,CAAA,QAAA,CAAA,IAAA,CAAA,gPAAA;AAEA,OAAK;AACH,IAAA,CAAA,CAAA;AAEA,EAAA;AAEE,EAAA,OAAA,KAAQ;AAAA;;;;"} | ||
| {"version":3,"file":"detection.js","sources":["../../../src/utils/detection.ts"],"sourcesContent":["import { consoleSandbox } from '@sentry/core';\nimport { NODE_MAJOR, NODE_MINOR } from '../nodeVersion';\n\nfunction isCjs(): boolean {\n /*! rollup-include-cjs-only */\n return true;\n /*! rollup-include-cjs-only-end */\n\n /*! rollup-include-esm-only */\n return false;\n /*! rollup-include-esm-only-end */\n}\n\nlet hasWarnedAboutNodeVersion: boolean | undefined;\n\n/**\n * Check if the current Node.js version supports module.register\n */\nexport function supportsEsmLoaderHooks(): boolean {\n if (isCjs()) {\n return false;\n }\n\n if (NODE_MAJOR >= 21 || (NODE_MAJOR === 20 && NODE_MINOR >= 6) || (NODE_MAJOR === 18 && NODE_MINOR >= 19)) {\n return true;\n }\n\n if (!hasWarnedAboutNodeVersion) {\n hasWarnedAboutNodeVersion = true;\n\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] You are using Node.js v${process.versions.node} in ESM mode (\"import syntax\"). The Sentry Node.js SDK is not compatible with ESM in Node.js versions before 18.19.0 or before 20.6.0. Please either build your application with CommonJS (\"require() syntax\"), or upgrade your Node.js version.`,\n );\n });\n }\n\n return false;\n}\n"],"names":[],"mappings":";;;AAKS,IACP,yBAAA;AAEA,SAAA,sBAAA,GAAA;AAKF,EAAA,IAAI,UAAA,IAAA,EAAA,IAAA,UAAA,KAAA,EAAA,IAAA,UAAA,IAAA,CAAA,IAAA,UAAA,KAAA,EAAA,IAAA,UAAA,IAAA,EAAA,EAAA;AAKG,IAAA,OAAA,IAAA;AACL,EAAA;AACE,EAAA,IAAA,CAAA,yBAAO,EAAA;AAAA,IACT,yBAAA,GAAA,IAAA;AAEA,IAAA,cAAI,CAAA;AACF,MAAA,OAAO,CAAA,IAAA;AAAA,QACT,CAAA,gCAAA,EAAA,OAAA,CAAA,QAAA,CAAA,IAAA,CAAA,gPAAA;AAEA,OAAK;AACH,IAAA,CAAA,CAAA;AAEA,EAAA;AAEE,EAAA,OAAA,KAAQ;AAAA;;;;"} |
| import { isWrapped } from '@opentelemetry/instrumentation'; | ||
| import { getClient, getOriginalFunction, isEnabled, hasSpansEnabled, consoleSandbox, getGlobalScope } from '@sentry/core'; | ||
| import { createMissingInstrumentationContext } from './createMissingInstrumentationContext.js'; | ||
| import '../nodeVersion.js'; | ||
@@ -10,7 +9,5 @@ function ensureIsWrapped(maybeWrappedFunction, name) { | ||
| consoleSandbox(() => { | ||
| { | ||
| console.warn( | ||
| `[Sentry] ${name} is not instrumented. Please make sure to initialize Sentry in a separate file that you \`--import\` when running node, see: https://docs.sentry.io/platforms/javascript/guides/${name}/install/esm/.` | ||
| ); | ||
| } | ||
| console.warn( | ||
| `[Sentry] ${name} is not instrumented. Please make sure to initialize Sentry in a separate file that you \`--import\` when running node, see: https://docs.sentry.io/platforms/javascript/guides/${name}/install/esm/.` | ||
| ); | ||
| }); | ||
@@ -17,0 +14,0 @@ getGlobalScope().setContext("missing_instrumentation", createMissingInstrumentationContext(name)); |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"ensureIsWrapped.js","sources":["../../../src/utils/ensureIsWrapped.ts"],"sourcesContent":["import { isWrapped } from '@opentelemetry/instrumentation';\nimport {\n consoleSandbox,\n getClient,\n getOriginalFunction,\n getGlobalScope,\n hasSpansEnabled,\n isEnabled,\n type WrappedFunction,\n} from '@sentry/core';\nimport type { NodeClient } from '../sdk/client';\nimport { createMissingInstrumentationContext } from './createMissingInstrumentationContext';\nimport { isCjs } from './detection';\n\n/**\n * Checks and warns if a framework isn't wrapped by opentelemetry.\n */\nexport function ensureIsWrapped(\n maybeWrappedFunction: unknown,\n name: 'express' | 'connect' | 'fastify' | 'hapi' | 'koa' | 'hono',\n): void {\n const clientOptions = getClient<NodeClient>()?.getOptions();\n if (\n !clientOptions?.disableInstrumentationWarnings &&\n !(\n isWrapped(maybeWrappedFunction) ||\n typeof getOriginalFunction(maybeWrappedFunction as WrappedFunction) === 'function'\n ) &&\n isEnabled() &&\n hasSpansEnabled(clientOptions)\n ) {\n consoleSandbox(() => {\n if (isCjs()) {\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] ${name} is not instrumented. This is likely because you required/imported ${name} before calling \\`Sentry.init()\\`.`,\n );\n } else {\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] ${name} is not instrumented. Please make sure to initialize Sentry in a separate file that you \\`--import\\` when running node, see: https://docs.sentry.io/platforms/javascript/guides/${name}/install/esm/.`,\n );\n }\n });\n\n getGlobalScope().setContext('missing_instrumentation', createMissingInstrumentationContext(name));\n }\n}\n"],"names":[],"mappings":";;;;;AAiBO,SAAS,eAAA,CACd,sBACA,IAAA,EACM;AACN,EAAA,MAAM,aAAA,GAAgB,SAAA,EAAsB,EAAG,UAAA,EAAW;AAC1D,EAAA,IACE,CAAC,aAAA,EAAe,8BAAA,IAChB,EACE,SAAA,CAAU,oBAAoB,CAAA,IAC9B,OAAO,mBAAA,CAAoB,oBAAuC,MAAM,UAAA,CAAA,IAE1E,SAAA,EAAU,IACV,eAAA,CAAgB,aAAa,CAAA,EAC7B;AACA,IAAA,cAAA,CAAe,MAAM;AACnB,MAKO;AAEL,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN,CAAA,SAAA,EAAY,IAAI,CAAA,gLAAA,EAAmL,IAAI,CAAA,cAAA;AAAA,SACzM;AAAA,MACF;AAAA,IACF,CAAC,CAAA;AAED,IAAA,cAAA,EAAe,CAAE,UAAA,CAAW,yBAAA,EAA2B,mCAAA,CAAoC,IAAI,CAAC,CAAA;AAAA,EAClG;AACF;;;;"} | ||
| {"version":3,"file":"ensureIsWrapped.js","sources":["../../../src/utils/ensureIsWrapped.ts"],"sourcesContent":["import { isWrapped } from '@opentelemetry/instrumentation';\nimport {\n consoleSandbox,\n getClient,\n getOriginalFunction,\n getGlobalScope,\n hasSpansEnabled,\n isEnabled,\n type WrappedFunction,\n} from '@sentry/core';\nimport type { NodeClient } from '../sdk/client';\nimport { createMissingInstrumentationContext } from './createMissingInstrumentationContext';\n\n/**\n * Checks and warns if a framework isn't wrapped by opentelemetry.\n */\nexport function ensureIsWrapped(\n maybeWrappedFunction: unknown,\n name: 'express' | 'connect' | 'fastify' | 'hapi' | 'koa' | 'hono',\n): void {\n const clientOptions = getClient<NodeClient>()?.getOptions();\n if (\n !clientOptions?.disableInstrumentationWarnings &&\n !(\n isWrapped(maybeWrappedFunction) ||\n typeof getOriginalFunction(maybeWrappedFunction as WrappedFunction) === 'function'\n ) &&\n isEnabled() &&\n hasSpansEnabled(clientOptions)\n ) {\n consoleSandbox(() => {\n /*! rollup-include-cjs-only */\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] ${name} is not instrumented. This is likely because you required/imported ${name} before calling \\`Sentry.init()\\`.`,\n );\n /*! rollup-include-cjs-only-end */\n\n /*! rollup-include-esm-only */\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] ${name} is not instrumented. Please make sure to initialize Sentry in a separate file that you \\`--import\\` when running node, see: https://docs.sentry.io/platforms/javascript/guides/${name}/install/esm/.`,\n );\n /*! rollup-include-esm-only-end */\n });\n\n getGlobalScope().setContext('missing_instrumentation', createMissingInstrumentationContext(name));\n }\n}\n"],"names":[],"mappings":";;;;AAgBO,SAAS,eAAA,CACd,sBACA,IAAA,EACM;AACN,EAAA,MAAM,aAAA,GAAgB,SAAA,EAAsB,EAAG,UAAA,EAAW;AAC1D,EAAA,IACE,CAAC,aAAA,EAAe,8BAAA,IAChB,EACE,SAAA,CAAU,oBAAoB,CAAA,IAC9B,OAAO,mBAAA,CAAoB,oBAAuC,MAAM,UAAA,CAAA,IAE1E,SAAA,EAAU,IACV,eAAA,CAAgB,aAAa,CAAA,EAC7B;AACA,IAAA,cAAA,CAAe,MAAM;AAAA,MACnB,OAAA,CAAA,IAAA;AAEA,QAAA,CAAA,SAAQ,EAAA,IAAA,CAAA,gLAAA,EAAA,IAAA,CAAA,cAAA;AAAA,OAAA;AACoF,IAAA,CAAA,CAC5F;AAAA,IAAA,cACA,EAAA,CAAA,UAAA,CAAA,yBAAA,EAAA,mCAAA,CAAA,IAAA,CAAA,CAAA;AAAA,EAAA;AAIA;;;;"} |
@@ -1,2 +0,2 @@ | ||
| import { getClient, shouldPropagateTraceForUrl, getTraceData, mergeBaggageHeaders, getBreadcrumbLogLevelFromHttpStatusCode, addBreadcrumb, debug, parseUrl, getSanitizedUrlString } from '@sentry/core'; | ||
| import { getClient, shouldPropagateTraceForUrl, getTraceData, mergeBaggageHeaders, getBreadcrumbLogLevelFromHttpStatusCode, addBreadcrumb, debug, parseUrl, getSanitizedUrlString, withActiveSpan } from '@sentry/core'; | ||
@@ -6,6 +6,9 @@ const SENTRY_TRACE_HEADER = "sentry-trace"; | ||
| const W3C_TRACEPARENT_HEADER = "traceparent"; | ||
| function addTracePropagationHeadersToFetchRequest(request, propagationDecisionMap) { | ||
| function addTracePropagationHeadersToFetchRequest(request, propagationDecisionMap, span) { | ||
| const url = getAbsoluteUrl(request.origin, request.path); | ||
| const { tracePropagationTargets, propagateTraceparent } = getClient()?.getOptions() || {}; | ||
| const addedHeaders = shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap) ? getTraceData({ propagateTraceparent }) : void 0; | ||
| if (!shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)) { | ||
| return; | ||
| } | ||
| const addedHeaders = span ? withActiveSpan(span, () => getTraceData({ propagateTraceparent })) : getTraceData({ propagateTraceparent }); | ||
| if (!addedHeaders) { | ||
@@ -12,0 +15,0 @@ return; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"outgoingFetchRequest.js","sources":["../../../src/utils/outgoingFetchRequest.ts"],"sourcesContent":["import type { LRUMap, SanitizedRequestData } from '@sentry/core';\nimport {\n addBreadcrumb,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getSanitizedUrlString,\n getTraceData,\n parseUrl,\n shouldPropagateTraceForUrl,\n mergeBaggageHeaders,\n} from '@sentry/core';\nimport type { UndiciRequest, UndiciResponse } from '../integrations/node-fetch/types';\nimport { debug } from '@sentry/core';\nconst SENTRY_TRACE_HEADER = 'sentry-trace';\nconst SENTRY_BAGGAGE_HEADER = 'baggage';\nconst W3C_TRACEPARENT_HEADER = 'traceparent';\n/**\n * Add trace propagation headers to an outgoing fetch/undici request.\n *\n * Checks if the request URL matches trace propagation targets,\n * then injects sentry-trace, traceparent, and baggage headers.\n */\n// eslint-disable-next-line complexity\nexport function addTracePropagationHeadersToFetchRequest(\n request: UndiciRequest,\n propagationDecisionMap: LRUMap<string, boolean>,\n): void {\n const url = getAbsoluteUrl(request.origin, request.path);\n\n // Manually add the trace headers, if it applies\n // Note: We do not use `propagation.inject()` here, because our propagator relies on an active span\n // Which we do not have in this case\n // The propagator _may_ overwrite this, but this should be fine as it is the same data\n const { tracePropagationTargets, propagateTraceparent } = getClient()?.getOptions() || {};\n const addedHeaders = shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)\n ? getTraceData({ propagateTraceparent })\n : undefined;\n\n if (!addedHeaders) {\n return;\n }\n\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = addedHeaders;\n\n // Undici can expose headers either as a raw string (v5-style) or as a flat array of pairs (v6-style).\n // In the array form, even indices are header names and odd indices are values; in undici v6 a value\n // may be `string | string[]` when a header has multiple values. The helpers below (_deduplicateArrayHeader,\n // push, etc.) expect each value slot to be a single string, so we normalize array headers first.\n const requestHeaders: string[] = Array.isArray(request.headers)\n ? normalizeUndiciHeaderPairs(request.headers)\n : stringToArrayHeaders(request.headers);\n\n // OTel's UndiciInstrumentation calls propagation.inject() which unconditionally\n // appends headers to the request. When the user also sets headers via getTraceData(),\n // this results in duplicate sentry-trace and baggage (and optionally traceparent) entries.\n // We clean these up before applying our own logic.\n _deduplicateArrayHeader(requestHeaders, SENTRY_TRACE_HEADER);\n _deduplicateArrayHeader(requestHeaders, SENTRY_BAGGAGE_HEADER);\n if (propagateTraceparent) {\n _deduplicateArrayHeader(requestHeaders, W3C_TRACEPARENT_HEADER);\n }\n\n // We do not want to overwrite existing headers here\n // If the core UndiciInstrumentation is registered, it will already have set the headers\n // We do not want to add any then\n const hasExistingSentryTraceHeader = _findExistingHeaderIndex(requestHeaders, SENTRY_TRACE_HEADER) !== -1;\n\n // We do not want to set any headers if we already have an existing sentry-trace header.\n // sentry-trace is still the source of truth, otherwise we risk mixing up baggage and sentry-trace values.\n if (!hasExistingSentryTraceHeader) {\n if (sentryTrace) {\n requestHeaders.push(SENTRY_TRACE_HEADER, sentryTrace);\n }\n\n if (traceparent && _findExistingHeaderIndex(requestHeaders, 'traceparent') === -1) {\n requestHeaders.push('traceparent', traceparent);\n }\n\n // For baggage, we make sure to merge this into a possibly existing header\n const existingBaggageIndex = _findExistingHeaderIndex(requestHeaders, SENTRY_BAGGAGE_HEADER);\n if (baggage && existingBaggageIndex === -1) {\n requestHeaders.push(SENTRY_BAGGAGE_HEADER, baggage);\n } else if (baggage) {\n // headers in format [key_0, value_0, key_1, value_1, ...], hence the +1 here\n const existingBaggageValue = requestHeaders[existingBaggageIndex + 1];\n const merged = mergeBaggageHeaders(existingBaggageValue, baggage);\n if (merged) {\n requestHeaders[existingBaggageIndex + 1] = merged;\n }\n }\n }\n\n if (Array.isArray(request.headers)) {\n // Replace contents in place so we keep the same array reference undici/fetch still holds.\n // `requestHeaders` is already normalized (string pairs only); splice writes them back.\n request.headers.splice(0, request.headers.length, ...requestHeaders);\n } else {\n request.headers = arrayToStringHeaders(requestHeaders);\n }\n}\n\n/**\n * Convert undici’s header array into `[name, value, name, value, ...]` where every value is a string.\n *\n * Undici v6 uses this shape: `[k1, v1, k2, v2, ...]`. Types allow each `v` to be `string | string[]` when\n * that header has multiple values. Sentry’s dedupe/merge helpers expect one string per value slot, so\n * multi-value arrays are joined with `', '`. Missing value slots become `''`.\n */\nfunction normalizeUndiciHeaderPairs(headers: (string | string[])[]): string[] {\n const out: string[] = [];\n for (let i = 0; i < headers.length; i++) {\n const entry = headers[i];\n if (i % 2 === 0) {\n // Header name (should always be a string; coerce defensively).\n out.push(typeof entry === 'string' ? entry : String(entry));\n } else {\n // Header value: flatten `string[]` to a single string for downstream string-only helpers.\n out.push(Array.isArray(entry) ? entry.join(', ') : (entry ?? ''));\n }\n }\n return out;\n}\n\nfunction stringToArrayHeaders(requestHeaders: string): string[] {\n const headersArray = requestHeaders.split('\\r\\n');\n const headers: string[] = [];\n for (const header of headersArray) {\n try {\n const colonIndex = header.indexOf(':');\n if (colonIndex === -1) {\n continue;\n }\n const key = header.slice(0, colonIndex).trim();\n const value = header.slice(colonIndex + 1).trim();\n if (key) {\n headers.push(key, value);\n }\n } catch {\n debug.warn(`Failed to convert string request header to array header: ${header}`);\n }\n }\n return headers;\n}\n\nfunction arrayToStringHeaders(headers: string[]): string {\n const headerPairs: string[] = [];\n\n for (let i = 0; i < headers.length; i += 2) {\n const key = headers[i];\n const value = headers[i + 1];\n if (!key || value == null) {\n // skip falsy keys but only null/undefined values\n continue;\n }\n headerPairs.push(`${key}: ${value}`);\n }\n\n if (!headerPairs.length) {\n return '';\n }\n\n return headerPairs.join('\\r\\n').concat('\\r\\n');\n}\n\n/**\n * For a given header name, if there are multiple entries in the [key, value, key, value, ...] array,\n * keep the first entry and remove the rest.\n * For baggage, values are merged to preserve all entries but to dedupe sentry- values, and always\n * keep the first occurrence of them\n */\nfunction _deduplicateArrayHeader(headers: string[], headerName: string): void {\n let firstIndex = -1;\n for (let i = 0; i < headers.length; i += 2) {\n if (headers[i] !== headerName) {\n continue;\n }\n\n if (firstIndex === -1) {\n firstIndex = i;\n continue;\n }\n\n const firstHeaderValue = headers[firstIndex + 1];\n if (headerName === SENTRY_BAGGAGE_HEADER && firstHeaderValue) {\n // mergeBaggageHeaders always takes sentry- values from the new baggage (2nd param) and merges\n // it with the existing one (1st param). Here, we want to keep the first header's existing\n // sentry- values in favor of the new ones. Hence we swap the parameters.\n const merged = mergeBaggageHeaders(headers[i + 1], firstHeaderValue);\n if (merged) {\n headers[firstIndex + 1] = merged;\n }\n }\n headers.splice(i, 2);\n i -= 2;\n }\n}\n\n/**\n * Find the index of an existing header in an array of headers.\n * Only take even indices, because headers are in format [key_0, value_0, key_1, value_1, ...]\n * otherwise we could match a header _value_ with @param name\n */\nfunction _findExistingHeaderIndex(headers: string[], name: string): number {\n return headers.findIndex((header, i) => i % 2 === 0 && header === name);\n}\n\n/** Add a breadcrumb for an outgoing fetch/undici request. */\nexport function addFetchRequestBreadcrumb(request: UndiciRequest, response: UndiciResponse): void {\n const data = getBreadcrumbData(request);\n\n const statusCode = response.statusCode;\n const level = getBreadcrumbLogLevelFromHttpStatusCode(statusCode);\n\n addBreadcrumb(\n {\n category: 'http',\n data: {\n status_code: statusCode,\n ...data,\n },\n type: 'http',\n level,\n },\n {\n event: 'response',\n request,\n response,\n },\n );\n}\n\nfunction getBreadcrumbData(request: UndiciRequest): Partial<SanitizedRequestData> {\n try {\n const url = getAbsoluteUrl(request.origin, request.path);\n const parsedUrl = parseUrl(url);\n\n const data: Partial<SanitizedRequestData> = {\n url: getSanitizedUrlString(parsedUrl),\n 'http.method': request.method || 'GET',\n };\n\n if (parsedUrl.search) {\n data['http.query'] = parsedUrl.search;\n }\n if (parsedUrl.hash) {\n data['http.fragment'] = parsedUrl.hash;\n }\n\n return data;\n } catch {\n return {};\n }\n}\n\n/** Get the absolute URL from an origin and path. */\nexport function getAbsoluteUrl(origin: string, path: string = '/'): string {\n try {\n const url = new URL(path, origin);\n return url.toString();\n } catch {\n // fallback: Construct it on our own\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}`;\n }\n\n return `${url}${path}`;\n }\n}\n"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"outgoingFetchRequest.js","sources":["../../../src/utils/outgoingFetchRequest.ts"],"sourcesContent":["import type { LRUMap, SanitizedRequestData, Span } from '@sentry/core';\nimport {\n addBreadcrumb,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getSanitizedUrlString,\n getTraceData,\n parseUrl,\n shouldPropagateTraceForUrl,\n mergeBaggageHeaders,\n withActiveSpan,\n} from '@sentry/core';\nimport type { UndiciRequest, UndiciResponse } from '../integrations/node-fetch/types';\nimport { debug } from '@sentry/core';\nconst SENTRY_TRACE_HEADER = 'sentry-trace';\nconst SENTRY_BAGGAGE_HEADER = 'baggage';\nconst W3C_TRACEPARENT_HEADER = 'traceparent';\n/**\n * Add trace propagation headers to an outgoing fetch/undici request.\n *\n * Checks if the request URL matches trace propagation targets,\n * then injects sentry-trace, traceparent, and baggage headers.\n *\n * When a `span` is passed (the outgoing `http.client` span), its trace data is propagated so downstream\n * services are parented to that span. Without a span, the active scope's trace data is used.\n *\n * Existing trace headers (e.g. set manually by the user via `getTraceData()`) always take precedence and\n * are de-duplicated rather than overwritten, so we never emit two `sentry-trace`/`baggage` entries.\n */\n// eslint-disable-next-line complexity\nexport function addTracePropagationHeadersToFetchRequest(\n request: UndiciRequest,\n propagationDecisionMap: LRUMap<string, boolean>,\n span?: Span,\n): void {\n const url = getAbsoluteUrl(request.origin, request.path);\n\n // Manually add the trace headers, if it applies\n // Note: We do not use `propagation.inject()` here, because our propagator relies on an active span\n // Which we do not have in this case\n // The propagator _may_ overwrite this, but this should be fine as it is the same data\n const { tracePropagationTargets, propagateTraceparent } = getClient()?.getOptions() || {};\n\n if (!shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)) {\n return;\n }\n\n // When a span is provided, make it active so the propagated headers reference it (and not the parent\n // span). Passing `{ span }` to `getTraceData()` is not enough: for an inactive span it resolves to the\n // span's captured scope, whose active span is still the parent.\n const addedHeaders = span\n ? withActiveSpan(span, () => getTraceData({ propagateTraceparent }))\n : getTraceData({ propagateTraceparent });\n\n if (!addedHeaders) {\n return;\n }\n\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = addedHeaders;\n\n // Undici can expose headers either as a raw string (v5-style) or as a flat array of pairs (v6-style).\n // In the array form, even indices are header names and odd indices are values; in undici v6 a value\n // may be `string | string[]` when a header has multiple values. The helpers below (_deduplicateArrayHeader,\n // push, etc.) expect each value slot to be a single string, so we normalize array headers first.\n const requestHeaders: string[] = Array.isArray(request.headers)\n ? normalizeUndiciHeaderPairs(request.headers)\n : stringToArrayHeaders(request.headers);\n\n // OTel's UndiciInstrumentation calls propagation.inject() which unconditionally\n // appends headers to the request. When the user also sets headers via getTraceData(),\n // this results in duplicate sentry-trace and baggage (and optionally traceparent) entries.\n // We clean these up before applying our own logic.\n _deduplicateArrayHeader(requestHeaders, SENTRY_TRACE_HEADER);\n _deduplicateArrayHeader(requestHeaders, SENTRY_BAGGAGE_HEADER);\n if (propagateTraceparent) {\n _deduplicateArrayHeader(requestHeaders, W3C_TRACEPARENT_HEADER);\n }\n\n // We do not want to overwrite existing headers here\n // If the core UndiciInstrumentation is registered, it will already have set the headers\n // We do not want to add any then\n const hasExistingSentryTraceHeader = _findExistingHeaderIndex(requestHeaders, SENTRY_TRACE_HEADER) !== -1;\n\n // We do not want to set any headers if we already have an existing sentry-trace header.\n // sentry-trace is still the source of truth, otherwise we risk mixing up baggage and sentry-trace values.\n if (!hasExistingSentryTraceHeader) {\n if (sentryTrace) {\n requestHeaders.push(SENTRY_TRACE_HEADER, sentryTrace);\n }\n\n if (traceparent && _findExistingHeaderIndex(requestHeaders, 'traceparent') === -1) {\n requestHeaders.push('traceparent', traceparent);\n }\n\n // For baggage, we make sure to merge this into a possibly existing header\n const existingBaggageIndex = _findExistingHeaderIndex(requestHeaders, SENTRY_BAGGAGE_HEADER);\n if (baggage && existingBaggageIndex === -1) {\n requestHeaders.push(SENTRY_BAGGAGE_HEADER, baggage);\n } else if (baggage) {\n // headers in format [key_0, value_0, key_1, value_1, ...], hence the +1 here\n const existingBaggageValue = requestHeaders[existingBaggageIndex + 1];\n const merged = mergeBaggageHeaders(existingBaggageValue, baggage);\n if (merged) {\n requestHeaders[existingBaggageIndex + 1] = merged;\n }\n }\n }\n\n if (Array.isArray(request.headers)) {\n // Replace contents in place so we keep the same array reference undici/fetch still holds.\n // `requestHeaders` is already normalized (string pairs only); splice writes them back.\n request.headers.splice(0, request.headers.length, ...requestHeaders);\n } else {\n request.headers = arrayToStringHeaders(requestHeaders);\n }\n}\n\n/**\n * Convert undici’s header array into `[name, value, name, value, ...]` where every value is a string.\n *\n * Undici v6 uses this shape: `[k1, v1, k2, v2, ...]`. Types allow each `v` to be `string | string[]` when\n * that header has multiple values. Sentry’s dedupe/merge helpers expect one string per value slot, so\n * multi-value arrays are joined with `', '`. Missing value slots become `''`.\n */\nfunction normalizeUndiciHeaderPairs(headers: (string | string[])[]): string[] {\n const out: string[] = [];\n for (let i = 0; i < headers.length; i++) {\n const entry = headers[i];\n if (i % 2 === 0) {\n // Header name (should always be a string; coerce defensively).\n out.push(typeof entry === 'string' ? entry : String(entry));\n } else {\n // Header value: flatten `string[]` to a single string for downstream string-only helpers.\n out.push(Array.isArray(entry) ? entry.join(', ') : (entry ?? ''));\n }\n }\n return out;\n}\n\nfunction stringToArrayHeaders(requestHeaders: string): string[] {\n const headersArray = requestHeaders.split('\\r\\n');\n const headers: string[] = [];\n for (const header of headersArray) {\n try {\n const colonIndex = header.indexOf(':');\n if (colonIndex === -1) {\n continue;\n }\n const key = header.slice(0, colonIndex).trim();\n const value = header.slice(colonIndex + 1).trim();\n if (key) {\n headers.push(key, value);\n }\n } catch {\n debug.warn(`Failed to convert string request header to array header: ${header}`);\n }\n }\n return headers;\n}\n\nfunction arrayToStringHeaders(headers: string[]): string {\n const headerPairs: string[] = [];\n\n for (let i = 0; i < headers.length; i += 2) {\n const key = headers[i];\n const value = headers[i + 1];\n if (!key || value == null) {\n // skip falsy keys but only null/undefined values\n continue;\n }\n headerPairs.push(`${key}: ${value}`);\n }\n\n if (!headerPairs.length) {\n return '';\n }\n\n return headerPairs.join('\\r\\n').concat('\\r\\n');\n}\n\n/**\n * For a given header name, if there are multiple entries in the [key, value, key, value, ...] array,\n * keep the first entry and remove the rest.\n * For baggage, values are merged to preserve all entries but to dedupe sentry- values, and always\n * keep the first occurrence of them\n */\nfunction _deduplicateArrayHeader(headers: string[], headerName: string): void {\n let firstIndex = -1;\n for (let i = 0; i < headers.length; i += 2) {\n if (headers[i] !== headerName) {\n continue;\n }\n\n if (firstIndex === -1) {\n firstIndex = i;\n continue;\n }\n\n const firstHeaderValue = headers[firstIndex + 1];\n if (headerName === SENTRY_BAGGAGE_HEADER && firstHeaderValue) {\n // mergeBaggageHeaders always takes sentry- values from the new baggage (2nd param) and merges\n // it with the existing one (1st param). Here, we want to keep the first header's existing\n // sentry- values in favor of the new ones. Hence we swap the parameters.\n const merged = mergeBaggageHeaders(headers[i + 1], firstHeaderValue);\n if (merged) {\n headers[firstIndex + 1] = merged;\n }\n }\n headers.splice(i, 2);\n i -= 2;\n }\n}\n\n/**\n * Find the index of an existing header in an array of headers.\n * Only take even indices, because headers are in format [key_0, value_0, key_1, value_1, ...]\n * otherwise we could match a header _value_ with @param name\n */\nfunction _findExistingHeaderIndex(headers: string[], name: string): number {\n return headers.findIndex((header, i) => i % 2 === 0 && header === name);\n}\n\n/** Add a breadcrumb for an outgoing fetch/undici request. */\nexport function addFetchRequestBreadcrumb(request: UndiciRequest, response: UndiciResponse): void {\n const data = getBreadcrumbData(request);\n\n const statusCode = response.statusCode;\n const level = getBreadcrumbLogLevelFromHttpStatusCode(statusCode);\n\n addBreadcrumb(\n {\n category: 'http',\n data: {\n status_code: statusCode,\n ...data,\n },\n type: 'http',\n level,\n },\n {\n event: 'response',\n request,\n response,\n },\n );\n}\n\nfunction getBreadcrumbData(request: UndiciRequest): Partial<SanitizedRequestData> {\n try {\n const url = getAbsoluteUrl(request.origin, request.path);\n const parsedUrl = parseUrl(url);\n\n const data: Partial<SanitizedRequestData> = {\n url: getSanitizedUrlString(parsedUrl),\n 'http.method': request.method || 'GET',\n };\n\n if (parsedUrl.search) {\n data['http.query'] = parsedUrl.search;\n }\n if (parsedUrl.hash) {\n data['http.fragment'] = parsedUrl.hash;\n }\n\n return data;\n } catch {\n return {};\n }\n}\n\n/** Get the absolute URL from an origin and path. */\nexport function getAbsoluteUrl(origin: string, path: string = '/'): string {\n try {\n const url = new URL(path, origin);\n return url.toString();\n } catch {\n // fallback: Construct it on our own\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}`;\n }\n\n return `${url}${path}`;\n }\n}\n"],"names":[],"mappings":"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"} |
@@ -29,3 +29,2 @@ /** | ||
| export { initializeEsmLoader } from './sdk/esmLoader'; | ||
| export { isCjs } from './utils/detection'; | ||
| export { createMissingInstrumentationContext } from './utils/createMissingInstrumentationContext'; | ||
@@ -32,0 +31,0 @@ export { makeNodeTransport, NodeTransportOptions } from './transports'; |
@@ -8,2 +8,4 @@ export { httpIntegration } from './integrations/http'; | ||
| export { nativeNodeFetchIntegration } from './integrations/node-fetch'; | ||
| export { NodeFetchOptions } from './integrations/node-fetch/types'; | ||
| export { instrumentUndici } from './integrations/node-fetch/undici-instrumentation'; | ||
| export { SentryNodeFetchInstrumentation, SentryNodeFetchInstrumentationOptions } from './integrations/node-fetch/SentryNodeFetchInstrumentation'; | ||
@@ -10,0 +12,0 @@ export { SentryContextManager } from './otel/contextManager'; |
@@ -1,23 +0,9 @@ | ||
| interface NodeFetchOptions { | ||
| /** | ||
| * Whether breadcrumbs should be recorded for requests. | ||
| * Defaults to true | ||
| */ | ||
| breadcrumbs?: boolean; | ||
| /** | ||
| * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing fetch requests. | ||
| * | ||
| * @default `true` | ||
| */ | ||
| tracePropagation?: boolean; | ||
| /** | ||
| * Do not capture spans or breadcrumbs for outgoing fetch requests to URLs where the given callback returns `true`. | ||
| * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled. | ||
| */ | ||
| ignoreOutgoingRequests?: (url: string) => boolean; | ||
| } | ||
| import { NodeFetchOptions } from './types'; | ||
| /** | ||
| * Instrument outgoing fetch requests made through the native node `fetch` API. | ||
| * This emits (depending on the integration options) spans and breadcrumbs, as well as injecting trace propagation headers into the request. | ||
| */ | ||
| export declare const nativeNodeFetchIntegration: (options?: NodeFetchOptions | undefined) => import("@sentry/core").Integration & { | ||
| name: "NodeFetch"; | ||
| }; | ||
| export {}; | ||
| //# sourceMappingURL=index.d.ts.map |
@@ -38,2 +38,4 @@ import { InstrumentationConfig } from '@opentelemetry/instrumentation'; | ||
| * https://github.com/open-telemetry/opentelemetry-js-contrib/blob/28e209a9da36bc4e1f8c2b0db7360170ed46cb80/plugins/node/instrumentation-undici/src/undici.ts | ||
| * | ||
| * @deprecated This class is no longer used internally and will be removed in a future major version. Use `nativeNodeFetchIntegration` instead. | ||
| */ | ||
@@ -40,0 +42,0 @@ export declare class SentryNodeFetchInstrumentation extends InstrumentationBase<SentryNodeFetchInstrumentationOptions> { |
@@ -1,5 +0,2 @@ | ||
| /** | ||
| * Aligned with upstream Undici request shape; see `packages/node/.../node-fetch/vendored/types.ts` | ||
| * (vendored from `@opentelemetry/instrumentation-undici`). | ||
| */ | ||
| import { Span } from '@sentry/core'; | ||
| export interface UndiciRequest { | ||
@@ -11,3 +8,4 @@ origin: string; | ||
| * Serialized string of headers in the form `name: value\r\n` for v5 | ||
| * Array of strings `[key1, value1, ...]` for v6 (values may be `string | string[]`) | ||
| * Array of strings `[key1, value1, key2, value2]`, where values are | ||
| * `string | string[]` for v6 | ||
| */ | ||
@@ -25,3 +23,3 @@ headers: string | (string | string[])[]; | ||
| contentType: string | null; | ||
| body: unknown; | ||
| body: any; | ||
| } | ||
@@ -33,2 +31,68 @@ export interface UndiciResponse { | ||
| } | ||
| export interface RequestHookFunction<T = UndiciRequest> { | ||
| (span: Span, request: T): void; | ||
| } | ||
| export interface ResponseHookFunction<RequestType = UndiciRequest, ResponseType = UndiciResponse> { | ||
| (span: Span, info: { | ||
| request: RequestType; | ||
| response: ResponseType; | ||
| }): void; | ||
| } | ||
| export interface RequestMessage { | ||
| request: UndiciRequest; | ||
| } | ||
| export interface RequestHeadersMessage { | ||
| request: UndiciRequest; | ||
| socket: any; | ||
| } | ||
| export interface ResponseHeadersMessage { | ||
| request: UndiciRequest; | ||
| response: UndiciResponse; | ||
| } | ||
| export interface RequestTrailersMessage { | ||
| request: UndiciRequest; | ||
| response: UndiciResponse; | ||
| } | ||
| export interface RequestErrorMessage { | ||
| request: UndiciRequest; | ||
| error: Error; | ||
| } | ||
| export interface UndiciInstrumentationConfig<RequestType = UndiciRequest, ResponseType = UndiciResponse> { | ||
| /** | ||
| * Do not capture spans or breadcrumbs for outgoing fetch requests to URLs where the given callback returns `true`. | ||
| * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled. | ||
| */ | ||
| ignoreOutgoingRequests?: (url: string) => boolean; | ||
| /** Function for adding custom attributes before request is handled */ | ||
| requestHook?: RequestHookFunction<RequestType>; | ||
| /** Function called once response headers have been received */ | ||
| responseHook?: ResponseHookFunction<RequestType, ResponseType>; | ||
| /** Map the following HTTP headers to span attributes. */ | ||
| headersToSpanAttributes?: { | ||
| requestHeaders?: string[]; | ||
| responseHeaders?: string[]; | ||
| }; | ||
| } | ||
| export interface NodeFetchOptions extends UndiciInstrumentationConfig { | ||
| /** | ||
| * Whether breadcrumbs should be recorded for requests. | ||
| * | ||
| * @default `true` | ||
| */ | ||
| breadcrumbs?: boolean; | ||
| /** | ||
| * If set to false, do not emit any spans. | ||
| * Breadcrumbs and trace propagation for outgoing fetch requests are still applied. | ||
| * | ||
| * If `skipOpenTelemetrySetup: true` is configured, this defaults to `false`, otherwise it defaults to `true`. | ||
| */ | ||
| spans?: boolean; | ||
| /** | ||
| * This option only has an effect when `spans` is set to false. When spans are enabled, you cannot disable trace propagation here. | ||
| * Instead, configure `tracePropagationTargets` in the client options. | ||
| * | ||
| * @default `true` | ||
| */ | ||
| tracePropagation?: boolean; | ||
| } | ||
| //# sourceMappingURL=types.d.ts.map |
| import { Tracer } from '@opentelemetry/api'; | ||
| import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base'; | ||
| import { DynamicSamplingContext, Scope, TraceContext } from '@sentry/core'; | ||
| import { ServerRuntimeClient } from '@sentry/core'; | ||
| import { AsyncLocalStorageLookup } from '@sentry/opentelemetry'; | ||
| import { AsyncLocalStorageLookup, OpenTelemetryTracerProvider } from '@sentry/opentelemetry'; | ||
| import { NodeClientOptions } from '../types'; | ||
| /** A client for using Sentry with Node & OpenTelemetry. */ | ||
| export declare class NodeClient extends ServerRuntimeClient<NodeClientOptions> { | ||
| traceProvider: BasicTracerProvider | undefined; | ||
| traceProvider: OpenTelemetryTracerProvider | undefined; | ||
| asyncLocalStorageLookup: AsyncLocalStorageLookup | undefined; | ||
@@ -11,0 +10,0 @@ private _tracer; |
@@ -29,4 +29,21 @@ import { Span as WriteableSpan } from '@opentelemetry/api'; | ||
| * Provide an array of additional OpenTelemetry SpanProcessors that should be registered. | ||
| * | ||
| * Note: providing this forces the full OpenTelemetry SDK `BasicTracerProvider` instead of Sentry's | ||
| * minimal tracer provider, since custom span processors require the SDK span pipeline. See | ||
| * {@link OpenTelemetryServerRuntimeOptions.openTelemetryBasicTracerProvider}. | ||
| */ | ||
| openTelemetrySpanProcessors?: SpanProcessor[]; | ||
| /** | ||
| * By default, the SDK uses Sentry's minimal OpenTelemetry tracer provider, which creates native | ||
| * Sentry spans directly instead of going through the full OpenTelemetry SDK span pipeline. | ||
| * | ||
| * Set this to `true` to use the full OpenTelemetry SDK `BasicTracerProvider` instead, e.g. if you | ||
| * rely on OpenTelemetry SDK features that the minimal provider does not support. | ||
| * | ||
| * Note: providing `openTelemetrySpanProcessors` also forces the full OpenTelemetry SDK provider, | ||
| * since custom span processors require the SDK span pipeline. | ||
| * | ||
| * @default false | ||
| */ | ||
| openTelemetryBasicTracerProvider?: boolean; | ||
| } | ||
@@ -33,0 +50,0 @@ /** |
@@ -1,3 +0,1 @@ | ||
| /** Detect CommonJS. */ | ||
| export declare function isCjs(): boolean; | ||
| /** | ||
@@ -4,0 +2,0 @@ * Check if the current Node.js version supports module.register |
@@ -1,2 +0,2 @@ | ||
| import { LRUMap } from '@sentry/core'; | ||
| import { LRUMap, Span } from '@sentry/core'; | ||
| import { UndiciRequest, UndiciResponse } from '../integrations/node-fetch/types'; | ||
@@ -8,4 +8,10 @@ /** | ||
| * then injects sentry-trace, traceparent, and baggage headers. | ||
| * | ||
| * When a `span` is passed (the outgoing `http.client` span), its trace data is propagated so downstream | ||
| * services are parented to that span. Without a span, the active scope's trace data is used. | ||
| * | ||
| * Existing trace headers (e.g. set manually by the user via `getTraceData()`) always take precedence and | ||
| * are de-duplicated rather than overwritten, so we never emit two `sentry-trace`/`baggage` entries. | ||
| */ | ||
| export declare function addTracePropagationHeadersToFetchRequest(request: UndiciRequest, propagationDecisionMap: LRUMap<string, boolean>): void; | ||
| export declare function addTracePropagationHeadersToFetchRequest(request: UndiciRequest, propagationDecisionMap: LRUMap<string, boolean>, span?: Span): void; | ||
| /** Add a breadcrumb for an outgoing fetch/undici request. */ | ||
@@ -12,0 +18,0 @@ export declare function addFetchRequestBreadcrumb(request: UndiciRequest, response: UndiciResponse): void; |
@@ -29,3 +29,2 @@ /** | ||
| export { initializeEsmLoader } from './sdk/esmLoader'; | ||
| export { isCjs } from './utils/detection'; | ||
| export { createMissingInstrumentationContext } from './utils/createMissingInstrumentationContext'; | ||
@@ -32,0 +31,0 @@ export { makeNodeTransport, type NodeTransportOptions } from './transports'; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"common-exports.d.ts","sourceRoot":"","sources":["../../src/common-exports.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"common-exports.d.ts","sourceRoot":"","sources":["../../src/common-exports.ts"],"names":[],"mappings":"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"} |
@@ -8,2 +8,4 @@ export { httpIntegration } from './integrations/http'; | ||
| export { nativeNodeFetchIntegration } from './integrations/node-fetch'; | ||
| export type { NodeFetchOptions } from './integrations/node-fetch/types'; | ||
| export { instrumentUndici } from './integrations/node-fetch/undici-instrumentation'; | ||
| export { SentryNodeFetchInstrumentation, type SentryNodeFetchInstrumentationOptions, } from './integrations/node-fetch/SentryNodeFetchInstrumentation'; | ||
@@ -10,0 +12,0 @@ export { SentryContextManager } from './otel/contextManager'; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,gDAAgD,CAAC;AAC5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAElF,YAAY,EAAE,4BAA4B,EAAE,MAAM,2CAA2C,CAAC;AAC9F,YAAY,EAAE,iCAAiC,EAAE,MAAM,gDAAgD,CAAC;AAExG,OAAO,EACL,yBAAyB,EACzB,KAAK,gCAAgC,GACtC,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EACL,8BAA8B,EAC9B,KAAK,qCAAqC,GAC3C,MAAM,0DAA0D,CAAC;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEhG,OAAO,EAAE,IAAI,EAAE,sBAAsB,EAAE,8BAA8B,EAAE,0BAA0B,EAAE,MAAM,OAAO,CAAC;AACjH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,YAAY,EAAE,iCAAiC,EAAE,MAAM,SAAS,CAAC;AAEjE,OAAO,EAEL,2CAA2C,IAAI,2BAA2B,GAC3E,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAE,cAAc,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AAEpF,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAEzD,YAAY,EAAE,kCAAkC,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGvF,cAAc,kBAAkB,CAAC"} | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,gDAAgD,CAAC;AAC5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAElF,YAAY,EAAE,4BAA4B,EAAE,MAAM,2CAA2C,CAAC;AAC9F,YAAY,EAAE,iCAAiC,EAAE,MAAM,gDAAgD,CAAC;AAExG,OAAO,EACL,yBAAyB,EACzB,KAAK,gCAAgC,GACtC,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAC;AACpF,OAAO,EAEL,8BAA8B,EAC9B,KAAK,qCAAqC,GAC3C,MAAM,0DAA0D,CAAC;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEhG,OAAO,EAAE,IAAI,EAAE,sBAAsB,EAAE,8BAA8B,EAAE,0BAA0B,EAAE,MAAM,OAAO,CAAC;AACjH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,YAAY,EAAE,iCAAiC,EAAE,MAAM,SAAS,CAAC;AAEjE,OAAO,EAEL,2CAA2C,IAAI,2BAA2B,GAC3E,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAE,cAAc,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AAEpF,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAEzD,YAAY,EAAE,kCAAkC,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGvF,cAAc,kBAAkB,CAAC"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"httpServerSpansIntegration.d.ts","sourceRoot":"","sources":["../../../../src/integrations/http/httpServerSpansIntegration.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,KAAK,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EAEX,IAAI,EAGL,MAAM,cAAc,CAAC;AActB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAQnD,MAAM,WAAW,iCAAiC;IAChD;;;;;;;;;OASG;IACH,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC;IAEpF;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IAElD;;OAEG;IACH,eAAe,CAAC,EAAE;QAChB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,iBAAiB,GAAG,mBAAmB,KAAK,IAAI,CAAC;QACjF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,mBAAmB,GAAG,kBAAkB,KAAK,IAAI,CAAC;QACxF,2BAA2B,CAAC,EAAE,CAC5B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,iBAAiB,GAAG,mBAAmB,EAChD,QAAQ,EAAE,mBAAmB,GAAG,kBAAkB,KAC/C,IAAI,CAAC;KACX,CAAC;IAEF;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAClG;AAyKD;;;GAGG;AACH,eAAO,MAAM,0BAA0B,EAAkC,CACvE,OAAO,CAAC,EAAE,iCAAiC,KACxC,WAAW,GAAG;IACjB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACpC,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,GAAG,IAAI,CAAC;CAC9C,CAAC;AAOF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAa7D"} | ||
| {"version":3,"file":"httpServerSpansIntegration.d.ts","sourceRoot":"","sources":["../../../../src/integrations/http/httpServerSpansIntegration.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,KAAK,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EAEX,IAAI,EAGL,MAAM,cAAc,CAAC;AActB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAQnD,MAAM,WAAW,iCAAiC;IAChD;;;;;;;;;OASG;IACH,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC;IAEpF;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IAElD;;OAEG;IACH,eAAe,CAAC,EAAE;QAChB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,iBAAiB,GAAG,mBAAmB,KAAK,IAAI,CAAC;QACjF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,mBAAmB,GAAG,kBAAkB,KAAK,IAAI,CAAC;QACxF,2BAA2B,CAAC,EAAE,CAC5B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,iBAAiB,GAAG,mBAAmB,EAChD,QAAQ,EAAE,mBAAmB,GAAG,kBAAkB,KAC/C,IAAI,CAAC;KACX,CAAC;IAEF;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAClG;AAgLD;;;GAGG;AACH,eAAO,MAAM,0BAA0B,EAAkC,CACvE,OAAO,CAAC,EAAE,iCAAiC,KACxC,WAAW,GAAG;IACjB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACpC,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,GAAG,IAAI,CAAC;CAC9C,CAAC;AAOF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAa7D"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../../../src/integrations/modules.ts"],"names":[],"mappings":"AAKA,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AA2CzC;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB;;;;CAAsB,CAAC;AAoEtD,kGAAkG;AAClG,iBAAS,WAAW,IAAI,UAAU,CAKjC"} | ||
| {"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../../../src/integrations/modules.ts"],"names":[],"mappings":"AAIA,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AA2CzC;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB;;;;CAAsB,CAAC;AAsEtD,kGAAkG;AAClG,iBAAS,WAAW,IAAI,UAAU,CAKjC"} |
@@ -1,23 +0,9 @@ | ||
| interface NodeFetchOptions { | ||
| /** | ||
| * Whether breadcrumbs should be recorded for requests. | ||
| * Defaults to true | ||
| */ | ||
| breadcrumbs?: boolean; | ||
| /** | ||
| * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing fetch requests. | ||
| * | ||
| * @default `true` | ||
| */ | ||
| tracePropagation?: boolean; | ||
| /** | ||
| * Do not capture spans or breadcrumbs for outgoing fetch requests to URLs where the given callback returns `true`. | ||
| * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled. | ||
| */ | ||
| ignoreOutgoingRequests?: (url: string) => boolean; | ||
| } | ||
| import type { NodeFetchOptions } from './types'; | ||
| /** | ||
| * Instrument outgoing fetch requests made through the native node `fetch` API. | ||
| * This emits (depending on the integration options) spans and breadcrumbs, as well as injecting trace propagation headers into the request. | ||
| */ | ||
| export declare const nativeNodeFetchIntegration: (options?: NodeFetchOptions | undefined) => import("@sentry/core").Integration & { | ||
| name: "NodeFetch"; | ||
| }; | ||
| export {}; | ||
| //# sourceMappingURL=index.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/integrations/node-fetch/index.ts"],"names":[],"mappings":"AAOA,UAAU,gBAAgB;IACxB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;OAGG;IACH,sBAAsB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;CACnD;AAmBD,eAAO,MAAM,0BAA0B;;CAAiD,CAAC"} | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/integrations/node-fetch/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAYhD;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;CAAiD,CAAC"} |
@@ -38,2 +38,4 @@ import type { InstrumentationConfig } from '@opentelemetry/instrumentation'; | ||
| * https://github.com/open-telemetry/opentelemetry-js-contrib/blob/28e209a9da36bc4e1f8c2b0db7360170ed46cb80/plugins/node/instrumentation-undici/src/undici.ts | ||
| * | ||
| * @deprecated This class is no longer used internally and will be removed in a future major version. Use `nativeNodeFetchIntegration` instead. | ||
| */ | ||
@@ -40,0 +42,0 @@ export declare class SentryNodeFetchInstrumentation extends InstrumentationBase<SentryNodeFetchInstrumentationOptions> { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"SentryNodeFetchInstrumentation.d.ts","sourceRoot":"","sources":["../../../../src/integrations/node-fetch/SentryNodeFetchInstrumentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAWrE,MAAM,MAAM,qCAAqC,GAAG,qBAAqB,GAAG;IAC1E;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;CACnD,CAAC;AAOF;;;;;;;;;GASG;AACH,qBAAa,8BAA+B,SAAQ,mBAAmB,CAAC,qCAAqC,CAAC;IAG5G,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,uBAAuB,CAA0B;IACzD,OAAO,CAAC,0BAA0B,CAAkC;gBAEjD,MAAM,GAAE,qCAA0C;IAOrE,2CAA2C;IACpC,IAAI,IAAI,IAAI;IAInB,mCAAmC;IAC5B,OAAO,IAAI,IAAI;IAMtB,kCAAkC;IAC3B,MAAM,IAAI,IAAI;IAyBrB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAsBzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkB1B,0CAA0C;IAC1C,OAAO,CAAC,mBAAmB;IAwB3B;;OAEG;IACH,OAAO,CAAC,4BAA4B;CAerC"} | ||
| {"version":3,"file":"SentryNodeFetchInstrumentation.d.ts","sourceRoot":"","sources":["../../../../src/integrations/node-fetch/SentryNodeFetchInstrumentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAWrE,MAAM,MAAM,qCAAqC,GAAG,qBAAqB,GAAG;IAC1E;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;CACnD,CAAC;AAOF;;;;;;;;;;;GAWG;AACH,qBAAa,8BAA+B,SAAQ,mBAAmB,CAAC,qCAAqC,CAAC;IAG5G,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,uBAAuB,CAA0B;IACzD,OAAO,CAAC,0BAA0B,CAAkC;gBAEjD,MAAM,GAAE,qCAA0C;IAOrE,2CAA2C;IACpC,IAAI,IAAI,IAAI;IAInB,mCAAmC;IAC5B,OAAO,IAAI,IAAI;IAMtB,kCAAkC;IAC3B,MAAM,IAAI,IAAI;IAyBrB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAsBzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkB1B,0CAA0C;IAC1C,OAAO,CAAC,mBAAmB;IAwB3B;;OAEG;IACH,OAAO,CAAC,4BAA4B;CAerC"} |
@@ -1,5 +0,2 @@ | ||
| /** | ||
| * Aligned with upstream Undici request shape; see `packages/node/.../node-fetch/vendored/types.ts` | ||
| * (vendored from `@opentelemetry/instrumentation-undici`). | ||
| */ | ||
| import type { Span } from '@sentry/core'; | ||
| export interface UndiciRequest { | ||
@@ -11,3 +8,4 @@ origin: string; | ||
| * Serialized string of headers in the form `name: value\r\n` for v5 | ||
| * Array of strings `[key1, value1, ...]` for v6 (values may be `string | string[]`) | ||
| * Array of strings `[key1, value1, key2, value2]`, where values are | ||
| * `string | string[]` for v6 | ||
| */ | ||
@@ -25,3 +23,3 @@ headers: string | (string | string[])[]; | ||
| contentType: string | null; | ||
| body: unknown; | ||
| body: any; | ||
| } | ||
@@ -33,2 +31,68 @@ export interface UndiciResponse { | ||
| } | ||
| export interface RequestHookFunction<T = UndiciRequest> { | ||
| (span: Span, request: T): void; | ||
| } | ||
| export interface ResponseHookFunction<RequestType = UndiciRequest, ResponseType = UndiciResponse> { | ||
| (span: Span, info: { | ||
| request: RequestType; | ||
| response: ResponseType; | ||
| }): void; | ||
| } | ||
| export interface RequestMessage { | ||
| request: UndiciRequest; | ||
| } | ||
| export interface RequestHeadersMessage { | ||
| request: UndiciRequest; | ||
| socket: any; | ||
| } | ||
| export interface ResponseHeadersMessage { | ||
| request: UndiciRequest; | ||
| response: UndiciResponse; | ||
| } | ||
| export interface RequestTrailersMessage { | ||
| request: UndiciRequest; | ||
| response: UndiciResponse; | ||
| } | ||
| export interface RequestErrorMessage { | ||
| request: UndiciRequest; | ||
| error: Error; | ||
| } | ||
| export interface UndiciInstrumentationConfig<RequestType = UndiciRequest, ResponseType = UndiciResponse> { | ||
| /** | ||
| * Do not capture spans or breadcrumbs for outgoing fetch requests to URLs where the given callback returns `true`. | ||
| * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled. | ||
| */ | ||
| ignoreOutgoingRequests?: (url: string) => boolean; | ||
| /** Function for adding custom attributes before request is handled */ | ||
| requestHook?: RequestHookFunction<RequestType>; | ||
| /** Function called once response headers have been received */ | ||
| responseHook?: ResponseHookFunction<RequestType, ResponseType>; | ||
| /** Map the following HTTP headers to span attributes. */ | ||
| headersToSpanAttributes?: { | ||
| requestHeaders?: string[]; | ||
| responseHeaders?: string[]; | ||
| }; | ||
| } | ||
| export interface NodeFetchOptions extends UndiciInstrumentationConfig { | ||
| /** | ||
| * Whether breadcrumbs should be recorded for requests. | ||
| * | ||
| * @default `true` | ||
| */ | ||
| breadcrumbs?: boolean; | ||
| /** | ||
| * If set to false, do not emit any spans. | ||
| * Breadcrumbs and trace propagation for outgoing fetch requests are still applied. | ||
| * | ||
| * If `skipOpenTelemetrySetup: true` is configured, this defaults to `false`, otherwise it defaults to `true`. | ||
| */ | ||
| spans?: boolean; | ||
| /** | ||
| * This option only has an effect when `spans` is set to false. When spans are enabled, you cannot disable trace propagation here. | ||
| * Instead, configure `tracePropagationTargets` in the client options. | ||
| * | ||
| * @default `true` | ||
| */ | ||
| tracePropagation?: boolean; | ||
| } | ||
| //# sourceMappingURL=types.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/integrations/node-fetch/types.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AAEH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC;IACxC;;OAEG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB"} | ||
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/integrations/node-fetch/types.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC;IACxC;;OAEG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B,IAAI,EAAE,GAAG,CAAC;CACX;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,GAAG,aAAa;IACpD,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB,CAAC,WAAW,GAAG,aAAa,EAAE,YAAY,GAAG,cAAc;IAC9F,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;QAAE,OAAO,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,GAAG,IAAI,CAAC;CAC5E;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,aAAa,CAAC;IAEvB,MAAM,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC;CACd;AAID,MAAM,WAAW,2BAA2B,CAAC,WAAW,GAAG,aAAa,EAAE,YAAY,GAAG,cAAc;IACrG;;;OAGG;IACH,sBAAsB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAClD,sEAAsE;IACtE,WAAW,CAAC,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC/C,+DAA+D;IAC/D,YAAY,CAAC,EAAE,oBAAoB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC/D,yDAAyD;IACzD,uBAAuB,CAAC,EAAE;QACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;KAC5B,CAAC;CACH;AAED,MAAM,WAAW,gBAAiB,SAAQ,2BAA2B;IACnE;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../../src/light/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAW,MAAM,cAAc,CAAC;AA6BzD,OAAO,KAAK,EAAqB,WAAW,EAAE,MAAM,UAAU,CAAC;AAI/D,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAI3C;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,WAAW,EAAE,CAuBtD;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,GAAE,WAAW,GAAG,SAAc,GAAG,eAAe,GAAG,SAAS,CAEvF;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,GAAE,WAAW,GAAG,SAAc,GAAG,eAAe,CAErG"} | ||
| {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../../src/light/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAW,MAAM,cAAc,CAAC;AA6BzD,OAAO,KAAK,EAAqB,WAAW,EAAE,MAAM,UAAU,CAAC;AAG/D,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAI3C;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,WAAW,EAAE,CAuBtD;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,GAAE,WAAW,GAAG,SAAc,GAAG,eAAe,GAAG,SAAS,CAEvF;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,GAAE,WAAW,GAAG,SAAc,GAAG,eAAe,CAErG"} |
| import type { Tracer } from '@opentelemetry/api'; | ||
| import type { BasicTracerProvider } from '@opentelemetry/sdk-trace-base'; | ||
| import type { DynamicSamplingContext, Scope, TraceContext } from '@sentry/core'; | ||
| import { ServerRuntimeClient } from '@sentry/core'; | ||
| import { type AsyncLocalStorageLookup } from '@sentry/opentelemetry'; | ||
| import { type AsyncLocalStorageLookup, type OpenTelemetryTracerProvider } from '@sentry/opentelemetry'; | ||
| import type { NodeClientOptions } from '../types'; | ||
| /** A client for using Sentry with Node & OpenTelemetry. */ | ||
| export declare class NodeClient extends ServerRuntimeClient<NodeClientOptions> { | ||
| traceProvider: BasicTracerProvider | undefined; | ||
| traceProvider: OpenTelemetryTracerProvider | undefined; | ||
| asyncLocalStorageLookup: AsyncLocalStorageLookup | undefined; | ||
@@ -11,0 +10,0 @@ private _tracer; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/sdk/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAGjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,sBAAsB,EAAE,KAAK,EAA8B,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5G,OAAO,EAML,mBAAmB,EACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,uBAAuB,EAA2B,MAAM,uBAAuB,CAAC;AAG9F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAIlD,2DAA2D;AAC3D,qBAAa,UAAW,SAAQ,mBAAmB,CAAC,iBAAiB,CAAC;IAC7D,aAAa,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC/C,uBAAuB,EAAE,uBAAuB,GAAG,SAAS,CAAC;IAEpE,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,qBAAqB,CAA6B;IAC1D,OAAO,CAAC,gCAAgC,CAA2B;IACnE,OAAO,CAAC,uBAAuB,CAA2B;gBAEvC,OAAO,EAAE,iBAAiB;IA4C7C,2BAA2B;IAC3B,IAAW,MAAM,IAAI,MAAM,CAW1B;IAED,kBAAkB;IAEL,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC;IAU1D,kBAAkB;IAEL,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC;IAqBtE;;;;;;OAMG;IASI,yBAAyB,IAAI,IAAI;IAkBxC,kBAAkB;IAClB,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAQpC,2EAA2E;IAC3E,SAAS,CAAC,sBAAsB,CAC9B,KAAK,EAAE,KAAK,GAAG,SAAS,GACvB,CAAC,sBAAsB,EAAE,OAAO,CAAC,sBAAsB,CAAC,GAAG,SAAS,EAAE,YAAY,EAAE,YAAY,GAAG,SAAS,CAAC;CAOjH"} | ||
| {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/sdk/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAGjD,OAAO,KAAK,EAAE,sBAAsB,EAAE,KAAK,EAA8B,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5G,OAAO,EAOL,mBAAmB,EACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,uBAAuB,EAE5B,KAAK,2BAA2B,EACjC,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAIlD,2DAA2D;AAC3D,qBAAa,UAAW,SAAQ,mBAAmB,CAAC,iBAAiB,CAAC;IAC7D,aAAa,EAAE,2BAA2B,GAAG,SAAS,CAAC;IACvD,uBAAuB,EAAE,uBAAuB,GAAG,SAAS,CAAC;IAEpE,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,qBAAqB,CAA6B;IAC1D,OAAO,CAAC,gCAAgC,CAA2B;IACnE,OAAO,CAAC,uBAAuB,CAA2B;gBAEvC,OAAO,EAAE,iBAAiB;IAsD7C,2BAA2B;IAC3B,IAAW,MAAM,IAAI,MAAM,CAW1B;IAED,kBAAkB;IAEL,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC;IAU1D,kBAAkB;IAEL,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC;IAqBtE;;;;;;OAMG;IASI,yBAAyB,IAAI,IAAI;IAkBxC,kBAAkB;IAClB,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAQpC,2EAA2E;IAC3E,SAAS,CAAC,sBAAsB,CAC9B,KAAK,EAAE,KAAK,GAAG,SAAS,GACvB,CAAC,sBAAsB,EAAE,OAAO,CAAC,sBAAsB,CAAC,GAAG,SAAS,EAAE,YAAY,EAAE,YAAY,GAAG,SAAS,CAAC;CAOjH"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sdk/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAW,MAAM,cAAc,CAAC;AAsCzD,OAAO,KAAK,EAAqB,WAAW,EAAE,MAAM,UAAU,CAAC;AAI/D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,WAAW,EAAE,CA0BtD;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,GAAE,WAAW,GAAG,SAAc,GAAG,UAAU,GAAG,SAAS,CAElF;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,GAAE,WAAW,GAAG,SAAc,GAAG,UAAU,CAEhG;AAqED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CA0BjD"} | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sdk/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAW,MAAM,cAAc,CAAC;AAsCzD,OAAO,KAAK,EAAqB,WAAW,EAAE,MAAM,UAAU,CAAC;AAG/D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,WAAW,EAAE,CA0BtD;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,GAAE,WAAW,GAAG,SAAc,GAAG,UAAU,GAAG,SAAS,CAElF;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,GAAE,WAAW,GAAG,SAAc,GAAG,UAAU,CAEhG;AA0ED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CA4BjD"} |
@@ -29,4 +29,21 @@ import type { Span as WriteableSpan } from '@opentelemetry/api'; | ||
| * Provide an array of additional OpenTelemetry SpanProcessors that should be registered. | ||
| * | ||
| * Note: providing this forces the full OpenTelemetry SDK `BasicTracerProvider` instead of Sentry's | ||
| * minimal tracer provider, since custom span processors require the SDK span pipeline. See | ||
| * {@link OpenTelemetryServerRuntimeOptions.openTelemetryBasicTracerProvider}. | ||
| */ | ||
| openTelemetrySpanProcessors?: SpanProcessor[]; | ||
| /** | ||
| * By default, the SDK uses Sentry's minimal OpenTelemetry tracer provider, which creates native | ||
| * Sentry spans directly instead of going through the full OpenTelemetry SDK span pipeline. | ||
| * | ||
| * Set this to `true` to use the full OpenTelemetry SDK `BasicTracerProvider` instead, e.g. if you | ||
| * rely on OpenTelemetry SDK features that the minimal provider does not support. | ||
| * | ||
| * Note: providing `openTelemetrySpanProcessors` also forces the full OpenTelemetry SDK provider, | ||
| * since custom span processors require the SDK span pipeline. | ||
| * | ||
| * @default false | ||
| */ | ||
| openTelemetryBasicTracerProvider?: boolean; | ||
| } | ||
@@ -33,0 +50,0 @@ /** |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC/G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEzD;;;;GAIG;AACH,MAAM,WAAW,iCAAkC,SAAQ,oBAAoB;IAC7E;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;OAIG;IACH,6BAA6B,CAAC,EAAE,eAAe,EAAE,CAAC;IAElD;;OAEG;IACH,2BAA2B,CAAC,EAAE,aAAa,EAAE,CAAC;CAC/C;AAED;;;GAGG;AACH,MAAM,WAAW,eAAgB,SAAQ,iCAAiC;IACxE;;;;;OAKG;IACH,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;;;;;;;;;;OAYG;IACH,eAAe,CAAC,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,MAAM,GAAG,OAAO,CAAC;IAEzE;;;OAGG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAElC;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAEtC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,OAAO,CAAC,oBAAoB,CAAC,EAAE,eAAe;CAAG;AAEtF;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa,CAAC,oBAAoB,CAAC,EAAE,eAAe;CAAG;AAElG,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,KAAK,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,YAAY,GAAG,IAAI,CAAC"} | ||
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC/G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEzD;;;;GAIG;AACH,MAAM,WAAW,iCAAkC,SAAQ,oBAAoB;IAC7E;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;OAIG;IACH,6BAA6B,CAAC,EAAE,eAAe,EAAE,CAAC;IAElD;;;;;;OAMG;IACH,2BAA2B,CAAC,EAAE,aAAa,EAAE,CAAC;IAE9C;;;;;;;;;;;OAWG;IACH,gCAAgC,CAAC,EAAE,OAAO,CAAC;CAC5C;AAED;;;GAGG;AACH,MAAM,WAAW,eAAgB,SAAQ,iCAAiC;IACxE;;;;;OAKG;IACH,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;;;;;;;;;;OAYG;IACH,eAAe,CAAC,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,MAAM,GAAG,OAAO,CAAC;IAEzE;;;OAGG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAElC;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAEtC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,OAAO,CAAC,oBAAoB,CAAC,EAAE,eAAe;CAAG;AAEtF;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa,CAAC,oBAAoB,CAAC,EAAE,eAAe;CAAG;AAElG,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,KAAK,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,YAAY,GAAG,IAAI,CAAC"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"createMissingInstrumentationContext.d.ts","sourceRoot":"","sources":["../../../src/utils/createMissingInstrumentationContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAGlE,eAAO,MAAM,mCAAmC,GAAI,KAAK,MAAM,KAAG,6BAGhE,CAAC"} | ||
| {"version":3,"file":"createMissingInstrumentationContext.d.ts","sourceRoot":"","sources":["../../../src/utils/createMissingInstrumentationContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAElE,eAAO,MAAM,mCAAmC,GAAI,KAAK,MAAM,KAAG,6BAajE,CAAC"} |
@@ -1,3 +0,1 @@ | ||
| /** Detect CommonJS. */ | ||
| export declare function isCjs(): boolean; | ||
| /** | ||
@@ -4,0 +2,0 @@ * Check if the current Node.js version supports module.register |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"detection.d.ts","sourceRoot":"","sources":["../../../src/utils/detection.ts"],"names":[],"mappings":"AAGA,uBAAuB;AACvB,wBAAgB,KAAK,IAAI,OAAO,CAQ/B;AAID;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAqBhD"} | ||
| {"version":3,"file":"detection.d.ts","sourceRoot":"","sources":["../../../src/utils/detection.ts"],"names":[],"mappings":"AAeA;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAqBhD"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"ensureIsWrapped.d.ts","sourceRoot":"","sources":["../../../src/utils/ensureIsWrapped.ts"],"names":[],"mappings":"AAcA;;GAEG;AACH,wBAAgB,eAAe,CAC7B,oBAAoB,EAAE,OAAO,EAC7B,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAChE,IAAI,CA2BN"} | ||
| {"version":3,"file":"ensureIsWrapped.d.ts","sourceRoot":"","sources":["../../../src/utils/ensureIsWrapped.ts"],"names":[],"mappings":"AAaA;;GAEG;AACH,wBAAgB,eAAe,CAC7B,oBAAoB,EAAE,OAAO,EAC7B,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAChE,IAAI,CA6BN"} |
@@ -1,2 +0,2 @@ | ||
| import type { LRUMap } from '@sentry/core'; | ||
| import type { LRUMap, Span } from '@sentry/core'; | ||
| import type { UndiciRequest, UndiciResponse } from '../integrations/node-fetch/types'; | ||
@@ -8,4 +8,10 @@ /** | ||
| * then injects sentry-trace, traceparent, and baggage headers. | ||
| * | ||
| * When a `span` is passed (the outgoing `http.client` span), its trace data is propagated so downstream | ||
| * services are parented to that span. Without a span, the active scope's trace data is used. | ||
| * | ||
| * Existing trace headers (e.g. set manually by the user via `getTraceData()`) always take precedence and | ||
| * are de-duplicated rather than overwritten, so we never emit two `sentry-trace`/`baggage` entries. | ||
| */ | ||
| export declare function addTracePropagationHeadersToFetchRequest(request: UndiciRequest, propagationDecisionMap: LRUMap<string, boolean>): void; | ||
| export declare function addTracePropagationHeadersToFetchRequest(request: UndiciRequest, propagationDecisionMap: LRUMap<string, boolean>, span?: Span): void; | ||
| /** Add a breadcrumb for an outgoing fetch/undici request. */ | ||
@@ -12,0 +18,0 @@ export declare function addFetchRequestBreadcrumb(request: UndiciRequest, response: UndiciResponse): void; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"outgoingFetchRequest.d.ts","sourceRoot":"","sources":["../../../src/utils/outgoingFetchRequest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAwB,MAAM,cAAc,CAAC;AAWjE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAKtF;;;;;GAKG;AAEH,wBAAgB,wCAAwC,CACtD,OAAO,EAAE,aAAa,EACtB,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9C,IAAI,CAyEN;AA2GD,6DAA6D;AAC7D,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAsBhG;AAyBD,oDAAoD;AACpD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,MAAY,GAAG,MAAM,CAkBzE"} | ||
| {"version":3,"file":"outgoingFetchRequest.d.ts","sourceRoot":"","sources":["../../../src/utils/outgoingFetchRequest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAwB,IAAI,EAAE,MAAM,cAAc,CAAC;AAYvE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAKtF;;;;;;;;;;;GAWG;AAEH,wBAAgB,wCAAwC,CACtD,OAAO,EAAE,aAAa,EACtB,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/C,IAAI,CAAC,EAAE,IAAI,GACV,IAAI,CAiFN;AA2GD,6DAA6D;AAC7D,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAsBhG;AAyBD,oDAAoD;AACpD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,MAAY,GAAG,MAAM,CAkBzE"} |
+8
-8
| { | ||
| "name": "@sentry/node-core", | ||
| "version": "10.63.0", | ||
| "version": "10.64.0", | ||
| "description": "Sentry Node-Core SDK", | ||
@@ -104,5 +104,5 @@ "repository": "git://github.com/getsentry/sentry-javascript.git", | ||
| "dependencies": { | ||
| "@sentry/conventions": "^0.12.0", | ||
| "@sentry/core": "10.63.0", | ||
| "@sentry/opentelemetry": "10.63.0", | ||
| "@sentry/conventions": "^0.15.1", | ||
| "@sentry/core": "10.64.0", | ||
| "@sentry/opentelemetry": "10.64.0", | ||
| "import-in-the-middle": "^3.0.0" | ||
@@ -112,6 +112,6 @@ }, | ||
| "@opentelemetry/api": "^1.9.1", | ||
| "@opentelemetry/core": "^2.6.1", | ||
| "@opentelemetry/exporter-trace-otlp-http": "^0.214.0", | ||
| "@opentelemetry/instrumentation": "^0.214.0", | ||
| "@opentelemetry/sdk-trace-base": "^2.6.1", | ||
| "@opentelemetry/core": "^2.9.0", | ||
| "@opentelemetry/exporter-trace-otlp-http": "^0.220.0", | ||
| "@opentelemetry/instrumentation": "^0.220.0", | ||
| "@opentelemetry/sdk-trace-base": "^2.9.0", | ||
| "@types/node": "^18.19.1" | ||
@@ -118,0 +118,0 @@ }, |
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Mixed license
LicensePackage contains multiple licenses.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
1742192
5.4%496
1.43%15514
4.56%1
Infinity%229
0.88%+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
Updated
Updated