Loading...
Loading...
Compare original and translation side by side
wrangler analytics-engine create my-datasetwrangler.jsonc{
"analytics_engine_datasets": [
{
"binding": "USER_EVENTS",
"dataset": "my-dataset"
}
]
}wrangler analytics-engine create my-datasetwrangler.jsonc{
"analytics_engine_datasets": [
{
"binding": "USER_EVENTS",
"dataset": "my-dataset"
}
]
}| Use Case | Why Analytics Engine |
|---|---|
| User behavior tracking | High-cardinality data (userId, sessionId, etc.) |
| Billing/usage metrics | Per-tenant aggregation with doubles |
| Custom telemetry | Non-blocking writes, queryable with SQL |
| A/B test metrics | Index by experiment ID, query results |
| API usage tracking | Count requests per customer/endpoint |
| 使用场景 | 选择Analytics Engine的原因 |
|---|---|
| 用户行为追踪 | 支持高基数数据(如userId、sessionId等) |
| 账单/使用指标 | 支持基于租户的数值聚合 |
| 自定义遥测 | 非阻塞写入,可通过SQL查询 |
| A/B测试指标 | 按实验ID索引,可查询结果 |
| API使用追踪 | 统计每个客户/端点的请求次数 |
| Operation | API | Notes |
|---|---|---|
| Write event | | Non-blocking, do NOT await |
| Metrics | | Up to 20 numeric values |
| Labels | | Up to 20 text values |
| Grouping | | 1 index per datapoint (max 96 bytes) |
| Query data | SQL API via REST | GraphQL also available |
| 操作 | API | 说明 |
|---|---|---|
| 写入事件 | | 非阻塞,请勿使用await |
| 指标 | | 最多支持20个数值 |
| 标签 | | 最多支持20个文本值 |
| 分组 | | 每个数据点1个索引(最大96字节) |
| 查询数据 | 基于REST的SQL API | 同时支持GraphQL |
| Field Type | Purpose | Limit | Example |
|---|---|---|---|
| doubles | Numeric metrics (counters, gauges, latency) | 20 per datapoint | |
| blobs | Text labels (URLs, names, IDs) | 20 per datapoint | |
| indexes | Grouping key (userId, tenantId, etc.) | 1 per datapoint | |
| 字段类型 | 用途 | 限制 | 示例 |
|---|---|---|---|
| doubles | 数值指标(计数器、仪表盘、延迟) | 每个数据点最多20个 | |
| blobs | 文本标签(URL、名称、ID) | 每个数据点最多20个 | |
| indexes | 分组键(userId、tenantId等) | 每个数据点最多1个 | |
interface Env {
USER_EVENTS: AnalyticsEngineDataset;
}
export default {
async fetch(req: Request, env: Env): Promise<Response> {
let url = new URL(req.url);
let path = url.pathname;
let userId = url.searchParams.get("userId");
// Write a datapoint for this visit, associating the data with
// the userId as our Analytics Engine 'index'
env.USER_EVENTS.writeDataPoint({
// Write metrics data: counters, gauges or latency statistics
doubles: [],
// Write text labels - URLs, app names, event_names, etc
blobs: [path],
// Provide an index that groups your data correctly.
indexes: [userId],
});
return Response.json({
hello: "world",
});
},
};interface Env {
USER_EVENTS: AnalyticsEngineDataset;
}
export default {
async fetch(req: Request, env: Env): Promise<Response> {
let url = new URL(req.url);
let path = url.pathname;
let userId = url.searchParams.get("userId");
// 写入该访问对应的数据点,将数据与作为Analytics Engine 'index'的userId关联
env.USER_EVENTS.writeDataPoint({
// 写入指标数据:计数器、仪表盘或延迟统计
doubles: [],
// 写入文本标签 - URL、应用名称、事件名称等
blobs: [path],
// 提供可正确分组数据的索引
indexes: [userId],
});
return Response.json({
hello: "world",
});
},
};interface Env {
API_METRICS: AnalyticsEngineDataset;
}
export default {
async fetch(req: Request, env: Env): Promise<Response> {
const start = Date.now();
const url = new URL(req.url);
const apiKey = req.headers.get("x-api-key") || "anonymous";
const endpoint = url.pathname;
try {
// Handle API request...
const response = await handleApiRequest(req);
const duration = Date.now() - start;
// Track successful request
env.API_METRICS.writeDataPoint({
doubles: [duration, response.headers.get("content-length") || 0],
blobs: [endpoint, "success", response.status.toString()],
indexes: [apiKey],
});
return response;
} catch (error) {
const duration = Date.now() - start;
// Track failed request
env.API_METRICS.writeDataPoint({
doubles: [duration, 0],
blobs: [endpoint, "error", error.message],
indexes: [apiKey],
});
return new Response("Error", { status: 500 });
}
},
};interface Env {
API_METRICS: AnalyticsEngineDataset;
}
export default {
async fetch(req: Request, env: Env): Promise<Response> {
const start = Date.now();
const url = new URL(req.url);
const apiKey = req.headers.get("x-api-key") || "anonymous";
const endpoint = url.pathname;
try {
// 处理API请求...
const response = await handleApiRequest(req);
const duration = Date.now() - start;
// 追踪成功的请求
env.API_METRICS.writeDataPoint({
doubles: [duration, response.headers.get("content-length") || 0],
blobs: [endpoint, "success", response.status.toString()],
indexes: [apiKey],
});
return response;
} catch (error) {
const duration = Date.now() - start;
// 追踪失败的请求
env.API_METRICS.writeDataPoint({
doubles: [duration, 0],
blobs: [endpoint, "error", error.message],
indexes: [apiKey],
});
return new Response("Error", { status: 500 });
}
},
};awaitwriteDataPoint()// ❌ WRONG - Do not await
await env.USER_EVENTS.writeDataPoint({ ... });
// ✅ CORRECT - Fire and forget
env.USER_EVENTS.writeDataPoint({ ... });writeDataPoint()await// ❌ 错误示例 - 不要使用await
await env.USER_EVENTS.writeDataPoint({ ... });
// ✅ 正确示例 - 无需等待
env.USER_EVENTS.writeDataPoint({ ... });https://api.cloudflare.com/client/v4/accounts/{account_id}/analytics_engine/sqlhttps://api.cloudflare.com/client/v4/accounts/{account_id}/analytics_engine/sqlSELECT
timestamp,
blob1 AS path,
index1 AS userId
FROM USER_EVENTS
WHERE timestamp > NOW() - INTERVAL '1' DAY
ORDER BY timestamp DESC
LIMIT 100SELECT
timestamp,
blob1 AS path,
index1 AS userId
FROM USER_EVENTS
WHERE timestamp > NOW() - INTERVAL '1' DAY
ORDER BY timestamp DESC
LIMIT 100SELECT
index1 AS apiKey,
COUNT(*) AS request_count,
AVG(double1) AS avg_duration_ms,
SUM(double2) AS total_bytes
FROM API_METRICS
WHERE timestamp > NOW() - INTERVAL '7' DAY
GROUP BY apiKey
ORDER BY request_count DESCSELECT
index1 AS apiKey,
COUNT(*) AS request_count,
AVG(double1) AS avg_duration_ms,
SUM(double2) AS total_bytes
FROM API_METRICS
WHERE timestamp > NOW() - INTERVAL '7' DAY
GROUP BY apiKey
ORDER BY request_count DESCcurl "https://api.cloudflare.com/client/v4/accounts/{account_id}/analytics_engine/sql" \
--header "Authorization: Bearer <API_TOKEN>" \
--data "SHOW TABLES"curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/analytics_engine/sql" \
--header "Authorization: Bearer <API_TOKEN>" \
--data "SHOW TABLES"double1double2double20blob1blob2blob20index1index2index20ASSELECT
double1 AS response_time,
blob1 AS endpoint,
index1 AS user_id
FROM my_datasetdouble1double2double20blob1blob2blob20index1index2index20ASSELECT
double1 AS response_time,
blob1 AS endpoint,
index1 AS user_id
FROM my_dataset{
"name": "analytics-engine-example",
"main": "src/index.ts",
"compatibility_date": "2025-02-11",
"analytics_engine_datasets": [
{
"binding": "USER_EVENTS",
"dataset": "user-events"
},
{
"binding": "API_METRICS",
"dataset": "api-metrics"
}
]
}{
"name": "analytics-engine-example",
"main": "src/index.ts",
"compatibility_date": "2025-02-11",
"analytics_engine_datasets": [
{
"binding": "USER_EVENTS",
"dataset": "user-events"
},
{
"binding": "API_METRICS",
"dataset": "api-metrics"
}
]
}interface Env {
// Analytics Engine dataset binding
USER_EVENTS: AnalyticsEngineDataset;
}
// Datapoint structure
interface AnalyticsEngineDataPoint {
doubles?: number[]; // Up to 20 numeric values
blobs?: string[]; // Up to 20 text values
indexes?: string[]; // Up to 20 grouping keys
}interface Env {
// Analytics Engine数据集绑定
USER_EVENTS: AnalyticsEngineDataset;
}
// 数据点结构
interface AnalyticsEngineDataPoint {
doubles?: number[]; // 最多20个数值
blobs?: string[]; // 最多20个文本值
indexes?: string[]; // 最多20个分组键
}writeDataPoint()writeDataPoint()env.SESSIONS.writeDataPoint({
doubles: [sessionDuration, pageViews, eventsCount],
blobs: [browser, country, deviceType],
indexes: [userId, sessionId],
});env.SESSIONS.writeDataPoint({
doubles: [sessionDuration, pageViews, eventsCount],
blobs: [browser, country, deviceType],
indexes: [userId, sessionId],
});env.ERRORS.writeDataPoint({
doubles: [1], // Error count
blobs: [errorType, errorMessage.slice(0, 256), endpoint],
indexes: [userId, appVersion],
});env.ERRORS.writeDataPoint({
doubles: [1], // 错误计数
blobs: [errorType, errorMessage.slice(0, 256), endpoint],
indexes: [userId, appVersion],
});env.REVENUE.writeDataPoint({
doubles: [amountCents, taxCents, discountCents],
blobs: [productId, currency, paymentMethod],
indexes: [customerId, merchantId],
});env.REVENUE.writeDataPoint({
doubles: [amountCents, taxCents, discountCents],
blobs: [productId, currency, paymentMethod],
indexes: [customerId, merchantId],
});// Before: D1
await env.DB.prepare("INSERT INTO events (userId, event) VALUES (?, ?)")
.bind(userId, event)
.run();
// After: Analytics Engine
env.EVENTS.writeDataPoint({
blobs: [event],
indexes: [userId],
}); // Non-blocking, no await// 之前:D1
await env.DB.prepare("INSERT INTO events (userId, event) VALUES (?, ?)")
.bind(userId, event)
.run();
// 之后:Analytics Engine
env.EVENTS.writeDataPoint({
blobs: [event],
indexes: [userId],
}); // 非阻塞,无需await