@omni-api/plugin-observability
v0.0.2
Published
Observability for OmniAPI: structured logger + OTel tracing + Prometheus metrics. All optional, all pluggable.
Downloads
20
Readme
@omni/plugin-observability
OmniAPI 一站式可观测:结构化日志 + OTel 追踪 + Prometheus 指标,三件套全部 peer-optional —— 装哪个用哪个,都不装也能跑。
安装
最小:
pnpm add @omni/plugin-observability按需启用(业务自己决定要哪个):
pnpm add pino # 结构化日志
pnpm add @opentelemetry/api # 分布式追踪(你需要自己配 SDK / Exporter)
pnpm add prom-client # Prometheus 指标快速使用
import { createObservability } from '@omni/plugin-observability';
const obs = await createObservability({
logger: { level: 'info', bindings: { service: 'orders', env: 'prod' } },
metrics: { prefix: 'myapp' },
});
defineProcedure({
name: 'order.create',
middleware: [obs.middleware /* 自动 log + trace + metrics */],
// ...
});
// HTTP 暴露 /metrics
import { createHttpAdapter } from '@omni/http';
const http = createHttpAdapter({ registry, logger: obs.logger });
http.server.get('/_metrics', async (_req, reply) => {
reply.header('content-type', 'text/plain; version=0.0.4');
return obs.metrics.render();
});自动产出
每个 procedure 调用都会产生:
日志
INFO procedure.success {"procedure":"order.create","source":"http","requestId":"req_xxx","durationMs":42}
WARN procedure.failure {"procedure":"order.delete","code":"FORBIDDEN","durationMs":3,"errorMessage":"..."}
ERROR procedure.failure {"procedure":"x","code":"INTERNAL",...} # 5xx 用 error 级别日志级别策略:
- 4xx 业务错误 →
warn(业务可预期) - 5xx / 非 OmniError →
error
指标(Prometheus)
omni_procedure_total{name, source, status, code}—— 计数- status:
success/client_error/server_error - code:
OK/VALIDATION_ERROR/FORBIDDEN/ ...
- status:
omni_procedure_duration_seconds{name, source, status}—— 直方图(默认桶 1ms~10s)
Trace
- 每个 procedure 一个 span:
procedure <name> - 自动属性:
omni.procedure.name、omni.source、omni.request_id、omni.user_id、omni.duration_ms - 异常自动
recordException+setStatus(ERROR)
子模块单独使用
import { createLogger, createTracer, createMetrics } from '@omni/plugin-observability';
const logger = await createLogger({ level: 'info' });
const tracer = await createTracer({ name: 'orders' });
const metrics = await createMetrics({ prefix: 'app' });为什么 peer-optional?
避免框架强绑定具体观测栈。业务可能:
- 只要日志(pino),不要 metrics
- 内部已经有自家 OTel 配置
- 只想跑测试,三个都不要
→ 这些场景全部支持,零 if-else。
