Local development environment
Everywhere else in local development, the two runtime readings are declared. The fixture backend serves a hand-written mock of the platform API, and the demo snapshot is computed over an estate that authors its collectors and its arrivals by hand. Both are the right answer for what they are, and neither lets you see the product work.
The development environment closes the loop on one machine. Real collectors run under real OpAMP Supervisors, are served the artefacts this repository renders, emit into a real telemetry backend, and report what they are running back over the wire. The collector estate and the arrivals are then read from those live systems and handed to the same evaluators that produce every verdict in production.
It exists so you can see a broken_pipeline: a lane that is configured,
wired, and delivering nothing. No tool that reads configuration alone can
produce that verdict, it is the one the product exists for, and until now
nothing outside a fixture had ever produced it here.
The decisions behind the environment are in ADR-0052.
What you need
- Docker, running. It is the only prerequisite the rest of development does not already have, and nothing in the default test path needs it.
- Go and Node.js, as development setup describes.
- One pull. The images are fetched once and then the environment runs offline. Nothing reaches the network at run time.
Start it
From the repository root:
devenv/devenv up
That renders the estate, composes each collector's Supervisor configuration, starts the containers, and then runs the OpAMP server and the snapshot loop in the foreground. Leave it running and work in another terminal.
Three things are listening:
| Address | What |
|---|---|
127.0.0.1:4320 |
The OpAMP endpoint, at /v1/opamp. The collectors connect here. |
127.0.0.1:4321 |
The snapshot, and the console bundle when one is built. |
127.0.0.1:9200 |
The telemetry backend. |
To stop it and delete its volumes:
devenv/devenv down
See it
The console reads the environment through demo mode, which is the shape that already exists for a console with no server to call. Build the bundle once:
cd console
npm run build:demo
Then open http://127.0.0.1:4321. Every card, band, population and finding on
the page was computed by the real evaluators over readings taken from the
collectors and the backend a moment earlier. The loop rebuilds the snapshot
every 10 seconds, so a reload shows the estate as it is now.
To work on the console itself, with hot reload against the same live data:
cd console
npm run dev:demo
The dev server proxies the snapshot from the loop.
Demo mode is read-only, and says so. The write surfaces still render in full: the composer validates on every keystroke, the claim flow previews impact, and each ends at a notice explaining that a real instance opens a pull request instead. To work on those paths, use the fixture backend as development setup describes.
Two pieces of demo copy are wrong here, because the console cannot tell this environment from the public demo: the banner reads "Read-only demo", and the welcome tour's first step says you are looking at a public estate rebuilt from git on every push. Read-only is true. The rest is the demo's sentence, not this environment's.
Check on it
devenv/devenv status
That prints the containers, the collectors as the OpAMP server sees them, what
has arrived in the last five minutes, and which reported configurations are on
disk. devenv/devenv logs collector-gateway-1 follows one container.
Drive it
Seven scenarios put the estate into a state worth looking at:
devenv/devenv scenario broken-pipeline
| Scenario | What it does | What to look for |
|---|---|---|
healthy |
Every sim running, every collector on the artefact the estate describes | The resting state. Compliant, with one waived finding on search's metrics. |
broken-pipeline |
Stops checkout's traces sim | The traces lane stays configured and nothing arrives. After one window, broken_pipeline, never not_configured. |
drift |
Merges a local configuration file into gateway-1's Supervisor |
drifted on gateway-1, naming the pipeline nobody rendered, and in_sync on gateway-2. The local send_batch_max_size is deliberately not drift: the artefact never mentions that key, and the cross judges the keys it asserts (ADR-0054). |
foreign-drift |
Rewrites the git-delivered collector's local file and restarts it | send_batch_size at 64 where the artefact says 512. Nothing puts it back until you reset, because nothing delivers to this collector. |
shrink |
Stops one of the gateway Tier's two collectors | The population drops below the Tier's declared floor of two. |
unmatched |
Starts a collector whose attributes satisfy no selector | It is served the Unmatched artefact: self-telemetry on, no data pipelines, never an empty config map. |
reset |
Everything back to healthy |
The windows in devenv/estate/requirements/ are five minutes rather than the
day a real library would use, so a scenario is visible while you are still
looking at it. Give each one a window to settle.
The drift scenario is checkable with the product's own command, because the
loop writes each collector's reported configuration to disk:
go run ./cmd/telecraft delivery \
-intended devenv/estate/rendered/platform/gateway.yaml \
-effective devenv/run/effective/gateway-1.yaml \
-path served
The same estate answers telecraft check, against the live backend:
go run ./cmd/telecraft check \
-library devenv/estate/requirements \
-estate devenv/estate/rows.yaml \
-exemptions devenv/estate/exemptions
What is in the tree
| Path | What lives there |
|---|---|
devenv/estate/ |
The authored estate: two teams, two Tiers, two Services, a small requirements library, and one Exemption |
devenv/estate/rendered/ |
Renderer-written, and committed. Re-render after any authored change |
devenv/identity/ |
One file per collector: which Tier's Supervisor artefact it starts from, and the identity it reports. It is the install overlay Install a served collector documents, and every adopter writes one |
devenv/drift/ |
The local configuration the drift scenario merges |
devenv/collector/ |
The collector image: the Supervisor, with the collector it runs |
devenv/cmd/telecraft-devenv/ |
The tool that composes the Supervisor configurations and runs the loop |
devenv/run/ |
Generated, and gitignored: composed configurations, the readings, the snapshot, the reported configs |
Change the estate
The estate renders at a fixed commit, d0d0d0…, which is deliberately not a
plausible SHA. The estate lives inside this repository rather than its own, so
stamping it with a real commit would make the rendered tree stale on every
platform commit, and the check that the tree matches its sources would fail
perpetually and stop meaning anything.
After changing anything under devenv/estate/teams/, re-render:
go run ./cmd/telecraft render \
-estate devenv/estate \
-catalogue devenv/estate/catalogues/catalogue-v0.159.0.json \
-commit d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0
devenv/devenv up does this for you. go test ./devenv/... fails if you
forget, so a stale tree never reaches a pull request.
Two joins have to be kept by hand, and a test holds each one:
- Selectors and identities. A Tier selector is equality over reported
attributes, and
devenv/identity/is what reports them. Change one and change the other, or the Tier sits empty and the collector reads as ungoverned. rows.yamland the rendered pipelines. The conformance estate is the one reading the environment leaves authored, and it names rendered component ids exactly as the artefact spells them.
Update the pins
devenv/.env names every version the environment runs, once. The Catalogue in
devenv/estate/catalogues/ is imported at the collector version, so moving one
means moving both:
go run ./cmd/catalogue-import -tag v0.159.0 -out devenv/estate/catalogues
That import needs the core collector components as well as the contrib ones,
so point it at a checkout holding both repositories with -source.
The pins age deliberately visibly. A pin that has drifted from the Catalogue the estate is judged against is a real finding about the product's version handling, and it is worth reading as one before bumping it.
What it does not cover
- Authoring's write paths. Demo mode has nothing to POST to. They stay on the fixture backend.
- The Foreign path. Every collector here is served over OpAMP. A
git-delivered collector reporting through the collector's own
opampextension is a second shape and not this one (issue #113). - Live rows. The Effective reading per Service is authored, as it is in the platform today (issue #112).