@wu529778790/open-im 1.11.2-beta.0 → 1.11.2-beta.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/dist/index.js CHANGED
@@ -183,7 +183,7 @@ export async function main() {
183
183
  logLevel: config.logLevel,
184
184
  telemetry: config.telemetry,
185
185
  });
186
- initSentry();
186
+ initSentry(config.telemetry.enabled);
187
187
  applyOpenImGitCoauthorToProcessEnv();
188
188
  }
189
189
  catch (err) {
@@ -1,21 +1,20 @@
1
1
  /**
2
2
  * Sentry 错误追踪集成
3
3
  *
4
- * 仅捕获错误,不开启性能监控(免费版 5K errors/月 够用)。
5
- * 通过 OPEN_IM_SENTRY_DSN 环境变量启用。
4
+ * - 默认启用,收集错误用于改进产品质量
5
+ * - 用户可通过 OPEN_IM_TELEMETRY=false 或 config.json opt-out
6
+ * - 只收集错误类型和堆栈,不收集用户数据(PII)
6
7
  */
7
8
  /**
8
- * 初始化 Sentry。无 DSN 则静默跳过。
9
+ * 初始化 Sentry
10
+ * - 默认启用(收集错误改进产品)
11
+ * - 用户可通过 OPEN_IM_TELEMETRY=false 或 telemetry.enabled=false opt-out
9
12
  */
10
- export declare function initSentry(): void;
13
+ export declare function initSentry(telemetryEnabled?: boolean): void;
11
14
  /**
12
- * 上报错误到 Sentry
15
+ * 上报错误到 Sentry(自动清理 PII)
13
16
  */
14
17
  export declare function captureError(error: Error | unknown, context?: Record<string, unknown>): void;
15
- /**
16
- * 添加面包屑(错误发生前的上下文)
17
- */
18
- export declare function addBreadcrumb(category: string, message: string, data?: Record<string, unknown>): void;
19
18
  /**
20
19
  * 刷新并关闭 Sentry(优雅关闭时调用)
21
20
  */
@@ -1,38 +1,81 @@
1
1
  /**
2
2
  * Sentry 错误追踪集成
3
3
  *
4
- * 仅捕获错误,不开启性能监控(免费版 5K errors/月 够用)。
5
- * 通过 OPEN_IM_SENTRY_DSN 环境变量启用。
4
+ * - 默认启用,收集错误用于改进产品质量
5
+ * - 用户可通过 OPEN_IM_TELEMETRY=false 或 config.json opt-out
6
+ * - 只收集错误类型和堆栈,不收集用户数据(PII)
6
7
  */
7
8
  import * as Sentry from '@sentry/node';
8
9
  import { createLogger } from '../logger.js';
9
10
  const log = createLogger('Sentry');
11
+ // 开发者的 Sentry DSN(所有 open-im 实例共享)
12
+ const DEFAULT_DSN = 'https://cc5ad094c1229b2a2ff23ab54b0fd807@o4508612762861568.ingest.us.sentry.io/4511583989727232';
10
13
  let initialized = false;
11
14
  /**
12
- * 初始化 Sentry。无 DSN 则静默跳过。
15
+ * 清理 PII(用户数据)
16
+ * 只保留错误信息,移除敏感内容
13
17
  */
14
- export function initSentry() {
15
- const dsn = process.env.OPEN_IM_SENTRY_DSN;
16
- if (!dsn) {
17
- log.debug('Sentry disabled (no OPEN_IM_SENTRY_DSN)');
18
+ function sanitizeContext(context) {
19
+ const clean = {};
20
+ for (const [key, value] of Object.entries(context)) {
21
+ // 跳过敏感字段
22
+ if (/token|secret|password|key|api_key|apikey|auth/i.test(key))
23
+ continue;
24
+ // 跳过用户 ID(只保留平台信息)
25
+ if (/userId|user_id|userKey|user_key/i.test(key)) {
26
+ clean[key] = '[redacted]';
27
+ continue;
28
+ }
29
+ // 截断长字符串
30
+ if (typeof value === 'string' && value.length > 200) {
31
+ clean[key] = value.substring(0, 200) + '...';
32
+ }
33
+ else {
34
+ clean[key] = value;
35
+ }
36
+ }
37
+ return clean;
38
+ }
39
+ /**
40
+ * 初始化 Sentry
41
+ * - 默认启用(收集错误改进产品)
42
+ * - 用户可通过 OPEN_IM_TELEMETRY=false 或 telemetry.enabled=false opt-out
43
+ */
44
+ export function initSentry(telemetryEnabled = true) {
45
+ // 检查 opt-out
46
+ const envOptOut = process.env.OPEN_IM_TELEMETRY?.trim().toLowerCase();
47
+ if (envOptOut === 'false' || envOptOut === '0' || envOptOut === 'no' || !telemetryEnabled) {
48
+ log.debug('Sentry disabled (user opt-out)');
18
49
  return;
19
50
  }
51
+ // 优先使用用户自定义 DSN,否则用默认 DSN
52
+ const dsn = process.env.OPEN_IM_SENTRY_DSN || DEFAULT_DSN;
20
53
  try {
21
54
  Sentry.init({
22
55
  dsn,
23
- // 只捕获 error 级别,不捕获 warning/info
56
+ // 只捕获 error 级别
24
57
  beforeSend(event) {
25
58
  if (event.level !== 'error' && event.level !== 'fatal')
26
59
  return null;
60
+ // 清理 PII
61
+ if (event.extra) {
62
+ event.extra = sanitizeContext(event.extra);
63
+ }
64
+ if (event.contexts) {
65
+ for (const [key, value] of Object.entries(event.contexts)) {
66
+ if (typeof value === 'object' && value !== null) {
67
+ event.contexts[key] = sanitizeContext(value);
68
+ }
69
+ }
70
+ }
27
71
  return event;
28
72
  },
29
73
  // 不开启 performance monitoring
30
74
  tracesSampleRate: 0,
31
75
  // 环境标识
32
76
  environment: process.env.NODE_ENV ?? 'production',
33
- // 附加面包屑(错误发生前的日志)
77
+ // 附加面包屑
34
78
  beforeBreadcrumb(breadcrumb) {
35
- // 只保留关键 breadcrumb
36
79
  if (breadcrumb.category === 'console' || breadcrumb.category === 'http') {
37
80
  return breadcrumb;
38
81
  }
@@ -40,14 +83,14 @@ export function initSentry() {
40
83
  },
41
84
  });
42
85
  initialized = true;
43
- log.info('Sentry initialized');
86
+ log.info('Sentry initialized (error tracking enabled)');
44
87
  }
45
88
  catch (err) {
46
89
  log.warn('Sentry init failed:', err);
47
90
  }
48
91
  }
49
92
  /**
50
- * 上报错误到 Sentry
93
+ * 上报错误到 Sentry(自动清理 PII)
51
94
  */
52
95
  export function captureError(error, context) {
53
96
  if (!initialized)
@@ -55,7 +98,7 @@ export function captureError(error, context) {
55
98
  try {
56
99
  Sentry.withScope((scope) => {
57
100
  if (context) {
58
- scope.setExtras(context);
101
+ scope.setExtras(sanitizeContext(context));
59
102
  }
60
103
  if (error instanceof Error) {
61
104
  scope.setTag('error.name', error.name);
@@ -68,24 +111,6 @@ export function captureError(error, context) {
68
111
  // Sentry 本身不应影响业务
69
112
  }
70
113
  }
71
- /**
72
- * 添加面包屑(错误发生前的上下文)
73
- */
74
- export function addBreadcrumb(category, message, data) {
75
- if (!initialized)
76
- return;
77
- try {
78
- Sentry.addBreadcrumb({
79
- category,
80
- message: message.substring(0, 200),
81
- data,
82
- level: 'info',
83
- });
84
- }
85
- catch {
86
- // ignore
87
- }
88
- }
89
114
  /**
90
115
  * 刷新并关闭 Sentry(优雅关闭时调用)
91
116
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu529778790/open-im",
3
- "version": "1.11.2-beta.0",
3
+ "version": "1.11.2-beta.1",
4
4
  "description": "Your AI coding assistant, in every chat app. Multi-platform IM bridge for Claude Code, Codex, and CodeBuddy.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",