Переглянути джерело

feat(opencode): add OTLP observability support (#21387)

Dax 1 тиждень тому
батько
коміт
c90fc6a486

+ 34 - 0
packages/opencode/src/effect/oltp.ts

@@ -0,0 +1,34 @@
+import { Layer } from "effect"
+import { FetchHttpClient } from "effect/unstable/http"
+import { Otlp } from "effect/unstable/observability"
+import { Flag } from "@/flag/flag"
+import { CHANNEL, VERSION } from "@/installation/meta"
+
+export namespace Observability {
+  export const enabled = !!Flag.OTEL_EXPORTER_OTLP_ENDPOINT
+
+  export const layer = !Flag.OTEL_EXPORTER_OTLP_ENDPOINT
+    ? Layer.empty
+    : Otlp.layerJson({
+        baseUrl: Flag.OTEL_EXPORTER_OTLP_ENDPOINT,
+        loggerMergeWithExisting: false,
+        resource: {
+          serviceName: "opencode",
+          serviceVersion: VERSION,
+          attributes: {
+            "deployment.environment.name": CHANNEL === "local" ? "local" : CHANNEL,
+            "opencode.client": Flag.OPENCODE_CLIENT,
+          },
+        },
+        headers: Flag.OTEL_EXPORTER_OTLP_HEADERS
+          ? Flag.OTEL_EXPORTER_OTLP_HEADERS.split(",").reduce(
+              (acc, x) => {
+                const [key, value] = x.split("=")
+                acc[key] = value
+                return acc
+              },
+              {} as Record<string, string>,
+            )
+          : undefined,
+      }).pipe(Layer.provide(FetchHttpClient.layer))
+}

+ 2 - 1
packages/opencode/src/effect/run-service.ts

@@ -3,6 +3,7 @@ import * as ServiceMap from "effect/ServiceMap"
 import { Instance } from "@/project/instance"
 import { Context } from "@/util/context"
 import { InstanceRef } from "./instance-ref"
+import { Observability } from "./oltp"
 
 export const memoMap = Layer.makeMemoMapUnsafe()
 
@@ -18,7 +19,7 @@ function attach<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>
 
 export function makeRuntime<I, S, E>(service: ServiceMap.Service<I, S>, layer: Layer.Layer<I, E>) {
   let rt: ManagedRuntime.ManagedRuntime<I, E> | undefined
-  const getRuntime = () => (rt ??= ManagedRuntime.make(layer, { memoMap }))
+  const getRuntime = () => (rt ??= ManagedRuntime.make(Layer.merge(layer, Observability.layer), { memoMap }))
 
   return {
     runSync: <A, Err>(fn: (svc: S) => Effect.Effect<A, Err, I>) => getRuntime().runSync(attach(service.use(fn))),

+ 3 - 0
packages/opencode/src/flag/flag.ts

@@ -11,6 +11,9 @@ function falsy(key: string) {
 }
 
 export namespace Flag {
+  export const OTEL_EXPORTER_OTLP_ENDPOINT = process.env["OTEL_EXPORTER_OTLP_ENDPOINT"]
+  export const OTEL_EXPORTER_OTLP_HEADERS = process.env["OTEL_EXPORTER_OTLP_HEADERS"]
+
   export const OPENCODE_AUTO_SHARE = truthy("OPENCODE_AUTO_SHARE")
   export const OPENCODE_AUTO_HEAP_SNAPSHOT = truthy("OPENCODE_AUTO_HEAP_SNAPSHOT")
   export const OPENCODE_GIT_BASH_PATH = process.env["OPENCODE_GIT_BASH_PATH"]