Skip to content

Commit 6bed7d4

Browse files
authored
feat(opencode): improve telemetry tracing and request spans (#22653)
1 parent 3b75f16 commit 6bed7d4

5 files changed

Lines changed: 68 additions & 32 deletions

File tree

packages/opencode/src/effect/app-runtime.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ import { ShareNext } from "@/share/share-next"
4949
import { SessionShare } from "@/share/session"
5050

5151
export const AppLayer = Layer.mergeAll(
52-
Observability.layer,
5352
AppFileSystem.defaultLayer,
5453
Bus.defaultLayer,
5554
Auth.defaultLayer,
@@ -95,7 +94,7 @@ export const AppLayer = Layer.mergeAll(
9594
Installation.defaultLayer,
9695
ShareNext.defaultLayer,
9796
SessionShare.defaultLayer,
98-
)
97+
).pipe(Layer.provideMerge(Observability.layer))
9998

10099
const rt = ManagedRuntime.make(AppLayer, { memoMap })
101100
type Runtime = Pick<typeof rt, "runSync" | "runPromise" | "runPromiseExit" | "runFork" | "runCallback" | "dispose">

packages/opencode/src/effect/run-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export function attach<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A
3838

3939
export function makeRuntime<I, S, E>(service: Context.Service<I, S>, layer: Layer.Layer<I, E>) {
4040
let rt: ManagedRuntime.ManagedRuntime<I, E> | undefined
41-
const getRuntime = () => (rt ??= ManagedRuntime.make(Layer.merge(layer, Observability.layer), { memoMap }))
41+
const getRuntime = () => (rt ??= ManagedRuntime.make(Layer.provideMerge(layer, Observability.layer), { memoMap }))
4242

4343
return {
4444
runSync: <A, Err>(fn: (svc: S) => Effect.Effect<A, Err, I>) => getRuntime().runSync(attach(service.use(fn))),

packages/opencode/src/server/instance/config.ts

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ import { Config } from "../../config/config"
55
import { Provider } from "../../provider/provider"
66
import { mapValues } from "remeda"
77
import { errors } from "../error"
8-
import { Log } from "../../util/log"
98
import { lazy } from "../../util/lazy"
109
import { AppRuntime } from "../../effect/app-runtime"
1110
import { Effect } from "effect"
12-
13-
const log = Log.create({ service: "server" })
11+
import { jsonRequest } from "./trace"
1412

1513
export const ConfigRoutes = lazy(() =>
1614
new Hono()
@@ -31,9 +29,11 @@ export const ConfigRoutes = lazy(() =>
3129
},
3230
},
3331
}),
34-
async (c) => {
35-
return c.json(await AppRuntime.runPromise(Config.Service.use((cfg) => cfg.get())))
36-
},
32+
async (c) =>
33+
jsonRequest("ConfigRoutes.get", c, function* () {
34+
const cfg = yield* Config.Service
35+
return yield* cfg.get()
36+
}),
3737
)
3838
.patch(
3939
"/",
@@ -82,18 +82,14 @@ export const ConfigRoutes = lazy(() =>
8282
},
8383
},
8484
}),
85-
async (c) => {
86-
using _ = log.time("providers")
87-
const providers = await AppRuntime.runPromise(
88-
Effect.gen(function* () {
89-
const svc = yield* Provider.Service
90-
return mapValues(yield* svc.list(), (item) => item)
91-
}),
92-
)
93-
return c.json({
94-
providers: Object.values(providers),
95-
default: mapValues(providers, (item) => Provider.sort(Object.values(item.models))[0].id),
96-
})
97-
},
85+
async (c) =>
86+
jsonRequest("ConfigRoutes.providers", c, function* () {
87+
const svc = yield* Provider.Service
88+
const providers = mapValues(yield* svc.list(), (item) => item)
89+
return {
90+
providers: Object.values(providers),
91+
default: mapValues(providers, (item) => Provider.sort(Object.values(item.models))[0].id),
92+
}
93+
}),
9894
),
9995
)

packages/opencode/src/server/instance/session.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { errors } from "../error"
2626
import { lazy } from "../../util/lazy"
2727
import { Bus } from "../../bus"
2828
import { NamedError } from "@opencode-ai/shared/util/error"
29+
import { jsonRequest } from "./trace"
2930

3031
const log = Log.create({ service: "server" })
3132

@@ -94,10 +95,11 @@ export const SessionRoutes = lazy(() =>
9495
...errors(400),
9596
},
9697
}),
97-
async (c) => {
98-
const result = await AppRuntime.runPromise(SessionStatus.Service.use((svc) => svc.list()))
99-
return c.json(Object.fromEntries(result))
100-
},
98+
async (c) =>
99+
jsonRequest("SessionRoutes.status", c, function* () {
100+
const svc = yield* SessionStatus.Service
101+
return Object.fromEntries(yield* svc.list())
102+
}),
101103
)
102104
.get(
103105
"/:sessionID",
@@ -126,8 +128,10 @@ export const SessionRoutes = lazy(() =>
126128
),
127129
async (c) => {
128130
const sessionID = c.req.valid("param").sessionID
129-
const session = await AppRuntime.runPromise(Session.Service.use((svc) => svc.get(sessionID)))
130-
return c.json(session)
131+
return jsonRequest("SessionRoutes.get", c, function* () {
132+
const session = yield* Session.Service
133+
return yield* session.get(sessionID)
134+
})
131135
},
132136
)
133137
.get(
@@ -157,8 +161,10 @@ export const SessionRoutes = lazy(() =>
157161
),
158162
async (c) => {
159163
const sessionID = c.req.valid("param").sessionID
160-
const session = await AppRuntime.runPromise(Session.Service.use((svc) => svc.children(sessionID)))
161-
return c.json(session)
164+
return jsonRequest("SessionRoutes.children", c, function* () {
165+
const session = yield* Session.Service
166+
return yield* session.children(sessionID)
167+
})
162168
},
163169
)
164170
.get(
@@ -187,8 +193,10 @@ export const SessionRoutes = lazy(() =>
187193
),
188194
async (c) => {
189195
const sessionID = c.req.valid("param").sessionID
190-
const todos = await AppRuntime.runPromise(Todo.Service.use((svc) => svc.get(sessionID)))
191-
return c.json(todos)
196+
return jsonRequest("SessionRoutes.todo", c, function* () {
197+
const todo = yield* Todo.Service
198+
return yield* todo.get(sessionID)
199+
})
192200
},
193201
)
194202
.post(
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type { Context } from "hono"
2+
import { Effect } from "effect"
3+
import { AppRuntime } from "../../effect/app-runtime"
4+
5+
type AppEnv = Parameters<typeof AppRuntime.runPromise>[0] extends Effect.Effect<any, any, infer R> ? R : never
6+
7+
export function runRequest<A, E>(name: string, c: Context, effect: Effect.Effect<A, E, AppEnv>) {
8+
const url = new URL(c.req.url)
9+
return AppRuntime.runPromise(
10+
effect.pipe(
11+
Effect.withSpan(name, {
12+
attributes: {
13+
"http.method": c.req.method,
14+
"http.path": url.pathname,
15+
},
16+
}),
17+
),
18+
)
19+
}
20+
21+
export async function jsonRequest<C extends Context, A, E>(
22+
name: string,
23+
c: C,
24+
effect: (c: C) => Effect.gen.Return<A, E, AppEnv>,
25+
) {
26+
return c.json(
27+
await runRequest(
28+
name,
29+
c,
30+
Effect.gen(() => effect(c)),
31+
),
32+
)
33+
}

0 commit comments

Comments
 (0)