This site is not affiliated with or endorsed by Cloudflare, Inc. It showcases deployable experiments across most Cloudflare products.
Edge Platform

Tail Logger

Tail Worker that stores recent traces from another Worker in KV - live log tail and debugging pattern

A Tail Worker that receives TraceItem batches from producer Workers, keeps the last 50 events in Workers KV, and exposes them over HTTP for inspection.

Features

  • tail handler - receives TraceItem batches and stores key recent
  • GET /logs - read recent events
  • DELETE /logs - clear stored events

API Reference

GET /logs

Example Request

curl "https://your-worker.workers.dev/logs"

Success Response

{
  "events": [
    {
      "scriptName": "my-producer",
      "outcome": "ok",
      "eventTimestamp": 1710000000000,
      "logs": ["request handled"]
    }
  ],
  "count": 1
}

DELETE /logs

Example Request

curl -X DELETE "https://your-worker.workers.dev/logs"

Success Response

{
  "cleared": true
}

Configuring a producer

In the producer Worker's wrangler.json, add this Worker as a tail consumer:

{
  "name": "my-producer",
  "tail_consumers": [{ "service": "tail-logger" }]
}

Deploy tail-logger first, then the producer. When the producer handles requests, its traces are delivered to this Worker's tail handler.

Use Cases

  • Learn Tail Workers / tail_consumers wiring
  • Debug producer Workers without streaming wrangler tail locally
  • Keep a short rolling window of outcomes and console logs
  • Teach observability patterns across Workers

Limitations

  • Stores only the last 50 events in a single KV key
  • Tail delivery from another Worker typically requires deployed Workers
  • No filtering UI - raw recent events only
  • No authentication on /logs

Use in your project

Copy these files into an existing Worker. Prefer Deployment to try the full experiment first. Source: apps/experiments/tail-logger.

DependenciesNoneBindingsKVPlatformWorkers runtime
import { MAX_RECENT_EVENTS, RECENT_KEY } from "../constants/defaults";import type { TailLogEntry } from "../types/log";export function extractLogMessages(event: TraceItem): string[] {  if (!event.logs || !Array.isArray(event.logs)) return [];  return event.logs.map((log) => {    if (typeof log.message === "string") return log.message;    if (Array.isArray(log.message)) {      return log.message.map((part) => String(part)).join(" ");    }    return String(log.message ?? "");  });}export function toTailLogEntry(event: TraceItem): TailLogEntry {  return {    scriptName: event.scriptName ?? "unknown",    outcome: event.outcome,    eventTimestamp: event.eventTimestamp ?? Date.now(),    logs: extractLogMessages(event),  };}export async function readRecent(kv: KVNamespace): Promise<TailLogEntry[]> {  const raw = await kv.get(RECENT_KEY);  if (!raw) return [];  try {    const parsed = JSON.parse(raw) as unknown;    if (!Array.isArray(parsed)) return [];    return parsed as TailLogEntry[];  } catch {    return [];  }}export async function appendTailEvents(  kv: KVNamespace,  events: TraceItem[]): Promise<TailLogEntry[]> {  const existing = await readRecent(kv);  const incoming = events.map(toTailLogEntry);  const merged = [...incoming, ...existing].slice(0, MAX_RECENT_EVENTS);  await kv.put(RECENT_KEY, JSON.stringify(merged));  return merged;}export async function clearRecent(kv: KVNamespace): Promise<void> {  await kv.delete(RECENT_KEY);}

Deployment

Click the deploy button

Deploy to Cloudflare Workers

Configure KV and producers

Create a KV namespace and bind it as TAIL_LOGS. Deploy this Worker, then add "tail_consumers": [{ "service": "tail-logger" }] to producer Workers.

Test your deployment

Trigger the producer, then:

curl "https://your-worker.workers.dev/logs"

Local Development

cd apps/experiments/tail-logger
npm install
npm run dev
curl "http://localhost:8787/logs"

Tail delivery from another Worker typically requires deployed Workers; unit tests call the tail export directly with mock events.

Configuration

wrangler.json declares:

  • KV namespace TAIL_LOGS

Cloudflare Features Used

On this page