Claude-skill-registry cloudflare-worker-logs
Query and analyze Cloudflare Workers logs. Use for debugging workers, checking error rates, viewing request logs. Activates with phrases like "check worker logs", "what errors are in the worker", "cloudflare logs", "worker observability".
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/cloudflare-worker-logs" ~/.claude/skills/majiayu000-claude-skill-registry-cloudflare-worker-logs && rm -rf "$T"
skills/data/cloudflare-worker-logs/SKILL.mdCloudflare Worker Logs
Query historical logs from Cloudflare Workers using the Workers Observability API.
Requirements
Requires environment variables (should be defined in env already; if not, available via
uv run poe init-secrets):
CLOUDFLARE_ACCOUNT_IDCLOUDFLARE_API_TOKEN
Real-time Logs
For real-time log streaming (not historical queries), use wrangler tail instead:
cd terraform/cloudflare && wrangler tail llms --format pretty
This requires a terminal session that stays open.
Available Scripts
All scripts are in the
scripts/ directory relative to this skill. Run them with:
uv run scripts/<script_name>.py [args]
cf_workers_list.py
List all Workers in the Cloudflare account. If you only need details of a single Worker, use
cf_worker_get.py instead.
uv run scripts/cf_workers_list.py
No arguments required.
cf_worker_get.py
Get the details of a Cloudflare Worker.
uv run scripts/cf_worker_get.py <script_name>
Arguments:
(required): The name of the worker script to retrievescript_name
cf_observability_keys.py
Find keys in the Workers Observability data.
Best Practices:
- Set a high limit (1000+) to ensure you see all available keys
- Add the
filter to narrow results to a specific Worker$metadata.service
Troubleshooting:
- If expected fields are missing, verify the Worker is actively logging
- For empty results, try broadening your time range
uv run scripts/cf_observability_keys.py [options]
Options:
: Time range in minutes (default: 60, max: 10080 for 7 days)--minutes N
: Max keys to return (default: 100, set high like 1000 for comprehensive list)--limit N
: Pattern to match key names--key-needle PATTERN
: Treat key-needle as regex--key-needle-regex
: General text search in log content--needle TEXT
: Treat needle as regex--needle-regex
: Filter (can be repeated)--filter KEY:OP:TYPE:VALUE
Example:
uv run scripts/cf_observability_keys.py --limit 1000 --filter '$metadata.service:eq:string:llms'
cf_observability_values.py
Find values in the Workers Observability Data.
Troubleshooting:
- For no results, verify the field exists using
firstcf_observability_keys.py - If expected values are missing, try broadening your time range
uv run scripts/cf_observability_values.py <key> [options]
Arguments:
(required): The key to get values for (e.g.,key
,$metadata.service
)$metadata.level
Options:
: Type of the key (default: string)--key-type {string,number,boolean}
: Time range in minutes (default: 60, max: 10080 for 7 days)--minutes N
: Max values to return (default: 50)--limit N
: Pattern to match values--needle PATTERN
: Treat needle as regex--needle-regex
: Filter (can be repeated)--filter KEY:OP:TYPE:VALUE
Example:
uv run scripts/cf_observability_values.py '$metadata.service' --limit 100
cf_observability_query.py
Query the Workers Observability API to analyze logs and metrics from Cloudflare Workers.
Core Capabilities:
This script provides three primary views of your Worker data:
- events (default): Browse individual request logs and errors
- calculations: Compute statistics across requests (avg, p99, etc.)
- invocations: Find specific request invocations matching criteria
Examples by View Type:
Events View:
- "Show all errors for worker llms in the last 30 minutes"
- "Show events where the path contains /api"
Calculation View:
- "What is the p99 wall time for worker llms?"
- "Count requests grouped by status code"
Invocation View:
- "Find a request that resulted in a 500 error"
- "List successful requests with status 200"
Filtering Best Practices:
- Before applying filters, use
andcf_observability_keys.py
to confirm available fields and valuescf_observability_values.py - Common filter fields:
,$metadata.service
,$metadata.origin
,$metadata.trigger
,$metadata.message
,$metadata.level$metadata.requestId
Calculation Best Practices:
- Before applying calculations, use
to confirm the key existscf_observability_keys.py
Troubleshooting:
- If no results returned, try broadening the time range or relaxing filters
- For errors about invalid fields, use
to see available optionscf_observability_keys.py
uv run scripts/cf_observability_query.py [options]
Options:
: Query view type (default: events)--view {events,calculations,invocations}
: Time range in minutes (default: 60, max: 10080 for 7 days)--minutes N
: Max results to return (default: 10)--limit N
: Pagination offset (use--offset ID
from previous results)$metadata.id
: Numeric offset for pagination--offset-by N
: Pagination direction--offset-direction {next,prev}
: Dry run - validate query without executing--dry
: Time bucket granularity for calculations--granularity N
: Filter (can be repeated)--filter KEY:OP:TYPE:VALUE
: How to combine filters (default: and)--filter-combination {and,or}
: Calculation (can be repeated, for calculations view)--calculation OPERATOR[:KEY[:TYPE[:ALIAS]]]
: Field to group by (can be repeated)--group-by VALUE[:TYPE]
: Calculation alias to sort by--order-by ALIAS
: Sort order (default: desc)--order {asc,desc}
: Full-text search in log content--needle TEXT
: Treat needle as regex--needle-regex
Filter Format:
Filters use format
key:operation:type:value where:
: Field name (e.g.,key
)$metadata.service
: One ofoperation
,includes
,not_includes
,starts_with
,regex
,exists
,is_null
,in
,not_in
,eq
,neq
,gt
,gte
,ltlte
: One oftype
,string
,numberboolean
: Comparison valuevalue
Calculation Format:
Calculations use format
operator[:key[:key_type[:alias]]] where:
: One ofoperator
,uniq
,count
,max
,min
,sum
,avg
,median
,p001
,p01
,p05
,p10
,p25
,p75
,p90
,p95
,p99
,p999
,stddevvariance
: Field to calculate on (optional forkey
)count
: Type of the key (default: number)key_type
: Name for this calculation in resultsalias
Examples:
Show recent errors for the llms worker:
uv run scripts/cf_observability_query.py --filter '$metadata.service:eq:string:llms' --filter '$metadata.level:eq:string:error' --limit 20
Get p99 wall time grouped by service:
uv run scripts/cf_observability_query.py --view calculations --calculation 'p99:wallTime:number:p99_wall' --group-by '$metadata.service'
Count requests by status code:
uv run scripts/cf_observability_query.py --view calculations --calculation 'count' --group-by 'response.status:number'
Search for specific text in logs:
uv run scripts/cf_observability_query.py --needle 'timeout' --minutes 120
cf_analytics_query.py
Query Workers Analytics Engine datasets using the SQL API. This is for custom metrics written via
writeDataPoint(), not request logs (use cf_observability_query.py for logs).
Key Features:
- Automatic semantic aliases for known datasets (e.g.,
→blob1
,path
→double1
)latency_ms - Built-in sampling-aware aggregation helpers
- Raw SQL mode for complex queries
Schema for llms_usage dataset:
| Raw Field | Semantic Name | Description |
|---|---|---|
| | HTTP method or "unauthorized" |
| | Request path |
| | HTTP status code |
| | Category: provider, amp-tab, amp-telemetry, amp-admin, management, oauth, other |
| | LLM provider: anthropic, google, openai, etc. (empty for non-provider requests) |
| | Model name from path (Gemini only; empty for Anthropic/OpenAI where model is in body) |
| | Client identifier: "VS Code CLI", "VS Code Insiders", "Bun", "node", etc. |
| | Response time in milliseconds |
| | Input/prompt tokens (non-streaming provider requests only; 0 for streaming) |
| | Output/completion tokens (non-streaming provider requests only; 0 for streaming) |
uv run scripts/cf_analytics_query.py [options]
Options:
: Analytics Engine dataset (default: llms_usage)--dataset NAME
: Time range in minutes (default: 60)--minutes N
: Max results (default: 20)--limit N
: Field to select (can be repeated). Omit for default fields with aliases.--field FIELD
: Aggregation expression (e.g.,--agg EXPR
). Can be repeated.SUM(_sample_interval) AS count
: Field to group by (can be repeated). Use with --agg.--group-by FIELD
: WHERE clause condition (can be repeated). E.g.,--where CONDITION"blob2 = '401'"
: Field or alias to order by--order-by FIELD
: Sort order (default: desc)--order {asc,desc}
: Execute raw SQL (ignores other query options)--raw QUERY
: Output format (default: json)--format {json,jsonl,tsv}
: Print generated SQL--show-query
: Show schema mapping for dataset--show-schema
: List available datasets--list-datasets
Examples:
Show recent events with semantic field names:
uv run scripts/cf_analytics_query.py --limit 10
Request counts by path and status (last 24 hours):
uv run scripts/cf_analytics_query.py --agg 'SUM(_sample_interval) AS request_count' --group-by blob1 --group-by blob2 --minutes 1440
Average latency by method:
uv run scripts/cf_analytics_query.py --agg 'SUM(_sample_interval * double1) / SUM(_sample_interval) AS avg_latency_ms' --group-by index1
Filter by status code (show 401 errors):
uv run scripts/cf_analytics_query.py --where "blob2 = '401'" --minutes 1440
Raw SQL query:
uv run scripts/cf_analytics_query.py --raw "SELECT blob1, SUM(_sample_interval) AS count FROM llms_usage GROUP BY blob1 ORDER BY count DESC LIMIT 10"
Sampling Notes:
Analytics Engine may sample high-volume data. Always use
_sample_interval for accurate counts:
- Count:
instead ofSUM(_sample_interval)COUNT() - Sum:
instead ofSUM(_sample_interval * field)SUM(field) - Average:
instead ofSUM(_sample_interval * field) / SUM(_sample_interval)AVG(field)
Preferred Filter Keys
These keys are faster and always available:
: Worker name$metadata.service
: Trigger type (fetch, scheduled, queue, etc.)$metadata.origin
: Request method and path (e.g., GET /users)$metadata.trigger
: Log message text$metadata.message
: Error message (when applicable)$metadata.error
: Log level (log, warn, error)$metadata.level
: Unique request identifier$metadata.requestId
cf_ai_gateway_logs.py
Query AI Gateway logs with conversation-focused interface. Each log entry contains the full conversation history (Anthropic Messages API format), so viewing the latest entry for a conversation gives you everything.
Modes (mutually exclusive, one required):
: List conversations grouped by conversation-id metadata--conversations
: Get messages from a specific conversation's latest log--conversation ID
: Dump raw logs to /tmp file (prints filename to avoid context overload)--raw
uv run scripts/cf_ai_gateway_logs.py <mode> [options]
Common Options:
: AI Gateway ID (default: llms)--gateway NAME
: Time range in minutes (default: 60)--minutes N
: Max results (default: 20)--limit N
Options for --conversation mode:
: Only show the last N messages (default: 4, use 0 for all)--last-messages N
: Include the full tools array (omitted by default)--include-tools
: Include the full system prompt (omitted by default)--include-system
: Truncate text content to N characters--truncate CHARS
Options for --raw mode:
: Include request bodies in dump (slow, fetches each individually)--include-bodies
Examples:
List recent conversations:
uv run scripts/cf_ai_gateway_logs.py --conversations --limit 10
Get last 10 messages from a conversation:
uv run scripts/cf_ai_gateway_logs.py --conversation T-xxx-xxx --last-messages 10
Dump 100 raw logs to file:
uv run scripts/cf_ai_gateway_logs.py --raw --limit 100
Include request bodies in raw dump:
uv run scripts/cf_ai_gateway_logs.py --raw --limit 10 --include-bodies
Workflow Example:
- List conversations:
uv run scripts/cf_ai_gateway_logs.py --conversations - Pick a conversation ID from the output
- View messages:
uv run scripts/cf_ai_gateway_logs.py --conversation T-xxx --last-messages 10
Regex Notes
For
regex operations, Cloudflare uses ClickHouse RE2 syntax (not PCRE/JavaScript):
- No lookaheads/lookbehinds
- Escape backslashes with double backslash