From e1a774b2cb658c946e1b80900ac4e8d2dd6d3950 Mon Sep 17 00:00:00 2001 From: Eric Allam Date: Sat, 11 Jan 2025 21:21:52 +0000 Subject: [PATCH 1/5] WIP langsmith & AI SDK integration --- .../cli-v3/src/entryPoints/dev-run-worker.ts | 1 + packages/core/src/v3/config.ts | 2 + packages/core/src/v3/otel/tracingSDK.ts | 5 ++ pnpm-lock.yaml | 29 +++++++++++ references/nextjs-realtime/package.json | 1 + references/nextjs-realtime/src/trigger/ai.ts | 10 ++-- references/nextjs-realtime/trigger.config.ts | 50 +++++++++++++++++++ 7 files changed, 94 insertions(+), 4 deletions(-) diff --git a/packages/cli-v3/src/entryPoints/dev-run-worker.ts b/packages/cli-v3/src/entryPoints/dev-run-worker.ts index 8784b1dfe5..31b9d458a6 100644 --- a/packages/cli-v3/src/entryPoints/dev-run-worker.ts +++ b/packages/cli-v3/src/entryPoints/dev-run-worker.ts @@ -129,6 +129,7 @@ async function bootstrap() { const tracingSDK = new TracingSDK({ url: env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://0.0.0.0:4318", instrumentations: config.instrumentations ?? [], + exporters: config.exporters ?? [], diagLogLevel: (env.OTEL_LOG_LEVEL as TracingDiagnosticLogLevel) ?? "none", forceFlushTimeoutMillis: 30_000, }); diff --git a/packages/core/src/v3/config.ts b/packages/core/src/v3/config.ts index d565d62614..ccfc7dfd5d 100644 --- a/packages/core/src/v3/config.ts +++ b/packages/core/src/v3/config.ts @@ -56,6 +56,8 @@ export type TriggerConfig = { */ instrumentations?: Array; + exporters?: Array; + /** * Specify a custom path to your tsconfig file. This is useful if you have a custom tsconfig file that you want to use. */ diff --git a/packages/core/src/v3/otel/tracingSDK.ts b/packages/core/src/v3/otel/tracingSDK.ts index 929b0c8011..8a40da8ac9 100644 --- a/packages/core/src/v3/otel/tracingSDK.ts +++ b/packages/core/src/v3/otel/tracingSDK.ts @@ -85,6 +85,7 @@ export type TracingSDKConfig = { forceFlushTimeoutMillis?: number; resource?: IResource; instrumentations?: Instrumentation[]; + exporters?: SpanExporter[]; diagLogLevel?: TracingDiagnosticLogLevel; }; @@ -153,6 +154,10 @@ export class TracingSDK { ) ); + for (const exporter of config.exporters ?? []) { + traceProvider.addSpanProcessor(new SimpleSpanProcessor(exporter)); + } + traceProvider.register(); registerInstrumentations({ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 20f797707c..45c135f554 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1667,6 +1667,9 @@ importers: date-fns: specifier: ^4.1.0 version: 4.1.0 + langsmith: + specifier: ^0.2.15 + version: 0.2.15(openai@4.68.4) lucide-react: specifier: ^0.451.0 version: 0.451.0(react@18.3.1) @@ -16938,6 +16941,10 @@ packages: resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} dev: true + /@types/uuid@10.0.0: + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + dev: false + /@types/uuid@9.0.0: resolution: {integrity: sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==} dev: true @@ -24007,6 +24014,23 @@ packages: engines: {node: '>=14.0.0'} dev: false + /langsmith@0.2.15(openai@4.68.4): + resolution: {integrity: sha512-homtJU41iitqIZVuuLW7iarCzD4f39KcfP9RTBWav9jifhrsDa1Ez89Ejr+4qi72iuBu8Y5xykchsGVgiEZ93w==} + peerDependencies: + openai: '*' + peerDependenciesMeta: + openai: + optional: true + dependencies: + '@types/uuid': 10.0.0 + commander: 10.0.1 + openai: 4.68.4(zod@3.23.8) + p-queue: 6.6.2 + p-retry: 4.6.2 + semver: 7.6.3 + uuid: 10.0.0 + dev: false + /language-subtag-registry@0.3.22: resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} dev: true @@ -31387,6 +31411,11 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + /uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + dev: false + /uuid@3.4.0: resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. diff --git a/references/nextjs-realtime/package.json b/references/nextjs-realtime/package.json index 9a00ea0b51..d3d1e505a6 100644 --- a/references/nextjs-realtime/package.json +++ b/references/nextjs-realtime/package.json @@ -27,6 +27,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "date-fns": "^4.1.0", + "langsmith": "^0.2.15", "lucide-react": "^0.451.0", "next": "14.2.15", "openai": "^4.68.4", diff --git a/references/nextjs-realtime/src/trigger/ai.ts b/references/nextjs-realtime/src/trigger/ai.ts index 26d4c63a9f..71a08a1318 100644 --- a/references/nextjs-realtime/src/trigger/ai.ts +++ b/references/nextjs-realtime/src/trigger/ai.ts @@ -4,6 +4,7 @@ import { streamText, type TextStreamPart } from "ai"; import { setTimeout } from "node:timers/promises"; import { z } from "zod"; import OpenAI from "openai"; +import { AISDKExporter } from "langsmith/vercel"; const openaiSDK = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, @@ -98,13 +99,14 @@ export const openaiStreaming = schemaTask({ run: async ({ model, prompt }) => { logger.info("Running OpenAI model", { model, prompt }); + const telemetrySettings = AISDKExporter.getSettings(); + + logger.info("Telemetry settings", { telemetrySettings }); + const result = streamText({ model: openai(model), prompt, - tools: { - getWeather: weatherTask.tool, - }, - maxSteps: 10, + experimental_telemetry: telemetrySettings, }); const stream = await metadata.stream("openai", result.fullStream); diff --git a/references/nextjs-realtime/trigger.config.ts b/references/nextjs-realtime/trigger.config.ts index 96a51a6b94..46d755fe5c 100644 --- a/references/nextjs-realtime/trigger.config.ts +++ b/references/nextjs-realtime/trigger.config.ts @@ -1,9 +1,59 @@ import { defineConfig } from "@trigger.dev/sdk/v3"; import { rscExtension } from "@trigger.dev/rsc"; +import { AISDKExporter } from "langsmith/vercel"; +import { Client } from "langsmith"; + +class LangsmithSpanExporterWrapper { + constructor( + private underlyingExporter: any, + private transformSpan: (span: any) => any | undefined = (span) => { + if (span.attributes["$span.partial"]) { + // Skip partial spans + return; + } + + // Check if this is an attempt span + if (span.name.startsWith("Attempt ")) { + // Create a new span that wraps the original but modifies spanContext + const spanContext = span.spanContext(); + + return { + ...span, + spanContext: () => spanContext, + parentSpanId: undefined, + }; + } + return span; + } + ) {} + + export(spans: any[], resultCallback: (result: any) => void): void { + const modifiedSpans = spans.map(this.transformSpan); + this.underlyingExporter.export(modifiedSpans.filter(Boolean), resultCallback); + } + + shutdown(): Promise { + return this.underlyingExporter.shutdown(); + } + + forceFlush?(): Promise { + return this.underlyingExporter.forceFlush + ? this.underlyingExporter.forceFlush() + : Promise.resolve(); + } +} + +const client = new Client(); + +const exporter = new AISDKExporter({ + debug: true, + client, +}); export default defineConfig({ project: "proj_bzhdaqhlymtuhlrcgbqy", dirs: ["./src/trigger"], + exporters: [new LangsmithSpanExporterWrapper(exporter)], build: { extensions: [rscExtension({ reactDomEnvironment: "worker" })], }, From 551a6afd389c62fc22ec2ef9ea5c60bbaac96ecf Mon Sep 17 00:00:00 2001 From: Eric Allam Date: Sat, 11 Jan 2025 21:22:47 +0000 Subject: [PATCH 2/5] Add changeset --- .changeset/rich-trainers-glow.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/rich-trainers-glow.md diff --git a/.changeset/rich-trainers-glow.md b/.changeset/rich-trainers-glow.md new file mode 100644 index 0000000000..d9faa804dc --- /dev/null +++ b/.changeset/rich-trainers-glow.md @@ -0,0 +1,6 @@ +--- +"trigger.dev": patch +"@trigger.dev/core": patch +--- + +Add otel exporter support From 11be90037d5562b82d4fb2aac68ffaeff79ad406 Mon Sep 17 00:00:00 2001 From: Eric Allam Date: Sat, 11 Jan 2025 21:35:19 +0000 Subject: [PATCH 3/5] Add exporter support to deployed tasks --- packages/cli-v3/src/entryPoints/deploy-run-worker.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cli-v3/src/entryPoints/deploy-run-worker.ts b/packages/cli-v3/src/entryPoints/deploy-run-worker.ts index a4bea9e393..54da875bef 100644 --- a/packages/cli-v3/src/entryPoints/deploy-run-worker.ts +++ b/packages/cli-v3/src/entryPoints/deploy-run-worker.ts @@ -149,6 +149,7 @@ async function bootstrap() { const tracingSDK = new TracingSDK({ url: env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://0.0.0.0:4318", instrumentations: config.instrumentations ?? [], + exporters: config.exporters ?? [], diagLogLevel: (env.OTEL_LOG_LEVEL as TracingDiagnosticLogLevel) ?? "none", forceFlushTimeoutMillis: 30_000, }); From d40a4383c08c15794731febf0f1fc68a1c4ba599 Mon Sep 17 00:00:00 2001 From: Eric Allam Date: Mon, 13 Jan 2025 15:17:15 +0000 Subject: [PATCH 4/5] Better support for external exporters and group exporters and instrumentations under the telemetry config property --- .../src/entryPoints/deploy-run-worker.ts | 4 +- .../cli-v3/src/entryPoints/dev-run-worker.ts | 4 +- packages/core/src/v3/config.ts | 18 ++++++- packages/core/src/v3/otel/tracingSDK.ts | 17 +++++- references/nextjs-realtime/src/trigger/ai.ts | 4 ++ references/nextjs-realtime/trigger.config.ts | 52 ++----------------- 6 files changed, 44 insertions(+), 55 deletions(-) diff --git a/packages/cli-v3/src/entryPoints/deploy-run-worker.ts b/packages/cli-v3/src/entryPoints/deploy-run-worker.ts index 54da875bef..2c6154a65a 100644 --- a/packages/cli-v3/src/entryPoints/deploy-run-worker.ts +++ b/packages/cli-v3/src/entryPoints/deploy-run-worker.ts @@ -148,8 +148,8 @@ async function bootstrap() { const tracingSDK = new TracingSDK({ url: env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://0.0.0.0:4318", - instrumentations: config.instrumentations ?? [], - exporters: config.exporters ?? [], + instrumentations: config.telemetry?.instrumentations ?? config.instrumentations ?? [], + exporters: config.telemetry?.exporters ?? [], diagLogLevel: (env.OTEL_LOG_LEVEL as TracingDiagnosticLogLevel) ?? "none", forceFlushTimeoutMillis: 30_000, }); diff --git a/packages/cli-v3/src/entryPoints/dev-run-worker.ts b/packages/cli-v3/src/entryPoints/dev-run-worker.ts index 31b9d458a6..e299dd1ebf 100644 --- a/packages/cli-v3/src/entryPoints/dev-run-worker.ts +++ b/packages/cli-v3/src/entryPoints/dev-run-worker.ts @@ -128,8 +128,8 @@ async function bootstrap() { const tracingSDK = new TracingSDK({ url: env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://0.0.0.0:4318", - instrumentations: config.instrumentations ?? [], - exporters: config.exporters ?? [], + instrumentations: config.telemetry?.instrumentations ?? config.instrumentations ?? [], + exporters: config.telemetry?.exporters ?? [], diagLogLevel: (env.OTEL_LOG_LEVEL as TracingDiagnosticLogLevel) ?? "none", forceFlushTimeoutMillis: 30_000, }); diff --git a/packages/core/src/v3/config.ts b/packages/core/src/v3/config.ts index ccfc7dfd5d..2a13859bf7 100644 --- a/packages/core/src/v3/config.ts +++ b/packages/core/src/v3/config.ts @@ -53,10 +53,26 @@ export type TriggerConfig = { * Instrumentations to use for OpenTelemetry. This is useful if you want to add custom instrumentations to your tasks. * * @see https://trigger.dev/docs/config/config-file#instrumentations + * + * @deprecated Use the `telemetry.instrumentations` option instead. */ instrumentations?: Array; - exporters?: Array; + telemetry?: { + /** + * Instrumentations to use for OpenTelemetry. This is useful if you want to add custom instrumentations to your tasks. + * + * @see https://trigger.dev/docs/config/config-file#instrumentations + */ + instrumentations?: Array; + + /** + * Exporters to use for OpenTelemetry. This is useful if you want to add custom exporters to your tasks. + * + * @see https://trigger.dev/docs/config/config-file#exporters + */ + exporters?: Array; + }; /** * Specify a custom path to your tsconfig file. This is useful if you have a custom tsconfig file that you want to use. diff --git a/packages/core/src/v3/otel/tracingSDK.ts b/packages/core/src/v3/otel/tracingSDK.ts index 8a40da8ac9..76d5ab6f86 100644 --- a/packages/core/src/v3/otel/tracingSDK.ts +++ b/packages/core/src/v3/otel/tracingSDK.ts @@ -154,8 +154,23 @@ export class TracingSDK { ) ); + const externalTraceId = crypto.randomUUID(); + for (const exporter of config.exporters ?? []) { - traceProvider.addSpanProcessor(new SimpleSpanProcessor(exporter)); + traceProvider.addSpanProcessor( + getEnvVar("OTEL_BATCH_PROCESSING_ENABLED") === "1" + ? new BatchSpanProcessor(new ExternalSpanExporterWrapper(exporter, externalTraceId), { + maxExportBatchSize: parseInt(getEnvVar("OTEL_SPAN_MAX_EXPORT_BATCH_SIZE") ?? "64"), + scheduledDelayMillis: parseInt( + getEnvVar("OTEL_SPAN_SCHEDULED_DELAY_MILLIS") ?? "200" + ), + exportTimeoutMillis: parseInt( + getEnvVar("OTEL_SPAN_EXPORT_TIMEOUT_MILLIS") ?? "30000" + ), + maxQueueSize: parseInt(getEnvVar("OTEL_SPAN_MAX_QUEUE_SIZE") ?? "512"), + }) + : new SimpleSpanProcessor(new ExternalSpanExporterWrapper(exporter, externalTraceId)) + ); } traceProvider.register(); diff --git a/references/nextjs-realtime/src/trigger/ai.ts b/references/nextjs-realtime/src/trigger/ai.ts index 71a08a1318..e11524e823 100644 --- a/references/nextjs-realtime/src/trigger/ai.ts +++ b/references/nextjs-realtime/src/trigger/ai.ts @@ -110,6 +110,10 @@ export const openaiStreaming = schemaTask({ }); const stream = await metadata.stream("openai", result.fullStream); + + for await (const chunk of stream) { + logger.log("Received chunk", { chunk }); + } }, }); diff --git a/references/nextjs-realtime/trigger.config.ts b/references/nextjs-realtime/trigger.config.ts index 46d755fe5c..bed71e2eff 100644 --- a/references/nextjs-realtime/trigger.config.ts +++ b/references/nextjs-realtime/trigger.config.ts @@ -1,59 +1,13 @@ import { defineConfig } from "@trigger.dev/sdk/v3"; import { rscExtension } from "@trigger.dev/rsc"; import { AISDKExporter } from "langsmith/vercel"; -import { Client } from "langsmith"; - -class LangsmithSpanExporterWrapper { - constructor( - private underlyingExporter: any, - private transformSpan: (span: any) => any | undefined = (span) => { - if (span.attributes["$span.partial"]) { - // Skip partial spans - return; - } - - // Check if this is an attempt span - if (span.name.startsWith("Attempt ")) { - // Create a new span that wraps the original but modifies spanContext - const spanContext = span.spanContext(); - - return { - ...span, - spanContext: () => spanContext, - parentSpanId: undefined, - }; - } - return span; - } - ) {} - - export(spans: any[], resultCallback: (result: any) => void): void { - const modifiedSpans = spans.map(this.transformSpan); - this.underlyingExporter.export(modifiedSpans.filter(Boolean), resultCallback); - } - - shutdown(): Promise { - return this.underlyingExporter.shutdown(); - } - - forceFlush?(): Promise { - return this.underlyingExporter.forceFlush - ? this.underlyingExporter.forceFlush() - : Promise.resolve(); - } -} - -const client = new Client(); - -const exporter = new AISDKExporter({ - debug: true, - client, -}); export default defineConfig({ project: "proj_bzhdaqhlymtuhlrcgbqy", dirs: ["./src/trigger"], - exporters: [new LangsmithSpanExporterWrapper(exporter)], + telemetry: { + exporters: [new AISDKExporter()], + }, build: { extensions: [rscExtension({ reactDomEnvironment: "worker" })], }, From d3bd091b8846efebf592f176d5ab8546b5d33761 Mon Sep 17 00:00:00 2001 From: Eric Allam Date: Mon, 13 Jan 2025 16:34:20 +0000 Subject: [PATCH 5/5] Missing changes --- packages/cli-v3/src/config.ts | 6 +- packages/core/src/v3/config.ts | 1 + packages/core/src/v3/otel/tracingSDK.ts | 49 +++++++ .../core/src/v3/semanticInternalAttributes.ts | 1 + packages/core/src/v3/workers/taskExecutor.ts | 1 + pnpm-lock.yaml | 121 +++++++++++++++++- references/nextjs-realtime/package.json | 1 + 7 files changed, 174 insertions(+), 6 deletions(-) diff --git a/packages/cli-v3/src/config.ts b/packages/cli-v3/src/config.ts index 3283c15eb6..928169abc7 100644 --- a/packages/cli-v3/src/config.ts +++ b/packages/cli-v3/src/config.ts @@ -317,8 +317,10 @@ function adaptResolveEnvVarsToSyncEnvVarsExtension( function getInstrumentedPackageNames(config: ResolvedConfig): Array { const packageNames = []; - if (config.instrumentations) { - for (const instrumentation of config.instrumentations) { + if (config.instrumentations ?? config.telemetry?.instrumentations) { + for (const instrumentation of config.telemetry?.instrumentations ?? + config.instrumentations ?? + []) { const moduleDefinitions = ( instrumentation as any ).getModuleDefinitions?.() as Array; diff --git a/packages/core/src/v3/config.ts b/packages/core/src/v3/config.ts index 2a13859bf7..a57eba1266 100644 --- a/packages/core/src/v3/config.ts +++ b/packages/core/src/v3/config.ts @@ -1,4 +1,5 @@ import type { Instrumentation } from "@opentelemetry/instrumentation"; +import type { SpanExporter } from "@opentelemetry/sdk-trace-base"; import type { BuildExtension } from "./build/extensions.js"; import type { MachinePresetName } from "./schemas/common.js"; import type { LogLevel } from "./logger/taskLogger.js"; diff --git a/packages/core/src/v3/otel/tracingSDK.ts b/packages/core/src/v3/otel/tracingSDK.ts index 76d5ab6f86..be7ab34012 100644 --- a/packages/core/src/v3/otel/tracingSDK.ts +++ b/packages/core/src/v3/otel/tracingSDK.ts @@ -20,6 +20,7 @@ import { import { BatchSpanProcessor, NodeTracerProvider, + ReadableSpan, SimpleSpanProcessor, SpanExporter, } from "@opentelemetry/sdk-trace-node"; @@ -112,6 +113,8 @@ export class TracingSDK { .merge( new Resource({ [SemanticResourceAttributes.CLOUD_PROVIDER]: "trigger.dev", + [SemanticResourceAttributes.SERVICE_NAME]: + getEnvVar("OTEL_SERVICE_NAME") ?? "trigger.dev", [SemanticInternalAttributes.TRIGGER]: true, [SemanticInternalAttributes.CLI_VERSION]: VERSION, }) @@ -256,3 +259,49 @@ function setLogLevel(level: TracingDiagnosticLogLevel) { diag.setLogger(new DiagConsoleLogger(), diagLogLevel); } + +class ExternalSpanExporterWrapper { + constructor( + private underlyingExporter: SpanExporter, + private externalTraceId: string + ) {} + + private transformSpan(span: ReadableSpan): ReadableSpan | undefined { + if (span.attributes[SemanticInternalAttributes.SPAN_PARTIAL]) { + // Skip partial spans + return; + } + + const spanContext = span.spanContext(); + + return { + ...span, + spanContext: () => ({ ...spanContext, traceId: this.externalTraceId }), + parentSpanId: span.attributes[SemanticInternalAttributes.SPAN_ATTEMPT] + ? undefined + : span.parentSpanId, + }; + } + + export(spans: any[], resultCallback: (result: any) => void): void { + try { + const modifiedSpans = spans.map(this.transformSpan.bind(this)); + this.underlyingExporter.export( + modifiedSpans.filter(Boolean) as ReadableSpan[], + resultCallback + ); + } catch (e) { + console.error(e); + } + } + + shutdown(): Promise { + return this.underlyingExporter.shutdown(); + } + + forceFlush?(): Promise { + return this.underlyingExporter.forceFlush + ? this.underlyingExporter.forceFlush() + : Promise.resolve(); + } +} diff --git a/packages/core/src/v3/semanticInternalAttributes.ts b/packages/core/src/v3/semanticInternalAttributes.ts index 98b14f1aa3..74b09426e1 100644 --- a/packages/core/src/v3/semanticInternalAttributes.ts +++ b/packages/core/src/v3/semanticInternalAttributes.ts @@ -51,4 +51,5 @@ export const SemanticInternalAttributes = { RATE_LIMIT_LIMIT: "response.rateLimit.limit", RATE_LIMIT_REMAINING: "response.rateLimit.remaining", RATE_LIMIT_RESET: "response.rateLimit.reset", + SPAN_ATTEMPT: "$span.attempt", }; diff --git a/packages/core/src/v3/workers/taskExecutor.ts b/packages/core/src/v3/workers/taskExecutor.ts index 06f965c35c..894145878a 100644 --- a/packages/core/src/v3/workers/taskExecutor.ts +++ b/packages/core/src/v3/workers/taskExecutor.ts @@ -231,6 +231,7 @@ export class TaskExecutor { kind: SpanKind.CONSUMER, attributes: { [SemanticInternalAttributes.STYLE_ICON]: "attempt", + [SemanticInternalAttributes.SPAN_ATTEMPT]: true, }, }, this._tracer.extractContext(traceContext), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 45c135f554..60a0ccd0f7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1628,6 +1628,9 @@ importers: '@fast-csv/parse': specifier: ^5.0.2 version: 5.0.2 + '@opentelemetry/exporter-trace-otlp-http': + specifier: ^0.57.0 + version: 0.57.0(@opentelemetry/api@1.9.0) '@radix-ui/react-dialog': specifier: ^1.0.3 version: 1.0.4(@types/react-dom@18.2.7)(@types/react@18.3.1)(react-dom@18.2.0)(react@18.3.1) @@ -1675,7 +1678,7 @@ importers: version: 0.451.0(react@18.3.1) next: specifier: 14.2.15 - version: 14.2.15(@playwright/test@1.37.0)(react-dom@18.2.0)(react@18.3.1) + version: 14.2.15(@opentelemetry/api@1.9.0)(@playwright/test@1.37.0)(react-dom@18.2.0)(react@18.3.1) openai: specifier: ^4.68.4 version: 4.68.4(zod@3.23.8) @@ -8213,6 +8216,13 @@ packages: dependencies: '@opentelemetry/api': 1.9.0 + /@opentelemetry/api-logs@0.57.0: + resolution: {integrity: sha512-l1aJ30CXeauVYaI+btiynHpw341LthkMTv3omi1VJDX14werY2Wmv9n1yudMsq9HuY0m8PvXEVX4d8zxEb+WRg==} + engines: {node: '>=14'} + dependencies: + '@opentelemetry/api': 1.9.0 + dev: false + /@opentelemetry/api@1.4.1: resolution: {integrity: sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA==} engines: {node: '>=8.0.0'} @@ -8292,6 +8302,16 @@ packages: '@opentelemetry/semantic-conventions': 1.25.1 dev: false + /@opentelemetry/core@1.30.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-Q/3u/K73KUjTCnFUP97ZY+pBjQ1kPEgjOfXj/bJl8zW7GbXdkw6cwuyZk6ZTXkVgCBsYRYUzx4fvYK1jxdb9MA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.28.0 + dev: false + /@opentelemetry/exporter-logs-otlp-http@0.49.1(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-3QoBnIGCmEkujynUP0mK155QtOM0MSf9FNrEw7u9ieCFsoMiyatg2hPp+alEDONJ8N8wGEK+wP2q3icgXBiggw==} engines: {node: '>=14'} @@ -8378,6 +8398,20 @@ packages: '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) dev: false + /@opentelemetry/exporter-trace-otlp-http@0.57.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-BJl35PSkwoMlGEOrzjCG1ih6zqZoAZJIR4xyqSKC2BqPtwuRjID0vWBaEdP9xrxxJTEIEQw+gEY/0pUgicX0ew==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.57.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.57.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.30.0(@opentelemetry/api@1.9.0) + dev: false + /@opentelemetry/exporter-trace-otlp-proto@0.49.1(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-n8ON/c9pdMyYAfSFWKkgsPwjYoxnki+6Olzo+klKfW7KqLWoyEkryNkbcMIYnGGNXwdkMIrjoaP0VxXB26Oxcg==} engines: {node: '>=14'} @@ -8657,6 +8691,17 @@ packages: '@opentelemetry/otlp-transformer': 0.52.1(@opentelemetry/api@1.9.0) dev: false + /@opentelemetry/otlp-exporter-base@0.57.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-QQl4Ngm3D6H8SDO0EM642ncTxjRsf/HDq7+IWIA0eaEK/NTsJeQ3iYJiZj3F4jkALnvyeM1kkwd+DHtqxTBx9Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.57.0(@opentelemetry/api@1.9.0) + dev: false + /@opentelemetry/otlp-grpc-exporter-base@0.49.1(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-DNDNUWmOqtKTFJAyOyHHKotVox0NQ/09ETX8fUOeEtyNVHoGekAVtBbvIA3AtK+JflP7LC0PTjlLfruPM3Wy6w==} engines: {node: '>=14'} @@ -8726,6 +8771,22 @@ packages: protobufjs: 7.3.2 dev: false + /@opentelemetry/otlp-transformer@0.57.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-yHX7sdwkdAmSa6Jbi3caSLDWy0PCHS1pKQeKz8AIWSyQqL7IojHKgdk9A+7eRd98Z1n9YTdwWSWLnObvIqhEhQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.57.0 + '@opentelemetry/core': 1.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.57.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.30.0(@opentelemetry/api@1.9.0) + protobufjs: 7.3.2 + dev: false + /@opentelemetry/propagator-b3@1.22.0(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-qBItJm9ygg/jCB5rmivyGz1qmKZPsL/sX715JqPMFgq++Idm0x+N9sLQvWFHFt2+ZINnCSojw7FVBgFW6izcXA==} engines: {node: '>=14'} @@ -8830,6 +8891,17 @@ packages: '@opentelemetry/semantic-conventions': 1.25.1 dev: false + /@opentelemetry/resources@1.30.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-5mGMjL0Uld/99t7/pcd7CuVtJbkARckLVuiOX84nO8RtLtIz0/J6EOHM2TGvPZ6F4K+XjUq13gMx14w80SVCQg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.28.0 + dev: false + /@opentelemetry/sdk-logs@0.49.1(@opentelemetry/api-logs@0.49.1)(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-gCzYWsJE0h+3cuh3/cK+9UwlVFyHvj3PReIOCDOmdeXOp90ZjKRoDOJBc3mvk1LL6wyl1RWIivR8Rg9OToyesw==} engines: {node: '>=14'} @@ -8868,6 +8940,18 @@ packages: '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) dev: false + /@opentelemetry/sdk-logs@0.57.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-6Kbxdu/QE9LWH7+WSLmYo3DjAq+c55TiCLXiXu6b/2m2muy5SyOG2m0MrGqetyRpfYSSbIqHmJoqNVTN3+2a9g==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.4.0 <1.10.0' + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.57.0 + '@opentelemetry/core': 1.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.30.0(@opentelemetry/api@1.9.0) + dev: false + /@opentelemetry/sdk-metrics@1.22.0(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-k6iIx6H3TZ+BVMr2z8M16ri2OxWaljg5h8ihGJxi/KQWcjign6FEaEzuigXt5bK9wVEhqAcWLCfarSftaNWkkg==} engines: {node: '>=14'} @@ -8892,6 +8976,17 @@ packages: lodash.merge: 4.6.2 dev: false + /@opentelemetry/sdk-metrics@1.30.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-5kcj6APyRMvv6dEIP5plz2qfJAD4OMipBRT11u/pa1a68rHKI2Ln+iXVkAGKgx8o7CXbD7FdPypTUY88ZQgP4Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.30.0(@opentelemetry/api@1.9.0) + dev: false + /@opentelemetry/sdk-node@0.49.1(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-feBIT85ndiSHXsQ2gfGpXC/sNeX4GCHLksC4A9s/bfpUbbgbCSl0RvzZlmEpCHarNrkZMwFRi4H0xFfgvJEjrg==} engines: {node: '>=14'} @@ -8988,6 +9083,18 @@ packages: '@opentelemetry/semantic-conventions': 1.25.1 dev: false + /@opentelemetry/sdk-trace-base@1.30.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-RKQDaDIkV7PwizmHw+rE/FgfB2a6MBx+AEVVlAHXRG1YYxLiBpPX2KhmoB99R5vA4b72iJrjle68NDWnbrE9Dg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.30.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.28.0 + dev: false + /@opentelemetry/sdk-trace-node@1.22.0(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-gTGquNz7ue8uMeiWPwp3CU321OstQ84r7PCDtOaCicjbJxzvO8RZMlEC4geOipTeiF88kss5n6w+//A0MhP1lQ==} engines: {node: '>=14'} @@ -9070,6 +9177,11 @@ packages: engines: {node: '>=14'} dev: false + /@opentelemetry/semantic-conventions@1.28.0: + resolution: {integrity: sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==} + engines: {node: '>=14'} + dev: false + /@pkgjs/parseargs@0.11.0: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -17221,7 +17333,7 @@ packages: dependencies: '@uploadthing/shared': 7.0.3 file-selector: 0.6.0 - next: 14.2.15(@playwright/test@1.37.0)(react-dom@18.2.0)(react@18.3.1) + next: 14.2.15(@opentelemetry/api@1.9.0)(@playwright/test@1.37.0)(react-dom@18.2.0)(react@18.3.1) react: 18.3.1 uploadthing: 7.1.0(next@14.2.15)(tailwindcss@3.4.1) dev: false @@ -25393,7 +25505,7 @@ packages: - babel-plugin-macros dev: false - /next@14.2.15(@playwright/test@1.37.0)(react-dom@18.2.0)(react@18.3.1): + /next@14.2.15(@opentelemetry/api@1.9.0)(@playwright/test@1.37.0)(react-dom@18.2.0)(react@18.3.1): resolution: {integrity: sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==} engines: {node: '>=18.17.0'} hasBin: true @@ -25412,6 +25524,7 @@ packages: optional: true dependencies: '@next/env': 14.2.15 + '@opentelemetry/api': 1.9.0 '@playwright/test': 1.37.0 '@swc/helpers': 0.5.5 busboy: 1.6.0 @@ -31266,7 +31379,7 @@ packages: '@uploadthing/mime-types': 0.3.0 '@uploadthing/shared': 7.0.3 effect: 3.7.2 - next: 14.2.15(@playwright/test@1.37.0)(react-dom@18.2.0)(react@18.3.1) + next: 14.2.15(@opentelemetry/api@1.9.0)(@playwright/test@1.37.0)(react-dom@18.2.0)(react@18.3.1) tailwindcss: 3.4.1(ts-node@10.9.1) dev: false diff --git a/references/nextjs-realtime/package.json b/references/nextjs-realtime/package.json index d3d1e505a6..342897d66d 100644 --- a/references/nextjs-realtime/package.json +++ b/references/nextjs-realtime/package.json @@ -14,6 +14,7 @@ "@ai-sdk/openai": "^1.0.1", "@fal-ai/serverless-client": "^0.15.0", "@fast-csv/parse": "^5.0.2", + "@opentelemetry/exporter-trace-otlp-http": "^0.57.0", "@radix-ui/react-dialog": "^1.0.3", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-progress": "^1.1.1",