dsh-log 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INTEGRATION.md +31 -12
- package/README.md +23 -10
- package/package.json +1 -1
package/INTEGRATION.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# 日志包集成教程(从安装到首条落盘)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
对应版本:与本仓 `packages/dsh-log/package.json` 同版本(本教程随包一起发布;升级后以新版教程为准,旧版教程只对应当时的包)。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
接口形状、配置默认值、失败语义查 `README.md` 第 4 到 7 节;本文只讲按什么顺序做什么、每步做完的判据是什么。
|
|
6
|
+
|
|
7
|
+
先按自己的形态选一条路走,**不要两条都走**:
|
|
6
8
|
|
|
7
9
|
**路线 A|DSH 插件作者**:你的代码跑在 DSH 宿主里(插件宿主侧与客户端侧两个半区)。走下面的步骤 0、1、2、3、4 一路到底。
|
|
8
10
|
|
|
9
|
-
**路线 B|独立 Node 程序作者**:你的程序不是 DSH 插件、自己独立跑(例如一个技能自己的命令行)。走下面的步骤 0、1、**2B
|
|
11
|
+
**路线 B|独立 Node 程序作者**:你的程序不是 DSH 插件、自己独立跑(例如一个技能自己的命令行)。走下面的步骤 0、1、**2B**,跳过 2 与 3,再看步骤 4 里的落点说明。你没有宿主文件服务、没有电话、也没有客户端要转发,用不上那两节。
|
|
10
12
|
|
|
11
13
|
全程用词:日志系统指日志功能本身,日志包指装着日志系统的这个 npm 包。电话指宿主对外提供的方法;落盘指宿主统一写本地文件的动作。
|
|
12
14
|
|
|
@@ -18,15 +20,22 @@ Node 22 或更高:
|
|
|
18
20
|
node --version
|
|
19
21
|
```
|
|
20
22
|
|
|
23
|
+
**做完的判据**:输出的版本号是 22 或更高。
|
|
24
|
+
|
|
21
25
|
## 步骤 1. 安装
|
|
22
26
|
|
|
23
27
|
```sh
|
|
24
28
|
npm install dsh-log
|
|
25
29
|
```
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
上面这条命令直接可用:包已发布到 npm 官方源(最新版本用 `npm view dsh-log version` 自查)。若你要接的是本仓库里改过、还没发出去的那份,才改用本地路径或工作区引用代替(例如 `npm install ../dsh-log`)。
|
|
32
|
+
|
|
33
|
+
本地路径那条命令要在你自己插件的目录里执行,不是在日志包目录里。
|
|
28
34
|
|
|
29
|
-
|
|
35
|
+
**做完的判据**:
|
|
36
|
+
|
|
37
|
+
- 路线 A:能引用到已构建产物(`dist/host.js` 与 `dist/client.js`),并且从 `hostLog.phoneNames` 里读得到 5 个电话名(`logBatch`、`logExport`、`logClear`、`logGetSwitch`、`logSetSwitch` 各一个)。
|
|
38
|
+
- 路线 B:能引用到 `dist/node.js` 即算装好,读不到电话名是正常的(见步骤 2B)。
|
|
30
39
|
|
|
31
40
|
## 步骤 2B. 独立 Node 程序的接线(只有这一节,一次调用就够)
|
|
32
41
|
|
|
@@ -48,7 +57,9 @@ await log.ready // 等这一下:程序退出前日志才真的落盘
|
|
|
48
57
|
|
|
49
58
|
1. **`cacheDir` 由你决定,入口不猜**。它不读任何环境变量、也没有默认路径;你要把日志放在自己的数据目录旁边,就把那个目录传进来。目录不存在时入口自己建。
|
|
50
59
|
2. **`pluginId` 必填**,规则与插件侧一样:小写英文字母、数字、中横线,1 到 32 个字符。它决定落点:日志写在 `<cacheDir>/logs-<标识>/` 下按天一个文件,调试开关写在 `<cacheDir>/log-switch-<标识>.json`。
|
|
51
|
-
3. **`await log.ready`
|
|
60
|
+
3. **`await log.ready` 不能省**。落盘是防抖加异步写的:程序自然跑完不会丢(Node 会等那个定时器),但结尾调了 `process.exit()`、抛错退出或被强杀,队列里还没写下去的那批就丢了(`warn` 与 `info` 一样会丢)。这一下会等到「前面写的每一行都已经在文件里」才返回。
|
|
61
|
+
|
|
62
|
+
**做完的判据**:跑一遍上面这段,`<cacheDir>/logs-<标识>/` 下出现当天日期的 `.log` 文件,文件里能看到那一行 JSON。想验证第 3 条:把 `await log.ready` 删掉,并在写完日志后加一行 `process.exit(0)`,那一行就不再落盘。
|
|
52
63
|
|
|
53
64
|
与插件侧的差别,一眼看清:
|
|
54
65
|
|
|
@@ -92,7 +103,7 @@ registerHostLogPhones(new Map(), hostLog)
|
|
|
92
103
|
|
|
93
104
|
只传 `pluginId` 就用上全部默认:电话名前缀回退到插件标识,目录名派生为 `logs-my-plugin`,开关文件名派生为 `log-switch-my-plugin.json`,文件名按天。第二个插件不得与第一个共用同一目录,走默认派生自然分开。
|
|
94
105
|
|
|
95
|
-
|
|
106
|
+
**做完的判据**:`hostLog.phoneNames` 打印出 5 个带自己前缀的电话名,注册过程没有报错。若是注册时报"电话名已被注册,不覆盖旧的",见常见坑第 4 条。
|
|
96
107
|
|
|
97
108
|
## 步骤 3. 客户端侧接线(两种消费二选一)
|
|
98
109
|
|
|
@@ -121,6 +132,8 @@ const host = { call: (name, args) => registry.get(name)(args) }
|
|
|
121
132
|
|
|
122
133
|
只有把客户端拼进插件主文件闭包一起运行的插件,才用文本拼接:构建时取客户端入口编译后的声明体,去行首 `export` 后拼进闭包,调用时把闭包里现成的四个名字原样传给工厂。文本拼接消费方式只走客户端入口的声明体文本。
|
|
123
134
|
|
|
135
|
+
**做完的判据**:客户端与宿主用的是同一个 `pluginId`,两端拼出的电话名一致;下一节写第一条日志就是这条的实测。
|
|
136
|
+
|
|
124
137
|
## 步骤 4. 写第一条日志并看它落盘
|
|
125
138
|
|
|
126
139
|
```js
|
|
@@ -133,7 +146,9 @@ clientLog.flush()
|
|
|
133
146
|
|
|
134
147
|
第二个参数是采样率,取 0 到 1 之间的小数,1 表示全量(默认就是 1);传非数字时保持旧值不变。
|
|
135
148
|
|
|
136
|
-
|
|
149
|
+
宿主是唯一的落盘者:客户端只进队列就返回,转发走电话,落盘走宿主刷盘链路。
|
|
150
|
+
|
|
151
|
+
**做完的判据**:在缓存目录下的 `logs-my-plugin` 目录里找到当天的 `年月日.log` 文件,里面有 `my-plugin.hello` 这一条。
|
|
137
152
|
|
|
138
153
|
等多久:调了 `flush` 只剩宿主侧约 1000 毫秒防抖刷盘,约 1 秒后去看文件;不调 `flush` 则客户端约 1000 毫秒转发加上宿主约 1000 毫秒刷盘,约 2 秒后再看。错误与告警两级直通,不用等满防抖。脚本里用轮询等文件出现(例如每 200 毫秒看一次、最多等 6 秒),不要写死睡固定秒数,心急看不到文件会误以为没接通。
|
|
139
154
|
|
|
@@ -189,21 +204,25 @@ checkEventCounts(manifest)
|
|
|
189
204
|
|
|
190
205
|
每条事件四样东西:事件名、级别、允许字段(之外的键一律不记)、脱敏引用(只记规则名不记原文)。增删事件必须同步改清单的 `counts`,否则计数检查变红。细节见 `README.md` 第 7 节。
|
|
191
206
|
|
|
207
|
+
**做完的判据**:`parseEventListManifest`、`checkEventFields`、`checkEventCounts` 三个检查器都通过(返回结构里的 `ok` 为真),且清单自报的 `counts` 与 `events` 里三类事件的个数逐项一致。
|
|
208
|
+
|
|
192
209
|
## 步骤 6. 界面建议(导出、清空、开关)
|
|
193
210
|
|
|
194
211
|
- 导出:在状态栏菜单与设置页各放一个导出入口,都调 `logExport`(入参可选日期,不传导出当天)。成功把回参的 `text` 存成文件给用户;失败分支记一行 `log.export.fail`(走 `logExportFail`,成功路径不调用);失败原因只给机器码,面向用户的文案由界面经多语言系统转换,日志包内不写面向用户的中文字符串。
|
|
195
212
|
- 清空:在设置页放清空入口,调 `logClear`(`date` 传某天或 `all`),回参的 `removed` 告诉用户删掉几个文件。
|
|
196
213
|
- 开关:在设置页放调试开关(是否开启加采样率),调 `setLogSwitch` / 启动时调 `reconcileLogSwitch` 向宿主对账(以宿主为准)。开关写失败保持旧值(失败原因只给机器码:`host-unavailable`、`host-rejected`、`switch-timeout`、`stale` 等),由调用处提示用户,不回退为开启。
|
|
197
214
|
|
|
215
|
+
**做完的判据**:三个入口在界面上各走通一次——导出能把 `text` 存成文件;清空能报出删掉几个文件;开关改完刷新一次,读到的仍是改后的值。
|
|
216
|
+
|
|
198
217
|
## 常见坑
|
|
199
218
|
|
|
200
219
|
1. 多进程同时写同一个目录会写坏:一个插件只建一个日志库实例,目录不要两个实例共用;第二个插件走默认派生自然分到不同目录。
|
|
201
220
|
2. Windows 文件名里不能有冒号:四段式文件名的启动时间已把冒号与斜杠转写为中横线,目录派生与标识字符约束也排除了文件不安全字符,不要自己拼带冒号的文件名。
|
|
202
221
|
3. 目录漂移(缓存目录变化导致找不到旧日志):取缓存目录走传入的 `getCacheDir`,不要在包外自己缓存一份目录路径;目录里只记散列不记原文路径。
|
|
203
|
-
4.
|
|
222
|
+
4. 电话名撞名(注册时报"电话名已被注册,不覆盖旧的"):这个前缀已被别的插件用掉,换一个没被用过的前缀(`prefix` 显式传入),不要复用默认前缀 `wf`(`wf` 只给当前插件用)。
|
|
204
223
|
5. 标识大小写:收到大写直接报错,不做静默转小写,全小写重传即可。
|
|
205
|
-
|
|
206
|
-
|
|
224
|
+
|
|
225
|
+
回参形状相关的两个坑(`bytes` 是日志原文的字符串长度不是真实字节数、开关写成功后采样率以请求时的值为准)写在 `README.md` 第 5.1 节,查回参时一起看。
|
|
207
226
|
|
|
208
227
|
## 自查清单(按本文档能否走通)
|
|
209
228
|
|
|
@@ -213,4 +232,4 @@ checkEventCounts(manifest)
|
|
|
213
232
|
- [ ] 首条日志落盘:在派生目录里找到当天文件并看到该条。
|
|
214
233
|
- [ ] `getDroppedCount` 可读;失败场景(断开宿主)只计数不抛错。
|
|
215
234
|
- [ ] 清单接入(如做):模板已复制改名,检查器三函数全过,计数逐项一致。
|
|
216
|
-
- [ ]
|
|
235
|
+
- [ ] 发布前跑过 `README.md` 第 9 节的门禁(包内单测与 14 个日志门禁全绿),事件条数与 `research/489-appendix.md` 第 1 章一致,dry-run 文件数与 `README.md` 第 9 节的 11 个对上。
|
package/README.md
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
# dsh-log(日志包)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
地图 #556 的一部分,本包包含宿主引擎(#559)、客户端引擎(#560)、事件清单格式与通用检查器(#561),集成步骤另见包内的 `INTEGRATION.md`(从安装到首条落盘的按序教程)。
|
|
3
|
+
把本仓日志系统装成的 npm 包:DSH 插件与独立跑的 Node 程序都能照着它集成使用。本包由三块合成——宿主落盘引擎(#559)、客户端转发引擎(#560)、事件清单格式与通用检查器(#561),是地图 #556 的产物。
|
|
5
4
|
|
|
6
5
|
全程用词:日志系统指日志功能本身(引擎、对外接口、检查器、文档);日志包指装着日志系统的这个 npm 包。电话指宿主对外提供的方法;落盘指宿主统一写本地文件的动作。
|
|
7
6
|
|
|
7
|
+
## 0. 我该读哪儿
|
|
8
|
+
|
|
9
|
+
| 你的情况 | 从哪儿开始 |
|
|
10
|
+
|---|---|
|
|
11
|
+
| 写 DSH 插件,要给插件接日志 | 包内 `INTEGRATION.md` 路线 A:步骤 0 到 4 一路到底 |
|
|
12
|
+
| 写独立 Node 程序(不是插件),要往本地写日志 | 包内 `INTEGRATION.md` 路线 B:步骤 0、1、2B,再看步骤 4 的落点说明 |
|
|
13
|
+
| 已经装好,要查接口形状(电话、配置、回参) | 本文第 4 到 7 节 |
|
|
14
|
+
| 改了本包要发版 | 本文第 9 节;发布记录与向导在仓库的 `packages/dsh-log/notes-publish-drill.md`(不随包发布) |
|
|
15
|
+
|
|
8
16
|
## 1. 安装
|
|
9
17
|
|
|
10
18
|
```sh
|
|
11
19
|
npm install dsh-log
|
|
12
20
|
```
|
|
13
21
|
|
|
14
|
-
要求 Node 22 或更高。当前版本 `0.2.
|
|
22
|
+
要求 Node 22 或更高。当前版本 `0.2.1`,已发布到 npm 官方源(标签 `latest`;可用 `npm view dsh-log version` 自查)。
|
|
15
23
|
|
|
16
24
|
## 2. 三个入口,按运行位置选用
|
|
17
25
|
|
|
@@ -23,6 +31,8 @@ npm install dsh-log
|
|
|
23
31
|
|
|
24
32
|
`dsh-log/node` 与前两个的区别:它不碰电话层、也没有客户端转发,只有「把日志落到本地文件」以及它背后的级别规则、目录派生与失败计数。它**不决定日志写到哪**——目录由调用方传入,入口自己不读任何环境变量、也不带默认路径。
|
|
25
33
|
|
|
34
|
+
**本包不做什么**(需要这三样得在调用方自己那层做):不自动上报日志,只做本地落盘加手动导出;不自动轮转,也不自动清理旧文件。
|
|
35
|
+
|
|
26
36
|
## 2.1 独立 Node 程序怎么接(`dsh-log/node`)
|
|
27
37
|
|
|
28
38
|
```js
|
|
@@ -39,9 +49,9 @@ await log.ready // 等这一下:程序退出前日志才真的落盘
|
|
|
39
49
|
|
|
40
50
|
落点由 `cacheDir` 与标识一起决定:日志写在 `<cacheDir>/logs-your-program/2026-09-11.log`,调试开关写在 `<cacheDir>/log-switch-your-program.json`。目录不存在时入口自己建。
|
|
41
51
|
|
|
42
|
-
|
|
52
|
+
三条要知道的事:
|
|
43
53
|
|
|
44
|
-
1. **`await log.ready`
|
|
54
|
+
1. **`await log.ready` 不能省**。落盘是先入内存队列、再由约 1000 毫秒的防抖窗口异步写下去的:程序顺着事件循环自然跑完,Node 会等这个定时器,日志自己会落;但结尾调了 `process.exit()`、抛错退出或被强杀的程序,队列里还没写下去的那批就随进程消失(`warn` 与 `info` 一样会丢)。命令行工具通常在结尾显式退出,所以这条按必须处理。`log.ready` 返回时表示「前面写的每一行都已经在文件里」。
|
|
45
55
|
2. **开关每次新建时会被读回来**。独立程序每次调用都是新进程,所以入口建库时会把上次留下的开关读回来,打开的详细日志在下次调用仍然生效;写入用 `log.store.handleLogSetSwitch({ enabled: true, sampleRate: 1 })`。
|
|
46
56
|
3. **级别规则与插件侧完全一致**:错误与告警恒落盘,常驻信息落盘,其余信息与调试只在开关打开时落盘。
|
|
47
57
|
|
|
@@ -124,7 +134,10 @@ clientLog.log('info', 'my.event', { step: 'started' })
|
|
|
124
134
|
|
|
125
135
|
客户端批量转发口径(#558 冻结,复用 `CLIENT_BATCH` 常量,不另写一遍):每批最多 50 条、每 1000 毫秒发一次、单包约 128KB 或队列 100 条先到先截,裁掉的记入丢弃数。开关看门狗超时 5000 毫秒,只记一行告警,不改返回值。本地开关存在本地存储里,键名是 `dsws.debug`,形状是是否开启加采样率加版本号,默认关闭。建日志器时同步读本地做界面秒显,随后启动对账再向宿主看齐(以宿主为准)。
|
|
126
136
|
|
|
127
|
-
|
|
137
|
+
日志器的调用面(`createClientLog` 的返回对象)里,接入要用的是下面两类;对象上还有队列、开关状态等内部字段,调用处可以直接读,改开关请走第二类里的两个方法:
|
|
138
|
+
|
|
139
|
+
- 与宿主同名同参同语义的四个:是否允许记(`isEnabled`)、记一行(`log`)、立刻转发或刷盘(`flush`,客户端侧只管转发,不管落盘;调转发后约 1 秒可见、不调约 2 秒、错误与告警直通,见 INTEGRATION.md 步骤 4)、读累计丢弃数(`getDroppedCount`)。
|
|
140
|
+
- 客户端独有的两个开关动作(写开关界面时要用,最容易漏):`setLogSwitch(是否开启, 采样率)` 写开关(写成功后用请求时的采样率更新本地,不等宿主回;失败原因只给机器码),`reconcileLogSwitch()` 启动时向宿主对账(以宿主为准)。用法见 INTEGRATION.md 步骤 4 与步骤 6。
|
|
128
141
|
|
|
129
142
|
## 6. 失败语义(#558 冻结)
|
|
130
143
|
|
|
@@ -164,7 +177,7 @@ checkEventFields(manifest, 'gh.exec', ['argv0', 'cwdHash'])
|
|
|
164
177
|
checkEventCounts(manifest)
|
|
165
178
|
```
|
|
166
179
|
|
|
167
|
-
`parseEventListManifest` 验形状,`checkEventFields` 做字段白名单检查(未知事件名、未知字段键都算不通过,并把名单带回给调用方),`checkEventCounts` 做计数检查(增删事件必须同步改清单的 `counts
|
|
180
|
+
`parseEventListManifest` 验形状,`checkEventFields` 做字段白名单检查(未知事件名、未知字段键都算不通过,并把名单带回给调用方),`checkEventCounts` 做计数检查(增删事件必须同步改清单的 `counts`,否则这里变红)。本仓现行的事件对照表以 `research/489-appendix.md` 第 1 章与 `tests/verify-log-*.js` 为准,本包只给格式与检查器,不复刻那张表,免得两处对照要双写同步;条数会随票增删,查之前先看该附录,别在文档里抄一个数字。
|
|
168
181
|
|
|
169
182
|
## 8. 已知事项(#560 带走的两条 P1,本包首版行为)
|
|
170
183
|
|
|
@@ -185,7 +198,7 @@ cd packages/dsh-log && npm publish --dry-run
|
|
|
185
198
|
门禁跑法(改包后全跑,退出码全 0 才算过):
|
|
186
199
|
|
|
187
200
|
```sh
|
|
188
|
-
|
|
201
|
+
npm --prefix packages/dsh-log test
|
|
189
202
|
node tests/verify-log-artifacts.js
|
|
190
203
|
node tests/verify-log-channel.js
|
|
191
204
|
node tests/verify-log-client.js
|
|
@@ -202,9 +215,9 @@ node tests/verify-log-count.js
|
|
|
202
215
|
node tests/verify-log-fields.js
|
|
203
216
|
```
|
|
204
217
|
|
|
205
|
-
|
|
218
|
+
第一条由 `package.json` 的 `test` 脚本给出用例清单(宿主引擎、客户端引擎、事件清单、Node 程序入口四套),后 14 条是日志门禁;事件条数由 `tests/verify-log-count.js` 与 `research/489-appendix.md` 第 1 章对账,改了事件就得两处同步。有 TypeScript 环境时另跑 `npm --prefix packages/dsh-log run typecheck`。
|
|
206
219
|
|
|
207
|
-
|
|
220
|
+
包已发布到官方源(最新版本与标签用 `npm view dsh-log version` 与 `npm view dsh-log dist-tags` 自查)。再发新版本时,除了上面两步,还要按第 10 节的版本策略定版本号、把实际发布输出记进发布记录(仓库的 `packages/dsh-log/notes-publish-drill.md`),或用包目录下的发布向导脚本 `publish-wizard.sh` 走一遍完整流程(体检、登录、升版本、干跑、发布、发布后验证六段)。发布后有一件事向导不代做、但必须自己做:核对包内 `README.md` 与 `INTEGRATION.md` 跟仓库一致——发出去的是发布那一刻的文档,仓库里改的不会自动跟上。
|
|
208
221
|
|
|
209
222
|
## 10. 版本策略
|
|
210
223
|
|