From 19d51650f6f541acc9e35d95897597530007b15d Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Wed, 15 Apr 2026 13:12:42 -0400 Subject: [PATCH] feat(opencode): add request route spans --- .../opencode/src/server/instance/config.ts | 28 +++++++--------- .../opencode/src/server/instance/session.ts | 33 ++++++++++--------- .../opencode/src/server/instance/trace.ts | 28 ++++++++++++++++ 3 files changed, 56 insertions(+), 33 deletions(-) create mode 100644 packages/opencode/src/server/instance/trace.ts diff --git a/packages/opencode/src/server/instance/config.ts b/packages/opencode/src/server/instance/config.ts index 41d5872c984f..919901284e1b 100644 --- a/packages/opencode/src/server/instance/config.ts +++ b/packages/opencode/src/server/instance/config.ts @@ -5,12 +5,10 @@ import { Config } from "../../config/config" import { Provider } from "../../provider/provider" import { mapValues } from "remeda" import { errors } from "../error" -import { Log } from "../../util/log" import { lazy } from "../../util/lazy" import { AppRuntime } from "../../effect/app-runtime" import { Effect } from "effect" - -const log = Log.create({ service: "server" }) +import { jsonRequest } from "./trace" export const ConfigRoutes = lazy(() => new Hono() @@ -31,9 +29,10 @@ export const ConfigRoutes = lazy(() => }, }, }), - async (c) => { - return c.json(await AppRuntime.runPromise(Config.Service.use((cfg) => cfg.get()))) - }, + jsonRequest("ConfigRoutes.get", function* () { + const cfg = yield* Config.Service + return yield* cfg.get() + }), ) .patch( "/", @@ -82,18 +81,13 @@ export const ConfigRoutes = lazy(() => }, }, }), - async (c) => { - using _ = log.time("providers") - const providers = await AppRuntime.runPromise( - Effect.gen(function* () { - const svc = yield* Provider.Service - return mapValues(yield* svc.list(), (item) => item) - }), - ) - return c.json({ + jsonRequest("ConfigRoutes.providers", function* () { + const svc = yield* Provider.Service + const providers = mapValues(yield* svc.list(), (item) => item) + return { providers: Object.values(providers), default: mapValues(providers, (item) => Provider.sort(Object.values(item.models))[0].id), - }) - }, + } + }), ), ) diff --git a/packages/opencode/src/server/instance/session.ts b/packages/opencode/src/server/instance/session.ts index a011c32f9b2d..cbc38ef89343 100644 --- a/packages/opencode/src/server/instance/session.ts +++ b/packages/opencode/src/server/instance/session.ts @@ -26,6 +26,7 @@ import { errors } from "../error" import { lazy } from "../../util/lazy" import { Bus } from "../../bus" import { NamedError } from "@opencode-ai/shared/util/error" +import { jsonRequest } from "./trace" const log = Log.create({ service: "server" }) @@ -94,10 +95,10 @@ export const SessionRoutes = lazy(() => ...errors(400), }, }), - async (c) => { - const result = await AppRuntime.runPromise(SessionStatus.Service.use((svc) => svc.list())) - return c.json(Object.fromEntries(result)) - }, + jsonRequest("SessionRoutes.status", function* () { + const svc = yield* SessionStatus.Service + return Object.fromEntries(yield* svc.list()) + }), ) .get( "/:sessionID", @@ -124,11 +125,11 @@ export const SessionRoutes = lazy(() => sessionID: Session.GetInput, }), ), - async (c) => { + jsonRequest("SessionRoutes.get", function* (c) { const sessionID = c.req.valid("param").sessionID - const session = await AppRuntime.runPromise(Session.Service.use((svc) => svc.get(sessionID))) - return c.json(session) - }, + const session = yield* Session.Service + return yield* session.get(sessionID) + }), ) .get( "/:sessionID/children", @@ -155,11 +156,11 @@ export const SessionRoutes = lazy(() => sessionID: Session.ChildrenInput, }), ), - async (c) => { + jsonRequest("SessionRoutes.children", function* (c) { const sessionID = c.req.valid("param").sessionID - const session = await AppRuntime.runPromise(Session.Service.use((svc) => svc.children(sessionID))) - return c.json(session) - }, + const session = yield* Session.Service + return yield* session.children(sessionID) + }), ) .get( "/:sessionID/todo", @@ -185,11 +186,11 @@ export const SessionRoutes = lazy(() => sessionID: SessionID.zod, }), ), - async (c) => { + jsonRequest("SessionRoutes.todo", function* (c) { const sessionID = c.req.valid("param").sessionID - const todos = await AppRuntime.runPromise(Todo.Service.use((svc) => svc.get(sessionID))) - return c.json(todos) - }, + const todo = yield* Todo.Service + return yield* todo.get(sessionID) + }), ) .post( "/", diff --git a/packages/opencode/src/server/instance/trace.ts b/packages/opencode/src/server/instance/trace.ts new file mode 100644 index 000000000000..4b063a0e6fa3 --- /dev/null +++ b/packages/opencode/src/server/instance/trace.ts @@ -0,0 +1,28 @@ +import type { Context } from "hono" +import { Effect } from "effect" +import { AppRuntime } from "../../effect/app-runtime" + +export function runRequest(name: string, c: Context, effect: Effect.Effect) { + 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 function jsonRequest(name: string, effect: (c: any) => Effect.gen.Return) { + return async (c: Context) => + c.json( + await runRequest( + name, + c, + Effect.gen(() => effect(c)), + ), + ) +}