@glasstrace/sdk 1.1.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/trpc/index.ts","../../../../node_modules/@opentelemetry/api/src/version.ts","../../../../node_modules/@opentelemetry/api/src/internal/semver.ts","../../../../node_modules/@opentelemetry/api/src/internal/global-utils.ts","../../../../node_modules/@opentelemetry/api/src/diag/ComponentLogger.ts","../../../../node_modules/@opentelemetry/api/src/diag/types.ts","../../../../node_modules/@opentelemetry/api/src/diag/internal/logLevelLogger.ts","../../../../node_modules/@opentelemetry/api/src/api/diag.ts","../../../../node_modules/@opentelemetry/api/src/context/context.ts","../../../../node_modules/@opentelemetry/api/src/context/NoopContextManager.ts","../../../../node_modules/@opentelemetry/api/src/api/context.ts","../../../../node_modules/@opentelemetry/api/src/trace/trace_flags.ts","../../../../node_modules/@opentelemetry/api/src/trace/invalid-span-constants.ts","../../../../node_modules/@opentelemetry/api/src/trace/NonRecordingSpan.ts","../../../../node_modules/@opentelemetry/api/src/trace/context-utils.ts","../../../../node_modules/@opentelemetry/api/src/trace/spancontext-utils.ts","../../../../node_modules/@opentelemetry/api/src/trace/NoopTracer.ts","../../../../node_modules/@opentelemetry/api/src/trace/ProxyTracer.ts","../../../../node_modules/@opentelemetry/api/src/trace/NoopTracerProvider.ts","../../../../node_modules/@opentelemetry/api/src/trace/ProxyTracerProvider.ts","../../../../node_modules/@opentelemetry/api/src/trace/status.ts","../../../../node_modules/@opentelemetry/api/src/api/trace.ts","../../../../node_modules/@opentelemetry/api/src/trace-api.ts"],"sourcesContent":["/**\n * tRPC middleware-chain instrumentation for Glasstrace.\n *\n * Subpath: `@glasstrace/sdk/trpc`\n *\n * This module exposes {@link tracedMiddleware}, a thin wrapper that turns\n * a user-supplied tRPC middleware function into a span-emitting middleware\n * function. Each invocation of the wrapped middleware opens a child span\n * (via {@link https://opentelemetry.io/docs/specs/otel/trace/api/#starting-a-new-active-span | tracer.startActiveSpan})\n * under whatever active OTel context the runtime exposes when the tRPC\n * dispatcher calls the middleware. In a typical Next.js / Node HTTP server\n * deployment that active context is the HTTP server span, so middleware\n * spans land as children of the HTTP span automatically — no manual\n * parent plumbing required.\n *\n * The helper does not import the `@trpc/server` runtime; it consumes the\n * middleware function shape structurally so that:\n *\n * 1. Projects that do not use tRPC pay no runtime cost (the subpath is\n * excluded from the root barrel and tree-shakeable on its own).\n * 2. The same helper works against `@trpc/server@^10.0.0` and\n * `@trpc/server@^11.0.0` without two parallel implementations.\n *\n * The wrapped function preserves the user's call-site type (`T`) so that\n * tRPC's procedure-builder context narrowing (e.g., adding a `session`\n * field across `.use()` chains) continues to flow through.\n *\n * Compatibility with the existing `glasstrace.trpc.procedure` URL-derived\n * attribute (DISC-1215, shipped) is by construction: that attribute is\n * attached to the **parent** HTTP span at exporter time, never to a\n * middleware child span. Middleware spans only carry `trpc.path` and\n * `trpc.type` (forwarded from the middleware options) plus whatever\n * caller-supplied attributes the {@link TracedMiddlewareOptions.attributes}\n * field carries.\n *\n * @module @glasstrace/sdk/trpc\n */\n\nimport {\n trace,\n SpanStatusCode,\n type AttributeValue,\n} from \"@opentelemetry/api\";\n\n/**\n * Permissive structural bound for a tRPC middleware function. The shape\n * is the intersection of `@trpc/server@^10` and `@trpc/server@^11`'s\n * middleware signature: an async function taking a single options object\n * and returning a thenable middleware result.\n *\n * The `opts` parameter is typed `any` so any user-narrowed middleware\n * (with strongly-typed `ctx` / `input` / `meta`) is assignable, and the\n * return type is `Promise<unknown>` so both v10's\n * `Promise<MiddlewareResult<...>>` and v11's identically-named result\n * shape (with extra fields) are accepted without import-time coupling\n * to either major version.\n *\n * Exported so consumers can reference it for type-inference assertions\n * (e.g., proving a strongly-typed middleware fits the bound) without\n * having to recreate the structural shape. The runtime contract is\n * fixed by the `@trpc/server` versions in the peer-dependency range.\n */\n// The `any` here is load-bearing: a tighter bound would reject either\n// v10 or v11 middleware shapes, or both, because tRPC narrows `ctx`,\n// `input`, and `meta` to user-supplied types via generics. Capturing\n// `T extends MiddlewareFunction` preserves that narrowing through the\n// wrapper's `: T` return type (see the type-inference fixture in\n// tests/unit/sdk/trpc/traced-middleware-types.test.ts).\n//\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type MiddlewareFunction = (opts: any) => Promise<unknown>;\n\n/**\n * Options for {@link tracedMiddleware}.\n *\n * @example\n * ```ts\n * import { tracedMiddleware } from \"@glasstrace/sdk/trpc\";\n *\n * const isAuthed = t.middleware(\n * tracedMiddleware(\n * { name: \"isAuthed\", attributes: { \"auth.required\": true } },\n * async ({ ctx, next }) => {\n * if (!ctx.session) throw new TRPCError({ code: \"UNAUTHORIZED\" });\n * return next({ ctx: { ...ctx, session: ctx.session } });\n * },\n * ),\n * );\n * ```\n */\nexport interface TracedMiddlewareOptions {\n /**\n * Span name. Required. Used as the OTel span name; appears in trace\n * timelines and is the primary identifier surfaced by enrichment when\n * a middleware step short-circuits (e.g., auth failure).\n *\n * Must be a non-empty string. Names should be stable across runs so\n * enrichment can reason about middleware identity (e.g., \"isAuthed\",\n * \"isPro\"); avoid embedding request data in the name.\n */\n name: string;\n /**\n * Optional attributes attached to the span before the wrapped\n * middleware body runs. Forwarded to OTel as-is via\n * `span.setAttributes(...)`. The SDK does not redact, sanitize, or\n * scan values here — callers must avoid placing tokens, credentials,\n * or other sensitive data in `attributes`.\n *\n * Sensitive request/response data is captured through the gated\n * `glasstrace.error.response_body` path (see DISC-1216), not through\n * this surface.\n */\n attributes?: Record<string, AttributeValue>;\n}\n\n/**\n * Module-level OTel tracer name for the tRPC subpath. Resolves through\n * the global `ProxyTracerProvider` so it inherits whatever provider the\n * SDK has detected or registered (Glasstrace's enriching exporter,\n * Sentry's processor in coexistence mode, Datadog's processor, etc.).\n *\n * Re-resolved on every call site rather than cached at module top-level\n * so that the test harness's `trace.setGlobalTracerProvider` can be\n * picked up after this module is imported. (Caching the tracer at module\n * top-level would race against test harness setup and produce stale\n * no-op spans for the very first test.)\n */\nconst TRACER_NAME = \"@glasstrace/sdk/trpc\";\n\n/**\n * Wrap a tRPC middleware function in an OTel span.\n *\n * Each call to the returned middleware:\n *\n * 1. Opens a span named `options.name` under the active OTel context\n * (typically the HTTP server span). The span inherits `traceId` and\n * parent `spanId` automatically — no manual context plumbing.\n * 2. Sets caller-supplied {@link TracedMiddlewareOptions.attributes}\n * plus `trpc.path` and `trpc.type` (forwarded from the middleware\n * options) on the span before calling the wrapped middleware body.\n * 3. Lets the wrapped middleware run with the new span as the active\n * span (so any `tracer.startActiveSpan` calls inside the body open\n * grandchild spans under the middleware span).\n * 4. On a thrown error: records the exception via `span.recordException`\n * and sets `span.status` to `ERROR` with the error's message; rethrows.\n * 5. On a returned `{ ok: false, error }` middleware result (tRPC's\n * short-circuit shape): sets `span.status` to `ERROR` without\n * `recordException` (no `Error` object to record).\n * 6. On a successful `{ ok: true, ... }` result: leaves the span status\n * as `UNSET` (per OTel instrumentation-library guidance — explicit\n * `OK` here would shadow downstream consumers attempting their own\n * status transitions).\n * 7. Always ends the span (`span.end()`), even on `throw` or `return`.\n *\n * Type-inference: the returned function preserves the input function's\n * type `T`, so tRPC's procedure-builder context narrowing flows through\n * unchanged. See `sdk-trpc.md` §3.3 for the recommended call pattern.\n *\n * @param options - Span name and optional pre-start attributes.\n * @param middleware - The user's tRPC middleware function. Must be\n * structurally compatible with `@trpc/server@^10` or `@trpc/server@^11`.\n * @returns The wrapped middleware function with the same call signature\n * and return type as `middleware`.\n *\n * @example\n * ```ts\n * // trpc.ts — user's project\n * import { initTRPC, TRPCError } from \"@trpc/server\";\n * import { tracedMiddleware } from \"@glasstrace/sdk/trpc\";\n *\n * interface MyContext { session?: { userId: string }; tier?: string }\n * const t = initTRPC.context<MyContext>().create();\n *\n * const isAuthed = t.middleware(\n * tracedMiddleware({ name: \"isAuthed\" }, async ({ ctx, next }) => {\n * if (!ctx.session) throw new TRPCError({ code: \"UNAUTHORIZED\" });\n * return next({ ctx: { ...ctx, session: ctx.session } });\n * }),\n * );\n *\n * const isPro = t.middleware(\n * tracedMiddleware({ name: \"isPro\" }, async ({ ctx, next }) => {\n * if (ctx.tier !== \"pro\") throw new TRPCError({ code: \"FORBIDDEN\" });\n * return next();\n * }),\n * );\n *\n * export const proProcedure = t.procedure.use(isAuthed).use(isPro);\n * ```\n */\nexport function tracedMiddleware<T extends MiddlewareFunction>(\n options: TracedMiddlewareOptions,\n middleware: T,\n): T {\n // Validate the span name eagerly so a mis-typed call site fails at\n // wrapper-construction time (typically at module load) rather than at\n // first request, when the failure is harder to diagnose. The structural\n // bound only enforces shape, not value-level invariants.\n if (typeof options.name !== \"string\" || options.name.length === 0) {\n throw new TypeError(\n \"tracedMiddleware: options.name must be a non-empty string\",\n );\n }\n\n // The wrapped function. Capture `options` and `middleware` lexically;\n // do not read them from `this` since tRPC invokes middleware as a\n // plain function (not a method).\n const wrapped = async (mwOpts: Parameters<T>[0]): Promise<unknown> => {\n const tracer = trace.getTracer(TRACER_NAME);\n return tracer.startActiveSpan(options.name, async (span) => {\n try {\n // Set caller-supplied attributes first so they appear on the\n // span before any internal attribute we add below. Caller-supplied\n // attributes are forwarded as-is — no redaction or scanning (see\n // TracedMiddlewareOptions.attributes JSDoc).\n if (options.attributes) {\n span.setAttributes(options.attributes);\n }\n // Forward the tRPC-provided `path` and `type` so consumers (the\n // enriching exporter, third-party UIs) can correlate the\n // middleware span back to its procedure without joining against\n // the parent HTTP span. Both fields are documented as Tier 2\n // heuristics in `sdk-trpc.md` §4.\n if (mwOpts && typeof mwOpts === \"object\") {\n const path = (mwOpts as { path?: unknown }).path;\n if (typeof path === \"string\") {\n span.setAttribute(\"trpc.path\", path);\n }\n const type = (mwOpts as { type?: unknown }).type;\n if (\n type === \"query\" ||\n type === \"mutation\" ||\n type === \"subscription\"\n ) {\n span.setAttribute(\"trpc.type\", type);\n }\n }\n\n const result = await middleware(mwOpts);\n\n // tRPC's middleware result is a discriminated union:\n // { ok: true, ... } — successful pass-through\n // { ok: false, error, ... } — middleware short-circuited with\n // an explicit error envelope\n //\n // The error envelope is the path users hit when they call\n // `next()` and the next link returns ok:false; from the wrapper's\n // perspective the middleware did not throw, but the request did\n // fail. Mark the span ERROR so the exporter and downstream UIs\n // surface the failure, but do not call `recordException` —\n // there is no `Error` object to record.\n if (\n result !== null &&\n typeof result === \"object\" &&\n (result as { ok?: unknown }).ok === false\n ) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n }\n\n return result;\n } catch (error) {\n // Thrown error path. `recordException` produces an OTel\n // exception event with the error name, message, and stack;\n // `setStatus({ code: ERROR, message })` lets standard OTel UIs\n // display the error message inline with the span.\n //\n // OpenTelemetry's `Span.recordException` accepts only\n // `Exception = string | Error` — a non-Error, non-string\n // throwable (e.g. a plain object, number, or symbol thrown by\n // user code via valid JavaScript) can cause `recordException`\n // to throw, which would otherwise leave the span status UNSET\n // even though the request failed. Normalize the throwable\n // first, then guard `recordException` and `setStatus` in\n // independent try/catch blocks so a failure inside one cannot\n // block the other from running. The user's original `error`\n // value is preserved verbatim for the `throw error` re-raise\n // below — wrapping is purely a span-side normalization.\n const normalized: Error | string =\n error instanceof Error\n ? error\n : typeof error === \"string\"\n ? error\n : new Error(String(error));\n const statusMessage =\n normalized instanceof Error ? normalized.message : normalized;\n try {\n span.recordException(normalized);\n } catch {\n // Swallow — instrumentation must never replace the user's\n // error with its own. The span is still ended in `finally`.\n }\n try {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: statusMessage,\n });\n } catch {\n // Swallow — see comment above. Independent from the\n // recordException try/catch so a failing recordException\n // does not prevent the ERROR status from being recorded.\n }\n throw error;\n } finally {\n // Always end the span. `try/finally` covers both the success\n // and throw paths; the `return result` above happens inside the\n // try, so finally still runs before the value is yielded.\n // Defensively suppress any throw from `span.end()` so a\n // misbehaving OTel impl cannot replace the wrapped middleware's\n // return value (or thrown error) with an unrelated one.\n try {\n span.end();\n } catch {\n // Span lifecycle errors are always non-fatal at this layer.\n }\n }\n });\n };\n\n // The `T` cast preserves the user's function type at the call site\n // even though our wrapper widens parameters to `Parameters<T>[0]` and\n // return to `Promise<unknown>` internally. This is the load-bearing\n // type-inference contract documented in `sdk-trpc.md` §3.3 and\n // verified by `tests/unit/sdk/trpc/traced-middleware-types.test.ts`.\n return wrapped as T;\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// this is autogenerated file, see scripts/version-update.js\nexport const VERSION = '1.9.1';\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { VERSION } from '../version';\n\nconst re = /^(\\d+)\\.(\\d+)\\.(\\d+)(-(.+))?$/;\n\n/**\n * Create a function to test an API version to see if it is compatible with the provided ownVersion.\n *\n * The returned function has the following semantics:\n * - Exact match is always compatible\n * - Major versions must match exactly\n * - 1.x package cannot use global 2.x package\n * - 2.x package cannot use global 1.x package\n * - The minor version of the API module requesting access to the global API must be less than or equal to the minor version of this API\n * - 1.3 package may use 1.4 global because the later global contains all functions 1.3 expects\n * - 1.4 package may NOT use 1.3 global because it may try to call functions which don't exist on 1.3\n * - If the major version is 0, the minor version is treated as the major and the patch is treated as the minor\n * - Patch and build tag differences are not considered at this time\n *\n * @param ownVersion version which should be checked against\n */\nexport function _makeCompatibilityCheck(\n ownVersion: string\n): (globalVersion: string) => boolean {\n const acceptedVersions = new Set<string>([ownVersion]);\n const rejectedVersions = new Set<string>();\n\n const myVersionMatch = ownVersion.match(re);\n if (!myVersionMatch) {\n // we cannot guarantee compatibility so we always return noop\n return () => false;\n }\n\n const ownVersionParsed = {\n major: +myVersionMatch[1],\n minor: +myVersionMatch[2],\n patch: +myVersionMatch[3],\n prerelease: myVersionMatch[4],\n };\n\n // if ownVersion has a prerelease tag, versions must match exactly\n if (ownVersionParsed.prerelease != null) {\n return function isExactmatch(globalVersion: string): boolean {\n return globalVersion === ownVersion;\n };\n }\n\n function _reject(v: string) {\n rejectedVersions.add(v);\n return false;\n }\n\n function _accept(v: string) {\n acceptedVersions.add(v);\n return true;\n }\n\n return function isCompatible(globalVersion: string): boolean {\n if (acceptedVersions.has(globalVersion)) {\n return true;\n }\n\n if (rejectedVersions.has(globalVersion)) {\n return false;\n }\n\n const globalVersionMatch = globalVersion.match(re);\n if (!globalVersionMatch) {\n // cannot parse other version\n // we cannot guarantee compatibility so we always noop\n return _reject(globalVersion);\n }\n\n const globalVersionParsed = {\n major: +globalVersionMatch[1],\n minor: +globalVersionMatch[2],\n patch: +globalVersionMatch[3],\n prerelease: globalVersionMatch[4],\n };\n\n // if globalVersion has a prerelease tag, versions must match exactly\n if (globalVersionParsed.prerelease != null) {\n return _reject(globalVersion);\n }\n\n // major versions must match\n if (ownVersionParsed.major !== globalVersionParsed.major) {\n return _reject(globalVersion);\n }\n\n if (ownVersionParsed.major === 0) {\n if (\n ownVersionParsed.minor === globalVersionParsed.minor &&\n ownVersionParsed.patch <= globalVersionParsed.patch\n ) {\n return _accept(globalVersion);\n }\n\n return _reject(globalVersion);\n }\n\n if (ownVersionParsed.minor <= globalVersionParsed.minor) {\n return _accept(globalVersion);\n }\n\n return _reject(globalVersion);\n };\n}\n\n/**\n * Test an API version to see if it is compatible with this API.\n *\n * - Exact match is always compatible\n * - Major versions must match exactly\n * - 1.x package cannot use global 2.x package\n * - 2.x package cannot use global 1.x package\n * - The minor version of the API module requesting access to the global API must be less than or equal to the minor version of this API\n * - 1.3 package may use 1.4 global because the later global contains all functions 1.3 expects\n * - 1.4 package may NOT use 1.3 global because it may try to call functions which don't exist on 1.3\n * - If the major version is 0, the minor version is treated as the major and the patch is treated as the minor\n * - Patch and build tag differences are not considered at this time\n *\n * @param version version of the API requesting an instance of the global API\n */\nexport const isCompatible = _makeCompatibilityCheck(VERSION);\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { MeterProvider } from '../metrics/MeterProvider';\nimport type { ContextManager } from '../context/types';\nimport type { DiagLogger } from '../diag/types';\nimport type { TextMapPropagator } from '../propagation/TextMapPropagator';\nimport type { TracerProvider } from '../trace/tracer_provider';\nimport { VERSION } from '../version';\nimport { isCompatible } from './semver';\n\nconst major = VERSION.split('.')[0];\nconst GLOBAL_OPENTELEMETRY_API_KEY = Symbol.for(\n `opentelemetry.js.api.${major}`\n);\n\ndeclare const self: unknown;\ndeclare const window: unknown;\ndeclare const global: unknown;\n\nconst _global = (\n typeof globalThis === 'object'\n ? globalThis\n : typeof self === 'object'\n ? self\n : typeof window === 'object'\n ? window\n : typeof global === 'object'\n ? global\n : {}\n) as OTelGlobal;\n\nexport function registerGlobal<Type extends keyof OTelGlobalAPI>(\n type: Type,\n instance: OTelGlobalAPI[Type],\n diag: DiagLogger,\n allowOverride = false\n): boolean {\n const api = (_global[GLOBAL_OPENTELEMETRY_API_KEY] = _global[\n GLOBAL_OPENTELEMETRY_API_KEY\n ] ?? {\n version: VERSION,\n });\n\n if (!allowOverride && api[type]) {\n // already registered an API of this type\n const err = new Error(\n `@opentelemetry/api: Attempted duplicate registration of API: ${type}`\n );\n diag.error(err.stack || err.message);\n return false;\n }\n\n if (api.version !== VERSION) {\n // All registered APIs must be of the same version exactly\n const err = new Error(\n `@opentelemetry/api: Registration of version v${api.version} for ${type} does not match previously registered API v${VERSION}`\n );\n diag.error(err.stack || err.message);\n return false;\n }\n\n api[type] = instance;\n diag.debug(\n `@opentelemetry/api: Registered a global for ${type} v${VERSION}.`\n );\n\n return true;\n}\n\nexport function getGlobal<Type extends keyof OTelGlobalAPI>(\n type: Type\n): OTelGlobalAPI[Type] | undefined {\n const globalVersion = _global[GLOBAL_OPENTELEMETRY_API_KEY]?.version;\n if (!globalVersion || !isCompatible(globalVersion)) {\n return;\n }\n return _global[GLOBAL_OPENTELEMETRY_API_KEY]?.[type];\n}\n\nexport function unregisterGlobal(type: keyof OTelGlobalAPI, diag: DiagLogger) {\n diag.debug(\n `@opentelemetry/api: Unregistering a global for ${type} v${VERSION}.`\n );\n const api = _global[GLOBAL_OPENTELEMETRY_API_KEY];\n\n if (api) {\n delete api[type];\n }\n}\n\ntype OTelGlobal = {\n [GLOBAL_OPENTELEMETRY_API_KEY]?: OTelGlobalAPI;\n};\n\ntype OTelGlobalAPI = {\n version: string;\n\n diag?: DiagLogger;\n trace?: TracerProvider;\n context?: ContextManager;\n metrics?: MeterProvider;\n propagation?: TextMapPropagator;\n};\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { getGlobal } from '../internal/global-utils';\nimport type { ComponentLoggerOptions, DiagLogger } from './types';\n\n/**\n * Component Logger which is meant to be used as part of any component which\n * will add automatically additional namespace in front of the log message.\n * It will then forward all message to global diag logger\n * @example\n * const cLogger = diag.createComponentLogger({ namespace: '@opentelemetry/instrumentation-http' });\n * cLogger.debug('test');\n * // @opentelemetry/instrumentation-http test\n */\nexport class DiagComponentLogger implements DiagLogger {\n private _namespace: string;\n\n constructor(props: ComponentLoggerOptions) {\n this._namespace = props.namespace || 'DiagComponentLogger';\n }\n\n public debug(...args: unknown[]): void {\n return logProxy('debug', this._namespace, args);\n }\n\n public error(...args: unknown[]): void {\n return logProxy('error', this._namespace, args);\n }\n\n public info(...args: unknown[]): void {\n return logProxy('info', this._namespace, args);\n }\n\n public warn(...args: unknown[]): void {\n return logProxy('warn', this._namespace, args);\n }\n\n public verbose(...args: unknown[]): void {\n return logProxy('verbose', this._namespace, args);\n }\n}\n\nfunction logProxy(\n funcName: keyof DiagLogger,\n namespace: string,\n args: unknown[]\n): void {\n const logger = getGlobal('diag');\n // shortcut if logger not set\n if (!logger) {\n return;\n }\n\n return logger[funcName](namespace, ...args);\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @since 1.0.0\n */\nexport type DiagLogFunction = (message: string, ...args: unknown[]) => void;\n\n/**\n * Defines an internal diagnostic logger interface which is used to log internal diagnostic\n * messages, you can set the default diagnostic logger via the {@link DiagAPI} setLogger function.\n * API provided implementations include :-\n * - a No-Op {@link createNoopDiagLogger}\n * - a {@link DiagLogLevel} filtering wrapper {@link createLogLevelDiagLogger}\n * - a general Console {@link DiagConsoleLogger} version.\n *\n * @since 1.0.0\n */\nexport interface DiagLogger {\n /** Log an error scenario that was not expected and caused the requested operation to fail. */\n error: DiagLogFunction;\n\n /**\n * Log a warning scenario to inform the developer of an issues that should be investigated.\n * The requested operation may or may not have succeeded or completed.\n */\n warn: DiagLogFunction;\n\n /**\n * Log a general informational message, this should not affect functionality.\n * This is also the default logging level so this should NOT be used for logging\n * debugging level information.\n */\n info: DiagLogFunction;\n\n /**\n * Log a general debug message that can be useful for identifying a failure.\n * Information logged at this level may include diagnostic details that would\n * help identify a failure scenario.\n * For example: Logging the order of execution of async operations.\n */\n debug: DiagLogFunction;\n\n /**\n * Log a detailed (verbose) trace level logging that can be used to identify failures\n * where debug level logging would be insufficient, this level of tracing can include\n * input and output parameters and as such may include PII information passing through\n * the API. As such it is recommended that this level of tracing should not be enabled\n * in a production environment.\n */\n verbose: DiagLogFunction;\n}\n\n/**\n * Defines the available internal logging levels for the diagnostic logger, the numeric values\n * of the levels are defined to match the original values from the initial LogLevel to avoid\n * compatibility/migration issues for any implementation that assume the numeric ordering.\n */\nexport enum DiagLogLevel {\n /** Diagnostic Logging level setting to disable all logging (except and forced logs) */\n NONE = 0,\n\n /** Identifies an error scenario */\n ERROR = 30,\n\n /** Identifies a warning scenario */\n WARN = 50,\n\n /** General informational log message */\n INFO = 60,\n\n /** General debug log message */\n DEBUG = 70,\n\n /**\n * Detailed trace level logging should only be used for development, should only be set\n * in a development environment.\n */\n VERBOSE = 80,\n\n /** Used to set the logging level to include all logging */\n ALL = 9999,\n}\n\n/**\n * Defines options for ComponentLogger\n *\n * @since 1.0.0\n */\nexport interface ComponentLoggerOptions {\n namespace: string;\n}\n\n/**\n * @since 1.4.1\n */\nexport interface DiagLoggerOptions {\n /**\n * The {@link DiagLogLevel} used to filter logs sent to the logger.\n *\n * @defaultValue DiagLogLevel.INFO\n */\n logLevel?: DiagLogLevel;\n\n /**\n * Setting this value to `true` will suppress the warning message normally emitted when registering a logger when another logger is already registered.\n */\n suppressOverrideMessage?: boolean;\n}\n\nexport interface DiagLoggerApi {\n /**\n * Set the global DiagLogger and DiagLogLevel.\n * If a global diag logger is already set, this will override it.\n *\n * @param logger - The {@link DiagLogger} instance to set as the default logger.\n * @param options - A {@link DiagLoggerOptions} object. If not provided, default values will be set.\n * @returns `true` if the logger was successfully registered, else `false`\n */\n setLogger(logger: DiagLogger, options?: DiagLoggerOptions): boolean;\n\n /**\n *\n * @param logger - The {@link DiagLogger} instance to set as the default logger.\n * @param logLevel - The {@link DiagLogLevel} used to filter logs sent to the logger. If not provided it will default to {@link DiagLogLevel.INFO}.\n * @returns `true` if the logger was successfully registered, else `false`\n */\n setLogger(logger: DiagLogger, logLevel?: DiagLogLevel): boolean;\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { DiagLogFunction, DiagLogger } from '../types';\nimport { DiagLogLevel } from '../types';\n\nexport function createLogLevelDiagLogger(\n maxLevel: DiagLogLevel,\n logger: DiagLogger\n): DiagLogger {\n if (maxLevel < DiagLogLevel.NONE) {\n maxLevel = DiagLogLevel.NONE;\n } else if (maxLevel > DiagLogLevel.ALL) {\n maxLevel = DiagLogLevel.ALL;\n }\n\n // In case the logger is null or undefined\n logger = logger || {};\n\n function _filterFunc(\n funcName: keyof DiagLogger,\n theLevel: DiagLogLevel\n ): DiagLogFunction {\n const theFunc = logger[funcName];\n\n if (typeof theFunc === 'function' && maxLevel >= theLevel) {\n return theFunc.bind(logger);\n }\n return function () {};\n }\n\n return {\n error: _filterFunc('error', DiagLogLevel.ERROR),\n warn: _filterFunc('warn', DiagLogLevel.WARN),\n info: _filterFunc('info', DiagLogLevel.INFO),\n debug: _filterFunc('debug', DiagLogLevel.DEBUG),\n verbose: _filterFunc('verbose', DiagLogLevel.VERBOSE),\n };\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { DiagComponentLogger } from '../diag/ComponentLogger';\nimport { createLogLevelDiagLogger } from '../diag/internal/logLevelLogger';\nimport type {\n ComponentLoggerOptions,\n DiagLogFunction,\n DiagLogger,\n DiagLoggerApi,\n} from '../diag/types';\nimport { DiagLogLevel } from '../diag/types';\nimport {\n getGlobal,\n registerGlobal,\n unregisterGlobal,\n} from '../internal/global-utils';\n\nconst API_NAME = 'diag';\n\n/**\n * Singleton object which represents the entry point to the OpenTelemetry internal\n * diagnostic API\n *\n * @since 1.0.0\n */\nexport class DiagAPI implements DiagLogger, DiagLoggerApi {\n private static _instance?: DiagAPI;\n\n /** Get the singleton instance of the DiagAPI API */\n public static instance(): DiagAPI {\n if (!this._instance) {\n this._instance = new DiagAPI();\n }\n\n return this._instance;\n }\n\n /**\n * Private internal constructor\n * @private\n */\n private constructor() {\n function _logProxy(funcName: keyof DiagLogger): DiagLogFunction {\n return function (...args) {\n const logger = getGlobal('diag');\n // shortcut if logger not set\n if (!logger) return;\n return logger[funcName](...args);\n };\n }\n\n // Using self local variable for minification purposes as 'this' cannot be minified\n const self = this;\n\n // DiagAPI specific functions\n\n const setLogger: DiagLoggerApi['setLogger'] = (\n logger,\n optionsOrLogLevel = { logLevel: DiagLogLevel.INFO }\n ) => {\n if (logger === self) {\n // There isn't much we can do here.\n // Logging to the console might break the user application.\n // Try to log to self. If a logger was previously registered it will receive the log.\n const err = new Error(\n 'Cannot use diag as the logger for itself. Please use a DiagLogger implementation like ConsoleDiagLogger or a custom implementation'\n );\n self.error(err.stack ?? err.message);\n return false;\n }\n\n if (typeof optionsOrLogLevel === 'number') {\n optionsOrLogLevel = {\n logLevel: optionsOrLogLevel,\n };\n }\n\n const oldLogger = getGlobal('diag');\n const newLogger = createLogLevelDiagLogger(\n optionsOrLogLevel.logLevel ?? DiagLogLevel.INFO,\n logger\n );\n // There already is an logger registered. We'll let it know before overwriting it.\n if (oldLogger && !optionsOrLogLevel.suppressOverrideMessage) {\n const stack = new Error().stack ?? '<failed to generate stacktrace>';\n oldLogger.warn(`Current logger will be overwritten from ${stack}`);\n newLogger.warn(\n `Current logger will overwrite one already registered from ${stack}`\n );\n }\n\n return registerGlobal('diag', newLogger, self, true);\n };\n\n self.setLogger = setLogger;\n\n self.disable = () => {\n unregisterGlobal(API_NAME, self);\n };\n\n self.createComponentLogger = (options: ComponentLoggerOptions) => {\n return new DiagComponentLogger(options);\n };\n\n self.verbose = _logProxy('verbose');\n self.debug = _logProxy('debug');\n self.info = _logProxy('info');\n self.warn = _logProxy('warn');\n self.error = _logProxy('error');\n }\n\n public setLogger!: DiagLoggerApi['setLogger'];\n /**\n *\n */\n public createComponentLogger!: (\n options: ComponentLoggerOptions\n ) => DiagLogger;\n\n // DiagLogger implementation\n public verbose!: DiagLogFunction;\n public debug!: DiagLogFunction;\n public info!: DiagLogFunction;\n public warn!: DiagLogFunction;\n public error!: DiagLogFunction;\n\n /**\n * Unregister the global logger and return to Noop\n */\n public disable!: () => void;\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Context } from './types';\n\n/**\n * Get a key to uniquely identify a context value\n *\n * @since 1.0.0\n */\nexport function createContextKey(description: string) {\n // The specification states that for the same input, multiple calls should\n // return different keys. Due to the nature of the JS dependency management\n // system, this creates problems where multiple versions of some package\n // could hold different keys for the same property.\n //\n // Therefore, we use Symbol.for which returns the same key for the same input.\n return Symbol.for(description);\n}\n\nclass BaseContext implements Context {\n private _currentContext!: Map<symbol, unknown>;\n\n /**\n * Construct a new context which inherits values from an optional parent context.\n *\n * @param parentContext a context from which to inherit values\n */\n constructor(parentContext?: Map<symbol, unknown>) {\n // for minification\n const self = this;\n\n self._currentContext = parentContext ? new Map(parentContext) : new Map();\n\n self.getValue = (key: symbol) => self._currentContext.get(key);\n\n self.setValue = (key: symbol, value: unknown): Context => {\n const context = new BaseContext(self._currentContext);\n context._currentContext.set(key, value);\n return context;\n };\n\n self.deleteValue = (key: symbol): Context => {\n const context = new BaseContext(self._currentContext);\n context._currentContext.delete(key);\n return context;\n };\n }\n\n /**\n * Get a value from the context.\n *\n * @param key key which identifies a context value\n */\n public getValue!: (key: symbol) => unknown;\n\n /**\n * Create a new context which inherits from this context and has\n * the given key set to the given value.\n *\n * @param key context key for which to set the value\n * @param value value to set for the given key\n */\n public setValue!: (key: symbol, value: unknown) => Context;\n\n /**\n * Return a new context which inherits from this context but does\n * not contain a value for the given key.\n *\n * @param key context key for which to clear a value\n */\n public deleteValue!: (key: symbol) => Context;\n}\n\n/**\n * The root context is used as the default parent context when there is no active context\n *\n * @since 1.0.0\n */\nexport const ROOT_CONTEXT: Context = new BaseContext();\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { ROOT_CONTEXT } from './context';\nimport type * as types from './types';\n\nexport class NoopContextManager implements types.ContextManager {\n active(): types.Context {\n return ROOT_CONTEXT;\n }\n\n with<A extends unknown[], F extends (...args: A) => ReturnType<F>>(\n _context: types.Context,\n fn: F,\n thisArg?: ThisParameterType<F>,\n ...args: A\n ): ReturnType<F> {\n return fn.call(thisArg, ...args);\n }\n\n bind<T>(_context: types.Context, target: T): T {\n return target;\n }\n\n enable(): this {\n return this;\n }\n\n disable(): this {\n return this;\n }\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { NoopContextManager } from '../context/NoopContextManager';\nimport type { Context, ContextManager } from '../context/types';\nimport {\n getGlobal,\n registerGlobal,\n unregisterGlobal,\n} from '../internal/global-utils';\nimport { DiagAPI } from './diag';\n\nconst API_NAME = 'context';\nconst NOOP_CONTEXT_MANAGER = new NoopContextManager();\n\n/**\n * Singleton object which represents the entry point to the OpenTelemetry Context API\n *\n * @since 1.0.0\n */\nexport class ContextAPI {\n private static _instance?: ContextAPI;\n\n /** Empty private constructor prevents end users from constructing a new instance of the API */\n private constructor() {}\n\n /** Get the singleton instance of the Context API */\n public static getInstance(): ContextAPI {\n if (!this._instance) {\n this._instance = new ContextAPI();\n }\n\n return this._instance;\n }\n\n /**\n * Set the current context manager.\n *\n * @returns true if the context manager was successfully registered, else false\n */\n public setGlobalContextManager(contextManager: ContextManager): boolean {\n return registerGlobal(API_NAME, contextManager, DiagAPI.instance());\n }\n\n /**\n * Get the currently active context\n */\n public active(): Context {\n return this._getContextManager().active();\n }\n\n /**\n * Execute a function with an active context\n *\n * @param context context to be active during function execution\n * @param fn function to execute in a context\n * @param thisArg optional receiver to be used for calling fn\n * @param args optional arguments forwarded to fn\n */\n public with<A extends unknown[], F extends (...args: A) => ReturnType<F>>(\n context: Context,\n fn: F,\n thisArg?: ThisParameterType<F>,\n ...args: A\n ): ReturnType<F> {\n return this._getContextManager().with(context, fn, thisArg, ...args);\n }\n\n /**\n * Bind a context to a target function or event emitter\n *\n * @param context context to bind to the event emitter or function. Defaults to the currently active context\n * @param target function or event emitter to bind\n */\n public bind<T>(context: Context, target: T): T {\n return this._getContextManager().bind(context, target);\n }\n\n private _getContextManager(): ContextManager {\n return getGlobal(API_NAME) || NOOP_CONTEXT_MANAGER;\n }\n\n /** Disable and remove the global context manager */\n public disable() {\n this._getContextManager().disable();\n unregisterGlobal(API_NAME, DiagAPI.instance());\n }\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * @since 1.0.0\n */\nexport enum TraceFlags {\n /** Represents no flag set. */\n NONE = 0x0,\n /** Bit to represent whether trace is sampled in trace flags. */\n SAMPLED = 0x1 << 0,\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { SpanContext } from './span_context';\nimport { TraceFlags } from './trace_flags';\n\n/**\n * @since 1.0.0\n */\nexport const INVALID_SPANID = '0000000000000000';\n\n/**\n * @since 1.0.0\n */\nexport const INVALID_TRACEID = '00000000000000000000000000000000';\n\n/**\n * @since 1.0.0\n */\nexport const INVALID_SPAN_CONTEXT: SpanContext = {\n traceId: INVALID_TRACEID,\n spanId: INVALID_SPANID,\n traceFlags: TraceFlags.NONE,\n};\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Exception } from '../common/Exception';\nimport type { TimeInput } from '../common/Time';\nimport type { SpanAttributes } from './attributes';\nimport { INVALID_SPAN_CONTEXT } from './invalid-span-constants';\nimport type { Span } from './span';\nimport type { SpanContext } from './span_context';\nimport type { SpanStatus } from './status';\nimport type { Link } from './link';\n\n/**\n * The NonRecordingSpan is the default {@link Span} that is used when no Span\n * implementation is available. All operations are no-op including context\n * propagation.\n */\nexport class NonRecordingSpan implements Span {\n private readonly _spanContext: SpanContext;\n\n constructor(spanContext: SpanContext = INVALID_SPAN_CONTEXT) {\n this._spanContext = spanContext;\n }\n\n // Returns a SpanContext.\n spanContext(): SpanContext {\n return this._spanContext;\n }\n\n // By default does nothing\n setAttribute(_key: string, _value: unknown): this {\n return this;\n }\n\n // By default does nothing\n setAttributes(_attributes: SpanAttributes): this {\n return this;\n }\n\n // By default does nothing\n addEvent(_name: string, _attributes?: SpanAttributes): this {\n return this;\n }\n\n addLink(_link: Link): this {\n return this;\n }\n\n addLinks(_links: Link[]): this {\n return this;\n }\n\n // By default does nothing\n setStatus(_status: SpanStatus): this {\n return this;\n }\n\n // By default does nothing\n updateName(_name: string): this {\n return this;\n }\n\n // By default does nothing\n end(_endTime?: TimeInput): void {}\n\n // isRecording always returns false for NonRecordingSpan.\n isRecording(): boolean {\n return false;\n }\n\n // By default does nothing\n recordException(_exception: Exception, _time?: TimeInput): void {}\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createContextKey } from '../context/context';\nimport type { Context } from '../context/types';\nimport type { Span } from './span';\nimport type { SpanContext } from './span_context';\nimport { NonRecordingSpan } from './NonRecordingSpan';\nimport { ContextAPI } from '../api/context';\n\n/**\n * span key\n */\nconst SPAN_KEY = createContextKey('OpenTelemetry Context Key SPAN');\n\n/**\n * Return the span if one exists\n *\n * @param context context to get span from\n */\nexport function getSpan(context: Context): Span | undefined {\n return (context.getValue(SPAN_KEY) as Span) || undefined;\n}\n\n/**\n * Gets the span from the current context, if one exists.\n */\nexport function getActiveSpan(): Span | undefined {\n return getSpan(ContextAPI.getInstance().active());\n}\n\n/**\n * Set the span on a context\n *\n * @param context context to use as parent\n * @param span span to set active\n */\nexport function setSpan(context: Context, span: Span): Context {\n return context.setValue(SPAN_KEY, span);\n}\n\n/**\n * Remove current span stored in the context\n *\n * @param context context to delete span from\n */\nexport function deleteSpan(context: Context): Context {\n return context.deleteValue(SPAN_KEY);\n}\n\n/**\n * Wrap span context in a NoopSpan and set as span in a new\n * context\n *\n * @param context context to set active span on\n * @param spanContext span context to be wrapped\n */\nexport function setSpanContext(\n context: Context,\n spanContext: SpanContext\n): Context {\n return setSpan(context, new NonRecordingSpan(spanContext));\n}\n\n/**\n * Get the span context of the span if it exists.\n *\n * @param context context to get values from\n */\nexport function getSpanContext(context: Context): SpanContext | undefined {\n return getSpan(context)?.spanContext();\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { INVALID_SPANID, INVALID_TRACEID } from './invalid-span-constants';\nimport { NonRecordingSpan } from './NonRecordingSpan';\nimport type { Span } from './span';\nimport type { SpanContext } from './span_context';\n\n// Valid characters (0-9, a-f, A-F) are marked as 1.\nconst isHex = new Uint8Array([\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,\n 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,\n]);\n\nfunction isValidHex(id: string, length: number): boolean {\n // As of 1.9.0 the id was allowed to be a non-string value,\n // even though it was not possible in the types.\n if (typeof id !== 'string' || id.length !== length) return false;\n\n let r = 0;\n for (let i = 0; i < id.length; i += 4) {\n r +=\n (isHex[id.charCodeAt(i)] | 0) +\n (isHex[id.charCodeAt(i + 1)] | 0) +\n (isHex[id.charCodeAt(i + 2)] | 0) +\n (isHex[id.charCodeAt(i + 3)] | 0);\n }\n\n return r === length;\n}\n\n/**\n * @since 1.0.0\n */\nexport function isValidTraceId(traceId: string): boolean {\n return isValidHex(traceId, 32) && traceId !== INVALID_TRACEID;\n}\n\n/**\n * @since 1.0.0\n */\nexport function isValidSpanId(spanId: string): boolean {\n return isValidHex(spanId, 16) && spanId !== INVALID_SPANID;\n}\n\n/**\n * Returns true if this {@link SpanContext} is valid.\n * @return true if this {@link SpanContext} is valid.\n *\n * @since 1.0.0\n */\nexport function isSpanContextValid(spanContext: SpanContext): boolean {\n return (\n isValidTraceId(spanContext.traceId) && isValidSpanId(spanContext.spanId)\n );\n}\n\n/**\n * Wrap the given {@link SpanContext} in a new non-recording {@link Span}\n *\n * @param spanContext span context to be wrapped\n * @returns a new non-recording {@link Span} with the provided context\n */\nexport function wrapSpanContext(spanContext: SpanContext): Span {\n return new NonRecordingSpan(spanContext);\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { ContextAPI } from '../api/context';\nimport type { Context } from '../context/types';\nimport { getSpanContext, setSpan } from '../trace/context-utils';\nimport { NonRecordingSpan } from './NonRecordingSpan';\nimport type { Span } from './span';\nimport { isSpanContextValid } from './spancontext-utils';\nimport type { SpanOptions } from './SpanOptions';\nimport type { SpanContext } from './span_context';\nimport type { Tracer } from './tracer';\n\nconst contextApi = ContextAPI.getInstance();\n\n/**\n * No-op implementations of {@link Tracer}.\n */\nexport class NoopTracer implements Tracer {\n // startSpan starts a noop span.\n startSpan(\n name: string,\n options?: SpanOptions,\n context = contextApi.active()\n ): Span {\n const root = Boolean(options?.root);\n if (root) {\n return new NonRecordingSpan();\n }\n\n const parentFromContext = context && getSpanContext(context);\n\n if (\n isSpanContext(parentFromContext) &&\n isSpanContextValid(parentFromContext)\n ) {\n return new NonRecordingSpan(parentFromContext);\n } else {\n return new NonRecordingSpan();\n }\n }\n\n startActiveSpan<F extends (span: Span) => ReturnType<F>>(\n name: string,\n fn: F\n ): ReturnType<F>;\n startActiveSpan<F extends (span: Span) => ReturnType<F>>(\n name: string,\n opts: SpanOptions | undefined,\n fn: F\n ): ReturnType<F>;\n startActiveSpan<F extends (span: Span) => ReturnType<F>>(\n name: string,\n opts: SpanOptions | undefined,\n ctx: Context | undefined,\n fn: F\n ): ReturnType<F>;\n startActiveSpan<F extends (span: Span) => ReturnType<F>>(\n name: string,\n arg2?: F | SpanOptions,\n arg3?: F | Context,\n arg4?: F\n ): ReturnType<F> | undefined {\n let opts: SpanOptions | undefined;\n let ctx: Context | undefined;\n let fn: F;\n\n if (arguments.length < 2) {\n return;\n } else if (arguments.length === 2) {\n fn = arg2 as F;\n } else if (arguments.length === 3) {\n opts = arg2 as SpanOptions | undefined;\n fn = arg3 as F;\n } else {\n opts = arg2 as SpanOptions | undefined;\n ctx = arg3 as Context | undefined;\n fn = arg4 as F;\n }\n\n const parentContext = ctx ?? contextApi.active();\n const span = this.startSpan(name, opts, parentContext);\n const contextWithSpanSet = setSpan(parentContext, span);\n\n return contextApi.with(contextWithSpanSet, fn, undefined, span);\n }\n}\n\nfunction isSpanContext(spanContext: unknown): spanContext is SpanContext {\n return (\n spanContext !== null &&\n typeof spanContext === 'object' &&\n 'spanId' in spanContext &&\n typeof spanContext['spanId'] === 'string' &&\n 'traceId' in spanContext &&\n typeof spanContext['traceId'] === 'string' &&\n 'traceFlags' in spanContext &&\n typeof spanContext['traceFlags'] === 'number'\n );\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Context } from '../context/types';\nimport { NoopTracer } from './NoopTracer';\nimport type { Span } from './span';\nimport type { SpanOptions } from './SpanOptions';\nimport type { Tracer } from './tracer';\nimport type { TracerOptions } from './tracer_options';\n\nconst NOOP_TRACER = new NoopTracer();\n\n/**\n * Proxy tracer provided by the proxy tracer provider\n *\n * @since 1.0.0\n */\nexport class ProxyTracer implements Tracer {\n // When a real implementation is provided, this will be it\n private _delegate?: Tracer;\n private _provider: TracerDelegator;\n public readonly name: string;\n public readonly version?: string;\n public readonly options?: TracerOptions;\n\n constructor(\n provider: TracerDelegator,\n name: string,\n version?: string,\n options?: TracerOptions\n ) {\n this._provider = provider;\n this.name = name;\n this.version = version;\n this.options = options;\n }\n\n startSpan(name: string, options?: SpanOptions, context?: Context): Span {\n return this._getTracer().startSpan(name, options, context);\n }\n\n startActiveSpan<F extends (span: Span) => unknown>(\n _name: string,\n _options: F | SpanOptions,\n _context?: F | Context,\n _fn?: F\n ): ReturnType<F> {\n const tracer = this._getTracer();\n return Reflect.apply(tracer.startActiveSpan, tracer, arguments);\n }\n\n /**\n * Try to get a tracer from the proxy tracer provider.\n * If the proxy tracer provider has no delegate, return a noop tracer.\n */\n private _getTracer() {\n if (this._delegate) {\n return this._delegate;\n }\n\n const tracer = this._provider.getDelegateTracer(\n this.name,\n this.version,\n this.options\n );\n\n if (!tracer) {\n return NOOP_TRACER;\n }\n\n this._delegate = tracer;\n return this._delegate;\n }\n}\n\n/**\n * @since 1.0.3\n */\nexport interface TracerDelegator {\n getDelegateTracer(\n name: string,\n version?: string,\n options?: TracerOptions\n ): Tracer | undefined;\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { NoopTracer } from './NoopTracer';\nimport type { Tracer } from './tracer';\nimport type { TracerOptions } from './tracer_options';\nimport type { TracerProvider } from './tracer_provider';\n\n/**\n * An implementation of the {@link TracerProvider} which returns an impotent\n * Tracer for all calls to `getTracer`.\n *\n * All operations are no-op.\n */\nexport class NoopTracerProvider implements TracerProvider {\n getTracer(\n _name?: string,\n _version?: string,\n _options?: TracerOptions\n ): Tracer {\n return new NoopTracer();\n }\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Tracer } from './tracer';\nimport type { TracerProvider } from './tracer_provider';\nimport { ProxyTracer } from './ProxyTracer';\nimport { NoopTracerProvider } from './NoopTracerProvider';\nimport type { TracerOptions } from './tracer_options';\n\nconst NOOP_TRACER_PROVIDER = new NoopTracerProvider();\n\n/**\n * Tracer provider which provides {@link ProxyTracer}s.\n *\n * Before a delegate is set, tracers provided are NoOp.\n * When a delegate is set, traces are provided from the delegate.\n * When a delegate is set after tracers have already been provided,\n * all tracers already provided will use the provided delegate implementation.\n *\n * @deprecated This will be removed in the next major version.\n * @since 1.0.0\n */\nexport class ProxyTracerProvider implements TracerProvider {\n private _delegate?: TracerProvider;\n\n /**\n * Get a {@link ProxyTracer}\n */\n getTracer(name: string, version?: string, options?: TracerOptions): Tracer {\n return (\n this.getDelegateTracer(name, version, options) ??\n new ProxyTracer(this, name, version, options)\n );\n }\n\n getDelegate(): TracerProvider {\n return this._delegate ?? NOOP_TRACER_PROVIDER;\n }\n\n /**\n * Set the delegate tracer provider\n */\n setDelegate(delegate: TracerProvider) {\n this._delegate = delegate;\n }\n\n getDelegateTracer(\n name: string,\n version?: string,\n options?: TracerOptions\n ): Tracer | undefined {\n return this._delegate?.getTracer(name, version, options);\n }\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @since 1.0.0\n */\nexport interface SpanStatus {\n /** The status code of this message. */\n code: SpanStatusCode;\n /** A developer-facing error message. */\n message?: string;\n}\n\n/**\n * An enumeration of status codes.\n *\n * @since 1.0.0\n */\nexport enum SpanStatusCode {\n /**\n * The default status.\n */\n UNSET = 0,\n /**\n * The operation has been validated by an Application developer or\n * Operator to have completed successfully.\n */\n OK = 1,\n /**\n * The operation contains an error.\n */\n ERROR = 2,\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n getGlobal,\n registerGlobal,\n unregisterGlobal,\n} from '../internal/global-utils';\nimport { ProxyTracerProvider } from '../trace/ProxyTracerProvider';\nimport {\n isSpanContextValid,\n wrapSpanContext,\n} from '../trace/spancontext-utils';\nimport type { Tracer } from '../trace/tracer';\nimport type { TracerProvider } from '../trace/tracer_provider';\nimport {\n deleteSpan,\n getActiveSpan,\n getSpan,\n getSpanContext,\n setSpan,\n setSpanContext,\n} from '../trace/context-utils';\nimport { DiagAPI } from './diag';\n\nconst API_NAME = 'trace';\n\n/**\n * Singleton object which represents the entry point to the OpenTelemetry Tracing API\n *\n * @since 1.0.0\n */\nexport class TraceAPI {\n private static _instance?: TraceAPI;\n\n private _proxyTracerProvider = new ProxyTracerProvider();\n\n /** Empty private constructor prevents end users from constructing a new instance of the API */\n private constructor() {}\n\n /** Get the singleton instance of the Trace API */\n public static getInstance(): TraceAPI {\n if (!this._instance) {\n this._instance = new TraceAPI();\n }\n\n return this._instance;\n }\n\n /**\n * Set the current global tracer.\n *\n * @returns true if the tracer provider was successfully registered, else false\n */\n public setGlobalTracerProvider(provider: TracerProvider): boolean {\n const success = registerGlobal(\n API_NAME,\n this._proxyTracerProvider,\n DiagAPI.instance()\n );\n if (success) {\n this._proxyTracerProvider.setDelegate(provider);\n }\n return success;\n }\n\n /**\n * Returns the global tracer provider.\n */\n public getTracerProvider(): TracerProvider {\n return getGlobal(API_NAME) || this._proxyTracerProvider;\n }\n\n /**\n * Returns a tracer from the global tracer provider.\n */\n public getTracer(name: string, version?: string): Tracer {\n return this.getTracerProvider().getTracer(name, version);\n }\n\n /** Remove the global tracer provider */\n public disable() {\n unregisterGlobal(API_NAME, DiagAPI.instance());\n this._proxyTracerProvider = new ProxyTracerProvider();\n }\n\n public wrapSpanContext = wrapSpanContext;\n\n public isSpanContextValid = isSpanContextValid;\n\n public deleteSpan = deleteSpan;\n\n public getSpan = getSpan;\n\n public getActiveSpan = getActiveSpan;\n\n public getSpanContext = getSpanContext;\n\n public setSpan = setSpan;\n\n public setSpanContext = setSpanContext;\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Split module-level variable definition into separate files to allow\n// tree-shaking on each api instance.\nimport { TraceAPI } from './api/trace';\n\n/**\n * Entrypoint for trace API\n *\n * @since 1.0.0\n */\nexport const trace = TraceAPI.getInstance();\n"],"mappings":"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","names":["isCompatible","DiagLogLevel","self","self","API_NAME","TraceFlags","SpanStatusCode","API_NAME"]}
@@ -0,0 +1,165 @@
1
+ import { AttributeValue } from './common/Attributes';
2
+
3
+ /**
4
+ * tRPC middleware-chain instrumentation for Glasstrace.
5
+ *
6
+ * Subpath: `@glasstrace/sdk/trpc`
7
+ *
8
+ * This module exposes {@link tracedMiddleware}, a thin wrapper that turns
9
+ * a user-supplied tRPC middleware function into a span-emitting middleware
10
+ * function. Each invocation of the wrapped middleware opens a child span
11
+ * (via {@link https://opentelemetry.io/docs/specs/otel/trace/api/#starting-a-new-active-span | tracer.startActiveSpan})
12
+ * under whatever active OTel context the runtime exposes when the tRPC
13
+ * dispatcher calls the middleware. In a typical Next.js / Node HTTP server
14
+ * deployment that active context is the HTTP server span, so middleware
15
+ * spans land as children of the HTTP span automatically — no manual
16
+ * parent plumbing required.
17
+ *
18
+ * The helper does not import the `@trpc/server` runtime; it consumes the
19
+ * middleware function shape structurally so that:
20
+ *
21
+ * 1. Projects that do not use tRPC pay no runtime cost (the subpath is
22
+ * excluded from the root barrel and tree-shakeable on its own).
23
+ * 2. The same helper works against `@trpc/server@^10.0.0` and
24
+ * `@trpc/server@^11.0.0` without two parallel implementations.
25
+ *
26
+ * The wrapped function preserves the user's call-site type (`T`) so that
27
+ * tRPC's procedure-builder context narrowing (e.g., adding a `session`
28
+ * field across `.use()` chains) continues to flow through.
29
+ *
30
+ * Compatibility with the existing `glasstrace.trpc.procedure` URL-derived
31
+ * attribute (DISC-1215, shipped) is by construction: that attribute is
32
+ * attached to the **parent** HTTP span at exporter time, never to a
33
+ * middleware child span. Middleware spans only carry `trpc.path` and
34
+ * `trpc.type` (forwarded from the middleware options) plus whatever
35
+ * caller-supplied attributes the {@link TracedMiddlewareOptions.attributes}
36
+ * field carries.
37
+ *
38
+ * @module @glasstrace/sdk/trpc
39
+ */
40
+
41
+ /**
42
+ * Permissive structural bound for a tRPC middleware function. The shape
43
+ * is the intersection of `@trpc/server@^10` and `@trpc/server@^11`'s
44
+ * middleware signature: an async function taking a single options object
45
+ * and returning a thenable middleware result.
46
+ *
47
+ * The `opts` parameter is typed `any` so any user-narrowed middleware
48
+ * (with strongly-typed `ctx` / `input` / `meta`) is assignable, and the
49
+ * return type is `Promise<unknown>` so both v10's
50
+ * `Promise<MiddlewareResult<...>>` and v11's identically-named result
51
+ * shape (with extra fields) are accepted without import-time coupling
52
+ * to either major version.
53
+ *
54
+ * Exported so consumers can reference it for type-inference assertions
55
+ * (e.g., proving a strongly-typed middleware fits the bound) without
56
+ * having to recreate the structural shape. The runtime contract is
57
+ * fixed by the `@trpc/server` versions in the peer-dependency range.
58
+ */
59
+ type MiddlewareFunction = (opts: any) => Promise<unknown>;
60
+ /**
61
+ * Options for {@link tracedMiddleware}.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * import { tracedMiddleware } from "@glasstrace/sdk/trpc";
66
+ *
67
+ * const isAuthed = t.middleware(
68
+ * tracedMiddleware(
69
+ * { name: "isAuthed", attributes: { "auth.required": true } },
70
+ * async ({ ctx, next }) => {
71
+ * if (!ctx.session) throw new TRPCError({ code: "UNAUTHORIZED" });
72
+ * return next({ ctx: { ...ctx, session: ctx.session } });
73
+ * },
74
+ * ),
75
+ * );
76
+ * ```
77
+ */
78
+ interface TracedMiddlewareOptions {
79
+ /**
80
+ * Span name. Required. Used as the OTel span name; appears in trace
81
+ * timelines and is the primary identifier surfaced by enrichment when
82
+ * a middleware step short-circuits (e.g., auth failure).
83
+ *
84
+ * Must be a non-empty string. Names should be stable across runs so
85
+ * enrichment can reason about middleware identity (e.g., "isAuthed",
86
+ * "isPro"); avoid embedding request data in the name.
87
+ */
88
+ name: string;
89
+ /**
90
+ * Optional attributes attached to the span before the wrapped
91
+ * middleware body runs. Forwarded to OTel as-is via
92
+ * `span.setAttributes(...)`. The SDK does not redact, sanitize, or
93
+ * scan values here — callers must avoid placing tokens, credentials,
94
+ * or other sensitive data in `attributes`.
95
+ *
96
+ * Sensitive request/response data is captured through the gated
97
+ * `glasstrace.error.response_body` path (see DISC-1216), not through
98
+ * this surface.
99
+ */
100
+ attributes?: Record<string, AttributeValue>;
101
+ }
102
+ /**
103
+ * Wrap a tRPC middleware function in an OTel span.
104
+ *
105
+ * Each call to the returned middleware:
106
+ *
107
+ * 1. Opens a span named `options.name` under the active OTel context
108
+ * (typically the HTTP server span). The span inherits `traceId` and
109
+ * parent `spanId` automatically — no manual context plumbing.
110
+ * 2. Sets caller-supplied {@link TracedMiddlewareOptions.attributes}
111
+ * plus `trpc.path` and `trpc.type` (forwarded from the middleware
112
+ * options) on the span before calling the wrapped middleware body.
113
+ * 3. Lets the wrapped middleware run with the new span as the active
114
+ * span (so any `tracer.startActiveSpan` calls inside the body open
115
+ * grandchild spans under the middleware span).
116
+ * 4. On a thrown error: records the exception via `span.recordException`
117
+ * and sets `span.status` to `ERROR` with the error's message; rethrows.
118
+ * 5. On a returned `{ ok: false, error }` middleware result (tRPC's
119
+ * short-circuit shape): sets `span.status` to `ERROR` without
120
+ * `recordException` (no `Error` object to record).
121
+ * 6. On a successful `{ ok: true, ... }` result: leaves the span status
122
+ * as `UNSET` (per OTel instrumentation-library guidance — explicit
123
+ * `OK` here would shadow downstream consumers attempting their own
124
+ * status transitions).
125
+ * 7. Always ends the span (`span.end()`), even on `throw` or `return`.
126
+ *
127
+ * Type-inference: the returned function preserves the input function's
128
+ * type `T`, so tRPC's procedure-builder context narrowing flows through
129
+ * unchanged. See `sdk-trpc.md` §3.3 for the recommended call pattern.
130
+ *
131
+ * @param options - Span name and optional pre-start attributes.
132
+ * @param middleware - The user's tRPC middleware function. Must be
133
+ * structurally compatible with `@trpc/server@^10` or `@trpc/server@^11`.
134
+ * @returns The wrapped middleware function with the same call signature
135
+ * and return type as `middleware`.
136
+ *
137
+ * @example
138
+ * ```ts
139
+ * // trpc.ts — user's project
140
+ * import { initTRPC, TRPCError } from "@trpc/server";
141
+ * import { tracedMiddleware } from "@glasstrace/sdk/trpc";
142
+ *
143
+ * interface MyContext { session?: { userId: string }; tier?: string }
144
+ * const t = initTRPC.context<MyContext>().create();
145
+ *
146
+ * const isAuthed = t.middleware(
147
+ * tracedMiddleware({ name: "isAuthed" }, async ({ ctx, next }) => {
148
+ * if (!ctx.session) throw new TRPCError({ code: "UNAUTHORIZED" });
149
+ * return next({ ctx: { ...ctx, session: ctx.session } });
150
+ * }),
151
+ * );
152
+ *
153
+ * const isPro = t.middleware(
154
+ * tracedMiddleware({ name: "isPro" }, async ({ ctx, next }) => {
155
+ * if (ctx.tier !== "pro") throw new TRPCError({ code: "FORBIDDEN" });
156
+ * return next();
157
+ * }),
158
+ * );
159
+ *
160
+ * export const proProcedure = t.procedure.use(isAuthed).use(isPro);
161
+ * ```
162
+ */
163
+ declare function tracedMiddleware<T extends MiddlewareFunction>(options: TracedMiddlewareOptions, middleware: T): T;
164
+
165
+ export { type MiddlewareFunction, type TracedMiddlewareOptions, tracedMiddleware };
@@ -0,0 +1,165 @@
1
+ import { AttributeValue } from './common/Attributes';
2
+
3
+ /**
4
+ * tRPC middleware-chain instrumentation for Glasstrace.
5
+ *
6
+ * Subpath: `@glasstrace/sdk/trpc`
7
+ *
8
+ * This module exposes {@link tracedMiddleware}, a thin wrapper that turns
9
+ * a user-supplied tRPC middleware function into a span-emitting middleware
10
+ * function. Each invocation of the wrapped middleware opens a child span
11
+ * (via {@link https://opentelemetry.io/docs/specs/otel/trace/api/#starting-a-new-active-span | tracer.startActiveSpan})
12
+ * under whatever active OTel context the runtime exposes when the tRPC
13
+ * dispatcher calls the middleware. In a typical Next.js / Node HTTP server
14
+ * deployment that active context is the HTTP server span, so middleware
15
+ * spans land as children of the HTTP span automatically — no manual
16
+ * parent plumbing required.
17
+ *
18
+ * The helper does not import the `@trpc/server` runtime; it consumes the
19
+ * middleware function shape structurally so that:
20
+ *
21
+ * 1. Projects that do not use tRPC pay no runtime cost (the subpath is
22
+ * excluded from the root barrel and tree-shakeable on its own).
23
+ * 2. The same helper works against `@trpc/server@^10.0.0` and
24
+ * `@trpc/server@^11.0.0` without two parallel implementations.
25
+ *
26
+ * The wrapped function preserves the user's call-site type (`T`) so that
27
+ * tRPC's procedure-builder context narrowing (e.g., adding a `session`
28
+ * field across `.use()` chains) continues to flow through.
29
+ *
30
+ * Compatibility with the existing `glasstrace.trpc.procedure` URL-derived
31
+ * attribute (DISC-1215, shipped) is by construction: that attribute is
32
+ * attached to the **parent** HTTP span at exporter time, never to a
33
+ * middleware child span. Middleware spans only carry `trpc.path` and
34
+ * `trpc.type` (forwarded from the middleware options) plus whatever
35
+ * caller-supplied attributes the {@link TracedMiddlewareOptions.attributes}
36
+ * field carries.
37
+ *
38
+ * @module @glasstrace/sdk/trpc
39
+ */
40
+
41
+ /**
42
+ * Permissive structural bound for a tRPC middleware function. The shape
43
+ * is the intersection of `@trpc/server@^10` and `@trpc/server@^11`'s
44
+ * middleware signature: an async function taking a single options object
45
+ * and returning a thenable middleware result.
46
+ *
47
+ * The `opts` parameter is typed `any` so any user-narrowed middleware
48
+ * (with strongly-typed `ctx` / `input` / `meta`) is assignable, and the
49
+ * return type is `Promise<unknown>` so both v10's
50
+ * `Promise<MiddlewareResult<...>>` and v11's identically-named result
51
+ * shape (with extra fields) are accepted without import-time coupling
52
+ * to either major version.
53
+ *
54
+ * Exported so consumers can reference it for type-inference assertions
55
+ * (e.g., proving a strongly-typed middleware fits the bound) without
56
+ * having to recreate the structural shape. The runtime contract is
57
+ * fixed by the `@trpc/server` versions in the peer-dependency range.
58
+ */
59
+ type MiddlewareFunction = (opts: any) => Promise<unknown>;
60
+ /**
61
+ * Options for {@link tracedMiddleware}.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * import { tracedMiddleware } from "@glasstrace/sdk/trpc";
66
+ *
67
+ * const isAuthed = t.middleware(
68
+ * tracedMiddleware(
69
+ * { name: "isAuthed", attributes: { "auth.required": true } },
70
+ * async ({ ctx, next }) => {
71
+ * if (!ctx.session) throw new TRPCError({ code: "UNAUTHORIZED" });
72
+ * return next({ ctx: { ...ctx, session: ctx.session } });
73
+ * },
74
+ * ),
75
+ * );
76
+ * ```
77
+ */
78
+ interface TracedMiddlewareOptions {
79
+ /**
80
+ * Span name. Required. Used as the OTel span name; appears in trace
81
+ * timelines and is the primary identifier surfaced by enrichment when
82
+ * a middleware step short-circuits (e.g., auth failure).
83
+ *
84
+ * Must be a non-empty string. Names should be stable across runs so
85
+ * enrichment can reason about middleware identity (e.g., "isAuthed",
86
+ * "isPro"); avoid embedding request data in the name.
87
+ */
88
+ name: string;
89
+ /**
90
+ * Optional attributes attached to the span before the wrapped
91
+ * middleware body runs. Forwarded to OTel as-is via
92
+ * `span.setAttributes(...)`. The SDK does not redact, sanitize, or
93
+ * scan values here — callers must avoid placing tokens, credentials,
94
+ * or other sensitive data in `attributes`.
95
+ *
96
+ * Sensitive request/response data is captured through the gated
97
+ * `glasstrace.error.response_body` path (see DISC-1216), not through
98
+ * this surface.
99
+ */
100
+ attributes?: Record<string, AttributeValue>;
101
+ }
102
+ /**
103
+ * Wrap a tRPC middleware function in an OTel span.
104
+ *
105
+ * Each call to the returned middleware:
106
+ *
107
+ * 1. Opens a span named `options.name` under the active OTel context
108
+ * (typically the HTTP server span). The span inherits `traceId` and
109
+ * parent `spanId` automatically — no manual context plumbing.
110
+ * 2. Sets caller-supplied {@link TracedMiddlewareOptions.attributes}
111
+ * plus `trpc.path` and `trpc.type` (forwarded from the middleware
112
+ * options) on the span before calling the wrapped middleware body.
113
+ * 3. Lets the wrapped middleware run with the new span as the active
114
+ * span (so any `tracer.startActiveSpan` calls inside the body open
115
+ * grandchild spans under the middleware span).
116
+ * 4. On a thrown error: records the exception via `span.recordException`
117
+ * and sets `span.status` to `ERROR` with the error's message; rethrows.
118
+ * 5. On a returned `{ ok: false, error }` middleware result (tRPC's
119
+ * short-circuit shape): sets `span.status` to `ERROR` without
120
+ * `recordException` (no `Error` object to record).
121
+ * 6. On a successful `{ ok: true, ... }` result: leaves the span status
122
+ * as `UNSET` (per OTel instrumentation-library guidance — explicit
123
+ * `OK` here would shadow downstream consumers attempting their own
124
+ * status transitions).
125
+ * 7. Always ends the span (`span.end()`), even on `throw` or `return`.
126
+ *
127
+ * Type-inference: the returned function preserves the input function's
128
+ * type `T`, so tRPC's procedure-builder context narrowing flows through
129
+ * unchanged. See `sdk-trpc.md` §3.3 for the recommended call pattern.
130
+ *
131
+ * @param options - Span name and optional pre-start attributes.
132
+ * @param middleware - The user's tRPC middleware function. Must be
133
+ * structurally compatible with `@trpc/server@^10` or `@trpc/server@^11`.
134
+ * @returns The wrapped middleware function with the same call signature
135
+ * and return type as `middleware`.
136
+ *
137
+ * @example
138
+ * ```ts
139
+ * // trpc.ts — user's project
140
+ * import { initTRPC, TRPCError } from "@trpc/server";
141
+ * import { tracedMiddleware } from "@glasstrace/sdk/trpc";
142
+ *
143
+ * interface MyContext { session?: { userId: string }; tier?: string }
144
+ * const t = initTRPC.context<MyContext>().create();
145
+ *
146
+ * const isAuthed = t.middleware(
147
+ * tracedMiddleware({ name: "isAuthed" }, async ({ ctx, next }) => {
148
+ * if (!ctx.session) throw new TRPCError({ code: "UNAUTHORIZED" });
149
+ * return next({ ctx: { ...ctx, session: ctx.session } });
150
+ * }),
151
+ * );
152
+ *
153
+ * const isPro = t.middleware(
154
+ * tracedMiddleware({ name: "isPro" }, async ({ ctx, next }) => {
155
+ * if (ctx.tier !== "pro") throw new TRPCError({ code: "FORBIDDEN" });
156
+ * return next();
157
+ * }),
158
+ * );
159
+ *
160
+ * export const proProcedure = t.procedure.use(isAuthed).use(isPro);
161
+ * ```
162
+ */
163
+ declare function tracedMiddleware<T extends MiddlewareFunction>(options: TracedMiddlewareOptions, middleware: T): T;
164
+
165
+ export { type MiddlewareFunction, type TracedMiddlewareOptions, tracedMiddleware };
@@ -0,0 +1,65 @@
1
+ import {
2
+ SpanStatusCode,
3
+ trace
4
+ } from "../chunk-DQ25VOKK.js";
5
+ import "../chunk-NSBPE2FW.js";
6
+
7
+ // src/trpc/index.ts
8
+ var TRACER_NAME = "@glasstrace/sdk/trpc";
9
+ function tracedMiddleware(options, middleware) {
10
+ if (typeof options.name !== "string" || options.name.length === 0) {
11
+ throw new TypeError(
12
+ "tracedMiddleware: options.name must be a non-empty string"
13
+ );
14
+ }
15
+ const wrapped = async (mwOpts) => {
16
+ const tracer = trace.getTracer(TRACER_NAME);
17
+ return tracer.startActiveSpan(options.name, async (span) => {
18
+ try {
19
+ if (options.attributes) {
20
+ span.setAttributes(options.attributes);
21
+ }
22
+ if (mwOpts && typeof mwOpts === "object") {
23
+ const path = mwOpts.path;
24
+ if (typeof path === "string") {
25
+ span.setAttribute("trpc.path", path);
26
+ }
27
+ const type = mwOpts.type;
28
+ if (type === "query" || type === "mutation" || type === "subscription") {
29
+ span.setAttribute("trpc.type", type);
30
+ }
31
+ }
32
+ const result = await middleware(mwOpts);
33
+ if (result !== null && typeof result === "object" && result.ok === false) {
34
+ span.setStatus({ code: SpanStatusCode.ERROR });
35
+ }
36
+ return result;
37
+ } catch (error) {
38
+ const normalized = error instanceof Error ? error : typeof error === "string" ? error : new Error(String(error));
39
+ const statusMessage = normalized instanceof Error ? normalized.message : normalized;
40
+ try {
41
+ span.recordException(normalized);
42
+ } catch {
43
+ }
44
+ try {
45
+ span.setStatus({
46
+ code: SpanStatusCode.ERROR,
47
+ message: statusMessage
48
+ });
49
+ } catch {
50
+ }
51
+ throw error;
52
+ } finally {
53
+ try {
54
+ span.end();
55
+ } catch {
56
+ }
57
+ }
58
+ });
59
+ };
60
+ return wrapped;
61
+ }
62
+ export {
63
+ tracedMiddleware
64
+ };
65
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/trpc/index.ts"],"sourcesContent":["/**\n * tRPC middleware-chain instrumentation for Glasstrace.\n *\n * Subpath: `@glasstrace/sdk/trpc`\n *\n * This module exposes {@link tracedMiddleware}, a thin wrapper that turns\n * a user-supplied tRPC middleware function into a span-emitting middleware\n * function. Each invocation of the wrapped middleware opens a child span\n * (via {@link https://opentelemetry.io/docs/specs/otel/trace/api/#starting-a-new-active-span | tracer.startActiveSpan})\n * under whatever active OTel context the runtime exposes when the tRPC\n * dispatcher calls the middleware. In a typical Next.js / Node HTTP server\n * deployment that active context is the HTTP server span, so middleware\n * spans land as children of the HTTP span automatically — no manual\n * parent plumbing required.\n *\n * The helper does not import the `@trpc/server` runtime; it consumes the\n * middleware function shape structurally so that:\n *\n * 1. Projects that do not use tRPC pay no runtime cost (the subpath is\n * excluded from the root barrel and tree-shakeable on its own).\n * 2. The same helper works against `@trpc/server@^10.0.0` and\n * `@trpc/server@^11.0.0` without two parallel implementations.\n *\n * The wrapped function preserves the user's call-site type (`T`) so that\n * tRPC's procedure-builder context narrowing (e.g., adding a `session`\n * field across `.use()` chains) continues to flow through.\n *\n * Compatibility with the existing `glasstrace.trpc.procedure` URL-derived\n * attribute (DISC-1215, shipped) is by construction: that attribute is\n * attached to the **parent** HTTP span at exporter time, never to a\n * middleware child span. Middleware spans only carry `trpc.path` and\n * `trpc.type` (forwarded from the middleware options) plus whatever\n * caller-supplied attributes the {@link TracedMiddlewareOptions.attributes}\n * field carries.\n *\n * @module @glasstrace/sdk/trpc\n */\n\nimport {\n trace,\n SpanStatusCode,\n type AttributeValue,\n} from \"@opentelemetry/api\";\n\n/**\n * Permissive structural bound for a tRPC middleware function. The shape\n * is the intersection of `@trpc/server@^10` and `@trpc/server@^11`'s\n * middleware signature: an async function taking a single options object\n * and returning a thenable middleware result.\n *\n * The `opts` parameter is typed `any` so any user-narrowed middleware\n * (with strongly-typed `ctx` / `input` / `meta`) is assignable, and the\n * return type is `Promise<unknown>` so both v10's\n * `Promise<MiddlewareResult<...>>` and v11's identically-named result\n * shape (with extra fields) are accepted without import-time coupling\n * to either major version.\n *\n * Exported so consumers can reference it for type-inference assertions\n * (e.g., proving a strongly-typed middleware fits the bound) without\n * having to recreate the structural shape. The runtime contract is\n * fixed by the `@trpc/server` versions in the peer-dependency range.\n */\n// The `any` here is load-bearing: a tighter bound would reject either\n// v10 or v11 middleware shapes, or both, because tRPC narrows `ctx`,\n// `input`, and `meta` to user-supplied types via generics. Capturing\n// `T extends MiddlewareFunction` preserves that narrowing through the\n// wrapper's `: T` return type (see the type-inference fixture in\n// tests/unit/sdk/trpc/traced-middleware-types.test.ts).\n//\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type MiddlewareFunction = (opts: any) => Promise<unknown>;\n\n/**\n * Options for {@link tracedMiddleware}.\n *\n * @example\n * ```ts\n * import { tracedMiddleware } from \"@glasstrace/sdk/trpc\";\n *\n * const isAuthed = t.middleware(\n * tracedMiddleware(\n * { name: \"isAuthed\", attributes: { \"auth.required\": true } },\n * async ({ ctx, next }) => {\n * if (!ctx.session) throw new TRPCError({ code: \"UNAUTHORIZED\" });\n * return next({ ctx: { ...ctx, session: ctx.session } });\n * },\n * ),\n * );\n * ```\n */\nexport interface TracedMiddlewareOptions {\n /**\n * Span name. Required. Used as the OTel span name; appears in trace\n * timelines and is the primary identifier surfaced by enrichment when\n * a middleware step short-circuits (e.g., auth failure).\n *\n * Must be a non-empty string. Names should be stable across runs so\n * enrichment can reason about middleware identity (e.g., \"isAuthed\",\n * \"isPro\"); avoid embedding request data in the name.\n */\n name: string;\n /**\n * Optional attributes attached to the span before the wrapped\n * middleware body runs. Forwarded to OTel as-is via\n * `span.setAttributes(...)`. The SDK does not redact, sanitize, or\n * scan values here — callers must avoid placing tokens, credentials,\n * or other sensitive data in `attributes`.\n *\n * Sensitive request/response data is captured through the gated\n * `glasstrace.error.response_body` path (see DISC-1216), not through\n * this surface.\n */\n attributes?: Record<string, AttributeValue>;\n}\n\n/**\n * Module-level OTel tracer name for the tRPC subpath. Resolves through\n * the global `ProxyTracerProvider` so it inherits whatever provider the\n * SDK has detected or registered (Glasstrace's enriching exporter,\n * Sentry's processor in coexistence mode, Datadog's processor, etc.).\n *\n * Re-resolved on every call site rather than cached at module top-level\n * so that the test harness's `trace.setGlobalTracerProvider` can be\n * picked up after this module is imported. (Caching the tracer at module\n * top-level would race against test harness setup and produce stale\n * no-op spans for the very first test.)\n */\nconst TRACER_NAME = \"@glasstrace/sdk/trpc\";\n\n/**\n * Wrap a tRPC middleware function in an OTel span.\n *\n * Each call to the returned middleware:\n *\n * 1. Opens a span named `options.name` under the active OTel context\n * (typically the HTTP server span). The span inherits `traceId` and\n * parent `spanId` automatically — no manual context plumbing.\n * 2. Sets caller-supplied {@link TracedMiddlewareOptions.attributes}\n * plus `trpc.path` and `trpc.type` (forwarded from the middleware\n * options) on the span before calling the wrapped middleware body.\n * 3. Lets the wrapped middleware run with the new span as the active\n * span (so any `tracer.startActiveSpan` calls inside the body open\n * grandchild spans under the middleware span).\n * 4. On a thrown error: records the exception via `span.recordException`\n * and sets `span.status` to `ERROR` with the error's message; rethrows.\n * 5. On a returned `{ ok: false, error }` middleware result (tRPC's\n * short-circuit shape): sets `span.status` to `ERROR` without\n * `recordException` (no `Error` object to record).\n * 6. On a successful `{ ok: true, ... }` result: leaves the span status\n * as `UNSET` (per OTel instrumentation-library guidance — explicit\n * `OK` here would shadow downstream consumers attempting their own\n * status transitions).\n * 7. Always ends the span (`span.end()`), even on `throw` or `return`.\n *\n * Type-inference: the returned function preserves the input function's\n * type `T`, so tRPC's procedure-builder context narrowing flows through\n * unchanged. See `sdk-trpc.md` §3.3 for the recommended call pattern.\n *\n * @param options - Span name and optional pre-start attributes.\n * @param middleware - The user's tRPC middleware function. Must be\n * structurally compatible with `@trpc/server@^10` or `@trpc/server@^11`.\n * @returns The wrapped middleware function with the same call signature\n * and return type as `middleware`.\n *\n * @example\n * ```ts\n * // trpc.ts — user's project\n * import { initTRPC, TRPCError } from \"@trpc/server\";\n * import { tracedMiddleware } from \"@glasstrace/sdk/trpc\";\n *\n * interface MyContext { session?: { userId: string }; tier?: string }\n * const t = initTRPC.context<MyContext>().create();\n *\n * const isAuthed = t.middleware(\n * tracedMiddleware({ name: \"isAuthed\" }, async ({ ctx, next }) => {\n * if (!ctx.session) throw new TRPCError({ code: \"UNAUTHORIZED\" });\n * return next({ ctx: { ...ctx, session: ctx.session } });\n * }),\n * );\n *\n * const isPro = t.middleware(\n * tracedMiddleware({ name: \"isPro\" }, async ({ ctx, next }) => {\n * if (ctx.tier !== \"pro\") throw new TRPCError({ code: \"FORBIDDEN\" });\n * return next();\n * }),\n * );\n *\n * export const proProcedure = t.procedure.use(isAuthed).use(isPro);\n * ```\n */\nexport function tracedMiddleware<T extends MiddlewareFunction>(\n options: TracedMiddlewareOptions,\n middleware: T,\n): T {\n // Validate the span name eagerly so a mis-typed call site fails at\n // wrapper-construction time (typically at module load) rather than at\n // first request, when the failure is harder to diagnose. The structural\n // bound only enforces shape, not value-level invariants.\n if (typeof options.name !== \"string\" || options.name.length === 0) {\n throw new TypeError(\n \"tracedMiddleware: options.name must be a non-empty string\",\n );\n }\n\n // The wrapped function. Capture `options` and `middleware` lexically;\n // do not read them from `this` since tRPC invokes middleware as a\n // plain function (not a method).\n const wrapped = async (mwOpts: Parameters<T>[0]): Promise<unknown> => {\n const tracer = trace.getTracer(TRACER_NAME);\n return tracer.startActiveSpan(options.name, async (span) => {\n try {\n // Set caller-supplied attributes first so they appear on the\n // span before any internal attribute we add below. Caller-supplied\n // attributes are forwarded as-is — no redaction or scanning (see\n // TracedMiddlewareOptions.attributes JSDoc).\n if (options.attributes) {\n span.setAttributes(options.attributes);\n }\n // Forward the tRPC-provided `path` and `type` so consumers (the\n // enriching exporter, third-party UIs) can correlate the\n // middleware span back to its procedure without joining against\n // the parent HTTP span. Both fields are documented as Tier 2\n // heuristics in `sdk-trpc.md` §4.\n if (mwOpts && typeof mwOpts === \"object\") {\n const path = (mwOpts as { path?: unknown }).path;\n if (typeof path === \"string\") {\n span.setAttribute(\"trpc.path\", path);\n }\n const type = (mwOpts as { type?: unknown }).type;\n if (\n type === \"query\" ||\n type === \"mutation\" ||\n type === \"subscription\"\n ) {\n span.setAttribute(\"trpc.type\", type);\n }\n }\n\n const result = await middleware(mwOpts);\n\n // tRPC's middleware result is a discriminated union:\n // { ok: true, ... } — successful pass-through\n // { ok: false, error, ... } — middleware short-circuited with\n // an explicit error envelope\n //\n // The error envelope is the path users hit when they call\n // `next()` and the next link returns ok:false; from the wrapper's\n // perspective the middleware did not throw, but the request did\n // fail. Mark the span ERROR so the exporter and downstream UIs\n // surface the failure, but do not call `recordException` —\n // there is no `Error` object to record.\n if (\n result !== null &&\n typeof result === \"object\" &&\n (result as { ok?: unknown }).ok === false\n ) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n }\n\n return result;\n } catch (error) {\n // Thrown error path. `recordException` produces an OTel\n // exception event with the error name, message, and stack;\n // `setStatus({ code: ERROR, message })` lets standard OTel UIs\n // display the error message inline with the span.\n //\n // OpenTelemetry's `Span.recordException` accepts only\n // `Exception = string | Error` — a non-Error, non-string\n // throwable (e.g. a plain object, number, or symbol thrown by\n // user code via valid JavaScript) can cause `recordException`\n // to throw, which would otherwise leave the span status UNSET\n // even though the request failed. Normalize the throwable\n // first, then guard `recordException` and `setStatus` in\n // independent try/catch blocks so a failure inside one cannot\n // block the other from running. The user's original `error`\n // value is preserved verbatim for the `throw error` re-raise\n // below — wrapping is purely a span-side normalization.\n const normalized: Error | string =\n error instanceof Error\n ? error\n : typeof error === \"string\"\n ? error\n : new Error(String(error));\n const statusMessage =\n normalized instanceof Error ? normalized.message : normalized;\n try {\n span.recordException(normalized);\n } catch {\n // Swallow — instrumentation must never replace the user's\n // error with its own. The span is still ended in `finally`.\n }\n try {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: statusMessage,\n });\n } catch {\n // Swallow — see comment above. Independent from the\n // recordException try/catch so a failing recordException\n // does not prevent the ERROR status from being recorded.\n }\n throw error;\n } finally {\n // Always end the span. `try/finally` covers both the success\n // and throw paths; the `return result` above happens inside the\n // try, so finally still runs before the value is yielded.\n // Defensively suppress any throw from `span.end()` so a\n // misbehaving OTel impl cannot replace the wrapped middleware's\n // return value (or thrown error) with an unrelated one.\n try {\n span.end();\n } catch {\n // Span lifecycle errors are always non-fatal at this layer.\n }\n }\n });\n };\n\n // The `T` cast preserves the user's function type at the call site\n // even though our wrapper widens parameters to `Parameters<T>[0]` and\n // return to `Promise<unknown>` internally. This is the load-bearing\n // type-inference contract documented in `sdk-trpc.md` §3.3 and\n // verified by `tests/unit/sdk/trpc/traced-middleware-types.test.ts`.\n return wrapped as T;\n}\n"],"mappings":";;;;;;;AA+HA,IAAM,cAAc;AA+Db,SAAS,iBACd,SACA,YACG;AAKH,MAAI,OAAO,QAAQ,SAAS,YAAY,QAAQ,KAAK,WAAW,GAAG;AACjE,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAKA,QAAM,UAAU,OAAO,WAA+C;AACpE,UAAM,SAAS,MAAM,UAAU,WAAW;AAC1C,WAAO,OAAO,gBAAgB,QAAQ,MAAM,OAAO,SAAS;AAC1D,UAAI;AAKF,YAAI,QAAQ,YAAY;AACtB,eAAK,cAAc,QAAQ,UAAU;AAAA,QACvC;AAMA,YAAI,UAAU,OAAO,WAAW,UAAU;AACxC,gBAAM,OAAQ,OAA8B;AAC5C,cAAI,OAAO,SAAS,UAAU;AAC5B,iBAAK,aAAa,aAAa,IAAI;AAAA,UACrC;AACA,gBAAM,OAAQ,OAA8B;AAC5C,cACE,SAAS,WACT,SAAS,cACT,SAAS,gBACT;AACA,iBAAK,aAAa,aAAa,IAAI;AAAA,UACrC;AAAA,QACF;AAEA,cAAM,SAAS,MAAM,WAAW,MAAM;AAatC,YACE,WAAW,QACX,OAAO,WAAW,YACjB,OAA4B,OAAO,OACpC;AACA,eAAK,UAAU,EAAE,MAAM,eAAe,MAAM,CAAC;AAAA,QAC/C;AAEA,eAAO;AAAA,MACT,SAAS,OAAO;AAiBd,cAAM,aACJ,iBAAiB,QACb,QACA,OAAO,UAAU,WACf,QACA,IAAI,MAAM,OAAO,KAAK,CAAC;AAC/B,cAAM,gBACJ,sBAAsB,QAAQ,WAAW,UAAU;AACrD,YAAI;AACF,eAAK,gBAAgB,UAAU;AAAA,QACjC,QAAQ;AAAA,QAGR;AACA,YAAI;AACF,eAAK,UAAU;AAAA,YACb,MAAM,eAAe;AAAA,YACrB,SAAS;AAAA,UACX,CAAC;AAAA,QACH,QAAQ;AAAA,QAIR;AACA,cAAM;AAAA,MACR,UAAE;AAOA,YAAI;AACF,eAAK,IAAI;AAAA,QACX,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAOA,SAAO;AACT;","names":[]}