@longzai-intelligence-telemetry/react 0.0.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/README.md +13 -0
- package/dist/index.d.mts +564 -0
- package/dist/index.d.ts +565 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @longzai-intelligence-telemetry/react
|
|
2
|
+
|
|
3
|
+
遥测体系 L1 React Native 表面包(消费 `@longzai-intelligence-telemetry/core` 端口与契约):Logger 可插拔 listener、fetch 裸传输(无鉴权头/短超时)、SQLite outbox(结构化句柄注入,宿主传 op-sqlite 连接)、全局错误接线(ErrorUtils)、ErrorBoundary、事件常量与 TelemetryClient(分级同意门、成功才删行/毒批即弃/冷却熔断的递送协调、关闭即 purge)。
|
|
4
|
+
|
|
5
|
+
## 设计约束
|
|
6
|
+
|
|
7
|
+
- 裸传输纪律:不走业务 http 客户端、不带 Authorization、失败静默三态归类。
|
|
8
|
+
- outbox 句柄端口化:包内零原生依赖,op-sqlite 版本选择与装配由宿主壳层承担。
|
|
9
|
+
- 本包禁止使用业务 Logger(防「上报失败→错误日志→再上报」通道自激)。
|
|
10
|
+
|
|
11
|
+
## Peer 依赖
|
|
12
|
+
|
|
13
|
+
`react >= 19`、`react-native >= 0.87`(宿主提供)。
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
import { StoredTelemetryRecord, TelemetryBatchContext, TelemetryChannelKind, TelemetryClockPort, TelemetryConsent, TelemetryEventBatch, TelemetryEventEntry, TelemetryLogBatch, TelemetryLogEntry, TelemetryLogLevel, TelemetryPropertyValue, TelemetrySendResult, TelemetryStoragePort, TelemetryTransportPort } from "@longzai-intelligence-telemetry/core";
|
|
2
|
+
import { Component, ReactNode } from "react";
|
|
3
|
+
//#region src/event-names.constants.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* 遥测事件名常量表(接线点禁止裸写字符串;catalog 登记随 O4 事件目录维护)
|
|
6
|
+
*/
|
|
7
|
+
declare const TELEMETRY_EVENT_NAMES: {
|
|
8
|
+
/**
|
|
9
|
+
* 应用启动(遥测初始化补发)
|
|
10
|
+
*/
|
|
11
|
+
readonly appLaunch: 'app_launch';
|
|
12
|
+
/**
|
|
13
|
+
* 前后台切换(生命周期接线)
|
|
14
|
+
*/
|
|
15
|
+
readonly appStateChange: 'app_state_change';
|
|
16
|
+
/**
|
|
17
|
+
* JS 错误捕获(全局错误接线 / ErrorBoundary)
|
|
18
|
+
*/
|
|
19
|
+
readonly jsError: 'js_error';
|
|
20
|
+
/**
|
|
21
|
+
* 上次会话异常退出(NativeCrashMarkerPort 过渡检测)
|
|
22
|
+
*/
|
|
23
|
+
readonly previousSessionAbnormalExit: 'previous_session_abnormal_exit';
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* 合法事件名联合(track API 的 name 参数类型收窄)
|
|
27
|
+
*/
|
|
28
|
+
type TelemetryEventName = (typeof TELEMETRY_EVENT_NAMES)[keyof typeof TELEMETRY_EVENT_NAMES];
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/fetch-transport.utils.d.ts
|
|
31
|
+
/**
|
|
32
|
+
* fetch 传输配置
|
|
33
|
+
*/
|
|
34
|
+
type FetchTransportOptions = {
|
|
35
|
+
/**
|
|
36
|
+
* 服务基址(如 https://telemetry.example.com,不含尾斜杠)
|
|
37
|
+
*/
|
|
38
|
+
baseUrl: string;
|
|
39
|
+
/**
|
|
40
|
+
* 单请求超时毫秒(缺省 8000,对齐 watch 传输口径)
|
|
41
|
+
*/
|
|
42
|
+
timeoutMs?: number;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* fetch 裸传输器(实现 core TransportPort)
|
|
46
|
+
*/
|
|
47
|
+
declare class FetchTelemetryTransport implements TelemetryTransportPort {
|
|
48
|
+
/**
|
|
49
|
+
* 服务基址
|
|
50
|
+
*/
|
|
51
|
+
private readonly baseUrl;
|
|
52
|
+
/**
|
|
53
|
+
* 超时毫秒
|
|
54
|
+
*/
|
|
55
|
+
private readonly timeoutMs;
|
|
56
|
+
/**
|
|
57
|
+
* 构造传输器(记录基址与超时)。
|
|
58
|
+
*
|
|
59
|
+
* @param options - 传输配置
|
|
60
|
+
*/
|
|
61
|
+
constructor(options: FetchTransportOptions);
|
|
62
|
+
/**
|
|
63
|
+
* 发送事件批量
|
|
64
|
+
*
|
|
65
|
+
* @param batch - 事件批量上报体
|
|
66
|
+
* @returns 三态发送结果
|
|
67
|
+
*/
|
|
68
|
+
sendEventBatch(batch: TelemetryEventBatch): Promise<TelemetrySendResult>;
|
|
69
|
+
/**
|
|
70
|
+
* 发送日志批量
|
|
71
|
+
*
|
|
72
|
+
* @param batch - 日志批量上报体
|
|
73
|
+
* @returns 三态发送结果
|
|
74
|
+
*/
|
|
75
|
+
sendLogBatch(batch: TelemetryLogBatch): Promise<TelemetrySendResult>;
|
|
76
|
+
/**
|
|
77
|
+
* 单次发送(POST JSON + 超时中断;失败一律静默归类)
|
|
78
|
+
*
|
|
79
|
+
* @param path - 端点路径(core 契约端点)
|
|
80
|
+
* @param body - 批量上报体
|
|
81
|
+
* @returns 三态发送结果
|
|
82
|
+
*/
|
|
83
|
+
private send;
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/logger.utils.d.ts
|
|
87
|
+
/**
|
|
88
|
+
* 单条日志条目(listener 消费形态)
|
|
89
|
+
*/
|
|
90
|
+
type LoggerEntry = {
|
|
91
|
+
/**
|
|
92
|
+
* 日志级别
|
|
93
|
+
*/
|
|
94
|
+
level: TelemetryLogLevel;
|
|
95
|
+
/**
|
|
96
|
+
* 日志消息(Error 实例已被归一为 message + stack)
|
|
97
|
+
*/
|
|
98
|
+
message: string;
|
|
99
|
+
/**
|
|
100
|
+
* 关联堆栈(非 Error 来源为空字符串)
|
|
101
|
+
*/
|
|
102
|
+
stack: string;
|
|
103
|
+
/**
|
|
104
|
+
* 来源标签
|
|
105
|
+
*/
|
|
106
|
+
tag: string;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* 日志监听器接口(可插拔)
|
|
110
|
+
*/
|
|
111
|
+
type LoggerListener = {
|
|
112
|
+
/**
|
|
113
|
+
* 接收日志条目
|
|
114
|
+
*
|
|
115
|
+
* @param entry - 日志条目
|
|
116
|
+
*/
|
|
117
|
+
log(entry: LoggerEntry): void;
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* 日志远程镜像接收面(telemetry listener 转发目标,由 TelemetryClient 实现)
|
|
121
|
+
*/
|
|
122
|
+
type TelemetryLogSink = {
|
|
123
|
+
/**
|
|
124
|
+
* 镜像一条日志(仅 WARN+ 会被转发;FATAL 已并入 ERROR)
|
|
125
|
+
*
|
|
126
|
+
* @param entry - 已归级的日志条目
|
|
127
|
+
*/
|
|
128
|
+
mirrorLog(entry: LoggerEntry): void;
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* 归一错误结果(消息 + 堆栈)
|
|
132
|
+
*/
|
|
133
|
+
type NormalizedError = {
|
|
134
|
+
/**
|
|
135
|
+
* 归一消息
|
|
136
|
+
*/
|
|
137
|
+
message: string;
|
|
138
|
+
/**
|
|
139
|
+
* 归一堆栈(可空)
|
|
140
|
+
*/
|
|
141
|
+
stack: string;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* 退订函数形态
|
|
145
|
+
*/
|
|
146
|
+
type Unsubscribe = () => void;
|
|
147
|
+
/**
|
|
148
|
+
* 归一未知错误值为 message + stack(非 Error 形态 String 化、堆栈为空)
|
|
149
|
+
*
|
|
150
|
+
* @param value - 任意抛出值
|
|
151
|
+
* @returns 归一后的消息与堆栈
|
|
152
|
+
*/
|
|
153
|
+
declare function normalizeErrorValue(value: unknown): NormalizedError;
|
|
154
|
+
/**
|
|
155
|
+
* tagged Logger(级别分发 + 多 listener 扇出; unregister 经返回的退订函数)
|
|
156
|
+
*/
|
|
157
|
+
declare class Logger {
|
|
158
|
+
/**
|
|
159
|
+
* 来源标签
|
|
160
|
+
*/
|
|
161
|
+
private readonly tag;
|
|
162
|
+
/**
|
|
163
|
+
* 已挂载 listener 集合
|
|
164
|
+
*/
|
|
165
|
+
private readonly listeners;
|
|
166
|
+
/**
|
|
167
|
+
* 构造 tagged Logger。
|
|
168
|
+
*
|
|
169
|
+
* @param tag - 来源标签(模块/页面名)
|
|
170
|
+
*/
|
|
171
|
+
constructor(tag: string);
|
|
172
|
+
/**
|
|
173
|
+
* 挂载 listener。
|
|
174
|
+
*
|
|
175
|
+
* @param listener - 日志监听器
|
|
176
|
+
* @returns 退订函数
|
|
177
|
+
*/
|
|
178
|
+
addListener(listener: LoggerListener): Unsubscribe;
|
|
179
|
+
/**
|
|
180
|
+
* 输出 debug 级日志
|
|
181
|
+
*
|
|
182
|
+
* @param message - 消息或 Error 实例
|
|
183
|
+
*/
|
|
184
|
+
debug(message: unknown): void;
|
|
185
|
+
/**
|
|
186
|
+
* 输出 info 级日志
|
|
187
|
+
*
|
|
188
|
+
* @param message - 消息或 Error 实例
|
|
189
|
+
*/
|
|
190
|
+
info(message: unknown): void;
|
|
191
|
+
/**
|
|
192
|
+
* 输出 warn 级日志
|
|
193
|
+
*
|
|
194
|
+
* @param message - 消息或 Error 实例
|
|
195
|
+
*/
|
|
196
|
+
warn(message: unknown): void;
|
|
197
|
+
/**
|
|
198
|
+
* 输出 error 级日志
|
|
199
|
+
*
|
|
200
|
+
* @param message - 消息或 Error 实例
|
|
201
|
+
*/
|
|
202
|
+
error(message: unknown): void;
|
|
203
|
+
/**
|
|
204
|
+
* 按级别分发至全部 listener(Error 实例归一为 message + stack)
|
|
205
|
+
*
|
|
206
|
+
* @param level - 日志级别
|
|
207
|
+
* @param message - 消息或 Error 实例
|
|
208
|
+
*/
|
|
209
|
+
private dispatch;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* 创建遥测日志 listener(WARN+ 镜像至 sink;FATAL 并入 ERROR——watch 日志通道语义)
|
|
213
|
+
*
|
|
214
|
+
* @param sink - 远程镜像接收面
|
|
215
|
+
* @returns 日志监听器
|
|
216
|
+
*/
|
|
217
|
+
declare function createTelemetryLogListener(sink: TelemetryLogSink): LoggerListener;
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/global-error.utils.d.ts
|
|
220
|
+
/**
|
|
221
|
+
* RN 全局错误处理函数形态
|
|
222
|
+
*/
|
|
223
|
+
type GlobalErrorHandler = (error: unknown, isFatal: boolean) => void;
|
|
224
|
+
/**
|
|
225
|
+
* ErrorUtils 最小面(宿主可注入;缺省探测 globalThis.ErrorUtils)
|
|
226
|
+
*/
|
|
227
|
+
type ErrorUtilsLike = {
|
|
228
|
+
/**
|
|
229
|
+
* 设置全局错误处理器
|
|
230
|
+
*/
|
|
231
|
+
setGlobalHandler(handler: GlobalErrorHandler): void;
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* 捕获错误回调载荷
|
|
235
|
+
*/
|
|
236
|
+
type CapturedError = {
|
|
237
|
+
/**
|
|
238
|
+
* 归一消息
|
|
239
|
+
*/
|
|
240
|
+
message: string;
|
|
241
|
+
/**
|
|
242
|
+
* 归一堆栈(可空)
|
|
243
|
+
*/
|
|
244
|
+
stack: string;
|
|
245
|
+
/**
|
|
246
|
+
* 是否致命(RN fatal 标记)
|
|
247
|
+
*/
|
|
248
|
+
isFatal: boolean;
|
|
249
|
+
};
|
|
250
|
+
/**
|
|
251
|
+
* 接线选项
|
|
252
|
+
*/
|
|
253
|
+
type GlobalErrorWiringOptions = {
|
|
254
|
+
/**
|
|
255
|
+
* 捕获错误回调(fatal 与非 fatal 均回调)
|
|
256
|
+
*/
|
|
257
|
+
onError: (captured: CapturedError) => void;
|
|
258
|
+
/**
|
|
259
|
+
* ErrorUtils 注入(缺省探测 globalThis.ErrorUtils)
|
|
260
|
+
*/
|
|
261
|
+
errorUtils?: ErrorUtilsLike;
|
|
262
|
+
};
|
|
263
|
+
/**
|
|
264
|
+
* 接线卸载函数形态
|
|
265
|
+
*/
|
|
266
|
+
type Uninstall = () => void;
|
|
267
|
+
/**
|
|
268
|
+
* 安装全局错误接线(返回卸载函数;ErrorUtils 不可用时返回空操作卸载)。
|
|
269
|
+
*
|
|
270
|
+
* @param options - 接线选项
|
|
271
|
+
* @returns 卸载函数(回落静默空处理器)
|
|
272
|
+
*/
|
|
273
|
+
declare function installGlobalErrorHandler(options: GlobalErrorWiringOptions): Uninstall;
|
|
274
|
+
//#endregion
|
|
275
|
+
//#region src/telemetry-error-boundary.utils.d.ts
|
|
276
|
+
/**
|
|
277
|
+
* ErrorBoundary 属性
|
|
278
|
+
*/
|
|
279
|
+
type TelemetryErrorBoundaryProps = {
|
|
280
|
+
/**
|
|
281
|
+
* 子树
|
|
282
|
+
*/
|
|
283
|
+
children?: ReactNode;
|
|
284
|
+
/**
|
|
285
|
+
* 捕获后的回退 UI(缺省渲染 null)
|
|
286
|
+
*/
|
|
287
|
+
fallback?: (error: Error) => ReactNode;
|
|
288
|
+
/**
|
|
289
|
+
* 捕获回调(上报接线由此承接)
|
|
290
|
+
*/
|
|
291
|
+
onError?: (error: Error) => void;
|
|
292
|
+
};
|
|
293
|
+
/**
|
|
294
|
+
* ErrorBoundary 状态
|
|
295
|
+
*/
|
|
296
|
+
type TelemetryErrorBoundaryState = {
|
|
297
|
+
/**
|
|
298
|
+
* 是否已捕获错误
|
|
299
|
+
*/
|
|
300
|
+
hasError: boolean;
|
|
301
|
+
/**
|
|
302
|
+
* 捕获的错误实例
|
|
303
|
+
*/
|
|
304
|
+
error: Error | null;
|
|
305
|
+
};
|
|
306
|
+
/**
|
|
307
|
+
* 遥测 ErrorBoundary(渲染异常捕获 → onError 上报 + 回退 UI)
|
|
308
|
+
*/
|
|
309
|
+
declare class TelemetryErrorBoundary extends Component<TelemetryErrorBoundaryProps, TelemetryErrorBoundaryState> {
|
|
310
|
+
/**
|
|
311
|
+
* 初始状态(未捕获)
|
|
312
|
+
*/
|
|
313
|
+
state: TelemetryErrorBoundaryState;
|
|
314
|
+
/**
|
|
315
|
+
* 派生状态(渲染异常时置位)
|
|
316
|
+
*
|
|
317
|
+
* @param error - 捕获的错误
|
|
318
|
+
* @returns 捕获态状态
|
|
319
|
+
*/
|
|
320
|
+
static getDerivedStateFromError(error: Error): TelemetryErrorBoundaryState;
|
|
321
|
+
/**
|
|
322
|
+
* 捕获回调(上报接线)
|
|
323
|
+
*
|
|
324
|
+
* @param error - 捕获的错误
|
|
325
|
+
*/
|
|
326
|
+
componentDidCatch(error: Error): void;
|
|
327
|
+
/**
|
|
328
|
+
* 渲染(捕获后渲染回退 UI,否则渲染子树)
|
|
329
|
+
*
|
|
330
|
+
* @returns 当前渲染节点
|
|
331
|
+
*/
|
|
332
|
+
render(): ReactNode;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* ErrorBoundary 元素工厂(壳层 createElement 别名,便于无 JSX 接线)
|
|
336
|
+
*
|
|
337
|
+
* @param props - ErrorBoundary 属性
|
|
338
|
+
* @returns React 元素
|
|
339
|
+
*/
|
|
340
|
+
declare function createTelemetryErrorBoundaryElement(props: TelemetryErrorBoundaryProps): ReactNode;
|
|
341
|
+
//#endregion
|
|
342
|
+
//#region src/telemetry-client.utils.d.ts
|
|
343
|
+
/**
|
|
344
|
+
* 客户端依赖端口集合
|
|
345
|
+
*/
|
|
346
|
+
type TelemetryClientPorts = {
|
|
347
|
+
/**
|
|
348
|
+
* 持久存储端口(outbox 载体)
|
|
349
|
+
*/
|
|
350
|
+
storage: TelemetryStoragePort;
|
|
351
|
+
/**
|
|
352
|
+
* 时钟端口
|
|
353
|
+
*/
|
|
354
|
+
clock: TelemetryClockPort;
|
|
355
|
+
/**
|
|
356
|
+
* 传输端口(裸传输)
|
|
357
|
+
*/
|
|
358
|
+
transport: TelemetryTransportPort;
|
|
359
|
+
};
|
|
360
|
+
/**
|
|
361
|
+
* 客户端选项
|
|
362
|
+
*/
|
|
363
|
+
type TelemetryClientOptions = {
|
|
364
|
+
/**
|
|
365
|
+
* 初始同意状态(缺省为 O-2 推荐口径默认值)
|
|
366
|
+
*/
|
|
367
|
+
consent?: TelemetryConsent;
|
|
368
|
+
/**
|
|
369
|
+
* 递送档位标识(缺省 lossless)
|
|
370
|
+
*/
|
|
371
|
+
deliveryMode?: 'lossless' | 'balanced' | 'lite';
|
|
372
|
+
/**
|
|
373
|
+
* 单批装载条数(缺省 100,契约批上限内)
|
|
374
|
+
*/
|
|
375
|
+
batchEntries?: number;
|
|
376
|
+
};
|
|
377
|
+
/**
|
|
378
|
+
* 单次冲刷结果
|
|
379
|
+
*/
|
|
380
|
+
type TelemetryFlushOutcome = {
|
|
381
|
+
/**
|
|
382
|
+
* 成功送出的事件批数
|
|
383
|
+
*/
|
|
384
|
+
eventBatchesSent: number;
|
|
385
|
+
/**
|
|
386
|
+
* 成功送出的日志批数
|
|
387
|
+
*/
|
|
388
|
+
logBatchesSent: number;
|
|
389
|
+
/**
|
|
390
|
+
* 是否因失败冷却被整轮跳过
|
|
391
|
+
*/
|
|
392
|
+
blockedByCooldown: boolean;
|
|
393
|
+
};
|
|
394
|
+
/**
|
|
395
|
+
* 遥测客户端(端侧装配核心:track / captureError / mirrorLog / flushOnce / setConsent)
|
|
396
|
+
*/
|
|
397
|
+
declare class TelemetryClient {
|
|
398
|
+
/**
|
|
399
|
+
* 依赖端口
|
|
400
|
+
*/
|
|
401
|
+
private readonly ports;
|
|
402
|
+
/**
|
|
403
|
+
* 会话批次上下文(batchedAt 每轮冲刷刷新)
|
|
404
|
+
*/
|
|
405
|
+
private readonly context;
|
|
406
|
+
/**
|
|
407
|
+
* 递送档位参数面
|
|
408
|
+
*/
|
|
409
|
+
private readonly profile;
|
|
410
|
+
/**
|
|
411
|
+
* 单批装载条数
|
|
412
|
+
*/
|
|
413
|
+
private readonly batchEntries;
|
|
414
|
+
/**
|
|
415
|
+
* 当前同意状态
|
|
416
|
+
*/
|
|
417
|
+
private consent;
|
|
418
|
+
/**
|
|
419
|
+
* 发送冷却状态
|
|
420
|
+
*/
|
|
421
|
+
private cooldown;
|
|
422
|
+
/**
|
|
423
|
+
* 构造客户端(装配端口、上下文、档位与同意初值)。
|
|
424
|
+
*
|
|
425
|
+
* @param ports - 依赖端口集合
|
|
426
|
+
* @param context - 会话批次上下文
|
|
427
|
+
* @param options - 客户端选项
|
|
428
|
+
*/
|
|
429
|
+
constructor(ports: TelemetryClientPorts, context: TelemetryBatchContext, options?: TelemetryClientOptions);
|
|
430
|
+
/**
|
|
431
|
+
* 行为事件上报(事件通道经同意门 + 属性封闭字段集清洗)
|
|
432
|
+
*
|
|
433
|
+
* @param name - 事件名(常量表联合类型,禁止裸写字符串)
|
|
434
|
+
* @param properties - 事件属性
|
|
435
|
+
* @param allowedKeys - 属性白名单(缺省为属性键集合自身)
|
|
436
|
+
*/
|
|
437
|
+
track(name: TelemetryEventName, properties?: Record<string, TelemetryPropertyValue>, allowedKeys?: readonly string[]): Promise<void>;
|
|
438
|
+
/**
|
|
439
|
+
* 错误捕获(崩溃通道:日志条目 + js_error 事件条目双落)
|
|
440
|
+
*
|
|
441
|
+
* @param error - 捕获的未知抛出值
|
|
442
|
+
* @param captureOptions - 捕获选项
|
|
443
|
+
*/
|
|
444
|
+
captureError(error: unknown, captureOptions?: {
|
|
445
|
+
isFatal?: boolean;
|
|
446
|
+
tag?: string;
|
|
447
|
+
}): Promise<void>;
|
|
448
|
+
/**
|
|
449
|
+
* 日志远程镜像(WARN+ 且崩溃通道开启时落日志通道;Logger listener 的 sink 承接)
|
|
450
|
+
*
|
|
451
|
+
* @param level - 已归级日志级别(fatal 已并入 error)
|
|
452
|
+
* @param message - 日志消息
|
|
453
|
+
* @param stack - 关联堆栈
|
|
454
|
+
* @param tag - 来源标签
|
|
455
|
+
*/
|
|
456
|
+
mirrorLog(level: TelemetryLogLevel, message: string, stack: string, tag: string): Promise<void>;
|
|
457
|
+
/**
|
|
458
|
+
* 更新同意状态(任一通道关闭即整库 purge——关闭不留存口径)
|
|
459
|
+
*
|
|
460
|
+
* @param consent - 新同意状态
|
|
461
|
+
*/
|
|
462
|
+
setConsent(consent: TelemetryConsent): Promise<void>;
|
|
463
|
+
/**
|
|
464
|
+
* 单轮冲刷(双通道批量装载 → 裸传输 → 成功删行 / 拒绝即弃 / 可重试熔断冷却)
|
|
465
|
+
*
|
|
466
|
+
* @returns 冲刷结果
|
|
467
|
+
*/
|
|
468
|
+
flushOnce(): Promise<TelemetryFlushOutcome>;
|
|
469
|
+
/**
|
|
470
|
+
* 单通道递送一轮(至多 maxBatchesPerRun 批;可重试失败熔断并登记冷却)
|
|
471
|
+
*
|
|
472
|
+
* @param channel - 通道
|
|
473
|
+
* @param nowMs - 本轮基准时间
|
|
474
|
+
* @returns 通道轮结果
|
|
475
|
+
*/
|
|
476
|
+
private runChannel;
|
|
477
|
+
/**
|
|
478
|
+
* 装配并发送单批(按通道选装配器;batchedAt 刷新为本轮时间)
|
|
479
|
+
*
|
|
480
|
+
* @param channel - 通道
|
|
481
|
+
* @param records - 装载记录
|
|
482
|
+
* @param nowMs - 本轮基准时间
|
|
483
|
+
* @returns 三态发送结果
|
|
484
|
+
*/
|
|
485
|
+
private sendChannelBatch;
|
|
486
|
+
}
|
|
487
|
+
//#endregion
|
|
488
|
+
//#region src/sqlite-outbox.utils.d.ts
|
|
489
|
+
/**
|
|
490
|
+
* SQLite 执行结果(对齐 op-sqlite execute 返回形态)
|
|
491
|
+
*/
|
|
492
|
+
type SqliteExecuteResult = {
|
|
493
|
+
/**
|
|
494
|
+
* 查询行集合(写入语句为空)
|
|
495
|
+
*/
|
|
496
|
+
rows?: Record<string, unknown>[];
|
|
497
|
+
/**
|
|
498
|
+
* 插入语句分配的自增行号
|
|
499
|
+
*/
|
|
500
|
+
insertId?: number;
|
|
501
|
+
};
|
|
502
|
+
/**
|
|
503
|
+
* SQLite 句柄(结构化端口:宿主传入 op-sqlite 连接即可)
|
|
504
|
+
*/
|
|
505
|
+
type SqliteDbHandle = {
|
|
506
|
+
/**
|
|
507
|
+
* 执行 SQL(参数绑定)
|
|
508
|
+
*
|
|
509
|
+
* @param sql - SQL 文本
|
|
510
|
+
* @param params - 绑定参数
|
|
511
|
+
*/
|
|
512
|
+
execute(sql: string, params?: unknown[]): SqliteExecuteResult;
|
|
513
|
+
};
|
|
514
|
+
/**
|
|
515
|
+
* SQLite outbox(写穿落库、按行号序装载、成功才删行由调用方(TelemetryClient)承接)
|
|
516
|
+
*/
|
|
517
|
+
declare class SqliteOutbox implements TelemetryStoragePort {
|
|
518
|
+
/**
|
|
519
|
+
* SQLite 句柄(宿主注入)
|
|
520
|
+
*/
|
|
521
|
+
private readonly handle;
|
|
522
|
+
/**
|
|
523
|
+
* 构造 outbox(建表幂等)。
|
|
524
|
+
*
|
|
525
|
+
* @param handle - SQLite 句柄(op-sqlite 连接或测试替身)
|
|
526
|
+
*/
|
|
527
|
+
constructor(handle: SqliteDbHandle);
|
|
528
|
+
/**
|
|
529
|
+
* 追加条目
|
|
530
|
+
*
|
|
531
|
+
* @param channel - 通道
|
|
532
|
+
* @param entry - 条目载荷
|
|
533
|
+
* @returns 分配的行号(句柄未回传时为 0)
|
|
534
|
+
*/
|
|
535
|
+
append(channel: TelemetryChannelKind, entry: TelemetryEventEntry | TelemetryLogEntry): Promise<number>;
|
|
536
|
+
/**
|
|
537
|
+
* 按行号序装载一批(载荷损坏行自愈跳过——毒行防御)
|
|
538
|
+
*
|
|
539
|
+
* @param channel - 通道
|
|
540
|
+
* @param maxEntries - 单批上限
|
|
541
|
+
* @returns 装载记录集合
|
|
542
|
+
*/
|
|
543
|
+
loadBatch(channel: TelemetryChannelKind, maxEntries: number): Promise<StoredTelemetryRecord[]>;
|
|
544
|
+
/**
|
|
545
|
+
* 删除指定行(成功后调用——至少一次语义的删行侧)
|
|
546
|
+
*
|
|
547
|
+
* @param channel - 通道
|
|
548
|
+
* @param ids - 行号集合
|
|
549
|
+
*/
|
|
550
|
+
deleteRecords(channel: TelemetryChannelKind, ids: readonly number[]): Promise<void>;
|
|
551
|
+
/**
|
|
552
|
+
* 清空全部通道(同意关闭即 purge)
|
|
553
|
+
*/
|
|
554
|
+
purgeAll(): Promise<void>;
|
|
555
|
+
/**
|
|
556
|
+
* 统计行数
|
|
557
|
+
*
|
|
558
|
+
* @param channel - 通道
|
|
559
|
+
* @returns 行数
|
|
560
|
+
*/
|
|
561
|
+
count(channel: TelemetryChannelKind): Promise<number>;
|
|
562
|
+
}
|
|
563
|
+
//#endregion
|
|
564
|
+
export { type CapturedError, type ErrorUtilsLike, FetchTelemetryTransport, type FetchTransportOptions, type GlobalErrorHandler, type GlobalErrorWiringOptions, Logger, type LoggerEntry, type LoggerListener, type NormalizedError, type SqliteDbHandle, type SqliteExecuteResult, SqliteOutbox, TELEMETRY_EVENT_NAMES, TelemetryClient, type TelemetryClientOptions, type TelemetryClientPorts, TelemetryErrorBoundary, type TelemetryErrorBoundaryProps, type TelemetryEventName, type TelemetryFlushOutcome, type TelemetryLogSink, type Uninstall, type Unsubscribe, createTelemetryErrorBoundaryElement, createTelemetryLogListener, installGlobalErrorHandler, normalizeErrorValue };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
import "./rolldown-runtime-B7xKLgmA.js";
|
|
2
|
+
import { StoredTelemetryRecord, TelemetryBatchContext, TelemetryChannelKind, TelemetryClockPort, TelemetryConsent, TelemetryEventBatch, TelemetryEventEntry, TelemetryLogBatch, TelemetryLogEntry, TelemetryLogLevel, TelemetryPropertyValue, TelemetrySendResult, TelemetryStoragePort, TelemetryTransportPort } from "@longzai-intelligence-telemetry/core";
|
|
3
|
+
import { Component, ReactNode } from "react";
|
|
4
|
+
//#region src/event-names.constants.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* 遥测事件名常量表(接线点禁止裸写字符串;catalog 登记随 O4 事件目录维护)
|
|
7
|
+
*/
|
|
8
|
+
declare const TELEMETRY_EVENT_NAMES: {
|
|
9
|
+
/**
|
|
10
|
+
* 应用启动(遥测初始化补发)
|
|
11
|
+
*/
|
|
12
|
+
readonly appLaunch: 'app_launch';
|
|
13
|
+
/**
|
|
14
|
+
* 前后台切换(生命周期接线)
|
|
15
|
+
*/
|
|
16
|
+
readonly appStateChange: 'app_state_change';
|
|
17
|
+
/**
|
|
18
|
+
* JS 错误捕获(全局错误接线 / ErrorBoundary)
|
|
19
|
+
*/
|
|
20
|
+
readonly jsError: 'js_error';
|
|
21
|
+
/**
|
|
22
|
+
* 上次会话异常退出(NativeCrashMarkerPort 过渡检测)
|
|
23
|
+
*/
|
|
24
|
+
readonly previousSessionAbnormalExit: 'previous_session_abnormal_exit';
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* 合法事件名联合(track API 的 name 参数类型收窄)
|
|
28
|
+
*/
|
|
29
|
+
type TelemetryEventName = (typeof TELEMETRY_EVENT_NAMES)[keyof typeof TELEMETRY_EVENT_NAMES];
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/fetch-transport.utils.d.ts
|
|
32
|
+
/**
|
|
33
|
+
* fetch 传输配置
|
|
34
|
+
*/
|
|
35
|
+
type FetchTransportOptions = {
|
|
36
|
+
/**
|
|
37
|
+
* 服务基址(如 https://telemetry.example.com,不含尾斜杠)
|
|
38
|
+
*/
|
|
39
|
+
baseUrl: string;
|
|
40
|
+
/**
|
|
41
|
+
* 单请求超时毫秒(缺省 8000,对齐 watch 传输口径)
|
|
42
|
+
*/
|
|
43
|
+
timeoutMs?: number;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* fetch 裸传输器(实现 core TransportPort)
|
|
47
|
+
*/
|
|
48
|
+
declare class FetchTelemetryTransport implements TelemetryTransportPort {
|
|
49
|
+
/**
|
|
50
|
+
* 服务基址
|
|
51
|
+
*/
|
|
52
|
+
private readonly baseUrl;
|
|
53
|
+
/**
|
|
54
|
+
* 超时毫秒
|
|
55
|
+
*/
|
|
56
|
+
private readonly timeoutMs;
|
|
57
|
+
/**
|
|
58
|
+
* 构造传输器(记录基址与超时)。
|
|
59
|
+
*
|
|
60
|
+
* @param options - 传输配置
|
|
61
|
+
*/
|
|
62
|
+
constructor(options: FetchTransportOptions);
|
|
63
|
+
/**
|
|
64
|
+
* 发送事件批量
|
|
65
|
+
*
|
|
66
|
+
* @param batch - 事件批量上报体
|
|
67
|
+
* @returns 三态发送结果
|
|
68
|
+
*/
|
|
69
|
+
sendEventBatch(batch: TelemetryEventBatch): Promise<TelemetrySendResult>;
|
|
70
|
+
/**
|
|
71
|
+
* 发送日志批量
|
|
72
|
+
*
|
|
73
|
+
* @param batch - 日志批量上报体
|
|
74
|
+
* @returns 三态发送结果
|
|
75
|
+
*/
|
|
76
|
+
sendLogBatch(batch: TelemetryLogBatch): Promise<TelemetrySendResult>;
|
|
77
|
+
/**
|
|
78
|
+
* 单次发送(POST JSON + 超时中断;失败一律静默归类)
|
|
79
|
+
*
|
|
80
|
+
* @param path - 端点路径(core 契约端点)
|
|
81
|
+
* @param body - 批量上报体
|
|
82
|
+
* @returns 三态发送结果
|
|
83
|
+
*/
|
|
84
|
+
private send;
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/logger.utils.d.ts
|
|
88
|
+
/**
|
|
89
|
+
* 单条日志条目(listener 消费形态)
|
|
90
|
+
*/
|
|
91
|
+
type LoggerEntry = {
|
|
92
|
+
/**
|
|
93
|
+
* 日志级别
|
|
94
|
+
*/
|
|
95
|
+
level: TelemetryLogLevel;
|
|
96
|
+
/**
|
|
97
|
+
* 日志消息(Error 实例已被归一为 message + stack)
|
|
98
|
+
*/
|
|
99
|
+
message: string;
|
|
100
|
+
/**
|
|
101
|
+
* 关联堆栈(非 Error 来源为空字符串)
|
|
102
|
+
*/
|
|
103
|
+
stack: string;
|
|
104
|
+
/**
|
|
105
|
+
* 来源标签
|
|
106
|
+
*/
|
|
107
|
+
tag: string;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* 日志监听器接口(可插拔)
|
|
111
|
+
*/
|
|
112
|
+
type LoggerListener = {
|
|
113
|
+
/**
|
|
114
|
+
* 接收日志条目
|
|
115
|
+
*
|
|
116
|
+
* @param entry - 日志条目
|
|
117
|
+
*/
|
|
118
|
+
log(entry: LoggerEntry): void;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* 日志远程镜像接收面(telemetry listener 转发目标,由 TelemetryClient 实现)
|
|
122
|
+
*/
|
|
123
|
+
type TelemetryLogSink = {
|
|
124
|
+
/**
|
|
125
|
+
* 镜像一条日志(仅 WARN+ 会被转发;FATAL 已并入 ERROR)
|
|
126
|
+
*
|
|
127
|
+
* @param entry - 已归级的日志条目
|
|
128
|
+
*/
|
|
129
|
+
mirrorLog(entry: LoggerEntry): void;
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* 归一错误结果(消息 + 堆栈)
|
|
133
|
+
*/
|
|
134
|
+
type NormalizedError = {
|
|
135
|
+
/**
|
|
136
|
+
* 归一消息
|
|
137
|
+
*/
|
|
138
|
+
message: string;
|
|
139
|
+
/**
|
|
140
|
+
* 归一堆栈(可空)
|
|
141
|
+
*/
|
|
142
|
+
stack: string;
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* 退订函数形态
|
|
146
|
+
*/
|
|
147
|
+
type Unsubscribe = () => void;
|
|
148
|
+
/**
|
|
149
|
+
* 归一未知错误值为 message + stack(非 Error 形态 String 化、堆栈为空)
|
|
150
|
+
*
|
|
151
|
+
* @param value - 任意抛出值
|
|
152
|
+
* @returns 归一后的消息与堆栈
|
|
153
|
+
*/
|
|
154
|
+
declare function normalizeErrorValue(value: unknown): NormalizedError;
|
|
155
|
+
/**
|
|
156
|
+
* tagged Logger(级别分发 + 多 listener 扇出; unregister 经返回的退订函数)
|
|
157
|
+
*/
|
|
158
|
+
declare class Logger {
|
|
159
|
+
/**
|
|
160
|
+
* 来源标签
|
|
161
|
+
*/
|
|
162
|
+
private readonly tag;
|
|
163
|
+
/**
|
|
164
|
+
* 已挂载 listener 集合
|
|
165
|
+
*/
|
|
166
|
+
private readonly listeners;
|
|
167
|
+
/**
|
|
168
|
+
* 构造 tagged Logger。
|
|
169
|
+
*
|
|
170
|
+
* @param tag - 来源标签(模块/页面名)
|
|
171
|
+
*/
|
|
172
|
+
constructor(tag: string);
|
|
173
|
+
/**
|
|
174
|
+
* 挂载 listener。
|
|
175
|
+
*
|
|
176
|
+
* @param listener - 日志监听器
|
|
177
|
+
* @returns 退订函数
|
|
178
|
+
*/
|
|
179
|
+
addListener(listener: LoggerListener): Unsubscribe;
|
|
180
|
+
/**
|
|
181
|
+
* 输出 debug 级日志
|
|
182
|
+
*
|
|
183
|
+
* @param message - 消息或 Error 实例
|
|
184
|
+
*/
|
|
185
|
+
debug(message: unknown): void;
|
|
186
|
+
/**
|
|
187
|
+
* 输出 info 级日志
|
|
188
|
+
*
|
|
189
|
+
* @param message - 消息或 Error 实例
|
|
190
|
+
*/
|
|
191
|
+
info(message: unknown): void;
|
|
192
|
+
/**
|
|
193
|
+
* 输出 warn 级日志
|
|
194
|
+
*
|
|
195
|
+
* @param message - 消息或 Error 实例
|
|
196
|
+
*/
|
|
197
|
+
warn(message: unknown): void;
|
|
198
|
+
/**
|
|
199
|
+
* 输出 error 级日志
|
|
200
|
+
*
|
|
201
|
+
* @param message - 消息或 Error 实例
|
|
202
|
+
*/
|
|
203
|
+
error(message: unknown): void;
|
|
204
|
+
/**
|
|
205
|
+
* 按级别分发至全部 listener(Error 实例归一为 message + stack)
|
|
206
|
+
*
|
|
207
|
+
* @param level - 日志级别
|
|
208
|
+
* @param message - 消息或 Error 实例
|
|
209
|
+
*/
|
|
210
|
+
private dispatch;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* 创建遥测日志 listener(WARN+ 镜像至 sink;FATAL 并入 ERROR——watch 日志通道语义)
|
|
214
|
+
*
|
|
215
|
+
* @param sink - 远程镜像接收面
|
|
216
|
+
* @returns 日志监听器
|
|
217
|
+
*/
|
|
218
|
+
declare function createTelemetryLogListener(sink: TelemetryLogSink): LoggerListener;
|
|
219
|
+
//#endregion
|
|
220
|
+
//#region src/global-error.utils.d.ts
|
|
221
|
+
/**
|
|
222
|
+
* RN 全局错误处理函数形态
|
|
223
|
+
*/
|
|
224
|
+
type GlobalErrorHandler = (error: unknown, isFatal: boolean) => void;
|
|
225
|
+
/**
|
|
226
|
+
* ErrorUtils 最小面(宿主可注入;缺省探测 globalThis.ErrorUtils)
|
|
227
|
+
*/
|
|
228
|
+
type ErrorUtilsLike = {
|
|
229
|
+
/**
|
|
230
|
+
* 设置全局错误处理器
|
|
231
|
+
*/
|
|
232
|
+
setGlobalHandler(handler: GlobalErrorHandler): void;
|
|
233
|
+
};
|
|
234
|
+
/**
|
|
235
|
+
* 捕获错误回调载荷
|
|
236
|
+
*/
|
|
237
|
+
type CapturedError = {
|
|
238
|
+
/**
|
|
239
|
+
* 归一消息
|
|
240
|
+
*/
|
|
241
|
+
message: string;
|
|
242
|
+
/**
|
|
243
|
+
* 归一堆栈(可空)
|
|
244
|
+
*/
|
|
245
|
+
stack: string;
|
|
246
|
+
/**
|
|
247
|
+
* 是否致命(RN fatal 标记)
|
|
248
|
+
*/
|
|
249
|
+
isFatal: boolean;
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* 接线选项
|
|
253
|
+
*/
|
|
254
|
+
type GlobalErrorWiringOptions = {
|
|
255
|
+
/**
|
|
256
|
+
* 捕获错误回调(fatal 与非 fatal 均回调)
|
|
257
|
+
*/
|
|
258
|
+
onError: (captured: CapturedError) => void;
|
|
259
|
+
/**
|
|
260
|
+
* ErrorUtils 注入(缺省探测 globalThis.ErrorUtils)
|
|
261
|
+
*/
|
|
262
|
+
errorUtils?: ErrorUtilsLike;
|
|
263
|
+
};
|
|
264
|
+
/**
|
|
265
|
+
* 接线卸载函数形态
|
|
266
|
+
*/
|
|
267
|
+
type Uninstall = () => void;
|
|
268
|
+
/**
|
|
269
|
+
* 安装全局错误接线(返回卸载函数;ErrorUtils 不可用时返回空操作卸载)。
|
|
270
|
+
*
|
|
271
|
+
* @param options - 接线选项
|
|
272
|
+
* @returns 卸载函数(回落静默空处理器)
|
|
273
|
+
*/
|
|
274
|
+
declare function installGlobalErrorHandler(options: GlobalErrorWiringOptions): Uninstall;
|
|
275
|
+
//#endregion
|
|
276
|
+
//#region src/telemetry-error-boundary.utils.d.ts
|
|
277
|
+
/**
|
|
278
|
+
* ErrorBoundary 属性
|
|
279
|
+
*/
|
|
280
|
+
type TelemetryErrorBoundaryProps = {
|
|
281
|
+
/**
|
|
282
|
+
* 子树
|
|
283
|
+
*/
|
|
284
|
+
children?: ReactNode;
|
|
285
|
+
/**
|
|
286
|
+
* 捕获后的回退 UI(缺省渲染 null)
|
|
287
|
+
*/
|
|
288
|
+
fallback?: (error: Error) => ReactNode;
|
|
289
|
+
/**
|
|
290
|
+
* 捕获回调(上报接线由此承接)
|
|
291
|
+
*/
|
|
292
|
+
onError?: (error: Error) => void;
|
|
293
|
+
};
|
|
294
|
+
/**
|
|
295
|
+
* ErrorBoundary 状态
|
|
296
|
+
*/
|
|
297
|
+
type TelemetryErrorBoundaryState = {
|
|
298
|
+
/**
|
|
299
|
+
* 是否已捕获错误
|
|
300
|
+
*/
|
|
301
|
+
hasError: boolean;
|
|
302
|
+
/**
|
|
303
|
+
* 捕获的错误实例
|
|
304
|
+
*/
|
|
305
|
+
error: Error | null;
|
|
306
|
+
};
|
|
307
|
+
/**
|
|
308
|
+
* 遥测 ErrorBoundary(渲染异常捕获 → onError 上报 + 回退 UI)
|
|
309
|
+
*/
|
|
310
|
+
declare class TelemetryErrorBoundary extends Component<TelemetryErrorBoundaryProps, TelemetryErrorBoundaryState> {
|
|
311
|
+
/**
|
|
312
|
+
* 初始状态(未捕获)
|
|
313
|
+
*/
|
|
314
|
+
state: TelemetryErrorBoundaryState;
|
|
315
|
+
/**
|
|
316
|
+
* 派生状态(渲染异常时置位)
|
|
317
|
+
*
|
|
318
|
+
* @param error - 捕获的错误
|
|
319
|
+
* @returns 捕获态状态
|
|
320
|
+
*/
|
|
321
|
+
static getDerivedStateFromError(error: Error): TelemetryErrorBoundaryState;
|
|
322
|
+
/**
|
|
323
|
+
* 捕获回调(上报接线)
|
|
324
|
+
*
|
|
325
|
+
* @param error - 捕获的错误
|
|
326
|
+
*/
|
|
327
|
+
componentDidCatch(error: Error): void;
|
|
328
|
+
/**
|
|
329
|
+
* 渲染(捕获后渲染回退 UI,否则渲染子树)
|
|
330
|
+
*
|
|
331
|
+
* @returns 当前渲染节点
|
|
332
|
+
*/
|
|
333
|
+
render(): ReactNode;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* ErrorBoundary 元素工厂(壳层 createElement 别名,便于无 JSX 接线)
|
|
337
|
+
*
|
|
338
|
+
* @param props - ErrorBoundary 属性
|
|
339
|
+
* @returns React 元素
|
|
340
|
+
*/
|
|
341
|
+
declare function createTelemetryErrorBoundaryElement(props: TelemetryErrorBoundaryProps): ReactNode;
|
|
342
|
+
//#endregion
|
|
343
|
+
//#region src/telemetry-client.utils.d.ts
|
|
344
|
+
/**
|
|
345
|
+
* 客户端依赖端口集合
|
|
346
|
+
*/
|
|
347
|
+
type TelemetryClientPorts = {
|
|
348
|
+
/**
|
|
349
|
+
* 持久存储端口(outbox 载体)
|
|
350
|
+
*/
|
|
351
|
+
storage: TelemetryStoragePort;
|
|
352
|
+
/**
|
|
353
|
+
* 时钟端口
|
|
354
|
+
*/
|
|
355
|
+
clock: TelemetryClockPort;
|
|
356
|
+
/**
|
|
357
|
+
* 传输端口(裸传输)
|
|
358
|
+
*/
|
|
359
|
+
transport: TelemetryTransportPort;
|
|
360
|
+
};
|
|
361
|
+
/**
|
|
362
|
+
* 客户端选项
|
|
363
|
+
*/
|
|
364
|
+
type TelemetryClientOptions = {
|
|
365
|
+
/**
|
|
366
|
+
* 初始同意状态(缺省为 O-2 推荐口径默认值)
|
|
367
|
+
*/
|
|
368
|
+
consent?: TelemetryConsent;
|
|
369
|
+
/**
|
|
370
|
+
* 递送档位标识(缺省 lossless)
|
|
371
|
+
*/
|
|
372
|
+
deliveryMode?: 'lossless' | 'balanced' | 'lite';
|
|
373
|
+
/**
|
|
374
|
+
* 单批装载条数(缺省 100,契约批上限内)
|
|
375
|
+
*/
|
|
376
|
+
batchEntries?: number;
|
|
377
|
+
};
|
|
378
|
+
/**
|
|
379
|
+
* 单次冲刷结果
|
|
380
|
+
*/
|
|
381
|
+
type TelemetryFlushOutcome = {
|
|
382
|
+
/**
|
|
383
|
+
* 成功送出的事件批数
|
|
384
|
+
*/
|
|
385
|
+
eventBatchesSent: number;
|
|
386
|
+
/**
|
|
387
|
+
* 成功送出的日志批数
|
|
388
|
+
*/
|
|
389
|
+
logBatchesSent: number;
|
|
390
|
+
/**
|
|
391
|
+
* 是否因失败冷却被整轮跳过
|
|
392
|
+
*/
|
|
393
|
+
blockedByCooldown: boolean;
|
|
394
|
+
};
|
|
395
|
+
/**
|
|
396
|
+
* 遥测客户端(端侧装配核心:track / captureError / mirrorLog / flushOnce / setConsent)
|
|
397
|
+
*/
|
|
398
|
+
declare class TelemetryClient {
|
|
399
|
+
/**
|
|
400
|
+
* 依赖端口
|
|
401
|
+
*/
|
|
402
|
+
private readonly ports;
|
|
403
|
+
/**
|
|
404
|
+
* 会话批次上下文(batchedAt 每轮冲刷刷新)
|
|
405
|
+
*/
|
|
406
|
+
private readonly context;
|
|
407
|
+
/**
|
|
408
|
+
* 递送档位参数面
|
|
409
|
+
*/
|
|
410
|
+
private readonly profile;
|
|
411
|
+
/**
|
|
412
|
+
* 单批装载条数
|
|
413
|
+
*/
|
|
414
|
+
private readonly batchEntries;
|
|
415
|
+
/**
|
|
416
|
+
* 当前同意状态
|
|
417
|
+
*/
|
|
418
|
+
private consent;
|
|
419
|
+
/**
|
|
420
|
+
* 发送冷却状态
|
|
421
|
+
*/
|
|
422
|
+
private cooldown;
|
|
423
|
+
/**
|
|
424
|
+
* 构造客户端(装配端口、上下文、档位与同意初值)。
|
|
425
|
+
*
|
|
426
|
+
* @param ports - 依赖端口集合
|
|
427
|
+
* @param context - 会话批次上下文
|
|
428
|
+
* @param options - 客户端选项
|
|
429
|
+
*/
|
|
430
|
+
constructor(ports: TelemetryClientPorts, context: TelemetryBatchContext, options?: TelemetryClientOptions);
|
|
431
|
+
/**
|
|
432
|
+
* 行为事件上报(事件通道经同意门 + 属性封闭字段集清洗)
|
|
433
|
+
*
|
|
434
|
+
* @param name - 事件名(常量表联合类型,禁止裸写字符串)
|
|
435
|
+
* @param properties - 事件属性
|
|
436
|
+
* @param allowedKeys - 属性白名单(缺省为属性键集合自身)
|
|
437
|
+
*/
|
|
438
|
+
track(name: TelemetryEventName, properties?: Record<string, TelemetryPropertyValue>, allowedKeys?: readonly string[]): Promise<void>;
|
|
439
|
+
/**
|
|
440
|
+
* 错误捕获(崩溃通道:日志条目 + js_error 事件条目双落)
|
|
441
|
+
*
|
|
442
|
+
* @param error - 捕获的未知抛出值
|
|
443
|
+
* @param captureOptions - 捕获选项
|
|
444
|
+
*/
|
|
445
|
+
captureError(error: unknown, captureOptions?: {
|
|
446
|
+
isFatal?: boolean;
|
|
447
|
+
tag?: string;
|
|
448
|
+
}): Promise<void>;
|
|
449
|
+
/**
|
|
450
|
+
* 日志远程镜像(WARN+ 且崩溃通道开启时落日志通道;Logger listener 的 sink 承接)
|
|
451
|
+
*
|
|
452
|
+
* @param level - 已归级日志级别(fatal 已并入 error)
|
|
453
|
+
* @param message - 日志消息
|
|
454
|
+
* @param stack - 关联堆栈
|
|
455
|
+
* @param tag - 来源标签
|
|
456
|
+
*/
|
|
457
|
+
mirrorLog(level: TelemetryLogLevel, message: string, stack: string, tag: string): Promise<void>;
|
|
458
|
+
/**
|
|
459
|
+
* 更新同意状态(任一通道关闭即整库 purge——关闭不留存口径)
|
|
460
|
+
*
|
|
461
|
+
* @param consent - 新同意状态
|
|
462
|
+
*/
|
|
463
|
+
setConsent(consent: TelemetryConsent): Promise<void>;
|
|
464
|
+
/**
|
|
465
|
+
* 单轮冲刷(双通道批量装载 → 裸传输 → 成功删行 / 拒绝即弃 / 可重试熔断冷却)
|
|
466
|
+
*
|
|
467
|
+
* @returns 冲刷结果
|
|
468
|
+
*/
|
|
469
|
+
flushOnce(): Promise<TelemetryFlushOutcome>;
|
|
470
|
+
/**
|
|
471
|
+
* 单通道递送一轮(至多 maxBatchesPerRun 批;可重试失败熔断并登记冷却)
|
|
472
|
+
*
|
|
473
|
+
* @param channel - 通道
|
|
474
|
+
* @param nowMs - 本轮基准时间
|
|
475
|
+
* @returns 通道轮结果
|
|
476
|
+
*/
|
|
477
|
+
private runChannel;
|
|
478
|
+
/**
|
|
479
|
+
* 装配并发送单批(按通道选装配器;batchedAt 刷新为本轮时间)
|
|
480
|
+
*
|
|
481
|
+
* @param channel - 通道
|
|
482
|
+
* @param records - 装载记录
|
|
483
|
+
* @param nowMs - 本轮基准时间
|
|
484
|
+
* @returns 三态发送结果
|
|
485
|
+
*/
|
|
486
|
+
private sendChannelBatch;
|
|
487
|
+
}
|
|
488
|
+
//#endregion
|
|
489
|
+
//#region src/sqlite-outbox.utils.d.ts
|
|
490
|
+
/**
|
|
491
|
+
* SQLite 执行结果(对齐 op-sqlite execute 返回形态)
|
|
492
|
+
*/
|
|
493
|
+
type SqliteExecuteResult = {
|
|
494
|
+
/**
|
|
495
|
+
* 查询行集合(写入语句为空)
|
|
496
|
+
*/
|
|
497
|
+
rows?: Record<string, unknown>[];
|
|
498
|
+
/**
|
|
499
|
+
* 插入语句分配的自增行号
|
|
500
|
+
*/
|
|
501
|
+
insertId?: number;
|
|
502
|
+
};
|
|
503
|
+
/**
|
|
504
|
+
* SQLite 句柄(结构化端口:宿主传入 op-sqlite 连接即可)
|
|
505
|
+
*/
|
|
506
|
+
type SqliteDbHandle = {
|
|
507
|
+
/**
|
|
508
|
+
* 执行 SQL(参数绑定)
|
|
509
|
+
*
|
|
510
|
+
* @param sql - SQL 文本
|
|
511
|
+
* @param params - 绑定参数
|
|
512
|
+
*/
|
|
513
|
+
execute(sql: string, params?: unknown[]): SqliteExecuteResult;
|
|
514
|
+
};
|
|
515
|
+
/**
|
|
516
|
+
* SQLite outbox(写穿落库、按行号序装载、成功才删行由调用方(TelemetryClient)承接)
|
|
517
|
+
*/
|
|
518
|
+
declare class SqliteOutbox implements TelemetryStoragePort {
|
|
519
|
+
/**
|
|
520
|
+
* SQLite 句柄(宿主注入)
|
|
521
|
+
*/
|
|
522
|
+
private readonly handle;
|
|
523
|
+
/**
|
|
524
|
+
* 构造 outbox(建表幂等)。
|
|
525
|
+
*
|
|
526
|
+
* @param handle - SQLite 句柄(op-sqlite 连接或测试替身)
|
|
527
|
+
*/
|
|
528
|
+
constructor(handle: SqliteDbHandle);
|
|
529
|
+
/**
|
|
530
|
+
* 追加条目
|
|
531
|
+
*
|
|
532
|
+
* @param channel - 通道
|
|
533
|
+
* @param entry - 条目载荷
|
|
534
|
+
* @returns 分配的行号(句柄未回传时为 0)
|
|
535
|
+
*/
|
|
536
|
+
append(channel: TelemetryChannelKind, entry: TelemetryEventEntry | TelemetryLogEntry): Promise<number>;
|
|
537
|
+
/**
|
|
538
|
+
* 按行号序装载一批(载荷损坏行自愈跳过——毒行防御)
|
|
539
|
+
*
|
|
540
|
+
* @param channel - 通道
|
|
541
|
+
* @param maxEntries - 单批上限
|
|
542
|
+
* @returns 装载记录集合
|
|
543
|
+
*/
|
|
544
|
+
loadBatch(channel: TelemetryChannelKind, maxEntries: number): Promise<StoredTelemetryRecord[]>;
|
|
545
|
+
/**
|
|
546
|
+
* 删除指定行(成功后调用——至少一次语义的删行侧)
|
|
547
|
+
*
|
|
548
|
+
* @param channel - 通道
|
|
549
|
+
* @param ids - 行号集合
|
|
550
|
+
*/
|
|
551
|
+
deleteRecords(channel: TelemetryChannelKind, ids: readonly number[]): Promise<void>;
|
|
552
|
+
/**
|
|
553
|
+
* 清空全部通道(同意关闭即 purge)
|
|
554
|
+
*/
|
|
555
|
+
purgeAll(): Promise<void>;
|
|
556
|
+
/**
|
|
557
|
+
* 统计行数
|
|
558
|
+
*
|
|
559
|
+
* @param channel - 通道
|
|
560
|
+
* @returns 行数
|
|
561
|
+
*/
|
|
562
|
+
count(channel: TelemetryChannelKind): Promise<number>;
|
|
563
|
+
}
|
|
564
|
+
//#endregion
|
|
565
|
+
export { type CapturedError, type ErrorUtilsLike, FetchTelemetryTransport, type FetchTransportOptions, type GlobalErrorHandler, type GlobalErrorWiringOptions, Logger, type LoggerEntry, type LoggerListener, type NormalizedError, type SqliteDbHandle, type SqliteExecuteResult, SqliteOutbox, TELEMETRY_EVENT_NAMES, TelemetryClient, type TelemetryClientOptions, type TelemetryClientPorts, TelemetryErrorBoundary, type TelemetryErrorBoundaryProps, type TelemetryEventName, type TelemetryFlushOutcome, type TelemetryLogSink, type Uninstall, type Unsubscribe, createTelemetryErrorBoundaryElement, createTelemetryLogListener, installGlobalErrorHandler, normalizeErrorValue };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@longzai-intelligence-telemetry/core"),t=require("react");const n={appLaunch:`app_launch`,appStateChange:`app_state_change`,jsError:`js_error`,previousSessionAbnormalExit:`previous_session_abnormal_exit`};var r=class{baseUrl;timeoutMs;constructor(e){this.baseUrl=e.baseUrl,this.timeoutMs=e.timeoutMs??8e3}sendEventBatch(t){return this.send(e.TELEMETRY_ENDPOINTS.trackingEventsBatch,t)}sendLogBatch(t){return this.send(e.TELEMETRY_ENDPOINTS.clientLogsBatch,t)}async send(t,n){let r=new AbortController,i=setTimeout(()=>{r.abort()},this.timeoutMs);try{let i=await fetch(`${this.baseUrl}${t}`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(n),signal:r.signal});return(0,e.classifyHttpStatus)(i.status)}catch{return(0,e.classifyTransportFailure)()}finally{clearTimeout(i)}}};function i(e){return e instanceof Error?{message:e.message,stack:e.stack??``}:{message:String(e),stack:``}}var a=class{tag;listeners=new Set;constructor(e){this.tag=e}addListener(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}debug(e){this.dispatch(`debug`,e)}info(e){this.dispatch(`info`,e)}warn(e){this.dispatch(`warn`,e)}error(e){this.dispatch(`error`,e)}dispatch(e,t){let n=i(t),r={level:e,message:n.message,stack:n.stack,tag:this.tag};for(let e of this.listeners)e.log(r)}};function o(e){return{log(t){(t.level===`warn`||t.level===`error`||t.level===`fatal`)&&e.mirrorLog({...t,level:t.level===`fatal`?`error`:t.level})}}}const s=()=>{};function c(){let e=Reflect.get(globalThis,`ErrorUtils`);if(typeof e!=`object`||!e)return;let t=Reflect.get(e,`setGlobalHandler`);if(typeof t==`function`)return{setGlobalHandler:n=>{t.call(e,n)}}}function l(e){let t=e.errorUtils??c();return t===void 0?()=>{}:(t.setGlobalHandler((t,n)=>{let r=i(t);e.onError({...r,isFatal:n})}),()=>{t.setGlobalHandler(s)})}var u=class extends t.Component{state={hasError:!1,error:null};static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e){this.props.onError?.(e)}render(){return this.state.hasError&&this.state.error!==null?this.props.fallback?.(this.state.error)??null:this.props.children??null}};function d(e){return(0,t.createElement)(u,e)}var f=class{ports;context;profile;batchEntries;consent;cooldown=e.INITIAL_COOLDOWN_STATE;constructor(t,n,r){this.ports=t,this.context=n,this.profile=(0,e.getDeliveryProfile)(r?.deliveryMode??`lossless`),this.batchEntries=r?.batchEntries??100,this.consent=r?.consent??e.DEFAULT_TELEMETRY_CONSENT}async track(t,n={},r){if(!(0,e.isChannelUploadAllowed)(this.consent,`behavioral-events`))return;let i=(0,e.sanitizeProperties)(n,r??Object.keys(n));await this.ports.storage.append(`event`,{name:t,properties:i,occurredAt:this.ports.clock.nowMs()})}async captureError(t,r={}){if(!(0,e.isChannelUploadAllowed)(this.consent,`crash-reporting`))return;let a=i(t),o=r.isFatal??!1,s=r.tag??`global`;await this.ports.storage.append(`log`,{level:o?`fatal`:`error`,message:a.message,stack:a.stack,tag:s,occurredAt:this.ports.clock.nowMs()}),await this.ports.storage.append(`event`,{name:n.jsError,properties:{fatal:o,tag:s},occurredAt:this.ports.clock.nowMs()})}async mirrorLog(t,n,r,i){(t===`warn`||t===`error`)&&(0,e.isChannelUploadAllowed)(this.consent,`crash-reporting`)&&await this.ports.storage.append(`log`,{level:t,message:n,stack:r,tag:i,occurredAt:this.ports.clock.nowMs()})}async setConsent(e){(!e.crashChannelEnabled||!e.behavioralEventsEnabled)&&await this.ports.storage.purgeAll(),this.consent=e}async flushOnce(){let t=this.ports.clock.nowMs();if(!(0,e.shouldAttemptSend)(this.cooldown,t))return{eventBatchesSent:0,logBatchesSent:0,blockedByCooldown:!0};let n=await this.runChannel(`event`,t),r=n.aborted?{batchesSent:0,aborted:!0}:await this.runChannel(`log`,t);return{eventBatchesSent:n.batchesSent,logBatchesSent:r.batchesSent,blockedByCooldown:!1}}async runChannel(t,n){let r=0;for(;r<this.profile.maxBatchesPerRun;){let i=await this.ports.storage.loadBatch(t,this.batchEntries);if(i.length===0)break;let a=await this.sendChannelBatch(t,i,n);if(a.outcome===`success`){await this.ports.storage.deleteRecords(t,i.map(e=>e.id)),this.cooldown=(0,e.registerSendSuccess)(),r+=1;continue}if(a.outcome===`retryable`)return this.cooldown=(0,e.registerSendFailure)(this.cooldown,n,this.profile.failureCooldownMs),{batchesSent:r,aborted:!0};await this.ports.storage.deleteRecords(t,i.map(e=>e.id)),r+=1}return{batchesSent:r,aborted:!1}}async sendChannelBatch(t,n,r){let i={...this.context,batchedAt:r};if(t===`event`){let r=n.filter(e=>`name`in e.entry).map(e=>({id:e.id,channel:t,entry:e.entry})),a=(0,e.assembleEventBatch)(i,r,this.batchEntries);return this.ports.transport.sendEventBatch(a.batch)}let a=n.filter(e=>`level`in e.entry).map(e=>({id:e.id,channel:t,entry:e.entry})),o=(0,e.assembleLogBatch)(i,a,this.batchEntries);return this.ports.transport.sendLogBatch(o.batch)}};const p=`telemetry_outbox_events`,m=`telemetry_outbox_logs`;function h(e){return e===`event`?p:m}function g(e){if(typeof e!=`object`||!e)return!1;let t=Reflect.get(e,`name`),n=Reflect.get(e,`occurredAt`);return typeof t==`string`&&typeof n==`number`}function _(e){if(typeof e!=`object`||!e)return!1;let t=Reflect.get(e,`message`),n=Reflect.get(e,`occurredAt`);return typeof t==`string`&&typeof n==`number`}var v=class{handle;constructor(e){this.handle=e,this.handle.execute(`CREATE TABLE IF NOT EXISTS ${p} (id INTEGER PRIMARY KEY AUTOINCREMENT, payload TEXT NOT NULL)`),this.handle.execute(`CREATE TABLE IF NOT EXISTS ${m} (id INTEGER PRIMARY KEY AUTOINCREMENT, payload TEXT NOT NULL)`)}async append(e,t){return this.handle.execute(`INSERT INTO ${h(e)} (payload) VALUES (?)`,[JSON.stringify(t)]).insertId??0}async loadBatch(e,t){let n=this.handle.execute(`SELECT id, payload FROM ${h(e)} ORDER BY id ASC LIMIT ?`,[t]),r=[];for(let t of n.rows??[]){let n=Number(t.id),i;try{i=JSON.parse(String(t.payload))}catch{continue}if(e===`event`&&g(i)){r.push({id:n,channel:e,entry:i});continue}e===`log`&&_(i)&&r.push({id:n,channel:e,entry:i})}return r}async deleteRecords(e,t){if(t.length===0)return;let n=t.map(()=>`?`).join(`, `);this.handle.execute(`DELETE FROM ${h(e)} WHERE id IN (${n})`,t.slice())}async purgeAll(){this.handle.execute(`DELETE FROM ${p}`),this.handle.execute(`DELETE FROM ${m}`)}async count(e){let t=(this.handle.execute(`SELECT COUNT(*) AS count FROM ${h(e)}`).rows??[])[0];return t===void 0?0:Number(t.count)}};exports.FetchTelemetryTransport=r,exports.Logger=a,exports.SqliteOutbox=v,exports.TELEMETRY_EVENT_NAMES=n,exports.TelemetryClient=f,exports.TelemetryErrorBoundary=u,exports.createTelemetryErrorBoundaryElement=d,exports.createTelemetryLogListener=o,exports.installGlobalErrorHandler=l,exports.normalizeErrorValue=i;
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DEFAULT_TELEMETRY_CONSENT as e,INITIAL_COOLDOWN_STATE as t,TELEMETRY_ENDPOINTS as n,assembleEventBatch as r,assembleLogBatch as i,classifyHttpStatus as a,classifyTransportFailure as o,getDeliveryProfile as s,isChannelUploadAllowed as c,registerSendFailure as l,registerSendSuccess as u,sanitizeProperties as d,shouldAttemptSend as f}from"@longzai-intelligence-telemetry/core";import{Component as p,createElement as m}from"react";const h={appLaunch:`app_launch`,appStateChange:`app_state_change`,jsError:`js_error`,previousSessionAbnormalExit:`previous_session_abnormal_exit`};var g=class{baseUrl;timeoutMs;constructor(e){this.baseUrl=e.baseUrl,this.timeoutMs=e.timeoutMs??8e3}sendEventBatch(e){return this.send(n.trackingEventsBatch,e)}sendLogBatch(e){return this.send(n.clientLogsBatch,e)}async send(e,t){let n=new AbortController,r=setTimeout(()=>{n.abort()},this.timeoutMs);try{let r=await fetch(`${this.baseUrl}${e}`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(t),signal:n.signal});return a(r.status)}catch{return o()}finally{clearTimeout(r)}}};function _(e){return e instanceof Error?{message:e.message,stack:e.stack??``}:{message:String(e),stack:``}}var v=class{tag;listeners=new Set;constructor(e){this.tag=e}addListener(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}debug(e){this.dispatch(`debug`,e)}info(e){this.dispatch(`info`,e)}warn(e){this.dispatch(`warn`,e)}error(e){this.dispatch(`error`,e)}dispatch(e,t){let n=_(t),r={level:e,message:n.message,stack:n.stack,tag:this.tag};for(let e of this.listeners)e.log(r)}};function y(e){return{log(t){(t.level===`warn`||t.level===`error`||t.level===`fatal`)&&e.mirrorLog({...t,level:t.level===`fatal`?`error`:t.level})}}}const b=()=>{};function x(){let e=Reflect.get(globalThis,`ErrorUtils`);if(typeof e!=`object`||!e)return;let t=Reflect.get(e,`setGlobalHandler`);if(typeof t==`function`)return{setGlobalHandler:n=>{t.call(e,n)}}}function S(e){let t=e.errorUtils??x();return t===void 0?()=>{}:(t.setGlobalHandler((t,n)=>{let r=_(t);e.onError({...r,isFatal:n})}),()=>{t.setGlobalHandler(b)})}var C=class extends p{state={hasError:!1,error:null};static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e){this.props.onError?.(e)}render(){return this.state.hasError&&this.state.error!==null?this.props.fallback?.(this.state.error)??null:this.props.children??null}};function w(e){return m(C,e)}var T=class{ports;context;profile;batchEntries;consent;cooldown=t;constructor(t,n,r){this.ports=t,this.context=n,this.profile=s(r?.deliveryMode??`lossless`),this.batchEntries=r?.batchEntries??100,this.consent=r?.consent??e}async track(e,t={},n){if(!c(this.consent,`behavioral-events`))return;let r=d(t,n??Object.keys(t));await this.ports.storage.append(`event`,{name:e,properties:r,occurredAt:this.ports.clock.nowMs()})}async captureError(e,t={}){if(!c(this.consent,`crash-reporting`))return;let n=_(e),r=t.isFatal??!1,i=t.tag??`global`;await this.ports.storage.append(`log`,{level:r?`fatal`:`error`,message:n.message,stack:n.stack,tag:i,occurredAt:this.ports.clock.nowMs()}),await this.ports.storage.append(`event`,{name:h.jsError,properties:{fatal:r,tag:i},occurredAt:this.ports.clock.nowMs()})}async mirrorLog(e,t,n,r){(e===`warn`||e===`error`)&&c(this.consent,`crash-reporting`)&&await this.ports.storage.append(`log`,{level:e,message:t,stack:n,tag:r,occurredAt:this.ports.clock.nowMs()})}async setConsent(e){(!e.crashChannelEnabled||!e.behavioralEventsEnabled)&&await this.ports.storage.purgeAll(),this.consent=e}async flushOnce(){let e=this.ports.clock.nowMs();if(!f(this.cooldown,e))return{eventBatchesSent:0,logBatchesSent:0,blockedByCooldown:!0};let t=await this.runChannel(`event`,e),n=t.aborted?{batchesSent:0,aborted:!0}:await this.runChannel(`log`,e);return{eventBatchesSent:t.batchesSent,logBatchesSent:n.batchesSent,blockedByCooldown:!1}}async runChannel(e,t){let n=0;for(;n<this.profile.maxBatchesPerRun;){let r=await this.ports.storage.loadBatch(e,this.batchEntries);if(r.length===0)break;let i=await this.sendChannelBatch(e,r,t);if(i.outcome===`success`){await this.ports.storage.deleteRecords(e,r.map(e=>e.id)),this.cooldown=u(),n+=1;continue}if(i.outcome===`retryable`)return this.cooldown=l(this.cooldown,t,this.profile.failureCooldownMs),{batchesSent:n,aborted:!0};await this.ports.storage.deleteRecords(e,r.map(e=>e.id)),n+=1}return{batchesSent:n,aborted:!1}}async sendChannelBatch(e,t,n){let a={...this.context,batchedAt:n};if(e===`event`){let n=t.filter(e=>`name`in e.entry).map(t=>({id:t.id,channel:e,entry:t.entry})),i=r(a,n,this.batchEntries);return this.ports.transport.sendEventBatch(i.batch)}let o=t.filter(e=>`level`in e.entry).map(t=>({id:t.id,channel:e,entry:t.entry})),s=i(a,o,this.batchEntries);return this.ports.transport.sendLogBatch(s.batch)}};const E=`telemetry_outbox_events`,D=`telemetry_outbox_logs`;function O(e){return e===`event`?E:D}function k(e){if(typeof e!=`object`||!e)return!1;let t=Reflect.get(e,`name`),n=Reflect.get(e,`occurredAt`);return typeof t==`string`&&typeof n==`number`}function A(e){if(typeof e!=`object`||!e)return!1;let t=Reflect.get(e,`message`),n=Reflect.get(e,`occurredAt`);return typeof t==`string`&&typeof n==`number`}var j=class{handle;constructor(e){this.handle=e,this.handle.execute(`CREATE TABLE IF NOT EXISTS ${E} (id INTEGER PRIMARY KEY AUTOINCREMENT, payload TEXT NOT NULL)`),this.handle.execute(`CREATE TABLE IF NOT EXISTS ${D} (id INTEGER PRIMARY KEY AUTOINCREMENT, payload TEXT NOT NULL)`)}async append(e,t){return this.handle.execute(`INSERT INTO ${O(e)} (payload) VALUES (?)`,[JSON.stringify(t)]).insertId??0}async loadBatch(e,t){let n=this.handle.execute(`SELECT id, payload FROM ${O(e)} ORDER BY id ASC LIMIT ?`,[t]),r=[];for(let t of n.rows??[]){let n=Number(t.id),i;try{i=JSON.parse(String(t.payload))}catch{continue}if(e===`event`&&k(i)){r.push({id:n,channel:e,entry:i});continue}e===`log`&&A(i)&&r.push({id:n,channel:e,entry:i})}return r}async deleteRecords(e,t){if(t.length===0)return;let n=t.map(()=>`?`).join(`, `);this.handle.execute(`DELETE FROM ${O(e)} WHERE id IN (${n})`,t.slice())}async purgeAll(){this.handle.execute(`DELETE FROM ${E}`),this.handle.execute(`DELETE FROM ${D}`)}async count(e){let t=(this.handle.execute(`SELECT COUNT(*) AS count FROM ${O(e)}`).rows??[])[0];return t===void 0?0:Number(t.count)}};export{g as FetchTelemetryTransport,v as Logger,j as SqliteOutbox,h as TELEMETRY_EVENT_NAMES,T as TelemetryClient,C as TelemetryErrorBoundary,w as createTelemetryErrorBoundaryElement,y as createTelemetryLogListener,S as installGlobalErrorHandler,_ as normalizeErrorValue};
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@longzai-intelligence-telemetry/react",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"keywords": [
|
|
6
|
+
"observability",
|
|
7
|
+
"react",
|
|
8
|
+
"react-native",
|
|
9
|
+
"telemetry"
|
|
10
|
+
],
|
|
11
|
+
"license": "UNLICENSED",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"module": "./dist/index.mjs",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.mjs",
|
|
22
|
+
"require": "./dist/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "lzi-builder",
|
|
27
|
+
"build:prod": "NODE_ENV=production bun run build",
|
|
28
|
+
"prepublishOnly": "bun run build:prod",
|
|
29
|
+
"typecheck": "bun run typecheck:app && bun run typecheck:node && bun run typecheck:test",
|
|
30
|
+
"typecheck:app": "lzi-tsgo typecheck tsconfig/app.json",
|
|
31
|
+
"typecheck:node": "lzi-tsgo typecheck tsconfig/node.json",
|
|
32
|
+
"typecheck:test": "lzi-tsgo typecheck tsconfig/test.json",
|
|
33
|
+
"lint": "oxlint && oxfmt --check",
|
|
34
|
+
"lint:fix": "oxlint --fix && oxfmt",
|
|
35
|
+
"test": "bun test",
|
|
36
|
+
"test:watch": "bun test --watch",
|
|
37
|
+
"test:coverage": "bun test --coverage",
|
|
38
|
+
"clean": "lzi-dev-cli clean"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@longzai-intelligence-telemetry/core": "0.0.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/react": "^19.2.15",
|
|
45
|
+
"react": "^19.2.6"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"react": ">=19.0.0",
|
|
49
|
+
"react-native": ">=0.87.0"
|
|
50
|
+
}
|
|
51
|
+
}
|