| 1 | import * as Effect from "effect/Effect"; |
| 2 | import { routeCacheLayer } from "../../Alchemist/Session.ts"; |
| 3 | import { recordCli } from "../../Telemetry/Metrics.ts"; |
| 4 | |
| 5 | /** |
| 6 | * Wraps a command handler as one traced, metered unit that is also one |
| 7 | * route-cache scope: the stack sessions and auth registries its routes open |
| 8 | * are memoized for the command's duration (`routeCacheLayer`). Commands that |
| 9 | * never open a session (`dev`, which only supervises the exec child) stay |
| 10 | * off this wrapper and therefore never load `Alchemist/Session`. |
| 11 | */ |
| 12 | export const instrumentCommand = |
| 13 | <AttrsArgs = unknown>( |
| 14 | command: string, |
| 15 | attrs?: (args: AttrsArgs) => Record<string, unknown>, |
| 16 | ) => |
| 17 | <Args extends AttrsArgs, A, E, R>( |
| 18 | handler: (args: Args) => Effect.Effect<A, E, R>, |
| 19 | ): ((args: Args) => Effect.Effect<A, E, R>) => |
| 20 | (args) => |
| 21 | handler(args).pipe( |
| 22 | Effect.withSpan(`cli.${command}`, { |
| 23 | attributes: attrs ? attrs(args) : {}, |
| 24 | }), |
| 25 | recordCli(command), |
| 26 | Effect.provide(routeCacheLayer), |
| 27 | ); |