Răsfoiți Sursa

fix(cli): keep OTLP failures best effort (#41479)

Luke Parker 6 zile în urmă
părinte
comite
d97aca139f
2 a modificat fișierele cu 23 adăugiri și 12 ștergeri
  1. 1 1
      packages/util/src/observability.ts
  2. 22 11
      packages/util/src/observability/otlp.ts

+ 1 - 1
packages/util/src/observability.ts

@@ -45,7 +45,7 @@ export function layer(
         Layer.orDie,
         Layer.merge(Layer.succeed(References.MinimumLogLevel, Logging.minimumLogLevel())),
       )
-      return Layer.merge(logs, yield* Effect.promise(() => Otlp.tracingLayer(options, app)))
+      return Layer.merge(logs, yield* Otlp.tracingLayer(options, app))
     }),
   ).pipe(Layer.catchCause(() => local))
 }

+ 22 - 11
packages/util/src/observability/otlp.ts

@@ -1,4 +1,4 @@
-import { Layer } from "effect"
+import { Effect, Layer, Scope } from "effect"
 import { OtlpLogger } from "effect/unstable/observability"
 import { runID } from "./shared.js"
 
@@ -71,28 +71,39 @@ export function loggers(options: Options | undefined, app: App) {
   ]
 }
 
-export async function tracingLayer(options: Options | undefined, app: App) {
+export const tracingLayer = Effect.fnUntraced(function* (options: Options | undefined, app: App) {
   if (!options?.endpoint) return Layer.empty
-  const NodeSdk = await import("@effect/opentelemetry/NodeSdk")
-  const OTLP = await import("@opentelemetry/exporter-trace-otlp-http")
-  const SdkBase = await import("@opentelemetry/sdk-trace-base")
-  const { AsyncLocalStorageContextManager } = await import("@opentelemetry/context-async-hooks")
-  const { context } = await import("@opentelemetry/api")
+  const [{ layer }, { OTLPTraceExporter }, { BatchSpanProcessor }, { AsyncLocalStorageContextManager }, { context }] =
+    yield* Effect.all(
+      [
+        Effect.promise(() => import("@effect/opentelemetry/NodeSdk")),
+        Effect.promise(() => import("@opentelemetry/exporter-trace-otlp-http")),
+        Effect.promise(() => import("@opentelemetry/sdk-trace-base")),
+        Effect.promise(() => import("@opentelemetry/context-async-hooks")),
+        Effect.promise(() => import("@opentelemetry/api")),
+      ],
+      { concurrency: "unbounded" },
+    )
 
   // The Effect Node SDK does not register a global context manager, but the AI SDK uses it to parent spans.
   const manager = new AsyncLocalStorageContextManager()
   manager.enable()
   context.setGlobalContextManager(manager)
 
-  return NodeSdk.layer(() => ({
+  const tracing = layer(() => ({
     resource: resource(app),
-    spanProcessor: new SdkBase.BatchSpanProcessor(
-      new OTLP.OTLPTraceExporter({
+    spanProcessor: new BatchSpanProcessor(
+      new OTLPTraceExporter({
         url: `${options.endpoint}/v1/traces`,
         headers: parseHeaders(options.headers),
       }),
     ),
   }))
-}
+  return Layer.effectContext(
+    Effect.acquireRelease(Scope.make(), (scope, exit) =>
+      Scope.close(scope, exit).pipe(Effect.ignoreCause),
+    ).pipe(Effect.flatMap((scope) => Layer.buildWithScope(tracing, scope))),
+  )
+})
 
 export * as Otlp from "./otlp.js"