diff --git a/apps/docs/lib/integrations/data.ts b/apps/docs/lib/integrations/data.ts index 8d0708d788..bf4469cbfb 100644 --- a/apps/docs/lib/integrations/data.ts +++ b/apps/docs/lib/integrations/data.ts @@ -2147,6 +2147,56 @@ export default defineInstrumentation({ \`\`\``, configure: `Create a write key in the Raindrop dashboard and expose it as \`RAINDROP_WRITE_KEY\`. Raindrop's Vercel AI SDK integration picks up the AI SDK spans eve emits on every turn. See the [instrumentation guide](/docs/guides/instrumentation) for the trace hierarchy and the \`recordInputs\`/\`recordOutputs\` controls.`, }, + "telemetry-dev": { + logo: "telemetry-dev", + docsHref: "/docs/guides/instrumentation", + keywords: ["otel", "opentelemetry", "tracing", "observability", "tokens", "cost", "llm"], + install: `Add the telemetry.dev integration from eve's registry: + +\`\`\`bash +eve add instrumentation/telemetry-dev +\`\`\``, + + quickStart: `eve installs an instrumentation file that registers telemetry.dev as the OpenTelemetry provider and a hook that emits lifecycle logs for sessions, turns, steps, tool results, and subagent calls: + +\`\`\`ts +// agent/instrumentation.ts +import { telemetryDevInstrumentation } from "@telemetry-dev/eve"; +import { defineInstrumentation } from "eve/instrumentation"; + +export default defineInstrumentation(telemetryDevInstrumentation()); +\`\`\` + +\`\`\`ts +// agent/hooks/telemetry-dev.ts +import { telemetryDevHook } from "@telemetry-dev/eve"; +import { defineHook } from "eve/hooks"; + +export default defineHook(telemetryDevHook()); +\`\`\` + +telemetry.dev also ingests OTLP directly, so you can skip the package and point \`@vercel/otel\` at its endpoint instead — either setup works: + +\`\`\`ts +// agent/instrumentation.ts +import { OTLPHttpProtoTraceExporter, registerOTel } from "@vercel/otel"; +import { defineInstrumentation } from "eve/instrumentation"; + +export default defineInstrumentation({ + setup: ({ agentName }) => + registerOTel({ + serviceName: agentName, + traceExporter: new OTLPHttpProtoTraceExporter({ + url: "https://ingest.telemetry.dev/v1/traces", + headers: { + Authorization: \`Bearer \${process.env.TELEMETRY_DEV_API_KEY}\`, + }, + }), + }), +}); +\`\`\``, + configure: `Create an ingest API key in the [telemetry.dev](https://telemetry.dev) dashboard and expose it as \`TELEMETRY_DEV_API_KEY\`; without the key the packaged integration is a no-op. Traces and lifecycle logs land in your telemetry.dev project joined by \`gen_ai.conversation.id\`, with tokens, cost, and latency attached to every turn. See the [instrumentation guide](/docs/guides/instrumentation) for the trace hierarchy and the \`recordInputs\`/\`recordOutputs\` controls.`, + }, jaeger: { logo: "jaeger", docsHref: "/docs/guides/instrumentation", diff --git a/apps/docs/lib/integrations/logos.tsx b/apps/docs/lib/integrations/logos.tsx index 354923aa5e..b5bc92cc01 100644 --- a/apps/docs/lib/integrations/logos.tsx +++ b/apps/docs/lib/integrations/logos.tsx @@ -686,6 +686,47 @@ export const raindropLogo = (props: LogoProps) => ( ); +export const telemetryDevLogo = (props: LogoProps) => ( + + + + + + + + + + + +); + export const logos = { eve: eveLogo, web: webLogo, @@ -708,6 +749,7 @@ export const logos = { braintrust: braintrustLogo, jaeger: jaegerLogo, raindrop: raindropLogo, + "telemetry-dev": telemetryDevLogo, kernel: kernelLogo, upstash: upstashLogo, arcana: arcanaLogo, diff --git a/apps/docs/package.json b/apps/docs/package.json index 01283f8f97..6c8df073e5 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -73,6 +73,7 @@ "@posthog/ai": "7.19.6", "@resend/chat-sdk-adapter": "0.2.2", "@tailwindcss/postcss": "4.3.0", + "@telemetry-dev/eve": "0.1.0", "@types/mdx": "2.0.13", "@types/node": "catalog:", "@types/pngjs": "^6.0.5", diff --git a/apps/docs/registry.json b/apps/docs/registry.json index 9bd080207c..b709d6e1aa 100644 --- a/apps/docs/registry.json +++ b/apps/docs/registry.json @@ -2184,6 +2184,28 @@ } ] }, + { + "name": "instrumentation/telemetry-dev", + "type": "registry:item", + "title": "telemetry.dev", + "description": "Send agent traces to telemetry.dev with tokens, cost, and latency on every turn.", + "dependencies": ["@telemetry-dev/eve"], + "envVars": { + "TELEMETRY_DEV_API_KEY": "" + }, + "files": [ + { + "path": "registry/instrumentation/telemetry-dev.ts", + "type": "registry:file", + "target": "agent/instrumentation.ts" + }, + { + "path": "registry/instrumentation/telemetry-dev-hook.ts", + "type": "registry:file", + "target": "agent/hooks/telemetry-dev.ts" + } + ] + }, { "name": "instrumentation/jaeger", "type": "registry:item", diff --git a/apps/docs/registry/instrumentation/telemetry-dev-hook.ts b/apps/docs/registry/instrumentation/telemetry-dev-hook.ts new file mode 100644 index 0000000000..6bffc95a9b --- /dev/null +++ b/apps/docs/registry/instrumentation/telemetry-dev-hook.ts @@ -0,0 +1,4 @@ +import { telemetryDevHook } from "@telemetry-dev/eve"; +import { defineHook } from "eve/hooks"; + +export default defineHook(telemetryDevHook()); diff --git a/apps/docs/registry/instrumentation/telemetry-dev.ts b/apps/docs/registry/instrumentation/telemetry-dev.ts new file mode 100644 index 0000000000..cdaf3017c5 --- /dev/null +++ b/apps/docs/registry/instrumentation/telemetry-dev.ts @@ -0,0 +1,4 @@ +import { telemetryDevInstrumentation } from "@telemetry-dev/eve"; +import { defineInstrumentation } from "eve/instrumentation"; + +export default defineInstrumentation(telemetryDevInstrumentation()); diff --git a/apps/docs/scripts/validate-instrumentation-registry.ts b/apps/docs/scripts/validate-instrumentation-registry.ts index 433ab7f625..c814536f1f 100644 --- a/apps/docs/scripts/validate-instrumentation-registry.ts +++ b/apps/docs/scripts/validate-instrumentation-registry.ts @@ -25,6 +25,7 @@ const registrySlugsByCatalogSlug: Readonly> = { "honeycomb-instrumentation": "honeycomb", arize: "arize", raindrop: "raindrop", + "telemetry-dev": "telemetry-dev", jaeger: "jaeger", }; @@ -61,6 +62,14 @@ for (const item of items) { }, ] : []), + ...(slug === "telemetry-dev" + ? [ + { + path: "registry/instrumentation/telemetry-dev-hook.ts", + target: "agent/hooks/telemetry-dev.ts", + }, + ] + : []), ]; const actualFiles = item.files?.map(({ path, target }) => ({ path, target })); if (JSON.stringify(actualFiles) !== JSON.stringify(expectedFiles)) { diff --git a/packages/eve-catalog/src/index.ts b/packages/eve-catalog/src/index.ts index 5ff1dfb4d9..1b266eb029 100644 --- a/packages/eve-catalog/src/index.ts +++ b/packages/eve-catalog/src/index.ts @@ -863,6 +863,13 @@ export const INTEGRATIONS: readonly IntegrationEntry[] = [ tagline: "Send agent traces to Raindrop to detect and debug AI product issues.", surfaces: { scaffoldable: false, registry: true, gallery: true }, }, + { + slug: "telemetry-dev", + name: "telemetry.dev", + kind: "instrumentation", + tagline: "Send agent traces to telemetry.dev with tokens, cost, and latency on every turn.", + surfaces: { scaffoldable: false, gallery: true }, + }, { slug: "jaeger", name: "Jaeger", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9b19ef4f88..e83e830b97 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -320,6 +320,9 @@ importers: '@tailwindcss/postcss': specifier: 4.3.0 version: 4.3.0 + '@telemetry-dev/eve': + specifier: 0.1.0 + version: 0.1.0(eve@packages+eve) '@types/mdx': specifier: 2.0.13 version: 2.0.13 @@ -7068,6 +7071,23 @@ packages: peerDependencies: vite: ^5.2.0 || ^6 || ^7 || ^8 + '@telemetry-dev/eve@0.1.0': + resolution: {integrity: sha512-6vLOTmxTj8WndJkVfPv/pVVF0Q9SCi4rh3aZz3FGly/s4Wdq4au9bX/HciNo6DDHmv1Cn+gT3MMk16DW8jg9pg==} + peerDependencies: + eve: '>=0.19.0 <1' + + '@telemetry-dev/otel@0.1.0': + resolution: {integrity: sha512-Ydx+5/Y12tgeGgx2rR4E3Vmf0QEe923YahK44OMHPZo7fRXD5q3D1s17hvwqt9b4ba18Fjln+7m5tfW7jXfTWg==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@opentelemetry/api': '>=1.9.0 <2' + + '@telemetry-dev/sdk@0.1.0': + resolution: {integrity: sha512-NXoFKCRfCsweZ02LsQW9Bes96B3ousDhD4vC5lLUMep99/IwdCzxHapgzDF/xzNl9Pa/ZqRfrJXLJFYxBRBNOg==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@opentelemetry/api': '>=1.9.0 <2' + '@tokenizer/inflate@0.4.1': resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} engines: {node: '>=18'} @@ -21460,6 +21480,33 @@ snapshots: tailwindcss: 4.3.0 vite: 8.1.5(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.49.0)(tsx@4.21.0)(yaml@2.9.0) + '@telemetry-dev/eve@0.1.0(eve@packages+eve)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@telemetry-dev/sdk': 0.1.0(@opentelemetry/api@1.9.1) + eve: link:packages/eve + + '@telemetry-dev/otel@0.1.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.218.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.218.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.10.0(@opentelemetry/api@1.9.1) + + '@telemetry-dev/sdk@0.1.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.218.0 + '@opentelemetry/core': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.218.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.10.0(@opentelemetry/api@1.9.1) + '@telemetry-dev/otel': 0.1.0(@opentelemetry/api@1.9.1) + '@tokenizer/inflate@0.4.1(supports-color@10.2.2)': dependencies: debug: 4.4.3(supports-color@10.2.2)