{"_id":"@aient/otel","_rev":"4-1d325dadded68f6402eaf7420403eedc","name":"@aient/otel","dist-tags":{"latest":"2.1.0"},"versions":{"1.0.0":{"name":"@aient/otel","version":"1.0.0","author":{"name":"Triple Alpha AB"},"license":"MIT","_id":"@aient/otel@1.0.0","maintainers":[{"name":"haf","email":"henrik@haf.se"}],"dist":{"shasum":"a52cd2922fe54fa0e09b5412e2422759b2cfdac6","tarball":"https://registry.npmjs.org/@aient/otel/-/otel-1.0.0.tgz","fileCount":58,"integrity":"sha512-1pCnbEvBcwH3WMkO/kUK4/3d+Uzg4nqVVOX7GOBjaj/XM0GtEX2QTs9oE0KJ9IQatnkuXnJZuQDUAjxWv/TZ/Q==","signatures":[{"sig":"MEYCIQCF8m2eW+fwTPR7QDWiJzVg9qKp4YrZw+Pc1palk/C01QIhAMv1leoBMTWt66WsVW7kZr/EnxYoqG8K+ugok2S5jgbb","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3649325},"type":"module","_from":"file:aient-otel-1.0.0.tgz","types":"./dist/types/index.d.ts","engines":{"node":"^18 || ^20 || ^22 || ^24"},"exports":{".":{"edge":{"types":"./dist/types/index.d.ts","import":"./dist/edge/index.js","default":"./dist/edge/index.js"},"node":{"types":"./dist/types/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"types":"./dist/types/index.d.ts","import":"./dist/edge/index.js","worker":{"types":"./dist/types/index.d.ts","import":"./dist/edge/index.js","default":"./dist/edge/index.js"},"browser":{"types":"./dist/types/index.d.ts","import":"./dist/edge/index.js","default":"./dist/edge/index.js"},"default":"./dist/edge/index.js","workerd":{"types":"./dist/types/index.d.ts","import":"./dist/edge/index.js","default":"./dist/edge/index.js"},"edge-light":{"types":"./dist/types/index.d.ts","import":"./dist/edge/index.js","default":"./dist/edge/index.js"}}},"private":false,"scripts":{"lint":"pnpm eslint","build":"pnpm clean && pnpm tsx build.ts && pnpm build-types && pnpm build-site","clean":"rm -rf dist && rm -rf dist-site","eslint":"node ./runner/eslint.mjs","lint:fix":"pnpm eslint-fix","test:unit":"pnpm unit-test","unit-test":"vitest --run","build-only":"pnpm tsx build.ts","build-site":"pnpm build-typedoc && mkdir -p dist-site && cp index.html LICENSE CHANGELOG.md dist-site","eslint-fix":"node ./runner/eslint.mjs --fix","type-check":"pnpm build-types","build-types":"tsc --project tsconfig.types.json","build-typedoc":"pnpm typedoc src/index.ts","test:unit:watch":"pnpm unit-test-watch","unit-test-watch":"vitest"},"_npmUser":{"name":"haf","email":"henrik@haf.se"},"_resolved":"/private/var/folders/ln/9kcrdg0x1_s2w5m05flp9v280000gn/T/fda232da1ba8a57d129ba8179308b1f6/aient-otel-1.0.0.tgz","_integrity":"sha512-1pCnbEvBcwH3WMkO/kUK4/3d+Uzg4nqVVOX7GOBjaj/XM0GtEX2QTs9oE0KJ9IQatnkuXnJZuQDUAjxWv/TZ/Q==","_npmVersion":"11.8.0","description":"Aient wrapper around OpenTelemetry APIs","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","chalk":"^5.6.2","eslint":"^9.18.0","globby":"^16.0.0","vitest":"4.0.15","esbuild":"^0.27.1","typedoc":"^0.28.15","@eslint/js":"^9.18.0","log-update":"^7.0.2","protobufjs":"^7.5.4","typescript":"^5.9.3","@types/node":"25.0.1","typescript-config":"1.0.0","typescript-eslint":"^8.20.0","@opentelemetry/api":"^1.9.0","@opentelemetry/core":"^2.2.0","@opentelemetry/api-logs":"^0.208.0","@opentelemetry/sdk-logs":"^0.208.0","@opentelemetry/resources":"^2.2.0","@opentelemetry/sdk-metrics":"^2.2.0","@opentelemetry/sdk-trace-base":"^2.2.0","@opentelemetry/instrumentation":"^0.208.0","@opentelemetry/otlp-transformer":"^0.208.0","@opentelemetry/otlp-exporter-base":"^0.208.0","@opentelemetry/context-async-hooks":"^2.2.0","@opentelemetry/exporter-trace-otlp-http":"^0.208.0"},"peerDependencies":{"@opentelemetry/api":">=1.9.0 <3.0.0","@opentelemetry/api-logs":">=0.200.0 <0.300.0","@opentelemetry/sdk-logs":">=0.200.0 <0.300.0","@opentelemetry/resources":">=2.0.0 <3.0.0","@opentelemetry/sdk-metrics":">=2.0.0 <3.0.0","@opentelemetry/sdk-trace-base":">=2.0.0 <3.0.0","@opentelemetry/instrumentation":">=0.200.0 <0.300.0"},"_npmOperationalInternal":{"tmp":"tmp/otel_1.0.0_1775196848949_0.3107737562477886","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@aient/otel","version":"1.0.1","author":{"name":"Triple Alpha AB"},"license":"MIT","_id":"@aient/otel@1.0.1","maintainers":[{"name":"haf","email":"henrik@haf.se"}],"dist":{"shasum":"869c9bc3a9cea3731785fa91818d77466c565cfa","tarball":"https://registry.npmjs.org/@aient/otel/-/otel-1.0.1.tgz","fileCount":67,"integrity":"sha512-C/6aHCjh1wXLTR7CA2Md0wFO6XHraPL/jRRUvjyXoSQakk60LENqBFUfcV4Y9fxZSuFcCWO7ZNMCMtQKQnFVjQ==","signatures":[{"sig":"MEQCIG/1/9JO5YX1o43O/0MGFH/QpEjaJ/NlmB+JWT+H8YUeAiAsw7U5dy7i+/6ob1jdw/HIZnTSYilR6nKPq88xblp0oQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3681602},"type":"module","types":"./dist/types/index.d.ts","engines":{"node":"^18 || ^20 || ^22 || ^24"},"exports":{".":{"edge":"./dist/edge/index.js","node":"./dist/node/index.js","types":"./dist/types/index.d.ts","import":"./dist/node/index.js","worker":"./dist/edge/index.js","browser":"./dist/edge/index.js","default":"./dist/node/index.js","workerd":"./dist/edge/index.js","edge-light":"./dist/edge/index.js"},"./exception-attributes":{"edge":"./dist/edge/exception-attributes.js","node":"./dist/node/exception-attributes.js","types":"./dist/types/exception-attributes.d.ts","import":"./dist/node/exception-attributes.js","worker":"./dist/edge/exception-attributes.js","browser":"./dist/edge/exception-attributes.js","default":"./dist/node/exception-attributes.js","workerd":"./dist/edge/exception-attributes.js","edge-light":"./dist/edge/exception-attributes.js"}},"gitHead":"3d6a0402c21f718c25c059c162d9f21920462ef2","private":false,"scripts":{"lint":"pnpm eslint","build":"pnpm clean && pnpm tsx build.ts && pnpm build-types && pnpm build-site","clean":"rm -rf dist && rm -rf dist-site","eslint":"node ./runner/eslint.mjs","prepare":"pnpm clean && pnpm build-only && pnpm build-types","lint:fix":"pnpm eslint-fix","test:unit":"pnpm unit-test","unit-test":"vitest --run","build-only":"pnpm tsx build.ts","build-site":"pnpm build-typedoc && mkdir -p dist-site && cp index.html LICENSE CHANGELOG.md dist-site","eslint-fix":"node ./runner/eslint.mjs --fix","type-check":"pnpm build-types","build-types":"tsc --project tsconfig.types.json","build-typedoc":"pnpm typedoc src/index.ts","prepublishOnly":"pnpm build","test:unit:watch":"pnpm unit-test-watch","unit-test-watch":"vitest"},"_npmUser":{"name":"haf","email":"henrik@haf.se"},"_npmVersion":"11.8.0","description":"Aient wrapper around OpenTelemetry APIs","directories":{},"sideEffects":false,"_nodeVersion":"24.13.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","chalk":"^5.6.2","eslint":"^9.18.0","globby":"^16.0.0","vitest":"4.0.15","esbuild":"^0.27.1","typedoc":"^0.28.15","@eslint/js":"^9.18.0","log-update":"^7.0.2","protobufjs":"^7.5.4","typescript":"^5.9.3","@types/node":"25.0.1","typescript-config":"workspace:*","typescript-eslint":"^8.20.0","@opentelemetry/api":"^1.9.0","@opentelemetry/core":"^2.2.0","@opentelemetry/api-logs":"^0.208.0","@opentelemetry/sdk-logs":"^0.208.0","@opentelemetry/resources":"^2.2.0","@opentelemetry/sdk-metrics":"^2.2.0","@opentelemetry/sdk-trace-base":"^2.2.0","@opentelemetry/instrumentation":"^0.208.0","@opentelemetry/otlp-transformer":"^0.208.0","@opentelemetry/otlp-exporter-base":"^0.208.0","@opentelemetry/context-async-hooks":"^2.2.0","@opentelemetry/exporter-trace-otlp-http":"^0.208.0"},"peerDependencies":{"@opentelemetry/api":">=1.9.0 <3.0.0","@opentelemetry/api-logs":">=0.200.0 <0.300.0","@opentelemetry/sdk-logs":">=0.200.0 <0.300.0","@opentelemetry/resources":">=2.0.0 <3.0.0","@opentelemetry/sdk-metrics":">=2.0.0 <3.0.0","@opentelemetry/sdk-trace-base":">=2.0.0 <3.0.0","@opentelemetry/instrumentation":">=0.200.0 <0.300.0"},"_npmOperationalInternal":{"tmp":"tmp/otel_1.0.1_1776101120147_0.6147327116302546","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@aient/otel","version":"2.0.0","author":{"name":"Triple Alpha AB"},"license":"MIT","_id":"@aient/otel@2.0.0","maintainers":[{"name":"haf","email":"henrik@haf.se"}],"dist":{"shasum":"02724f060d9c133fdc7970e5caa2131ebece636e","tarball":"https://registry.npmjs.org/@aient/otel/-/otel-2.0.0.tgz","fileCount":66,"integrity":"sha512-zBFVUoxI5sh7Ja+G6LGsXrl/Lf0h/Kp/4gqCouqEQkEP5WIVOOhH04jN/bz72PHAYyco6tKMbdXljXNX37kw2g==","signatures":[{"sig":"MEYCIQDCt9QubswcEpy8OvW68+3nOTs6VboAmZGLpd3oq1D7IAIhALR45Prs2VPQW2qhIIrNTY3IcEFYkUPdn+hJ+V4BQBRZ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2742794},"type":"module","types":"./dist/types/index.d.ts","engines":{"node":"^18 || ^20 || ^22 || ^24"},"exports":{".":{"edge":"./dist/edge/index.js","node":"./dist/node/index.js","types":"./dist/types/index.d.ts","import":"./dist/node/index.js","worker":"./dist/edge/index.js","browser":"./dist/edge/index.js","default":"./dist/node/index.js","workerd":"./dist/edge/index.js","edge-light":"./dist/edge/index.js"},"./exception-attributes":{"edge":"./dist/edge/exception-attributes.js","node":"./dist/node/exception-attributes.js","types":"./dist/types/exception-attributes.d.ts","import":"./dist/node/exception-attributes.js","worker":"./dist/edge/exception-attributes.js","browser":"./dist/edge/exception-attributes.js","default":"./dist/node/exception-attributes.js","workerd":"./dist/edge/exception-attributes.js","edge-light":"./dist/edge/exception-attributes.js"}},"gitHead":"8c9197371c7a2312ed3a19c1649761e7c9019365","private":false,"scripts":{"lint":"pnpm eslint","test":"pnpm test:unit","build":"pnpm clean && pnpm tsx build.ts && pnpm build-types && pnpm build-site","clean":"rm -rf dist && rm -rf dist-site","eslint":"node ./runner/eslint.mjs","prepare":"pnpm clean && pnpm build-only && pnpm build-types","lint:fix":"pnpm eslint-fix","test:unit":"pnpm unit-test","unit-test":"vitest --run","build-only":"pnpm tsx build.ts","build-site":"pnpm build-typedoc && mkdir -p dist-site && cp index.html LICENSE CHANGELOG.md dist-site","eslint-fix":"node ./runner/eslint.mjs --fix","type-check":"tsc --project tsconfig.types.json --noEmit","build-types":"tsc --project tsconfig.types.json","build-typedoc":"pnpm typedoc src/index.ts","prepublishOnly":"pnpm build","test:unit:watch":"pnpm unit-test-watch","unit-test-watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:893c496a-1d1e-4034-901f-ec3840ea273a"}},"_npmVersion":"11.11.0","description":"Aient wrapper around OpenTelemetry APIs","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","chalk":"^5.6.2","eslint":"^9.18.0","globby":"^16.0.0","vitest":"4.0.15","esbuild":"^0.27.1","typedoc":"^0.28.15","@eslint/js":"^9.18.0","log-update":"^7.0.2","typescript":"^5.9.3","@types/node":"25.0.1","typescript-config":"workspace:*","typescript-eslint":"^8.20.0","@opentelemetry/api":"^1.9.0","@opentelemetry/core":"^2.2.0","@opentelemetry/api-logs":"^0.208.0","@opentelemetry/sdk-logs":"^0.208.0","@opentelemetry/resources":"^2.2.0","@opentelemetry/sdk-metrics":"^2.2.0","@opentelemetry/sdk-trace-base":"^2.2.0","@opentelemetry/instrumentation":"^0.208.0","@opentelemetry/context-async-hooks":"^2.2.0"},"peerDependencies":{"@opentelemetry/api":">=1.9.0 <3.0.0","@opentelemetry/api-logs":">=0.200.0 <0.300.0","@opentelemetry/sdk-logs":">=0.200.0 <0.300.0","@opentelemetry/resources":">=2.0.0 <3.0.0","@opentelemetry/sdk-metrics":">=2.0.0 <3.0.0","@opentelemetry/sdk-trace-base":">=2.0.0 <3.0.0","@opentelemetry/instrumentation":">=0.200.0 <0.300.0"},"_npmOperationalInternal":{"tmp":"tmp/otel_2.0.0_1778167829929_0.8201384077755041","host":"s3://npm-registry-packages-npm-production"}},"2.1.0":{"name":"@aient/otel","version":"2.1.0","private":false,"publishConfig":{"access":"public"},"description":"Aient wrapper around OpenTelemetry APIs","author":{"name":"Triple Alpha AB"},"license":"MIT","sideEffects":false,"type":"module","exports":{".":{"types":"./dist/types/index.d.ts","browser":"./dist/edge/index.js","edge":"./dist/edge/index.js","edge-light":"./dist/edge/index.js","worker":"./dist/edge/index.js","workerd":"./dist/edge/index.js","node":"./dist/node/index.js","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./exception-attributes":{"types":"./dist/types/exception-attributes.d.ts","browser":"./dist/edge/exception-attributes.js","edge":"./dist/edge/exception-attributes.js","edge-light":"./dist/edge/exception-attributes.js","worker":"./dist/edge/exception-attributes.js","workerd":"./dist/edge/exception-attributes.js","node":"./dist/node/exception-attributes.js","import":"./dist/node/exception-attributes.js","default":"./dist/node/exception-attributes.js"}},"types":"./dist/types/index.d.ts","engines":{"node":"^18 || ^20 || ^22 || ^24"},"scripts":{"build":"pnpm clean && pnpm tsx build.ts && pnpm build-types && pnpm build-site","build-only":"pnpm tsx build.ts","build-types":"tsc --project tsconfig.types.json","build-site":"pnpm build-typedoc && mkdir -p dist-site && cp index.html LICENSE CHANGELOG.md dist-site","build-typedoc":"pnpm typedoc src/index.ts","clean":"rm -rf dist && rm -rf dist-site","lint":"pnpm eslint","lint:fix":"pnpm eslint-fix","eslint":"node ./runner/eslint.mjs","eslint-fix":"node ./runner/eslint.mjs --fix","prepare":"pnpm clean && pnpm build-only && pnpm build-types","prepublishOnly":"pnpm build","type-check":"tsc --project tsconfig.types.json --noEmit","test":"pnpm test:unit","test:unit":"pnpm unit-test","test:unit:watch":"pnpm unit-test-watch","unit-test":"vitest --run","unit-test-watch":"vitest"},"devDependencies":{"@eslint/js":"^9.18.0","@opentelemetry/api":"^1.9.0","@opentelemetry/api-logs":"^0.208.0","@opentelemetry/context-async-hooks":"^2.2.0","@opentelemetry/core":"^2.2.0","@opentelemetry/instrumentation":"^0.208.0","@opentelemetry/resources":"^2.2.0","@opentelemetry/sdk-logs":"^0.208.0","@opentelemetry/sdk-metrics":"^2.2.0","@opentelemetry/sdk-trace-base":"^2.2.0","@types/node":"25.0.1","chalk":"^5.6.2","esbuild":"^0.27.1","eslint":"^9.18.0","globby":"^16.0.0","log-update":"^7.0.2","tsx":"^4.21.0","typedoc":"^0.28.19","typescript":"^5.9.3","typescript-config":"workspace:*","typescript-eslint":"^8.20.0","vitest":"4.0.15"},"peerDependencies":{"@opentelemetry/api":">=1.9.0 <3.0.0","@opentelemetry/api-logs":">=0.200.0 <0.300.0","@opentelemetry/instrumentation":">=0.200.0 <0.300.0","@opentelemetry/resources":">=2.0.0 <3.0.0","@opentelemetry/sdk-logs":">=0.200.0 <0.300.0","@opentelemetry/sdk-metrics":">=2.0.0 <3.0.0","@opentelemetry/sdk-trace-base":">=2.0.0 <3.0.0"},"gitHead":"1b7f83ee238e7f7783dce4f9955d92ab14152c8a","_id":"@aient/otel@2.1.0","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-R3bvD//Qpqs9ZN/5FK0IaAvlmQwp60zdlQSHZdjIP2RGB1U/B5EXydugx+lNfCP3b9LVUEOPKm3KU/BojUku0Q==","shasum":"37fe8bf64bf342dbf1856fd72f388a9b286291fb","tarball":"https://registry.npmjs.org/@aient/otel/-/otel-2.1.0.tgz","fileCount":66,"unpackedSize":2765564,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIG6/aYYBy70yhASJ/GgNjAM8BMRcCvffKB6RyzgvapabAiAkVE0/u33Jsdb1WfKvHIgXyumC3ftEythAz5vEwtd83g=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:893c496a-1d1e-4034-901f-ec3840ea273a"}},"directories":{},"maintainers":[{"name":"haf","email":"henrik@haf.se"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/otel_2.1.0_1785524866702_0.8651368286440853"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-03T06:14:08.824Z","modified":"2026-07-31T19:07:47.063Z","1.0.0":"2026-04-03T06:14:09.118Z","1.0.1":"2026-04-13T17:25:20.443Z","2.0.0":"2026-05-07T15:30:30.158Z","2.1.0":"2026-07-31T19:07:46.909Z"},"author":{"name":"Triple Alpha AB"},"license":"MIT","description":"Aient wrapper around OpenTelemetry APIs","maintainers":[{"name":"haf","email":"henrik@haf.se"}],"readme":"# @aient/otel\n\nOpenTelemetry for Node.js/Next.js/Edge. Works out of the box, highly configurable.\n\n## Quick Start (3 lines)\n\n```bash\nnpm install @aient/otel @opentelemetry/api @opentelemetry/api-logs\n```\n\n```ts\n// instrumentation.ts (Next.js 13.4+)\nimport { registerOTel } from '@aient/otel'\n\nexport function register() {\n  registerOTel({ serviceName: 'my-app' })\n}\n```\n\nBrowser-propagated `app.installation.id`, `enduser.id`, and `enduser.pseudo.id` are untrusted correlation hints. `@aient/otel` projects only those safe browser identity fields, then applies `attributesFromHeaders`, so a gateway/session-derived trusted `enduser.id` wins. Never map a freely client-set header as trusted identity, and never authorize from baggage.\n\nDone. Traces go to `https://ingest.aient.ai/v1/traces` by default, logs to `/v1/logs`.\n\n### Local Development\n\nFor local development with a collector on localhost, set the env var:\n\n```bash\nOTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318\n```\n\n### Custom Endpoint (programmatic)\n\nTo set the endpoint in code instead of env vars, use `exporterUrl`:\n\n```ts\nregisterOTel({\n  serviceName: 'my-app',\n  exporterUrl: 'https://my-collector.example.com', // SDK appends /v1/traces and /v1/logs\n  exporterHeaders: { 'x-api-key': 'your-key' },    // optional custom headers\n})\n```\n\n---\n\n## Full Example (all options)\n\n```ts\nimport { registerOTel, OTLPHttpJsonTraceExporter, OTLPHttpJsonLogsExporter } from '@aient/otel'\nimport { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'\nimport { BatchLogRecordProcessor } from '@opentelemetry/sdk-logs'\n\nexport function register() {\n  registerOTel({\n    // Identity\n    serviceName: 'my-app',\n    attributes: {\n      'app.version': process.env.npm_package_version,\n    },\n\n    // Release metadata (CRITICAL for source mapping)\n    // Config takes precedence over env vars (COMMIT_SHA, COMMIT_REF, etc.)\n    release: {\n      commit: process.env.COMMIT_SHA,\n      branch: process.env.COMMIT_REF,\n      version: '1.0.0',\n      environment: 'production',\n    },\n\n    // Aient auth (or set AIENT_PUBLISHABLE_KEY env var)\n    publishableKey: process.env.AIENT_PUBLISHABLE_KEY,\n\n    // Extract request context\n    attributesFromHeaders: {\n      'enduser.id': 'x-user-id',\n      'tenant.id': 'x-tenant-id',\n      'client.ip': 'x-forwarded-for',\n    },\n\n    // Sampling (10% in production)\n    traceSampler: 'parentbased_traceidratio',\n\n    // Error handling\n    captureUnhandledErrors: true,\n    exitOnUnhandledException: true,\n    flushTimeoutMs: 2000,\n\n    // Custom endpoint (alternative to OTEL_EXPORTER_OTLP_ENDPOINT env var)\n    exporterUrl: 'https://collector.example.com',\n    exporterHeaders: { 'x-api-key': 'your-key' },\n\n    // Debug logging (alternative to OTEL_LOG_LEVEL env var)\n    logLevel: 'DEBUG',  // 'ALL' | 'VERBOSE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'NONE'\n\n    // Multi-backend fan-out (advanced - overrides exporterUrl)\n    // spanProcessors: [\n    //   new BatchSpanProcessor(new OTLPHttpJsonTraceExporter({\n    //     url: 'https://collector-a.example.com/v1/traces',\n    //   })),\n    //   new BatchSpanProcessor(new OTLPHttpJsonTraceExporter({\n    //     url: 'https://collector-b.example.com/v1/traces',\n    //   })),\n    // ],\n  })\n}\n```\n\n```bash\n# Set sampling ratio\nOTEL_TRACES_SAMPLER_ARG=0.1\n```\n\n---\n\n## Environment Variables\n\nConfigure via env instead of code:\n\n```bash\n# Endpoints\nOTEL_EXPORTER_OTLP_ENDPOINT=https://collector.example.com  # Base URL\nOTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://traces.example.com/v1/traces\nOTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://logs.example.com/v1/logs\n\n# Protocol\nOTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/json\nOTEL_EXPORTER_OTLP_LOGS_PROTOCOL=http/json\n# Legacy http/protobuf values are accepted for compatibility but fall back to JSON.\n\n# Headers\nOTEL_EXPORTER_OTLP_HEADERS=x-api-key=secret,env=prod\n\n# Sampling\nOTEL_TRACES_SAMPLER=parentbased_traceidratio\nOTEL_TRACES_SAMPLER_ARG=0.1\n\n# Service\nOTEL_SERVICE_NAME=my-service\nOTEL_SDK_DISABLED=true  # Kill switch\n\n# Aient auth\nAIENT_PUBLISHABLE_KEY=pk_xxx\n```\n\n---\n\n## OTLP JSON protocol contract\n\nThe SDK exports traces and logs as OTLP/HTTP JSON protobuf payloads with `Content-Type: application/json`.\n\nThe serializer follows the OTLP JSON mapping used by the OpenTelemetry protocol:\n\n- request envelopes are `ExportTraceServiceRequest` and `ExportLogsServiceRequest` JSON objects (`resourceSpans` and `resourceLogs`);\n- JSON field names are lowerCamelCase, for example `startTimeUnixNano` and `droppedAttributesCount`;\n- trace IDs and span IDs are hex strings, not base64;\n- 64-bit timestamps and integer attribute values are decimal strings;\n- enum fields such as span kind, span status, and log severity are encoded as numbers;\n- arbitrary byte attributes are base64 strings;\n- spans and logs are grouped by resource and instrumentation scope, including schema URLs when present.\n\n`@aient/otel` does not bundle `protobufjs`, `@opentelemetry/otlp-transformer`, `@opentelemetry/otlp-exporter-base`, or `@opentelemetry/exporter-trace-otlp-http`. Protocol-sensitive serializer behavior is covered by `test/otlp-json-serializer.test.ts`, and dependency regressions are covered by `test/package-contract.test.ts`.\n\n---\n\n## Build Metadata (required for source mapping)\n\nSet commit info for Aient to map errors to code. Use either the `release` config option or environment variables:\n\n**Via config (recommended):**\n```ts\nregisterOTel({\n  serviceName: 'my-app',\n  release: {\n    commit: process.env.COMMIT_SHA,\n    branch: process.env.COMMIT_REF,\n    version: '1.0.0',\n    environment: 'production',\n  }\n})\n```\n\n**Via environment variables:**\n```bash\nCOMMIT_SHA=$(git rev-parse HEAD)\nCOMMIT_REF=$(git rev-parse --abbrev-ref HEAD)\nBUILD_DATE=$(date -u +\"%Y-%m-%dT%H:%M:%SZ\")\n```\n\nAlso reads `VERCEL_GIT_COMMIT_SHA`, `NEXT_PUBLIC_COMMIT_SHA`, etc.\n\n---\n\n## Manual Spans & Logs\n\n```ts\nimport { trace } from '@opentelemetry/api'\nimport { logs, SeverityNumber } from '@opentelemetry/api-logs'\n\n// Spans\nconst tracer = trace.getTracer('my-component')\nconst span = tracer.startSpan('operation')\nspan.setAttribute('key', 'value')\nspan.end()\n\n// Logs\nconst logger = logs.getLogger('my-component')\nlogger.emit({\n  severityNumber: SeverityNumber.INFO,\n  body: 'User signed up',\n  attributes: { plan: 'pro' },\n})\n```\n\n---\n\n## Recording external-service failures on the active span\n\nWhen integrating with third-party systems (GitHub, Slack, Stripe, Linear, email providers, etc),\nprefer attaching the failure reason to the *current active span* so traces are self-explanatory.\n\n```ts\nimport { recordExternalFailure, recordExternalFailureReason } from '@aient/otel'\n\n// When you have an Error/exception:\ntry {\n  await doExternalCall()\n} catch (e) {\n  recordExternalFailure({\n    system: 'github',\n    operation: 'listInstallationRepos',\n    error: e,\n    attributes: {\n      'aient.external.http.status_code': 404,\n      'aient.external.installation_id': 123,\n    },\n  })\n  throw e\n}\n\n// When you only have a protocol-level error string (no exception thrown):\nrecordExternalFailureReason({\n  system: 'slack',\n  operation: 'chat.postMessage',\n  reason: 'not_in_channel',\n  attributes: { 'aient.external.slack.channel': 'C123...' },\n})\n```\n\nNotes:\n- Both helpers set span status to **ERROR**, attach `glimt.external.*` attributes, and emit an `exception` event.\n- `recordExternalFailureReason` **does not** synthesize an Error/stacktrace (to avoid misleading stacks).\n\n---\n\n## Defaults\n\n| Feature | Default |\n|---------|---------|\n| Trace exporter | `http/json` → `https://ingest.aient.ai/v1/traces` |\n| Log exporter | `http/json` → `https://ingest.aient.ai/v1/logs` |\n| Sampler | `always_on` |\n| Propagators | W3C Trace Context + Baggage |\n| Instrumentations | `fetch`, Node `http/https` |\n| Error capture | `uncaughtException`, `unhandledRejection` → log + flush + exit |\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}