chore: merge v2 into service channel config
This commit is contained in:
commit
e76b29c0b4
1174 changed files with 21121 additions and 336917 deletions
|
|
@ -5,7 +5,7 @@ import { Observability } from "../observability"
|
|||
export function makeRuntime<I, S, E>(service: Context.Service<I, S>, layer: Layer.Layer<I, E>) {
|
||||
let rt: ManagedRuntime.ManagedRuntime<I, E> | undefined
|
||||
const getRuntime = () =>
|
||||
(rt ??= ManagedRuntime.make(Layer.provideMerge(layer, Observability.layer) as Layer.Layer<I, E>, {
|
||||
(rt ??= ManagedRuntime.make(Layer.provideMerge(layer, Observability.layer()) as Layer.Layer<I, E>, {
|
||||
memoMap,
|
||||
}))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
import { Config } from "effect"
|
||||
|
||||
export function truthy(key: string) {
|
||||
const value = process.env[key]?.toLowerCase()
|
||||
return value === "true" || value === "1"
|
||||
}
|
||||
|
||||
const copy = process.env["OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT"]
|
||||
const fff = process.env["OPENCODE_DISABLE_FFF"]
|
||||
|
||||
function enabledByExperimental(key: string) {
|
||||
return process.env[key] === undefined ? truthy("OPENCODE_EXPERIMENTAL") : truthy(key)
|
||||
}
|
||||
|
||||
export const Flag = {
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: process.env["OTEL_EXPORTER_OTLP_ENDPOINT"],
|
||||
OTEL_EXPORTER_OTLP_HEADERS: process.env["OTEL_EXPORTER_OTLP_HEADERS"],
|
||||
|
||||
OPENCODE_AUTO_HEAP_SNAPSHOT: truthy("OPENCODE_AUTO_HEAP_SNAPSHOT"),
|
||||
OPENCODE_GIT_BASH_PATH: process.env["OPENCODE_GIT_BASH_PATH"],
|
||||
OPENCODE_CONFIG: process.env["OPENCODE_CONFIG"],
|
||||
OPENCODE_CONFIG_CONTENT: process.env["OPENCODE_CONFIG_CONTENT"],
|
||||
OPENCODE_DISABLE_AUTOUPDATE: truthy("OPENCODE_DISABLE_AUTOUPDATE"),
|
||||
OPENCODE_ALWAYS_NOTIFY_UPDATE: truthy("OPENCODE_ALWAYS_NOTIFY_UPDATE"),
|
||||
OPENCODE_DISABLE_PRUNE: truthy("OPENCODE_DISABLE_PRUNE"),
|
||||
OPENCODE_DISABLE_TERMINAL_TITLE: truthy("OPENCODE_DISABLE_TERMINAL_TITLE"),
|
||||
OPENCODE_SHOW_TTFD: truthy("OPENCODE_SHOW_TTFD"),
|
||||
OPENCODE_DISABLE_AUTOCOMPACT: truthy("OPENCODE_DISABLE_AUTOCOMPACT"),
|
||||
OPENCODE_DISABLE_MODELS_FETCH: truthy("OPENCODE_DISABLE_MODELS_FETCH"),
|
||||
OPENCODE_DISABLE_MOUSE: truthy("OPENCODE_DISABLE_MOUSE"),
|
||||
OPENCODE_FAKE_VCS: process.env["OPENCODE_FAKE_VCS"],
|
||||
OPENCODE_SERVER_PASSWORD: process.env["OPENCODE_SERVER_PASSWORD"],
|
||||
OPENCODE_SERVER_USERNAME: process.env["OPENCODE_SERVER_USERNAME"],
|
||||
OPENCODE_DISABLE_FFF: fff === undefined ? process.platform === "win32" : truthy("OPENCODE_DISABLE_FFF"),
|
||||
OPENCODE_DISABLE_FILEWATCHER: truthy("OPENCODE_DISABLE_FILEWATCHER"),
|
||||
|
||||
// Experimental
|
||||
OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT:
|
||||
copy === undefined ? process.platform === "win32" : truthy("OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT"),
|
||||
OPENCODE_MODELS_URL: process.env["OPENCODE_MODELS_URL"],
|
||||
OPENCODE_MODELS_PATH: process.env["OPENCODE_MODELS_PATH"],
|
||||
OPENCODE_DB: process.env["OPENCODE_DB"],
|
||||
|
||||
OPENCODE_WORKSPACE_ID: process.env["OPENCODE_WORKSPACE_ID"],
|
||||
OPENCODE_EXPERIMENTAL_WORKSPACES: enabledByExperimental("OPENCODE_EXPERIMENTAL_WORKSPACES"),
|
||||
|
||||
// Evaluated at access time (not module load) because tests, the CLI, and
|
||||
// external tooling set these env vars at runtime.
|
||||
get OPENCODE_DISABLE_PROJECT_CONFIG() {
|
||||
return truthy("OPENCODE_DISABLE_PROJECT_CONFIG")
|
||||
},
|
||||
get OPENCODE_EXPERIMENTAL_REFERENCES() {
|
||||
return enabledByExperimental("OPENCODE_EXPERIMENTAL_REFERENCES")
|
||||
},
|
||||
get OPENCODE_TUI_CONFIG() {
|
||||
return process.env["OPENCODE_TUI_CONFIG"]
|
||||
},
|
||||
get OPENCODE_CONFIG_DIR() {
|
||||
return process.env["OPENCODE_CONFIG_DIR"]
|
||||
},
|
||||
get OPENCODE_PURE() {
|
||||
return truthy("OPENCODE_PURE")
|
||||
},
|
||||
get OPENCODE_PERMISSION() {
|
||||
return process.env["OPENCODE_PERMISSION"]
|
||||
},
|
||||
get OPENCODE_PLUGIN_META_FILE() {
|
||||
return process.env["OPENCODE_PLUGIN_META_FILE"]
|
||||
},
|
||||
get OPENCODE_CLIENT() {
|
||||
return process.env["OPENCODE_CLIENT"] ?? "cli"
|
||||
},
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ import { xdgData, xdgCache, xdgConfig, xdgState } from "xdg-basedir"
|
|||
import os from "os"
|
||||
import { Context, Effect, Layer } from "effect"
|
||||
import { Flock } from "./flock"
|
||||
import { Flag } from "./flag"
|
||||
import { makeGlobalNode } from "./effect/app-node"
|
||||
|
||||
const app = "opencode"
|
||||
|
|
@ -61,7 +60,7 @@ export function make(input: Partial<Interface> = {}): Interface {
|
|||
home: Path.home,
|
||||
data: Path.data,
|
||||
cache: Path.cache,
|
||||
config: Flag.OPENCODE_CONFIG_DIR ?? Path.config,
|
||||
config: Path.config,
|
||||
state: Path.state,
|
||||
tmp: Path.tmp,
|
||||
bin: Path.bin,
|
||||
|
|
@ -73,7 +72,7 @@ export function make(input: Partial<Interface> = {}): Interface {
|
|||
|
||||
const layer = Layer.effect(
|
||||
Service,
|
||||
Effect.sync(() => Service.of(make())),
|
||||
Effect.sync(() => Service.of(make({ config: process.env.OPENCODE_CONFIG_DIR ?? Path.config }))),
|
||||
)
|
||||
|
||||
export const node = makeGlobalNode({ service: Service, layer: layer, deps: [] })
|
||||
|
|
|
|||
|
|
@ -2,29 +2,43 @@ export * as Observability from "./observability"
|
|||
|
||||
import { NodeFileSystem } from "@effect/platform-node"
|
||||
import { LayerNode } from "./effect/layer-node"
|
||||
import { Effect, Layer, Logger, References } from "effect"
|
||||
import { Effect, Layer, Logger, References, Schema } from "effect"
|
||||
import { FetchHttpClient } from "effect/unstable/http"
|
||||
import { OtlpSerialization } from "effect/unstable/observability"
|
||||
import { Logging } from "./observability/logging"
|
||||
import { Otlp } from "./observability/otlp"
|
||||
|
||||
const local = Logger.layer(Logging.loggers(), { mergeWithExisting: false }).pipe(
|
||||
Layer.provide(NodeFileSystem.layer),
|
||||
Layer.orDie,
|
||||
Layer.merge(Layer.succeed(References.MinimumLogLevel, Logging.minimumLogLevel())),
|
||||
)
|
||||
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
|
||||
|
||||
export const layer = Layer.unwrap(
|
||||
Effect.gen(function* () {
|
||||
const logs = Logger.layer([...Logging.loggers(), ...Otlp.loggers()], { 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))
|
||||
}),
|
||||
).pipe(Layer.catchCause(() => local))
|
||||
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(
|
||||
Layer.provide(NodeFileSystem.layer),
|
||||
Layer.orDie,
|
||||
Layer.merge(Layer.succeed(References.MinimumLogLevel, Logging.minimumLogLevel())),
|
||||
)
|
||||
return Layer.unwrap(
|
||||
Effect.gen(function* () {
|
||||
const logs = Logger.layer([...Logging.loggers(), ...Otlp.loggers(options)], { 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)))
|
||||
}),
|
||||
).pipe(Layer.catchCause(() => local))
|
||||
}
|
||||
|
||||
export const node = LayerNode.make({ name: "observability", layer, deps: [] })
|
||||
export const node = LayerNode.make({ name: "observability", layer: layer(), deps: [] })
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
import { Layer } from "effect"
|
||||
import { OtlpLogger } from "effect/unstable/observability"
|
||||
import { Flag } from "../flag"
|
||||
import { InstallationChannel, InstallationVersion } from "../installation/version"
|
||||
import { runID } from "./shared"
|
||||
|
||||
const endpoint = Flag.OTEL_EXPORTER_OTLP_ENDPOINT
|
||||
export interface Options {
|
||||
readonly endpoint?: string
|
||||
readonly headers?: string
|
||||
readonly client?: string
|
||||
}
|
||||
|
||||
const headers = Flag.OTEL_EXPORTER_OTLP_HEADERS
|
||||
? Flag.OTEL_EXPORTER_OTLP_HEADERS.split(",").reduce(
|
||||
function parseHeaders(value?: string) {
|
||||
return value
|
||||
? value.split(",").reduce(
|
||||
(acc, entry) => {
|
||||
const [key, ...value] = entry.split("=")
|
||||
acc[key] = value.join("=")
|
||||
|
|
@ -15,7 +19,8 @@ const headers = Flag.OTEL_EXPORTER_OTLP_HEADERS
|
|||
},
|
||||
{} as Record<string, string>,
|
||||
)
|
||||
: undefined
|
||||
: undefined
|
||||
}
|
||||
|
||||
function resourceAttributes() {
|
||||
const value = process.env.OTEL_RESOURCE_ATTRIBUTES
|
||||
|
|
@ -33,27 +38,33 @@ function resourceAttributes() {
|
|||
}
|
||||
}
|
||||
|
||||
export function resource(): { 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,
|
||||
attributes: {
|
||||
...resourceAttributes(),
|
||||
"deployment.environment.name": InstallationChannel,
|
||||
"opencode.client": Flag.OPENCODE_CLIENT,
|
||||
"opencode.client": client,
|
||||
"opencode.run": runID,
|
||||
"service.instance.id": runID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export function loggers() {
|
||||
if (!endpoint) return []
|
||||
return [OtlpLogger.make({ url: `${endpoint}/v1/logs`, resource: resource(), headers })]
|
||||
export function loggers(options?: Options) {
|
||||
if (!options?.endpoint) return []
|
||||
return [
|
||||
OtlpLogger.make({
|
||||
url: `${options.endpoint}/v1/logs`,
|
||||
resource: resource(options.client),
|
||||
headers: parseHeaders(options.headers),
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
export async function tracingLayer() {
|
||||
if (!endpoint) return Layer.empty
|
||||
export async function tracingLayer(options?: Options) {
|
||||
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")
|
||||
|
|
@ -66,11 +77,11 @@ export async function tracingLayer() {
|
|||
context.setGlobalContextManager(manager)
|
||||
|
||||
return NodeSdk.layer(() => ({
|
||||
resource: resource(),
|
||||
resource: resource(options.client),
|
||||
spanProcessor: new SdkBase.BatchSpanProcessor(
|
||||
new OTLP.OTLPTraceExporter({
|
||||
url: `${endpoint}/v1/traces`,
|
||||
headers,
|
||||
url: `${options.endpoint}/v1/traces`,
|
||||
headers: parseHeaders(options.headers),
|
||||
}),
|
||||
),
|
||||
}))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue