Imported from rknightion/genai-otel-bridge (
AGENTS.md). Install upstream withnpx skills add rknightion/genai-otel-bridge. Copyright stays with the author.
genai-otel-bridge
Vendor-neutral Go service that polls AI-platform APIs (LLM gateways, eval platforms) and emits operational telemetry to Grafana Cloud as OTLP metrics and logs. It sits on the production observability critical path: leader-elected, single-emit, self-observing, resilient to downstream slowness.
Hard rules (do not violate)
- Decoupled. No vendor, customer or domain knowledge in core code or defaults. Metric names,
label keys, endpoints, cadences, windows and env identifiers are all config. Vendor code lives
only in its
internal/source/<vendor>package behind the common interface. - Content minimisation is a release gate. Never request message bodies, prompts or completions.
An outbound field allow/deny-list governs every emitted field (labels, log body, metadata), so
content cannot leak via non-label fields.
internal/appwires the denylist;source.Guardenforces label allow-listing, default-deny (an empty allow-list denies all labels). - Conditional gap-free is engineered, not assumed. It emerges from emit-once-after-settle plus deterministic byte-identical encoding plus monotonic, lease-epoch-fenced checkpoint writes. Do not weaken any of the three expecting the others to compensate.
- Operationally honest. Every polling or emit gap and every skipped sample is alertable
(
window_lag,samples_skipped_total), never silent. A non-retryable reject advances past the bad bucket with a counted gap so the loop always progresses; it never stalls or drops silently. - FROZEN seams.
model.*types andsource.Source/source.Loopare marked FROZEN. Adding or renaming a field or method there is a design change requiring anARCHITECTURE.mdupdate.
Architecture
Source.Loop.Collect (pull a bounded window forward from the watermark) to model.Batch to
source.Guard.Sanitize (cardinality and content governance) to schedule.LoopRunner (single-flight,
bounded queue, epoch-fenced checkpoint) to emit.Emitter (deterministic OTLP encode plus retry).
Read ARCHITECTURE.md (durable seams, decision ledger) and docs/DESIGN.md (build spec, F1-F47
failure handling) before changing a seam.
Task interface
just check is the gate. just ci adds the two legs needing Docker or a service container
(e2e, test-dynamodb). Repo deltas beyond the standard task-surface rule:
- Run
justwith stdin from/dev/null.publishis[confirm]and pushes to a real registry. Never pass--yesorJUST_YES=1. just checkcovers every leg of ci.yml'shygienejob (forbidden-words,spdx-check,helm-lint,tf-validate), so a local green gate implies a green hygiene leg.tf-validateself-skips when the IaC tools are absent, andforbidden-wordsscans only the built-in credential shapes when neither$FORBIDDEN_WORDS_PATTERNnorscripts/forbidden-words.localis present. A clean local run is weaker than CI's on both.ci-successis the only required check onmain; the individual CI legs are not, so adding or renaming a leg never touches branch rules. Renovate PRs self-automerge, majors included, onceci-successis green.
Conventions
- Conventional Commits. Subjects drive the release-please
CHANGELOG.md. Onlyfeat,fixand breaking changes bump the version;chore,styleandtestare hidden from the changelog. - No live network in tests.
httptest.Serverfakes for HTTP, injectable clocks (SetLoopClockForTest) for determinism. *_review_test.gofiles encode specific adversarial-review findings (tagged[ext-review-14],CP-R3b,Cdx-C14). They are regression guards for known attack and race scenarios; keep them.- Config resolves
${ENV}andfile:/pathrefs at load time;.env,*.local.yamland*.secret.*are gitignored. scripts/forbidden-words.shblocks deployment-specific identifiers anywhere in the tracked tree,backlog/included. The repo is public: write the shape, not the instance (<vendor>/<workspace>/<loop>, "the tenant's second workspace"). Counts, timings and structural findings are fine.
Release
release-please maintains a release PR from the Conventional Commits on main; merging it tags
vX.Y.Z, creates the GitHub Release and triggers publish.yml. There is no manual changelog or tag
step.
- Version is single-source: chart
version=appVersion= release version, kept in step by the two# x-release-please-versionlines indeploy/helm/Chart.yaml. - Published artifacts carry no
vprefix. The git tag isvX.Y.Z, butdocker/metadata-actioninside the sharedcontainer-publish.ymlstrips it, so image tags areghcr.io/rknightion/genai-otel-bridge:X.Y.Z(plus:X.Y,:X,:latest). Use the unprefixed form in--set image=...and registry references. - Third-party notices and SBOMs are release artifacts, deliberately outside
just check.just noticesregenerates from the real import graph and churns on every dependency bump, so gating on it would break Renovate automerge. SBOMs come from syft insidecontainer-publish.yml, scanning the built image rather than the local binary. SeeLICENSING.md. scripts/publish.shis a local manual fallback, not the CI path.
Task tracking
Open work lives in Backlog.md under backlog/, task prefix gob. Work closed before the move off
GitHub Issues is indexed in the "Closed GitHub issues" doc and cited by its original #NNN, not by a
task ID.
Loops: the protocol lives in ~/repos/agent-docs/sources/loop/ (this board's "Loop protocol pointer" doc points there); this repository's loop facts are in LOOP.md.
- Do not build a workflow on decisions: half-built upstream, with no
edit/view/update, no supersede and no MCP surface. Durable reference goes in docs; tasks are the unit.
Deeper references
deploy/grafana/README.md- read before querying the emitted metrics or changing an alert. Also carries GS1-GS4, the Grafana-staff stack-side prerequisites this repo cannot set.
<CRITICAL_INSTRUCTION>
Backlog.md Workflow
This project uses Backlog.md for task and project management.
For every user request in this project, run backlog instructions overview before answering or taking action.
Use the overview to decide whether to search, read, create, or update Backlog tasks.
Before task lifecycle actions, read the matching detailed guide:
backlog instructions task-creationbefore creating or splitting tasksbacklog instructions task-executionbefore planning, changing status or assignee, adding a plan or implementation notes, or implementing task workbacklog instructions task-finalizationbefore checking acceptance criteria, writing final summaries, or moving tasks to terminal statuses
Use backlog <command> --help before running unfamiliar commands. Help shows options, fields, and examples.
Do not edit Backlog task, draft, document, decision, or milestone markdown files directly. Use the backlog CLI so metadata, relationships, and history stay consistent.
</CRITICAL_INSTRUCTION>
