{"_id":"@aotoki/edge-otel","_rev":"2-76782a93f225918e95cbabe8508c306a","name":"@aotoki/edge-otel","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@aotoki/edge-otel","version":"0.1.0","keywords":["opentelemetry","edge","cloudflare-workers","tracing"],"author":{"name":"Aotokitsuruya"},"license":"Apache-2.0","_id":"@aotoki/edge-otel@0.1.0","maintainers":[{"name":"elct9620","email":"elct9620@frost.tw"}],"homepage":"https://github.com/elct9620/edge-otel#readme","bugs":{"url":"https://github.com/elct9620/edge-otel/issues"},"dist":{"shasum":"2c9cc7effd2d0a3825716cc38784b4e6b5698bf7","tarball":"https://registry.npmjs.org/@aotoki/edge-otel/-/edge-otel-0.1.0.tgz","fileCount":17,"integrity":"sha512-EGUMwVlUnFZUN7fF2MA8D2xCm3qSSLOlVF7/Z0EIPSLfk1GmtRmVnB5tXYCC4OlRlJdU4eOgG3cjoxFgsaNomw==","signatures":[{"sig":"MEQCIBFxFPf623zCp7/NIyVMGc3LL8IS2/EWGF8Y4WsbG6u0AiBFj8BT5NNLk3oyQqMCfYxrrNAthHXmu3ZBS2ZMcPR0Ng==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":50531},"type":"module","_from":"file:aotoki-edge-otel-0.1.0.tgz","exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"}},"./middleware/hono":{"import":{"types":"./dist/middleware/hono.d.mts","default":"./dist/middleware/hono.mjs"}},"./exporters/langfuse":{"import":{"types":"./dist/exporters/langfuse.d.mts","default":"./dist/exporters/langfuse.mjs"}}},"scripts":{"lint":"eslint .","test":"vitest run","build":"tsdown","format":"prettier --write .","lint:fix":"eslint . --fix","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"elct9620","email":"elct9620@frost.tw"},"_resolved":"/private/var/folders/vl/4zdff9yd5132j4719fxx7fl80000gn/T/f2c47e1a726152f9d6dc506f33746911/aotoki-edge-otel-0.1.0.tgz","_integrity":"sha512-EGUMwVlUnFZUN7fF2MA8D2xCm3qSSLOlVF7/Z0EIPSLfk1GmtRmVnB5tXYCC4OlRlJdU4eOgG3cjoxFgsaNomw==","repository":{"url":"git+https://github.com/elct9620/edge-otel.git","type":"git"},"_npmVersion":"10.9.4","description":"Lightweight OpenTelemetry SDK for V8 isolate edge runtimes","directories":{},"_nodeVersion":"22.22.0","dependencies":{"@opentelemetry/api":"^1.9.1","@opentelemetry/core":"^2.6.1","@opentelemetry/resources":"^2.6.1","@opentelemetry/sdk-trace-base":"^2.6.1","@opentelemetry/context-async-hooks":"^2.6.1"},"_hasShrinkwrap":false,"devDependencies":{"hono":"^4.12.10","jiti":"^2.6.1","eslint":"^10.2.0","tsdown":"^0.21.7","vitest":"^4.1.2","prettier":"^3.8.1","@eslint/js":"^10.0.1","typescript":"^6.0.2","typescript-eslint":"^8.58.0"},"peerDependencies":{"hono":">=4.0.0"},"peerDependenciesMeta":{"hono":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/edge-otel_0.1.0_1775476396292_0.9046326016336457","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@aotoki/edge-otel","version":"0.2.0","description":"Lightweight OpenTelemetry SDK for V8 isolate edge runtimes","type":"module","exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"}},"./exporters/langfuse":{"import":{"types":"./dist/exporters/langfuse.d.mts","default":"./dist/exporters/langfuse.mjs"}}},"keywords":["opentelemetry","edge","cloudflare-workers","tracing"],"repository":{"type":"git","url":"git+https://github.com/elct9620/edge-otel.git"},"bugs":{"url":"https://github.com/elct9620/edge-otel/issues"},"homepage":"https://github.com/elct9620/edge-otel#readme","author":{"name":"Aotokitsuruya"},"license":"Apache-2.0","devDependencies":{"@eslint/js":"^10.0.1","@vitest/coverage-v8":"^4.1.2","eslint":"^10.2.0","jiti":"^2.6.1","prettier":"^3.8.1","tsdown":"^0.21.7","typescript":"^6.0.2","typescript-eslint":"^8.58.0","vitest":"^4.1.2"},"dependencies":{"@opentelemetry/api":"^1.9.1","@opentelemetry/context-async-hooks":"^2.6.1","@opentelemetry/core":"^2.6.1","@opentelemetry/resources":"^2.6.1","@opentelemetry/sdk-trace-base":"^2.6.1"},"scripts":{"build":"tsdown","test":"vitest run","test:watch":"vitest","lint":"eslint .","lint:fix":"eslint . --fix","format":"prettier --write .","format:check":"prettier --check ."},"_id":"@aotoki/edge-otel@0.2.0","_integrity":"sha512-HCGiC864B9Tdxz5CYYfsV1iy+Xf9JoX9ps8NvyqZr8CQ43G36es0XGS3q2vjR7E4oP8GdgMAOcAF0x4gBv91mQ==","_resolved":"/private/var/folders/vl/4zdff9yd5132j4719fxx7fl80000gn/T/fffa77394781ce71acbe33787297e029/aotoki-edge-otel-0.2.0.tgz","_from":"file:aotoki-edge-otel-0.2.0.tgz","_nodeVersion":"22.22.0","_npmVersion":"10.9.4","dist":{"integrity":"sha512-HCGiC864B9Tdxz5CYYfsV1iy+Xf9JoX9ps8NvyqZr8CQ43G36es0XGS3q2vjR7E4oP8GdgMAOcAF0x4gBv91mQ==","shasum":"1dedb4d861b0191a7933e9144b1ad6333c579ce1","tarball":"https://registry.npmjs.org/@aotoki/edge-otel/-/edge-otel-0.2.0.tgz","fileCount":13,"unpackedSize":41620,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGbccEFh8f2QftkEMk+Adft9Y+CyOBktBW9ltMQ5KxSpAiAanxLWHUz4EgnZR/IVTIGmdfADuyIdVHXPBnwvO6Wcmg=="}]},"_npmUser":{"name":"elct9620","email":"elct9620@frost.tw"},"directories":{},"maintainers":[{"name":"elct9620","email":"elct9620@frost.tw"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/edge-otel_0.2.0_1775484860511_0.9032056958332773"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-06T11:53:16.179Z","modified":"2026-04-06T14:14:20.809Z","0.1.0":"2026-04-06T11:53:16.427Z","0.2.0":"2026-04-06T14:14:20.673Z"},"bugs":{"url":"https://github.com/elct9620/edge-otel/issues"},"author":{"name":"Aotokitsuruya"},"license":"Apache-2.0","homepage":"https://github.com/elct9620/edge-otel#readme","keywords":["opentelemetry","edge","cloudflare-workers","tracing"],"repository":{"type":"git","url":"git+https://github.com/elct9620/edge-otel.git"},"description":"Lightweight OpenTelemetry SDK for V8 isolate edge runtimes","maintainers":[{"name":"elct9620","email":"elct9620@frost.tw"}],"readme":"# @aotoki/edge-otel\n\n[![Tests](https://github.com/elct9620/edge-otel/actions/workflows/tests.yml/badge.svg)](https://github.com/elct9620/edge-otel/actions/workflows/tests.yml)\n[![codecov](https://codecov.io/gh/elct9620/edge-otel/graph/badge.svg)](https://codecov.io/gh/elct9620/edge-otel)\n\nLightweight OpenTelemetry SDK for V8 isolate edge runtimes (Cloudflare Workers, Vercel Edge Functions, Deno Deploy).\n\nThe standard `@opentelemetry/sdk-node` depends on `node:perf_hooks`, `node:async_hooks`, and `node:http`, which are absent or broken in V8 isolate runtimes. This package provides a correct OTel span exporter and tracer provider that works in these environments using only Web Platform APIs (`fetch`, `btoa`) — no Node.js built-ins required.\n\n## Features\n\n- **OTLP/HTTP JSON exporter** — exports spans to any OTLP-compatible collector (Langfuse, Grafana Tempo, Honeycomb, Jaeger, etc.)\n- **SimpleSpanProcessor** — per-span buffering with explicit flush, no background timers\n- **Context propagation** — `AsyncLocalStorage`-based trace grouping across multiple AI SDK calls\n- **Langfuse preset** — pre-configured exporter for Langfuse backend\n- **Manual spans** — standard OTel `Tracer` API for custom instrumentation (RAG, DB queries, etc.)\n- **Streaming support** — defer flush until the stream is fully consumed\n\n## Install\n\n```bash\npnpm add @aotoki/edge-otel\n```\n\n## Quick Start\n\n### Cloudflare Workers\n\n```typescript\nimport { createTracerProvider } from \"@aotoki/edge-otel\";\n\nconst provider = createTracerProvider({\n  endpoint: \"https://your-collector.example.com/v1/traces\",\n  headers: {\n    Authorization: \"Bearer your-token\",\n  },\n});\n\nconst tracer = provider.getTracer(\"ai\");\n\n// Use tracer with AI SDK\nconst result = await generateText({\n  model: openai(\"gpt-4o\"),\n  prompt: \"Hello!\",\n  experimental_telemetry: {\n    isEnabled: true,\n    tracer,\n  },\n});\n\n// Flush spans before the isolate exits\nctx.waitUntil(provider.forceFlush());\n```\n\n### Manual Spans\n\n```typescript\nconst tracer = provider.getTracer(\"ai\");\n\n// Custom spans appear alongside AI SDK spans in the same trace\nconst docs = await tracer.startActiveSpan(\"rag.retrieve\", async (span) => {\n  try {\n    const results = await vectorStore.similaritySearch(query, 5);\n    span.setAttribute(\"rag.result_count\", results.length);\n    return results;\n  } finally {\n    span.end();\n  }\n});\n\nconst result = await generateText({\n  model: openai(\"gpt-4o\"),\n  prompt: buildPrompt(docs),\n  experimental_telemetry: { isEnabled: true, tracer },\n});\n```\n\n## API\n\n### `createTracerProvider(options): TracerProvider`\n\nCreates a tracer provider wired with `SimpleSpanProcessor` and `OtlpHttpJsonExporter`. Options include `endpoint`, `headers`, `serviceName`, and `resourceAttributes`. Returns a provider with `getTracer(scopeName)` and `forceFlush()`.\n\n```typescript\nimport { createTracerProvider } from \"@aotoki/edge-otel\";\n```\n\n### `langfuseExporter(options): LangfuseExporterConfig`\n\nConstructs exporter configuration for Langfuse. Spread the result into `createTracerProvider`. Accepts `publicKey`, `secretKey`, and optional `baseUrl`, `environment`, `release`.\n\n```typescript\nimport { langfuseExporter } from \"@aotoki/edge-otel/exporters/langfuse\";\n```\n\n### `OtlpHttpJsonExporter`\n\nExported for advanced use cases (e.g., multiple backends, custom span processors).\n\n```typescript\nimport { OtlpHttpJsonExporter } from \"@aotoki/edge-otel\";\n```\n\n## Requirements\n\n- **Cloudflare Workers**: `nodejs_compat` compatibility flag required for multi-call trace grouping via `AsyncLocalStorage`\n- **Single AI SDK call per request**: No compatibility flag needed\n\n## Documentation\n\nFor detailed specifications and design rationale:\n\n- [Specification Overview](SPEC.md) — project scope, user journeys, and feature list\n- [API Contracts & Types](docs/contracts.md) — public API surface, type contracts, and correctness rules\n- [Architecture](docs/architecture.md) — layer structure, directory mapping, and dependency graph\n- [Behavior Specs](docs/behavior/) — exporter, provider, context propagation, error handling\n- [Langfuse Backend Guide](docs/backends/langfuse.md) — Langfuse-specific configuration and semantic mapping\n\n## Contributing\n\n```bash\npnpm install        # Install dependencies\npnpm test           # Run tests\npnpm lint           # Lint\npnpm format:check   # Check formatting\n```\n\n## License\n\nApache-2.0\n","readmeFilename":"README.md"}