feat: request-ID based logging and structured JSON logging defaults #49

Open
ginjiruu wants to merge 0 commits from feat/48-request-id-logging into master
Owner

Closes #48

What

  • Attach a request ID to every served request:
    • gRPC (OIDC + Exchange Check): a unary server interceptor that honors an incoming request ID, generating one (16 random bytes, base64url) when absent. The ID is carried on the request context logger and echoed back in the response metadata.
    • HTTP (callback/logout): middleware that honors an incoming X-Request-Id header, generating one when absent, sets it on the response, and carries it on the request context logger.
  • The ID is attached to the context logger under the requestID key, so every existing logf.FromContext(ctx) line in the flows picks it up without call-site changes.
  • Structured JSON by default: zap.Options{Development: false} (JSON encoder, Info level, stacktraces on errors). --zap-devel still switches to the console development encoder.

Key finding (verified live on the portable cluster)

The gateway (Envoy) forwards allowedHeaders into the ext_authz CheckRequest body (attributes.request.http.headers), not as gRPC metadata. The interceptor therefore reads the request ID from the CheckRequest's forwarded headers (x-request-id, then Envoy's x-envoy-request-id), keeping gRPC metadata as a fallback for direct callers. A client-sent X-Request-Id is honored end-to-end and appears in the bridge's JSON log lines.

Tests

  • TestRequestIDInterceptorCarriesTheIDOnTheLogger / TestRequestIDMiddlewareCarriesTheIDOnTheLogger: the honored (or generated) ID is carried on the handler's context logger.
  • TestRequestIDInterceptorHonorsTheCheckRequestHeader: the ID from the CheckRequest's forwarded headers is honored (x-request-id, x-envoy-request-id, and header-over-metadata precedence).
  • TestServerEchoesTheRequestID: end-to-end through the real listeners — the gRPC Check echoes the ID in the response metadata and the callback listener echoes it in the response header (honored and generated cases, both gRPC listeners).

Live verification (portable cluster)

  • task deploy (skaffold) → https://httpbin-auth.portable.animeteamspeak.moe/get with X-Request-Id: fixed-… + a bad bearer → 401, and the bridge log line is JSON carrying "requestID":"fixed-…".
  • /logout with X-Request-Id: cb-… → 302, response echoes x-request-id: cb-…, and the log line carries "requestID":"cb-…".
Closes #48 ## What - Attach a request ID to every served request: - **gRPC (OIDC + Exchange Check)**: a unary server interceptor that honors an incoming request ID, generating one (16 random bytes, base64url) when absent. The ID is carried on the request context logger and echoed back in the response metadata. - **HTTP (callback/logout)**: middleware that honors an incoming `X-Request-Id` header, generating one when absent, sets it on the response, and carries it on the request context logger. - The ID is attached to the context logger under the `requestID` key, so every existing `logf.FromContext(ctx)` line in the flows picks it up without call-site changes. - **Structured JSON by default**: `zap.Options{Development: false}` (JSON encoder, Info level, stacktraces on errors). `--zap-devel` still switches to the console development encoder. ### Key finding (verified live on the portable cluster) The gateway (Envoy) forwards `allowedHeaders` into the ext_authz **CheckRequest body** (`attributes.request.http.headers`), **not** as gRPC metadata. The interceptor therefore reads the request ID from the CheckRequest's forwarded headers (`x-request-id`, then Envoy's `x-envoy-request-id`), keeping gRPC metadata as a fallback for direct callers. A client-sent `X-Request-Id` is honored end-to-end and appears in the bridge's JSON log lines. ## Tests - `TestRequestIDInterceptorCarriesTheIDOnTheLogger` / `TestRequestIDMiddlewareCarriesTheIDOnTheLogger`: the honored (or generated) ID is carried on the handler's context logger. - `TestRequestIDInterceptorHonorsTheCheckRequestHeader`: the ID from the CheckRequest's forwarded headers is honored (x-request-id, x-envoy-request-id, and header-over-metadata precedence). - `TestServerEchoesTheRequestID`: end-to-end through the real listeners — the gRPC Check echoes the ID in the response metadata and the callback listener echoes it in the response header (honored and generated cases, both gRPC listeners). ## Live verification (portable cluster) - `task deploy` (skaffold) → `https://httpbin-auth.portable.animeteamspeak.moe/get` with `X-Request-Id: fixed-…` + a bad bearer → 401, and the bridge log line is JSON carrying `"requestID":"fixed-…"`. - `/logout` with `X-Request-Id: cb-…` → 302, response echoes `x-request-id: cb-…`, and the log line carries `"requestID":"cb-…"`.
feat: request-ID based logging and structured JSON logging defaults
Some checks failed
Lint / Run on Ubuntu (pull_request) Has been cancelled
E2E Tests / Run on Ubuntu (pull_request) Has been cancelled
Tests / Run on Ubuntu (pull_request) Has been cancelled
f1a936a982
Some checks failed
Lint / Run on Ubuntu (pull_request) Has been cancelled
E2E Tests / Run on Ubuntu (pull_request) Has been cancelled
Tests / Run on Ubuntu (pull_request) Has been cancelled
This pull request is broken due to missing fork information.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/48-request-id-logging:feat/48-request-id-logging
git switch feat/48-request-id-logging

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch master
git merge --no-ff feat/48-request-id-logging
git switch feat/48-request-id-logging
git rebase master
git switch master
git merge --ff-only feat/48-request-id-logging
git switch feat/48-request-id-logging
git rebase master
git switch master
git merge --no-ff feat/48-request-id-logging
git switch master
git merge --squash feat/48-request-id-logging
git switch master
git merge --ff-only feat/48-request-id-logging
git switch master
git merge feat/48-request-id-logging
git push origin master
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lab/authz-bridge!49
No description provided.