feat(collector): run builder-api alongside Benthos - #80
Conversation
140c91f to
7590264
Compare
7590264 to
119b6e6
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the openmeter-collector container so it can run the Go builder-api service alongside the Benthos collector, including container build wiring, a supervising entrypoint, and collector configuration changes to support per-tenant ingest credentials resolution.
Changes:
- Build and ship the
builder-apibinary into theopenmeter-collectorimage and run it alongside Benthos viaentrypoint.sh. - Extend the Benthos pipeline to optionally resolve per-tenant OpenMeter ingest URL/token from
konnect-credentialsand use per-message metadata for output auth/URL. - Expose
builder-apilocally viadocker-composeport binding and document additional env knobs in.env.example.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
openmeter-collector/entrypoint.sh |
Adds env loading, OpenMeter URL normalization for mgmt vs ingest, starts/supervises Benthos + builder-api. |
openmeter-collector/Dockerfile |
Multi-stage build to compile builder-api and copy it into the Benthos collector image. |
openmeter-collector/collector.yaml |
Adds optional per-tenant ingest credential lookup and routes output URL/auth via message metadata. |
docker-compose.yml |
Publishes builder-api port 8095 from the openmeter-collector container to localhost. |
.env.example |
Documents new builder-api/OpenMeter settings and konnect-credentials-related variables. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
119b6e6 to
201204c
Compare
201204c to
4ef89be
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (2)
openmeter-collector/entrypoint.sh:92
- When a child process exits, the script always exits 1 and it discards the child’s exit status. This makes failures harder to diagnose and can incorrectly mark a clean shutdown as an error. Capture and propagate the exited child’s status after
wait, then exit with that code.
if ! kill -0 "$benthos_pid" 2>/dev/null; then
wait "$benthos_pid" 2>/dev/null || true
cleanup
exit 1
fi
openmeter-collector/entrypoint.sh:68
- The INT/TERM trap only runs cleanup but doesn’t exit the entrypoint. With
set -eand the supervision loop, this can lead to confusing shutdown behavior (e.g., TERM triggers cleanup, then the loop continues until it notices a dead child and exits 1). It’s safer to exit directly from the trap with a signal-appropriate code.
trap cleanup INT TERM
4ef89be to
42e050a
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (2)
openmeter-collector/entrypoint.sh:20
- Comment says the auth0-provisioner → builder-api env mapping happens "only when unset", but the
${var:=...}form also overwrites variables that are set to an empty string. Either update the comment to match behavior, or switch to${var=...}if you truly only want the unset case.
# Map auth0-provisioner names → builder-api env (only when unset).
openmeter-collector/entrypoint.sh:86
openmeter_mgmt_urlis always non-empty becauseOPENMETER_URLis required andopenmeter_mgmt_urlis initialized from it. The extraif [ -n "$openmeter_mgmt_url" ]branch (and its "OPENMETER_URL unset" message) is effectively unreachable and can be simplified.
if [ -x /usr/local/bin/builder-api ]; then
if [ -n "${AUTH0_MGMT_CLIENT_ID:-}" ] && [ -n "${AUTH0_MGMT_CLIENT_SECRET:-}" ]; then
if [ -n "$openmeter_mgmt_url" ]; then
OPENMETER_URL="$openmeter_mgmt_url" /usr/local/bin/builder-api &
builder_pid=$!
42e050a to
9b735ec
Compare
9b735ec to
dbff9fe
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Suppressed comments (2)
openmeter-collector/collector.yaml:219
- This processor sets
meta client_id, but that metadata is never referenced later in the config. It adds per-message work and can confuse future readers; suggest removing it (or wiring it into a log/metric if it’s meant to be used).
- mapping: |
meta client_id = this.data.client_id.or("")
openmeter-collector/collector.yaml:229
OPENMETER_API_KEYis copied into message metadata (meta openmeter_token). Keeping secrets in per-message metadata increases the chance of accidental leakage (e.g., if metadata is ever logged or forwarded). You can avoid storing the token by reading it directly from env() in the Authorization header and only keeping the non-secret URL in metadata.
- mapping: |
meta openmeter_url = env("OPENMETER_URL").or("")
meta openmeter_token = env("OPENMETER_API_KEY").or("")
root = if meta("openmeter_url") == "" || meta("openmeter_token") == "" {
throw("openmeter ingest unresolved: set OPENMETER_URL and OPENMETER_API_KEY")
| if [ -x /usr/local/bin/builder-api ]; then | ||
| if [ -n "${AUTH0_MGMT_CLIENT_ID:-}" ] && [ -n "${AUTH0_MGMT_CLIENT_SECRET:-}" ]; then | ||
| if [ -n "$openmeter_mgmt_url" ]; then | ||
| OPENMETER_URL="$openmeter_mgmt_url" /usr/local/bin/builder-api & | ||
| builder_pid=$! |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.
Suppressed comments (2)
openmeter-collector/collector.yaml:233
- The
meta client_idprocessor is introduced here but the meta value is never referenced anywhere else in this config (nometa("client_id")usage). This extra processor adds noise and maintenance surface without affecting the output.
- mapping: |
meta client_id = this.data.client_id.or("")
openmeter-collector/entrypoint.sh:92
- This log message references
AUTH0_MGMT_CLIENT_ID/SECRET, but the actual env var checked isAUTH0_MGMT_CLIENT_SECRET. Using the exact variable name makes the startup guidance unambiguous for operators.
else
echo "builder-api: skipped — AUTH0_MGMT_CLIENT_ID/SECRET not set (re-run auth0-provisioner/provision/bootstrap.sh)" >&2
fi
Third split out of #57: the collector-side wiring that actually runs the builder-api binary. Multi-stage Dockerfile builds the Go service and drops it beside the Benthos collector; entrypoint supervises both. collector.yaml here is the real three-way merge with main, not #57's copy. #57 branched before #70 and both rewrote this file, so taking #57's version verbatim would have silently reverted the app-owner vs M2M identity split and the exact-fractional fee mapping. The merged pipeline passes main's full Benthos suite, including #70's own identity and fee cases. docker-compose drops the konnect-credentials service, its depends_on health gate, KONNECT_CREDENTIALS_URL, and the auth0-provisioner .env.livepeer bind mount. Neither directory is in the tree; the bind mount in particular would have had Docker create a directory at that path and break the container. entrypoint.sh already falls back to OPENMETER_URL when KONNECT_CREDENTIALS_URL is unset, so the single-org path works as-is. Verified: benthos test suite passes, shellcheck clean on entrypoint.sh, docker compose config validates, and the image builds and runs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Session exchange and go-livepeer both call the same /authorize contract.
472897d to
564915d
Compare
Third of the #57 split. #78 and #79 have landed; this now targets
main. Remaining stack: this → #81 → #82.Collector-side wiring that runs the
builder-apibinary beside Benthos: a multi-stage Dockerfile builds the Go service into the collector image, andentrypoint.shsupervises both.collector.yamlis a three-way merge with #70, not #57's copyWorth the most review attention. #57 branched before #70, and both rewrote
openmeter-collector/collector.yaml. Taking #57's version verbatim would have silently reverted #70's app-owner vs M2M identity split and the exact-fractional fee mapping.This branch carries the merged pipeline. Main's Benthos suite — which never ran against #57, because #57 predates the
openmeter-collectorCI job — passes in full, including #70's own cases:Ingest credentials are resolved via
env()into message metadata rather than${OPENMETER_URL}interpolations. Benthos substitutes dollar-brace vars in the raw config text before parsing, which made them lint-required even inside comments and blocked startup in the shared-tenant configuration.One Kong OpenMeter organization serves every tenant; customers are separated by the
openmeter_customer_keycontract, not per-tenant ingest credentials.Entrypoint supervises both processes
OPENMETER_URLandOPENMETER_API_KEY/eventssuffix so builder-api hits the management API (<base>/customers), while Benthos keeps the ingest URLAUTH0_MGMT_CLIENT_IDandAUTH0_MGMT_CLIENT_SECRETare setkill -9on benthos surfaces as 137, not a hardcoded 1)docker stop/ INT/TERM exit 0 rather than falling back into the loop and looking like a crashIDENTITY_WEBHOOK_URLdroppedSession exchange and go-livepeer both call the same
/authorizecontract. builder-api now readsREMOTE_SIGNER_WEBHOOK_URL+WEBHOOK_SECRETonly — the same vars as the remote signer.Compose / env
Net compose change vs main is the
127.0.0.1:8095port binding for builder-api..env.exampledocuments the builder-api OpenMeter knobs (default plan, trial grant, allowance enforcement).Verification
collector.yaml(above)shellcheckclean onentrypoint.shdocker compose configvalidatesdocker build -f openmeter-collector/Dockerfile .succeeds; the built image has a working/usr/local/bin/builder-apiand the entrypoint's required-env guard fires correctly