#1817

sidecar: log the pgwire principal once on the session line

OpenNaurisSadovskiswants to merge intofrom

[claude]

Problem

On a postgres lane the session opened and session closed log lines carry two principal keys:

{"msg":"session opened","principal":"anonymous","principal":"app_user","upstream":"db.example.internal:5432"}

The logger is built with principal=anonymous before the pgwire StartupMessage is read. When the user is learned, log.With("principal", user) appends a second key. slog never replaces an attribute. The deferred teardown logs through the same logger, so session closed shows it too.

Fix

Rebuild the logger from the root with the final principal. One line in sidecar/proxy/proxy.go.

How to test

make test-sidecar, or the one test:

cd sidecar && CGO_ENABLED=0 go test ./proxy/ -run TestSessionLinesLogThePrincipalOnce -count=1

The test starts a postgres lane with a JSON logger, sends a StartupMessage for user alice, and decodes the session opened and session closed lines with a token decoder that counts top-level principal keys. It fails on the old code with principal keys = ["anonymous" "alice"].

Manual: open psql through a postgres lane and check both lines have one principal key.

Not in scope

The session_start audit event also reports anonymous, because the gate starts before the startup message is read. The store folds later events, so the session row ends up correct. Reordering that is a separate change.

🤖 Generated with Claude Code

Activity

7
github-actions[bot]1mo ago

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

NaurisSadovskis1mo ago

I have read the CLA Document and I hereby sign the CLA

qodo-code-review[bot]1mo ago

PR Summary by Qodo

Log one pgwire principal per sidecar session line

🐞 Bug fix 🧪 Tests 🕐 10-20 Minutes

AI Description

• Rebuilds pgwire session loggers with the discovered user, preventing duplicate principal keys.
• Verifies opened and closed JSON logs contain exactly one final principal.
Diagram

sequenceDiagram
    actor Client as PostgreSQL Client
    participant Proxy as Sidecar Proxy
    participant PGWire as PGWire Negotiation
    participant Logger as Root Logger
    Client->>Proxy: Open connection
    Proxy->>Logger: Create anonymous context
    Proxy->>PGWire: Read startup message
    PGWire-->>Proxy: Return claimed user
    Proxy->>Logger: Rebuild final context
    Logger-->>Proxy: Single principal logger
    Proxy->>Logger: Log opened and closed
High-Level Assessment

Rebuilding the session logger from the root is the best approach because slog attributes are append-only and cannot safely overwrite the earlier anonymous principal. Delaying principal attachment would complicate non-PostgreSQL and pre-negotiation logging, while handler-level duplicate suppression would introduce broad behavior for a localized issue.

Files changed (2) +123 / -1

Bug fix (1) +4 / -1
proxy.goRebuild pgwire logger with the final principal +4/-1

Rebuild pgwire logger with the final principal

• Recreates the session logger from the server’s root logger after pgwire reveals the claimed user. This preserves the session identifier while preventing the initial anonymous and final user principals from appearing together on lifecycle log lines.

sidecar/proxy/proxy.go

Tests (1) +119 / -0
proxy_test.goVerify one principal on session lifecycle logs +119/-0

Verify one principal on session lifecycle logs

• Adds a pgwire StartupMessage builder, synchronized log buffer, and duplicate-aware JSON token decoder. The regression test confirms both session-opened and deferred session-closed lines contain exactly one principal with the discovered user.

sidecar/proxy/proxy_test.go

qodo-code-review[bot]1mo ago

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


1. A deadline failure can hang the test 📘 Rule violation ☼ Reliability
Description
TestSessionLinesLogThePrincipalOnce ignores errors from Write, SetReadDeadline, ReadFull,
and Close. If deadline setup fails or network I/O is partial, the test can block or continue after
an incomplete exchange, obscuring whether the regression path ran.
Code

sidecar/proxy/proxy_test.go[R370-373]

+	c.Write(pgStartup("alice"))
+	c.SetReadDeadline(time.Now().Add(2 * time.Second))
+	io.ReadFull(c, make([]byte, len(pgStartup("alice"))))
+	c.Close()
Relevance

●●● Strong

Explicit I/O error handling is a deterministic reliability fix, consistent with recent accepted
test-safety feedback.

PR-#1809

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 1807206 requires errors from OS, execution, and I/O calls to be handled or
propagated. The added test invokes four network I/O operations without checking any returned error
or documenting why it is safe to ignore them.

Rule 1807206: Do not ignore errors from OS/exec/IO calls; handle or propagate them sidecar/proxy/proxy_test.go[370-373]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new regression test ignores errors returned by its connection write, deadline setup, response read, and close operations, allowing hangs or incomplete exchanges.

## Fix Focus Areas
- sidecar/proxy/proxy_test.go[370-373]

## Recommended Fix
Check each returned error and fail the test immediately with operation-specific context. Also verify the write and read byte counts, and treat any close error as a test failure unless explicitly documented as safe to ignore.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Context sources
✅ Compliance rules (platform): 80 rules
✅ Cross-repo context — repo relationships
Review mode: ⚖️ Balanced: This is a localized runtime logging fix with a focused regression test, but it changes session logger construction on a proxy path and merits a complete single-pass review.
Tip of the day
💡 Did you know, you can reply 'qodo' on any finding to push back, ask questions, or dig deeper

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

qodo-code-review[bot]reviewed1mo ago