diff --git a/.changeset/five-nails-whisper.md b/.changeset/five-nails-whisper.md new file mode 100644 index 0000000000..185f4a0cf6 --- /dev/null +++ b/.changeset/five-nails-whisper.md @@ -0,0 +1,92 @@ +--- +"@trigger.dev/sdk": patch +--- + +External Trace Correlation & OpenTelemetry Package Updates. + +| Package | Previous Version | New Version | Change Type | +|---------|------------------|-------------|-------------| +| `@opentelemetry/api` | 1.9.0 | 1.9.0 | No change (stable API) | +| `@opentelemetry/api-logs` | 0.52.1 | 0.203.0 | Major update | +| `@opentelemetry/core` | - | 2.0.1 | New dependency | +| `@opentelemetry/exporter-logs-otlp-http` | 0.52.1 | 0.203.0 | Major update | +| `@opentelemetry/exporter-trace-otlp-http` | 0.52.1 | 0.203.0 | Major update | +| `@opentelemetry/instrumentation` | 0.52.1 | 0.203.0 | Major update | +| `@opentelemetry/instrumentation-fetch` | 0.52.1 | 0.203.0 | Major update | +| `@opentelemetry/resources` | 1.25.1 | 2.0.1 | Major update | +| `@opentelemetry/sdk-logs` | 0.52.1 | 0.203.0 | Major update | +| `@opentelemetry/sdk-node` | 0.52.1 | - | Removed (functionality consolidated) | +| `@opentelemetry/sdk-trace-base` | 1.25.1 | 2.0.1 | Major update | +| `@opentelemetry/sdk-trace-node` | 1.25.1 | 2.0.1 | Major update | +| `@opentelemetry/semantic-conventions` | 1.25.1 | 1.36.0 | Minor update | + +### External trace correlation and propagation + +We will now correlate your external traces with trigger.dev traces and logs when using our external exporters: + +```ts +import { defineConfig } from "@trigger.dev/sdk"; +import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http"; +import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"; + +export default defineConfig({ + project: process.env.TRIGGER_PROJECT_REF, + dirs: ["./src/trigger"], + telemetry: { + logExporters: [ + new OTLPLogExporter({ + url: "https://api.axiom.co/v1/logs", + headers: { + Authorization: `Bearer ${process.env.AXIOM_TOKEN}`, + "X-Axiom-Dataset": "test", + }, + }), + ], + exporters: [ + new OTLPTraceExporter({ + url: "https://api.axiom.co/v1/traces", + headers: { + Authorization: `Bearer ${process.env.AXIOM_TOKEN}`, + "X-Axiom-Dataset": "test", + }, + }), + ], + }, + maxDuration: 3600, +}); +``` + +You can also now propagate your external trace context when calling back into your own backend infra from inside a trigger.dev task: + +```ts +import { otel, task } from "@trigger.dev/sdk"; +import { context, propagation } from "@opentelemetry/api"; + +async function callNextjsApp() { + return await otel.withExternalTrace(async () => { + const headersObject = {}; + + // Now context.active() refers to your external trace context + propagation.inject(context.active(), headersObject); + + const result = await fetch("http://localhost:3000/api/demo-call-from-trigger", { + headers: new Headers(headersObject), + method: "POST", + body: JSON.stringify({ + message: "Hello from Trigger.dev", + }), + }); + + return result.json(); + }); +} + +export const myTask = task({ + id: "my-task", + run: async (payload: any) => { + await callNextjsApp() + } +}) +``` + + diff --git a/apps/webapp/app/presenters/v3/SpanPresenter.server.ts b/apps/webapp/app/presenters/v3/SpanPresenter.server.ts index 0d9065e28a..a3a5747846 100644 --- a/apps/webapp/app/presenters/v3/SpanPresenter.server.ts +++ b/apps/webapp/app/presenters/v3/SpanPresenter.server.ts @@ -4,9 +4,10 @@ import { SemanticInternalAttributes, TaskRunContext, TaskRunError, + TriggerTraceContext, V3TaskRunContext, } from "@trigger.dev/core/v3"; -import { AttemptId, getMaxDuration } from "@trigger.dev/core/v3/isomorphic"; +import { AttemptId, getMaxDuration, parseTraceparent } from "@trigger.dev/core/v3/isomorphic"; import { RUNNING_STATUSES } from "~/components/runs/v3/TaskRunStatus"; import { logger } from "~/services/logger.server"; import { eventRepository, rehydrateAttribute } from "~/v3/eventRepository.server"; @@ -173,6 +174,8 @@ export class SpanPresenter extends BasePresenter { const context = await this.#getTaskRunContext({ run, machine: machine ?? undefined }); + const externalTraceId = this.#getExternalTraceId(run.traceContext); + return { id: run.id, friendlyId: run.friendlyId, @@ -234,6 +237,7 @@ export class SpanPresenter extends BasePresenter { spanId: run.spanId, isCached: !!span.originalRun, machinePreset: machine?.name, + externalTraceId, }; } @@ -272,6 +276,7 @@ export class SpanPresenter extends BasePresenter { id: true, spanId: true, traceId: true, + traceContext: true, //metadata number: true, taskIdentifier: true, @@ -574,4 +579,26 @@ export class SpanPresenter extends BasePresenter { async #getV4TaskRunContext({ run }: { run: FindRunResult }): Promise { return engine.resolveTaskRunContext(run.id); } + + #getExternalTraceId(traceContext: unknown) { + if (!traceContext) { + return; + } + + const parsedTraceContext = TriggerTraceContext.safeParse(traceContext); + + if (!parsedTraceContext.success) { + return; + } + + const externalTraceparent = parsedTraceContext.data.external?.traceparent; + + if (!externalTraceparent) { + return; + } + + const parsedTraceparent = parseTraceparent(externalTraceparent); + + return parsedTraceparent?.traceId; + } } diff --git a/apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts b/apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts index a5e4e16225..11613427a9 100644 --- a/apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts +++ b/apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts @@ -93,10 +93,9 @@ const { action, loader } = createActionApiRoute( const service = new TriggerTaskService(); try { - const traceContext = - traceparent && isFromWorker /// If the request is from a worker, we should pass the trace context - ? { traceparent, tracestate } - : undefined; + const traceContext = isFromWorker + ? { traceparent, tracestate } + : { external: { traceparent, tracestate } }; const oneTimeUseToken = await getOneTimeUseToken(authentication); @@ -111,6 +110,14 @@ const { action, loader } = createActionApiRoute( traceContext, }); + logger.debug("[otelContext]", { + taskId: params.taskId, + headers, + options: body.options, + isFromWorker, + traceContext, + }); + const idempotencyKeyExpiresAt = resolveIdempotencyKeyTTL(idempotencyKeyTTL); const result = await service.call( diff --git a/apps/webapp/app/routes/api.v2.tasks.batch.ts b/apps/webapp/app/routes/api.v2.tasks.batch.ts index ba03919d49..93715bbdd5 100644 --- a/apps/webapp/app/routes/api.v2.tasks.batch.ts +++ b/apps/webapp/app/routes/api.v2.tasks.batch.ts @@ -103,10 +103,9 @@ const { action, loader } = createActionApiRoute( return cachedResponse; } - const traceContext = - traceparent && isFromWorker // If the request is from a worker, we should pass the trace context - ? { traceparent, tracestate } - : undefined; + const traceContext = isFromWorker + ? { traceparent, tracestate } + : { external: { traceparent, tracestate } }; const service = new RunEngineBatchTriggerService(batchProcessingStrategy ?? undefined); diff --git a/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx b/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx index 7158c57b01..945a87acda 100644 --- a/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx +++ b/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx @@ -738,6 +738,12 @@ function RunBody({ Run Engine {run.engine} + {run.externalTraceId && ( + + External Trace ID + {run.externalTraceId} + + )} {isAdmin && (
diff --git a/apps/webapp/app/runEngine/services/batchTrigger.server.ts b/apps/webapp/app/runEngine/services/batchTrigger.server.ts index 2a476e5a1e..beadcc9cf7 100644 --- a/apps/webapp/app/runEngine/services/batchTrigger.server.ts +++ b/apps/webapp/app/runEngine/services/batchTrigger.server.ts @@ -42,7 +42,7 @@ export type BatchProcessingOptions = z.infer; export type BatchTriggerTaskServiceOptions = { triggerVersion?: string; - traceContext?: Record; + traceContext?: Record>; spanParentAsLink?: boolean; oneTimeUseToken?: string; }; diff --git a/apps/webapp/app/runEngine/services/triggerTask.server.ts b/apps/webapp/app/runEngine/services/triggerTask.server.ts index 3847a3036b..ea41c12c79 100644 --- a/apps/webapp/app/runEngine/services/triggerTask.server.ts +++ b/apps/webapp/app/runEngine/services/triggerTask.server.ts @@ -10,8 +10,14 @@ import { taskRunErrorEnhancer, taskRunErrorToString, TriggerTaskRequestBody, + TriggerTraceContext, } from "@trigger.dev/core/v3"; -import { RunId, stringifyDuration } from "@trigger.dev/core/v3/isomorphic"; +import { + parseTraceparent, + RunId, + serializeTraceparent, + stringifyDuration, +} from "@trigger.dev/core/v3/isomorphic"; import type { PrismaClientOrTransaction } from "@trigger.dev/database"; import { createTags } from "~/models/taskRunTag.server"; import type { AuthenticatedEnvironment } from "~/services/apiAuth.server"; @@ -253,7 +259,11 @@ export class RunEngineTriggerTaskService { payload: payloadPacket.data ?? "", payloadType: payloadPacket.dataType, context: body.context, - traceContext: event.traceContext, + traceContext: this.#propagateExternalTraceContext( + event.traceContext, + parentRun?.traceContext, + event.traceparent?.spanId + ), traceId: event.traceId, spanId: event.spanId, parentSpanId: @@ -341,4 +351,49 @@ export class RunEngineTriggerTaskService { } }); } + + #propagateExternalTraceContext( + traceContext: Record, + parentRunTraceContext: unknown, + parentSpanId: string | undefined + ): TriggerTraceContext { + if (!parentRunTraceContext) { + return traceContext; + } + + const parsedParentRunTraceContext = TriggerTraceContext.safeParse(parentRunTraceContext); + + if (!parsedParentRunTraceContext.success) { + return traceContext; + } + + const { external } = parsedParentRunTraceContext.data; + + if (!external) { + return traceContext; + } + + if (!external.traceparent) { + return traceContext; + } + + const parsedTraceparent = parseTraceparent(external.traceparent); + + if (!parsedTraceparent) { + return traceContext; + } + + const newExternalTraceparent = serializeTraceparent( + parsedTraceparent.traceId, + parentSpanId ?? parsedTraceparent.spanId + ); + + return { + ...traceContext, + external: { + ...external, + traceparent: newExternalTraceparent, + }, + }; + } } diff --git a/apps/webapp/app/runEngine/types.ts b/apps/webapp/app/runEngine/types.ts index 9523999d54..3564a5d717 100644 --- a/apps/webapp/app/runEngine/types.ts +++ b/apps/webapp/app/runEngine/types.ts @@ -12,7 +12,7 @@ export type TriggerTaskServiceOptions = { idempotencyKey?: string; idempotencyKeyExpiresAt?: Date; triggerVersion?: string; - traceContext?: Record; + traceContext?: Record; spanParentAsLink?: boolean; parentAsLinkType?: "replay" | "trigger"; batchId?: string; @@ -119,7 +119,7 @@ export interface TriggerTaskValidator { export type TracedEventSpan = { traceId: string; spanId: string; - traceContext: Record; + traceContext: Record; traceparent?: { traceId: string; spanId: string; diff --git a/apps/webapp/app/v3/environmentVariableRules.server.ts b/apps/webapp/app/v3/environmentVariableRules.server.ts index ddaee2b249..fce17d0364 100644 --- a/apps/webapp/app/v3/environmentVariableRules.server.ts +++ b/apps/webapp/app/v3/environmentVariableRules.server.ts @@ -8,8 +8,6 @@ type VariableRule = const blacklistedVariables: VariableRule[] = [ { type: "exact", key: "TRIGGER_SECRET_KEY" }, { type: "exact", key: "TRIGGER_API_URL" }, - { type: "prefix", prefix: "OTEL_" }, - { type: "whitelist", key: "OTEL_LOG_LEVEL" }, ]; export function removeBlacklistedVariables( diff --git a/apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts b/apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts index ea6243f4a5..12d0a12369 100644 --- a/apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts +++ b/apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts @@ -17,6 +17,7 @@ import { } from "./repository"; import { removeBlacklistedVariables } from "../environmentVariableRules.server"; import { deduplicateVariableArray } from "../deduplicateVariableArray.server"; +import { logger } from "~/services/logger.server"; function secretKeyProjectPrefix(projectId: string) { return `environmentvariable:${projectId}:`; @@ -837,11 +838,23 @@ export async function resolveVariablesForEnvironment( ? await resolveBuiltInDevVariables(runtimeEnvironment) : await resolveBuiltInProdVariables(runtimeEnvironment, parentEnvironment); - return deduplicateVariableArray([ + const overridableOtelVariables = + runtimeEnvironment.type === "DEVELOPMENT" + ? await resolveOverridableOtelDevVariables(runtimeEnvironment) + : []; + + const result = deduplicateVariableArray([ ...overridableTriggerVariables, + ...overridableOtelVariables, ...projectSecrets, ...builtInVariables, ]); + + logger.debug("Resolved variables", { + result, + }); + + return result; } async function resolveOverridableTriggerVariables( @@ -860,7 +873,7 @@ async function resolveOverridableTriggerVariables( async function resolveBuiltInDevVariables(runtimeEnvironment: RuntimeEnvironmentForEnvRepo) { let result: Array = [ { - key: "OTEL_EXPORTER_OTLP_ENDPOINT", + key: "TRIGGER_OTEL_EXPORTER_OTLP_ENDPOINT", value: env.DEV_OTEL_EXPORTER_OTLP_ENDPOINT ?? `${env.APP_ORIGIN.replace(/\/$/, "")}/otel`, }, { @@ -875,6 +888,42 @@ async function resolveBuiltInDevVariables(runtimeEnvironment: RuntimeEnvironment if (env.DEV_OTEL_BATCH_PROCESSING_ENABLED === "1") { result = result.concat([ + { + key: "TRIGGER_OTEL_BATCH_PROCESSING_ENABLED", + value: "1", + }, + { + key: "TRIGGER_OTEL_SPAN_MAX_EXPORT_BATCH_SIZE", + value: env.DEV_OTEL_SPAN_MAX_EXPORT_BATCH_SIZE, + }, + { + key: "TRIGGER_OTEL_SPAN_SCHEDULED_DELAY_MILLIS", + value: env.DEV_OTEL_SPAN_SCHEDULED_DELAY_MILLIS, + }, + { + key: "TRIGGER_OTEL_SPAN_EXPORT_TIMEOUT_MILLIS", + value: env.DEV_OTEL_SPAN_EXPORT_TIMEOUT_MILLIS, + }, + { + key: "TRIGGER_OTEL_SPAN_MAX_QUEUE_SIZE", + value: env.DEV_OTEL_SPAN_MAX_QUEUE_SIZE, + }, + { + key: "TRIGGER_OTEL_LOG_MAX_EXPORT_BATCH_SIZE", + value: env.DEV_OTEL_LOG_MAX_EXPORT_BATCH_SIZE, + }, + { + key: "TRIGGER_OTEL_LOG_SCHEDULED_DELAY_MILLIS", + value: env.DEV_OTEL_LOG_SCHEDULED_DELAY_MILLIS, + }, + { + key: "TRIGGER_OTEL_LOG_EXPORT_TIMEOUT_MILLIS", + value: env.DEV_OTEL_LOG_EXPORT_TIMEOUT_MILLIS, + }, + { + key: "TRIGGER_OTEL_LOG_MAX_QUEUE_SIZE", + value: env.DEV_OTEL_LOG_MAX_QUEUE_SIZE, + }, { key: "OTEL_BATCH_PROCESSING_ENABLED", value: "1", @@ -919,6 +968,19 @@ async function resolveBuiltInDevVariables(runtimeEnvironment: RuntimeEnvironment return [...result, ...commonVariables]; } +async function resolveOverridableOtelDevVariables( + runtimeEnvironment: RuntimeEnvironmentForEnvRepo +) { + let result: Array = [ + { + key: "OTEL_EXPORTER_OTLP_ENDPOINT", + value: env.DEV_OTEL_EXPORTER_OTLP_ENDPOINT ?? `${env.APP_ORIGIN.replace(/\/$/, "")}/otel`, + }, + ]; + + return result; +} + async function resolveBuiltInProdVariables( runtimeEnvironment: RuntimeEnvironmentForEnvRepo, parentEnvironment?: RuntimeEnvironmentForEnvRepo @@ -957,6 +1019,42 @@ async function resolveBuiltInProdVariables( if (env.PROD_OTEL_BATCH_PROCESSING_ENABLED === "1") { result = result.concat([ + { + key: "TRIGGER_OTEL_BATCH_PROCESSING_ENABLED", + value: "1", + }, + { + key: "TRIGGER_OTEL_SPAN_MAX_EXPORT_BATCH_SIZE", + value: env.PROD_OTEL_SPAN_MAX_EXPORT_BATCH_SIZE, + }, + { + key: "TRIGGER_OTEL_SPAN_SCHEDULED_DELAY_MILLIS", + value: env.PROD_OTEL_SPAN_SCHEDULED_DELAY_MILLIS, + }, + { + key: "TRIGGER_OTEL_SPAN_EXPORT_TIMEOUT_MILLIS", + value: env.PROD_OTEL_SPAN_EXPORT_TIMEOUT_MILLIS, + }, + { + key: "TRIGGER_OTEL_SPAN_MAX_QUEUE_SIZE", + value: env.PROD_OTEL_SPAN_MAX_QUEUE_SIZE, + }, + { + key: "TRIGGER_OTEL_LOG_MAX_EXPORT_BATCH_SIZE", + value: env.PROD_OTEL_LOG_MAX_EXPORT_BATCH_SIZE, + }, + { + key: "TRIGGER_OTEL_LOG_SCHEDULED_DELAY_MILLIS", + value: env.PROD_OTEL_LOG_SCHEDULED_DELAY_MILLIS, + }, + { + key: "TRIGGER_OTEL_LOG_EXPORT_TIMEOUT_MILLIS", + value: env.PROD_OTEL_LOG_EXPORT_TIMEOUT_MILLIS, + }, + { + key: "TRIGGER_OTEL_LOG_MAX_QUEUE_SIZE", + value: env.PROD_OTEL_LOG_MAX_QUEUE_SIZE, + }, { key: "OTEL_BATCH_PROCESSING_ENABLED", value: "1", diff --git a/apps/webapp/app/v3/eventRepository.server.ts b/apps/webapp/app/v3/eventRepository.server.ts index dc4fdd43e5..d70deb3ef4 100644 --- a/apps/webapp/app/v3/eventRepository.server.ts +++ b/apps/webapp/app/v3/eventRepository.server.ts @@ -2,9 +2,14 @@ import { Attributes, AttributeValue, Link, trace, TraceFlags, Tracer } from "@op import { RandomIdGenerator } from "@opentelemetry/sdk-trace-base"; import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions"; import { + correctErrorStackTrace, + createPacketAttributesAsJson, ExceptionEventProperties, ExceptionSpanEvent, + flattenAttributes, + isExceptionSpanEvent, NULL_SENTINEL, + omit, PRIMARY_VARIANT, SemanticInternalAttributes, SpanEvent, @@ -13,28 +18,24 @@ import { TaskEventEnvironment, TaskEventStyle, TaskRunError, - correctErrorStackTrace, - createPacketAttributesAsJson, - flattenAttributes, - isExceptionSpanEvent, - omit, unflattenAttributes, } from "@trigger.dev/core/v3"; +import { parseTraceparent, serializeTraceparent } from "@trigger.dev/core/v3/isomorphic"; import { Prisma, TaskEvent, TaskEventKind, TaskEventStatus } from "@trigger.dev/database"; +import { nanoid } from "nanoid"; import { createHash } from "node:crypto"; import { EventEmitter } from "node:stream"; import { Gauge } from "prom-client"; -import { $replica, PrismaClient, PrismaReplicaClient, prisma } from "~/db.server"; +import { $replica, prisma, PrismaClient, PrismaReplicaClient } from "~/db.server"; import { env } from "~/env.server"; import { metricsRegister } from "~/metrics.server"; +import { createRedisClient, RedisClient, RedisWithClusterOptions } from "~/redis.server"; import { logger } from "~/services/logger.server"; import { singleton } from "~/utils/singleton"; import { DynamicFlushScheduler } from "./dynamicFlushScheduler.server"; +import { TaskEventStore, TaskEventStoreTable } from "./taskEventStore.server"; import { startActiveSpan } from "./tracer.server"; -import { createRedisClient, RedisClient, RedisWithClusterOptions } from "~/redis.server"; import { startSpan } from "./tracing.server"; -import { nanoid } from "nanoid"; -import { TaskEventStore, TaskEventStoreTable } from "./taskEventStore.server"; const MAX_FLUSH_DEPTH = 5; @@ -80,7 +81,7 @@ export type SetAttribute = (key: keyof T, value: T[ke export type TraceEventOptions = { kind?: CreatableEventKind; - context?: Record; + context?: Record; spanParentAsLink?: boolean; parentAsLinkType?: "trigger" | "replay"; spanIdSeed?: string; @@ -932,7 +933,7 @@ export class EventRepository { traceId, spanId, parentId, - tracestate, + tracestate: typeof tracestate === "string" ? tracestate : undefined, message: message, serviceName: "api server", serviceNamespace: "trigger.dev", @@ -989,6 +990,11 @@ export class EventRepository { ): Promise { const propagatedContext = extractContextFromCarrier(options.context ?? {}); + logger.debug("[otelContext]", { + propagatedContext, + options, + }); + const start = process.hrtime.bigint(); const startTime = options.startTime ?? getNowInNanoseconds(); @@ -1002,7 +1008,8 @@ export class EventRepository { : this.generateSpanId(); const traceContext = { - traceparent: `00-${traceId}-${spanId}-01`, + ...options.context, + traceparent: serializeTraceparent(traceId, spanId), }; const links: Link[] = @@ -1087,7 +1094,7 @@ export class EventRepository { traceId, spanId, parentId, - tracestate, + tracestate: typeof tracestate === "string" ? tracestate : undefined, duration: options.incomplete ? 0 : duration, isPartial: failedWithError ? false : options.incomplete, isError: !!failedWithError, @@ -1486,36 +1493,21 @@ function excludePartialEventsWithCorrespondingFullEvent(batch: CreatableEvent[]) ); } -export function extractContextFromCarrier(carrier: Record) { +export function extractContextFromCarrier(carrier: Record) { const traceparent = carrier["traceparent"]; const tracestate = carrier["tracestate"]; + if (typeof traceparent !== "string") { + return undefined; + } + return { + ...carrier, traceparent: parseTraceparent(traceparent), tracestate, }; } -function parseTraceparent(traceparent?: string): { traceId: string; spanId: string } | undefined { - if (!traceparent) { - return undefined; - } - - const parts = traceparent.split("-"); - - if (parts.length !== 4) { - return undefined; - } - - const [version, traceId, spanId, flags] = parts; - - if (version !== "00") { - return undefined; - } - - return { traceId, spanId }; -} - function prepareEvent(event: QueriedEvent): PreparedEvent { return { ...event, diff --git a/apps/webapp/app/v3/services/triggerTask.server.ts b/apps/webapp/app/v3/services/triggerTask.server.ts index c43485cbb5..bfb31e2499 100644 --- a/apps/webapp/app/v3/services/triggerTask.server.ts +++ b/apps/webapp/app/v3/services/triggerTask.server.ts @@ -19,7 +19,7 @@ export type TriggerTaskServiceOptions = { idempotencyKey?: string; idempotencyKeyExpiresAt?: Date; triggerVersion?: string; - traceContext?: Record; + traceContext?: Record; spanParentAsLink?: boolean; parentAsLinkType?: "replay" | "trigger"; batchId?: string; diff --git a/apps/webapp/test/environmentVariableRules.test.ts b/apps/webapp/test/environmentVariableRules.test.ts index af27dd3c7c..39e3d9892e 100644 --- a/apps/webapp/test/environmentVariableRules.test.ts +++ b/apps/webapp/test/environmentVariableRules.test.ts @@ -15,33 +15,6 @@ describe("removeBlacklistedVariables", () => { expect(result).toEqual([{ key: "NORMAL_VAR", value: "normal" }]); }); - it("should remove variables with blacklisted prefixes", () => { - const variables: EnvironmentVariable[] = [ - { key: "OTEL_SERVICE_NAME", value: "my-service" }, - { key: "OTEL_TRACE_SAMPLER", value: "always_on" }, - { key: "NORMAL_VAR", value: "normal" }, - ]; - - const result = removeBlacklistedVariables(variables); - - expect(result).toEqual([{ key: "NORMAL_VAR", value: "normal" }]); - }); - - it("should keep whitelisted variables even if they match a blacklisted prefix", () => { - const variables: EnvironmentVariable[] = [ - { key: "OTEL_LOG_LEVEL", value: "debug" }, - { key: "OTEL_SERVICE_NAME", value: "my-service" }, - { key: "NORMAL_VAR", value: "normal" }, - ]; - - const result = removeBlacklistedVariables(variables); - - expect(result).toEqual([ - { key: "OTEL_LOG_LEVEL", value: "debug" }, - { key: "NORMAL_VAR", value: "normal" }, - ]); - }); - it("should handle empty input array", () => { const variables: EnvironmentVariable[] = []; @@ -53,8 +26,6 @@ describe("removeBlacklistedVariables", () => { it("should handle mixed case variables", () => { const variables: EnvironmentVariable[] = [ { key: "trigger_secret_key", value: "secret123" }, // Different case - { key: "OTEL_LOG_LEVEL", value: "debug" }, - { key: "otel_service_name", value: "my-service" }, // Different case { key: "NORMAL_VAR", value: "normal" }, ]; @@ -64,8 +35,6 @@ describe("removeBlacklistedVariables", () => { // Note: The function is case-sensitive, so different case variables should pass through expect(result).toEqual([ { key: "trigger_secret_key", value: "secret123" }, - { key: "OTEL_LOG_LEVEL", value: "debug" }, - { key: "otel_service_name", value: "my-service" }, { key: "NORMAL_VAR", value: "normal" }, ]); }); @@ -73,17 +42,12 @@ describe("removeBlacklistedVariables", () => { it("should handle variables with empty values", () => { const variables: EnvironmentVariable[] = [ { key: "TRIGGER_SECRET_KEY", value: "" }, - { key: "OTEL_SERVICE_NAME", value: "" }, - { key: "OTEL_LOG_LEVEL", value: "" }, { key: "NORMAL_VAR", value: "" }, ]; const result = removeBlacklistedVariables(variables); - expect(result).toEqual([ - { key: "OTEL_LOG_LEVEL", value: "" }, - { key: "NORMAL_VAR", value: "" }, - ]); + expect(result).toEqual([{ key: "NORMAL_VAR", value: "" }]); }); it("should handle all types of rules in a single array", () => { @@ -91,11 +55,6 @@ describe("removeBlacklistedVariables", () => { // Exact matches (should be removed) { key: "TRIGGER_SECRET_KEY", value: "secret123" }, { key: "TRIGGER_API_URL", value: "https://api.example.com" }, - // Prefix matches (should be removed) - { key: "OTEL_SERVICE_NAME", value: "my-service" }, - { key: "OTEL_TRACE_SAMPLER", value: "always_on" }, - // Whitelist exception (should be kept) - { key: "OTEL_LOG_LEVEL", value: "debug" }, // Normal variables (should be kept) { key: "NORMAL_VAR", value: "normal" }, { key: "DATABASE_URL", value: "postgres://..." }, @@ -104,7 +63,6 @@ describe("removeBlacklistedVariables", () => { const result = removeBlacklistedVariables(variables); expect(result).toEqual([ - { key: "OTEL_LOG_LEVEL", value: "debug" }, { key: "NORMAL_VAR", value: "normal" }, { key: "DATABASE_URL", value: "postgres://..." }, ]); diff --git a/internal-packages/run-engine/src/engine/types.ts b/internal-packages/run-engine/src/engine/types.ts index e15f90b1c5..7f22b6770d 100644 --- a/internal-packages/run-engine/src/engine/types.ts +++ b/internal-packages/run-engine/src/engine/types.ts @@ -6,6 +6,7 @@ import { MachinePresetName, RetryOptions, RunChainState, + TriggerTraceContext, } from "@trigger.dev/core/v3"; import { PrismaClient, PrismaReplicaClient } from "@trigger.dev/database"; import { Worker, type WorkerConcurrencyOptions } from "@trigger.dev/redis-worker"; @@ -89,7 +90,7 @@ export type TriggerParams = { payload: string; payloadType: string; context: any; - traceContext: Record; + traceContext: TriggerTraceContext; traceId: string; spanId: string; parentSpanId?: string; diff --git a/packages/cli-v3/package.json b/packages/cli-v3/package.json index 3d4e4c8a9f..24c68670aa 100644 --- a/packages/cli-v3/package.json +++ b/packages/cli-v3/package.json @@ -82,17 +82,13 @@ "@depot/cli": "0.0.1-cli.2.80.0", "@modelcontextprotocol/sdk": "^1.6.1", "@opentelemetry/api": "1.9.0", - "@opentelemetry/api-logs": "0.52.1", - "@opentelemetry/exporter-logs-otlp-http": "0.52.1", - "@opentelemetry/exporter-trace-otlp-http": "0.52.1", - "@opentelemetry/instrumentation": "0.52.1", - "@opentelemetry/instrumentation-fetch": "0.52.1", - "@opentelemetry/resources": "1.25.1", - "@opentelemetry/sdk-logs": "0.52.1", - "@opentelemetry/sdk-node": "0.52.1", - "@opentelemetry/sdk-trace-base": "1.25.1", - "@opentelemetry/sdk-trace-node": "1.25.1", - "@opentelemetry/semantic-conventions": "1.25.1", + "@opentelemetry/api-logs": "0.203.0", + "@opentelemetry/exporter-trace-otlp-http": "0.203.0", + "@opentelemetry/instrumentation": "0.203.0", + "@opentelemetry/instrumentation-fetch": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-trace-node": "2.0.1", + "@opentelemetry/semantic-conventions": "1.36.0", "@trigger.dev/build": "workspace:4.0.0-v4-beta.26", "@trigger.dev/core": "workspace:4.0.0-v4-beta.26", "ansi-escapes": "^7.0.0", diff --git a/packages/cli-v3/src/cli/common.ts b/packages/cli-v3/src/cli/common.ts index b607ca07ff..3cf9f2aba1 100644 --- a/packages/cli-v3/src/cli/common.ts +++ b/packages/cli-v3/src/cli/common.ts @@ -1,15 +1,13 @@ -import { flattenAttributes } from "@trigger.dev/core/v3"; -import { recordSpanException } from "@trigger.dev/core/v3/workers"; +import { outro } from "@clack/prompts"; import { Command } from "commander"; import { z } from "zod"; -import { getTracer, provider } from "../telemetry/tracing.js"; import { fromZodError } from "zod-validation-error"; -import { logger } from "../utilities/logger.js"; -import { outro } from "@clack/prompts"; -import { chalkError } from "../utilities/cliOutput.js"; +import { BundleError } from "../build/bundle.js"; import { CLOUD_API_URL } from "../consts.js"; +import { chalkError } from "../utilities/cliOutput.js"; import { readAuthConfigCurrentProfileName } from "../utilities/configFiles.js"; -import { BundleError } from "../build/bundle.js"; +import { logger } from "../utilities/logger.js"; +import { trace } from "@opentelemetry/api"; export const CommonCommandOptions = z.object({ apiUrl: z.string().optional(), @@ -39,69 +37,52 @@ export class OutroCommandError extends SkipCommandError {} export async function handleTelemetry(action: () => Promise) { try { await action(); - - await provider?.forceFlush(); } catch (e) { - await provider?.forceFlush(); - process.exitCode = 1; } } -export const tracer = getTracer(); - export async function wrapCommandAction( name: string, schema: T, options: unknown, action: (opts: z.output) => Promise ): Promise { - return await tracer.startActiveSpan(name, async (span) => { - try { - const parsedOptions = schema.safeParse(options); - - if (!parsedOptions.success) { - throw new Error(fromZodError(parsedOptions.error).toString()); - } - - span.setAttributes({ - ...flattenAttributes(parsedOptions.data, "cli.options"), - }); - - logger.loggerLevel = parsedOptions.data.logLevel; - - logger.debug(`Running "${name}" with the following options`, { - options: options, - spanContext: span?.spanContext(), - }); - - const result = await action(parsedOptions.data); + try { + const parsedOptions = schema.safeParse(options); - span.end(); + if (!parsedOptions.success) { + throw new Error(fromZodError(parsedOptions.error).toString()); + } - return result; - } catch (e) { - if (e instanceof SkipLoggingError) { - recordSpanException(span, e); - } else if (e instanceof OutroCommandError) { - outro("Operation cancelled"); - } else if (e instanceof SkipCommandError) { - // do nothing - } else if (e instanceof BundleError) { - process.exit(1); - } else { - recordSpanException(span, e); + logger.loggerLevel = parsedOptions.data.logLevel; - logger.log(`${chalkError("X Error:")} ${e instanceof Error ? e.message : String(e)}`); - } + logger.debug(`Running "${name}" with the following options`, { + options: options, + }); - span.end(); + const result = await action(parsedOptions.data); - throw e; + return result; + } catch (e) { + if (e instanceof SkipLoggingError) { + // do nothing + } else if (e instanceof OutroCommandError) { + outro("Operation cancelled"); + } else if (e instanceof SkipCommandError) { + // do nothing + } else if (e instanceof BundleError) { + process.exit(1); + } else { + logger.log(`${chalkError("X Error:")} ${e instanceof Error ? e.message : String(e)}`); } - }); + + throw e; + } } +export const tracer = trace.getTracer("trigger.dev/cli"); + export function installExitHandler() { process.on("SIGINT", () => { process.exit(0); diff --git a/packages/cli-v3/src/entryPoints/dev-run-worker.ts b/packages/cli-v3/src/entryPoints/dev-run-worker.ts index 8a148eaa71..6a526a57c3 100644 --- a/packages/cli-v3/src/entryPoints/dev-run-worker.ts +++ b/packages/cli-v3/src/entryPoints/dev-run-worker.ts @@ -21,6 +21,7 @@ import { runtime, runTimelineMetrics, taskContext, + TaskRunContext, TaskRunErrorCodes, TaskRunExecution, timeout, @@ -29,6 +30,7 @@ import { waitUntil, WorkerManifest, WorkerToExecutorMessageCatalog, + traceContext, } from "@trigger.dev/core/v3"; import { TriggerTracer } from "@trigger.dev/core/v3/tracer"; import { @@ -52,6 +54,7 @@ import { TracingSDK, usage, UsageTimeoutManager, + StandardTraceContextManager, } from "@trigger.dev/core/v3/workers"; import { ZodIpcConnection } from "@trigger.dev/core/v3/zodIpc"; import { readFile } from "node:fs/promises"; @@ -126,6 +129,9 @@ timeout.setGlobalManager(usageTimeoutManager); const standardResourceCatalog = new StandardResourceCatalog(); resourceCatalog.setGlobalResourceCatalog(standardResourceCatalog); +const standardTraceContextManager = new StandardTraceContextManager(); +traceContext.setGlobalManager(standardTraceContextManager); + const durableClock = new DurableClock(); clock.setGlobalClock(durableClock); const runMetadataManager = new StandardMetadataManager( @@ -175,11 +181,11 @@ async function doBootstrap() { const { config, handleError } = await importConfig(workerManifest.configPath); const tracingSDK = new TracingSDK({ - url: env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://0.0.0.0:4318", + url: env.TRIGGER_OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://0.0.0.0:4318", instrumentations: config.telemetry?.instrumentations ?? config.instrumentations ?? [], exporters: config.telemetry?.exporters ?? [], logExporters: config.telemetry?.logExporters ?? [], - diagLogLevel: (env.OTEL_LOG_LEVEL as TracingDiagnosticLogLevel) ?? "none", + diagLogLevel: (env.TRIGGER_OTEL_LOG_LEVEL as TracingDiagnosticLogLevel) ?? "none", forceFlushTimeoutMillis: 30_000, }); @@ -301,6 +307,7 @@ function resetExecutionEnvironment() { _sharedWorkerRuntime?.reset(); durableClock.reset(); taskContext.disable(); + standardTraceContextManager.reset(); log(`[${new Date().toISOString()}] Reset execution environment`); } @@ -337,6 +344,7 @@ const zodIpc = new ZodIpcConnection({ resetExecutionEnvironment(); + standardTraceContextManager.traceContext = traceContext; standardRunTimelineMetricsManager.registerMetricsFromExecution(metrics, isWarmStart); if (_isRunning) { @@ -361,6 +369,14 @@ const zodIpc = new ZodIpcConnection({ return; } + const ctx = TaskRunContext.parse(execution); + + taskContext.setGlobalTaskContext({ + ctx, + worker: metadata, + isWarmStart: isWarmStart ?? false, + }); + try { const { tracer, tracingSDK, consoleInterceptor, config, workerManifest } = await bootstrap(); @@ -516,7 +532,7 @@ const zodIpc = new ZodIpcConnection({ const signal = AbortSignal.any([_cancelController.signal, timeoutController.signal]); - const { result } = await executor.execute(execution, metadata, traceContext, signal); + const { result } = await executor.execute(execution, ctx, signal); if (_isRunning && !_isCancelled) { const usageSample = usage.stop(_executionMeasurement); diff --git a/packages/cli-v3/src/entryPoints/managed-run-worker.ts b/packages/cli-v3/src/entryPoints/managed-run-worker.ts index 21ed6a265f..c659af93de 100644 --- a/packages/cli-v3/src/entryPoints/managed-run-worker.ts +++ b/packages/cli-v3/src/entryPoints/managed-run-worker.ts @@ -20,6 +20,7 @@ import { runtime, runTimelineMetrics, taskContext, + TaskRunContext, TaskRunErrorCodes, TaskRunExecution, timeout, @@ -28,6 +29,7 @@ import { waitUntil, WorkerManifest, WorkerToExecutorMessageCatalog, + traceContext, } from "@trigger.dev/core/v3"; import { TriggerTracer } from "@trigger.dev/core/v3/tracer"; import { @@ -52,6 +54,7 @@ import { TracingSDK, usage, UsageTimeoutManager, + StandardTraceContextManager, } from "@trigger.dev/core/v3/workers"; import { ZodIpcConnection } from "@trigger.dev/core/v3/zodIpc"; import { readFile } from "node:fs/promises"; @@ -119,6 +122,9 @@ resourceCatalog.setGlobalResourceCatalog(standardResourceCatalog); const durableClock = new DurableClock(); clock.setGlobalClock(durableClock); +const standardTraceContextManager = new StandardTraceContextManager(); +traceContext.setGlobalManager(standardTraceContextManager); + const runMetadataManager = new StandardMetadataManager( apiClientManager.clientOrThrow(), getEnvVar("TRIGGER_STREAM_URL", getEnvVar("TRIGGER_API_URL")) ?? "https://api.trigger.dev" @@ -166,9 +172,9 @@ async function doBootstrap() { ); const tracingSDK = new TracingSDK({ - url: env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://0.0.0.0:4318", + url: env.TRIGGER_OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://0.0.0.0:4318", instrumentations: config.instrumentations ?? [], - diagLogLevel: (env.OTEL_LOG_LEVEL as TracingDiagnosticLogLevel) ?? "none", + diagLogLevel: (env.TRIGGER_OTEL_LOG_LEVEL as TracingDiagnosticLogLevel) ?? "none", forceFlushTimeoutMillis: 30_000, exporters: config.telemetry?.exporters ?? [], logExporters: config.telemetry?.logExporters ?? [], @@ -287,6 +293,7 @@ function resetExecutionEnvironment() { _sharedWorkerRuntime?.reset(); durableClock.reset(); taskContext.disable(); + standardTraceContextManager.reset(); console.log(`[${new Date().toISOString()}] Reset execution environment`); } @@ -328,6 +335,8 @@ const zodIpc = new ZodIpcConnection({ resetExecutionEnvironment(); + standardTraceContextManager.traceContext = traceContext; + const prodManager = initializeUsageManager({ usageIntervalMs: getEnvVar("USAGE_HEARTBEAT_INTERVAL_MS"), usageEventUrl: getEnvVar("USAGE_EVENT_URL"), @@ -365,6 +374,14 @@ const zodIpc = new ZodIpcConnection({ return; } + const ctx = TaskRunContext.parse(execution); + + taskContext.setGlobalTaskContext({ + ctx, + worker: metadata, + isWarmStart: isWarmStart ?? false, + }); + try { const { tracer, tracingSDK, consoleInterceptor, config, workerManifest } = await bootstrap(); @@ -514,7 +531,7 @@ const zodIpc = new ZodIpcConnection({ const signal = AbortSignal.any([_cancelController.signal, timeoutController.signal]); - const { result } = await executor.execute(execution, metadata, traceContext, signal); + const { result } = await executor.execute(execution, ctx, signal); if (_isRunning && !_isCancelled) { const usageSample = usage.stop(_executionMeasurement); diff --git a/packages/cli-v3/src/telemetry/tracing.ts b/packages/cli-v3/src/telemetry/tracing.ts deleted file mode 100644 index e00e0668b5..0000000000 --- a/packages/cli-v3/src/telemetry/tracing.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"; -import { registerInstrumentations } from "@opentelemetry/instrumentation"; -import { Resource, detectResourcesSync, processDetectorSync } from "@opentelemetry/resources"; -import { NodeTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-node"; -import { FetchInstrumentation } from "@opentelemetry/instrumentation-fetch"; -import { DiagConsoleLogger, DiagLogLevel, diag, trace } from "@opentelemetry/api"; -import { - SEMRESATTRS_SERVICE_NAME, - SEMRESATTRS_SERVICE_VERSION, -} from "@opentelemetry/semantic-conventions"; -import { logger } from "../utilities/logger.js"; -import { VERSION } from "../version.js"; -import { env } from "std-env"; - -function initializeTracing(): NodeTracerProvider | undefined { - if ( - process.argv.includes("--skip-telemetry") || - env.TRIGGER_DEV_SKIP_TELEMETRY || // only for backwards compat - env.TRIGGER_TELEMETRY_DISABLED - ) { - logger.debug("📉 Telemetry disabled"); - return; - } - - if (env.OTEL_INTERNAL_DIAG_DEBUG) { - diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG); - } - - const resource = detectResourcesSync({ - detectors: [processDetectorSync], - }).merge( - new Resource({ - [SEMRESATTRS_SERVICE_NAME]: "trigger.dev cli v3", - [SEMRESATTRS_SERVICE_VERSION]: VERSION, - }) - ); - - const traceProvider = new NodeTracerProvider({ - forceFlushTimeoutMillis: 30_000, - resource, - spanLimits: { - attributeCountLimit: 1000, - attributeValueLengthLimit: 2048, - eventCountLimit: 100, - attributePerEventCountLimit: 100, - linkCountLimit: 10, - attributePerLinkCountLimit: 100, - }, - }); - - const spanExporter = new OTLPTraceExporter({ - url: "https://otel.baselime.io/v1", - timeoutMillis: 5000, - headers: { - "x-api-key": "b6e0fbbaf8dc2524773d2152ae2e9eb5c7fbaa52", - }, - }); - - const spanProcessor = new SimpleSpanProcessor(spanExporter); - - traceProvider.addSpanProcessor(spanProcessor); - traceProvider.register(); - - registerInstrumentations({ - instrumentations: [new FetchInstrumentation()], - }); - - return traceProvider; -} - -export const provider = initializeTracing(); - -export function getTracer() { - return trace.getTracer("trigger.dev cli v3", VERSION); -} diff --git a/packages/cli-v3/src/utilities/session.ts b/packages/cli-v3/src/utilities/session.ts index be9d9ebfd4..341947ff74 100644 --- a/packages/cli-v3/src/utilities/session.ts +++ b/packages/cli-v3/src/utilities/session.ts @@ -1,12 +1,9 @@ import { recordSpanException } from "@trigger.dev/core/v3/workers"; import { CliApiClient } from "../apiClient.js"; import { readAuthConfigProfile } from "./configFiles.js"; -import { getTracer } from "../telemetry/tracing.js"; import { logger } from "./logger.js"; import { GitMeta } from "@trigger.dev/core/v3"; -const tracer = getTracer(); - export type LoginResultOk = { ok: true; profile: string; @@ -31,63 +28,44 @@ export type LoginResult = }; export async function isLoggedIn(profile: string = "default"): Promise { - return await tracer.startActiveSpan("isLoggedIn", async (span) => { - try { - const config = readAuthConfigProfile(profile); - - if (!config?.accessToken || !config?.apiUrl) { - span.recordException(new Error("You must login first")); - span.end(); - return { ok: false as const, error: "You must login first" }; - } - - const apiClient = new CliApiClient(config.apiUrl, config.accessToken); - const userData = await apiClient.whoAmI(); - - if (!userData.success) { - recordSpanException(span, userData.error); - span.end(); - - return { - ok: false as const, - error: userData.error, - auth: { - apiUrl: config.apiUrl, - accessToken: config.accessToken, - }, - }; - } - - span.setAttributes({ - "login.userId": userData.data.userId, - "login.email": userData.data.email, - "login.dashboardUrl": userData.data.dashboardUrl, - "login.profile": profile, - }); - - span.end(); + try { + const config = readAuthConfigProfile(profile); + + if (!config?.accessToken || !config?.apiUrl) { + return { ok: false as const, error: "You must login first" }; + } + + const apiClient = new CliApiClient(config.apiUrl, config.accessToken); + const userData = await apiClient.whoAmI(); + if (!userData.success) { return { - ok: true as const, - profile, - userId: userData.data.userId, - email: userData.data.email, - dashboardUrl: userData.data.dashboardUrl, + ok: false as const, + error: userData.error, auth: { apiUrl: config.apiUrl, accessToken: config.accessToken, }, }; - } catch (e) { - recordSpanException(span, e); - span.end(); - - return { - ok: false as const, - error: e instanceof Error ? e.message : "Unknown error", - }; } - }); + + return { + ok: true as const, + profile, + userId: userData.data.userId, + email: userData.data.email, + dashboardUrl: userData.data.dashboardUrl, + auth: { + apiUrl: config.apiUrl, + accessToken: config.accessToken, + }, + }; + } catch (e) { + return { + ok: false as const, + error: e instanceof Error ? e.message : "Unknown error", + }; + } } export type GetEnvOptions = { diff --git a/packages/core/package.json b/packages/core/package.json index 05e781fda9..bf14dfdbd4 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -171,17 +171,16 @@ "@google-cloud/precise-date": "^4.0.0", "@jsonhero/path": "^1.0.21", "@opentelemetry/api": "1.9.0", - "@opentelemetry/api-logs": "0.52.1", - "@opentelemetry/core": "^1.30.1", - "@opentelemetry/exporter-logs-otlp-http": "0.52.1", - "@opentelemetry/exporter-trace-otlp-http": "0.52.1", - "@opentelemetry/instrumentation": "0.52.1", - "@opentelemetry/resources": "1.25.1", - "@opentelemetry/sdk-logs": "0.52.1", - "@opentelemetry/sdk-node": "0.52.1", - "@opentelemetry/sdk-trace-base": "1.25.1", - "@opentelemetry/sdk-trace-node": "1.25.1", - "@opentelemetry/semantic-conventions": "1.25.1", + "@opentelemetry/api-logs": "0.203.0", + "@opentelemetry/core": "2.0.1", + "@opentelemetry/exporter-logs-otlp-http": "0.203.0", + "@opentelemetry/exporter-trace-otlp-http": "0.203.0", + "@opentelemetry/instrumentation": "0.203.0", + "@opentelemetry/resources": "2.0.1", + "@opentelemetry/sdk-logs": "0.203.0", + "@opentelemetry/sdk-trace-base": "2.0.1", + "@opentelemetry/sdk-trace-node": "2.0.1", + "@opentelemetry/semantic-conventions": "1.36.0", "dequal": "^2.0.3", "eventsource": "^3.0.5", "eventsource-parser": "^3.0.0", diff --git a/packages/core/src/v3/apiClient/core.ts b/packages/core/src/v3/apiClient/core.ts index ec1fe8421e..1f3dca03fe 100644 --- a/packages/core/src/v3/apiClient/core.ts +++ b/packages/core/src/v3/apiClient/core.ts @@ -4,7 +4,7 @@ import { RetryOptions } from "../schemas/index.js"; import { calculateNextRetryDelay } from "../utils/retries.js"; import { ApiConnectionError, ApiError, ApiSchemaValidationError } from "./errors.js"; -import { Attributes, context, propagation, Span } from "@opentelemetry/api"; +import { Attributes, context, propagation, Span, trace } from "@opentelemetry/api"; import { suppressTracing } from "@opentelemetry/core"; import { SemanticInternalAttributes } from "../semanticInternalAttributes.js"; import type { TriggerTracer } from "../tracer.js"; @@ -617,10 +617,6 @@ export function hasOwn(obj: Object, key: string): boolean { function injectPropagationHeadersIfInWorker(requestInit?: RequestInit): RequestInit | undefined { const headers = new Headers(requestInit?.headers); - if (headers.get("x-trigger-worker") !== "true") { - return requestInit; - } - const headersObject = Object.fromEntries(headers.entries()); propagation.inject(context.active(), headersObject); diff --git a/packages/core/src/v3/index.ts b/packages/core/src/v3/index.ts index 3bd1fc4547..e1785e5049 100644 --- a/packages/core/src/v3/index.ts +++ b/packages/core/src/v3/index.ts @@ -9,6 +9,7 @@ export * from "./limits.js"; export * from "./logger-api.js"; export * from "./runtime-api.js"; export * from "./task-context-api.js"; +export * from "./trace-context-api.js"; export * from "./apiClientManager-api.js"; export * from "./usage-api.js"; export * from "./run-metadata-api.js"; diff --git a/packages/core/src/v3/isomorphic/index.ts b/packages/core/src/v3/isomorphic/index.ts index 53836fb096..8e15c36d2a 100644 --- a/packages/core/src/v3/isomorphic/index.ts +++ b/packages/core/src/v3/isomorphic/index.ts @@ -3,3 +3,4 @@ export * from "./duration.js"; export * from "./maxDuration.js"; export * from "./queueName.js"; export * from "./consts.js"; +export * from "./traceContext.js"; diff --git a/packages/core/src/v3/isomorphic/traceContext.ts b/packages/core/src/v3/isomorphic/traceContext.ts new file mode 100644 index 0000000000..b6754c4c6f --- /dev/null +++ b/packages/core/src/v3/isomorphic/traceContext.ts @@ -0,0 +1,29 @@ +export function parseTraceparent( + traceparent?: string +): { traceId: string; spanId: string } | undefined { + if (!traceparent) { + return undefined; + } + + const parts = traceparent.split("-"); + + if (parts.length !== 4) { + return undefined; + } + + const [version, traceId, spanId] = parts; + + if (version !== "00") { + return undefined; + } + + if (!traceId || !spanId) { + return undefined; + } + + return { traceId, spanId }; +} + +export function serializeTraceparent(traceId: string, spanId: string) { + return `00-${traceId}-${spanId}-01`; +} diff --git a/packages/core/src/v3/otel/tracingSDK.ts b/packages/core/src/v3/otel/tracingSDK.ts index c2d7b3d342..7fded903cd 100644 --- a/packages/core/src/v3/otel/tracingSDK.ts +++ b/packages/core/src/v3/otel/tracingSDK.ts @@ -1,25 +1,19 @@ import { DiagConsoleLogger, DiagLogLevel, TracerProvider, diag } from "@opentelemetry/api"; -import { RandomIdGenerator } from "@opentelemetry/sdk-trace-base"; import { logs } from "@opentelemetry/api-logs"; +import { TraceState } from "@opentelemetry/core"; import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http"; import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"; import { registerInstrumentations, type Instrumentation } from "@opentelemetry/instrumentation"; -import { - DetectorSync, - IResource, - Resource, - ResourceAttributes, - ResourceDetectionConfig, - detectResourcesSync, - processDetectorSync, -} from "@opentelemetry/resources"; +import { detectResources, processDetector, resourceFromAttributes } from "@opentelemetry/resources"; import { BatchLogRecordProcessor, - LoggerProvider, LogRecordExporter, + LogRecordProcessor, + LoggerProvider, ReadableLogRecord, SimpleLogRecordProcessor, } from "@opentelemetry/sdk-logs"; +import { RandomIdGenerator, SpanProcessor } from "@opentelemetry/sdk-trace-base"; import { BatchSpanProcessor, NodeTracerProvider, @@ -40,45 +34,14 @@ import { OTEL_SPAN_EVENT_COUNT_LIMIT, } from "../limits.js"; import { SemanticInternalAttributes } from "../semanticInternalAttributes.js"; +import { taskContext } from "../task-context-api.js"; import { TaskContextLogProcessor, TaskContextSpanProcessor, } from "../taskContext/otelProcessors.js"; +import { traceContext } from "../trace-context-api.js"; import { getEnvVar } from "../utils/getEnv.js"; -class AsyncResourceDetector implements DetectorSync { - private _promise: Promise; - private _resolver?: (value: ResourceAttributes) => void; - private _resolved: boolean = false; - - constructor() { - this._promise = new Promise((resolver) => { - this._resolver = resolver; - }); - } - - get isResolved() { - return this._resolved; - } - - detect(_config?: ResourceDetectionConfig): Resource { - return new Resource({}, this._promise); - } - - resolveWithAttributes(attributes: ResourceAttributes) { - if (!this._resolver) { - throw new Error("Resolver not available"); - } - - if (this._resolved) { - return; - } - - this._resolved = true; - this._resolver(attributes); - } -} - export type TracingDiagnosticLogLevel = | "none" | "error" @@ -91,7 +54,6 @@ export type TracingDiagnosticLogLevel = export type TracingSDKConfig = { url: string; forceFlushTimeoutMillis?: number; - resource?: IResource; instrumentations?: Instrumentation[]; exporters?: SpanExporter[]; logExporters?: LogRecordExporter[]; @@ -101,7 +63,6 @@ export type TracingSDKConfig = { const idGenerator = new RandomIdGenerator(); export class TracingSDK { - public readonly asyncResourceDetector = new AsyncResourceDetector(); private readonly _logProvider: LoggerProvider; private readonly _spanExporter: SpanExporter; private readonly _traceProvider: NodeTracerProvider; @@ -112,83 +73,96 @@ export class TracingSDK { constructor(private readonly config: TracingSDKConfig) { setLogLevel(config.diagLogLevel ?? "none"); - const envResourceAttributesSerialized = getEnvVar("OTEL_RESOURCE_ATTRIBUTES"); + const envResourceAttributesSerialized = getEnvVar("TRIGGER_OTEL_RESOURCE_ATTRIBUTES"); const envResourceAttributes = envResourceAttributesSerialized ? JSON.parse(envResourceAttributesSerialized) : {}; - const commonResources = detectResourcesSync({ - detectors: [this.asyncResourceDetector, processDetectorSync], + const commonResources = detectResources({ + detectors: [processDetector], }) .merge( - new Resource({ + resourceFromAttributes({ [SemanticResourceAttributes.CLOUD_PROVIDER]: "trigger.dev", [SemanticResourceAttributes.SERVICE_NAME]: - getEnvVar("OTEL_SERVICE_NAME") ?? "trigger.dev", + getEnvVar("TRIGGER_OTEL_SERVICE_NAME") ?? "trigger.dev", [SemanticInternalAttributes.TRIGGER]: true, [SemanticInternalAttributes.CLI_VERSION]: VERSION, [SemanticInternalAttributes.SDK_VERSION]: VERSION, [SemanticInternalAttributes.SDK_LANGUAGE]: "typescript", }) ) - .merge(config.resource ?? new Resource({})) - .merge(new Resource(envResourceAttributes)); - - const traceProvider = new NodeTracerProvider({ - forceFlushTimeoutMillis: config.forceFlushTimeoutMillis, - resource: commonResources, - spanLimits: { - attributeCountLimit: OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT, - attributeValueLengthLimit: OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT, - eventCountLimit: OTEL_SPAN_EVENT_COUNT_LIMIT, - attributePerEventCountLimit: OTEL_ATTRIBUTE_PER_EVENT_COUNT_LIMIT, - linkCountLimit: OTEL_LINK_COUNT_LIMIT, - attributePerLinkCountLimit: OTEL_ATTRIBUTE_PER_LINK_COUNT_LIMIT, - }, - }); + .merge(resourceFromAttributes(envResourceAttributes)) + .merge(resourceFromAttributes(taskContext.resourceAttributes)); const spanExporter = new OTLPTraceExporter({ url: `${config.url}/v1/traces`, timeoutMillis: config.forceFlushTimeoutMillis, }); - traceProvider.addSpanProcessor( + const spanProcessors: Array = []; + + spanProcessors.push( new TaskContextSpanProcessor( - traceProvider.getTracer("trigger-dev-worker", VERSION), - getEnvVar("OTEL_BATCH_PROCESSING_ENABLED") === "1" + VERSION, + getEnvVar("TRIGGER_OTEL_BATCH_PROCESSING_ENABLED") === "1" ? new BatchSpanProcessor(spanExporter, { - maxExportBatchSize: parseInt(getEnvVar("OTEL_SPAN_MAX_EXPORT_BATCH_SIZE") ?? "64"), + maxExportBatchSize: parseInt( + getEnvVar("TRIGGER_OTEL_SPAN_MAX_EXPORT_BATCH_SIZE") ?? "64" + ), scheduledDelayMillis: parseInt( - getEnvVar("OTEL_SPAN_SCHEDULED_DELAY_MILLIS") ?? "200" + getEnvVar("TRIGGER_OTEL_SPAN_SCHEDULED_DELAY_MILLIS") ?? "200" ), exportTimeoutMillis: parseInt( - getEnvVar("OTEL_SPAN_EXPORT_TIMEOUT_MILLIS") ?? "30000" + getEnvVar("TRIGGER_OTEL_SPAN_EXPORT_TIMEOUT_MILLIS") ?? "30000" ), - maxQueueSize: parseInt(getEnvVar("OTEL_SPAN_MAX_QUEUE_SIZE") ?? "512"), + maxQueueSize: parseInt(getEnvVar("TRIGGER_OTEL_SPAN_MAX_QUEUE_SIZE") ?? "512"), }) : new SimpleSpanProcessor(spanExporter) ) ); const externalTraceId = idGenerator.generateTraceId(); + const externalTraceContext = traceContext.getExternalTraceContext(); for (const exporter of config.exporters ?? []) { - 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)) + spanProcessors.push( + getEnvVar("TRIGGER_OTEL_BATCH_PROCESSING_ENABLED") === "1" + ? new BatchSpanProcessor( + new ExternalSpanExporterWrapper(exporter, externalTraceId, externalTraceContext), + { + maxExportBatchSize: parseInt( + getEnvVar("TRIGGER_OTEL_SPAN_MAX_EXPORT_BATCH_SIZE") ?? "64" + ), + scheduledDelayMillis: parseInt( + getEnvVar("TRIGGER_OTEL_SPAN_SCHEDULED_DELAY_MILLIS") ?? "200" + ), + exportTimeoutMillis: parseInt( + getEnvVar("TRIGGER_OTEL_SPAN_EXPORT_TIMEOUT_MILLIS") ?? "30000" + ), + maxQueueSize: parseInt(getEnvVar("TRIGGER_OTEL_SPAN_MAX_QUEUE_SIZE") ?? "512"), + } + ) + : new SimpleSpanProcessor( + new ExternalSpanExporterWrapper(exporter, externalTraceId, externalTraceContext) + ) ); } + const traceProvider = new NodeTracerProvider({ + forceFlushTimeoutMillis: config.forceFlushTimeoutMillis, + resource: commonResources, + spanLimits: { + attributeCountLimit: OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT, + attributeValueLengthLimit: OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT, + eventCountLimit: OTEL_SPAN_EVENT_COUNT_LIMIT, + attributePerEventCountLimit: OTEL_ATTRIBUTE_PER_EVENT_COUNT_LIMIT, + linkCountLimit: OTEL_LINK_COUNT_LIMIT, + attributePerLinkCountLimit: OTEL_ATTRIBUTE_PER_LINK_COUNT_LIMIT, + }, + spanProcessors, + }); + traceProvider.register(); registerInstrumentations({ @@ -200,50 +174,67 @@ export class TracingSDK { url: `${config.url}/v1/logs`, }); - // To start a logger, you first need to initialize the Logger provider. - const loggerProvider = new LoggerProvider({ - resource: commonResources, - logRecordLimits: { - attributeCountLimit: OTEL_LOG_ATTRIBUTE_COUNT_LIMIT, - attributeValueLengthLimit: OTEL_LOG_ATTRIBUTE_VALUE_LENGTH_LIMIT, - }, - }); - - loggerProvider.addLogRecordProcessor( + const logProcessors: Array = [ new TaskContextLogProcessor( - getEnvVar("OTEL_BATCH_PROCESSING_ENABLED") === "1" + getEnvVar("TRIGGER_OTEL_BATCH_PROCESSING_ENABLED") === "1" ? new BatchLogRecordProcessor(logExporter, { - maxExportBatchSize: parseInt(getEnvVar("OTEL_LOG_MAX_EXPORT_BATCH_SIZE") ?? "64"), - scheduledDelayMillis: parseInt(getEnvVar("OTEL_LOG_SCHEDULED_DELAY_MILLIS") ?? "200"), - exportTimeoutMillis: parseInt(getEnvVar("OTEL_LOG_EXPORT_TIMEOUT_MILLIS") ?? "30000"), - maxQueueSize: parseInt(getEnvVar("OTEL_LOG_MAX_QUEUE_SIZE") ?? "512"), + maxExportBatchSize: parseInt( + getEnvVar("TRIGGER_OTEL_LOG_MAX_EXPORT_BATCH_SIZE") ?? "64" + ), + scheduledDelayMillis: parseInt( + getEnvVar("TRIGGER_OTEL_LOG_SCHEDULED_DELAY_MILLIS") ?? "200" + ), + exportTimeoutMillis: parseInt( + getEnvVar("TRIGGER_OTEL_LOG_EXPORT_TIMEOUT_MILLIS") ?? "30000" + ), + maxQueueSize: parseInt(getEnvVar("TRIGGER_OTEL_LOG_MAX_QUEUE_SIZE") ?? "512"), }) : new SimpleLogRecordProcessor(logExporter) - ) - ); + ), + ]; for (const externalLogExporter of config.logExporters ?? []) { - loggerProvider.addLogRecordProcessor( - getEnvVar("OTEL_BATCH_PROCESSING_ENABLED") === "1" + logProcessors.push( + getEnvVar("TRIGGER_OTEL_BATCH_PROCESSING_ENABLED") === "1" ? new BatchLogRecordProcessor( - new ExternalLogRecordExporterWrapper(externalLogExporter, externalTraceId), + new ExternalLogRecordExporterWrapper( + externalLogExporter, + externalTraceId, + externalTraceContext + ), { - maxExportBatchSize: parseInt(getEnvVar("OTEL_LOG_MAX_EXPORT_BATCH_SIZE") ?? "64"), + maxExportBatchSize: parseInt( + getEnvVar("TRIGGER_OTEL_LOG_MAX_EXPORT_BATCH_SIZE") ?? "64" + ), scheduledDelayMillis: parseInt( - getEnvVar("OTEL_LOG_SCHEDULED_DELAY_MILLIS") ?? "200" + getEnvVar("TRIGGER_OTEL_LOG_SCHEDULED_DELAY_MILLIS") ?? "200" ), exportTimeoutMillis: parseInt( - getEnvVar("OTEL_LOG_EXPORT_TIMEOUT_MILLIS") ?? "30000" + getEnvVar("TRIGGER_OTEL_LOG_EXPORT_TIMEOUT_MILLIS") ?? "30000" ), - maxQueueSize: parseInt(getEnvVar("OTEL_LOG_MAX_QUEUE_SIZE") ?? "512"), + maxQueueSize: parseInt(getEnvVar("TRIGGER_OTEL_LOG_MAX_QUEUE_SIZE") ?? "512"), } ) : new SimpleLogRecordProcessor( - new ExternalLogRecordExporterWrapper(externalLogExporter, externalTraceId) + new ExternalLogRecordExporterWrapper( + externalLogExporter, + externalTraceId, + externalTraceContext + ) ) ); } + // To start a logger, you first need to initialize the Logger provider. + const loggerProvider = new LoggerProvider({ + resource: commonResources, + logRecordLimits: { + attributeCountLimit: OTEL_LOG_ATTRIBUTE_COUNT_LIMIT, + attributeValueLengthLimit: OTEL_LOG_ATTRIBUTE_VALUE_LENGTH_LIMIT, + }, + processors: logProcessors, + }); + this._logProvider = loggerProvider; this._spanExporter = spanExporter; this._traceProvider = traceProvider; @@ -298,7 +289,10 @@ function setLogLevel(level: TracingDiagnosticLogLevel) { class ExternalSpanExporterWrapper { constructor( private underlyingExporter: SpanExporter, - private externalTraceId: string + private externalTraceId: string, + private externalTraceContext: + | { traceId: string; spanId: string; tracestate?: string } + | undefined ) {} private transformSpan(span: ReadableSpan): ReadableSpan | undefined { @@ -307,14 +301,38 @@ class ExternalSpanExporterWrapper { return; } + const externalTraceId = this.externalTraceContext + ? this.externalTraceContext.traceId + : this.externalTraceId; + + const isAttemptSpan = span.attributes[SemanticInternalAttributes.SPAN_ATTEMPT]; + const spanContext = span.spanContext(); + let parentSpanContext = span.parentSpanContext; + + if (parentSpanContext) { + parentSpanContext = { + ...parentSpanContext, + traceId: externalTraceId, + }; + } + + if (isAttemptSpan && this.externalTraceContext) { + parentSpanContext = { + ...parentSpanContext, + traceId: externalTraceId, + spanId: this.externalTraceContext.spanId, + traceState: this.externalTraceContext.tracestate + ? new TraceState(this.externalTraceContext.tracestate) + : undefined, + traceFlags: parentSpanContext?.traceFlags ?? 0, + }; + } return { ...span, - spanContext: () => ({ ...spanContext, traceId: this.externalTraceId }), - parentSpanId: span.attributes[SemanticInternalAttributes.SPAN_ATTEMPT] - ? undefined - : span.parentSpanId, + spanContext: () => ({ ...spanContext, traceId: externalTraceId }), + parentSpanContext, }; } @@ -344,7 +362,10 @@ class ExternalSpanExporterWrapper { class ExternalLogRecordExporterWrapper { constructor( private underlyingExporter: LogRecordExporter, - private externalTraceId: string + private externalTraceId: string, + private externalTraceContext: + | { traceId: string; spanId: string; tracestate?: string } + | undefined ) {} export(logs: any[], resultCallback: (result: any) => void): void { @@ -359,12 +380,14 @@ class ExternalLogRecordExporterWrapper { transformLogRecord(logRecord: ReadableLogRecord): ReadableLogRecord { // If there's no spanContext, or if the externalTraceId is not set, return the original logRecord. - if (!logRecord.spanContext || !this.externalTraceId) { + if (!logRecord.spanContext || !this.externalTraceId || !this.externalTraceContext) { return logRecord; } // Capture externalTraceId for use within the proxy's scope. - const { externalTraceId } = this; + const externalTraceId = this.externalTraceContext + ? this.externalTraceContext.traceId + : this.externalTraceId; return new Proxy(logRecord, { get(target, prop, receiver) { diff --git a/packages/core/src/v3/schemas/schemas.ts b/packages/core/src/v3/schemas/schemas.ts index bd32d848ff..ccd0fa1880 100644 --- a/packages/core/src/v3/schemas/schemas.ts +++ b/packages/core/src/v3/schemas/schemas.ts @@ -296,3 +296,16 @@ export const RunChainState = z.object({ }); export type RunChainState = z.infer; + +export const TriggerTraceContext = z.object({ + traceparent: z.string().optional(), + tracestate: z.string().optional(), + external: z + .object({ + traceparent: z.string().optional(), + tracestate: z.string().optional(), + }) + .optional(), +}); + +export type TriggerTraceContext = z.infer; diff --git a/packages/core/src/v3/taskContext/otelProcessors.ts b/packages/core/src/v3/taskContext/otelProcessors.ts index db30624ff6..16f93d42a9 100644 --- a/packages/core/src/v3/taskContext/otelProcessors.ts +++ b/packages/core/src/v3/taskContext/otelProcessors.ts @@ -1,17 +1,16 @@ -import { LogRecord, LogRecordProcessor } from "@opentelemetry/sdk-logs"; +import { Context, trace, Tracer } from "@opentelemetry/api"; +import { LogRecordProcessor, SdkLogRecord } from "@opentelemetry/sdk-logs"; import { Span, SpanProcessor } from "@opentelemetry/sdk-trace-base"; import { SemanticInternalAttributes } from "../semanticInternalAttributes.js"; -import { Context } from "@opentelemetry/api"; -import { flattenAttributes } from "../utils/flattenAttributes.js"; import { taskContext } from "../task-context-api.js"; -import { Tracer } from "@opentelemetry/api"; +import { flattenAttributes } from "../utils/flattenAttributes.js"; export class TaskContextSpanProcessor implements SpanProcessor { private _innerProcessor: SpanProcessor; private _tracer: Tracer; - constructor(tracer: Tracer, innerProcessor: SpanProcessor) { - this._tracer = tracer; + constructor(version: string, innerProcessor: SpanProcessor) { + this._tracer = trace.getTracer("trigger-dev-worker", version); this._innerProcessor = innerProcessor; } @@ -91,7 +90,7 @@ export class TaskContextLogProcessor implements LogRecordProcessor { forceFlush(): Promise { return this._innerProcessor.forceFlush(); } - onEmit(logRecord: LogRecord, context?: Context | undefined): void { + onEmit(logRecord: SdkLogRecord, context?: Context | undefined): void { // Adds in the context attributes to the log record if (taskContext.ctx) { logRecord.setAttributes( diff --git a/packages/core/src/v3/trace-context-api.ts b/packages/core/src/v3/trace-context-api.ts new file mode 100644 index 0000000000..1a4333fbe2 --- /dev/null +++ b/packages/core/src/v3/trace-context-api.ts @@ -0,0 +1,5 @@ +// Split module-level variable definition into separate files to allow +// tree-shaking on each api instance. +import { TraceContextAPI } from "./traceContext/api.js"; +/** Entrypoint for trace context API */ +export const traceContext = TraceContextAPI.getInstance(); diff --git a/packages/core/src/v3/traceContext/api.ts b/packages/core/src/v3/traceContext/api.ts new file mode 100644 index 0000000000..3b21e0668a --- /dev/null +++ b/packages/core/src/v3/traceContext/api.ts @@ -0,0 +1,74 @@ +import { context, Context } from "@opentelemetry/api"; +import { getGlobal, registerGlobal, unregisterGlobal } from "../utils/globals.js"; +import { TraceContextManager } from "./types.js"; + +const API_NAME = "trace-context"; + +class NoopTraceContextManager implements TraceContextManager { + getTraceContext() { + return {}; + } + + reset() {} + + getExternalTraceContext() { + return undefined; + } + + extractContext(): Context { + return context.active(); + } + + withExternalTrace(fn: () => T): T { + return fn(); + } +} + +const NOOP_TRACE_CONTEXT_MANAGER = new NoopTraceContextManager(); + +export class TraceContextAPI implements TraceContextManager { + private static _instance?: TraceContextAPI; + + private constructor() {} + + public static getInstance(): TraceContextAPI { + if (!this._instance) { + this._instance = new TraceContextAPI(); + } + + return this._instance; + } + + public setGlobalManager(manager: TraceContextManager): boolean { + return registerGlobal(API_NAME, manager); + } + + public disable() { + unregisterGlobal(API_NAME); + } + + public reset() { + this.#getManager().reset(); + this.disable(); + } + + public getTraceContext() { + return this.#getManager().getTraceContext(); + } + + public getExternalTraceContext() { + return this.#getManager().getExternalTraceContext(); + } + + public extractContext() { + return this.#getManager().extractContext(); + } + + public withExternalTrace(fn: () => T): T { + return this.#getManager().withExternalTrace(fn); + } + + #getManager(): TraceContextManager { + return getGlobal(API_NAME) ?? NOOP_TRACE_CONTEXT_MANAGER; + } +} diff --git a/packages/core/src/v3/traceContext/manager.ts b/packages/core/src/v3/traceContext/manager.ts new file mode 100644 index 0000000000..aa7f92b748 --- /dev/null +++ b/packages/core/src/v3/traceContext/manager.ts @@ -0,0 +1,77 @@ +import { Context, context, propagation, trace, TraceFlags } from "@opentelemetry/api"; +import { TraceContextManager } from "./types.js"; + +export class StandardTraceContextManager implements TraceContextManager { + public traceContext: Record = {}; + + getTraceContext() { + return this.traceContext; + } + + reset() { + this.traceContext = {}; + } + + getExternalTraceContext() { + return extractExternalTraceContext(this.traceContext?.external); + } + + extractContext(): Context { + return propagation.extract(context.active(), this.traceContext ?? {}); + } + + withExternalTrace(fn: () => T): T { + const externalTraceContext = this.getExternalTraceContext(); + + if (!externalTraceContext) { + return fn(); + } + + // Get the current active span context to extract the span ID + const currentSpanContext = trace.getActiveSpan()?.spanContext(); + + if (!currentSpanContext) { + throw new Error( + "No active span found. withExternalSpan must be called within an active span context." + ); + } + + const spanContext = { + traceId: externalTraceContext.traceId, + spanId: currentSpanContext.spanId, + traceFlags: TraceFlags.SAMPLED, + isRemote: true, + }; + + const contextWithSpan = trace.setSpanContext(context.active(), spanContext); + + return context.with(contextWithSpan, fn); + } +} + +function extractExternalTraceContext(traceContext: unknown) { + if (typeof traceContext !== "object" || traceContext === null) { + return undefined; + } + + const tracestate = + "tracestate" in traceContext && typeof traceContext.tracestate === "string" + ? traceContext.tracestate + : undefined; + + if ("traceparent" in traceContext && typeof traceContext.traceparent === "string") { + const [version, traceId, spanId] = traceContext.traceparent.split("-"); + + if (!traceId || !spanId) { + return undefined; + } + + return { + traceId, + spanId, + tracestate: tracestate, + }; + } + + return undefined; +} diff --git a/packages/core/src/v3/traceContext/types.ts b/packages/core/src/v3/traceContext/types.ts new file mode 100644 index 0000000000..a1130cdf56 --- /dev/null +++ b/packages/core/src/v3/traceContext/types.ts @@ -0,0 +1,15 @@ +import { Context } from "@opentelemetry/api"; + +export interface TraceContextManager { + getTraceContext(): Record; + extractContext(): Context; + reset(): void; + getExternalTraceContext(): + | { + traceId: string; + spanId: string; + tracestate?: string; + } + | undefined; + withExternalTrace(fn: () => T): T; +} diff --git a/packages/core/src/v3/tracer.ts b/packages/core/src/v3/tracer.ts index 4adf8268b5..5b21391759 100644 --- a/packages/core/src/v3/tracer.ts +++ b/packages/core/src/v3/tracer.ts @@ -63,10 +63,6 @@ export class TriggerTracer { return this._logger; } - extractContext(traceContext?: Record) { - return propagation.extract(context.active(), traceContext ?? {}); - } - startActiveSpan( name: string, fn: (span: Span) => Promise, diff --git a/packages/core/src/v3/utils/globals.ts b/packages/core/src/v3/utils/globals.ts index e59539b343..570bb34150 100644 --- a/packages/core/src/v3/utils/globals.ts +++ b/packages/core/src/v3/utils/globals.ts @@ -8,6 +8,7 @@ import type { RuntimeManager } from "../runtime/manager.js"; import { RunTimelineMetricsManager } from "../runTimelineMetrics/types.js"; import { TaskContext } from "../taskContext/types.js"; import { TimeoutManager } from "../timeout/types.js"; +import { TraceContextManager } from "../traceContext/types.js"; import { UsageManager } from "../usage/types.js"; import { WaitUntilManager } from "../waitUntil/types.js"; import { _globalThis } from "./platform.js"; @@ -66,4 +67,5 @@ type TriggerDotDevGlobalAPI = { ["run-timeline-metrics"]?: RunTimelineMetricsManager; ["lifecycle-hooks"]?: LifecycleHooksManager; ["locals"]?: LocalsManager; + ["trace-context"]?: TraceContextManager; }; diff --git a/packages/core/src/v3/workers/index.ts b/packages/core/src/v3/workers/index.ts index 5ff626f2ea..613fe33025 100644 --- a/packages/core/src/v3/workers/index.ts +++ b/packages/core/src/v3/workers/index.ts @@ -28,3 +28,4 @@ export { WarmStartClient, type WarmStartClientOptions } from "../workers/warmSta export { StandardLifecycleHooksManager } from "../lifecycleHooks/manager.js"; export { StandardLocalsManager } from "../locals/manager.js"; export { populateEnv } from "./populateEnv.js"; +export { StandardTraceContextManager } from "../traceContext/manager.js"; diff --git a/packages/core/src/v3/workers/taskExecutor.ts b/packages/core/src/v3/workers/taskExecutor.ts index eafe00b1f3..38e7d7c19a 100644 --- a/packages/core/src/v3/workers/taskExecutor.ts +++ b/packages/core/src/v3/workers/taskExecutor.ts @@ -1,5 +1,5 @@ -import { Context, context, SpanKind, trace } from "@opentelemetry/api"; -import { VERSION } from "../../version.js"; +import { Context, context, SpanKind } from "@opentelemetry/api"; +import { promiseWithResolvers } from "../../utils.js"; import { ApiError, RateLimitError } from "../apiClient/errors.js"; import { ConsoleInterceptor } from "../consoleInterceptor.js"; import { @@ -17,6 +17,7 @@ import { lifecycleHooks, OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT, runMetadata, + traceContext, waitUntil, } from "../index.js"; import { @@ -31,7 +32,6 @@ import { runTimelineMetrics } from "../run-timeline-metrics-api.js"; import { COLD_VARIANT, RetryOptions, - ServerBackgroundWorker, TaskRunContext, TaskRunErrorCodes, TaskRunExecution, @@ -40,7 +40,6 @@ import { WARM_VARIANT, } from "../schemas/index.js"; import { SemanticInternalAttributes } from "../semanticInternalAttributes.js"; -import { taskContext } from "../task-context-api.js"; import { TriggerTracer } from "../tracer.js"; import { tryCatch } from "../tryCatch.js"; import { HandleErrorModificationOptions, TaskMetadataWithFunctions } from "../types/index.js"; @@ -52,7 +51,6 @@ import { stringifyIO, } from "../utils/ioSerialization.js"; import { calculateNextRetryDelay } from "../utils/retries.js"; -import { promiseWithResolvers } from "../../utils.js"; export type TaskExecutorOptions = { tracingSDK: TracingSDK; @@ -93,12 +91,9 @@ export class TaskExecutor { async execute( execution: TaskRunExecution, - worker: ServerBackgroundWorker, - traceContext: Record, - signal: AbortSignal, - isWarmStart?: boolean + ctx: TaskRunContext, + signal: AbortSignal ): Promise<{ result: TaskRunExecutionResult }> { - const ctx = TaskRunContext.parse(execution); const attemptMessage = `Attempt ${execution.attempt.number}`; const originalPacket = { @@ -106,22 +101,10 @@ export class TaskExecutor { dataType: execution.run.payloadType, }; - taskContext.setGlobalTaskContext({ - ctx, - worker, - isWarmStart: isWarmStart ?? this._isWarmStart, - }); - if (execution.run.metadata) { runMetadata.enterWithMetadata(execution.run.metadata); } - if (!this._tracingSDK.asyncResourceDetector.isResolved) { - this._tracingSDK.asyncResourceDetector.resolveWithAttributes({ - ...taskContext.resourceAttributes, - }); - } - const result = await this._tracer.startActiveSpan( attemptMessage, async (span) => { @@ -369,7 +352,7 @@ export class TaskExecutor { ? runTimelineMetrics.convertMetricsToSpanEvents() : undefined, }, - this._tracer.extractContext(traceContext), + traceContext.extractContext(), signal ); diff --git a/packages/core/test/taskExecutor.test.ts b/packages/core/test/taskExecutor.test.ts index d78cc57cd7..229a952fff 100644 --- a/packages/core/test/taskExecutor.test.ts +++ b/packages/core/test/taskExecutor.test.ts @@ -1942,5 +1942,5 @@ function executeTask( const $signal = signal ? signal : new AbortController().signal; - return executor.execute(execution, worker, {}, $signal); + return executor.execute(execution, execution, $signal); } diff --git a/packages/trigger-sdk/package.json b/packages/trigger-sdk/package.json index 8b2ce0db4e..d070d2049c 100644 --- a/packages/trigger-sdk/package.json +++ b/packages/trigger-sdk/package.json @@ -50,8 +50,7 @@ }, "dependencies": { "@opentelemetry/api": "1.9.0", - "@opentelemetry/api-logs": "0.52.1", - "@opentelemetry/semantic-conventions": "1.25.1", + "@opentelemetry/semantic-conventions": "1.36.0", "@trigger.dev/core": "workspace:4.0.0-v4-beta.26", "chalk": "^5.2.0", "cronstrue": "^2.21.0", diff --git a/packages/trigger-sdk/src/v3/index.ts b/packages/trigger-sdk/src/v3/index.ts index 4527cd6d01..94e3e23cd0 100644 --- a/packages/trigger-sdk/src/v3/index.ts +++ b/packages/trigger-sdk/src/v3/index.ts @@ -13,6 +13,7 @@ export * from "./metadata.js"; export * from "./timeout.js"; export * from "./webhooks.js"; export * from "./locals.js"; +export * from "./otel.js"; export type { Context }; import type { Context } from "./shared.js"; diff --git a/packages/trigger-sdk/src/v3/otel.ts b/packages/trigger-sdk/src/v3/otel.ts new file mode 100644 index 0000000000..e80c77562e --- /dev/null +++ b/packages/trigger-sdk/src/v3/otel.ts @@ -0,0 +1,7 @@ +import { traceContext } from "@trigger.dev/core/v3"; + +export const otel = { + withExternalTrace: (fn: () => T): T => { + return traceContext.withExternalTrace(fn); + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 90b1371956..0c91127b61 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -304,7 +304,7 @@ importers: version: 0.52.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0) + version: 0.52.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-express': specifier: ^0.36.1 version: 0.36.1(@opentelemetry/api@1.9.0) @@ -322,7 +322,7 @@ importers: version: 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-node': specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0) + version: 0.52.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': specifier: 1.25.1 version: 1.25.1(@opentelemetry/api@1.9.0) @@ -1276,38 +1276,26 @@ importers: specifier: 1.9.0 version: 1.9.0 '@opentelemetry/api-logs': - specifier: 0.52.1 - version: 0.52.1 - '@opentelemetry/exporter-logs-otlp-http': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0) + specifier: 0.203.0 + version: 0.203.0 '@opentelemetry/exporter-trace-otlp-http': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0) + specifier: 0.203.0 + version: 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0) + specifier: 0.203.0 + version: 0.203.0(@opentelemetry/api@1.9.0)(supports-color@10.0.0) '@opentelemetry/instrumentation-fetch': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0) + specifier: 0.203.0 + version: 0.203.0(@opentelemetry/api@1.9.0)(supports-color@10.0.0) '@opentelemetry/resources': - specifier: 1.25.1 - version: 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-node': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0) - '@opentelemetry/sdk-trace-base': - specifier: 1.25.1 - version: 1.25.1(@opentelemetry/api@1.9.0) + specifier: 2.0.1 + version: 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-node': - specifier: 1.25.1 - version: 1.25.1(@opentelemetry/api@1.9.0) + specifier: 2.0.1 + version: 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': - specifier: 1.25.1 - version: 1.25.1 + specifier: 1.36.0 + version: 1.36.0 '@trigger.dev/build': specifier: workspace:4.0.0-v4-beta.26 version: link:../build @@ -1526,38 +1514,35 @@ importers: specifier: 1.9.0 version: 1.9.0 '@opentelemetry/api-logs': - specifier: 0.52.1 - version: 0.52.1 + specifier: 0.203.0 + version: 0.203.0 '@opentelemetry/core': - specifier: ^1.30.1 - version: 1.30.1(@opentelemetry/api@1.9.0) + specifier: 2.0.1 + version: 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/exporter-logs-otlp-http': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0) + specifier: 0.203.0 + version: 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/exporter-trace-otlp-http': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0) + specifier: 0.203.0 + version: 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0) + specifier: 0.203.0 + version: 0.203.0(@opentelemetry/api@1.9.0)(supports-color@10.0.0) '@opentelemetry/resources': - specifier: 1.25.1 - version: 1.25.1(@opentelemetry/api@1.9.0) + specifier: 2.0.1 + version: 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-logs': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-node': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0) + specifier: 0.203.0 + version: 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': - specifier: 1.25.1 - version: 1.25.1(@opentelemetry/api@1.9.0) + specifier: 2.0.1 + version: 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-node': - specifier: 1.25.1 - version: 1.25.1(@opentelemetry/api@1.9.0) + specifier: 2.0.1 + version: 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': - specifier: 1.25.1 - version: 1.25.1 + specifier: 1.36.0 + version: 1.36.0 dequal: specifier: ^2.0.3 version: 2.0.3 @@ -1815,12 +1800,9 @@ importers: '@opentelemetry/api': specifier: 1.9.0 version: 1.9.0 - '@opentelemetry/api-logs': - specifier: 0.52.1 - version: 0.52.1 '@opentelemetry/semantic-conventions': - specifier: 1.25.1 - version: 1.25.1 + specifier: 1.36.0 + version: 1.36.0 '@trigger.dev/core': specifier: workspace:4.0.0-v4-beta.26 version: link:../core @@ -1913,12 +1895,24 @@ importers: '@e2b/code-interpreter': specifier: ^1.1.0 version: 1.1.0 + '@opentelemetry/api': + specifier: ^1.9.0 + version: 1.9.0 + '@opentelemetry/api-logs': + specifier: ^0.203.0 + version: 0.203.0 '@opentelemetry/exporter-logs-otlp-http': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0) + specifier: 0.203.0 + version: 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/exporter-trace-otlp-http': - specifier: 0.52.1 - version: 0.52.1(@opentelemetry/api@1.9.0) + specifier: 0.203.0 + version: 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': + specifier: ^0.203.0 + version: 0.203.0(@opentelemetry/api@1.9.0)(supports-color@10.0.0) + '@opentelemetry/sdk-logs': + specifier: ^0.203.0 + version: 0.203.0(@opentelemetry/api@1.9.0) '@radix-ui/react-avatar': specifier: ^1.1.3 version: 1.1.3(@types/react-dom@19.0.4)(@types/react@19.0.12)(react-dom@19.0.0)(react@19.0.0) @@ -1934,6 +1928,9 @@ importers: '@trigger.dev/sdk': specifier: workspace:* version: link:../../packages/trigger-sdk + '@vercel/otel': + specifier: ^1.13.0 + version: 1.13.0(@opentelemetry/api-logs@0.203.0)(@opentelemetry/api@1.9.0)(@opentelemetry/instrumentation@0.203.0)(@opentelemetry/resources@1.25.1)(@opentelemetry/sdk-logs@0.203.0)(@opentelemetry/sdk-metrics@1.25.1)(@opentelemetry/sdk-trace-base@1.25.1) '@vercel/postgres': specifier: ^0.10.0 version: 0.10.0 @@ -2469,7 +2466,7 @@ importers: version: 1.25.1(@opentelemetry/api@1.4.1) '@opentelemetry/sdk-logs': specifier: ^0.49.1 - version: 0.49.1(@opentelemetry/api-logs@0.52.1)(@opentelemetry/api@1.4.1) + version: 0.49.1(@opentelemetry/api-logs@0.203.0)(@opentelemetry/api@1.4.1) '@opentelemetry/sdk-node': specifier: ^0.49.1 version: 0.49.1(@opentelemetry/api@1.4.1) @@ -3019,7 +3016,7 @@ packages: dependencies: '@andrewbranch/untar.js': 1.0.3 fflate: 0.8.2 - semver: 7.6.3 + semver: 7.7.2 ts-expose-internals-conditionally: 1.0.0-empty.0 typescript: 5.3.3 validate-npm-package-name: 5.0.0 @@ -4817,7 +4814,7 @@ packages: '@babel/traverse': 7.24.7 '@babel/types': 7.24.0 convert-source-map: 1.9.0 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -4839,7 +4836,7 @@ packages: '@babel/traverse': 7.24.7 '@babel/types': 7.27.0 convert-source-map: 2.0.0 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -5416,7 +5413,7 @@ packages: '@babel/helper-split-export-declaration': 7.22.6 '@babel/parser': 7.24.7 '@babel/types': 7.24.0 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -5434,7 +5431,7 @@ packages: '@babel/helper-split-export-declaration': 7.24.7 '@babel/parser': 7.27.0 '@babel/types': 7.27.0 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -5448,7 +5445,7 @@ packages: '@babel/parser': 7.27.0 '@babel/template': 7.25.0 '@babel/types': 7.27.0 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -5544,7 +5541,7 @@ packages: outdent: 0.5.0 prettier: 2.8.8 resolve-from: 5.0.0 - semver: 7.6.3 + semver: 7.7.2 dev: false /@changesets/assemble-release-plan@5.2.4(patch_hash=3wuhjtl4hjck4itk3w32z4cd5u): @@ -5555,7 +5552,7 @@ packages: '@changesets/get-dependents-graph': 1.3.6 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 - semver: 7.6.3 + semver: 7.7.2 dev: false patched: true @@ -5629,7 +5626,7 @@ packages: '@manypkg/get-packages': 1.1.3 chalk: 2.4.2 fs-extra: 7.0.1 - semver: 7.6.3 + semver: 7.7.2 dev: false /@changesets/get-github-info@0.5.2: @@ -7955,7 +7952,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 espree: 9.6.0 globals: 13.19.0 ignore: 5.2.4 @@ -8205,13 +8202,6 @@ packages: '@grpc/proto-loader': 0.7.13 '@js-sdsl/ordered-map': 4.4.2 - /@grpc/grpc-js@1.8.17: - resolution: {integrity: sha512-DGuSbtMFbaRsyffMf+VEkVu8HkSXEUfO3UyGJNtqxW9ABdtTIA+2UXAJpwbJS+xfQxuwqLUeELmL6FuZkOqPxw==} - engines: {node: ^8.13.0 || >=10.10.0} - dependencies: - '@grpc/proto-loader': 0.7.7 - '@types/node': 20.14.14 - /@grpc/proto-loader@0.7.13: resolution: {integrity: sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==} engines: {node: '>=6'} @@ -8222,17 +8212,6 @@ packages: protobufjs: 7.3.2 yargs: 17.7.2 - /@grpc/proto-loader@0.7.7: - resolution: {integrity: sha512-1TIeXOi8TuSCQprPItwoMymZXxWT0CPxUhkrkeCUH+D8U7QDwQ6b7SUz2MaLuWM2llT+J/TVFLmQI5KtML3BhQ==} - engines: {node: '>=6'} - hasBin: true - dependencies: - '@types/long': 4.0.2 - lodash.camelcase: 4.3.0 - long: 4.0.0 - protobufjs: 7.3.2 - yargs: 17.7.2 - /@hapi/boom@10.0.1: resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==} dependencies: @@ -8332,7 +8311,7 @@ packages: engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -9679,7 +9658,7 @@ packages: resolution: {integrity: sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: - semver: 7.6.3 + semver: 7.7.2 /@npmcli/git@4.1.0: resolution: {integrity: sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==} @@ -9691,7 +9670,7 @@ packages: proc-log: 3.0.0 promise-inflight: 1.0.1 promise-retry: 2.0.1 - semver: 7.6.3 + semver: 7.7.2 which: 3.0.1 transitivePeerDependencies: - bluebird @@ -9718,7 +9697,7 @@ packages: json-parse-even-better-errors: 3.0.0 normalize-package-data: 5.0.0 proc-log: 3.0.0 - semver: 7.6.3 + semver: 7.7.2 transitivePeerDependencies: - bluebird dev: true @@ -9748,6 +9727,12 @@ packages: resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} dev: false + /@opentelemetry/api-logs@0.203.0: + resolution: {integrity: sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==} + engines: {node: '>=8.0.0'} + dependencies: + '@opentelemetry/api': 1.9.0 + /@opentelemetry/api-logs@0.49.1: resolution: {integrity: sha512-kaNl/T7WzyMUQHQlVq7q0oV4Kev6+0xFwqzofryC66jgGMacd0QH5TwfpbUwSTby+SdAdprAe5UKMvBw4tKS5Q==} engines: {node: '>=14'} @@ -9766,6 +9751,7 @@ packages: engines: {node: '>=14'} dependencies: '@opentelemetry/api': 1.9.0 + dev: false /@opentelemetry/api-logs@0.57.0: resolution: {integrity: sha512-l1aJ30CXeauVYaI+btiynHpw341LthkMTv3omi1VJDX14werY2Wmv9n1yudMsq9HuY0m8PvXEVX4d8zxEb+WRg==} @@ -9830,6 +9816,15 @@ packages: '@opentelemetry/api': 1.9.0 dev: false + /@opentelemetry/context-async-hooks@2.0.1(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-XuY23lSI3d4PEqKA+7SLtAgwqIfc6E/E9eAQWLN1vlpC53ybO3o6jW4BsXo1xvz9lYyyWItfQDDLzezER01mCw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + dependencies: + '@opentelemetry/api': 1.9.0 + dev: false + /@opentelemetry/core@1.22.0(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-0VoAlT6x+Xzik1v9goJ3pZ2ppi6+xd3aUfg4brfrLkDBHRIVjMP0eBHrKrhB+NKcDyMAg8fAbGL3Npg/F6AwWA==} engines: {node: '>=14'} @@ -9889,6 +9884,30 @@ packages: '@opentelemetry/semantic-conventions': 1.28.0 dev: false + /@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.36.0 + dev: false + + /@opentelemetry/exporter-logs-otlp-http@0.203.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-s0hys1ljqlMTbXx2XiplmMJg9wG570Z5lH7wMvrZX6lcODI56sG4HL03jklF63tBeyNwK2RV1/ntXGo3HgG4Qw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.203.0 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.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'} @@ -9952,7 +9971,7 @@ packages: peerDependencies: '@opentelemetry/api': ^1.0.0 dependencies: - '@grpc/grpc-js': 1.8.17 + '@grpc/grpc-js': 1.12.6 '@opentelemetry/api': 1.4.1 '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.4.1) '@opentelemetry/otlp-grpc-exporter-base': 0.49.1(@opentelemetry/api@1.4.1) @@ -9967,7 +9986,7 @@ packages: peerDependencies: '@opentelemetry/api': ^1.0.0 dependencies: - '@grpc/grpc-js': 1.8.17 + '@grpc/grpc-js': 1.12.6 '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/otlp-grpc-exporter-base': 0.52.1(@opentelemetry/api@1.9.0) @@ -9976,6 +9995,20 @@ packages: '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) dev: false + /@opentelemetry/exporter-trace-otlp-http@0.203.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-ZDiaswNYo0yq/cy1bBLJFe691izEJ6IgNmkjm4C6kE9ub/OMQqDXORx2D2j8fzTBTxONyzusbaZlqtfmyqURPw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + dev: false + /@opentelemetry/exporter-trace-otlp-http@0.49.1(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-KOLtZfZvIrpGZLVvblKsiVQT7gQUZNKcUUH24Zz6Xbi7LJb9Vt6xtUZFYdR5IIjvt47PIqBKDWUQlU0o1wAsRw==} engines: {node: '>=14'} @@ -10080,7 +10113,7 @@ packages: '@opentelemetry/api': ^1.3.0 dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.36.0 transitivePeerDependencies: @@ -10094,7 +10127,7 @@ packages: '@opentelemetry/api': ^1.3.0 dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.36.0 '@types/connect': 3.4.38 @@ -10123,7 +10156,7 @@ packages: '@opentelemetry/api': 1.4.1 '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.4.1) '@opentelemetry/instrumentation': 0.49.1(@opentelemetry/api@1.4.1) - '@opentelemetry/semantic-conventions': 1.25.1 + '@opentelemetry/semantic-conventions': 1.36.0 transitivePeerDependencies: - supports-color dev: true @@ -10149,13 +10182,28 @@ packages: '@opentelemetry/api': ^1.3.0 dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.36.0 transitivePeerDependencies: - supports-color dev: false + /@opentelemetry/instrumentation-fetch@0.203.0(@opentelemetry/api@1.9.0)(supports-color@10.0.0): + resolution: {integrity: sha512-Z+mls3rOP2BaVykDZLLZPvchjj9l2oj3dYG1GTnrc27Y8o3biE+5M1b0izblycbbQHXjMPHQCpmjHbLMQuWtBg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0)(supports-color@10.0.0) + '@opentelemetry/sdk-trace-web': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.36.0 + transitivePeerDependencies: + - supports-color + dev: false + /@opentelemetry/instrumentation-fetch@0.49.1(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-hizhULZXlq02y8YC0vPQ4WtUWiXcwxPdEqHBy8p75jzF9rAuP/ldrVr0Oxvz5Xr9qQcdEOFLvEl0ZxbVL76WKw==} engines: {node: '>=14'} @@ -10171,21 +10219,6 @@ packages: - supports-color dev: true - /@opentelemetry/instrumentation-fetch@0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0): - resolution: {integrity: sha512-EJDQXdv1ZGyBifox+8BK+hP0tg29abNPdScE+lW77bUVrThD5vn2dOo+blAS3Z8Od+eqTUTDzXVDIFjGgTK01w==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': ^1.0.0 - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0) - '@opentelemetry/sdk-trace-web': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.25.1 - transitivePeerDependencies: - - supports-color - dev: false - /@opentelemetry/instrumentation-fs@0.19.1(@opentelemetry/api@1.9.0): resolution: {integrity: sha512-6g0FhB3B9UobAR60BGTcXg4IHZ6aaYJzp0Ki5FhnxyAPt8Ns+9SSvgcrnsN2eGmk3RWG5vYycUGOEApycQL24A==} engines: {node: '>=14'} @@ -10193,7 +10226,7 @@ packages: '@opentelemetry/api': ^1.3.0 dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color @@ -10230,7 +10263,7 @@ packages: '@opentelemetry/api': ^1.3.0 dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.36.0 transitivePeerDependencies: @@ -10260,7 +10293,7 @@ packages: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.25.1 semver: 7.6.3 transitivePeerDependencies: @@ -10330,7 +10363,7 @@ packages: '@opentelemetry/api': ^1.3.0 dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.36.0 transitivePeerDependencies: @@ -10369,7 +10402,7 @@ packages: '@opentelemetry/api': ^1.3.0 dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.36.0 transitivePeerDependencies: @@ -10456,7 +10489,7 @@ packages: '@opentelemetry/api': ^1.7.0 dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color @@ -10475,6 +10508,20 @@ packages: - supports-color dev: true + /@opentelemetry/instrumentation@0.203.0(@opentelemetry/api@1.9.0)(supports-color@10.0.0): + resolution: {integrity: sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.203.0 + import-in-the-middle: 1.11.0 + require-in-the-middle: 7.1.1(supports-color@10.0.0) + transitivePeerDependencies: + - supports-color + dev: false + /@opentelemetry/instrumentation@0.49.1(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-0DLtWtaIppuNNRRllSD4bjU8ZIiLp1cDXvJEbp752/Zf+y3gaLNaoGRGIlX4UHhcsrmtL+P2qxi3Hodi8VuKiQ==} engines: {node: '>=14'} @@ -10534,10 +10581,10 @@ packages: dependencies: '@opentelemetry/api': 1.4.1 '@opentelemetry/api-logs': 0.51.1 - '@types/shimmer': 1.0.2 + '@types/shimmer': 1.2.0 import-in-the-middle: 1.7.4 require-in-the-middle: 7.1.1(supports-color@10.0.0) - semver: 7.6.3 + semver: 7.7.2 shimmer: 1.2.1 transitivePeerDependencies: - supports-color @@ -10551,16 +10598,16 @@ packages: dependencies: '@opentelemetry/api': 1.4.1 '@opentelemetry/api-logs': 0.52.1 - '@types/shimmer': 1.0.2 + '@types/shimmer': 1.2.0 import-in-the-middle: 1.11.0 require-in-the-middle: 7.1.1(supports-color@10.0.0) - semver: 7.6.3 + semver: 7.7.2 shimmer: 1.2.1 transitivePeerDependencies: - supports-color dev: false - /@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0): + /@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0): resolution: {integrity: sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==} engines: {node: '>=14'} peerDependencies: @@ -10568,10 +10615,10 @@ packages: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/api-logs': 0.52.1 - '@types/shimmer': 1.0.2 + '@types/shimmer': 1.2.0 import-in-the-middle: 1.11.0 require-in-the-middle: 7.1.1(supports-color@10.0.0) - semver: 7.6.3 + semver: 7.7.2 shimmer: 1.2.1 transitivePeerDependencies: - supports-color @@ -10594,6 +10641,17 @@ packages: - supports-color dev: false + /@opentelemetry/otlp-exporter-base@0.203.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) + dev: false + /@opentelemetry/otlp-exporter-base@0.49.1(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-z6sHliPqDgJU45kQatAettY9/eVF58qVPaTuejw9YWfSRqid9pXPYeegDCSdyS47KAUgAtm+nC28K3pfF27HWg==} engines: {node: '>=14'} @@ -10632,7 +10690,7 @@ packages: peerDependencies: '@opentelemetry/api': ^1.0.0 dependencies: - '@grpc/grpc-js': 1.8.17 + '@grpc/grpc-js': 1.12.6 '@opentelemetry/api': 1.4.1 '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.4.1) '@opentelemetry/otlp-exporter-base': 0.49.1(@opentelemetry/api@1.4.1) @@ -10645,7 +10703,7 @@ packages: peerDependencies: '@opentelemetry/api': ^1.0.0 dependencies: - '@grpc/grpc-js': 1.8.17 + '@grpc/grpc-js': 1.12.6 '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/otlp-exporter-base': 0.52.1(@opentelemetry/api@1.9.0) @@ -10664,6 +10722,22 @@ packages: protobufjs: 7.3.2 dev: true + /@opentelemetry/otlp-transformer@0.203.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.203.0 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + protobufjs: 7.3.2 + dev: false + /@opentelemetry/otlp-transformer@0.49.1(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-Z+koA4wp9L9e3jkFacyXTGphSWTbOKjwwXMpb0CxNb0kjTHGUxhYRN8GnkLFsFo5NbZPjP07hwAqeEG/uCratQ==} engines: {node: '>=14'} @@ -10842,7 +10916,30 @@ packages: '@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): + /@opentelemetry/resources@2.0.1(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.36.0 + dev: false + + /@opentelemetry/sdk-logs@0.203.0(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.4.0 <1.10.0' + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.203.0 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) + dev: false + + /@opentelemetry/sdk-logs@0.49.1(@opentelemetry/api-logs@0.203.0)(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-gCzYWsJE0h+3cuh3/cK+9UwlVFyHvj3PReIOCDOmdeXOp90ZjKRoDOJBc3mvk1LL6wyl1RWIivR8Rg9OToyesw==} engines: {node: '>=14'} peerDependencies: @@ -10850,12 +10947,12 @@ packages: '@opentelemetry/api-logs': '>=0.39.1' dependencies: '@opentelemetry/api': 1.4.1 - '@opentelemetry/api-logs': 0.49.1 + '@opentelemetry/api-logs': 0.203.0 '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.4.1) '@opentelemetry/resources': 1.22.0(@opentelemetry/api@1.4.1) dev: true - /@opentelemetry/sdk-logs@0.49.1(@opentelemetry/api-logs@0.52.1)(@opentelemetry/api@1.4.1): + /@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'} peerDependencies: @@ -10863,7 +10960,7 @@ packages: '@opentelemetry/api-logs': '>=0.39.1' dependencies: '@opentelemetry/api': 1.4.1 - '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/api-logs': 0.49.1 '@opentelemetry/core': 1.22.0(@opentelemetry/api@1.4.1) '@opentelemetry/resources': 1.22.0(@opentelemetry/api@1.4.1) dev: true @@ -10927,6 +11024,17 @@ packages: '@opentelemetry/resources': 1.30.0(@opentelemetry/api@1.9.0) dev: false + /@opentelemetry/sdk-metrics@2.0.1(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.9.0 <1.10.0' + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.0.1(@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'} @@ -10951,7 +11059,7 @@ packages: - supports-color dev: true - /@opentelemetry/sdk-node@0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0): + /@opentelemetry/sdk-node@0.52.1(@opentelemetry/api@1.9.0): resolution: {integrity: sha512-uEG+gtEr6eKd8CVWeKMhH2olcCHM9dEK68pe0qE0be32BcCRsvYURhHaD1Srngh1SQcnQzZ4TP324euxqtBOJA==} engines: {node: '>=14'} peerDependencies: @@ -10964,7 +11072,7 @@ packages: '@opentelemetry/exporter-trace-otlp-http': 0.52.1(@opentelemetry/api@1.9.0) '@opentelemetry/exporter-trace-otlp-proto': 0.52.1(@opentelemetry/api@1.9.0) '@opentelemetry/exporter-zipkin': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-logs': 0.52.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.0) @@ -11047,6 +11155,18 @@ packages: '@opentelemetry/semantic-conventions': 1.28.0 dev: false + /@opentelemetry/sdk-trace-base@2.0.1(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.36.0 + dev: false + /@opentelemetry/sdk-trace-node@1.22.0(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-gTGquNz7ue8uMeiWPwp3CU321OstQ84r7PCDtOaCicjbJxzvO8RZMlEC4geOipTeiF88kss5n6w+//A0MhP1lQ==} engines: {node: '>=14'} @@ -11059,7 +11179,7 @@ packages: '@opentelemetry/propagator-b3': 1.22.0(@opentelemetry/api@1.4.1) '@opentelemetry/propagator-jaeger': 1.22.0(@opentelemetry/api@1.4.1) '@opentelemetry/sdk-trace-base': 1.22.0(@opentelemetry/api@1.4.1) - semver: 7.6.3 + semver: 7.7.2 dev: true /@opentelemetry/sdk-trace-node@1.25.1(@opentelemetry/api@1.4.1): @@ -11092,6 +11212,18 @@ packages: semver: 7.6.3 dev: false + /@opentelemetry/sdk-trace-node@2.0.1(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-UhdbPF19pMpBtCWYP5lHbTogLWx9N0EBxtdagvkn5YtsAnCBZzL7SjktG+ZmupRgifsHMjwUaCCaVmqGfSADmA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/context-async-hooks': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + dev: false + /@opentelemetry/sdk-trace-web@1.22.0(@opentelemetry/api@1.4.1): resolution: {integrity: sha512-id5bUhWYg475xbm4hjwWA4PnWM4duNK1EyFRkZxa3BZNuCITwiKCLvDkVhlE9RK2kvuDOPmcRxgSbU1apF9/1w==} engines: {node: '>=14'} @@ -11104,16 +11236,15 @@ packages: '@opentelemetry/semantic-conventions': 1.22.0 dev: true - /@opentelemetry/sdk-trace-web@1.25.1(@opentelemetry/api@1.9.0): - resolution: {integrity: sha512-SS6JaSkHngcBCNdWGthzcvaKGRnDw2AeP57HyTEileLToJ7WLMeV+064iRlVyoT4+e77MRp2T2dDSrmaUyxoNg==} - engines: {node: '>=14'} + /@opentelemetry/sdk-trace-web@2.0.1(@opentelemetry/api@1.9.0): + resolution: {integrity: sha512-R4/i0rISvAujG4Zwk3s6ySyrWG+Db3SerZVM4jZ2lEzjrNylF7nRAy1hVvWe8gTbwIxX+6w6ZvZwdtl2C7UQHQ==} + engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.25.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) dev: false /@opentelemetry/semantic-conventions@1.22.0: @@ -11132,7 +11263,6 @@ packages: /@opentelemetry/semantic-conventions@1.36.0: resolution: {integrity: sha512-TtxJSRD8Ohxp6bKkhrm27JRHAxPczQA7idtcTOMYI+wQRRrfgqxHv1cFbCApcSnNjtXkmzFozn6jQtFrOmbjPQ==} engines: {node: '>=14'} - dev: false /@opentelemetry/sql-common@0.40.1(@opentelemetry/api@1.9.0): resolution: {integrity: sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==} @@ -11141,7 +11271,7 @@ packages: '@opentelemetry/api': ^1.1.0 dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) dev: false /@pkgjs/parseargs@0.11.0: @@ -11330,7 +11460,7 @@ packages: '@opentelemetry/api': ^1.8 dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)(supports-color@10.0.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color dev: false @@ -11427,7 +11557,7 @@ packages: engines: {node: '>=18'} hasBin: true dependencies: - debug: 4.4.1 + debug: 4.4.1(supports-color@10.0.0) extract-zip: 2.0.1 progress: 2.0.3 proxy-agent: 6.5.0 @@ -11444,11 +11574,11 @@ packages: engines: {node: '>=18'} hasBin: true dependencies: - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) extract-zip: 2.0.1 progress: 2.0.3 proxy-agent: 6.4.0 - semver: 7.6.3 + semver: 7.7.2 tar-fs: 3.0.9 unbzip2-stream: 1.4.3 yargs: 17.7.2 @@ -19552,7 +19682,7 @@ packages: dependencies: '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.4.1) '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.4.1) - '@opentelemetry/semantic-conventions': 1.28.0 + '@opentelemetry/semantic-conventions': 1.36.0 '@traceloop/ai-semantic-conventions': 0.10.0 js-tiktoken: 1.0.14 tslib: 2.6.2 @@ -19912,9 +20042,6 @@ packages: resolution: {integrity: sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==} dev: true - /@types/long@4.0.2: - resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} - /@types/marked@4.0.8: resolution: {integrity: sha512-HVNzMT5QlWCOdeuBsgXP8EZzKUf0+AXzN+sLmjvaB3ZlLqO+e4u0uXrdw9ub69wBKFs+c6/pA4r9sy6cCDvImw==} dev: true @@ -20211,7 +20338,6 @@ packages: /@types/shimmer@1.2.0: resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==} - dev: false /@types/simple-oauth2@5.0.4: resolution: {integrity: sha512-4SvTfmAa1fGUa1d07j9vIiC4o92bGh0ihPXmtS05udMMmNwVIaU2nZ706cC4wI8cJxOlHD4P/d5tzqvWYd+KxA==} @@ -20419,7 +20545,7 @@ packages: '@typescript-eslint/scope-manager': 5.59.6 '@typescript-eslint/types': 5.59.6 '@typescript-eslint/typescript-estree': 5.59.6(typescript@5.5.4) - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 eslint: 8.31.0 typescript: 5.5.4 transitivePeerDependencies: @@ -20446,7 +20572,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 5.59.6(typescript@5.5.4) '@typescript-eslint/utils': 5.59.6(eslint@8.31.0)(typescript@5.5.4) - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 eslint: 8.31.0 tsutils: 3.21.0(typescript@5.5.4) typescript: 5.5.4 @@ -20470,10 +20596,10 @@ packages: dependencies: '@typescript-eslint/types': 5.59.6 '@typescript-eslint/visitor-keys': 5.59.6 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.6.3 + semver: 7.7.2 tsutils: 3.21.0(typescript@5.5.4) typescript: 5.5.4 transitivePeerDependencies: @@ -20494,7 +20620,7 @@ packages: '@typescript-eslint/typescript-estree': 5.59.6(typescript@5.5.4) eslint: 8.31.0 eslint-scope: 5.1.1 - semver: 7.6.3 + semver: 7.7.2 transitivePeerDependencies: - supports-color - typescript @@ -20676,6 +20802,27 @@ packages: resolution: {integrity: sha512-17kVyLq3ePTKOkveHxXuIJZtGYs+cSoev7BlP+Lf4916qfDhk/HBjvlYDe8egrea7LNPHKwSZJK/bzZC+Q6AwQ==} dev: true + /@vercel/otel@1.13.0(@opentelemetry/api-logs@0.203.0)(@opentelemetry/api@1.9.0)(@opentelemetry/instrumentation@0.203.0)(@opentelemetry/resources@1.25.1)(@opentelemetry/sdk-logs@0.203.0)(@opentelemetry/sdk-metrics@1.25.1)(@opentelemetry/sdk-trace-base@1.25.1): + resolution: {integrity: sha512-esRkt470Y2jRK1B1g7S1vkt4Csu44gp83Zpu8rIyPoqy2BKgk4z7ik1uSMswzi45UogLHFl6yR5TauDurBQi4Q==} + engines: {node: '>=18'} + peerDependencies: + '@opentelemetry/api': '>=1.7.0 <2.0.0' + '@opentelemetry/api-logs': '>=0.46.0 <0.200.0' + '@opentelemetry/instrumentation': '>=0.46.0 <0.200.0' + '@opentelemetry/resources': '>=1.19.0 <2.0.0' + '@opentelemetry/sdk-logs': '>=0.46.0 <0.200.0' + '@opentelemetry/sdk-metrics': '>=1.19.0 <2.0.0' + '@opentelemetry/sdk-trace-base': '>=1.19.0 <2.0.0' + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.203.0 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0)(supports-color@10.0.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) + dev: false + /@vercel/postgres@0.10.0: resolution: {integrity: sha512-fSD23DxGND40IzSkXjcFcxr53t3Tiym59Is0jSYIFpG4/0f0KO9SGtcp1sXiebvPaGe7N/tU05cH4yt2S6/IPg==} engines: {node: '>=18.14'} @@ -20698,7 +20845,7 @@ packages: dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 @@ -21179,20 +21326,12 @@ packages: negotiator: 1.0.0 dev: false - /acorn-import-assertions@1.9.0(acorn@8.12.1): - resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} - peerDependencies: - acorn: ^8 - dependencies: - acorn: 8.12.1 - /acorn-import-assertions@1.9.0(acorn@8.14.1): resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} peerDependencies: acorn: ^8 dependencies: acorn: 8.14.1 - dev: false /acorn-import-attributes@1.9.5(acorn@8.12.1): resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} @@ -21222,7 +21361,6 @@ packages: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: acorn: 8.14.1 - dev: true /acorn-node@1.8.2: resolution: {integrity: sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==} @@ -21276,7 +21414,7 @@ packages: engines: {node: '>= 6.0.0'} requiresBuild: true dependencies: - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) transitivePeerDependencies: - supports-color @@ -21284,7 +21422,7 @@ packages: resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} engines: {node: '>= 14'} dependencies: - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) transitivePeerDependencies: - supports-color @@ -22216,7 +22354,7 @@ packages: dependencies: bytes: 3.1.2 content-type: 1.0.5 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) http-errors: 2.0.0 iconv-lite: 0.6.3 on-finished: 2.4.1 @@ -22577,7 +22715,7 @@ packages: /capnp-ts@0.7.0: resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==} dependencies: - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -23691,7 +23829,7 @@ packages: ms: 2.1.3 supports-color: 10.0.0 - /debug@4.4.0(supports-color@10.0.0): + /debug@4.4.0: resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} peerDependencies: @@ -23701,9 +23839,8 @@ packages: optional: true dependencies: ms: 2.1.3 - supports-color: 10.0.0 - /debug@4.4.1: + /debug@4.4.1(supports-color@10.0.0): resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} peerDependencies: @@ -23713,7 +23850,7 @@ packages: optional: true dependencies: ms: 2.1.3 - dev: false + supports-color: 10.0.0 /decamelize-keys@1.1.1: resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} @@ -23977,7 +24114,7 @@ packages: resolution: {integrity: sha512-ens7BiayssQz/uAxGzH8zGXCtiV24rRWXdjNha5V4zSOcxmAZsfGVm/PPFbwQdqEkDnhG+SyR9E3zSHUbOKXBQ==} engines: {node: '>= 8.0'} dependencies: - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 readable-stream: 3.6.0 split-ca: 1.0.1 ssh2: 1.16.0 @@ -25030,7 +25167,7 @@ packages: eslint: '*' eslint-plugin-import: '*' dependencies: - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 enhanced-resolve: 5.15.0 eslint: 8.31.0 eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.59.6)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.31.0) @@ -25399,8 +25536,8 @@ packages: resolution: {integrity: sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) eslint-visitor-keys: 3.4.2 /esprima@4.0.1: @@ -25727,7 +25864,7 @@ packages: engines: {node: '>= 10.17.0'} hasBin: true dependencies: - debug: 4.4.1 + debug: 4.4.1(supports-color@10.0.0) get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -25998,7 +26135,7 @@ packages: resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} engines: {node: '>= 0.8'} dependencies: - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -26479,7 +26616,7 @@ packages: dependencies: basic-ftp: 5.0.3 data-uri-to-buffer: 5.0.1 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) fs-extra: 8.1.0 transitivePeerDependencies: - supports-color @@ -26709,9 +26846,9 @@ packages: '@types/node': 20.14.14 '@types/semver': 7.5.1 chalk: 4.1.2 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 interpret: 3.1.1 - semver: 7.6.3 + semver: 7.7.2 tslib: 2.6.2 yargs: 17.7.2 transitivePeerDependencies: @@ -27008,7 +27145,7 @@ packages: dependencies: '@tootallnate/once': 1.1.2 agent-base: 6.0.2 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) transitivePeerDependencies: - supports-color dev: false @@ -27019,7 +27156,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.1 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) transitivePeerDependencies: - supports-color @@ -27028,7 +27165,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.4 - debug: 4.4.1 + debug: 4.4.1(supports-color@10.0.0) transitivePeerDependencies: - supports-color dev: false @@ -27047,7 +27184,7 @@ packages: engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 transitivePeerDependencies: - supports-color @@ -27056,7 +27193,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.1 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) transitivePeerDependencies: - supports-color dev: true @@ -27066,7 +27203,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.1 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) transitivePeerDependencies: - supports-color dev: false @@ -27076,7 +27213,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.4 - debug: 4.4.1 + debug: 4.4.1(supports-color@10.0.0) transitivePeerDependencies: - supports-color dev: false @@ -27180,8 +27317,8 @@ packages: /import-in-the-middle@1.7.1: resolution: {integrity: sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==} dependencies: - acorn: 8.12.1 - acorn-import-assertions: 1.9.0(acorn@8.12.1) + acorn: 8.14.1 + acorn-import-assertions: 1.9.0(acorn@8.14.1) cjs-module-lexer: 1.2.3 module-details-from-path: 1.0.3 @@ -27770,7 +27907,7 @@ packages: engines: {node: '>=10'} dependencies: '@jridgewell/trace-mapping': 0.3.25 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -28522,9 +28659,6 @@ packages: chalk: 4.1.2 is-unicode-supported: 0.1.0 - /long@4.0.0: - resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} - /long@5.2.3: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} @@ -29500,7 +29634,7 @@ packages: resolution: {integrity: sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA==} dependencies: '@types/debug': 4.1.12 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) decode-named-character-reference: 1.0.2 micromark-core-commonmark: 1.0.6 micromark-factory-space: 1.0.0 @@ -29524,7 +29658,7 @@ packages: resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} dependencies: '@types/debug': 4.1.12 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 @@ -29621,7 +29755,7 @@ packages: hasBin: true dependencies: '@cspotcode/source-map-support': 0.8.1 - acorn: 8.12.1 + acorn: 8.14.1 acorn-walk: 8.3.2 capnp-ts: 0.7.0 exit-hook: 2.2.1 @@ -30397,7 +30531,7 @@ packages: nopt: 5.0.0 npmlog: 6.0.2 rimraf: 3.0.2 - semver: 7.6.3 + semver: 7.7.2 tar: 6.2.1 which: 2.0.2 transitivePeerDependencies: @@ -30458,7 +30592,7 @@ packages: dependencies: hosted-git-info: 6.1.1 is-core-module: 2.14.0 - semver: 7.6.3 + semver: 7.7.2 validate-npm-package-license: 3.0.4 dev: true @@ -31134,7 +31268,7 @@ packages: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.1 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) get-uri: 6.0.1 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.5 @@ -31150,7 +31284,7 @@ packages: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.4 - debug: 4.4.1 + debug: 4.4.1(supports-color@10.0.0) get-uri: 6.0.1 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 @@ -32357,7 +32491,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.1 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.5 lru-cache: 7.18.3 @@ -32373,7 +32507,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.4 - debug: 4.4.1 + debug: 4.4.1(supports-color@10.0.0) http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 lru-cache: 7.18.3 @@ -32435,7 +32569,7 @@ packages: dependencies: '@puppeteer/browsers': 2.4.0 chromium-bidi: 0.6.5(devtools-protocol@0.0.1342118) - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) devtools-protocol: 0.0.1342118 typed-query-selector: 2.12.0 ws: 8.18.0(bufferutil@4.0.9) @@ -32452,7 +32586,7 @@ packages: dependencies: '@puppeteer/browsers': 2.10.6 chromium-bidi: 7.2.0(devtools-protocol@0.0.1464554) - debug: 4.4.1 + debug: 4.4.1(supports-color@10.0.0) devtools-protocol: 0.0.1464554 typed-query-selector: 2.12.0 ws: 8.18.3 @@ -33546,7 +33680,7 @@ packages: remix-auth: ^3.6.0 dependencies: '@remix-run/server-runtime': 2.1.0(typescript@5.5.4) - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 remix-auth: 3.6.0(@remix-run/react@2.1.0)(@remix-run/server-runtime@2.1.0) transitivePeerDependencies: - supports-color @@ -33673,7 +33807,7 @@ packages: resolution: {integrity: sha512-OScOjQjrrjhAdFpQmnkE/qbIBGCRFhQB/YaJhcC3CPOlmhe7llnW46Ac1J5+EjcNXOTnDdpF96Erw/yedsGksQ==} engines: {node: '>=8.6.0'} dependencies: - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) module-details-from-path: 1.0.3 resolve: 1.22.8 transitivePeerDependencies: @@ -34131,7 +34265,7 @@ packages: resolution: {integrity: sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA==} engines: {node: '>= 18'} dependencies: - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) destroy: 1.2.0 encodeurl: 2.0.0 escape-html: 1.0.3 @@ -34237,7 +34371,7 @@ packages: dependencies: color: 4.2.3 detect-libc: 2.0.3 - semver: 7.6.3 + semver: 7.7.2 optionalDependencies: '@img/sharp-darwin-arm64': 0.33.5 '@img/sharp-darwin-x64': 0.33.5 @@ -34584,7 +34718,7 @@ packages: requiresBuild: true dependencies: agent-base: 6.0.2 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -34596,7 +34730,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.1 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -34607,7 +34741,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.4 - debug: 4.4.1 + debug: 4.4.1(supports-color@10.0.0) socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -35198,7 +35332,7 @@ packages: dependencies: component-emitter: 1.3.1 cookiejar: 2.1.4 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 fast-safe-stringify: 2.1.1 form-data: 4.0.4 formidable: 3.5.1 @@ -35748,7 +35882,7 @@ packages: archiver: 7.0.1 async-lock: 1.4.1 byline: 5.0.0 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 docker-compose: 0.24.8 dockerode: 4.0.6 get-port: 7.1.0 @@ -36259,7 +36393,7 @@ packages: cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 esbuild: 0.25.1 joycon: 3.1.1 picocolors: 1.1.1 @@ -36904,7 +37038,7 @@ packages: /unplugin@1.0.1: resolution: {integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==} dependencies: - acorn: 8.12.1 + acorn: 8.14.1 chokidar: 3.6.0 webpack-sources: 3.2.3 webpack-virtual-modules: 0.5.0 @@ -37288,7 +37422,7 @@ packages: hasBin: true dependencies: cac: 6.7.14 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) mlly: 1.7.1 pathe: 1.1.2 picocolors: 1.1.1 @@ -37312,7 +37446,7 @@ packages: hasBin: true dependencies: cac: 6.7.14 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.1(supports-color@10.0.0) es-module-lexer: 1.7.0 pathe: 2.0.3 vite: 5.2.7(@types/node@20.14.14) @@ -37481,7 +37615,7 @@ packages: '@vitest/spy': 3.1.4 '@vitest/utils': 3.1.4 chai: 5.2.0 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 expect-type: 1.2.1 magic-string: 0.30.17 pathe: 2.0.3 @@ -37588,7 +37722,7 @@ packages: hasBin: true dependencies: '@discoveryjs/json-ext': 0.5.7 - acorn: 8.12.1 + acorn: 8.14.1 acorn-walk: 8.3.2 commander: 7.2.0 debounce: 1.2.1 diff --git a/references/d3-chat/package.json b/references/d3-chat/package.json index 36dc313f2b..2d14a1d22e 100644 --- a/references/d3-chat/package.json +++ b/references/d3-chat/package.json @@ -22,13 +22,18 @@ "@ai-sdk/anthropic": "^1.2.4", "@ai-sdk/openai": "1.3.3", "@e2b/code-interpreter": "^1.1.0", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/api-logs": "^0.203.0", + "@opentelemetry/exporter-logs-otlp-http": "0.203.0", + "@opentelemetry/exporter-trace-otlp-http": "0.203.0", + "@opentelemetry/instrumentation": "^0.203.0", + "@opentelemetry/sdk-logs": "^0.203.0", "@radix-ui/react-avatar": "^1.1.3", "@slack/web-api": "7.9.1", "@trigger.dev/python": "workspace:*", "@trigger.dev/react-hooks": "workspace:*", "@trigger.dev/sdk": "workspace:*", - "@opentelemetry/exporter-logs-otlp-http": "0.52.1", - "@opentelemetry/exporter-trace-otlp-http": "0.52.1", + "@vercel/otel": "^1.13.0", "@vercel/postgres": "^0.10.0", "ai": "4.2.5", "class-variance-authority": "^0.7.1", diff --git a/references/d3-chat/src/app/api/demo-batch-trigger/route.ts b/references/d3-chat/src/app/api/demo-batch-trigger/route.ts new file mode 100644 index 0000000000..9342830c32 --- /dev/null +++ b/references/d3-chat/src/app/api/demo-batch-trigger/route.ts @@ -0,0 +1,18 @@ +import { NextResponse } from "next/server"; +import { tasks } from "@trigger.dev/sdk"; +import type { todoChat } from "@/trigger/chat"; + +export async function POST(request: Request) { + const body = await request.json(); + + const handle = await tasks.batchTrigger("todo-chat", [ + { + payload: { + input: body.input, + userId: "123", + }, + }, + ]); + + return NextResponse.json({ handle }); +} diff --git a/references/d3-chat/src/app/api/demo-call-from-trigger/route.ts b/references/d3-chat/src/app/api/demo-call-from-trigger/route.ts new file mode 100644 index 0000000000..940c844d06 --- /dev/null +++ b/references/d3-chat/src/app/api/demo-call-from-trigger/route.ts @@ -0,0 +1,5 @@ +import { NextResponse } from "next/server"; + +export async function POST(request: Request) { + return NextResponse.json({ body: "Hello, world!" }); +} diff --git a/references/d3-chat/src/app/api/demo-trigger/route.ts b/references/d3-chat/src/app/api/demo-trigger/route.ts new file mode 100644 index 0000000000..f97874f262 --- /dev/null +++ b/references/d3-chat/src/app/api/demo-trigger/route.ts @@ -0,0 +1,14 @@ +import { NextResponse } from "next/server"; +import { tasks } from "@trigger.dev/sdk"; +import type { todoChat } from "@/trigger/chat"; + +export async function POST(request: Request) { + const body = await request.json(); + + const handle = await tasks.trigger("todo-chat", { + input: body.input, + userId: "123", + }); + + return NextResponse.json({ handle }); +} diff --git a/references/d3-chat/src/instrumentation.ts b/references/d3-chat/src/instrumentation.ts new file mode 100644 index 0000000000..ad3e547447 --- /dev/null +++ b/references/d3-chat/src/instrumentation.ts @@ -0,0 +1,5 @@ +import { registerOTel } from "@vercel/otel"; + +export function register() { + registerOTel({ serviceName: "d3-chat" }); +} diff --git a/references/d3-chat/src/trigger/chat.ts b/references/d3-chat/src/trigger/chat.ts index 7ac4d77f67..9870cbc17d 100644 --- a/references/d3-chat/src/trigger/chat.ts +++ b/references/d3-chat/src/trigger/chat.ts @@ -1,7 +1,7 @@ import { anthropic } from "@ai-sdk/anthropic"; import { openai } from "@ai-sdk/openai"; import { ai } from "@trigger.dev/sdk/ai"; -import { logger, metadata, runs, schemaTask, tasks, wait } from "@trigger.dev/sdk/v3"; +import { logger, metadata, runs, schemaTask, tasks, wait, otel } from "@trigger.dev/sdk/v3"; import { sql } from "@vercel/postgres"; import { CoreMessage, @@ -17,6 +17,25 @@ import { sendSQLApprovalMessage } from "../lib/slack"; import { crawler } from "./crawler"; import { chartTool } from "./sandbox"; import { QueryApproval } from "./schemas"; +import { context, propagation } from "@opentelemetry/api"; + +async function callNextjsApp() { + return await otel.withExternalTrace(async () => { + const headersObject = {}; + + propagation.inject(context.active(), headersObject); + + const result = await fetch("http://localhost:3000/api/demo-call-from-trigger", { + headers: new Headers(headersObject), + method: "POST", + body: JSON.stringify({ + message: "Hello from Trigger.dev", + }), + }); + + return result.json(); + }); +} const queryApprovalTask = schemaTask({ id: "query-approval", @@ -29,6 +48,8 @@ const queryApprovalTask = schemaTask({ run: async ({ userId, input, query }) => { logger.info("queryApproval: starting", { projectRef: process.env.TRIGGER_PROJECT_REF }); + await callNextjsApp(); + const token = await wait.createToken({ tags: [`user:${userId}`, "approval"], timeout: "5m", // timeout in 5 minutes @@ -129,6 +150,8 @@ export const todoChat = schemaTask({ run: async ({ input, userId }, { signal }) => { metadata.set("user_id", userId); + logger.info("todoChat: starting", { input, userId }); + const system = ` You are a SQL (postgres) expert who can turn natural language descriptions for a todo app into a SQL query which can then be executed against a SQL database. Here is the schema: