@sebspark/otel 3.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -3
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/instrumentations.ts","../src/logger.ts","../src/metrics.ts","../src/otel.ts","../src/tracer.ts"],"mappings":";;;;;;cAca,gBAAA;EAAA,
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/instrumentations.ts","../src/logger.ts","../src/metrics.ts","../src/otel.ts","../src/tracer.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -307,7 +307,7 @@ const instrumentations = {
|
|
|
307
307
|
return _socketIo;
|
|
308
308
|
},
|
|
309
309
|
get opensearch() {
|
|
310
|
-
if (!_opensearch) _opensearch = import("@sebspark/opentelemetry-instrumentation-opensearch").then(({ OpenSearchInstrumentation }) => new OpenSearchInstrumentation());
|
|
310
|
+
if (!_opensearch) _opensearch = import("@sebspark/opentelemetry-instrumentation-opensearch").then(({ OpenSearchInstrumentation }) => new OpenSearchInstrumentation({ suppressInternalInstrumentation: true }));
|
|
311
311
|
return _opensearch;
|
|
312
312
|
}
|
|
313
313
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["SpanStatusCode","SpanStatusCode","SpanStatusCode","context","context","SpanStatusCode"],"sources":["../src/enrichments/outgoing-http/consts.ts","../src/enrichments/outgoing-http/apply-attributes.ts","../src/enrichments/outgoing-http/helpers.ts","../src/enrichments/outgoing-http/normalize-http.ts","../src/enrichments/outgoing-http/build-http-config.ts","../src/enrichments/outgoing-http/normalize-undici.ts","../src/enrichments/outgoing-http/build-undici-config.ts","../src/instrumentations.ts","../src/consts.ts","../src/loggers/formatters/style.ts","../src/loggers/formatters/shared.ts","../src/loggers/formatters/log-record.ts","../src/loggers/formatters/metrics.ts","../src/loggers/formatters/span.ts","../src/loggers/console-metric-pretty-exporter.ts","../src/loggers/console-log-pretty-exporter.ts","../src/loggers/console-span-pretty-exporter.ts","../src/loggers/tree-span-processor.ts","../src/providers.ts","../src/otel-context.ts","../src/resource.ts","../src/otel.ts","../src/logger.ts","../src/metrics.ts","../src/tracer.ts"],"sourcesContent":["// Incubating attrs — copied as string literals per OTel JS team recommendation:\n// importing from /incubating at runtime is explicitly discouraged because that\n// entry-point is NOT subject to semver and may break in minor releases.\n// https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-semantic-conventions#unstable-semconv\nexport const ATTR_HTTP_REQUEST_BODY_SIZE = 'http.request.body.size'\nexport const ATTR_HTTP_RESPONSE_BODY_SIZE = 'http.response.body.size'\n\nexport const DEFAULT_REQUEST_HEADERS: string[] = [\n 'content-type',\n 'accept',\n 'x-request-id',\n 'x-correlation-id',\n 'traceparent',\n 'tracestate',\n] as const\n\nexport const DEFAULT_RESPONSE_HEADERS: string[] = [\n 'content-type',\n 'x-request-id',\n 'x-correlation-id',\n 'x-ratelimit-limit',\n 'x-ratelimit-remaining',\n 'x-ratelimit-reset',\n 'retry-after',\n] as const\n\nexport const PROTOCOLS = ['https', 'http'] as const\n","import { type Span, SpanStatusCode } from '@opentelemetry/api'\nimport {\n ATTR_ERROR_TYPE,\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_NETWORK_PEER_ADDRESS,\n ATTR_NETWORK_PEER_PORT,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n ATTR_URL_FULL,\n ATTR_URL_PATH,\n ATTR_URL_QUERY,\n ATTR_URL_SCHEME,\n} from '@opentelemetry/semantic-conventions'\nimport {\n ATTR_HTTP_REQUEST_BODY_SIZE,\n ATTR_HTTP_RESPONSE_BODY_SIZE,\n} from './consts'\nimport type {\n NormalisedRequest,\n NormalisedResponse,\n ResolvedConfig,\n} from './types'\n\nconst requestHeaderAttr = (h: string) =>\n `http.request.header.${h.toLowerCase().replace(/-/g, '_')}`\nconst responseHeaderAttr = (h: string) =>\n `http.response.header.${h.toLowerCase().replace(/-/g, '_')}`\n\nexport const applyRequestAttributes = (\n span: Span,\n req: NormalisedRequest,\n cfg: ResolvedConfig\n): void => {\n const { method, hostname, port, path, protocol } = req\n const [urlPath, urlQuery] = path.split('?')\n const defaultPort = protocol === 'https' ? 443 : 80\n const portSuffix = port !== defaultPort ? `:${port}` : ''\n\n // Stable semconv v1.23+ attributes\n span.setAttributes({\n [ATTR_HTTP_REQUEST_METHOD]: method.toUpperCase(),\n [ATTR_SERVER_ADDRESS]: hostname,\n [ATTR_SERVER_PORT]: port,\n [ATTR_URL_SCHEME]: protocol,\n [ATTR_URL_PATH]: urlPath ?? '/',\n [ATTR_URL_FULL]: `${protocol}://${hostname}${portSuffix}${path}`,\n })\n\n if (urlQuery) {\n span.setAttribute(ATTR_URL_QUERY, urlQuery)\n }\n\n if (cfg.useDescriptiveSpanNames) {\n span.updateName(`${method.toUpperCase()} ${hostname}${urlPath ?? '/'}`)\n }\n\n for (const header of cfg.captureRequestHeaders) {\n const value = req.getHeader(header)\n if (value !== undefined) {\n span.setAttribute(requestHeaderAttr(header), value)\n }\n }\n\n const contentLength = req.getHeader('content-length')\n if (contentLength !== undefined) {\n span.setAttribute(ATTR_HTTP_REQUEST_BODY_SIZE, Number(contentLength))\n }\n\n cfg.enrichSpan(span, req)\n}\n\nexport const applyResponseAttributes = (\n span: Span,\n res: NormalisedResponse,\n cfg: ResolvedConfig\n): void => {\n const { statusCode } = res\n\n span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, statusCode)\n\n // OTel spec for CLIENT spans: 5xx = SDK error; 4xx is not (it's the\n // server's fault). We still record error.type for both so they're filterable.\n if (statusCode >= 500) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: `HTTP ${statusCode}`,\n })\n span.setAttribute(ATTR_ERROR_TYPE, String(statusCode))\n } else if (statusCode >= 400) {\n span.setAttribute(ATTR_ERROR_TYPE, String(statusCode))\n }\n\n for (const header of cfg.captureResponseHeaders) {\n const value = res.getHeader(header)\n if (value !== undefined) {\n span.setAttribute(responseHeaderAttr(header), value)\n }\n }\n\n const contentLength = res.getHeader('content-length')\n if (contentLength !== undefined) {\n span.setAttribute(ATTR_HTTP_RESPONSE_BODY_SIZE, Number(contentLength))\n }\n\n // Resolved wire address (post-proxy) — separate from the original hostname\n // so you can see both in the span and spot mesh rewrites.\n if (res.remoteAddress) {\n span.setAttribute(ATTR_NETWORK_PEER_ADDRESS, res.remoteAddress)\n }\n if (res.remotePort) {\n span.setAttribute(ATTR_NETWORK_PEER_PORT, res.remotePort)\n }\n}\n","import type { ClientRequest, IncomingMessage } from 'node:http'\nimport { DEFAULT_REQUEST_HEADERS, DEFAULT_RESPONSE_HEADERS } from './consts'\nimport type { OutgoingHttpEnrichmentConfig, ResolvedConfig } from './types'\n\nexport const resolve = (\n opts: OutgoingHttpEnrichmentConfig\n): ResolvedConfig => ({\n captureRequestHeaders: opts.captureRequestHeaders ?? DEFAULT_REQUEST_HEADERS,\n captureResponseHeaders:\n opts.captureResponseHeaders ?? DEFAULT_RESPONSE_HEADERS,\n enrichSpan: opts.enrichSpan ?? (() => {}),\n useDescriptiveSpanNames: opts.useDescriptiveSpanNames ?? true,\n ignoreOutgoingPaths: opts.ignoreOutgoingPaths ?? [],\n})\n\nexport const isClientRequest = (\n req: ClientRequest | IncomingMessage\n): req is ClientRequest =>\n typeof (req as ClientRequest).getHeader === 'function'\n\nexport const isIncomingMessage = (res: unknown): res is IncomingMessage =>\n res != null &&\n typeof res === 'object' &&\n 'statusCode' in res &&\n 'headers' in res\n","import type { IncomingMessage, RequestOptions } from 'node:http'\nimport type { NormalisedRequest, NormalisedResponse, Protocol } from './types'\n\nexport const normHttpRequest = (req: RequestOptions): NormalisedRequest => {\n const hostname = String(req.hostname ?? req.host ?? '').split(':')[0]\n const port = Number(req.port ?? req.defaultPort ?? 80)\n const path = String(req.path ?? '/')\n const protocol: Protocol = port === 443 ? 'https' : 'http'\n\n return {\n method: req.method ?? 'GET',\n hostname,\n port,\n path,\n protocol,\n getHeader(name) {\n const headers = req.headers\n if (!headers || Array.isArray(headers)) return undefined\n return getHeaderFromObject(headers as Record<string, unknown>, name)\n },\n }\n}\n\nexport const normHttpResponse = (res: IncomingMessage): NormalisedResponse => {\n const socket = res.socket\n return {\n statusCode: res.statusCode ?? 0,\n statusMessage: res.statusMessage ?? '',\n getHeader(name) {\n return getHeaderFromObject(res.headers, name)\n },\n remoteAddress: socket?.remoteAddress,\n remotePort: socket?.remotePort,\n }\n}\n\nexport const getHeaderFromObject = (\n headers: Record<string, unknown> | undefined,\n name: string\n): string[] | undefined => {\n if (!headers) return undefined\n\n const target = name.toLowerCase()\n\n // Iterate over all keys to find case-insensitive match\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === target) {\n const value = headers[key]\n if (Array.isArray(value)) return value\n if (typeof value === 'string') return [value]\n return undefined\n }\n }\n\n return undefined\n}\n","import type { Attributes } from '@opentelemetry/api'\nimport type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http'\nimport {\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_NETWORK_PEER_ADDRESS,\n ATTR_NETWORK_PEER_PORT,\n ATTR_NETWORK_PROTOCOL_VERSION,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n ATTR_URL_FULL,\n ATTR_URL_PATH,\n ATTR_URL_SCHEME,\n} from '@opentelemetry/semantic-conventions'\nimport {\n applyRequestAttributes,\n applyResponseAttributes,\n} from './apply-attributes'\nimport { isClientRequest, isIncomingMessage, resolve } from './helpers'\nimport { normHttpRequest, normHttpResponse } from './normalize-http'\nimport type { OutgoingHttpEnrichmentConfig } from './types'\n\n/**\n * Build an HttpInstrumentationConfig that applies shared enrichment logic.\n *\n * The returned config can be spread with your own additional options:\n * new HttpInstrumentation({ ...buildHttpConfig(opts), serverName: 'gateway' })\n */\nexport const buildHttpConfig = (\n opts: OutgoingHttpEnrichmentConfig = {}\n): HttpInstrumentationConfig => {\n const cfg = resolve(opts)\n\n const config: HttpInstrumentationConfig = {\n ignoreOutgoingRequestHook(req) {\n if (!cfg.ignoreOutgoingPaths.length) return false\n const path = req.path ?? ''\n return cfg.ignoreOutgoingPaths.some((p) =>\n path.toLowerCase().startsWith(p.toLowerCase())\n )\n },\n\n // startOutgoingSpanHook fires at span creation time — before any proxy or\n // service-mesh sidecar can rewrite the destination socket. The returned\n // attributes are the \"ground truth\" hostname we captured off the wire.\n startOutgoingSpanHook(req) {\n const { method, hostname, port, path, protocol } = normHttpRequest(req)\n const [urlPath] = path.split('?')\n const defaultPort = protocol === 'https' ? 443 : 80\n const portSuffix = port !== defaultPort ? `:${port}` : ''\n\n const attrs: Attributes = {\n [ATTR_HTTP_REQUEST_METHOD]: method.toUpperCase(),\n [ATTR_SERVER_ADDRESS]: hostname,\n [ATTR_SERVER_PORT]: port,\n [ATTR_URL_SCHEME]: protocol,\n [ATTR_URL_PATH]: urlPath ?? '/',\n [ATTR_URL_FULL]: `${protocol}://${hostname}${portSuffix}${path}`,\n [ATTR_NETWORK_PEER_ADDRESS]: hostname,\n [ATTR_NETWORK_PEER_PORT]: port,\n }\n for (const [key, val] of Object.entries(req.headers || {})) {\n if (!val) continue\n\n const name = key.toLowerCase().replace(/-/g, '_')\n const value = Array.isArray(val) ? val.join(',') : val\n attrs[`http.request.header.${name}`] = value\n }\n return attrs\n },\n\n requestHook(span, request) {\n // requestHook fires for both incoming (IncomingMessage) and outgoing\n // (ClientRequest) spans — skip the incoming side.\n if (!isClientRequest(request)) return\n\n // HTTP version isn't always accessible here, but try to read it.\n const proto = request.protocol\n if (proto) {\n span.setAttribute(\n ATTR_NETWORK_PROTOCOL_VERSION,\n proto === 'https:' ? '1.1' : '1.1'\n )\n }\n\n applyRequestAttributes(span, normHttpRequest(request), cfg)\n },\n\n responseHook(span, response) {\n if (!isIncomingMessage(response)) return\n applyResponseAttributes(span, normHttpResponse(response), cfg)\n },\n }\n\n return config\n}\n","import type {\n UndiciRequest,\n UndiciResponse,\n} from '@opentelemetry/instrumentation-undici'\nimport type { NormalisedRequest, NormalisedResponse } from './types'\n\nexport const normUndiciRequest = (req: UndiciRequest): NormalisedRequest => {\n const origin = new URL(req.origin)\n const protocol = origin.protocol.replace(':', '') as 'http' | 'https'\n const port = Number(origin.port) || (protocol === 'https' ? 443 : 80)\n\n // Parse \"Key: Value\\r\\nKey2: Value2\\r\\n\" → Map\n const headers = parseUndiciRequestHeaders(req.headers)\n\n return {\n method: req.method,\n hostname: origin.hostname,\n port,\n path: req.path,\n protocol,\n getHeader: (name) => headers[name.toLowerCase()],\n }\n}\n\nexport const normUndiciResponse = (res: UndiciResponse): NormalisedResponse => {\n const headers = parseUndiciResponseHeaders(res.headers)\n\n return {\n statusCode: res.statusCode,\n statusMessage: res.statusText,\n getHeader: (name) => headers[name.toLowerCase()],\n }\n}\n\nexport const parseUndiciResponseHeaders = (\n headers: Buffer<ArrayBufferLike>[]\n): Record<string, string[]> => {\n const result: Record<string, string[]> = {}\n\n for (let i = 0; i < headers.length; i += 2) {\n const keyBuf = headers[i]\n const valBuf = headers[i + 1]\n\n if (!keyBuf || !valBuf) continue\n\n const key = (\n Buffer.isBuffer(keyBuf)\n ? keyBuf.toString('utf8').trim()\n : Buffer.from(keyBuf as ArrayBuffer)\n .toString('utf8')\n .trim()\n ).toLowerCase()\n\n const val = Buffer.isBuffer(valBuf)\n ? valBuf.toString('utf8').trim()\n : Buffer.from(valBuf as ArrayBuffer)\n .toString('utf8')\n .trim()\n\n if (!key || !val) continue\n\n if (!result[key]) result[key] = []\n result[key].push(val)\n }\n\n return result\n}\n\nexport const parseUndiciRequestHeaders = (\n headers: string | (string | string[])[]\n) => {\n const result: Record<string, string[]> = {}\n\n if (typeof headers === 'string') {\n // Single string format: \"key: value\"\n const [key, ...rest] = headers.split(':')\n if (key && rest.length > 0) {\n result[key.trim().toLowerCase()] = [rest.join(':').trim()]\n }\n } else if (Array.isArray(headers)) {\n // Array format: [key, value] or [key, [value1, value2]]\n for (let i = 0; i < headers.length; i += 2) {\n const key = headers[i]\n const val = headers[i + 1]\n if (typeof key !== 'string' || val == null) continue\n\n if (Array.isArray(val)) {\n result[key.toLowerCase()] = val.map((v) => String(v))\n } else {\n result[key.toLowerCase()] = [String(val)]\n }\n }\n }\n\n return result\n}\n","import type { UndiciInstrumentationConfig } from '@opentelemetry/instrumentation-undici'\nimport {\n applyRequestAttributes,\n applyResponseAttributes,\n} from './apply-attributes'\nimport { resolve } from './helpers'\nimport { normUndiciRequest, normUndiciResponse } from './normalize-undici'\nimport type { OutgoingHttpEnrichmentConfig } from './types'\n\n/**\n * Build an UndiciInstrumentationConfig that applies shared enrichment logic.\n *\n * new UndiciInstrumentation(buildUndiciConfig(opts))\n */\nexport function buildUndiciConfig(\n opts: OutgoingHttpEnrichmentConfig = {}\n): UndiciInstrumentationConfig {\n const cfg = resolve(opts)\n\n const config: UndiciInstrumentationConfig = {\n ignoreRequestHook(req) {\n if (!cfg.ignoreOutgoingPaths.length) return false\n const path = req.path ?? ''\n return cfg.ignoreOutgoingPaths.some((p) =>\n path.toLowerCase().startsWith(p.toLowerCase())\n )\n },\n\n // undici collapses startSpanHook + requestHook into a single requestHook\n // because diagnostics_channel gives us everything at once.\n requestHook(span, request) {\n applyRequestAttributes(span, normUndiciRequest(request), cfg)\n },\n\n responseHook(span, { response }) {\n applyResponseAttributes(span, normUndiciResponse(response), cfg)\n },\n }\n\n return config\n}\n","import type { Instrumentation } from '@opentelemetry/instrumentation'\nimport { buildHttpConfig, buildUndiciConfig } from './enrichments/outgoing-http'\n\nlet _http: Promise<Instrumentation> | undefined\nlet _express: Promise<Instrumentation> | undefined\nlet _grpc: Promise<Instrumentation> | undefined\nlet _redis: Promise<Instrumentation> | undefined\nlet _dns: Promise<Instrumentation> | undefined\nlet _net: Promise<Instrumentation> | undefined\nlet _fs: Promise<Instrumentation> | undefined\nlet _undici: Promise<Instrumentation> | undefined\nlet _socketIo: Promise<Instrumentation> | undefined\nlet _opensearch: Promise<Instrumentation> | undefined\n\nexport const instrumentations = {\n get http() {\n if (!_http) {\n _http = import('@opentelemetry/instrumentation-http').then(\n ({ HttpInstrumentation }) => new HttpInstrumentation(buildHttpConfig())\n )\n }\n return _http\n },\n\n get express() {\n if (!_express) {\n _express = import('@opentelemetry/instrumentation-express').then(\n ({ ExpressInstrumentation }) => new ExpressInstrumentation()\n )\n }\n return _express\n },\n\n get grpc() {\n if (!_grpc) {\n _grpc = import('@opentelemetry/instrumentation-grpc').then(\n ({ GrpcInstrumentation }) => new GrpcInstrumentation()\n )\n }\n return _grpc\n },\n\n get redis() {\n if (!_redis) {\n _redis = import('@opentelemetry/instrumentation-redis').then(\n ({ RedisInstrumentation }) => new RedisInstrumentation()\n )\n }\n return _redis\n },\n\n get dns() {\n if (!_dns) {\n _dns = import('@opentelemetry/instrumentation-dns').then(\n ({ DnsInstrumentation }) => new DnsInstrumentation()\n )\n }\n return _dns\n },\n\n get net() {\n if (!_net) {\n _net = import('@opentelemetry/instrumentation-net').then(\n ({ NetInstrumentation }) => new NetInstrumentation()\n )\n }\n return _net\n },\n\n get fs() {\n if (!_fs) {\n _fs = import('@opentelemetry/instrumentation-fs').then(\n ({ FsInstrumentation }) => new FsInstrumentation()\n )\n }\n return _fs\n },\n\n get undici() {\n if (!_undici) {\n _undici = import('@opentelemetry/instrumentation-undici').then(\n ({ UndiciInstrumentation }) =>\n new UndiciInstrumentation(buildUndiciConfig())\n )\n }\n return _undici\n },\n\n get socketIo() {\n if (!_socketIo) {\n _socketIo = import('@opentelemetry/instrumentation-socket.io').then(\n ({ SocketIoInstrumentation }) => new SocketIoInstrumentation()\n )\n }\n return _socketIo\n },\n\n get opensearch() {\n if (!_opensearch) {\n _opensearch = import(\n '@sebspark/opentelemetry-instrumentation-opensearch'\n ).then(({ OpenSearchInstrumentation }) => new OpenSearchInstrumentation())\n }\n return _opensearch\n },\n} as const\n","export const LOG_SEVERITY_MAP = {\n TRACE: 1,\n DEBUG: 5,\n INFO: 9,\n NOTICE: 10,\n WARNING: 13,\n WARN: 13,\n ERROR: 17,\n FATAL: 21,\n CRITICAL: 21,\n ALERT: 22,\n EMERGENCY: 23,\n} as const\n\nexport type LOG_SEVERITY_NAME = keyof typeof LOG_SEVERITY_MAP\n","import kleur from 'kleur'\n\nexport const colors = {\n gray: kleur.gray,\n dim: kleur.dim,\n cyan: kleur.cyan,\n white: kleur.white,\n green: kleur.green,\n yellow: kleur.yellow,\n red: kleur.red,\n magenta: kleur.magenta,\n}\n\nexport const levelColorMap: Record<string, (s: string) => string> = {\n DEBUG: kleur.magenta,\n INFO: kleur.green,\n WARN: kleur.yellow,\n ERROR: kleur.red,\n FATAL: kleur.red,\n}\n\nexport const levelIconMap: Record<string, string> = {\n DEBUG: '🐛',\n INFO: 'ℹ️ ',\n WARN: '⚠️ ',\n ERROR: '❌',\n FATAL: '💀',\n}\n\n// --- Span status codes (per OpenTelemetry spec) ---\nexport const statusLabelMap: Record<number, string> = {\n 0: 'UNSET',\n 1: 'OK',\n 2: 'ERROR',\n}\n\nexport const statusColorMap: Record<number, (s: string) => string> = {\n 0: colors.gray, // UNSET\n 1: colors.green, // OK\n 2: colors.red, // ERROR\n}\n\n// --- Span kinds (for visual context: client/server etc.) ---\nexport const kindLabelMap: Record<number, string> = {\n 0: 'INTERNAL',\n 1: 'SERVER',\n 2: 'CLIENT',\n 3: 'PRODUCER',\n 4: 'CONSUMER',\n}\n\nexport const kindColorMap: Record<number, (s: string) => string> = {\n 0: colors.white, // INTERNAL\n 1: colors.cyan, // SERVER\n 2: colors.yellow, // CLIENT\n 3: colors.magenta, // PRODUCER\n 4: colors.green, // CONSUMER\n}\n","import type { HrTime } from '@opentelemetry/api'\nimport type { LogAttributes } from '@opentelemetry/api-logs'\nimport type { Resource } from '@opentelemetry/resources'\nimport type { ReadableLogRecord } from '@opentelemetry/sdk-logs'\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-node'\nimport {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from '@opentelemetry/semantic-conventions'\nimport fss from 'fast-safe-stringify'\nimport { colors, levelColorMap, levelIconMap } from './style'\n\nconst stringify = fss.default.stableStringify\n\ntype IResource = Pick<Resource, 'attributes'>\ntype IInstrumentation = ReadableLogRecord['instrumentationScope']\n\nexport function formatTimestamp(time: HrTime): string {\n const date = new Date(hrTimeToMillis(time))\n return colors.dim(date.toISOString().slice(11, 23)) // HH:mm:ss.sss\n}\n\nexport function formatService(resource: IResource): string {\n const name = resource.attributes[ATTR_SERVICE_NAME] ?? 'unknown-service'\n const version = resource.attributes[ATTR_SERVICE_VERSION] ?? '1.0.0'\n return colors.gray(`[${name}@${version}]`)\n}\n\nexport function formatLevel(record: ReadableLogRecord): string {\n const text = (record.severityText ?? 'INFO').toUpperCase()\n const colorFn = levelColorMap[text] ?? colors.white\n const icon = levelIconMap[text] ?? '•'\n return `${icon} ${colorFn(text.padEnd(5))}`\n}\n\nexport function formatScope(\n resource: IResource,\n instrumentationScope: IInstrumentation\n): string {\n const component = resource.attributes['component.name']\n const { name } = instrumentationScope\n const scopeLabel =\n component || (name && name !== 'unknown' ? name : undefined)\n\n if (!scopeLabel) return ''\n\n return colors.cyan(`${scopeLabel} `)\n}\n\nexport function formatMessage(record: ReadableLogRecord): string {\n return typeof record.body === 'string' ? record.body : stringify(record.body)\n}\n\nexport function formatAttributes(attrs: LogAttributes): string {\n const keys = Object.keys(attrs).filter(\n (k) =>\n !k.startsWith('service.') &&\n !k.startsWith('serviceContext.') &&\n k !== 'cloud.orchestrator' &&\n k !== 'component.name'\n )\n if (keys.length === 0) return ''\n const formatted = keys.map((k) => {\n const val = attrs[k]\n return `${k}=${typeof val === 'object' ? stringify(val) : val}`\n })\n return ` ${colors.gray(formatted.join(' '))}`\n}\n\nexport function hrTimeToMillis(hrTime: [number, number]): number {\n return hrTime[0] * 1000 + Math.floor(hrTime[1] / 1_000_000)\n}\n\nexport function calculateDuration(span: ReadableSpan): number {\n const start = hrTimeToMillis(span.startTime)\n const end = hrTimeToMillis(span.endTime)\n return Math.max(0, Math.round(end - start))\n}\n","import type { ReadableLogRecord } from '@opentelemetry/sdk-logs'\nimport {\n formatAttributes,\n formatLevel,\n formatMessage,\n formatScope,\n formatService,\n formatTimestamp,\n} from './shared'\n\nexport function formatLogRecord(record: ReadableLogRecord): string {\n const timestamp = formatTimestamp(record.hrTime)\n const service = formatService(record.resource)\n const level = formatLevel(record)\n const scope = formatScope(record.resource, record.instrumentationScope)\n const message = formatMessage(record)\n const attrs = formatAttributes(record.attributes)\n\n return `${service} ${timestamp} ${level} ${scope}${message}${attrs}`\n}\n","import type { Resource } from '@opentelemetry/resources'\nimport type {\n DataPoint,\n MetricData,\n ResourceMetrics,\n ScopeMetrics,\n} from '@opentelemetry/sdk-metrics'\nimport {\n formatAttributes,\n formatScope,\n formatService,\n formatTimestamp,\n} from './shared'\nimport { colors } from './style'\n\nexport function formatMetrics(resourceMetrics: ResourceMetrics): string {\n const { resource, scopeMetrics } = resourceMetrics\n\n return scopeMetrics\n .map((scopeMetric) => formatScopeMetric(scopeMetric, resource))\n .join('\\n')\n}\n\nfunction formatScopeMetric(\n scopeMetric: ScopeMetrics,\n resource: Resource\n): string {\n return scopeMetric.metrics\n .map((metric: MetricData) =>\n formatMetricData(metric, resource, scopeMetric.scope)\n )\n .join('\\n')\n}\n\nfunction formatMetricData(\n metric: MetricData,\n resource: Resource,\n scope: ScopeMetrics['scope']\n): string {\n const scopeStr = formatScope(resource, scope)\n const serviceStr = formatService(resource)\n\n const lines: string[] = []\n\n for (const dp of metric.dataPoints) {\n const ts = formatTimestamp(dp.startTime)\n const value = extractMetricValue(dp)\n const attrs = formatAttributes(dp.attributes ?? {})\n\n lines.push(\n `${serviceStr} ${ts} 📊 ${scopeStr}${colors.white(metric.descriptor.name)} ${colors.dim(value)}${attrs}`\n )\n }\n\n return lines.join('\\n')\n}\n\nfunction extractMetricValue(dp: DataPoint<unknown>): string {\n const value = dp.value\n\n if (typeof value === 'number') {\n return value.toString()\n }\n\n if (isHistogramLike(value)) {\n return value.sum.toString()\n }\n\n return '[complex]'\n}\n\nfunction isHistogramLike(val: unknown): val is { sum: number } {\n return (\n typeof val === 'object' &&\n val !== null &&\n 'sum' in val &&\n typeof (val as { sum: number }).sum === 'number'\n )\n}\n","import { SpanStatusCode } from '@opentelemetry/api'\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-node'\nimport {\n calculateDuration,\n formatService,\n formatTimestamp,\n hrTimeToMillis,\n} from './shared'\nimport { colors, statusColorMap, statusLabelMap } from './style'\n\nconst LABEL_WIDTH = 20\nconst DESCRIPTION_MAX_WIDTH = 16\nconst BAR_MIN_WIDTH = 1\nconst BAR_MAX_WIDTH = 20\n\nexport function formatSpans(spans: ReadableSpan[]) {\n const rootSpan = spans[0]\n const rootStart = hrTimeToMillis(rootSpan.startTime)\n const rootEnd = hrTimeToMillis(rootSpan.endTime)\n const totalDuration = rootEnd - rootStart\n\n const service = formatService(rootSpan.resource)\n const timestamp = formatTimestamp(rootSpan.startTime)\n const traceId = colors.gray(`[${rootSpan.spanContext().traceId}]`)\n\n const lines = [`${service} ${timestamp} ${traceId}`]\n\n for (const span of spans) {\n const offset = hrTimeToMillis(span.startTime) - rootStart\n const depth = computeDepth(span, spans) // optional\n lines.push(\n formatSpan(span, {\n offsetMs: offset,\n totalDurationMs: totalDuration,\n depth,\n })\n )\n }\n\n return lines.join('\\n')\n}\n\nexport function formatSpan(\n span: ReadableSpan,\n opts: {\n offsetMs: number // relative start time in ms (0 for root)\n totalDurationMs: number // total duration in ms (root span duration)\n depth: number // nesting level for indent\n }\n): string {\n const label = formatLabel(span, opts.depth)\n const bar = buildBar(span, opts?.offsetMs, opts?.totalDurationMs)\n const barColor =\n span.status.code === SpanStatusCode.OK\n ? colors.green\n : span.status.code === SpanStatusCode.ERROR\n ? colors.red\n : colors.gray\n const desc = formatDescription(span)\n const status = formatStatus(span)\n const duration = formatDuration(span, opts?.offsetMs)\n const spanId = colors.gray(`[${span.spanContext().spanId}]`)\n\n return `${label} ${barColor(bar)} ${desc} ${status} ${duration} ${spanId}`\n}\n\nfunction formatLabel(span: ReadableSpan, depth: number) {\n const indent = ' '.repeat(depth) // 2 spaces per depth level\n const label = `${indent}└─ ${span.name}`\n return label.padEnd(LABEL_WIDTH)\n}\n\nfunction buildBar(\n span: ReadableSpan,\n offsetMs: number | undefined,\n totalDurationMs: number | undefined\n) {\n const duration = calculateDuration(span)\n\n if (\n typeof offsetMs !== 'number' ||\n typeof totalDurationMs !== 'number' ||\n totalDurationMs === 0\n ) {\n // fallback: show duration-only bar\n const capped = Math.min(duration, 1000)\n const barLength = Math.max(\n BAR_MIN_WIDTH,\n Math.round((capped / 1000) * BAR_MAX_WIDTH)\n )\n return '█'.repeat(barLength).padEnd(BAR_MAX_WIDTH + 2)\n }\n\n // Relative position and size\n const offsetRatio = Math.max(0, Math.min(offsetMs / totalDurationMs, 1))\n const durationRatio = Math.max(0, Math.min(duration / totalDurationMs, 1))\n\n const offsetChars = Math.floor(offsetRatio * BAR_MAX_WIDTH)\n const barChars = Math.max(\n BAR_MIN_WIDTH,\n Math.round(durationRatio * BAR_MAX_WIDTH)\n )\n\n const empty = ' '.repeat(offsetChars)\n const bar = '█'.repeat(barChars)\n\n return (empty + bar).padEnd(BAR_MAX_WIDTH + 2)\n}\n\nfunction formatDescription(span: ReadableSpan): string {\n const keyPriority = [\n // HTTP\n ['http.method', 'http.target'], // → GET /users/123\n ['http.route'], // → /users/:id\n ['http.url'], // → https://...\n\n // GraphQL\n ['graphql.operation.name'], // → getUsers\n ['graphql.operation.type'], // → query\n ['graphql.document'], // → full query text (maybe too long)\n\n // WebSocket\n ['ws.event'], // → connection, message, disconnect\n ['ws.message_type'], // → ping/pong/text/binary\n ['ws.url'], // → wss://...\n\n // Redis\n ['db.system', 'db.statement'], // → redis, \"SET foo bar\"\n ['db.operation'], // → GET, SET\n\n // Spanner\n ['db.statement'], // → SELECT * FROM...\n ['db.operation'], // → SELECT, INSERT\n ['db.name'], // → projects/.../instances/.../databases/...\n\n // OpenSearch\n ['db.operation'], // → search, index, bulk\n ['db.statement'], // → { query DSL... }\n\n // Pub/Sub (GCP)\n ['messaging.operation'], // → publish, receive\n ['messaging.destination'], // → topic-a\n ['messaging.gcp_pubsub.topic'], // → projects/x/topics/y\n\n // General FaaS\n ['faas.invoked_name'], // → myFunction\n ['faas.trigger'], // → http, pubsub, etc.\n\n // Custom or fallback\n ['otel.description'],\n ]\n\n for (const keys of keyPriority) {\n const parts = keys\n .map((k) => span.attributes[k])\n .filter((v) => v !== undefined && v !== null)\n .map((v) => String(v)) // 👈 FIX — guarantees string\n if (parts.length > 0) {\n return truncate(parts.join(' '), DESCRIPTION_MAX_WIDTH - 1).padEnd(\n DESCRIPTION_MAX_WIDTH\n )\n }\n }\n\n return ''.padEnd(DESCRIPTION_MAX_WIDTH)\n}\n\nfunction formatStatus(span: ReadableSpan): string {\n const code = span.status.code\n const label = statusLabelMap[code] ?? 'UNSET'\n const colorFn = statusColorMap[code] ?? colors.gray\n return colorFn(label).padEnd(6)\n}\n\nfunction formatDuration(\n span: ReadableSpan,\n offsetMs: number | undefined\n): string {\n const duration = calculateDuration(span)\n\n const format = (ms: number): string =>\n ms >= 1000 ? `${(ms / 1000).toFixed(2)} s` : `${ms} ms`\n\n return `(${format(offsetMs || 0)}–${format(duration)})`.padEnd(16)\n}\n\nfunction truncate(input: unknown, maxLength: number): string {\n const str = String(input ?? '')\n return str.length > maxLength ? `${str.slice(0, maxLength - 1)}…` : str\n}\n\nfunction computeDepth(span: ReadableSpan, allSpans: ReadableSpan[]): number {\n let depth = 0\n let currentParentId = span.parentSpanContext?.spanId\n\n while (currentParentId) {\n const parentSpan = allSpans.find(\n (s) => s.spanContext().spanId === currentParentId\n )\n if (!parentSpan) break\n\n depth += 1\n currentParentId = parentSpan.parentSpanContext?.spanId\n }\n\n return depth\n}\n","import { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type {\n PushMetricExporter,\n ResourceMetrics,\n} from '@opentelemetry/sdk-metrics'\nimport { formatMetrics } from './formatters/index'\n\nexport class ConsoleMetricPrettyExporter implements PushMetricExporter {\n private readonly patterns: RegExp[]\n\n constructor() {\n const raw = process.env.METRIC_FILTER ?? ''\n const entries = raw\n .split(',')\n .map((e) => e.trim())\n .filter(Boolean)\n\n this.patterns = entries.map(globToRegex)\n }\n\n private filterMetrics(\n resourceMetrics: ResourceMetrics\n ): ResourceMetrics | undefined {\n // No filter = block all metrics\n if (this.patterns.length === 0) return undefined\n\n const filteredScopes = resourceMetrics.scopeMetrics\n .map((scopeMetric) => {\n const filteredMetrics = scopeMetric.metrics.filter((metric) =>\n this.patterns.some((pattern) => pattern.test(metric.descriptor.name))\n )\n\n if (filteredMetrics.length === 0) return undefined\n\n return {\n ...scopeMetric,\n metrics: filteredMetrics,\n }\n })\n .filter((s): s is NonNullable<typeof s> => s !== undefined)\n\n if (filteredScopes.length === 0) return undefined\n\n return {\n ...resourceMetrics,\n scopeMetrics: filteredScopes,\n }\n }\n\n export(\n metrics: ResourceMetrics,\n resultCallback: (result: ExportResult) => void\n ): void {\n const filtered = this.filterMetrics(metrics)\n if (filtered) {\n console.log(formatMetrics(filtered))\n }\n resultCallback({ code: ExportResultCode.SUCCESS })\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n}\n\nfunction globToRegex(glob: string): RegExp {\n const escaped = glob.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&')\n const regex = `^${escaped.replace(/\\*/g, '.*')}$`\n return new RegExp(regex)\n}\n","import { SeverityNumber } from '@opentelemetry/api-logs'\nimport { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type {\n LogRecordExporter,\n ReadableLogRecord,\n} from '@opentelemetry/sdk-logs'\nimport { LOG_SEVERITY_MAP, type LOG_SEVERITY_NAME } from '../consts'\nimport { formatLogRecord } from './formatters/index'\n\nexport class ConsoleLogPrettyExporter implements LogRecordExporter {\n private readonly logThreshold: number\n constructor() {\n const defaultLogLevel = 'INFO'\n const env = (process.env.LOG_LEVEL?.toUpperCase() ??\n defaultLogLevel) as LOG_SEVERITY_NAME\n this.logThreshold =\n LOG_SEVERITY_MAP[env] ?? LOG_SEVERITY_MAP[defaultLogLevel]\n }\n export(\n logs: ReadableLogRecord[],\n resultCallback: (result: ExportResult) => void\n ): void {\n this._sendLogRecords(logs, resultCallback)\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n\n private _sendLogRecords(\n logRecords: ReadableLogRecord[],\n done: (result: ExportResult) => void\n ): void {\n for (const record of logRecords) {\n if ((record.severityNumber ?? 0) >= this.logThreshold) {\n const formatted = formatLogRecord(record)\n const severity = record.severityNumber || SeverityNumber.UNSPECIFIED\n\n if (severity >= SeverityNumber.ERROR) {\n console.error(formatted)\n } else if (severity >= SeverityNumber.WARN) {\n console.log(formatted)\n } else if (severity >= SeverityNumber.INFO) {\n console.info(formatted)\n } else if (severity >= SeverityNumber.DEBUG) {\n console.debug(formatted)\n } else {\n console.trace(formatted)\n }\n }\n }\n\n done?.({ code: ExportResultCode.SUCCESS })\n }\n}\n","import { SpanStatusCode } from '@opentelemetry/api'\nimport { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-node'\nimport { formatSpans } from './formatters/index'\n\nexport class ConsoleSpanPrettyExporter implements SpanExporter {\n private readonly allowedStatuses: Set<number>\n\n constructor() {\n const env = process.env.SPAN_LEVEL?.toUpperCase()\n if (!env) {\n this.allowedStatuses = new Set([\n SpanStatusCode.UNSET,\n SpanStatusCode.OK,\n SpanStatusCode.ERROR,\n ])\n } else {\n const map: Record<string, number> = {\n UNSET: SpanStatusCode.UNSET,\n OK: SpanStatusCode.OK,\n ERROR: SpanStatusCode.ERROR,\n }\n\n this.allowedStatuses = new Set(\n env\n .split(',')\n .map((s) => s.trim())\n .map((s) => map[s])\n .filter((v): v is number => typeof v === 'number')\n )\n }\n }\n\n private shouldExport(spans: ReadableSpan[]) {\n // print all spans\n if (this.allowedStatuses.size === 3) {\n return true\n }\n // print only certain levels\n return spans.some((span) => this.allowedStatuses.has(span.status.code))\n }\n\n export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void\n ): void {\n if (this.shouldExport(spans)) {\n console.log(formatSpans(spans))\n }\n\n resultCallback({ code: ExportResultCode.SUCCESS })\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n}\n","import type {\n ReadableSpan,\n SpanExporter,\n SpanProcessor,\n} from '@opentelemetry/sdk-trace-node'\n\nexport class TreeSpanProcessor implements SpanProcessor {\n private exporter: SpanExporter\n private orphans: Map<string, ReadableSpan[]> = new Map()\n\n constructor(exporter: SpanExporter) {\n this.exporter = exporter\n }\n\n onStart(): void {\n // no-op\n }\n\n onEnd(span: ReadableSpan): void {\n const parentId = span.parentSpanContext?.spanId\n\n if (parentId) {\n const siblings = this.orphans.get(parentId) || []\n this.orphans.set(parentId, [...siblings, span])\n\n return\n }\n\n const children = this.getChildrenRecursively(span)\n const sorted = [span, ...children].sort((s1, s2) => {\n const [sec1, nano1] = s1.startTime\n const [sec2, nano2] = s2.startTime\n\n if (sec1 !== sec2) return sec1 - sec2\n return nano1 - nano2\n })\n this.exporter.export(sorted, () => {})\n }\n\n private getChildrenRecursively(span: ReadableSpan) {\n const spanId = span.spanContext().spanId\n const children = this.orphans.get(spanId) || []\n this.orphans.delete(spanId)\n\n const result = [...children]\n for (const child of children) {\n result.push(...this.getChildrenRecursively(child))\n }\n\n return result\n }\n\n shutdown(): Promise<void> {\n return this.exporter.shutdown()\n }\n\n async forceFlush(): Promise<void> {\n await this.exporter.forceFlush?.()\n }\n}\n","import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'\nimport { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport type { Resource } from '@opentelemetry/resources'\nimport {\n BatchLogRecordProcessor,\n LoggerProvider,\n type LogRecordProcessor,\n SimpleLogRecordProcessor,\n} from '@opentelemetry/sdk-logs'\nimport { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'\nimport {\n BatchSpanProcessor,\n type SpanProcessor,\n} from '@opentelemetry/sdk-trace-node'\nimport { ConsoleMetricPrettyExporter } from './loggers/console-metric-pretty-exporter'\nimport {\n ConsoleLogPrettyExporter,\n ConsoleSpanPrettyExporter,\n} from './loggers/index'\nimport { TreeSpanProcessor } from './loggers/tree-span-processor'\n\nexport const getLogProvider = (\n resource: Resource,\n otlpEndpoint: string | undefined\n) => {\n // With collector\n if (otlpEndpoint) {\n const exporter = new OTLPLogExporter({ url: `${otlpEndpoint}/v1/logs` })\n const processors: LogRecordProcessor[] = [\n new BatchLogRecordProcessor(exporter),\n ]\n\n // Console logging for cluster\n if (process.env.LOG_LEVEL) {\n const consoleExporter = new ConsoleLogPrettyExporter()\n processors.push(new SimpleLogRecordProcessor(consoleExporter))\n }\n\n return new LoggerProvider({\n resource,\n processors,\n })\n }\n\n // Local dev\n const exporter = new ConsoleLogPrettyExporter()\n const processor = new SimpleLogRecordProcessor(exporter)\n return new LoggerProvider({\n resource,\n processors: [processor],\n })\n}\n\nexport const getSpanProcessor = (\n otlpEndpoint: string | undefined\n): SpanProcessor => {\n const exporter = otlpEndpoint\n ? new OTLPTraceExporter({\n url: `${otlpEndpoint}/v1/traces`,\n })\n : new ConsoleSpanPrettyExporter()\n const processor = otlpEndpoint\n ? new BatchSpanProcessor(exporter)\n : new TreeSpanProcessor(exporter)\n\n return processor\n}\n\nexport const getMetricReader = (otlpEndpoint: string | undefined) => {\n const metricExporter = otlpEndpoint\n ? new OTLPMetricExporter({\n url: `${otlpEndpoint}/v1/metrics`,\n })\n : new ConsoleMetricPrettyExporter()\n const metricReader = new PeriodicExportingMetricReader({\n exporter: metricExporter,\n })\n\n return metricReader\n}\n","import {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from '@opentelemetry/semantic-conventions'\n\n/**\n * Extracts telemetry context from environment (cloud/k8s aware),\n * with support for subservice/component override.\n */\nexport function detectTelemetryContext(componentNameOverride?: string) {\n const {\n OTEL_SERVICE_NAME, // e.g. \"UserSystem\"\n OTEL_SERVICE_VERSION, // e.g. \"1.2.3\"\n K_SERVICE,\n K_REVISION,\n K_CONFIGURATION,\n KUBERNETES_SERVICE_HOST,\n POD_NAME,\n POD_NAMESPACE,\n GCP_PROJECT,\n CLOUD_PROVIDER,\n } = process.env\n\n const systemName = OTEL_SERVICE_NAME || 'unknown-service'\n const systemVersion = OTEL_SERVICE_VERSION || '1.0.0'\n\n // Only use component if explicitly provided\n const componentName = componentNameOverride || undefined\n\n const resourceAttributes = {\n [ATTR_SERVICE_NAME]: systemName,\n [ATTR_SERVICE_VERSION]: systemVersion,\n 'serviceContext.service': systemName,\n 'serviceContext.version': systemVersion,\n ...(K_SERVICE && { 'cloud.run.service': K_SERVICE }),\n ...(K_REVISION && { 'cloud.run.revision': K_REVISION }),\n ...(K_CONFIGURATION && { 'cloud.run.configuration': K_CONFIGURATION }),\n ...(POD_NAME && { 'k8s.pod_name': POD_NAME }),\n ...(POD_NAMESPACE && { 'k8s.namespace_name': POD_NAMESPACE }),\n ...(KUBERNETES_SERVICE_HOST && { 'cloud.orchestrator': 'kubernetes' }),\n ...(GCP_PROJECT && { 'cloud.account.id': GCP_PROJECT }),\n ...(CLOUD_PROVIDER && { 'cloud.provider': CLOUD_PROVIDER }),\n ...(componentName && { 'component.name': componentName }),\n }\n\n return {\n systemName,\n systemVersion,\n componentName,\n resourceAttributes,\n }\n}\n","import { containerDetector } from '@opentelemetry/resource-detector-container'\nimport { gcpDetector } from '@opentelemetry/resource-detector-gcp'\nimport {\n detectResources,\n envDetector,\n osDetector,\n processDetector,\n resourceFromAttributes,\n serviceInstanceIdDetector,\n} from '@opentelemetry/resources'\nimport { detectTelemetryContext } from './otel-context'\n\nconst isOnGcp = () =>\n !!(\n process.env.K_SERVICE ||\n process.env.GAE_APPLICATION ||\n process.env.KUBERNETES_SERVICE_HOST\n )\n\nexport const getResource = async () => {\n const baseRes = detectResources({\n detectors: [\n containerDetector,\n envDetector,\n ...(isOnGcp() ? [gcpDetector] : []),\n osDetector,\n processDetector,\n serviceInstanceIdDetector,\n ],\n })\n\n if (baseRes.waitForAsyncAttributes) {\n await baseRes.waitForAsyncAttributes()\n }\n\n const { resourceAttributes } = detectTelemetryContext()\n const customRes = resourceFromAttributes(resourceAttributes)\n const resource = baseRes.merge(customRes)\n\n if (resource.waitForAsyncAttributes) {\n await resource.waitForAsyncAttributes()\n }\n\n return resource\n}\n","import {\n context,\n DiagConsoleLogger,\n DiagLogLevel,\n diag,\n metrics,\n trace,\n} from '@opentelemetry/api'\nimport { logs } from '@opentelemetry/api-logs'\nimport type { Instrumentation } from '@opentelemetry/instrumentation'\nimport type { LoggerProvider } from '@opentelemetry/sdk-logs'\nimport { NodeSDK } from '@opentelemetry/sdk-node'\nimport { getLogProvider, getMetricReader, getSpanProcessor } from './providers'\nimport { getResource } from './resource'\n\ndiag.disable()\ndiag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR)\n\n// Use globalThis with a Symbol key so the flag is shared even when the module\n// is instantiated more than once (e.g. --import preload vs main app graph when\n// using tsx or other loaders that don't share the ESM module cache).\nconst OTEL_INIT_KEY = Symbol.for('@sebspark/otel:initialized')\nconst OTEL_INIT_PROMISE_KEY = Symbol.for('@sebspark/otel:initPromise')\n\nfunction getGlobal(): {\n [key: symbol]: unknown\n} {\n return globalThis as Record<symbol, unknown>\n}\n\nexport async function initialize(\n ...instrumentations: Promise<Instrumentation>[]\n) {\n const g = getGlobal()\n if (!g[OTEL_INIT_PROMISE_KEY]) {\n const resolvedInstrumentations = await Promise.all(instrumentations)\n const promise = _initialize(resolvedInstrumentations).catch((err) => {\n // Allow re-initialization if the first attempt fails\n g[OTEL_INIT_PROMISE_KEY] = undefined\n throw err\n })\n g[OTEL_INIT_PROMISE_KEY] = promise\n }\n return g[OTEL_INIT_PROMISE_KEY] as Promise<void>\n}\n\nexport function isInitialized() {\n return getGlobal()[OTEL_INIT_KEY] === true\n}\n\nlet sdk: NodeSDK | undefined\nlet logProvider: LoggerProvider | undefined\n\nasync function _initialize(instrumentations: Instrumentation[]) {\n const serviceName = process.env.OTEL_SERVICE_NAME ?? 'unknown-service'\n const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT\n\n const resource = await getResource()\n\n // Reset any previous instrumentation\n context.disable()\n logs.disable()\n trace.disable()\n metrics.disable()\n\n // Manual setup for logs\n logProvider = getLogProvider(resource, otlpEndpoint)\n logs.setGlobalLoggerProvider(logProvider)\n\n // NodeSDK setup\n const spanProcessor = getSpanProcessor(otlpEndpoint)\n const metricReader = getMetricReader(otlpEndpoint)\n sdk = new NodeSDK({\n spanProcessor,\n metricReader,\n instrumentations,\n resource,\n })\n\n sdk.start()\n getGlobal()[OTEL_INIT_KEY] = true\n console.log(`[otel] Telemetry initialized for \"${serviceName}\"`)\n}\n\nexport const dispose = async () => {\n const processes: Promise<void>[] = []\n if (sdk) processes.push(sdk.shutdown())\n if (logProvider) processes.push(logProvider.shutdown())\n\n if (processes.length) {\n console.log('[otel] Shutting down...')\n await Promise.all(processes)\n console.log('[otel] Shutdown complete.')\n }\n}\n","import { context, trace } from '@opentelemetry/api'\nimport { logs } from '@opentelemetry/api-logs'\nimport { LOG_SEVERITY_MAP, type LOG_SEVERITY_NAME } from './consts'\nimport { isInitialized } from './otel'\nimport { detectTelemetryContext } from './otel-context'\n\n// biome-ignore lint/suspicious/noExplicitAny: library\ntype Attrs = Record<string, any>\n\nexport type Logger = ReturnType<typeof getLogger>\nexport function getLogger(serviceOverride?: string, extraAttrs: Attrs = {}) {\n const { systemName, systemVersion, resourceAttributes } =\n detectTelemetryContext(serviceOverride)\n\n const defaultAttrs = {\n ...resourceAttributes,\n ...extraAttrs,\n }\n\n let hasWarnedAboutInit = false\n\n function emit(\n severityText: LOG_SEVERITY_NAME,\n body: string,\n attrs: Attrs = {}\n ) {\n // Get the logger at the last second\n if (!isInitialized() && process.env.NODE_ENV !== 'test') {\n if (!hasWarnedAboutInit) {\n console.warn('OTEL must be initialized before using logger')\n hasWarnedAboutInit = true\n }\n console.log(`[${severityText}] ${body}`)\n return\n }\n const logger = logs.getLogger(systemName, systemVersion)\n\n const span = trace.getSpan(context.active())\n const spanContext = span?.spanContext()\n\n logger.emit({\n severityText,\n severityNumber: LOG_SEVERITY_MAP[severityText],\n body,\n attributes: {\n 'gcp.log_name': systemName.replace(/^@/, '').replace(/\\//g, '-'),\n ...defaultAttrs,\n ...(spanContext && {\n trace_id: spanContext.traceId,\n span_id: spanContext.spanId,\n }),\n ...attrs,\n },\n })\n }\n\n function resolveArgs(\n msg: string | Error,\n errOrAttrs?: Error | Attrs,\n maybeAttrs: Attrs = {}\n ): { body: string; attrs: Attrs } {\n if (errOrAttrs instanceof Error) {\n const body = `${msg}: ${errOrAttrs.stack || errOrAttrs.message}`\n return { body, attrs: maybeAttrs }\n }\n\n const body = msg instanceof Error ? msg.stack || msg.message : msg\n const attrs = errOrAttrs || {}\n return { body, attrs }\n }\n\n type LogFn = {\n (msg: string, attrs?: Attrs): void\n (msg: string, error: Error, attrs?: Attrs): void\n (error: Error, attrs?: Attrs): void\n }\n\n function createLogFn(severity: LOG_SEVERITY_NAME): LogFn {\n return (\n msg: string | Error,\n errOrAttrs?: Error | Attrs,\n maybeAttrs: Attrs = {}\n ) => {\n const { body, attrs } = resolveArgs(msg, errOrAttrs, maybeAttrs)\n emit(severity, body, attrs)\n }\n }\n\n return {\n debug: createLogFn('DEBUG'),\n info: createLogFn('INFO'),\n notice: createLogFn('NOTICE'),\n warn: createLogFn('WARN'),\n error: createLogFn('ERROR'),\n critical: createLogFn('CRITICAL'),\n alert: createLogFn('ALERT'),\n emergency: createLogFn('EMERGENCY'),\n }\n}\n","import { metrics } from '@opentelemetry/api'\nimport { isInitialized } from './otel'\nimport { detectTelemetryContext } from './otel-context'\n\nexport function getMeter(componentNameOverride?: string) {\n if (!isInitialized() && process.env.NODE_ENV !== 'test') {\n console.warn('OTEL must be initialized before using getMeter()')\n }\n\n const { componentName, systemName, systemVersion } = detectTelemetryContext(\n componentNameOverride\n )\n return metrics.getMeter(componentName ?? systemName, systemVersion)\n}\n","import {\n context,\n type SpanOptions,\n SpanStatusCode,\n trace,\n} from '@opentelemetry/api'\nimport { isInitialized } from './otel'\nimport { detectTelemetryContext } from './otel-context'\n\ntype OtelTracer = ReturnType<typeof trace.getTracer>\ntype Span = ReturnType<OtelTracer['startSpan']>\n\ntype Func<T> = (span: Span) => Promise<T> | T\ntype SyncFunc<T> = (span: Span) => T\n\ntype WithTrace = {\n <T>(name: string, fn: Func<T>): Promise<T>\n <T>(name: string, options: SpanOptions, fn: Func<T>): Promise<T>\n <T>(name: string, parent: Span, fn: Func<T>): Promise<T>\n <T>(name: string, options: SpanOptions, parent: Span, fn: Func<T>): Promise<T>\n}\ntype WithTraceSync = {\n <T>(name: string, fn: SyncFunc<T>): T\n <T>(name: string, options: SpanOptions, fn: SyncFunc<T>): T\n <T>(name: string, parent: Span, fn: SyncFunc<T>): T\n <T>(name: string, options: SpanOptions, parent: Span, fn: SyncFunc<T>): T\n}\n\n/**\n * Extended tracer with helper methods for span-wrapped execution\n */\ninterface Tracer extends OtelTracer {\n withTrace: WithTrace\n withTraceSync: WithTraceSync\n}\n\n/**\n * Returns an OpenTelemetry tracer bound to the current service.\n * Includes `withTrace()` and `withTraceSync()` helpers for span-wrapped execution.\n *\n * @param serviceOverride - Optional override for service name\n * @returns Tracer with helpers\n */\nexport function getTracer(componentNameOverride?: string): Tracer {\n if (!isInitialized() && process.env.NODE_ENV !== 'test') {\n console.warn('OTEL must be initialized before calling getTracer()')\n }\n\n const { componentName, systemName, systemVersion } = detectTelemetryContext(\n componentNameOverride\n )\n const tracer = trace.getTracer(\n componentName ?? systemName,\n systemVersion\n ) as Tracer\n\n /**\n * Runs a function inside a new span (async variant).\n * Automatically handles span status and nesting.\n */\n const withTrace: WithTrace = async <T>(\n name: string,\n spanOptionsSpanOrFunc?: SpanOptions | Span | Func<T>,\n spanOrFunc?: Span | Func<T>,\n func?: Func<T>\n ): Promise<T> => {\n const { options, parent, fn } = extractArgs(\n spanOptionsSpanOrFunc,\n spanOrFunc,\n func\n )\n\n const parentContext = parent\n ? trace.setSpan(context.active(), parent)\n : context.active()\n\n const span = tracer.startSpan(name, options, parentContext)\n let ended = false\n const originalEnd = span.end.bind(span)\n const endOnce = () => {\n if (!ended) {\n ended = true\n originalEnd()\n }\n }\n span.end = endOnce\n\n return await context.with(trace.setSpan(parentContext, span), async () => {\n try {\n const result = await fn(span)\n span.setStatus({ code: SpanStatusCode.OK })\n return result\n } catch (err) {\n const error = err as Error\n span.setStatus({ code: SpanStatusCode.ERROR, message: error.message })\n span.recordException?.(error)\n throw err\n } finally {\n endOnce()\n }\n })\n }\n\n /**\n * Runs a synchronous function inside a new span.\n * Automatically handles span status and nesting.\n */\n const withTraceSync: WithTraceSync = <T>(\n name: string,\n spanOptionsSpanOrFunc?: SpanOptions | Span | SyncFunc<T>,\n spanOrFunc?: Span | SyncFunc<T>,\n func?: SyncFunc<T>\n ): T => {\n const { options, parent, fn } = extractArgs(\n spanOptionsSpanOrFunc,\n spanOrFunc,\n func\n )\n\n const parentContext = parent\n ? trace.setSpan(context.active(), parent)\n : context.active()\n\n const span = tracer.startSpan(name, options, parentContext)\n let ended = false\n const originalEnd = span.end.bind(span)\n const endOnce = () => {\n if (!ended) {\n ended = true\n originalEnd()\n }\n }\n span.end = endOnce\n\n return context.with(trace.setSpan(parentContext, span), () => {\n try {\n const result = fn(span)\n span.setStatus({ code: SpanStatusCode.OK })\n return result\n } catch (err) {\n const error = err as Error\n span.setStatus({ code: SpanStatusCode.ERROR, message: error.message })\n span.recordException?.(error)\n throw err\n } finally {\n endOnce()\n }\n })\n }\n\n tracer.withTrace = withTrace\n tracer.withTraceSync = withTraceSync\n\n return tracer\n}\n\ntype TraceArgs<T> = {\n options: SpanOptions\n parent?: Span\n fn: (span: Span) => T\n}\n\nfunction extractArgs<T>(\n spanOptionsSpanOrFunc?: SpanOptions | Span | ((span: Span) => T),\n spanOrFunc?: Span | ((span: Span) => T),\n func?: (span: Span) => T\n): TraceArgs<T> {\n let options: SpanOptions = {}\n let parent: Span | undefined\n let fn: (span: Span) => T\n\n if (isFunction(spanOptionsSpanOrFunc)) {\n fn = spanOptionsSpanOrFunc\n } else if (isFunction(spanOrFunc)) {\n const spanOrSpanOptions = spanOptionsSpanOrFunc as Span | SpanOptions\n if (isSpanOptions(spanOrSpanOptions)) {\n options = spanOrSpanOptions as SpanOptions\n } else {\n parent = spanOrSpanOptions as Span\n }\n fn = spanOrFunc\n } else {\n options = spanOptionsSpanOrFunc as SpanOptions\n parent = spanOrFunc as Span\n // biome-ignore lint/style/noNonNullAssertion: it IS defined here\n fn = func!\n }\n\n return { options, parent, fn }\n}\n\nconst isFunction = (value: unknown): value is (span: Span) => unknown =>\n typeof value === 'function'\nconst isSpan = (value: unknown): value is Span =>\n value !== null &&\n value !== undefined &&\n isFunction((value as Span).spanContext) &&\n isFunction((value as Span).end)\nconst isSpanOptions = (value: unknown): value is SpanOptions =>\n value !== null &&\n value !== undefined &&\n (!!(value as SpanOptions).startTime ||\n !!(value as SpanOptions).attributes ||\n !!(value as SpanOptions).kind) &&\n !isSpan(value)\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["SpanStatusCode","SpanStatusCode","SpanStatusCode","context","context","SpanStatusCode"],"sources":["../src/enrichments/outgoing-http/consts.ts","../src/enrichments/outgoing-http/apply-attributes.ts","../src/enrichments/outgoing-http/helpers.ts","../src/enrichments/outgoing-http/normalize-http.ts","../src/enrichments/outgoing-http/build-http-config.ts","../src/enrichments/outgoing-http/normalize-undici.ts","../src/enrichments/outgoing-http/build-undici-config.ts","../src/instrumentations.ts","../src/consts.ts","../src/loggers/formatters/style.ts","../src/loggers/formatters/shared.ts","../src/loggers/formatters/log-record.ts","../src/loggers/formatters/metrics.ts","../src/loggers/formatters/span.ts","../src/loggers/console-metric-pretty-exporter.ts","../src/loggers/console-log-pretty-exporter.ts","../src/loggers/console-span-pretty-exporter.ts","../src/loggers/tree-span-processor.ts","../src/providers.ts","../src/otel-context.ts","../src/resource.ts","../src/otel.ts","../src/logger.ts","../src/metrics.ts","../src/tracer.ts"],"sourcesContent":["// Incubating attrs — copied as string literals per OTel JS team recommendation:\n// importing from /incubating at runtime is explicitly discouraged because that\n// entry-point is NOT subject to semver and may break in minor releases.\n// https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-semantic-conventions#unstable-semconv\nexport const ATTR_HTTP_REQUEST_BODY_SIZE = 'http.request.body.size'\nexport const ATTR_HTTP_RESPONSE_BODY_SIZE = 'http.response.body.size'\n\nexport const DEFAULT_REQUEST_HEADERS: string[] = [\n 'content-type',\n 'accept',\n 'x-request-id',\n 'x-correlation-id',\n 'traceparent',\n 'tracestate',\n] as const\n\nexport const DEFAULT_RESPONSE_HEADERS: string[] = [\n 'content-type',\n 'x-request-id',\n 'x-correlation-id',\n 'x-ratelimit-limit',\n 'x-ratelimit-remaining',\n 'x-ratelimit-reset',\n 'retry-after',\n] as const\n\nexport const PROTOCOLS = ['https', 'http'] as const\n","import { type Span, SpanStatusCode } from '@opentelemetry/api'\nimport {\n ATTR_ERROR_TYPE,\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_NETWORK_PEER_ADDRESS,\n ATTR_NETWORK_PEER_PORT,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n ATTR_URL_FULL,\n ATTR_URL_PATH,\n ATTR_URL_QUERY,\n ATTR_URL_SCHEME,\n} from '@opentelemetry/semantic-conventions'\nimport {\n ATTR_HTTP_REQUEST_BODY_SIZE,\n ATTR_HTTP_RESPONSE_BODY_SIZE,\n} from './consts'\nimport type {\n NormalisedRequest,\n NormalisedResponse,\n ResolvedConfig,\n} from './types'\n\nconst requestHeaderAttr = (h: string) =>\n `http.request.header.${h.toLowerCase().replace(/-/g, '_')}`\nconst responseHeaderAttr = (h: string) =>\n `http.response.header.${h.toLowerCase().replace(/-/g, '_')}`\n\nexport const applyRequestAttributes = (\n span: Span,\n req: NormalisedRequest,\n cfg: ResolvedConfig\n): void => {\n const { method, hostname, port, path, protocol } = req\n const [urlPath, urlQuery] = path.split('?')\n const defaultPort = protocol === 'https' ? 443 : 80\n const portSuffix = port !== defaultPort ? `:${port}` : ''\n\n // Stable semconv v1.23+ attributes\n span.setAttributes({\n [ATTR_HTTP_REQUEST_METHOD]: method.toUpperCase(),\n [ATTR_SERVER_ADDRESS]: hostname,\n [ATTR_SERVER_PORT]: port,\n [ATTR_URL_SCHEME]: protocol,\n [ATTR_URL_PATH]: urlPath ?? '/',\n [ATTR_URL_FULL]: `${protocol}://${hostname}${portSuffix}${path}`,\n })\n\n if (urlQuery) {\n span.setAttribute(ATTR_URL_QUERY, urlQuery)\n }\n\n if (cfg.useDescriptiveSpanNames) {\n span.updateName(`${method.toUpperCase()} ${hostname}${urlPath ?? '/'}`)\n }\n\n for (const header of cfg.captureRequestHeaders) {\n const value = req.getHeader(header)\n if (value !== undefined) {\n span.setAttribute(requestHeaderAttr(header), value)\n }\n }\n\n const contentLength = req.getHeader('content-length')\n if (contentLength !== undefined) {\n span.setAttribute(ATTR_HTTP_REQUEST_BODY_SIZE, Number(contentLength))\n }\n\n cfg.enrichSpan(span, req)\n}\n\nexport const applyResponseAttributes = (\n span: Span,\n res: NormalisedResponse,\n cfg: ResolvedConfig\n): void => {\n const { statusCode } = res\n\n span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, statusCode)\n\n // OTel spec for CLIENT spans: 5xx = SDK error; 4xx is not (it's the\n // server's fault). We still record error.type for both so they're filterable.\n if (statusCode >= 500) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: `HTTP ${statusCode}`,\n })\n span.setAttribute(ATTR_ERROR_TYPE, String(statusCode))\n } else if (statusCode >= 400) {\n span.setAttribute(ATTR_ERROR_TYPE, String(statusCode))\n }\n\n for (const header of cfg.captureResponseHeaders) {\n const value = res.getHeader(header)\n if (value !== undefined) {\n span.setAttribute(responseHeaderAttr(header), value)\n }\n }\n\n const contentLength = res.getHeader('content-length')\n if (contentLength !== undefined) {\n span.setAttribute(ATTR_HTTP_RESPONSE_BODY_SIZE, Number(contentLength))\n }\n\n // Resolved wire address (post-proxy) — separate from the original hostname\n // so you can see both in the span and spot mesh rewrites.\n if (res.remoteAddress) {\n span.setAttribute(ATTR_NETWORK_PEER_ADDRESS, res.remoteAddress)\n }\n if (res.remotePort) {\n span.setAttribute(ATTR_NETWORK_PEER_PORT, res.remotePort)\n }\n}\n","import type { ClientRequest, IncomingMessage } from 'node:http'\nimport { DEFAULT_REQUEST_HEADERS, DEFAULT_RESPONSE_HEADERS } from './consts'\nimport type { OutgoingHttpEnrichmentConfig, ResolvedConfig } from './types'\n\nexport const resolve = (\n opts: OutgoingHttpEnrichmentConfig\n): ResolvedConfig => ({\n captureRequestHeaders: opts.captureRequestHeaders ?? DEFAULT_REQUEST_HEADERS,\n captureResponseHeaders:\n opts.captureResponseHeaders ?? DEFAULT_RESPONSE_HEADERS,\n enrichSpan: opts.enrichSpan ?? (() => {}),\n useDescriptiveSpanNames: opts.useDescriptiveSpanNames ?? true,\n ignoreOutgoingPaths: opts.ignoreOutgoingPaths ?? [],\n})\n\nexport const isClientRequest = (\n req: ClientRequest | IncomingMessage\n): req is ClientRequest =>\n typeof (req as ClientRequest).getHeader === 'function'\n\nexport const isIncomingMessage = (res: unknown): res is IncomingMessage =>\n res != null &&\n typeof res === 'object' &&\n 'statusCode' in res &&\n 'headers' in res\n","import type { IncomingMessage, RequestOptions } from 'node:http'\nimport type { NormalisedRequest, NormalisedResponse, Protocol } from './types'\n\nexport const normHttpRequest = (req: RequestOptions): NormalisedRequest => {\n const hostname = String(req.hostname ?? req.host ?? '').split(':')[0]\n const port = Number(req.port ?? req.defaultPort ?? 80)\n const path = String(req.path ?? '/')\n const protocol: Protocol = port === 443 ? 'https' : 'http'\n\n return {\n method: req.method ?? 'GET',\n hostname,\n port,\n path,\n protocol,\n getHeader(name) {\n const headers = req.headers\n if (!headers || Array.isArray(headers)) return undefined\n return getHeaderFromObject(headers as Record<string, unknown>, name)\n },\n }\n}\n\nexport const normHttpResponse = (res: IncomingMessage): NormalisedResponse => {\n const socket = res.socket\n return {\n statusCode: res.statusCode ?? 0,\n statusMessage: res.statusMessage ?? '',\n getHeader(name) {\n return getHeaderFromObject(res.headers, name)\n },\n remoteAddress: socket?.remoteAddress,\n remotePort: socket?.remotePort,\n }\n}\n\nexport const getHeaderFromObject = (\n headers: Record<string, unknown> | undefined,\n name: string\n): string[] | undefined => {\n if (!headers) return undefined\n\n const target = name.toLowerCase()\n\n // Iterate over all keys to find case-insensitive match\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === target) {\n const value = headers[key]\n if (Array.isArray(value)) return value\n if (typeof value === 'string') return [value]\n return undefined\n }\n }\n\n return undefined\n}\n","import type { Attributes } from '@opentelemetry/api'\nimport type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http'\nimport {\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_NETWORK_PEER_ADDRESS,\n ATTR_NETWORK_PEER_PORT,\n ATTR_NETWORK_PROTOCOL_VERSION,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n ATTR_URL_FULL,\n ATTR_URL_PATH,\n ATTR_URL_SCHEME,\n} from '@opentelemetry/semantic-conventions'\nimport {\n applyRequestAttributes,\n applyResponseAttributes,\n} from './apply-attributes'\nimport { isClientRequest, isIncomingMessage, resolve } from './helpers'\nimport { normHttpRequest, normHttpResponse } from './normalize-http'\nimport type { OutgoingHttpEnrichmentConfig } from './types'\n\n/**\n * Build an HttpInstrumentationConfig that applies shared enrichment logic.\n *\n * The returned config can be spread with your own additional options:\n * new HttpInstrumentation({ ...buildHttpConfig(opts), serverName: 'gateway' })\n */\nexport const buildHttpConfig = (\n opts: OutgoingHttpEnrichmentConfig = {}\n): HttpInstrumentationConfig => {\n const cfg = resolve(opts)\n\n const config: HttpInstrumentationConfig = {\n ignoreOutgoingRequestHook(req) {\n if (!cfg.ignoreOutgoingPaths.length) return false\n const path = req.path ?? ''\n return cfg.ignoreOutgoingPaths.some((p) =>\n path.toLowerCase().startsWith(p.toLowerCase())\n )\n },\n\n // startOutgoingSpanHook fires at span creation time — before any proxy or\n // service-mesh sidecar can rewrite the destination socket. The returned\n // attributes are the \"ground truth\" hostname we captured off the wire.\n startOutgoingSpanHook(req) {\n const { method, hostname, port, path, protocol } = normHttpRequest(req)\n const [urlPath] = path.split('?')\n const defaultPort = protocol === 'https' ? 443 : 80\n const portSuffix = port !== defaultPort ? `:${port}` : ''\n\n const attrs: Attributes = {\n [ATTR_HTTP_REQUEST_METHOD]: method.toUpperCase(),\n [ATTR_SERVER_ADDRESS]: hostname,\n [ATTR_SERVER_PORT]: port,\n [ATTR_URL_SCHEME]: protocol,\n [ATTR_URL_PATH]: urlPath ?? '/',\n [ATTR_URL_FULL]: `${protocol}://${hostname}${portSuffix}${path}`,\n [ATTR_NETWORK_PEER_ADDRESS]: hostname,\n [ATTR_NETWORK_PEER_PORT]: port,\n }\n for (const [key, val] of Object.entries(req.headers || {})) {\n if (!val) continue\n\n const name = key.toLowerCase().replace(/-/g, '_')\n const value = Array.isArray(val) ? val.join(',') : val\n attrs[`http.request.header.${name}`] = value\n }\n return attrs\n },\n\n requestHook(span, request) {\n // requestHook fires for both incoming (IncomingMessage) and outgoing\n // (ClientRequest) spans — skip the incoming side.\n if (!isClientRequest(request)) return\n\n // HTTP version isn't always accessible here, but try to read it.\n const proto = request.protocol\n if (proto) {\n span.setAttribute(\n ATTR_NETWORK_PROTOCOL_VERSION,\n proto === 'https:' ? '1.1' : '1.1'\n )\n }\n\n applyRequestAttributes(span, normHttpRequest(request), cfg)\n },\n\n responseHook(span, response) {\n if (!isIncomingMessage(response)) return\n applyResponseAttributes(span, normHttpResponse(response), cfg)\n },\n }\n\n return config\n}\n","import type {\n UndiciRequest,\n UndiciResponse,\n} from '@opentelemetry/instrumentation-undici'\nimport type { NormalisedRequest, NormalisedResponse } from './types'\n\nexport const normUndiciRequest = (req: UndiciRequest): NormalisedRequest => {\n const origin = new URL(req.origin)\n const protocol = origin.protocol.replace(':', '') as 'http' | 'https'\n const port = Number(origin.port) || (protocol === 'https' ? 443 : 80)\n\n // Parse \"Key: Value\\r\\nKey2: Value2\\r\\n\" → Map\n const headers = parseUndiciRequestHeaders(req.headers)\n\n return {\n method: req.method,\n hostname: origin.hostname,\n port,\n path: req.path,\n protocol,\n getHeader: (name) => headers[name.toLowerCase()],\n }\n}\n\nexport const normUndiciResponse = (res: UndiciResponse): NormalisedResponse => {\n const headers = parseUndiciResponseHeaders(res.headers)\n\n return {\n statusCode: res.statusCode,\n statusMessage: res.statusText,\n getHeader: (name) => headers[name.toLowerCase()],\n }\n}\n\nexport const parseUndiciResponseHeaders = (\n headers: Buffer<ArrayBufferLike>[]\n): Record<string, string[]> => {\n const result: Record<string, string[]> = {}\n\n for (let i = 0; i < headers.length; i += 2) {\n const keyBuf = headers[i]\n const valBuf = headers[i + 1]\n\n if (!keyBuf || !valBuf) continue\n\n const key = (\n Buffer.isBuffer(keyBuf)\n ? keyBuf.toString('utf8').trim()\n : Buffer.from(keyBuf as ArrayBuffer)\n .toString('utf8')\n .trim()\n ).toLowerCase()\n\n const val = Buffer.isBuffer(valBuf)\n ? valBuf.toString('utf8').trim()\n : Buffer.from(valBuf as ArrayBuffer)\n .toString('utf8')\n .trim()\n\n if (!key || !val) continue\n\n if (!result[key]) result[key] = []\n result[key].push(val)\n }\n\n return result\n}\n\nexport const parseUndiciRequestHeaders = (\n headers: string | (string | string[])[]\n) => {\n const result: Record<string, string[]> = {}\n\n if (typeof headers === 'string') {\n // Single string format: \"key: value\"\n const [key, ...rest] = headers.split(':')\n if (key && rest.length > 0) {\n result[key.trim().toLowerCase()] = [rest.join(':').trim()]\n }\n } else if (Array.isArray(headers)) {\n // Array format: [key, value] or [key, [value1, value2]]\n for (let i = 0; i < headers.length; i += 2) {\n const key = headers[i]\n const val = headers[i + 1]\n if (typeof key !== 'string' || val == null) continue\n\n if (Array.isArray(val)) {\n result[key.toLowerCase()] = val.map((v) => String(v))\n } else {\n result[key.toLowerCase()] = [String(val)]\n }\n }\n }\n\n return result\n}\n","import type { UndiciInstrumentationConfig } from '@opentelemetry/instrumentation-undici'\nimport {\n applyRequestAttributes,\n applyResponseAttributes,\n} from './apply-attributes'\nimport { resolve } from './helpers'\nimport { normUndiciRequest, normUndiciResponse } from './normalize-undici'\nimport type { OutgoingHttpEnrichmentConfig } from './types'\n\n/**\n * Build an UndiciInstrumentationConfig that applies shared enrichment logic.\n *\n * new UndiciInstrumentation(buildUndiciConfig(opts))\n */\nexport function buildUndiciConfig(\n opts: OutgoingHttpEnrichmentConfig = {}\n): UndiciInstrumentationConfig {\n const cfg = resolve(opts)\n\n const config: UndiciInstrumentationConfig = {\n ignoreRequestHook(req) {\n if (!cfg.ignoreOutgoingPaths.length) return false\n const path = req.path ?? ''\n return cfg.ignoreOutgoingPaths.some((p) =>\n path.toLowerCase().startsWith(p.toLowerCase())\n )\n },\n\n // undici collapses startSpanHook + requestHook into a single requestHook\n // because diagnostics_channel gives us everything at once.\n requestHook(span, request) {\n applyRequestAttributes(span, normUndiciRequest(request), cfg)\n },\n\n responseHook(span, { response }) {\n applyResponseAttributes(span, normUndiciResponse(response), cfg)\n },\n }\n\n return config\n}\n","import type { Instrumentation } from '@opentelemetry/instrumentation'\nimport { buildHttpConfig, buildUndiciConfig } from './enrichments/outgoing-http'\n\nlet _http: Promise<Instrumentation> | undefined\nlet _express: Promise<Instrumentation> | undefined\nlet _grpc: Promise<Instrumentation> | undefined\nlet _redis: Promise<Instrumentation> | undefined\nlet _dns: Promise<Instrumentation> | undefined\nlet _net: Promise<Instrumentation> | undefined\nlet _fs: Promise<Instrumentation> | undefined\nlet _undici: Promise<Instrumentation> | undefined\nlet _socketIo: Promise<Instrumentation> | undefined\nlet _opensearch: Promise<Instrumentation> | undefined\n\nexport const instrumentations = {\n get http() {\n if (!_http) {\n _http = import('@opentelemetry/instrumentation-http').then(\n ({ HttpInstrumentation }) => new HttpInstrumentation(buildHttpConfig())\n )\n }\n return _http\n },\n\n get express() {\n if (!_express) {\n _express = import('@opentelemetry/instrumentation-express').then(\n ({ ExpressInstrumentation }) => new ExpressInstrumentation()\n )\n }\n return _express\n },\n\n get grpc() {\n if (!_grpc) {\n _grpc = import('@opentelemetry/instrumentation-grpc').then(\n ({ GrpcInstrumentation }) => new GrpcInstrumentation()\n )\n }\n return _grpc\n },\n\n get redis() {\n if (!_redis) {\n _redis = import('@opentelemetry/instrumentation-redis').then(\n ({ RedisInstrumentation }) => new RedisInstrumentation()\n )\n }\n return _redis\n },\n\n get dns() {\n if (!_dns) {\n _dns = import('@opentelemetry/instrumentation-dns').then(\n ({ DnsInstrumentation }) => new DnsInstrumentation()\n )\n }\n return _dns\n },\n\n get net() {\n if (!_net) {\n _net = import('@opentelemetry/instrumentation-net').then(\n ({ NetInstrumentation }) => new NetInstrumentation()\n )\n }\n return _net\n },\n\n get fs() {\n if (!_fs) {\n _fs = import('@opentelemetry/instrumentation-fs').then(\n ({ FsInstrumentation }) => new FsInstrumentation()\n )\n }\n return _fs\n },\n\n get undici() {\n if (!_undici) {\n _undici = import('@opentelemetry/instrumentation-undici').then(\n ({ UndiciInstrumentation }) =>\n new UndiciInstrumentation(buildUndiciConfig())\n )\n }\n return _undici\n },\n\n get socketIo() {\n if (!_socketIo) {\n _socketIo = import('@opentelemetry/instrumentation-socket.io').then(\n ({ SocketIoInstrumentation }) => new SocketIoInstrumentation()\n )\n }\n return _socketIo\n },\n\n get opensearch() {\n if (!_opensearch) {\n _opensearch = import(\n '@sebspark/opentelemetry-instrumentation-opensearch'\n ).then(\n ({ OpenSearchInstrumentation }) =>\n new OpenSearchInstrumentation({\n suppressInternalInstrumentation: true,\n })\n )\n }\n return _opensearch\n },\n} as const\n","export const LOG_SEVERITY_MAP = {\n TRACE: 1,\n DEBUG: 5,\n INFO: 9,\n NOTICE: 10,\n WARNING: 13,\n WARN: 13,\n ERROR: 17,\n FATAL: 21,\n CRITICAL: 21,\n ALERT: 22,\n EMERGENCY: 23,\n} as const\n\nexport type LOG_SEVERITY_NAME = keyof typeof LOG_SEVERITY_MAP\n","import kleur from 'kleur'\n\nexport const colors = {\n gray: kleur.gray,\n dim: kleur.dim,\n cyan: kleur.cyan,\n white: kleur.white,\n green: kleur.green,\n yellow: kleur.yellow,\n red: kleur.red,\n magenta: kleur.magenta,\n}\n\nexport const levelColorMap: Record<string, (s: string) => string> = {\n DEBUG: kleur.magenta,\n INFO: kleur.green,\n WARN: kleur.yellow,\n ERROR: kleur.red,\n FATAL: kleur.red,\n}\n\nexport const levelIconMap: Record<string, string> = {\n DEBUG: '🐛',\n INFO: 'ℹ️ ',\n WARN: '⚠️ ',\n ERROR: '❌',\n FATAL: '💀',\n}\n\n// --- Span status codes (per OpenTelemetry spec) ---\nexport const statusLabelMap: Record<number, string> = {\n 0: 'UNSET',\n 1: 'OK',\n 2: 'ERROR',\n}\n\nexport const statusColorMap: Record<number, (s: string) => string> = {\n 0: colors.gray, // UNSET\n 1: colors.green, // OK\n 2: colors.red, // ERROR\n}\n\n// --- Span kinds (for visual context: client/server etc.) ---\nexport const kindLabelMap: Record<number, string> = {\n 0: 'INTERNAL',\n 1: 'SERVER',\n 2: 'CLIENT',\n 3: 'PRODUCER',\n 4: 'CONSUMER',\n}\n\nexport const kindColorMap: Record<number, (s: string) => string> = {\n 0: colors.white, // INTERNAL\n 1: colors.cyan, // SERVER\n 2: colors.yellow, // CLIENT\n 3: colors.magenta, // PRODUCER\n 4: colors.green, // CONSUMER\n}\n","import type { HrTime } from '@opentelemetry/api'\nimport type { LogAttributes } from '@opentelemetry/api-logs'\nimport type { Resource } from '@opentelemetry/resources'\nimport type { ReadableLogRecord } from '@opentelemetry/sdk-logs'\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-node'\nimport {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from '@opentelemetry/semantic-conventions'\nimport fss from 'fast-safe-stringify'\nimport { colors, levelColorMap, levelIconMap } from './style'\n\nconst stringify = fss.default.stableStringify\n\ntype IResource = Pick<Resource, 'attributes'>\ntype IInstrumentation = ReadableLogRecord['instrumentationScope']\n\nexport function formatTimestamp(time: HrTime): string {\n const date = new Date(hrTimeToMillis(time))\n return colors.dim(date.toISOString().slice(11, 23)) // HH:mm:ss.sss\n}\n\nexport function formatService(resource: IResource): string {\n const name = resource.attributes[ATTR_SERVICE_NAME] ?? 'unknown-service'\n const version = resource.attributes[ATTR_SERVICE_VERSION] ?? '1.0.0'\n return colors.gray(`[${name}@${version}]`)\n}\n\nexport function formatLevel(record: ReadableLogRecord): string {\n const text = (record.severityText ?? 'INFO').toUpperCase()\n const colorFn = levelColorMap[text] ?? colors.white\n const icon = levelIconMap[text] ?? '•'\n return `${icon} ${colorFn(text.padEnd(5))}`\n}\n\nexport function formatScope(\n resource: IResource,\n instrumentationScope: IInstrumentation\n): string {\n const component = resource.attributes['component.name']\n const { name } = instrumentationScope\n const scopeLabel =\n component || (name && name !== 'unknown' ? name : undefined)\n\n if (!scopeLabel) return ''\n\n return colors.cyan(`${scopeLabel} `)\n}\n\nexport function formatMessage(record: ReadableLogRecord): string {\n return typeof record.body === 'string' ? record.body : stringify(record.body)\n}\n\nexport function formatAttributes(attrs: LogAttributes): string {\n const keys = Object.keys(attrs).filter(\n (k) =>\n !k.startsWith('service.') &&\n !k.startsWith('serviceContext.') &&\n k !== 'cloud.orchestrator' &&\n k !== 'component.name'\n )\n if (keys.length === 0) return ''\n const formatted = keys.map((k) => {\n const val = attrs[k]\n return `${k}=${typeof val === 'object' ? stringify(val) : val}`\n })\n return ` ${colors.gray(formatted.join(' '))}`\n}\n\nexport function hrTimeToMillis(hrTime: [number, number]): number {\n return hrTime[0] * 1000 + Math.floor(hrTime[1] / 1_000_000)\n}\n\nexport function calculateDuration(span: ReadableSpan): number {\n const start = hrTimeToMillis(span.startTime)\n const end = hrTimeToMillis(span.endTime)\n return Math.max(0, Math.round(end - start))\n}\n","import type { ReadableLogRecord } from '@opentelemetry/sdk-logs'\nimport {\n formatAttributes,\n formatLevel,\n formatMessage,\n formatScope,\n formatService,\n formatTimestamp,\n} from './shared'\n\nexport function formatLogRecord(record: ReadableLogRecord): string {\n const timestamp = formatTimestamp(record.hrTime)\n const service = formatService(record.resource)\n const level = formatLevel(record)\n const scope = formatScope(record.resource, record.instrumentationScope)\n const message = formatMessage(record)\n const attrs = formatAttributes(record.attributes)\n\n return `${service} ${timestamp} ${level} ${scope}${message}${attrs}`\n}\n","import type { Resource } from '@opentelemetry/resources'\nimport type {\n DataPoint,\n MetricData,\n ResourceMetrics,\n ScopeMetrics,\n} from '@opentelemetry/sdk-metrics'\nimport {\n formatAttributes,\n formatScope,\n formatService,\n formatTimestamp,\n} from './shared'\nimport { colors } from './style'\n\nexport function formatMetrics(resourceMetrics: ResourceMetrics): string {\n const { resource, scopeMetrics } = resourceMetrics\n\n return scopeMetrics\n .map((scopeMetric) => formatScopeMetric(scopeMetric, resource))\n .join('\\n')\n}\n\nfunction formatScopeMetric(\n scopeMetric: ScopeMetrics,\n resource: Resource\n): string {\n return scopeMetric.metrics\n .map((metric: MetricData) =>\n formatMetricData(metric, resource, scopeMetric.scope)\n )\n .join('\\n')\n}\n\nfunction formatMetricData(\n metric: MetricData,\n resource: Resource,\n scope: ScopeMetrics['scope']\n): string {\n const scopeStr = formatScope(resource, scope)\n const serviceStr = formatService(resource)\n\n const lines: string[] = []\n\n for (const dp of metric.dataPoints) {\n const ts = formatTimestamp(dp.startTime)\n const value = extractMetricValue(dp)\n const attrs = formatAttributes(dp.attributes ?? {})\n\n lines.push(\n `${serviceStr} ${ts} 📊 ${scopeStr}${colors.white(metric.descriptor.name)} ${colors.dim(value)}${attrs}`\n )\n }\n\n return lines.join('\\n')\n}\n\nfunction extractMetricValue(dp: DataPoint<unknown>): string {\n const value = dp.value\n\n if (typeof value === 'number') {\n return value.toString()\n }\n\n if (isHistogramLike(value)) {\n return value.sum.toString()\n }\n\n return '[complex]'\n}\n\nfunction isHistogramLike(val: unknown): val is { sum: number } {\n return (\n typeof val === 'object' &&\n val !== null &&\n 'sum' in val &&\n typeof (val as { sum: number }).sum === 'number'\n )\n}\n","import { SpanStatusCode } from '@opentelemetry/api'\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-node'\nimport {\n calculateDuration,\n formatService,\n formatTimestamp,\n hrTimeToMillis,\n} from './shared'\nimport { colors, statusColorMap, statusLabelMap } from './style'\n\nconst LABEL_WIDTH = 20\nconst DESCRIPTION_MAX_WIDTH = 16\nconst BAR_MIN_WIDTH = 1\nconst BAR_MAX_WIDTH = 20\n\nexport function formatSpans(spans: ReadableSpan[]) {\n const rootSpan = spans[0]\n const rootStart = hrTimeToMillis(rootSpan.startTime)\n const rootEnd = hrTimeToMillis(rootSpan.endTime)\n const totalDuration = rootEnd - rootStart\n\n const service = formatService(rootSpan.resource)\n const timestamp = formatTimestamp(rootSpan.startTime)\n const traceId = colors.gray(`[${rootSpan.spanContext().traceId}]`)\n\n const lines = [`${service} ${timestamp} ${traceId}`]\n\n for (const span of spans) {\n const offset = hrTimeToMillis(span.startTime) - rootStart\n const depth = computeDepth(span, spans) // optional\n lines.push(\n formatSpan(span, {\n offsetMs: offset,\n totalDurationMs: totalDuration,\n depth,\n })\n )\n }\n\n return lines.join('\\n')\n}\n\nexport function formatSpan(\n span: ReadableSpan,\n opts: {\n offsetMs: number // relative start time in ms (0 for root)\n totalDurationMs: number // total duration in ms (root span duration)\n depth: number // nesting level for indent\n }\n): string {\n const label = formatLabel(span, opts.depth)\n const bar = buildBar(span, opts?.offsetMs, opts?.totalDurationMs)\n const barColor =\n span.status.code === SpanStatusCode.OK\n ? colors.green\n : span.status.code === SpanStatusCode.ERROR\n ? colors.red\n : colors.gray\n const desc = formatDescription(span)\n const status = formatStatus(span)\n const duration = formatDuration(span, opts?.offsetMs)\n const spanId = colors.gray(`[${span.spanContext().spanId}]`)\n\n return `${label} ${barColor(bar)} ${desc} ${status} ${duration} ${spanId}`\n}\n\nfunction formatLabel(span: ReadableSpan, depth: number) {\n const indent = ' '.repeat(depth) // 2 spaces per depth level\n const label = `${indent}└─ ${span.name}`\n return label.padEnd(LABEL_WIDTH)\n}\n\nfunction buildBar(\n span: ReadableSpan,\n offsetMs: number | undefined,\n totalDurationMs: number | undefined\n) {\n const duration = calculateDuration(span)\n\n if (\n typeof offsetMs !== 'number' ||\n typeof totalDurationMs !== 'number' ||\n totalDurationMs === 0\n ) {\n // fallback: show duration-only bar\n const capped = Math.min(duration, 1000)\n const barLength = Math.max(\n BAR_MIN_WIDTH,\n Math.round((capped / 1000) * BAR_MAX_WIDTH)\n )\n return '█'.repeat(barLength).padEnd(BAR_MAX_WIDTH + 2)\n }\n\n // Relative position and size\n const offsetRatio = Math.max(0, Math.min(offsetMs / totalDurationMs, 1))\n const durationRatio = Math.max(0, Math.min(duration / totalDurationMs, 1))\n\n const offsetChars = Math.floor(offsetRatio * BAR_MAX_WIDTH)\n const barChars = Math.max(\n BAR_MIN_WIDTH,\n Math.round(durationRatio * BAR_MAX_WIDTH)\n )\n\n const empty = ' '.repeat(offsetChars)\n const bar = '█'.repeat(barChars)\n\n return (empty + bar).padEnd(BAR_MAX_WIDTH + 2)\n}\n\nfunction formatDescription(span: ReadableSpan): string {\n const keyPriority = [\n // HTTP\n ['http.method', 'http.target'], // → GET /users/123\n ['http.route'], // → /users/:id\n ['http.url'], // → https://...\n\n // GraphQL\n ['graphql.operation.name'], // → getUsers\n ['graphql.operation.type'], // → query\n ['graphql.document'], // → full query text (maybe too long)\n\n // WebSocket\n ['ws.event'], // → connection, message, disconnect\n ['ws.message_type'], // → ping/pong/text/binary\n ['ws.url'], // → wss://...\n\n // Redis\n ['db.system', 'db.statement'], // → redis, \"SET foo bar\"\n ['db.operation'], // → GET, SET\n\n // Spanner\n ['db.statement'], // → SELECT * FROM...\n ['db.operation'], // → SELECT, INSERT\n ['db.name'], // → projects/.../instances/.../databases/...\n\n // OpenSearch\n ['db.operation'], // → search, index, bulk\n ['db.statement'], // → { query DSL... }\n\n // Pub/Sub (GCP)\n ['messaging.operation'], // → publish, receive\n ['messaging.destination'], // → topic-a\n ['messaging.gcp_pubsub.topic'], // → projects/x/topics/y\n\n // General FaaS\n ['faas.invoked_name'], // → myFunction\n ['faas.trigger'], // → http, pubsub, etc.\n\n // Custom or fallback\n ['otel.description'],\n ]\n\n for (const keys of keyPriority) {\n const parts = keys\n .map((k) => span.attributes[k])\n .filter((v) => v !== undefined && v !== null)\n .map((v) => String(v)) // 👈 FIX — guarantees string\n if (parts.length > 0) {\n return truncate(parts.join(' '), DESCRIPTION_MAX_WIDTH - 1).padEnd(\n DESCRIPTION_MAX_WIDTH\n )\n }\n }\n\n return ''.padEnd(DESCRIPTION_MAX_WIDTH)\n}\n\nfunction formatStatus(span: ReadableSpan): string {\n const code = span.status.code\n const label = statusLabelMap[code] ?? 'UNSET'\n const colorFn = statusColorMap[code] ?? colors.gray\n return colorFn(label).padEnd(6)\n}\n\nfunction formatDuration(\n span: ReadableSpan,\n offsetMs: number | undefined\n): string {\n const duration = calculateDuration(span)\n\n const format = (ms: number): string =>\n ms >= 1000 ? `${(ms / 1000).toFixed(2)} s` : `${ms} ms`\n\n return `(${format(offsetMs || 0)}–${format(duration)})`.padEnd(16)\n}\n\nfunction truncate(input: unknown, maxLength: number): string {\n const str = String(input ?? '')\n return str.length > maxLength ? `${str.slice(0, maxLength - 1)}…` : str\n}\n\nfunction computeDepth(span: ReadableSpan, allSpans: ReadableSpan[]): number {\n let depth = 0\n let currentParentId = span.parentSpanContext?.spanId\n\n while (currentParentId) {\n const parentSpan = allSpans.find(\n (s) => s.spanContext().spanId === currentParentId\n )\n if (!parentSpan) break\n\n depth += 1\n currentParentId = parentSpan.parentSpanContext?.spanId\n }\n\n return depth\n}\n","import { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type {\n PushMetricExporter,\n ResourceMetrics,\n} from '@opentelemetry/sdk-metrics'\nimport { formatMetrics } from './formatters/index'\n\nexport class ConsoleMetricPrettyExporter implements PushMetricExporter {\n private readonly patterns: RegExp[]\n\n constructor() {\n const raw = process.env.METRIC_FILTER ?? ''\n const entries = raw\n .split(',')\n .map((e) => e.trim())\n .filter(Boolean)\n\n this.patterns = entries.map(globToRegex)\n }\n\n private filterMetrics(\n resourceMetrics: ResourceMetrics\n ): ResourceMetrics | undefined {\n // No filter = block all metrics\n if (this.patterns.length === 0) return undefined\n\n const filteredScopes = resourceMetrics.scopeMetrics\n .map((scopeMetric) => {\n const filteredMetrics = scopeMetric.metrics.filter((metric) =>\n this.patterns.some((pattern) => pattern.test(metric.descriptor.name))\n )\n\n if (filteredMetrics.length === 0) return undefined\n\n return {\n ...scopeMetric,\n metrics: filteredMetrics,\n }\n })\n .filter((s): s is NonNullable<typeof s> => s !== undefined)\n\n if (filteredScopes.length === 0) return undefined\n\n return {\n ...resourceMetrics,\n scopeMetrics: filteredScopes,\n }\n }\n\n export(\n metrics: ResourceMetrics,\n resultCallback: (result: ExportResult) => void\n ): void {\n const filtered = this.filterMetrics(metrics)\n if (filtered) {\n console.log(formatMetrics(filtered))\n }\n resultCallback({ code: ExportResultCode.SUCCESS })\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n}\n\nfunction globToRegex(glob: string): RegExp {\n const escaped = glob.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&')\n const regex = `^${escaped.replace(/\\*/g, '.*')}$`\n return new RegExp(regex)\n}\n","import { SeverityNumber } from '@opentelemetry/api-logs'\nimport { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type {\n LogRecordExporter,\n ReadableLogRecord,\n} from '@opentelemetry/sdk-logs'\nimport { LOG_SEVERITY_MAP, type LOG_SEVERITY_NAME } from '../consts'\nimport { formatLogRecord } from './formatters/index'\n\nexport class ConsoleLogPrettyExporter implements LogRecordExporter {\n private readonly logThreshold: number\n constructor() {\n const defaultLogLevel = 'INFO'\n const env = (process.env.LOG_LEVEL?.toUpperCase() ??\n defaultLogLevel) as LOG_SEVERITY_NAME\n this.logThreshold =\n LOG_SEVERITY_MAP[env] ?? LOG_SEVERITY_MAP[defaultLogLevel]\n }\n export(\n logs: ReadableLogRecord[],\n resultCallback: (result: ExportResult) => void\n ): void {\n this._sendLogRecords(logs, resultCallback)\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n\n private _sendLogRecords(\n logRecords: ReadableLogRecord[],\n done: (result: ExportResult) => void\n ): void {\n for (const record of logRecords) {\n if ((record.severityNumber ?? 0) >= this.logThreshold) {\n const formatted = formatLogRecord(record)\n const severity = record.severityNumber || SeverityNumber.UNSPECIFIED\n\n if (severity >= SeverityNumber.ERROR) {\n console.error(formatted)\n } else if (severity >= SeverityNumber.WARN) {\n console.log(formatted)\n } else if (severity >= SeverityNumber.INFO) {\n console.info(formatted)\n } else if (severity >= SeverityNumber.DEBUG) {\n console.debug(formatted)\n } else {\n console.trace(formatted)\n }\n }\n }\n\n done?.({ code: ExportResultCode.SUCCESS })\n }\n}\n","import { SpanStatusCode } from '@opentelemetry/api'\nimport { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-node'\nimport { formatSpans } from './formatters/index'\n\nexport class ConsoleSpanPrettyExporter implements SpanExporter {\n private readonly allowedStatuses: Set<number>\n\n constructor() {\n const env = process.env.SPAN_LEVEL?.toUpperCase()\n if (!env) {\n this.allowedStatuses = new Set([\n SpanStatusCode.UNSET,\n SpanStatusCode.OK,\n SpanStatusCode.ERROR,\n ])\n } else {\n const map: Record<string, number> = {\n UNSET: SpanStatusCode.UNSET,\n OK: SpanStatusCode.OK,\n ERROR: SpanStatusCode.ERROR,\n }\n\n this.allowedStatuses = new Set(\n env\n .split(',')\n .map((s) => s.trim())\n .map((s) => map[s])\n .filter((v): v is number => typeof v === 'number')\n )\n }\n }\n\n private shouldExport(spans: ReadableSpan[]) {\n // print all spans\n if (this.allowedStatuses.size === 3) {\n return true\n }\n // print only certain levels\n return spans.some((span) => this.allowedStatuses.has(span.status.code))\n }\n\n export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void\n ): void {\n if (this.shouldExport(spans)) {\n console.log(formatSpans(spans))\n }\n\n resultCallback({ code: ExportResultCode.SUCCESS })\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n}\n","import type {\n ReadableSpan,\n SpanExporter,\n SpanProcessor,\n} from '@opentelemetry/sdk-trace-node'\n\nexport class TreeSpanProcessor implements SpanProcessor {\n private exporter: SpanExporter\n private orphans: Map<string, ReadableSpan[]> = new Map()\n\n constructor(exporter: SpanExporter) {\n this.exporter = exporter\n }\n\n onStart(): void {\n // no-op\n }\n\n onEnd(span: ReadableSpan): void {\n const parentId = span.parentSpanContext?.spanId\n\n if (parentId) {\n const siblings = this.orphans.get(parentId) || []\n this.orphans.set(parentId, [...siblings, span])\n\n return\n }\n\n const children = this.getChildrenRecursively(span)\n const sorted = [span, ...children].sort((s1, s2) => {\n const [sec1, nano1] = s1.startTime\n const [sec2, nano2] = s2.startTime\n\n if (sec1 !== sec2) return sec1 - sec2\n return nano1 - nano2\n })\n this.exporter.export(sorted, () => {})\n }\n\n private getChildrenRecursively(span: ReadableSpan) {\n const spanId = span.spanContext().spanId\n const children = this.orphans.get(spanId) || []\n this.orphans.delete(spanId)\n\n const result = [...children]\n for (const child of children) {\n result.push(...this.getChildrenRecursively(child))\n }\n\n return result\n }\n\n shutdown(): Promise<void> {\n return this.exporter.shutdown()\n }\n\n async forceFlush(): Promise<void> {\n await this.exporter.forceFlush?.()\n }\n}\n","import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'\nimport { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport type { Resource } from '@opentelemetry/resources'\nimport {\n BatchLogRecordProcessor,\n LoggerProvider,\n type LogRecordProcessor,\n SimpleLogRecordProcessor,\n} from '@opentelemetry/sdk-logs'\nimport { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'\nimport {\n BatchSpanProcessor,\n type SpanProcessor,\n} from '@opentelemetry/sdk-trace-node'\nimport { ConsoleMetricPrettyExporter } from './loggers/console-metric-pretty-exporter'\nimport {\n ConsoleLogPrettyExporter,\n ConsoleSpanPrettyExporter,\n} from './loggers/index'\nimport { TreeSpanProcessor } from './loggers/tree-span-processor'\n\nexport const getLogProvider = (\n resource: Resource,\n otlpEndpoint: string | undefined\n) => {\n // With collector\n if (otlpEndpoint) {\n const exporter = new OTLPLogExporter({ url: `${otlpEndpoint}/v1/logs` })\n const processors: LogRecordProcessor[] = [\n new BatchLogRecordProcessor(exporter),\n ]\n\n // Console logging for cluster\n if (process.env.LOG_LEVEL) {\n const consoleExporter = new ConsoleLogPrettyExporter()\n processors.push(new SimpleLogRecordProcessor(consoleExporter))\n }\n\n return new LoggerProvider({\n resource,\n processors,\n })\n }\n\n // Local dev\n const exporter = new ConsoleLogPrettyExporter()\n const processor = new SimpleLogRecordProcessor(exporter)\n return new LoggerProvider({\n resource,\n processors: [processor],\n })\n}\n\nexport const getSpanProcessor = (\n otlpEndpoint: string | undefined\n): SpanProcessor => {\n const exporter = otlpEndpoint\n ? new OTLPTraceExporter({\n url: `${otlpEndpoint}/v1/traces`,\n })\n : new ConsoleSpanPrettyExporter()\n const processor = otlpEndpoint\n ? new BatchSpanProcessor(exporter)\n : new TreeSpanProcessor(exporter)\n\n return processor\n}\n\nexport const getMetricReader = (otlpEndpoint: string | undefined) => {\n const metricExporter = otlpEndpoint\n ? new OTLPMetricExporter({\n url: `${otlpEndpoint}/v1/metrics`,\n })\n : new ConsoleMetricPrettyExporter()\n const metricReader = new PeriodicExportingMetricReader({\n exporter: metricExporter,\n })\n\n return metricReader\n}\n","import {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from '@opentelemetry/semantic-conventions'\n\n/**\n * Extracts telemetry context from environment (cloud/k8s aware),\n * with support for subservice/component override.\n */\nexport function detectTelemetryContext(componentNameOverride?: string) {\n const {\n OTEL_SERVICE_NAME, // e.g. \"UserSystem\"\n OTEL_SERVICE_VERSION, // e.g. \"1.2.3\"\n K_SERVICE,\n K_REVISION,\n K_CONFIGURATION,\n KUBERNETES_SERVICE_HOST,\n POD_NAME,\n POD_NAMESPACE,\n GCP_PROJECT,\n CLOUD_PROVIDER,\n } = process.env\n\n const systemName = OTEL_SERVICE_NAME || 'unknown-service'\n const systemVersion = OTEL_SERVICE_VERSION || '1.0.0'\n\n // Only use component if explicitly provided\n const componentName = componentNameOverride || undefined\n\n const resourceAttributes = {\n [ATTR_SERVICE_NAME]: systemName,\n [ATTR_SERVICE_VERSION]: systemVersion,\n 'serviceContext.service': systemName,\n 'serviceContext.version': systemVersion,\n ...(K_SERVICE && { 'cloud.run.service': K_SERVICE }),\n ...(K_REVISION && { 'cloud.run.revision': K_REVISION }),\n ...(K_CONFIGURATION && { 'cloud.run.configuration': K_CONFIGURATION }),\n ...(POD_NAME && { 'k8s.pod_name': POD_NAME }),\n ...(POD_NAMESPACE && { 'k8s.namespace_name': POD_NAMESPACE }),\n ...(KUBERNETES_SERVICE_HOST && { 'cloud.orchestrator': 'kubernetes' }),\n ...(GCP_PROJECT && { 'cloud.account.id': GCP_PROJECT }),\n ...(CLOUD_PROVIDER && { 'cloud.provider': CLOUD_PROVIDER }),\n ...(componentName && { 'component.name': componentName }),\n }\n\n return {\n systemName,\n systemVersion,\n componentName,\n resourceAttributes,\n }\n}\n","import { containerDetector } from '@opentelemetry/resource-detector-container'\nimport { gcpDetector } from '@opentelemetry/resource-detector-gcp'\nimport {\n detectResources,\n envDetector,\n osDetector,\n processDetector,\n resourceFromAttributes,\n serviceInstanceIdDetector,\n} from '@opentelemetry/resources'\nimport { detectTelemetryContext } from './otel-context'\n\nconst isOnGcp = () =>\n !!(\n process.env.K_SERVICE ||\n process.env.GAE_APPLICATION ||\n process.env.KUBERNETES_SERVICE_HOST\n )\n\nexport const getResource = async () => {\n const baseRes = detectResources({\n detectors: [\n containerDetector,\n envDetector,\n ...(isOnGcp() ? [gcpDetector] : []),\n osDetector,\n processDetector,\n serviceInstanceIdDetector,\n ],\n })\n\n if (baseRes.waitForAsyncAttributes) {\n await baseRes.waitForAsyncAttributes()\n }\n\n const { resourceAttributes } = detectTelemetryContext()\n const customRes = resourceFromAttributes(resourceAttributes)\n const resource = baseRes.merge(customRes)\n\n if (resource.waitForAsyncAttributes) {\n await resource.waitForAsyncAttributes()\n }\n\n return resource\n}\n","import {\n context,\n DiagConsoleLogger,\n DiagLogLevel,\n diag,\n metrics,\n trace,\n} from '@opentelemetry/api'\nimport { logs } from '@opentelemetry/api-logs'\nimport type { Instrumentation } from '@opentelemetry/instrumentation'\nimport type { LoggerProvider } from '@opentelemetry/sdk-logs'\nimport { NodeSDK } from '@opentelemetry/sdk-node'\nimport { getLogProvider, getMetricReader, getSpanProcessor } from './providers'\nimport { getResource } from './resource'\n\ndiag.disable()\ndiag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR)\n\n// Use globalThis with a Symbol key so the flag is shared even when the module\n// is instantiated more than once (e.g. --import preload vs main app graph when\n// using tsx or other loaders that don't share the ESM module cache).\nconst OTEL_INIT_KEY = Symbol.for('@sebspark/otel:initialized')\nconst OTEL_INIT_PROMISE_KEY = Symbol.for('@sebspark/otel:initPromise')\n\nfunction getGlobal(): {\n [key: symbol]: unknown\n} {\n return globalThis as Record<symbol, unknown>\n}\n\nexport async function initialize(\n ...instrumentations: Promise<Instrumentation>[]\n) {\n const g = getGlobal()\n if (!g[OTEL_INIT_PROMISE_KEY]) {\n const resolvedInstrumentations = await Promise.all(instrumentations)\n const promise = _initialize(resolvedInstrumentations).catch((err) => {\n // Allow re-initialization if the first attempt fails\n g[OTEL_INIT_PROMISE_KEY] = undefined\n throw err\n })\n g[OTEL_INIT_PROMISE_KEY] = promise\n }\n return g[OTEL_INIT_PROMISE_KEY] as Promise<void>\n}\n\nexport function isInitialized() {\n return getGlobal()[OTEL_INIT_KEY] === true\n}\n\nlet sdk: NodeSDK | undefined\nlet logProvider: LoggerProvider | undefined\n\nasync function _initialize(instrumentations: Instrumentation[]) {\n const serviceName = process.env.OTEL_SERVICE_NAME ?? 'unknown-service'\n const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT\n\n const resource = await getResource()\n\n // Reset any previous instrumentation\n context.disable()\n logs.disable()\n trace.disable()\n metrics.disable()\n\n // Manual setup for logs\n logProvider = getLogProvider(resource, otlpEndpoint)\n logs.setGlobalLoggerProvider(logProvider)\n\n // NodeSDK setup\n const spanProcessor = getSpanProcessor(otlpEndpoint)\n const metricReader = getMetricReader(otlpEndpoint)\n sdk = new NodeSDK({\n spanProcessor,\n metricReader,\n instrumentations,\n resource,\n })\n\n sdk.start()\n getGlobal()[OTEL_INIT_KEY] = true\n console.log(`[otel] Telemetry initialized for \"${serviceName}\"`)\n}\n\nexport const dispose = async () => {\n const processes: Promise<void>[] = []\n if (sdk) processes.push(sdk.shutdown())\n if (logProvider) processes.push(logProvider.shutdown())\n\n if (processes.length) {\n console.log('[otel] Shutting down...')\n await Promise.all(processes)\n console.log('[otel] Shutdown complete.')\n }\n}\n","import { context, trace } from '@opentelemetry/api'\nimport { logs } from '@opentelemetry/api-logs'\nimport { LOG_SEVERITY_MAP, type LOG_SEVERITY_NAME } from './consts'\nimport { isInitialized } from './otel'\nimport { detectTelemetryContext } from './otel-context'\n\n// biome-ignore lint/suspicious/noExplicitAny: library\ntype Attrs = Record<string, any>\n\nexport type Logger = ReturnType<typeof getLogger>\nexport function getLogger(serviceOverride?: string, extraAttrs: Attrs = {}) {\n const { systemName, systemVersion, resourceAttributes } =\n detectTelemetryContext(serviceOverride)\n\n const defaultAttrs = {\n ...resourceAttributes,\n ...extraAttrs,\n }\n\n let hasWarnedAboutInit = false\n\n function emit(\n severityText: LOG_SEVERITY_NAME,\n body: string,\n attrs: Attrs = {}\n ) {\n // Get the logger at the last second\n if (!isInitialized() && process.env.NODE_ENV !== 'test') {\n if (!hasWarnedAboutInit) {\n console.warn('OTEL must be initialized before using logger')\n hasWarnedAboutInit = true\n }\n console.log(`[${severityText}] ${body}`)\n return\n }\n const logger = logs.getLogger(systemName, systemVersion)\n\n const span = trace.getSpan(context.active())\n const spanContext = span?.spanContext()\n\n logger.emit({\n severityText,\n severityNumber: LOG_SEVERITY_MAP[severityText],\n body,\n attributes: {\n 'gcp.log_name': systemName.replace(/^@/, '').replace(/\\//g, '-'),\n ...defaultAttrs,\n ...(spanContext && {\n trace_id: spanContext.traceId,\n span_id: spanContext.spanId,\n }),\n ...attrs,\n },\n })\n }\n\n function resolveArgs(\n msg: string | Error,\n errOrAttrs?: Error | Attrs,\n maybeAttrs: Attrs = {}\n ): { body: string; attrs: Attrs } {\n if (errOrAttrs instanceof Error) {\n const body = `${msg}: ${errOrAttrs.stack || errOrAttrs.message}`\n return { body, attrs: maybeAttrs }\n }\n\n const body = msg instanceof Error ? msg.stack || msg.message : msg\n const attrs = errOrAttrs || {}\n return { body, attrs }\n }\n\n type LogFn = {\n (msg: string, attrs?: Attrs): void\n (msg: string, error: Error, attrs?: Attrs): void\n (error: Error, attrs?: Attrs): void\n }\n\n function createLogFn(severity: LOG_SEVERITY_NAME): LogFn {\n return (\n msg: string | Error,\n errOrAttrs?: Error | Attrs,\n maybeAttrs: Attrs = {}\n ) => {\n const { body, attrs } = resolveArgs(msg, errOrAttrs, maybeAttrs)\n emit(severity, body, attrs)\n }\n }\n\n return {\n debug: createLogFn('DEBUG'),\n info: createLogFn('INFO'),\n notice: createLogFn('NOTICE'),\n warn: createLogFn('WARN'),\n error: createLogFn('ERROR'),\n critical: createLogFn('CRITICAL'),\n alert: createLogFn('ALERT'),\n emergency: createLogFn('EMERGENCY'),\n }\n}\n","import { metrics } from '@opentelemetry/api'\nimport { isInitialized } from './otel'\nimport { detectTelemetryContext } from './otel-context'\n\nexport function getMeter(componentNameOverride?: string) {\n if (!isInitialized() && process.env.NODE_ENV !== 'test') {\n console.warn('OTEL must be initialized before using getMeter()')\n }\n\n const { componentName, systemName, systemVersion } = detectTelemetryContext(\n componentNameOverride\n )\n return metrics.getMeter(componentName ?? systemName, systemVersion)\n}\n","import {\n context,\n type SpanOptions,\n SpanStatusCode,\n trace,\n} from '@opentelemetry/api'\nimport { isInitialized } from './otel'\nimport { detectTelemetryContext } from './otel-context'\n\ntype OtelTracer = ReturnType<typeof trace.getTracer>\ntype Span = ReturnType<OtelTracer['startSpan']>\n\ntype Func<T> = (span: Span) => Promise<T> | T\ntype SyncFunc<T> = (span: Span) => T\n\ntype WithTrace = {\n <T>(name: string, fn: Func<T>): Promise<T>\n <T>(name: string, options: SpanOptions, fn: Func<T>): Promise<T>\n <T>(name: string, parent: Span, fn: Func<T>): Promise<T>\n <T>(name: string, options: SpanOptions, parent: Span, fn: Func<T>): Promise<T>\n}\ntype WithTraceSync = {\n <T>(name: string, fn: SyncFunc<T>): T\n <T>(name: string, options: SpanOptions, fn: SyncFunc<T>): T\n <T>(name: string, parent: Span, fn: SyncFunc<T>): T\n <T>(name: string, options: SpanOptions, parent: Span, fn: SyncFunc<T>): T\n}\n\n/**\n * Extended tracer with helper methods for span-wrapped execution\n */\ninterface Tracer extends OtelTracer {\n withTrace: WithTrace\n withTraceSync: WithTraceSync\n}\n\n/**\n * Returns an OpenTelemetry tracer bound to the current service.\n * Includes `withTrace()` and `withTraceSync()` helpers for span-wrapped execution.\n *\n * @param serviceOverride - Optional override for service name\n * @returns Tracer with helpers\n */\nexport function getTracer(componentNameOverride?: string): Tracer {\n if (!isInitialized() && process.env.NODE_ENV !== 'test') {\n console.warn('OTEL must be initialized before calling getTracer()')\n }\n\n const { componentName, systemName, systemVersion } = detectTelemetryContext(\n componentNameOverride\n )\n const tracer = trace.getTracer(\n componentName ?? systemName,\n systemVersion\n ) as Tracer\n\n /**\n * Runs a function inside a new span (async variant).\n * Automatically handles span status and nesting.\n */\n const withTrace: WithTrace = async <T>(\n name: string,\n spanOptionsSpanOrFunc?: SpanOptions | Span | Func<T>,\n spanOrFunc?: Span | Func<T>,\n func?: Func<T>\n ): Promise<T> => {\n const { options, parent, fn } = extractArgs(\n spanOptionsSpanOrFunc,\n spanOrFunc,\n func\n )\n\n const parentContext = parent\n ? trace.setSpan(context.active(), parent)\n : context.active()\n\n const span = tracer.startSpan(name, options, parentContext)\n let ended = false\n const originalEnd = span.end.bind(span)\n const endOnce = () => {\n if (!ended) {\n ended = true\n originalEnd()\n }\n }\n span.end = endOnce\n\n return await context.with(trace.setSpan(parentContext, span), async () => {\n try {\n const result = await fn(span)\n span.setStatus({ code: SpanStatusCode.OK })\n return result\n } catch (err) {\n const error = err as Error\n span.setStatus({ code: SpanStatusCode.ERROR, message: error.message })\n span.recordException?.(error)\n throw err\n } finally {\n endOnce()\n }\n })\n }\n\n /**\n * Runs a synchronous function inside a new span.\n * Automatically handles span status and nesting.\n */\n const withTraceSync: WithTraceSync = <T>(\n name: string,\n spanOptionsSpanOrFunc?: SpanOptions | Span | SyncFunc<T>,\n spanOrFunc?: Span | SyncFunc<T>,\n func?: SyncFunc<T>\n ): T => {\n const { options, parent, fn } = extractArgs(\n spanOptionsSpanOrFunc,\n spanOrFunc,\n func\n )\n\n const parentContext = parent\n ? trace.setSpan(context.active(), parent)\n : context.active()\n\n const span = tracer.startSpan(name, options, parentContext)\n let ended = false\n const originalEnd = span.end.bind(span)\n const endOnce = () => {\n if (!ended) {\n ended = true\n originalEnd()\n }\n }\n span.end = endOnce\n\n return context.with(trace.setSpan(parentContext, span), () => {\n try {\n const result = fn(span)\n span.setStatus({ code: SpanStatusCode.OK })\n return result\n } catch (err) {\n const error = err as Error\n span.setStatus({ code: SpanStatusCode.ERROR, message: error.message })\n span.recordException?.(error)\n throw err\n } finally {\n endOnce()\n }\n })\n }\n\n tracer.withTrace = withTrace\n tracer.withTraceSync = withTraceSync\n\n return tracer\n}\n\ntype TraceArgs<T> = {\n options: SpanOptions\n parent?: Span\n fn: (span: Span) => T\n}\n\nfunction extractArgs<T>(\n spanOptionsSpanOrFunc?: SpanOptions | Span | ((span: Span) => T),\n spanOrFunc?: Span | ((span: Span) => T),\n func?: (span: Span) => T\n): TraceArgs<T> {\n let options: SpanOptions = {}\n let parent: Span | undefined\n let fn: (span: Span) => T\n\n if (isFunction(spanOptionsSpanOrFunc)) {\n fn = spanOptionsSpanOrFunc\n } else if (isFunction(spanOrFunc)) {\n const spanOrSpanOptions = spanOptionsSpanOrFunc as Span | SpanOptions\n if (isSpanOptions(spanOrSpanOptions)) {\n options = spanOrSpanOptions as SpanOptions\n } else {\n parent = spanOrSpanOptions as Span\n }\n fn = spanOrFunc\n } else {\n options = spanOptionsSpanOrFunc as SpanOptions\n parent = spanOrFunc as Span\n // biome-ignore lint/style/noNonNullAssertion: it IS defined here\n fn = func!\n }\n\n return { options, parent, fn }\n}\n\nconst isFunction = (value: unknown): value is (span: Span) => unknown =>\n typeof value === 'function'\nconst isSpan = (value: unknown): value is Span =>\n value !== null &&\n value !== undefined &&\n isFunction((value as Span).spanContext) &&\n isFunction((value as Span).end)\nconst isSpanOptions = (value: unknown): value is SpanOptions =>\n value !== null &&\n value !== undefined &&\n (!!(value as SpanOptions).startTime ||\n !!(value as SpanOptions).attributes ||\n !!(value as SpanOptions).kind) &&\n !isSpan(value)\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sebspark/otel",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"dev": "tsc --watch --noEmit",
|
|
20
20
|
"lint": "biome check .",
|
|
21
21
|
"test": "vitest run --passWithNoTests --coverage",
|
|
22
|
+
"test:e2e": "vitest --config vitest.config.e2e.ts --run",
|
|
22
23
|
"typecheck": "vitest --typecheck.only --passWithNoTests"
|
|
23
24
|
},
|
|
24
25
|
"dependencies": {
|
|
@@ -46,12 +47,20 @@
|
|
|
46
47
|
"@opentelemetry/sdk-node": "0.214.0",
|
|
47
48
|
"@opentelemetry/sdk-trace-node": "2.6.1",
|
|
48
49
|
"@opentelemetry/semantic-conventions": "1.40.0",
|
|
49
|
-
"@sebspark/opentelemetry-instrumentation-opensearch": "0.
|
|
50
|
+
"@sebspark/opentelemetry-instrumentation-opensearch": "0.3.0",
|
|
50
51
|
"fast-safe-stringify": "2.1.1",
|
|
51
52
|
"kleur": "4.1.5"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
|
-
"@
|
|
55
|
+
"@opensearch-project/opensearch": "3.5.1",
|
|
56
|
+
"@opentelemetry/context-async-hooks": "2.6.1",
|
|
57
|
+
"@testcontainers/opensearch": "11.13.0",
|
|
58
|
+
"@testcontainers/redis": "11.13.0",
|
|
59
|
+
"axios": "1.14.0",
|
|
60
|
+
"express": "5.2.1",
|
|
61
|
+
"find-free-ports": "3.1.1",
|
|
62
|
+
"redis": "5.11.0",
|
|
63
|
+
"undici": "7.24.6"
|
|
55
64
|
},
|
|
56
65
|
"repository": {
|
|
57
66
|
"type": "git",
|