@dudousxd/nestjs-诊断
一个小小的标准公约 @dudousxd/nestjs-* 要发送的库
节点内部的可观察事件
diagnostics_channel 与
无人听时,零起伏,一个通用
望远镜 监视器
(单位:千美元)@dudousxd/nestjs-diagnostics-telescope记录他们全部.
公约
每个事件都通过一个频道流出,命名为:
aviary:<lib>:<event>
aviary是这个图书馆家族的固定前缀.<lib>识别排放库,例如:.billing, (中文(简体) ),audit, (中文(简体) ),jobs。 。 。 .<event>是该图书馆内的事件,例如:.invoice-paid。 。 。 .
每个出版物都载有 DiagnosticEvent 信封 :
interface DiagnosticEvent<TPayload = unknown> {
ts: number; // Date.now() at publish time
lib: string; // the <lib>
event: string; // the <event>
traceId?: string; // auto-filled from a context accessor when available
payload: TPayload; // your library-defined data
}
开始
打电话 emit 无论发生什么有趣的事
import { Injectable } from '@nestjs/common';
import { emit } from '@dudousxd/nestjs-diagnostics';
@Injectable()
export class BillingService {
async markInvoicePaid(invoiceId: string, amount: number) {
// … your domain logic …
emit('billing', 'invoice-paid', { invoiceId, amount });
}
}
emit 建立和出版信封 只有在频道有
订户 (单位:千美元)channel.hasSubscribers因此,生产过程没有
随附观察员每通电话基本上不支付任何费用。 它从不扔..
观察性不能打破排放码路径.
需要明确追踪身份吗? 传过来 opts 例如,在操作员内部
已持有关联 id :
emit('billing', 'invoice-paid', payload, { traceId });
追踪关联
如果你的应用程序使用 @dudousxd/nestjs-context (可选对等点——从未导入)
在此注册其访问者一次 emit 将自动填充 traceId数字 :
import { setContextAccessor, CONTEXT_ACCESSOR } from '@dudousxd/nestjs-diagnostics';
// e.g. in a Nest module after resolving the optional CONTEXT_ACCESSOR provider:
setContextAccessor(accessor);
CONTEXT_ACCESSOR 实值 Symbol.for('@dudousxd/nestjs-context:accessor') - 那个
同一符号的courjs-context 出版之下。 任何结构匹配对象
ContextAccessor 界面工作.
观察(登记册)
diagnostics_channel 已经 不订阅通配符 - 您只能订阅
转到一个频道 确切的名字。 因此,这个软件包保留了每个
aviary:<lib>:<event> 它创建或发射的频道 :
import { registeredChannels, onChannelRegistered } from '@dudousxd/nestjs-diagnostics';
// subscribe to all current channels…
for (const name of registeredChannels()) subscribe(name);
// …and any registered in the future
const off = onChannelRegistered(subscribe);
就是这样 @dudousxd/nestjs-diagnostics-telescope单一通用
观察者记录望远镜仪表板上的每一个诊断事件.
第三方 nestjs:* 频道
官方的 NestJS 软件包在
diagnostics_channel 与《公约》有关的 nestjs:<lib>:<type>: 一个生的
有效载荷,无信封和跟踪仪(见
docs.nestjs.com (中文(简体) )) (中文(简体) ). nestjs:* 是第一当事方
aviary从不出版. aviary:* 只是为了什么
官方包裹不会放出.
subscribeOfficial 让一个消费者都记录下来。 包着每个官员
aviary信封内的有效载荷 traceId 取自上下文访问器
财务报告和审定财务报表 source: 'nestjs'数字 :
import { subscribeOfficial } from '@dudousxd/nestjs-diagnostics';
const off = subscribeOfficial('resilience', ['retry', 'circuit-open'], (event, channel) => {
// event: { v, ts, lib: 'resilience', event: 'retry', traceId, payload, source: 'nestjs' }
});
subscribeOfficial('authentication', 'all', record);
off();
频道列表以一个文件导出每个 lib , 粘贴在官方名下
对照(OFFICIAL_PACKAGE_VERSIONS) (中文(简体) ). 测试
重新读取已安装的软件包, 如果一个信道被添加、 重新命名或失败
已删除.
| Lib 语句 | 常数 | 频道 |
|---|---|---|
@nestjs/resilience 0.0.3 经常预算: | NESTJS_RESILIENCE_CHANNELS | 第9条 |
@nestjs/workflows 0.5 (中文(简体) ) | NESTJS_WORKFLOWS_CHANNELS | 第 19 条 |
@nestjs/authentication 0.1.5 (中文(简体) ) | NESTJS_AUTHENTICATION_CHANNELS | 第13条 |
@nestjs/authorization 1.1.3 国家 | NESTJS_AUTHORIZATION_CHANNELS | (单位:千美元)denied(中文(简体) ) |
@nestjs/mail 0.0.2 (中文(简体) ) | NESTJS_MAIL_CHANNELS | 页:1sent, (中文(简体) ), failed(中文(简体) ) |
这些频道不添加到 aviary:* 登记
(单位:千美元)registeredChannels编号 :onChannelRegistered) (中文(简体) ). 他们的列表是固定的,所以订阅
向他们明确.
最近发生的事件
DiagnosticsModule 保留进程的最后事件(aviary:* 事件,
trace() 周期性阶段和 nestjs:* 在固定大小的环中
秘密型钥匙被修改,有效载荷被切成2KB. 开着 除非
NODE_ENV 实值 'production'· ; recent: true | { size } | false 推翻它.
DiagnosticsModule.forRoot({ recent: { size: 1000 } });
// inject DiagnosticsRecentEvents, or anywhere:
import { recentEvents } from '@dudousxd/nestjs-diagnostics';
recentEvents({ lib: 'durable', event: /run\.failed/, traceId: 'req-42', limit: 50 });
MCP dev 工具
与 @dudousxd/nestjs-agent-mcp-server 挂载, DiagnosticsModule 登记册
aviary dev MCP端点上的三个只读工具:
diagnostics_list_channels, (中文(简体) ), diagnostics_list_listeners 财务报告和审定财务报表
diagnostics_list_recent_events诊断没有控制台,所以终点
devTools.authorize 关上门:没有门,他们就外出生产
在生产中被拒绝. devTools: false 让他们出去.
API 密码
| 导出 | 说明 |
|---|---|
emit(lib, event, payload, opts?) | 构建 + 发布 a DiagnosticEvent 打开 aviary:<lib>:<event> (仅在订阅时). |
getChannel(lib, event) | 回忆 diagnostics_channel 对一对(也登记其名称). |
channelName(lib, event) | 这个 aviary:<lib>:<event> 绳子. |
CHANNEL_PREFIX | 'aviary'。 。 。 . |
registeredChannels() | 每个注册频道名称的快照 . |
onChannelRegistered(cb) | 每个未来频道注册一次通知;返回未订阅者. |
setContextAccessor(accessor | null) | 注册访问者 emit 读取 traceId 从. |
CONTEXT_ACCESSOR | 可选上下文访问器的共享 DI 令牌 . |
subscribeOfficial(lib, types | 'all', fn) | 订阅第一当事方 nestjs:<lib>:<type> 通道,每个有效载荷包裹在信封(+ source: 'nestjs'。返回未订阅者. |
OFFICIAL_CHANNELS, (中文(简体) ), NESTJS_*_CHANNELS, (中文(简体) ), OFFICIAL_PACKAGE_VERSIONS, (中文(简体) ), officialChannelNames() | 被封住的第一党频道列表. |
recentEvents(filter?) | 最新缓冲事件(最新第一), [] 当缓冲器关闭. |
startRecentEvents(size?), (中文(简体) ), stopRecentEvents(), (中文(简体) ), recentEventsBuffer() | 运行最近的事件缓冲器,而不 DiagnosticsModule。 。 。 . |
DiagnosticEvent, (中文(简体) ), EmitOptions, (中文(简体) ), ContextAccessor, (中文(简体) ), OfficialDiagnosticEvent | 类型. |
对NestJS事件的反应—— @OnDiagnostic
这个 @dudousxd/nestjs-diagnostics/nestjs 子路径添加了 ergonomic 反应方式
对任意 aviary:<lib>:<event> 在 NestJS app中——没有额外的事件库. 登记册
模块,然后装饰提供者方法:
import { Module } from '@nestjs/common';
import { DiagnosticsModule } from '@dudousxd/nestjs-diagnostics/nestjs';
@Module({ imports: [DiagnosticsModule.forRoot()] })
export class AppModule {}
import { Injectable } from '@nestjs/common';
import { OnDiagnostic } from '@dudousxd/nestjs-diagnostics/nestjs';
import type { DiagnosticEvent } from '@dudousxd/nestjs-diagnostics';
@Injectable()
export class Reactions {
@OnDiagnostic('resilience', 'circuit-opened') // one exact channel
onCircuitOpen(e: DiagnosticEvent) { /* … */ }
@OnDiagnostic('resilience') // every aviary:resilience:* channel
onAnyResilience(e: DiagnosticEvent) { /* … */ }
}
处理器运行在 DI 解析实例(注入依赖性工作)上. A 类
扔出或拒绝的操作员被记录并吞没——它永远无法打破
代码 释放. @nestjs/common + 键 @nestjs/core 是可选对等器; 主
枪管保持框架不可知性.
event 还需要一个 RegExp每一个听众都有稳定的身份证明, <ClassName>#<method>。 。 。 .
整个过程:运输和 role
选一个 default 传输到运行整个进程的听众 :
import { DiagnosticsModule, transports } from '@dudousxd/nestjs-diagnostics/nestjs';
DiagnosticsModule.forRoot({
role: 'api', // 'all' (default) | 'api' | 'worker'
default: 'queue',
transports: {
redis: transports.redis({ pub: redis, sub: redis.duplicate() }), // broadcast, best-effort
queue: transports.queue({ connection: { host: 'localhost', port: 6379 } }), // BullMQ, retried
durable: transports.durable({ retries: 5 }), // durable runs (@dudousxd/nestjs-durable-diagnostics)
},
});
| 运输 | 听者运行的地方 | 如果进程失效, 丢失吗 ? | 如果处理器抛出 |
|---|---|---|---|
| 无(当地) | 排放过程 | 对 | 已登录、已丢弃 |
redis | (广播) | 对 | 已登录、已丢弃 |
queue | 在一个工人中 | 没有 | BullMQ 重回任务( 最少一次) |
durable | 在一个耐用工人中 | 没有 | 有后退的持久重试; 偶数 |
见 听众和运输 医生.
许可证
麻省理工学院