INTEGRITY Cloudflare Docs

Write to Analytics Engine

Workers Analytics Engine provides time-series analytics at scale. Use it to track custom metrics, build usage-based billing, or understand service health on a per-customer basis.

Unlike logs, Analytics Engine is designed for aggregated queries over high-cardinality data. Writes are non-blocking and do not impact request latency.

Configure the binding

Add an Analytics Engine dataset binding to your Wrangler configuration file. The dataset is created automatically when you first write to it.

{
	"analytics_engine_datasets": [
		{
			"binding": "ANALYTICS",
			"dataset": "my_dataset",
		},
	],
}
[[analytics_engine_datasets]]
binding = "ANALYTICS"
dataset = "my_dataset"

Write data points

export default {
	async fetch(request, env) {
		const url = new URL(request.url);

		// Write a page view event
		env.ANALYTICS.writeDataPoint({
			blobs: [
				url.pathname,
				request.headers.get("cf-connecting-country") ?? "unknown",
			],
			doubles: [1], // Count
			indexes: [url.hostname], // Sampling key
		});

		// Write a response timing event
		const start = Date.now();
		const response = await fetch(request);
		const duration = Date.now() - start;

		env.ANALYTICS.writeDataPoint({
			blobs: [url.pathname, response.status.toString()],
			doubles: [duration],
			indexes: [url.hostname],
		});

		// Writes are non-blocking - no need to await or use waitUntil()
		return response;
	},
};
interface Env {
	ANALYTICS: AnalyticsEngineDataset;
}

export default {
	async fetch(request: Request, env: Env): Promise<Response> {
		const url = new URL(request.url);

		// Write a page view event
		env.ANALYTICS.writeDataPoint({
			blobs: [
				url.pathname,
				request.headers.get("cf-connecting-country") ?? "unknown",
			],
			doubles: [1], // Count
			indexes: [url.hostname], // Sampling key
		});

		// Write a response timing event
		const start = Date.now();
		const response = await fetch(request);
		const duration = Date.now() - start;

		env.ANALYTICS.writeDataPoint({
			blobs: [url.pathname, response.status.toString()],
			doubles: [duration],
			indexes: [url.hostname],
		});

		// Writes are non-blocking - no need to await or use waitUntil()
		return response;
	},
};

Data point structure

Each data point consists of:

Query your data

Query your data using the SQL API:

curl "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/analytics_engine/sql" \
  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  --data "SELECT blob1 AS path, SUM(_sample_interval) AS views FROM my_dataset WHERE timestamp > NOW() - INTERVAL '1' HOUR GROUP BY path ORDER BY views DESC LIMIT 10"