§9 trace all fetch + ENV service name + leveled logging (todo §9 follow-up); route every outbound fetch through the request logger, make the OTLP service name implementer-configurable, and add proper leveled logging throughout. An AsyncLocalStorage<Log> makes the per-request logger ambient (runWithLog/currentLog), so all outbound fetch traces with no signature churn: tracedFetch (a typeof fetch) routes through the active request log (client span + propagated W3C traceparent) for string/URL inputs, else plain fetch; server.ts wires it under the Ory timeout into every Kratos/Keto/Hydra + JWKS call (timeout still honoured — log.fetch spreads {...init,headers}). RequestContext gained ctx.log (request logger; additive/contract-stable, silent default) so a handler/plugin logs in-trace and ctx.log.fetch(url) traces upstream calls; the reference plugin's createUpstream defaults to tracedFetch and its handlers log via ctx.log; plugin-api.ts exports tracedFetch + the Log class. SERVICE_NAME (config + createLogger({serviceName})) brands the OTLP service.name. Leveled logging: who-did-what audit info lines on every admin write (user/group/role/client create·delete·assign — actor/target, no secrets), info on login (session mint) + logout, warn on missing-role 403 + CSRF rejections + Ory-unreachable, debug on a JWKS kid-miss reload. app.ts's handler body was extracted to handleRequest run inside runWithLog; end() now fires exactly once after BOTH the handler unwinds AND the response closes, so a client abort mid-handler can't end the log out from under a still-running ctx.log/tracedFetch (regression-tested) and the happy-path access line is never dropped. bootstrap.ts wraps main in runWithLog + traces the seed calls. Tests extended (logger: serviceName/runWithLog/currentLog/tracedFetch-continues-trace; config: SERVICE_NAME; context: ctx.log default+passthrough; app: ctx.log in-trace + ctx.log.fetch propagation + the abort race; plugin-api: tracedFetch+Log). Stability-reviewer: APPROVE, no Critical/High (fixed the abort-race end(); green nits addressed). docs/plugin-contract.md (ctx.log/ctx.log.fetch/tracedFetch) + README (config, Observability tracing/serviceName, plugin note, Layout) updated. typecheck + 333 units + the full scripts/ci.sh E2E gate green (326 → 333).
This commit is contained in:
+6
-4
@@ -9,16 +9,18 @@ import { createJwksProvider } from "./jwks.ts";
|
||||
import { createKetoClient } from "./keto-client.ts";
|
||||
import { createKratosAdmin } from "./kratos-admin.ts";
|
||||
import { createKratosPublic } from "./kratos-public.ts";
|
||||
import { createLogger } from "./logger.ts";
|
||||
import { createLogger, tracedFetch } from "./logger.ts";
|
||||
import { loadMenuConfig } from "./menu-config.ts";
|
||||
|
||||
const config = loadConfig(); // validates the env (incl. enforced secrets) — fails loud at boot
|
||||
// App-level logger (§9): structured, OTLP-capable when OTLP_ENDPOINT is set. The hot path clones it
|
||||
// per request for access logging + a trace span (src/app.ts); console-only otherwise.
|
||||
const log = createLogger({ format: config.logFormat, level: config.logLevel, otlpEndpoint: config.otlpEndpoint, otlpProtocol: config.otlpProtocol });
|
||||
const log = createLogger({ format: config.logFormat, level: config.logLevel, otlpEndpoint: config.otlpEndpoint, otlpProtocol: config.otlpProtocol, serviceName: config.serviceName });
|
||||
const menu = await loadMenuConfig(); // config/menu.ts override + branding — fails loud if malformed
|
||||
// Every outbound Ory call is bounded so a hung/silent Ory can't park a request handler forever.
|
||||
const oryFetch = withTimeout(fetch, config.oryTimeoutSec * 1000);
|
||||
// Every outbound Ory call is traced through the active request's logger (a client span continuing
|
||||
// the trace + a propagated traceparent — tracedFetch) and bounded by the Ory timeout, so a hung/
|
||||
// silent Ory can't park a request handler forever. Off the request path it's a plain timed fetch.
|
||||
const oryFetch = withTimeout(tracedFetch, config.oryTimeoutSec * 1000);
|
||||
// Ory clients for the themed self-service routes + login completion (§4).
|
||||
const kratos = createKratosPublic({ baseUrl: config.kratosPublicUrl, fetchImpl: oryFetch });
|
||||
const kratosAdmin = createKratosAdmin({ baseUrl: config.kratosAdminUrl, fetchImpl: oryFetch });
|
||||
|
||||
Reference in New Issue
Block a user