@cnpinsight/cnpclawinsights 2.0.0 → 2.0.2

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/README.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  `@cnpinsight/cnpclawinsights` 是一个 OpenClaw 插件,用于把 OpenClaw 产生的 trace、log、metrics 指标通过 OTLP HTTP/Protobuf 导出到 `otel-collector`。
4
4
 
5
- 插件读取 `openclaw.json` 中的 `cnpclawinsights` 配置,配置结构参考 `diagnostics`。
5
+ 插件默认按 `plugins.entries.cnpclawinsights` 这个插件条目启用。
6
+
7
+ 最简配置只需要开启插件条目;如果你需要自定义 endpoint、日志导出、headers 等,再补 `config`。
6
8
 
7
9
  ## 安装
8
10
 
@@ -18,17 +20,80 @@ openclaw plugins install @cnpinsight/cnpclawinsights
18
20
  openclaw plugins install @cnpinsight/cnpclawinsights@2.0.0
19
21
  ```
20
22
 
23
+ ## 安装器
24
+
25
+ 如果你不想手动编辑 `openclaw.json`,可以使用安装器命令自动写入插件配置。
26
+
27
+ 最简单的方式:
28
+
29
+ ```bash
30
+ npm exec -y --package=@cnpinsight/cnpclawinsights -- \
31
+ cnpclawinsights-install \
32
+ --non-interactive
33
+ ```
34
+
35
+ 这会自动把配置写入默认的 `~/.openclaw/openclaw.json`,并生成:
36
+
37
+ ```json
38
+ {
39
+ "plugins": {
40
+ "entries": {
41
+ "cnpclawinsights": {
42
+ "enabled": true,
43
+ "config": {
44
+ "otel": {
45
+ "endpoint": "http://127.0.0.1:4318"
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ 指定 endpoint 并开启 logs:
55
+
56
+ ```bash
57
+ npm exec -y --package=@cnpinsight/cnpclawinsights -- \
58
+ cnpclawinsights-install \
59
+ --non-interactive \
60
+ --endpoint http://127.0.0.1:4318 \
61
+ --logs
62
+ ```
63
+
64
+ 指定 service name 和 header:
65
+
66
+ ```bash
67
+ npm exec -y --package=@cnpinsight/cnpclawinsights -- \
68
+ cnpclawinsights-install \
69
+ --non-interactive \
70
+ --service-name openclaw \
71
+ --header Authorization="Bearer <token>"
72
+ ```
73
+
74
+ 安装器支持的主要参数:
75
+
76
+ - `--config-path <path>`:指定 `openclaw.json` 路径
77
+ - `--endpoint <url>`:设置 OTLP endpoint
78
+ - `--service-name <name>`:设置 OTel service name
79
+ - `--logs` / `--no-logs`:开启或关闭 logs 导出
80
+ - `--traces` / `--no-traces`:开启或关闭 traces 导出
81
+ - `--metrics` / `--no-metrics`:开启或关闭 metrics 导出
82
+ - `--sample-rate <0..1>`:设置 trace 采样率
83
+ - `--flush-interval-ms <ms>`:设置导出刷新间隔
84
+ - `--header <k=v>`:追加请求头,可重复传入
85
+
21
86
  ## 最小配置
22
87
 
23
88
  在 `openclaw.json` 中添加:
24
89
 
25
90
  ```json
26
91
  {
27
- "cnpclawinsights": {
28
- "enabled": true,
29
- "otel": {
30
- "enabled": true,
31
- "endpoint": "http://127.0.0.1:4318"
92
+ "plugins": {
93
+ "entries": {
94
+ "cnpclawinsights": {
95
+ "enabled": true
96
+ }
32
97
  }
33
98
  }
34
99
  }
@@ -36,37 +101,65 @@ openclaw plugins install @cnpinsight/cnpclawinsights@2.0.0
36
101
 
37
102
  这个最小配置下:
38
103
 
104
+ - 默认 OTLP endpoint 是 `http://127.0.0.1:4318`
39
105
  - `traces` 默认开启
40
106
  - `metrics` 默认开启
41
107
  - `logs` 默认关闭
42
108
  - OTLP 协议默认使用 `http/protobuf`
43
109
 
110
+ ## 自定义配置
111
+
112
+ 如果你需要覆盖默认行为,可以继续加 `config`:
113
+
114
+ ```json
115
+ {
116
+ "plugins": {
117
+ "entries": {
118
+ "cnpclawinsights": {
119
+ "enabled": true,
120
+ "config": {
121
+ "otel": {
122
+ "endpoint": "http://127.0.0.1:4318",
123
+ "logs": true
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+ }
130
+ ```
131
+
44
132
  ## 完整配置示例
45
133
 
46
134
  ```json
47
135
  {
48
- "cnpclawinsights": {
49
- "enabled": true,
50
- "otel": {
51
- "enabled": true,
52
- "protocol": "http/protobuf",
53
- "endpoint": "http://127.0.0.1:4318",
54
- "traces": true,
55
- "metrics": true,
56
- "logs": true,
57
- "serviceName": "openclaw",
58
- "sampleRate": 1,
59
- "flushIntervalMs": 5000,
60
- "headers": {
61
- "Authorization": "Bearer <token>"
62
- },
63
- "captureContent": {
136
+ "plugins": {
137
+ "entries": {
138
+ "cnpclawinsights": {
64
139
  "enabled": true,
65
- "inputMessages": true,
66
- "outputMessages": true,
67
- "toolInputs": false,
68
- "toolOutputs": false,
69
- "systemPrompt": false
140
+ "config": {
141
+ "otel": {
142
+ "protocol": "http/protobuf",
143
+ "endpoint": "http://127.0.0.1:4318",
144
+ "traces": true,
145
+ "metrics": true,
146
+ "logs": true,
147
+ "serviceName": "openclaw",
148
+ "sampleRate": 1,
149
+ "flushIntervalMs": 5000,
150
+ "headers": {
151
+ "Authorization": "Bearer <token>"
152
+ },
153
+ "captureContent": {
154
+ "enabled": true,
155
+ "inputMessages": true,
156
+ "outputMessages": true,
157
+ "toolInputs": false,
158
+ "toolOutputs": false,
159
+ "systemPrompt": false
160
+ }
161
+ }
162
+ }
70
163
  }
71
164
  }
72
165
  }
@@ -77,14 +170,19 @@ openclaw plugins install @cnpinsight/cnpclawinsights@2.0.0
77
170
 
78
171
  ```json
79
172
  {
80
- "cnpclawinsights": {
81
- "enabled": true,
82
- "otel": {
83
- "enabled": true,
84
- "tracesEndpoint": "http://127.0.0.1:4318/v1/traces",
85
- "metricsEndpoint": "http://127.0.0.1:4318/v1/metrics",
86
- "logsEndpoint": "http://127.0.0.1:4318/v1/logs",
87
- "logs": true
173
+ "plugins": {
174
+ "entries": {
175
+ "cnpclawinsights": {
176
+ "enabled": true,
177
+ "config": {
178
+ "otel": {
179
+ "tracesEndpoint": "http://127.0.0.1:4318/v1/traces",
180
+ "metricsEndpoint": "http://127.0.0.1:4318/v1/metrics",
181
+ "logsEndpoint": "http://127.0.0.1:4318/v1/logs",
182
+ "logs": true
183
+ }
184
+ }
185
+ }
88
186
  }
89
187
  }
90
188
  }
@@ -92,85 +190,93 @@ openclaw plugins install @cnpinsight/cnpclawinsights@2.0.0
92
190
 
93
191
  ## 配置说明
94
192
 
95
- `cnpclawinsights.enabled`
193
+ `plugins.entries.cnpclawinsights.enabled`
96
194
 
97
- - 是否启用插件本身
195
+ - 是否启用这个插件条目
98
196
  - 必须为 `true`
99
197
 
100
- `cnpclawinsights.otel.enabled`
198
+ `plugins.entries.cnpclawinsights.config.enabled`
101
199
 
102
- - 是否启用 OTel 导出
103
- - 必须为 `true`
200
+ - 可选的插件内部总开关
201
+ - 不写时默认按启用处理
202
+ - 只有显式写成 `false` 才会关闭
203
+
204
+ `plugins.entries.cnpclawinsights.config.otel.enabled`
104
205
 
105
- `cnpclawinsights.otel.protocol`
206
+ - 可选的 OTel 导出开关
207
+ - 不写时默认按启用处理
208
+ - 只有显式写成 `false` 才会关闭
209
+
210
+ `plugins.entries.cnpclawinsights.config.otel.protocol`
106
211
 
107
212
  - 目前只支持 `http/protobuf`
108
213
  - 不配置时默认也是 `http/protobuf`
109
214
 
110
- `cnpclawinsights.otel.endpoint`
215
+ `plugins.entries.cnpclawinsights.config.otel.endpoint`
111
216
 
112
217
  - 通用 OTLP endpoint
113
218
  - 例如 `http://127.0.0.1:4318`
219
+ - 不配置时默认值是 `http://127.0.0.1:4318`
114
220
  - 如果不带 `/v1/traces`、`/v1/metrics`、`/v1/logs`,插件会自动补全对应路径
115
221
 
116
- `cnpclawinsights.otel.traces`
222
+ `plugins.entries.cnpclawinsights.config.otel.traces`
117
223
 
118
224
  - 是否导出 traces
119
225
  - 默认 `true`
120
226
 
121
- `cnpclawinsights.otel.metrics`
227
+ `plugins.entries.cnpclawinsights.config.otel.metrics`
122
228
 
123
229
  - 是否导出 metrics
124
230
  - 默认 `true`
125
231
 
126
- `cnpclawinsights.otel.logs`
232
+ `plugins.entries.cnpclawinsights.config.otel.logs`
127
233
 
128
234
  - 是否导出 logs
129
235
  - 默认 `false`
130
236
 
131
- `cnpclawinsights.otel.tracesEndpoint`
237
+ `plugins.entries.cnpclawinsights.config.otel.tracesEndpoint`
132
238
 
133
239
  - 单独指定 traces 导出地址
134
240
  - 优先级高于 `endpoint`
135
241
 
136
- `cnpclawinsights.otel.metricsEndpoint`
242
+ `plugins.entries.cnpclawinsights.config.otel.metricsEndpoint`
137
243
 
138
244
  - 单独指定 metrics 导出地址
139
245
  - 优先级高于 `endpoint`
140
246
 
141
- `cnpclawinsights.otel.logsEndpoint`
247
+ `plugins.entries.cnpclawinsights.config.otel.logsEndpoint`
142
248
 
143
249
  - 单独指定 logs 导出地址
144
250
  - 优先级高于 `endpoint`
145
251
 
146
- `cnpclawinsights.otel.serviceName`
252
+ `plugins.entries.cnpclawinsights.config.otel.serviceName`
147
253
 
148
254
  - OpenTelemetry service name
149
255
  - 不配置时优先读取环境变量 `OTEL_SERVICE_NAME`
150
256
  - 如果环境变量也没有,默认值是 `openclaw`
151
257
 
152
- `cnpclawinsights.otel.sampleRate`
258
+ `plugins.entries.cnpclawinsights.config.otel.sampleRate`
153
259
 
154
260
  - trace 采样率
155
261
  - 取值范围 `0` 到 `1`
156
262
 
157
- `cnpclawinsights.otel.flushIntervalMs`
263
+ `plugins.entries.cnpclawinsights.config.otel.flushIntervalMs`
158
264
 
159
265
  - metrics 周期导出间隔
160
266
  - 也用于 logs 批量刷新间隔
161
267
  - 最小值为 `1000`
162
268
 
163
- `cnpclawinsights.otel.headers`
269
+ `plugins.entries.cnpclawinsights.config.otel.headers`
164
270
 
165
271
  - OTLP 请求头
166
272
  - 适合传认证信息
167
273
 
168
- `cnpclawinsights.otel.captureContent`
274
+ `plugins.entries.cnpclawinsights.config.otel.captureContent`
169
275
 
170
276
  - 控制是否导出消息内容
171
277
  - 默认不采集正文内容
172
278
 
173
- `cnpclawinsights.otel.captureContent = true`
279
+ `plugins.entries.cnpclawinsights.config.otel.captureContent = true`
174
280
 
175
281
  - 开启后会采集:
176
282
  - `inputMessages`
@@ -179,7 +285,7 @@ openclaw plugins install @cnpinsight/cnpclawinsights@2.0.0
179
285
  - `toolOutputs`
180
286
  - `systemPrompt` 仍默认不采集
181
287
 
182
- `cnpclawinsights.otel.captureContent = { ... }`
288
+ `plugins.entries.cnpclawinsights.config.otel.captureContent = { ... }`
183
289
 
184
290
  - 可以按字段精细控制:
185
291
  - `enabled`
@@ -191,7 +297,15 @@ openclaw plugins install @cnpinsight/cnpclawinsights@2.0.0
191
297
 
192
298
  ## 环境变量回退
193
299
 
194
- 如果部分配置未写入 `openclaw.json`,插件还会回退读取这些标准 OTel 环境变量:
300
+ 如果部分配置未写入 `plugins.entries.cnpclawinsights.config`,插件会按下面的优先级取值:
301
+
302
+ 1. `config.otel` 里的显式配置
303
+ 2. 对应的标准 OTel 环境变量
304
+ 3. 插件内置默认值
305
+
306
+ 其中 endpoint 的内置默认值是 `http://127.0.0.1:4318`。
307
+
308
+ 相关环境变量包括:
195
309
 
196
310
  - `OTEL_EXPORTER_OTLP_PROTOCOL`
197
311
  - `OTEL_EXPORTER_OTLP_ENDPOINT`
@@ -218,29 +332,63 @@ openclaw plugins install @cnpinsight/cnpclawinsights@2.0.0
218
332
 
219
333
  ```json
220
334
  {
221
- "cnpclawinsights": {
222
- "enabled": true,
223
- "otel": {
224
- "enabled": true,
225
- "endpoint": "http://127.0.0.1:4318",
226
- "logs": true
335
+ "plugins": {
336
+ "entries": {
337
+ "cnpclawinsights": {
338
+ "enabled": true,
339
+ "config": {
340
+ "otel": {
341
+ "endpoint": "http://127.0.0.1:4318",
342
+ "logs": true
343
+ }
344
+ }
345
+ }
227
346
  }
228
347
  }
229
348
  }
230
349
  ```
231
350
 
232
- ### 3. 为什么配置了但没有导出
351
+ ### 3. 为什么只写了 `enabled: true` 也能工作
233
352
 
234
- 请同时确认下面两个开关都为 `true`:
353
+ 插件现在支持最简模式:
235
354
 
236
355
  ```json
237
356
  {
238
- "cnpclawinsights": {
239
- "enabled": true,
240
- "otel": {
241
- "enabled": true
357
+ "plugins": {
358
+ "entries": {
359
+ "cnpclawinsights": {
360
+ "enabled": true
361
+ }
242
362
  }
243
363
  }
244
364
  }
245
365
  ```
246
366
 
367
+ 这时会默认:
368
+
369
+ - 使用 `http/protobuf`
370
+ - 发往 `http://127.0.0.1:4318`
371
+ - 开启 traces 和 metrics
372
+ - 关闭 logs
373
+
374
+ ### 4. 为什么配置了但没有导出
375
+
376
+ 如果你显式写了下面任意一个值为 `false`,插件就不会导出:
377
+
378
+ ```json
379
+ {
380
+ "plugins": {
381
+ "entries": {
382
+ "cnpclawinsights": {
383
+ "enabled": true,
384
+ "config": {
385
+ "enabled": false,
386
+ "otel": {
387
+ "enabled": false
388
+ }
389
+ }
390
+ }
391
+ }
392
+ }
393
+ }
394
+ ```
package/dist/cli.mjs ADDED
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+
7
+ const PLUGIN_ID = "cnpclawinsights";
8
+ const LEGACY_PLUGIN_ID = "cnpclawinsight";
9
+ const DEFAULT_CONFIG_PATH = path.join(os.homedir(), ".openclaw", "openclaw.json");
10
+ const DEFAULT_ENDPOINT = "http://127.0.0.1:4318";
11
+
12
+ function printHelp() {
13
+ console.log(`Usage:
14
+ cnpclawinsights-install [options]
15
+
16
+ Options:
17
+ --config-path <path> Path to openclaw.json
18
+ --endpoint <url> OTLP endpoint, default: ${DEFAULT_ENDPOINT}
19
+ --service-name <name> OpenTelemetry service name
20
+ --logs Enable logs export
21
+ --no-logs Disable logs export
22
+ --traces Enable traces export
23
+ --no-traces Disable traces export
24
+ --metrics Enable metrics export
25
+ --no-metrics Disable metrics export
26
+ --sample-rate <0..1> Trace sampling rate
27
+ --flush-interval-ms <ms> Export flush interval
28
+ --header <k=v> Add OTLP header, repeatable
29
+ --non-interactive Run without prompts
30
+ --help Show this help
31
+ `);
32
+ }
33
+
34
+ function fail(message) {
35
+ console.error(`cnpclawinsights-install: ${message}`);
36
+ process.exit(1);
37
+ }
38
+
39
+ function parseArgs(argv) {
40
+ const options = {
41
+ configPath: DEFAULT_CONFIG_PATH,
42
+ endpoint: DEFAULT_ENDPOINT,
43
+ headers: {}
44
+ };
45
+
46
+ for (let i = 0; i < argv.length; i += 1) {
47
+ const arg = argv[i];
48
+ switch (arg) {
49
+ case "--config-path":
50
+ options.configPath = argv[++i];
51
+ break;
52
+ case "--endpoint":
53
+ options.endpoint = argv[++i];
54
+ break;
55
+ case "--service-name":
56
+ options.serviceName = argv[++i];
57
+ break;
58
+ case "--logs":
59
+ options.logs = true;
60
+ break;
61
+ case "--no-logs":
62
+ options.logs = false;
63
+ break;
64
+ case "--traces":
65
+ options.traces = true;
66
+ break;
67
+ case "--no-traces":
68
+ options.traces = false;
69
+ break;
70
+ case "--metrics":
71
+ options.metrics = true;
72
+ break;
73
+ case "--no-metrics":
74
+ options.metrics = false;
75
+ break;
76
+ case "--sample-rate":
77
+ options.sampleRate = Number(argv[++i]);
78
+ break;
79
+ case "--flush-interval-ms":
80
+ options.flushIntervalMs = Number(argv[++i]);
81
+ break;
82
+ case "--header": {
83
+ const raw = argv[++i];
84
+ const eqIndex = raw.indexOf("=");
85
+ if (eqIndex <= 0) fail(`invalid --header value: ${raw}`);
86
+ const key = raw.slice(0, eqIndex).trim();
87
+ const value = raw.slice(eqIndex + 1).trim();
88
+ if (!key || !value) fail(`invalid --header value: ${raw}`);
89
+ options.headers[key] = value;
90
+ break;
91
+ }
92
+ case "--non-interactive":
93
+ options.nonInteractive = true;
94
+ break;
95
+ case "--help":
96
+ case "-h":
97
+ options.help = true;
98
+ break;
99
+ default:
100
+ fail(`unknown argument: ${arg}`);
101
+ }
102
+ }
103
+
104
+ return options;
105
+ }
106
+
107
+ function ensureParentDir(filePath) {
108
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
109
+ }
110
+
111
+ function readConfig(configPath) {
112
+ if (!fs.existsSync(configPath)) {
113
+ return {};
114
+ }
115
+ try {
116
+ return JSON.parse(fs.readFileSync(configPath, "utf8"));
117
+ } catch (error) {
118
+ fail(`failed to parse config file ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
119
+ }
120
+ }
121
+
122
+ function normalizePluginEntry(entries) {
123
+ const pluralEntry = entries[PLUGIN_ID];
124
+ if (pluralEntry && typeof pluralEntry === "object") {
125
+ return pluralEntry;
126
+ }
127
+ const legacyEntry = entries[LEGACY_PLUGIN_ID];
128
+ if (legacyEntry && typeof legacyEntry === "object") {
129
+ delete entries[LEGACY_PLUGIN_ID];
130
+ entries[PLUGIN_ID] = legacyEntry;
131
+ return legacyEntry;
132
+ }
133
+ const entry = {};
134
+ entries[PLUGIN_ID] = entry;
135
+ return entry;
136
+ }
137
+
138
+ function buildPluginConfig(options) {
139
+ const otel = {
140
+ endpoint: options.endpoint
141
+ };
142
+
143
+ if (options.logs !== undefined) otel.logs = options.logs;
144
+ if (options.traces !== undefined) otel.traces = options.traces;
145
+ if (options.metrics !== undefined) otel.metrics = options.metrics;
146
+ if (options.serviceName) otel.serviceName = options.serviceName;
147
+ if (options.sampleRate !== undefined) otel.sampleRate = options.sampleRate;
148
+ if (options.flushIntervalMs !== undefined) otel.flushIntervalMs = options.flushIntervalMs;
149
+ if (Object.keys(options.headers).length > 0) otel.headers = options.headers;
150
+
151
+ return { otel };
152
+ }
153
+
154
+ function writeConfig(configPath, config) {
155
+ ensureParentDir(configPath);
156
+ fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf8");
157
+ }
158
+
159
+ function main() {
160
+ const options = parseArgs(process.argv.slice(2));
161
+ if (options.help) {
162
+ printHelp();
163
+ return;
164
+ }
165
+
166
+ if (options.sampleRate !== undefined && (!Number.isFinite(options.sampleRate) || options.sampleRate < 0 || options.sampleRate > 1)) {
167
+ fail("--sample-rate must be a number between 0 and 1");
168
+ }
169
+
170
+ if (options.flushIntervalMs !== undefined && (!Number.isInteger(options.flushIntervalMs) || options.flushIntervalMs < 1000)) {
171
+ fail("--flush-interval-ms must be an integer >= 1000");
172
+ }
173
+
174
+ const config = readConfig(options.configPath);
175
+ if (!config.plugins || typeof config.plugins !== "object" || Array.isArray(config.plugins)) {
176
+ config.plugins = {};
177
+ }
178
+ if (!config.plugins.entries || typeof config.plugins.entries !== "object" || Array.isArray(config.plugins.entries)) {
179
+ config.plugins.entries = {};
180
+ }
181
+ const entry = normalizePluginEntry(config.plugins.entries);
182
+ entry.enabled = true;
183
+ entry.config = {
184
+ ...(entry.config && typeof entry.config === "object" && !Array.isArray(entry.config) ? entry.config : {}),
185
+ ...buildPluginConfig(options)
186
+ };
187
+
188
+ if (!Array.isArray(config.plugins.allow)) {
189
+ config.plugins.allow = [];
190
+ }
191
+ if (!config.plugins.allow.includes(PLUGIN_ID)) {
192
+ config.plugins.allow.push(PLUGIN_ID);
193
+ }
194
+ config.plugins.allow = config.plugins.allow.filter((value, index, values) => value !== LEGACY_PLUGIN_ID || values.indexOf(PLUGIN_ID) === -1);
195
+
196
+ writeConfig(options.configPath, config);
197
+
198
+ console.log(`Updated ${options.configPath}`);
199
+ console.log(`Configured plugins.entries.${PLUGIN_ID}.enabled = true`);
200
+ console.log(`Configured plugins.entries.${PLUGIN_ID}.config.otel.endpoint = ${options.endpoint}`);
201
+ if (options.logs !== undefined) {
202
+ console.log(`Configured plugins.entries.${PLUGIN_ID}.config.otel.logs = ${String(options.logs)}`);
203
+ }
204
+ }
205
+
206
+ main();
package/dist/index.js CHANGED
@@ -44,6 +44,7 @@ const OTEL_EXPORTER_OTLP_ENDPOINT_ENV = "OTEL_EXPORTER_OTLP_ENDPOINT";
44
44
  const OTEL_EXPORTER_OTLP_TRACES_ENDPOINT_ENV = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT";
45
45
  const OTEL_EXPORTER_OTLP_METRICS_ENDPOINT_ENV = "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT";
46
46
  const OTEL_EXPORTER_OTLP_LOGS_ENDPOINT_ENV = "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT";
47
+ const DEFAULT_OTLP_HTTP_ENDPOINT = "http://127.0.0.1:4318";
47
48
  const OTEL_SEMCONV_STABILITY_OPT_IN_ENV = "OTEL_SEMCONV_STABILITY_OPT_IN";
48
49
  const GEN_AI_LATEST_EXPERIMENTAL_OPT_IN = "gen_ai_latest_experimental";
49
50
  const GEN_AI_TOKEN_USAGE_BUCKETS = [
@@ -354,9 +355,9 @@ function createDiagnosticsOtelService() {
354
355
  id: "cnpclawinsights",
355
356
  async start(ctx) {
356
357
  await stopStarted();
357
- const cfg = ctx.config.cnpclawinsights;
358
- const otel = cfg?.otel;
359
- if (!cfg?.enabled || !otel?.enabled) return;
358
+ const cfg = ctx.config?.cnpclawinsights ?? ctx.config ?? {};
359
+ const otel = cfg?.otel ?? {};
360
+ if (cfg?.enabled === false || otel.enabled === false) return;
360
361
  const emitExporterEvent = (event) => {
361
362
  try {
362
363
  ctx.internalDiagnostics?.emit({
@@ -390,7 +391,7 @@ function createDiagnosticsOtelService() {
390
391
  ctx.logger.warn(`cnpclawinsights: unsupported protocol ${protocol}`);
391
392
  return;
392
393
  }
393
- const endpoint = normalizeEndpoint(otel.endpoint ?? process.env[OTEL_EXPORTER_OTLP_ENDPOINT_ENV]);
394
+ const endpoint = normalizeEndpoint(otel.endpoint ?? process.env[OTEL_EXPORTER_OTLP_ENDPOINT_ENV] ?? DEFAULT_OTLP_HTTP_ENDPOINT);
394
395
  const headers = otel.headers ?? void 0;
395
396
  const serviceName = otel.serviceName?.trim() || process.env.OTEL_SERVICE_NAME || DEFAULT_SERVICE_NAME;
396
397
  const sampleRate = resolveSampleRate(otel.sampleRate);
package/package.json CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "@cnpinsight/cnpclawinsights",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "OpenClaw insights OpenTelemetry exporter",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/openclaw/openclaw"
8
8
  },
9
9
  "type": "module",
10
+ "bin": {
11
+ "cnpclawinsights-install": "dist/cli.mjs"
12
+ },
10
13
  "dependencies": {
11
14
  "@opentelemetry/api": "1.9.1",
12
15
  "@opentelemetry/api-logs": "0.218.0",