feat: pi 2.9 遥测 - #295
Merged
Merged
Conversation
zmdyy0318
marked this pull request as draft
July 22, 2026 15:26
Contributor
There was a problem hiding this comment.
嗨——我已经审查了你的改动,一切看起来都很棒!
帮我变得更有用!请在每条评论上点击 👍 或 👎,我会根据你的反馈改进后续评审。
Original comment in English
Hey - I've reviewed your changes and they look great!
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
zmdyy0318
marked this pull request as ready for review
July 27, 2026 16:30
Contributor
There was a problem hiding this comment.
Hey - 我这边发现了两个问题,并给了一些整体性的反馈:
telemetry.rs里的PostingGuard结构体存了一个MutexGuard<'static, ...>,这在编译时会失败,因为这个 guard 的生命周期并不是'static。可以考虑让PostingGuard对生命周期做泛型(例如PostingGuard<'a> { runs: MutexGuard<'a, ...> }),或者重新设计,使得互斥锁的 guard 不需要用'static生命周期存储。- 在
telemetry_set_enabled(false)中,你清除了TELEMETRY_GUARD和RUNS,但保留了TELEMETRY_CONFIG。如果关闭遥测的目的是真正完全退出收集,建议考虑同时清理或标记缓存的配置,这样在同一进程中之后再次启用时,不会在没有显式初始化的情况下意外复用旧配置。
给 AI Agent 的提示
请根据这次代码评审中的评论进行修改:
## 总体评论
- `telemetry.rs` 里的 `PostingGuard` 结构体存了一个 `MutexGuard<'static, ...>`,这在编译时会失败,因为这个 guard 的生命周期并不是 `'static`。可以考虑让 `PostingGuard` 对生命周期做泛型(例如 `PostingGuard<'a> { runs: MutexGuard<'a, ...> }`),或者重新设计,使得互斥锁的 guard 不需要用 `'static` 生命周期存储。
- 在 `telemetry_set_enabled(false)` 中,你清除了 `TELEMETRY_GUARD` 和 `RUNS`,但保留了 `TELEMETRY_CONFIG`。如果关闭遥测的目的是真正完全退出收集,建议考虑同时清理或标记缓存的配置,这样在同一进程中之后再次启用时,不会在没有显式初始化的情况下意外复用旧配置。
## 逐条评论
### Comment 1
<location path="src-tauri/src/commands/telemetry.rs" line_range="538-539" />
<code_context>
+}
+
+/// 提交任务期间的元数据登记句柄,持有遥测状态锁。
+pub struct PostingGuard {
+ runs: std::sync::MutexGuard<'static, BTreeMap<String, RunState>>,
+ instance_id: String,
+}
</code_context>
<issue_to_address>
**issue (bug_risk):** 避免在 `PostingGuard` 中存储带有 `'static` 生命周期的 `MutexGuard`
`RUNS.lock()` 不可能返回一个生命周期为 `'static` 的 `MutexGuard`,因此这个字段类型无法通过编译,也会鼓励不安全的生命周期处理方式。请避免预设 `'static` 生命周期:可以让 `PostingGuard` 对 guard 的生命周期做泛型,或者只存一个 `Arc<Mutex<_>>` 加上 `instance_id`,并在每次 `register` 调用中再获取锁。鉴于临界区很小,每次调用重新加锁是可以接受的,同时可以保持 API 的内存安全。
</issue_to_address>
### Comment 2
<location path="src/services/telemetryService.ts" line_range="38-46" />
<code_context>
+const MAX_OPTION_VALUE_LENGTH = 64;
+
+/** 自由文本类输入只上报是否填写,避免把路径 / URL / 进程名等隐私内容带出去。 */
+const summarizeInputValue = (
+ value: string,
+ pipelineType?: 'string' | 'int' | 'bool',
+ inputType?: 'text' | 'file' | 'time',
+): string => {
+ const isSafeToReport =
+ pipelineType === 'int' || pipelineType === 'bool' || (inputType === 'time' && !!value);
+ if (isSafeToReport) return value;
+ return value ? 'filled' : 'empty';
+};
+
</code_context>
<issue_to_address>
**🚨 suggestion (security):** 请考虑从隐私角度看,原始整数输入值是否适合直接上报
对 `pipeline_type === 'int'` 的情况,目前会直接上报原始值。如果这些整数可能包含用户或账号标识(例如 ID、手机号片段),即使有匿名化策略,依然可能泄露敏感信息。除非你能保证这些整数永远是非敏感内容(如小范围枚举或计数),否则可以考虑像其他自由文本一样处理(只上报 `filled`/`empty`,或按区间粗粒度分桶),以降低隐私风险。
建议实现:
```typescript
import { isDebugVersion } from '@/services/updateService';
```
```typescript
import { isDebugVersion } from '@/services/updateService';
import { createDefaultOptionValue, sanitizeOptionValue } from '@/stores/helpers';
import type {
OptionDefinition,
OptionValue,
ProjectInterface,
SelectedTask,
} from '@/types/interface';
import { loggers } from '@/utils/logger';
import { findSwitchCase } from '@/utils/optionHelpers';
/** 单个任务上报的选项条目上限,避免异常配置撑大事件。 */
const MAX_OPTION_ENTRIES = 30;
/** 单个选项值的长度上限。 */
const MAX_OPTION_VALUE_LENGTH = 64;
/** 自由文本类输入只上报是否填写,避免把路径 / URL / 进程名等隐私内容带出去。 */
const summarizeInputValue = (
value: string,
pipelineType?: 'string' | 'int' | 'bool',
inputType?: 'text' | 'file' | 'time',
): string => {
const isSafeToReport =
pipelineType === 'bool' || (inputType === 'time' && !!value);
if (isSafeToReport) return value;
return value ? 'filled' : 'empty';
};
```
</issue_to_address>请帮我变得更有用!欢迎在每条评论上点 👍 或 👎,我会根据你的反馈改进后续评审。
Original comment in English
Hey - I've found 2 issues, and left some high level feedback:
- The
PostingGuardstruct intelemetry.rsstores aMutexGuard<'static, ...>, which won’t compile because the guard’s lifetime is not'static; makePostingGuardgeneric over a lifetime (e.g.PostingGuard<'a> { runs: MutexGuard<'a, ...> }) or redesign it so the mutex guard does not need to be stored with a'staticlifetime. - In
telemetry_set_enabled(false)you clearTELEMETRY_GUARDandRUNSbut keepTELEMETRY_CONFIG; if the intent of disabling is to fully opt out, consider also clearing or marking the cached config so it isn't reused accidentally on a later enable in the same process without an explicit init.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `PostingGuard` struct in `telemetry.rs` stores a `MutexGuard<'static, ...>`, which won’t compile because the guard’s lifetime is not `'static`; make `PostingGuard` generic over a lifetime (e.g. `PostingGuard<'a> { runs: MutexGuard<'a, ...> }`) or redesign it so the mutex guard does not need to be stored with a `'static` lifetime.
- In `telemetry_set_enabled(false)` you clear `TELEMETRY_GUARD` and `RUNS` but keep `TELEMETRY_CONFIG`; if the intent of disabling is to fully opt out, consider also clearing or marking the cached config so it isn't reused accidentally on a later enable in the same process without an explicit init.
## Individual Comments
### Comment 1
<location path="src-tauri/src/commands/telemetry.rs" line_range="538-539" />
<code_context>
+}
+
+/// 提交任务期间的元数据登记句柄,持有遥测状态锁。
+pub struct PostingGuard {
+ runs: std::sync::MutexGuard<'static, BTreeMap<String, RunState>>,
+ instance_id: String,
+}
</code_context>
<issue_to_address>
**issue (bug_risk):** Avoid storing a `MutexGuard` with a `'static` lifetime in `PostingGuard`
`RUNS.lock()` cannot return a `MutexGuard` with a `'static` lifetime, so this field type will not compile and encourages unsound lifetime handling. Instead, avoid a baked-in `'static` lifetime: make `PostingGuard` generic over the guard’s lifetime, or store an `Arc<Mutex<_>>` plus `instance_id` and acquire the lock in each `register` call. Given the small critical section, re-locking per call is acceptable and keeps the API sound.
</issue_to_address>
### Comment 2
<location path="src/services/telemetryService.ts" line_range="38-46" />
<code_context>
+const MAX_OPTION_VALUE_LENGTH = 64;
+
+/** 自由文本类输入只上报是否填写,避免把路径 / URL / 进程名等隐私内容带出去。 */
+const summarizeInputValue = (
+ value: string,
+ pipelineType?: 'string' | 'int' | 'bool',
+ inputType?: 'text' | 'file' | 'time',
+): string => {
+ const isSafeToReport =
+ pipelineType === 'int' || pipelineType === 'bool' || (inputType === 'time' && !!value);
+ if (isSafeToReport) return value;
+ return value ? 'filled' : 'empty';
+};
+
</code_context>
<issue_to_address>
**🚨 suggestion (security):** Consider whether raw integer input values are safe to report from a privacy perspective
For `pipeline_type === 'int'`, values are currently sent as-is. If these integers can include user or account identifiers (e.g., IDs, phone fragments), this may expose sensitive data despite the anonymization strategy. Unless you can guarantee these are always non-sensitive (e.g., small bounded enums or counts), consider handling them like other free-text inputs (only `filled`/`empty` or coarse numeric buckets) to reduce privacy risk.
Suggested implementation:
```typescript
import { isDebugVersion } from '@/services/updateService';
```
```typescript
import { isDebugVersion } from '@/services/updateService';
import { createDefaultOptionValue, sanitizeOptionValue } from '@/stores/helpers';
import type {
OptionDefinition,
OptionValue,
ProjectInterface,
SelectedTask,
} from '@/types/interface';
import { loggers } from '@/utils/logger';
import { findSwitchCase } from '@/utils/optionHelpers';
/** 单个任务上报的选项条目上限,避免异常配置撑大事件。 */
const MAX_OPTION_ENTRIES = 30;
/** 单个选项值的长度上限。 */
const MAX_OPTION_VALUE_LENGTH = 64;
/** 自由文本类输入只上报是否填写,避免把路径 / URL / 进程名等隐私内容带出去。 */
const summarizeInputValue = (
value: string,
pipelineType?: 'string' | 'int' | 'bool',
inputType?: 'text' | 'file' | 'time',
): string => {
const isSafeToReport =
pipelineType === 'bool' || (inputType === 'time' && !!value);
if (isSafeToReport) return value;
return value ? 'filled' : 'empty';
};
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
opus 5.0

MaaXYZ/MaaFramework#1414
默认开启
Summary by Sourcery
添加由 Sentry 驱动的可选匿名遥测功能,在调试/开发构建中进行基于构建类型的拦截,并在前端和 Tauri 后端对任务生命周期进行监控。
New Features:
telemetry.sentryDSN 的配置容器,支持从项目接口进行遥测配置。Enhancements:
Build:
Documentation:
Original summary in English
Summary by Sourcery
Add opt-in anonymous telemetry powered by Sentry, with build-based blocking in debug/dev and task lifecycle instrumentation across frontend and Tauri backend.
New Features:
Enhancements:
Build:
Documentation:
Summary by Sourcery
在前端和 Tauri 后端中添加基于 Sentry 的可选匿名遥测,以及任务生命周期的埋点,根据构建类型和新的用户设置进行控制。
New Features:
telemetry.sentry容器声明 Sentry 遥测配置,包括 DSN 和追踪选项。Enhancements:
Build:
Documentation:
Original summary in English
Summary by Sourcery
Add optional Sentry-based anonymous telemetry with task lifecycle instrumentation across frontend and Tauri backend, gated by build type and a new user setting.
New Features:
Enhancements:
Build:
Documentation: