|
|
1 lună în urmă | |
|---|---|---|
| .. | ||
| dashboard | 1 lună în urmă | |
| scripts | 1 lună în urmă | |
| worker | 1 lună în urmă | |
| README.md | 1 lună în urmă | |
本目录维护通用匿名埋点统计服务,采用 Cloudflare Workers + Analytics Engine + Workers Static Assets。
公开仓库只保存源码,不保存 ACCOUNT_ID、ADMIN_TOKEN、ANALYTICS_API_TOKEN 等密钥。
服务地址:
| 项目 | 地址 |
|---|---|
| API 地址 | https://analytics.agnet.top |
| 统计页面地址 | https://static.analytics.agnet.top |
目录结构:
analytics/
worker/ # 上报与查询 API Worker
dashboard/ # 统计看板 Worker Static Assets
worker/src/ 采用模块化结构:index.js 只负责路由分发,routes/ 放接口处理,services/ 放 Analytics Engine 与 KV 访问,http.js、utils.js、constants.js 放公共能力。
dashboard/public/ 是无需构建的静态看板:index.html 负责页面骨架,styles.css 负责样式,src/ 下使用原生 ES Module 拆分 API、渲染、标签页和各标签页逻辑。
核心接口:
| 接口 | 用途 | 鉴权 |
|---|---|---|
GET /health |
检查 API Worker | 无 |
POST /track |
上报埋点 | 无 |
GET /notice |
客户端读取最新公告 | 无 |
GET /api/projects |
查询最近 90 天出现过的项目名 | ADMIN_TOKEN |
GET /api/summary |
查询每日统计、页面排行、版本分布 | ADMIN_TOKEN |
GET /api/latest |
查询最近事件 | ADMIN_TOKEN |
GET /api/notice |
读取当前项目公告 | ADMIN_TOKEN |
POST /api/notice |
发布或更新当前项目公告 | ADMIN_TOKEN |
DELETE /api/notice |
停用当前项目公告 | ADMIN_TOKEN |
事件类型:
| event | 说明 | page 是否必填 |
|---|---|---|
app_open |
应用打开 | 否 |
page_view |
页面访问 | 是 |
config_usage |
配置使用快照 | 否 |
ai_request |
AI 接口请求 | 否 |
ai_request 只统计模型名称和请求类型,不采集 API Key、Base URL、Prompt、响应内容或错误详情。
统计页面使用:
https://static.analytics.agnet.top。https://analytics.agnet.top。ADMIN_TOKEN。yibiao-client。存储和数据库 -> Analytics Engine。Enable。Dataset 不需要手动创建,第一次写入后会自动创建 agnet_analytics。
客户端公告保存到 Cloudflare KV,绑定名固定为 NOTICE_STORE。
KV namespace 只需要创建一次。自动创建要求执行脚本的环境具备 Cloudflare 凭据:
| 变量 | 说明 |
|---|---|
CLOUDFLARE_API_TOKEN |
需要具备 Workers KV namespace 读写和 Worker 部署权限 |
CLOUDFLARE_ACCOUNT_ID |
Cloudflare Account ID,避免 Wrangler 在非交互环境选择账号 |
analytics/worker 部署前会检查 wrangler.jsonc 是否已经配置 NOTICE_STORE。已配置时直接部署;未配置时才运行 setup:notice-kv,创建或复用已有 KV namespace,并把 id 写入本次部署使用的 wrangler.jsonc。
本地首次启用时,也可以在登录 Wrangler 后手动运行:
cd analytics\worker
npm run setup:notice-kv
脚本会优先查询并复用现有 namespace;不存在时才执行 wrangler kv namespace create NOTICE_STORE,并把 namespace id 写入 analytics/worker/wrangler.jsonc 的 kv_namespaces。
如果需要手动配置,也可以运行:
cd analytics\worker
npx wrangler kv namespace create NOTICE_STORE
然后在 analytics/worker/wrangler.jsonc 中加入:
"kv_namespaces": [
{
"binding": "NOTICE_STORE",
"id": "<上一步输出的 namespace id>"
}
]
My Profile -> API Tokens。Create Token。Create Custom Token。Account -> Account Analytics -> Read。ANALYTICS_API_TOKEN。在 Cloudflare 创建 Worker,并连接当前 GitHub 仓库。
配置:
| 项目 | 值 |
|---|---|
| Worker 名称 | agnet-analytics-api |
| Root directory | analytics/worker |
| Build command | npm install |
| Deploy command | npm run deploy |
analytics/worker/wrangler.jsonc 已包含:
| 配置 | 值 |
|---|---|
| 自定义域名 | analytics.agnet.top |
| Analytics Engine binding | ANALYTICS |
| Analytics Engine dataset | agnet_analytics |
| 公告 KV binding | NOTICE_STORE(首次部署时创建或复用) |
| 变量保留 | keep_vars: true,避免部署覆盖后台配置 |
部署后在 Worker 的 Settings -> Variables and Secrets 配置 Secret:
| Secret | 说明 |
|---|---|
ACCOUNT_ID |
Cloudflare Account ID |
ADMIN_TOKEN |
统计看板查询密码 |
ANALYTICS_API_TOKEN |
上一步创建的 API Token |
注意:不要在 wrangler.jsonc 里声明 secrets.required。首次 GitHub 部署时 Secret 还没配置,Wrangler 会在部署前校验并失败。正确流程是先部署 Worker,再到 Cloudflare 后台配置这些 Secret,然后重新部署或直接访问验证。
确认绑定:
agnet-analytics-api。Settings -> Bindings。ANALYTICS -> Analytics Engine -> agnet_analytics。验证:
Invoke-RestMethod -Uri "https://analytics.agnet.top/health"
统计看板使用 Workers Static Assets,同样创建 Worker 并连接当前 GitHub 仓库。
配置:
| 项目 | 值 |
|---|---|
| Worker 名称 | agnet-analytics-dashboard |
| Root directory | analytics/dashboard |
| Build command | npm install |
| Deploy command | npm run deploy |
analytics/dashboard/wrangler.jsonc 已包含:
| 配置 | 值 |
|---|---|
| 自定义域名 | static.analytics.agnet.top |
| 静态资源目录 | ./public |
部署后访问:
https://static.analytics.agnet.top
上报应用打开:
Invoke-RestMethod `
-Uri "https://analytics.agnet.top/track" `
-Method Post `
-ContentType "application/json" `
-Body '{"projectName":"yibiao-client","event":"app_open","version":"0.1.0","platform":"win32","arch":"x64","client_id":"test-client"}'
上报页面访问:
Invoke-RestMethod `
-Uri "https://analytics.agnet.top/track" `
-Method Post `
-ContentType "application/json" `
-Body '{"projectName":"yibiao-client","event":"page_view","page":"knowledge-base","version":"0.1.0","platform":"win32","arch":"x64","client_id":"test-client"}'
查询统计:
Invoke-RestMethod `
-Uri "https://analytics.agnet.top/api/summary?projectName=yibiao-client&days=30" `
-Method Get `
-Headers @{ Authorization = "Bearer <ADMIN_TOKEN>" }
Analytics Engine 写入后可能需要等待几十秒才能查到。
概览指标口径:
| 指标 | 说明 |
|---|---|
| 新增客户端 | 所选时间范围内创建、并且期间有过事件上报的去重客户端数 |
| 老客户端活跃 | 所选时间范围内活跃客户端数减去新增客户端数 |
| 每日统计中的客户端数 | 当天有任意打开或页面访问事件上报的去重客户端数 |
| 版本分布中的活跃客户端数 | 所选时间范围内该版本上报过事件的去重客户端数 |
| 配置使用中的文本模型和生图模型 | 所选时间范围内真实 AI 接口请求使用的模型名称、去重客户端数和请求次数 |
| 留存概览中的当日回访客户端 | 创建后 D1/D3/D7 当天再次打开 App 的客户端数 |
配置使用只采集模型名称、开关和枚举类配置,不采集 api_key、base_url、mineru_token、Prompt、响应内容、错误详情等敏感数据。
发布公告:
Invoke-RestMethod `
-Uri "https://analytics.agnet.top/api/notice" `
-Method Post `
-ContentType "application/json" `
-Headers @{ Authorization = "Bearer <ADMIN_TOKEN>" } `
-Body '{"projectName":"yibiao-client","title":"公告标题","content":"## Markdown 公告内容","enabled":true}'
客户端读取公告:
Invoke-RestMethod -Uri "https://analytics.agnet.top/notice?projectName=yibiao-client"
本地登录 Cloudflare 后,可实时查看 API Worker 日志:
cd analytics\worker
npx wrangler tail agnet-analytics-api --format pretty
如果尚未登录,先执行:
cd analytics\worker
npx wrangler login
查询接口失败时,Worker 会输出类似 [analytics] summary query failed ... 的错误日志。
不需要修改 Worker 配置。任意合法 projectName 都可以直接上报和查询。
项目名规则:
前端封装示例:
const ANALYTICS_ENDPOINT = 'https://analytics.agnet.top/track';
const PROJECT_NAME = 'my-other-app';
export async function track(event: 'app_open' | 'page_view', data: Record<string, string> = {}) {
try {
const enabled = localStorage.getItem('telemetry_enabled') !== 'false';
if (!enabled) return;
await fetch(ANALYTICS_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
projectName: PROJECT_NAME,
event,
page: data.page || '',
version: data.version || '',
platform: data.platform || '',
arch: data.arch || '',
client_id: getOrCreateAnonymousClientId(),
}),
});
} catch {
// 埋点失败不能影响业务。
}
}
function getOrCreateAnonymousClientId() {
const key = 'analytics_client_id';
const existing = localStorage.getItem(key);
if (existing) return existing;
const id = crypto.randomUUID();
localStorage.setItem(key, id);
return id;
}
页面访问示例:
track('page_view', {
page: 'settings',
version: appVersion,
platform: window.yibiao?.platform || '',
arch: 'x64',
});
| 问题 | 处理 |
|---|---|
unauthorized |
检查统计页面输入的 ADMIN_TOKEN 是否与 Worker Secret 一致 |
NOTICE_STORE is not configured |
先确认 Worker 的 Settings -> Bindings 存在 NOTICE_STORE,或本地运行 cd analytics\worker; npm run setup:notice-kv 后提交更新后的 wrangler.jsonc 并重新部署 Worker |
| 公告无法发布或读取 | 访问 https://analytics.agnet.top/health,确认 noticeStoreConfigured 为 true 后再测试公告发布 |
invalid projectName |
检查项目名格式 |
invalid event |
仅支持 app_open、page_view |
missing page |
page_view 必须传 page |
| 查询为空 | 先上报测试数据,等待几十秒再查 |
| 自定义域名未生效 | 检查对应 Worker 的 Settings -> Domains & Routes 和 wrangler.jsonc |
| 绑定不存在 | 检查 API Worker 的 Settings -> Bindings 是否存在 ANALYTICS |
Cloudflare Workers Builds 会在生产分支推送时触发构建。仓库里已将两个项目的 deploy 命令改为按目录校验:
| Worker | 监听目录 |
|---|---|
agnet-analytics-api |
analytics/worker |
agnet-analytics-dashboard |
analytics/dashboard |
如果本次提交没有修改对应目录,构建会成功结束,但不会执行 wrangler deploy。
如果需要强制重新部署,在 Cloudflare 的 Deploy command 临时改为:
FORCE_DEPLOY=1 npm run deploy
重试成功后再改回:
npm run deploy