使用情況分析
Control Center 可以把假名化的使用事件傳送到一個 Umami 實例。使用情況分析預設關閉,直至伺服器營運者把它開啟。這項設定屬於伺服器,並套用於連線到它的每一個用戶端:桌面應用程式、Web 應用程式、手機,以及伺服器本身。
使用情況分析與分享當機報告互不相干;後者是針對單一裝置的當機與錯誤診斷設定。
由誰決定
標題為「由誰決定」的章節| 開關 | 位置 | 效果 |
|---|---|---|
| 分享使用情況分析 | 首次設定(沙箱步驟)及設定 → 隱私。只有伺服器營運者可以更改;其他成員只能以唯讀方式看到目前的值 | 套用於整個伺服器。以 telemetry.usage_analytics 儲存在伺服器設定中。除非設為 true,否則保持關閉 |
| 建置類型 | 自動 | debug 及 profile 建置不會傳送,而是把每個事件寫入除錯日誌 |
CC_ANALYTICS_DEBUG=1 |
cc_server 的環境或其 .env 檔案 |
讓伺服器及每個連線到它的用戶端的 debug 及 profile 建置真正傳送資料,以作測試。上方的開關仍須開啟 |
DO_NOT_TRACK=1 |
cc_server 的環境 |
無論開關如何,都會停止伺服器本身的回報。用戶端仍會遵循該開關 |
| 示範伺服器 | 自動 | 公開的示範伺服器不會以自身名義傳送任何內容。訪客無法更改該開關 |
用戶端會從伺服器讀取這項設定(先透過 telemetry.config,之後透過 telemetry.watch 即時取得)。收到答覆之前,事件會在一個細小的記憶體緩衝區中等候。如果答覆是否,緩衝區便會被捨棄。關閉開關會捨棄所有仍在佇列中的內容,並即時在每個用戶端上停止傳送。
永遠不會傳送的內容
標題為「永遠不會傳送的內容」的章節- 訊息、工單、審查或會議的內容、標題、提示詞、shell 指令及搜尋查詢
- 姓名、登入名稱、電郵地址、頭像及顯示名稱
- 檔案路徑、程式庫名稱、分支名稱、主機名稱及 URL(程式庫只以假名化的
repo_id傳送;會議連結只以其提供方傳送) - 任何形式的原始識別碼
每個事件離開行程之前都會先經過一套屬性政策。文字、路徑、URL、電郵地址、未經包裝的 ID,以及 email、*_name、path、title、prompt、content 或 token 等鍵之下的字串都會被捨棄,而不會傳送出去。只有來自封閉詞彙表的簡短代號才會以字串傳送,例如列舉值、版本、地區設定或模型 ID。
假名化 ID
標題為「假名化 ID」的章節ID 會被傳送,但只以假名的形式。每一個工作區、空間、對話、代理、執行、使用者及裝置的 ID,都會被替換成以該安裝本身的秘密鹽值(telemetry.pseudonym_salt)計算的 HMAC-SHA256,並截斷為 20 個十六進制字元。同一個工作區一律回報相同的值,因此事件可以互相關聯並加以計算,但原始 ID 永遠不會離開該安裝。鹽值在伺服器首次啟動時建立,並且從不傳送給分析服務提供方。刪除伺服器的資料目錄會產生新的鹽值及安裝 ID,與之前記錄的一切從此失去關聯。
每個事件都附帶的屬性
標題為「每個事件都附帶的屬性」的章節| 屬性 | 例子 | 意思 |
|---|---|---|
app_type |
desktop |
desktop、web、remote(手機)或 server。亦用作 Umami 中的主機名稱 |
app_version |
0.0.11 |
發行版本 |
app_build |
4baf980 |
該建置的 git 短提交 |
platform |
macos |
macos、windows、linux、web,或手機的作業系統(ios、android) |
locale |
fr_FR |
介面語言 |
server_mode |
local |
local(桌面應用程式執行自己的伺服器)或 remote |
server_version |
0.0.11 |
已連線伺服器的版本(如已知) |
is_demo |
false |
用戶端是否連線到公開示範 |
install_id |
假名 | 伺服器安裝 |
user_id |
假名 | 已登入的使用者(得知後) |
device_id |
假名 | 已配對的裝置(得知後)。亦是 Umami 中的唯一 ID |
launch_id |
假名 | 一次應用程式啟動,用來排列一個工作階段的事件次序 |
event_seq |
12 |
事件在這次啟動中的次序 |
此外,Umami 亦會收到請求的 IP 位址(它會據此推斷國家及地區,但不儲存位址本身),以及 User-Agent 及螢幕尺寸。
畫面瀏覽
標題為「畫面瀏覽」的章節每次導覽都會記錄一次頁面瀏覽,其 URL 是路由範本,例如 /workspaces/:workspaceId/spaces/:spaceId,而不是實際位址。畫面名稱由範本的字面片段組成,因此上例是 workspaces_spaces。以 Id 結尾的路由參數會以假名化的 *_id 屬性附加,數字參數(例如 PR 編號)則以數字附加。其他參數一律捨棄。
用戶端事件
標題為「用戶端事件」的章節由桌面應用程式、Web 應用程式及手機針對使用者的操作記錄。
| 事件 | 屬性 | 記錄時機 |
|---|---|---|
app_opened |
startup_ms |
應用程式完成啟動並已連線 |
app_backgrounded |
foreground_s |
視窗或分頁被隱藏 |
app_foregrounded |
background_s |
再次顯示 |
server_connected |
reconnect |
連線中斷後恢復 |
server_disconnected |
連線中斷 | |
server_switched |
使用者切換到另一台伺服器 | |
device_paired |
手機確認了配對 | |
onboarding_step_viewed |
step、step_index |
顯示了一個首次設定步驟 |
onboarding_completed |
duration_s、step_count、workspace_id |
首次設定完成 |
workspace_switched |
workspace_id、previous_workspace_id |
使用者開啟了另一個工作區 |
message_sent |
workspace_id、space_id、conversation_id、delivery(send、steer、queued)、char_count、attachment_count、agent_mention_count、other_mention_count、slash_command |
從撰寫框傳送了一則訊息 |
slash_command_run |
command、workspace_id、space_id |
執行了一個用戶端斜線指令。內置指令回報其名稱,技能回報 skill,程式庫指令回報 custom |
approval_decided |
decision、remembered、surface、action_classes、action_class_count、severity、workspace_id、space_id、conversation_id |
代理的批准請求得到答覆 |
command_palette_opened |
開啟了指令面板 | |
command_executed |
source(palette、keybinding)、command |
執行了一個指令。針對特定 PR、成員或對話的指令只回報其類別(pr、member、conversation) |
review_submitted |
verdict、comment_count、workspace_id |
提交了一份 pull request 審查 |
search_performed |
scope(space_messages、repo_content)、result_count、query_length、workspace_id、space_id |
執行了一次搜尋。查詢內容本身永遠不會記錄 |
meeting_recording_started |
workspace_id、meeting_id |
會議錄製開始 |
meeting_recording_stopped |
duration_s、workspace_id、meeting_id |
錄製停止 |
setting_changed |
setting(appearance.theme、appearance.locale)、value |
主題或語言更改 |
soundscape_started |
mood、source(user、focus) |
音景開始播放,來自控制項或隨專注模式啟動 |
soundscape_stopped |
mood、source、listened_s |
停止播放 |
soundscape_mood_changed |
from_mood、to_mood、playing |
使用者揀選了另一種氛圍 |
focus_mode_started |
planned_minutes、has_goal、block_notifications |
專注模式開始 |
focus_mode_ended |
elapsed_s、planned_minutes、completed |
專注模式結束,提早結束或時間用完 |
dictation_started |
撰寫框中的語音輸入開始 | |
dictation_ended |
outcome(completed、cancelled、failed)、duration_s、transcript_chars、error_kind |
語音輸入結束。只記錄轉錄文字的長度 |
pipeline_run_requested |
workspace_id、template_id、trigger、dry_run、started |
應用程式要求伺服器執行一條管線 |
pipeline_run_retried |
workspace_id、pipeline_run_id |
重試了一次失敗的執行 |
pipeline_run_cancel_requested |
workspace_id、pipeline_run_id |
從應用程式取消了一次執行 |
pipeline_step_killed |
workspace_id、step_run_id |
強制終止了一個執行中的步驟 |
calendar_connect_finished |
outcome(connected、denied、expired、failed、cancelled)、builtin_client、duration_s |
一次日曆登入嘗試結束 |
calendar_disconnected |
workspace_id |
中斷了一個日曆帳戶的連線 |
calendar_rsvp_sent |
calendar_event_id、response、previous_response、workspace_id |
回覆了一個邀請 |
calendar_event_recorded |
workspace_id、calendar_event_id |
從日曆活動開始了一次錄製 |
calendar_meeting_joined |
provider(meet、zoom、teams、webex、other)、workspace_id、calendar_event_id |
開啟了會議連結(手機)。只從連結推斷提供方 |
notification_action |
action(read、unread、dismiss、mark_all_read、clear_all)、workspace_id |
使用了通知中心 |
agent_created |
workspace_id、agent_id、adapter、model |
從登錄冊建立了一個代理 |
tab_opened |
kind(chat、terminal、browser、rig、codeServer、file、…) |
在空間中開啟了一個新的編輯器分頁 |
skill_action |
action(install、update、uninstall、source_added、source_removed)、skill_id、blocked |
工作區技能有所更改 |
orchestration_decided |
decision(approved、cancelled)、workspace_id、orchestration_id |
回覆了一個編排提案 |
plan_decided |
decision(approved、rejected)、plan_id、workspace_id、partial、node_count |
批准或拒絕了一個計劃(手機) |
goal_started |
kind(goal、loop)、workspace_id、space_id、conversation_id、agent_id、budget_cents、accepted |
啟動了一個受監督的目標或循環(手機) |
conversation_created |
workspace_id、space_id、conversation_id、source(new、fork) |
建立或分岔了一個對話 |
conversation_rewound |
conversation_id |
從較早的一則訊息繼續了對話 |
space_archived |
workspace_id、space_id |
封存了一個空間 |
伺服器事件
標題為「伺服器事件」的章節由 cc_server 記錄,針對沒有任何單一用戶端會剛好看到一次的事實。代理的一次執行只計算一次,無論有多少用戶端在觀看。
| 事件 | 屬性 | 記錄時機 |
|---|---|---|
server_started |
workspace_count、startup_ms |
伺服器完成開機 |
workspace_created |
workspace_id |
建立了一個工作區 |
space_created |
workspace_id、space_id |
建立了一個空間 |
repo_added |
workspace_id、repo_id |
連結了一個程式庫 |
ticket_created |
workspace_id、ticket_id |
有人或代理建立了工單 |
agent_run_completed |
agent_id、workspace_id、conversation_id、run_id、status、error_family、role、adapter、model、effort、task_family、subagent、pipeline、resumed_native_session、duration_ms、time_to_first_token_ms、input_tokens、output_tokens、thought_tokens、cache_read_tokens、cache_write_tokens、output_rejections、cost_usd |
代理執行結束 |
agent_awaiting_input |
kind(approval、question、credential)、workspace_id、agent_id、conversation_id |
代理停下來等候有人處理 |
agent_action_blocked |
workspace_id、agent_id、space_id、source |
動作政策拒絕了代理的某個動作 |
pipeline_run_finished |
outcome(completed、failed、cancelled)、workspace_id、pipeline_run_id、template_id、trigger、duration_ms、active_ms、attempt_count、template_version、cost_cents、tokens、dry_run、sub_pipeline |
一次管線執行結束。trigger 是 manual、啟動該執行的事件類型,或只是具名觸發條件的類別(webhook) |
pull_request_published |
workspace_id、pr_id |
從空間發佈了一個 pull request |
pull_request_merged |
workspace_id、pr_id、agent_id |
代理開啟的 pull request 已合併 |
meeting_recorded |
workspace_id、meeting_id、transcript_chars |
儲存了一段會議錄製 |
space_deleted |
workspace_id、space_id |
刪除了一個空間 |
ticket_status_changed |
workspace_id、ticket_id、from_status、to_status |
工單狀態更改 |
ticket_assigned |
workspace_id、ticket_id、assignee_type、agent_id、team_id |
工單已指派 |
ticket_reassigned |
workspace_id、ticket_id、from_agent_id、to_agent_id |
工單轉給了另一個代理 |
ticket_work_finished |
ticket_id、outcome(completed、failed、cancelled) |
工單上委派的工作結束 |
workspace_member_changed |
workspace_id、member_user_id、change(added、removed、role_changed)、role |
工作區成員有所更改 |
rig_closed |
workspace_id、rig_id、reason、reaped、agent_id |
測試機已關閉,或已被回收 |
skill_updated |
workspace_id、skill_id、origin、scan_verdict |
工作區技能已安裝、更新或在磁碟上更改 |
calendar_auth_expired |
workspace_id |
日曆連線需要重新登入 |
calendar_meeting_starting_soon |
workspace_id、calendar_event_id、has_meeting_link、lead_s |
日曆活動即將開始 |
budget_threshold_crossed |
scope_type、scope_id、spent_cents、budget_cents、hard_stop |
支出超越了預算門檻 |
pull_request_review_requested |
workspace_id、repo_id |
在追蹤中的 PR 上請求了審查 |
pull_request_review_decision_changed |
workspace_id、repo_id、decision、reviewers_remaining |
追蹤中 PR 的審查決定更改 |
external_pull_request_merged |
workspace_id、repo_id |
已連結程式庫中一個並非由代理開啟的 PR 已合併 |
事件會從一個最多容納 200 個事件的記憶體佇列中逐一傳送到 <host>/api/send。遇到網絡錯誤、逾時、429 或 5xx 時會保留事件,並以指數退避重試,間隔由 1 秒逐步增加至 5 分鐘。其他任何 4xx 都會捨棄該事件。不會有任何內容寫入磁碟,因此應用程式結束時仍在佇列中的事件會遺失。應用程式轉到背景及伺服器關閉時,佇列會全數送出。
把建置指向另一個實例
標題為「把建置指向另一個實例」的章節目的地在建置時已經固定:
--dart-define=CC_ANALYTICS_HOST=https://analytics.example.com/--dart-define=CC_ANALYTICS_WEBSITE_ID=<website uuid>提供方轉接器位於 packages/cc_analytics。要支援其他分析服務,就是在那裏新增一個轉接器。追蹤計劃及私隱規則維持不變。