<!-- Generated by docs/build.py from index.html. Edit the HTML, not this file. -->

# 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](quickstart.md) -- One command, four steps: a mock site, the pipeline, connect it, tear it down.
- [The contract](contract.md) -- The URL and the payload. The only thing you have to get right.
- [AWS](aws.md) -- CloudFront → Firehose → Lambda adapter. One real decision to make.
- [Google Cloud](gcp.md) -- 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](quickstart.md#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](quickstart.md#your-own-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](aws.md#wiring-it-in) and [what it creates](aws.md#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`](contract.md#obsero-mjs) 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`](llms.txt) for these docs as Markdown. [More below](#agents). | — |

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.

*one event per HTTP request*

```
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 →](contract.md)

## Which one do I want?

| Your setup | Start here | Why |
|---|---|---|
| CloudFront in front of anything | [AWS](aws.md) | Two log sources: cheap (User-Agent only) or full headers for ~$11/mo. |
| Google Cloud load balancer + Cloud CDN | [GCP](gcp.md) | Full headers on the cheap path — no trade to make. |
| A **plain GCS bucket** behind Cloud CDN | [GCP, caveat first](gcp.md#backend-buckets) | 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](contract.md#obsero-mjs) | 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`](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`](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.md`](https://github.com/Obsero-ai/obsero-public/blob/main/README.md) -- the same overview, as it reads on GitHub
- [`AGENTS.md`](https://github.com/Obsero-ai/obsero-public/blob/main/AGENTS.md) -- instructions for a coding agent working in the repo
- [`obsero.mjs`](https://github.com/Obsero-ai/obsero-public/blob/main/obsero.mjs) -- the contract as code: build, validate and POST an event
