Stream CDN request logs to Obsero
Every HTTP request hitting your CDN becomes one POST to Obsero, so AI agent traffic can be classified on the request headers it actually sent.
Two working end-to-end implementations — AWS CloudFront and Google Cloud — plus a demo site and a traffic harness for each. This is a starting point, not a product. Fork it, keep the parts that match your stack, throw away the rest.
Quickstart →
One command, four steps: a mock site, the pipeline, connect it, tear it down.
The contract →
The URL and the payload. The only thing you have to get right.
AWS →
CloudFront → Firehose → Lambda adapter. One real decision to make.
Google Cloud →
LB request logs → Pub/Sub → Cloud Run adapter. Named headers on the cheap path.
#Pick your path
The same repo serves three kinds of reader. Start from the row that sounds like you.
| You are | Do this | Time |
|---|---|---|
| New to this — you want to see it work before you touch anything real | Follow the quickstart checklist. Every step says what to run and
what you should see. setup.sh does the work; nothing needs editing. |
~20 min, including the CDN deploy |
| Already running a site on CloudFront — you want your real traffic | Skip the mock site: deploy the pipeline, then pick your distribution from the list. Your distribution is never modified. | ~5 min |
| Experienced with Terraform — you want the module in your own stack | Read one module block and what it
creates, then the code itself: aws/ingestion/main.tf and the adapter,
aws/ingestion/lambda/adapter/index.mjs. Or skip the infrastructure entirely and call
sendEvent from wherever you already see requests. |
an afternoon to review |
| A coding agent, or working with one | Read AGENTS.md in the repo, or llms.txt for these docs as
Markdown. More below. |
— |
Every file path on these pages links to that file on GitHub, and each page ends with the code it describes — so you can check any claim here against the source.
#The shape of it
Obsero cares about exactly two things: the URL you POST to, and the payload. Everything else — which cloud, which log source, which language, whether you batch, whether you use Terraform at all — is your call.
POST https://analytics-staging.obsero.ai/v1/events
content-type: application/json
x-obsero-domain: acme.com # which site this event belongs to
x-obsero-key: <tracking ID> # proves you own it
{
"path": "/pricing",
"method": "GET",
"statusCode": 200,
"headers": {
"host": "acme.com",
"user-agent": "Mozilla/5.0 ...; compatible; ChatGPT-User/1.0; +https://openai.com/bot",
"accept": "*/*",
"signature-agent": "\"https://chatgpt.com\""
}
}
That is the whole integration. Read the contract in full →
#Which one do I want?
| Your setup | Start here | Why |
|---|---|---|
| CloudFront in front of anything | AWS | Two log sources: cheap (User-Agent only) or full headers for ~$11/mo. |
| Google Cloud load balancer + Cloud CDN | GCP | Full headers on the cheap path — no trade to make. |
| A plain GCS bucket behind Cloud CDN | GCP, caveat first | Backend buckets emit no request logs at all. Your origin has to be a backend service. |
| Cloudflare, Fastly, Akamai, a bare origin | none of them | Import sendEvent and call it from wherever you already see requests. That is the entire integration. |
#What's in the repo
obsero.mjs the contract: build an event, validate it, POST it
setup.sh the interactive installer
destroy.sh teardown, plus a sweep for resources Terraform lost track of
aws/ CloudFront -> Firehose -> Lambda adapter -> Obsero
gcp/ LB request logs -> Pub/Sub -> Cloud Run adapter -> Obsero
docs/ this site
Each cloud directory has the same three parts:
ingestion/ the Terraform module you would actually ship
site/ a demo site to point it at, so you can see traffic flow
test/ a traffic harness: 19 client personas, then score what arrived
Both ingestion/ modules deploy on their own. site/ and
test/ exist to prove the thing works and are the first things to delete once it
does.
#If you work with a coding agent
There are AGENTS.md files at the repo root and in each cloud directory. They
carry the contract, the setup order, the failure modes that look like bugs but are not, and the
handful of things in the Terraform that must not be “cleaned up” because they fail
silently when removed. Point your agent at them before it touches anything.
| File | Read by | What is in it |
|---|---|---|
AGENTS.md | any agent working in the repo | the contract, the menu and its flags, the order to debug in, the rules |
CLAUDE.md | Claude Code, which looks for this name | imports AGENTS.md, so there is one source of truth |
aws/AGENTS.md, gcp/AGENTS.md | an agent working on one cloud | symptom → cause → fix, and what each step of setup.sh applies |
llms.txt | an agent reading these docs over the web | an index of every page as Markdown, and the key source files |
llms-full.txt | an agent that wants it all in one fetch | every page of these docs in one Markdown file |
Every page is also published as Markdown next to its HTML — quickstart.md beside
quickstart.html — and linked from the View as Markdown link at the bottom of the
page. Agents that do the driving themselves can use the non-interactive forms:
./setup.sh aws pipeline --token <tracking-id>
./setup.sh aws connect --dist <distribution-id>
./setup.sh aws status
The rule in AGENTS.md that matters most: an agent must never run an apply or a destroy
without the developer's go-ahead on that specific command. These stacks cost real money.
Code on this page
README.mdthe same overview, as it reads on GitHubAGENTS.mdinstructions for a coding agent working in the repoobsero.mjsthe contract as code: build, validate and POST an event