circle-info
Version 2 is coming up

Cloudflare (Worker)

Overview

This integration uses Cloudflare Logpush to stream CDN and edge activity logs directly to the Agent Analytics ingestion endpoint. Logpush provides a reliable, high throughput mechanism for exporting real time log data to external HTTPS destinations, making it ideal for monitoring traffic behavior and AI agent interactions at scale.

circle-info

For additional details about Logpush, refer to Cloudflare’s official documentation. Cloudflare Worker is free up to 100K requests per day, for additional details, refer to Cloudflare’s official documentationarrow-up-right.

1

Step 1

Open Terminal and install the following npm

npm create [email protected] -- log-collector

Select the "worker only”

sa

Select the “TypeScript” language.

Now the CLI will create a new project with the name log-collector and install the necessary dependencies.Select Git for version control.

VERY IMPORTANT - DO NOT DEPLOY YET

2

Step 2

Configure your worker

Edit your wrangler.jsonc file to configure the LIMY_KEY environment variable and the route binding:

circle-check
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "log-collector",
  "main": "src/index.ts",
  "compatibility_date": "2025-12-09",
  "observability": {
    "enabled": true
  },
  "route": {
    "pattern": "example.com/*",
    "zone_name": "example.com"
  },
  "vars": { "LIMY_URL": "https://stream.getlimy.ai" }
}

Then copy the TypeScript code into src/index.ts:

triangle-exclamation
/**
 * Cloudflare Worker for Log Collection
 *
 * This worker captures HTTP request/response data and forwards it to Limy's log collection API.
 * It runs as a middleware, meaning it doesn't interfere with the actual request handling.
 */

export interface Env {
     LIMY_KEY: string;
    LIMY_URL: string;
}

export default {
    async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {

    // Get the original response
    const response = await fetch(request);

    // Clone the response so we can read it multiple times
        const responseClone = response.clone();
    
        ctx.waitUntil(handleRequest(request, responseClone, env));
        return response;
    }
} satisfies ExportedHandler<Env>;

async function handleRequest(request: Request, response: Response, env: Env) {
	const requestUrl = new URL(request.url);
	const cf = request.cf;
  
	const headerSize = Array.from(response.headers.entries())
	  .reduce((total, [key, value]) => total + key.length + value.length + 4, 0);
	
	const responseBody = await response.blob();
	const bodySize = responseBody.size;

    // Total bytes sent includes headers and body
    const totalBytesSent = headerSize + bodySize;

    const logData = {
		// Timing
		timestamp: Date.now(),
		
		// Request basics
		host: requestUrl.hostname,
		method: request.method,
		pathname: requestUrl.pathname,
		query_params: Object.fromEntries(requestUrl.searchParams),
		
		// Client info
		ip: request.headers.get('cf-connecting-ip'),
		userAgent: request.headers.get('user-agent'),
		referer: request.headers.get('referer'),
		acceptLanguage: request.headers.get('accept-language'),
		
		// Response info
		bytes: headerSize + bodySize,
		status: response.status,
		contentType: response.headers.get('content-type'),
		
		// Cloudflare request ID
		rayId: request.headers.get('cf-ray'),
		
		// Geographic (from cf object)
		country: cf?.country,
		city: cf?.city,
		region: cf?.region,
		regionCode: cf?.regionCode,
		continent: cf?.continent,
		postalCode: cf?.postalCode,
		latitude: cf?.latitude,
		longitude: cf?.longitude,
		timezone: cf?.timezone,
		
		// Network
		asn: cf?.asn,
		asOrganization: cf?.asOrganization,
		colo: cf?.colo,  // Cloudflare datacenter
		
		// Connection
		httpProtocol: cf?.httpProtocol,
		tlsVersion: cf?.tlsVersion,
		tlsCipher: cf?.tlsCipher,
    }

    await fetch(env.LIMY_URL, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-API-Key': env.LIMY_KEY,
			'User-Agent': 'Cloudflare-Worker-Logs'
        },
        body: JSON.stringify([logData])
    }).catch(error => console.error('Failed to send logs:', error))
}
3

Step 3

Login to Cloudflare & Deploy Your Worker

Use the Wrangler CLI to deploy the Worker:

//Login to Cloudflare
npx wrangler login

Configure Limy API key

Secrets is a feature of Cloudflare Workers that allows you to store sensitive information like API keys in a secure environment.

//Configure the API key secret
npx wrangler secret put LIMY_KEY
4

Step 4

Deploy your worker

// Deploy the worker
npx wrangler deploy

Verify your Worker is functioning correctly:

Navigate to Limy dashboard and see Bot Events!

circle-check

Need More Help?

Last updated