Skip to content

feat(logging): [4/4] DB connection-error logging middleware (database channel)#478

Merged
turegjorup merged 17 commits into
feature/structured-logging-semconvfrom
feature/db-connection-error-logging
Jun 9, 2026
Merged

feat(logging): [4/4] DB connection-error logging middleware (database channel)#478
turegjorup merged 17 commits into
feature/structured-logging-semconvfrom
feature/db-connection-error-logging

Conversation

@turegjorup

Copy link
Copy Markdown
Contributor

PR 4 of 4 — Structured logging

Final PR of the series. Base is feature/logging-phpstan-gate until the earlier PRs merge, then retargets to release/3.0.0.

Logs MariaDB connection-establishment failures from the application layer so operators without database access get a failure signal (ADR 011). Logging-only — no reconnect/retry.

What this PR does

  • database channel — added to monolog.yaml and a prod per-channel handler (LOG_LEVEL_DATABASE, same LOG_LEVEL fallback, LOG_PATH destination).
  • ConnectionErrorMiddleware + ConnectionErrorDriver — a DBAL driver middleware wrapping connect(). It reads the raw driver error code, because a middleware sits below DBAL's exception conversion, which does not classify 1040 (too many connections), 1203, 2003 (connection refused), etc. as ConnectionException. Fires for every SAPI (web, CLI, Messenger) regardless of whether app code later swallows the exception.
    • Connection pressure / unreachability (1040, 1203, 1226, 2002, 2003, 2005) → critical; other connect failures (e.g. 1045 credentials) → error.
    • Logs event=db.connection_error, db.error_code, db.sqlstate, db.host (host only — never password/DSN), and the exception under the exception key.
    • The original exception is rethrown unchanged.
  • Wiring — registered with the explicit doctrine.middleware tag (doctrine-bundle collects tagged services in MiddlewaresPass; implementing the interface alone isn't enough), bound to @monolog.logger.database. Confirmed present on the default connection via debug:container --tag=doctrine.middleware.
  • Docsdocs/logging.md gains the database channel and the event=db.connection_error shape.

Mid-query drops (2006/2013) are out of scope (establishment only), per ADR 011.

Verification

  • composer code-analysis — green
  • composer coding-standards-check + env-coverage — green
  • composer test — 180 tests, green (added ConnectionErrorDriverTest: a stub driver throws Driver\Exception with code 2003→critical / 1045→error; asserts channel, level, db.* keys, and no secret-bearing keys)
  • cache:clear --env=prod — handler + middleware wiring resolve

🤖 Generated with Claude Code

@turegjorup
turegjorup force-pushed the feature/logging-phpstan-gate branch from 6049208 to b751a5d Compare June 3, 2026 08:15
@turegjorup
turegjorup force-pushed the feature/db-connection-error-logging branch from e3f9c6b to 9f92726 Compare June 3, 2026 08:16
@turegjorup
turegjorup force-pushed the feature/logging-phpstan-gate branch from b751a5d to db66d92 Compare June 3, 2026 08:27
@turegjorup
turegjorup force-pushed the feature/db-connection-error-logging branch from 9f92726 to 6e2ef9f Compare June 3, 2026 08:27
@turegjorup
turegjorup force-pushed the feature/logging-phpstan-gate branch from db66d92 to 0c8f2ca Compare June 3, 2026 08:46
@turegjorup
turegjorup force-pushed the feature/db-connection-error-logging branch from 6e2ef9f to ef3ee54 Compare June 3, 2026 08:47
@turegjorup
turegjorup force-pushed the feature/logging-phpstan-gate branch from 0c8f2ca to 57d45c1 Compare June 3, 2026 08:52
@turegjorup
turegjorup force-pushed the feature/db-connection-error-logging branch from ef3ee54 to 79c07ce Compare June 3, 2026 08:53
@turegjorup
turegjorup force-pushed the feature/logging-phpstan-gate branch from 57d45c1 to f174bae Compare June 3, 2026 08:59
@turegjorup
turegjorup force-pushed the feature/db-connection-error-logging branch from 79c07ce to 214d30c Compare June 3, 2026 09:00
@turegjorup
turegjorup force-pushed the feature/logging-phpstan-gate branch 2 times, most recently from dd333e7 to 54c7952 Compare June 3, 2026 11:14
@turegjorup
turegjorup force-pushed the feature/db-connection-error-logging branch from 214d30c to f0fa004 Compare June 3, 2026 11:16
@turegjorup
turegjorup force-pushed the feature/logging-phpstan-gate branch 2 times, most recently from ae123e3 to d030c28 Compare June 3, 2026 12:10
@turegjorup
turegjorup force-pushed the feature/db-connection-error-logging branch from f0fa004 to 5173e6c Compare June 3, 2026 12:10
@turegjorup
turegjorup force-pushed the feature/logging-phpstan-gate branch from d030c28 to e57f37b Compare June 3, 2026 21:03
@turegjorup
turegjorup force-pushed the feature/db-connection-error-logging branch from 5173e6c to 940ed3e Compare June 3, 2026 21:05
…hannel

Add the `database` Monolog channel and a DBAL driver middleware that logs
connection failures so operators without database access get a signal
(ADR 011). Logging-only — no reconnect/retry.

- ConnectionErrorDriver wraps connect() and reads the raw driver error code
  (a middleware sits below DBAL's exception conversion, which does not
  classify 1040/1203/2003 as ConnectionException). Connection-pressure /
  unreachability codes log at critical, other connect failures at error.
  The original exception is rethrown unchanged; only the host is logged,
  never the password or DSN.
- Register the middleware with the explicit doctrine.middleware tag (the
  bundle collects tagged services; implementing the interface is not enough)
  and bind the database channel.
- Add a prod per-channel handler for `database` (LOG_LEVEL_DATABASE with the
  LOG_LEVEL fallback) and document the event=db.connection_error shape.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@turegjorup
turegjorup force-pushed the feature/logging-phpstan-gate branch from e57f37b to 22ea6f9 Compare June 3, 2026 21:31
@turegjorup
turegjorup force-pushed the feature/db-connection-error-logging branch from 940ed3e to 8cb3bb0 Compare June 3, 2026 21:31
@turegjorup turegjorup changed the title feat(logging): DB connection-error logging middleware (database channel) feat(logging): [4/4] DB connection-error logging middleware (database channel) Jun 8, 2026
turegjorup and others added 7 commits June 8, 2026 17:56
…to feature/db-connection-error-logging

# Conflicts:
#	CHANGELOG.md
… channel

Rename ConnectionErrorMiddleware's injected logger $logger -> $databaseLogger
so the constructor self-documents its channel; binding key updated to match.
ConnectionErrorDriver keeps its positional $logger (not a channel-bound
service). No behaviour change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@turegjorup turegjorup self-assigned this Jun 9, 2026
… db.response.status_code

The database connection-error record now carries an OTel-compliant
categorisation: error.type holds a stable low-cardinality token
(too_many_connections, access_denied, …) mapped from the driver code, falling
back to the stringified code when unmapped. The verbose driver text remains in
exception.message.

Also rename the bespoke db.error_code to the OTel database semantic-convention
attribute db.response.status_code (emitted as a string).

Doc table and ConnectionErrorDriver test updated accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@turegjorup
turegjorup requested a review from tuj June 9, 2026 07:55
turegjorup and others added 7 commits June 9, 2026 10:57
The database channel has its own always-on handler; add it to the main
handler's channel blacklist so a critical connection error isn't emitted twice
(see the per-channel duplicate-emission fix).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ion host

There is no db.host OTel attribute; connection host/port are the general
server.address / server.port attributes. Rename db.host -> server.address
(host only, never password/DSN) and emit server.port conditionally
(omit-when-absent, per OTel). Doc table and driver test updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Base automatically changed from feature/logging-phpstan-gate to feature/structured-logging-semconv June 9, 2026 14:09
@turegjorup
turegjorup merged commit c442096 into feature/structured-logging-semconv Jun 9, 2026
25 checks passed
@turegjorup
turegjorup deleted the feature/db-connection-error-logging branch June 9, 2026 14:11
@turegjorup
turegjorup restored the feature/db-connection-error-logging branch June 9, 2026 14:14
@turegjorup
turegjorup deleted the feature/db-connection-error-logging branch June 9, 2026 14:15
turegjorup added a commit that referenced this pull request Jun 9, 2026
…mconv

feat(logging): [3–4/4] PHPStan logging gate + DB connection-error logging (re-target of #477/#478)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants