refactor: centralize client identity (#38148)

This commit is contained in:
Dax 2026-07-21 14:01:04 -04:00 committed by GitHub
commit 9c38358197
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 102 additions and 94 deletions

View file

@ -0,0 +1,14 @@
export * as Client from "./client.js"
import { Context, Layer } from "effect"
import { makeGlobalNode } from "./effect/app-node.js"
export const Name = Context.Reference<string>("@opencode/Client/Name", {
defaultValue: () => "cli",
})
export const layer = (name = "cli") => Layer.succeed(Name, name)
export const configured = (name?: string) => makeGlobalNode({ service: Name, layer: layer(name), deps: [] })
export const node = configured()

View file

@ -7,11 +7,11 @@ import { FetchHttpClient } from "effect/unstable/http"
import { OtlpSerialization } from "effect/unstable/observability"
import { Logging } from "./observability/logging.js"
import { Otlp } from "./observability/otlp.js"
import { Client } from "./client.js"
export const Options = Schema.Struct({
endpoint: Schema.optional(Schema.String),
headers: Schema.optional(Schema.String),
client: Schema.optional(Schema.String),
})
export type Options = typeof Options.Type
@ -19,7 +19,6 @@ export function layer(
options: Options = {
endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
headers: process.env.OTEL_EXPORTER_OTLP_HEADERS,
client: process.env.OPENCODE_CLIENT ?? "cli",
},
) {
const local = Logger.layer(Logging.loggers(), { mergeWithExisting: false }).pipe(
@ -29,14 +28,17 @@ export function layer(
)
return Layer.unwrap(
Effect.gen(function* () {
const logs = Logger.layer([...Logging.loggers(), ...Otlp.loggers(options)], { mergeWithExisting: false }).pipe(
const client = yield* Client.Name
const logs = Logger.layer([...Logging.loggers(), ...Otlp.loggers(options, client)], {
mergeWithExisting: false,
}).pipe(
Layer.provide(NodeFileSystem.layer),
Layer.provide(OtlpSerialization.layerJson),
Layer.provide(FetchHttpClient.layer),
Layer.orDie,
Layer.merge(Layer.succeed(References.MinimumLogLevel, Logging.minimumLogLevel())),
)
return Layer.merge(logs, yield* Effect.promise(() => Otlp.tracingLayer(options)))
return Layer.merge(logs, yield* Effect.promise(() => Otlp.tracingLayer(options, client)))
}),
).pipe(Layer.catchCause(() => local))
}

View file

@ -6,19 +6,18 @@ import { runID } from "./shared.js"
export interface Options {
readonly endpoint?: string
readonly headers?: string
readonly client?: string
}
function parseHeaders(value?: string) {
return value
? value.split(",").reduce(
(acc, entry) => {
const [key, ...value] = entry.split("=")
acc[key] = value.join("=")
return acc
},
{} as Record<string, string>,
)
(acc, entry) => {
const [key, ...value] = entry.split("=")
acc[key] = value.join("=")
return acc
},
{} as Record<string, string>,
)
: undefined
}
@ -38,7 +37,11 @@ function resourceAttributes() {
}
}
export function resource(client = "cli"): { serviceName: string; serviceVersion: string; attributes: Record<string, string> } {
export function resource(client = "cli"): {
serviceName: string
serviceVersion: string
attributes: Record<string, string>
} {
return {
serviceName: "opencode",
serviceVersion: InstallationVersion,
@ -52,18 +55,18 @@ export function resource(client = "cli"): { serviceName: string; serviceVersion:
}
}
export function loggers(options?: Options) {
export function loggers(options: Options | undefined, client: string) {
if (!options?.endpoint) return []
return [
OtlpLogger.make({
url: `${options.endpoint}/v1/logs`,
resource: resource(options.client),
resource: resource(client),
headers: parseHeaders(options.headers),
}),
]
}
export async function tracingLayer(options?: Options) {
export async function tracingLayer(options: Options | undefined, client: string) {
if (!options?.endpoint) return Layer.empty
const NodeSdk = await import("@effect/opentelemetry/NodeSdk")
const OTLP = await import("@opentelemetry/exporter-trace-otlp-http")
@ -77,7 +80,7 @@ export async function tracingLayer(options?: Options) {
context.setGlobalContextManager(manager)
return NodeSdk.layer(() => ({
resource: resource(options.client),
resource: resource(client),
spanProcessor: new SdkBase.BatchSpanProcessor(
new OTLP.OTLPTraceExporter({
url: `${options.endpoint}/v1/traces`,