Cloudflare Logpush → R2 Setup Guide
Cloudflare Logpush → R2 Setup Guide
Long-term log retention for bloqr-backend via Cloudflare Logpush to R2.
Why Logpush?
Cloudflare Workers Logs have a 24-hour TTL — logs older than one day are automatically discarded. Logpush delivers a continuous stream of Worker trace events and structured logs to an R2 bucket (or any supported destination), giving you indefinite retention at low cost.
Prerequisites
- Cloudflare account with Workers Logs and Logpush enabled (included in Workers Paid plans).
- An R2 bucket for log storage — a dedicated bucket is recommended to keep
logs separate from filter-list storage:
Terminal window # Create a dedicated R2 bucket for logs (recommended)wrangler r2 bucket create bloqr-backend-logs# Alternatively, re-use the existing FILTER_STORAGE bucket (not recommended —# mix of application data and logs makes queries harder) logpush = trueis already set inwrangler.toml— this flag enables Logpush eligibility for the Worker. The commands below create the actual delivery pipelines.
Setup commands
Worker trace requests (errors and non-ok outcomes)
Delivers a filtered stream of Worker invocation traces — useful for debugging failures without storing every successful request:
wrangler logpush create \ --dataset workers-trace-requests \ --destination-conf "r2://bloqr-backend-logs/{DATE}/trace-requests" \ --filter '{"where":{"key":"Outcome","operator":"!eq","value":"ok"}}' \ --fields "Outcome,ScriptName,EventTimestampMs,Logs,Exceptions,RequestUrl,RequestMethod,ResponseStatus"All Worker logs (structured JSON logs)
Delivers every structured log statement emitted by the Worker
(console.log, AdminLogger, AnalyticsService):
wrangler logpush create \ --dataset workers-logs \ --destination-conf "r2://bloqr-backend-logs/{DATE}/worker-logs"Manage Logpush jobs
# List all configured Logpush jobswrangler logpush list
# Inspect a specific jobwrangler logpush describe <job-id>
# Pause a job temporarilywrangler logpush update <job-id> --enabled false
# Delete a jobwrangler logpush delete <job-id>Querying logs from R2
Logs land in R2 as NDJSON (newline-delimited JSON), partitioned by date:
bloqr-backend-logs/ 2026-03-15/ trace-requests/ ← filtered Worker trace events worker-logs/ ← all structured log linesFetch and query with wrangler + jq
# List objects for a given datewrangler r2 object list bloqr-backend-logs --prefix "2026-03-15/"
# Download and query errorswrangler r2 object get bloqr-backend-logs "2026-03-15/trace-requests/..." \ | jq 'select(.Outcome != "ok") | {ts: .EventTimestampMs, url: .RequestUrl, status: .ResponseStatus}'Forward to Axiom or Grafana Loki
Add a second Logpush job targeting Axiom’s HTTP endpoint or a Loki push API:
# Example: forward to Axiom (replace with your actual endpoint and token)wrangler logpush create \ --dataset workers-logs \ --destination-conf "https://api.axiom.co/v1/datasets/<dataset>/ingest?token=<api-token>"Cost
| Resource | Rate |
|---|---|
| R2 storage | ~$0.015 / GB / month |
| R2 operations | $0.36 / million Class B reads |
| Logpush | No additional compute charge |
Typical Worker log volume is well under 1 GB/month for moderate traffic — total cost is usually under $0.05/month.
Notes
logpush = trueinwrangler.tomlonly marks the Worker as eligible for Logpush. The jobs above must be created separately viawrangler logpush createor the Cloudflare dashboard.- Each Logpush job is independent — you can have one for trace events and another for structured logs, each with different retention or destination settings.
- R2 bucket names must be globally unique within your Cloudflare account.