feat(opencode): improve telemetry tracing and request spans (#22653)
This commit is contained in:
@@ -49,7 +49,6 @@ import { ShareNext } from "@/share/share-next"
|
|||||||
import { SessionShare } from "@/share/session"
|
import { SessionShare } from "@/share/session"
|
||||||
|
|
||||||
export const AppLayer = Layer.mergeAll(
|
export const AppLayer = Layer.mergeAll(
|
||||||
Observability.layer,
|
|
||||||
AppFileSystem.defaultLayer,
|
AppFileSystem.defaultLayer,
|
||||||
Bus.defaultLayer,
|
Bus.defaultLayer,
|
||||||
Auth.defaultLayer,
|
Auth.defaultLayer,
|
||||||
@@ -95,7 +94,7 @@ export const AppLayer = Layer.mergeAll(
|
|||||||
Installation.defaultLayer,
|
Installation.defaultLayer,
|
||||||
ShareNext.defaultLayer,
|
ShareNext.defaultLayer,
|
||||||
SessionShare.defaultLayer,
|
SessionShare.defaultLayer,
|
||||||
)
|
).pipe(Layer.provideMerge(Observability.layer))
|
||||||
|
|
||||||
const rt = ManagedRuntime.make(AppLayer, { memoMap })
|
const rt = ManagedRuntime.make(AppLayer, { memoMap })
|
||||||
type Runtime = Pick<typeof rt, "runSync" | "runPromise" | "runPromiseExit" | "runFork" | "runCallback" | "dispose">
|
type Runtime = Pick<typeof rt, "runSync" | "runPromise" | "runPromiseExit" | "runFork" | "runCallback" | "dispose">
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export function attach<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A
|
|||||||
|
|
||||||
export function makeRuntime<I, S, E>(service: Context.Service<I, S>, layer: Layer.Layer<I, E>) {
|
export function makeRuntime<I, S, E>(service: Context.Service<I, S>, layer: Layer.Layer<I, E>) {
|
||||||
let rt: ManagedRuntime.ManagedRuntime<I, E> | undefined
|
let rt: ManagedRuntime.ManagedRuntime<I, E> | undefined
|
||||||
const getRuntime = () => (rt ??= ManagedRuntime.make(Layer.merge(layer, Observability.layer), { memoMap }))
|
const getRuntime = () => (rt ??= ManagedRuntime.make(Layer.provideMerge(layer, Observability.layer), { memoMap }))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
runSync: <A, Err>(fn: (svc: S) => Effect.Effect<A, Err, I>) => getRuntime().runSync(attach(service.use(fn))),
|
runSync: <A, Err>(fn: (svc: S) => Effect.Effect<A, Err, I>) => getRuntime().runSync(attach(service.use(fn))),
|
||||||
|
|||||||
@@ -5,12 +5,10 @@ import { Config } from "../../config/config"
|
|||||||
import { Provider } from "../../provider/provider"
|
import { Provider } from "../../provider/provider"
|
||||||
import { mapValues } from "remeda"
|
import { mapValues } from "remeda"
|
||||||
import { errors } from "../error"
|
import { errors } from "../error"
|
||||||
import { Log } from "../../util/log"
|
|
||||||
import { lazy } from "../../util/lazy"
|
import { lazy } from "../../util/lazy"
|
||||||
import { AppRuntime } from "../../effect/app-runtime"
|
import { AppRuntime } from "../../effect/app-runtime"
|
||||||
import { Effect } from "effect"
|
import { Effect } from "effect"
|
||||||
|
import { jsonRequest } from "./trace"
|
||||||
const log = Log.create({ service: "server" })
|
|
||||||
|
|
||||||
export const ConfigRoutes = lazy(() =>
|
export const ConfigRoutes = lazy(() =>
|
||||||
new Hono()
|
new Hono()
|
||||||
@@ -31,9 +29,11 @@ export const ConfigRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
return c.json(await AppRuntime.runPromise(Config.Service.use((cfg) => cfg.get())))
|
jsonRequest("ConfigRoutes.get", c, function* () {
|
||||||
},
|
const cfg = yield* Config.Service
|
||||||
|
return yield* cfg.get()
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.patch(
|
.patch(
|
||||||
"/",
|
"/",
|
||||||
@@ -82,18 +82,14 @@ export const ConfigRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
using _ = log.time("providers")
|
jsonRequest("ConfigRoutes.providers", c, function* () {
|
||||||
const providers = await AppRuntime.runPromise(
|
const svc = yield* Provider.Service
|
||||||
Effect.gen(function* () {
|
const providers = mapValues(yield* svc.list(), (item) => item)
|
||||||
const svc = yield* Provider.Service
|
return {
|
||||||
return mapValues(yield* svc.list(), (item) => item)
|
providers: Object.values(providers),
|
||||||
}),
|
default: mapValues(providers, (item) => Provider.sort(Object.values(item.models))[0].id),
|
||||||
)
|
}
|
||||||
return c.json({
|
}),
|
||||||
providers: Object.values(providers),
|
|
||||||
default: mapValues(providers, (item) => Provider.sort(Object.values(item.models))[0].id),
|
|
||||||
})
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import { errors } from "../error"
|
|||||||
import { lazy } from "../../util/lazy"
|
import { lazy } from "../../util/lazy"
|
||||||
import { Bus } from "../../bus"
|
import { Bus } from "../../bus"
|
||||||
import { NamedError } from "@opencode-ai/shared/util/error"
|
import { NamedError } from "@opencode-ai/shared/util/error"
|
||||||
|
import { jsonRequest } from "./trace"
|
||||||
|
|
||||||
const log = Log.create({ service: "server" })
|
const log = Log.create({ service: "server" })
|
||||||
|
|
||||||
@@ -94,10 +95,11 @@ export const SessionRoutes = lazy(() =>
|
|||||||
...errors(400),
|
...errors(400),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const result = await AppRuntime.runPromise(SessionStatus.Service.use((svc) => svc.list()))
|
jsonRequest("SessionRoutes.status", c, function* () {
|
||||||
return c.json(Object.fromEntries(result))
|
const svc = yield* SessionStatus.Service
|
||||||
},
|
return Object.fromEntries(yield* svc.list())
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/:sessionID",
|
"/:sessionID",
|
||||||
@@ -126,8 +128,10 @@ export const SessionRoutes = lazy(() =>
|
|||||||
),
|
),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const sessionID = c.req.valid("param").sessionID
|
const sessionID = c.req.valid("param").sessionID
|
||||||
const session = await AppRuntime.runPromise(Session.Service.use((svc) => svc.get(sessionID)))
|
return jsonRequest("SessionRoutes.get", c, function* () {
|
||||||
return c.json(session)
|
const session = yield* Session.Service
|
||||||
|
return yield* session.get(sessionID)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
@@ -157,8 +161,10 @@ export const SessionRoutes = lazy(() =>
|
|||||||
),
|
),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const sessionID = c.req.valid("param").sessionID
|
const sessionID = c.req.valid("param").sessionID
|
||||||
const session = await AppRuntime.runPromise(Session.Service.use((svc) => svc.children(sessionID)))
|
return jsonRequest("SessionRoutes.children", c, function* () {
|
||||||
return c.json(session)
|
const session = yield* Session.Service
|
||||||
|
return yield* session.children(sessionID)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
@@ -187,8 +193,10 @@ export const SessionRoutes = lazy(() =>
|
|||||||
),
|
),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const sessionID = c.req.valid("param").sessionID
|
const sessionID = c.req.valid("param").sessionID
|
||||||
const todos = await AppRuntime.runPromise(Todo.Service.use((svc) => svc.get(sessionID)))
|
return jsonRequest("SessionRoutes.todo", c, function* () {
|
||||||
return c.json(todos)
|
const todo = yield* Todo.Service
|
||||||
|
return yield* todo.get(sessionID)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import type { Context } from "hono"
|
||||||
|
import { Effect } from "effect"
|
||||||
|
import { AppRuntime } from "../../effect/app-runtime"
|
||||||
|
|
||||||
|
type AppEnv = Parameters<typeof AppRuntime.runPromise>[0] extends Effect.Effect<any, any, infer R> ? R : never
|
||||||
|
|
||||||
|
export function runRequest<A, E>(name: string, c: Context, effect: Effect.Effect<A, E, AppEnv>) {
|
||||||
|
const url = new URL(c.req.url)
|
||||||
|
return AppRuntime.runPromise(
|
||||||
|
effect.pipe(
|
||||||
|
Effect.withSpan(name, {
|
||||||
|
attributes: {
|
||||||
|
"http.method": c.req.method,
|
||||||
|
"http.path": url.pathname,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function jsonRequest<C extends Context, A, E>(
|
||||||
|
name: string,
|
||||||
|
c: C,
|
||||||
|
effect: (c: C) => Effect.gen.Return<A, E, AppEnv>,
|
||||||
|
) {
|
||||||
|
return c.json(
|
||||||
|
await runRequest(
|
||||||
|
name,
|
||||||
|
c,
|
||||||
|
Effect.gen(() => effect(c)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user