Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2ffbf37
feat(GH-1634): move LoggerService from zmscitizenapi to zmsslim
ThomasAFink May 30, 2026
e980c36
feat(GH-1634): move shared HTTP middleware to zmsslim and wire zmsapi…
ThomasAFink May 30, 2026
1a47573
fix(GH-1634): suppress PHPMD NPathComplexity on zmsapi initializeLogger
ThomasAFink May 30, 2026
d1d5416
clean(GH-1634): fix array_filter callback parameter order in LoggerSe…
ThomasAFink May 30, 2026
8ca45cc
clean(GH-1634): only return validated client IPs from forwarded headers
ThomasAFink May 30, 2026
715c77e
feat(GH-1634): use module-specific logger env vars for zmsapi and zms…
ThomasAFink May 30, 2026
0c34375
feat(GH-1634): add request logging to admin, calldisplay, statistic, …
ThomasAFink May 30, 2026
312c008
docs(GH-1634): document per-module HTTP logging and poll-heavy tuning
ThomasAFink May 30, 2026
0d4f81d
fix(GH-1634): add symfony/cache to zmsslim and align IpFilter test wi…
ThomasAFink May 30, 2026
72c24a5
fix(GH-1634): restore dev/stage header colors blocked by CSP
ThomasAFink May 30, 2026
41c8ba4
clean(GH-1634): address CodeRabbit review findings on logger middleware
ThomasAFink May 30, 2026
eccdf14
feat(GH-1634): route PHP warnings and notices into Monolog JSON logs
ThomasAFink May 30, 2026
64462c7
Merge branch 'main' into feat-gh-1634-move-logger-service-to-zmsslim
ThomasAFink May 30, 2026
7367ceb
fix(GH-1634): throw ErrorException after logging PHP warnings
ThomasAFink May 30, 2026
3ae71c4
fix(GH-1634): rewind response body after request logging
ThomasAFink May 30, 2026
ee5e044
fix(GH-1634): stop promoting PHP warnings to ErrorException
ThomasAFink May 30, 2026
10c7812
fix(GH-1634): skip PhpErrorHandler during PHPUnit to preserve test be…
ThomasAFink May 30, 2026
71c5306
fix(GH-1634): handle array query params in LoggerService::logRequest
ThomasAFink May 30, 2026
58ad778
fix(GH-1634): reduce logRequest cyclomatic complexity for PHPMD
ThomasAFink May 30, 2026
c5f3184
Merge branch 'main' into feat-gh-1634-move-logger-service-to-zmsslim
ThomasAFink Jun 1, 2026
feb8170
fix(GH-1634): align composer locks with PHP 8.3 CI runtime
ThomasAFink Jun 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 65 additions & 10 deletions .ddev/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,71 @@ SOURCE_CACHE_TTL=3600
# Maintenance Mode
MAINTENANCE_ENABLED=false

# Logger Configuration
LOGGER_MAX_REQUESTS=1000
LOGGER_RESPONSE_LENGTH=1048576 # 1MB
LOGGER_STACK_LINES=20
LOGGER_MESSAGE_SIZE=8192 # 8KB
LOGGER_CACHE_TTL=60
LOGGER_MAX_RETRIES=3
LOGGER_BACKOFF_MIN=100
LOGGER_BACKOFF_MAX=1000
LOGGER_LOCK_TIMEOUT=5
# zmscitizenapi Logger Configuration
ZMS_CITIZENAPI_LOGGER_MAX_REQUESTS=1000
ZMS_CITIZENAPI_LOGGER_RESPONSE_LENGTH=1048576 # 1MB
ZMS_CITIZENAPI_LOGGER_STACK_LINES=20
ZMS_CITIZENAPI_LOGGER_MESSAGE_SIZE=8192 # 8KB
ZMS_CITIZENAPI_LOGGER_CACHE_TTL=60
ZMS_CITIZENAPI_LOGGER_MAX_RETRIES=3
ZMS_CITIZENAPI_LOGGER_BACKOFF_MIN=100
ZMS_CITIZENAPI_LOGGER_BACKOFF_MAX=1000
ZMS_CITIZENAPI_LOGGER_LOCK_TIMEOUT=5

# zmsapi Logger Configuration
ZMS_API_LOGGER_MAX_REQUESTS=1000
ZMS_API_LOGGER_RESPONSE_LENGTH=1048576 # 1MB
ZMS_API_LOGGER_STACK_LINES=20
ZMS_API_LOGGER_MESSAGE_SIZE=8192 # 8KB
ZMS_API_LOGGER_CACHE_TTL=60
ZMS_API_LOGGER_MAX_RETRIES=3
ZMS_API_LOGGER_BACKOFF_MIN=100
ZMS_API_LOGGER_BACKOFF_MAX=1000
ZMS_API_LOGGER_LOCK_TIMEOUT=5

# zmsadmin Logger Configuration
ZMS_ADMIN_LOGGER_MAX_REQUESTS=1000
ZMS_ADMIN_LOGGER_RESPONSE_LENGTH=1048576 # 1MB
ZMS_ADMIN_LOGGER_STACK_LINES=20
ZMS_ADMIN_LOGGER_MESSAGE_SIZE=8192 # 8KB
ZMS_ADMIN_LOGGER_CACHE_TTL=60
ZMS_ADMIN_LOGGER_MAX_RETRIES=3
ZMS_ADMIN_LOGGER_BACKOFF_MIN=100
ZMS_ADMIN_LOGGER_BACKOFF_MAX=1000
ZMS_ADMIN_LOGGER_LOCK_TIMEOUT=5

# zmscalldisplay Logger Configuration
ZMS_CALLDISPLAY_LOGGER_MAX_REQUESTS=1000
ZMS_CALLDISPLAY_LOGGER_RESPONSE_LENGTH=1048576 # 1MB
ZMS_CALLDISPLAY_LOGGER_STACK_LINES=20
ZMS_CALLDISPLAY_LOGGER_MESSAGE_SIZE=8192 # 8KB
ZMS_CALLDISPLAY_LOGGER_CACHE_TTL=60
ZMS_CALLDISPLAY_LOGGER_MAX_RETRIES=3
ZMS_CALLDISPLAY_LOGGER_BACKOFF_MIN=100
ZMS_CALLDISPLAY_LOGGER_BACKOFF_MAX=1000
ZMS_CALLDISPLAY_LOGGER_LOCK_TIMEOUT=5

# zmsstatistic Logger Configuration
ZMS_STATISTIC_LOGGER_MAX_REQUESTS=1000
ZMS_STATISTIC_LOGGER_RESPONSE_LENGTH=1048576 # 1MB
ZMS_STATISTIC_LOGGER_STACK_LINES=20
ZMS_STATISTIC_LOGGER_MESSAGE_SIZE=8192 # 8KB
ZMS_STATISTIC_LOGGER_CACHE_TTL=60
ZMS_STATISTIC_LOGGER_MAX_RETRIES=3
ZMS_STATISTIC_LOGGER_BACKOFF_MIN=100
ZMS_STATISTIC_LOGGER_BACKOFF_MAX=1000
ZMS_STATISTIC_LOGGER_LOCK_TIMEOUT=5

# zmsticketprinter Logger Configuration
ZMS_TICKETPRINTER_LOGGER_MAX_REQUESTS=1000
ZMS_TICKETPRINTER_LOGGER_RESPONSE_LENGTH=1048576 # 1MB
ZMS_TICKETPRINTER_LOGGER_STACK_LINES=20
ZMS_TICKETPRINTER_LOGGER_MESSAGE_SIZE=8192 # 8KB
ZMS_TICKETPRINTER_LOGGER_CACHE_TTL=60
ZMS_TICKETPRINTER_LOGGER_MAX_RETRIES=3
ZMS_TICKETPRINTER_LOGGER_BACKOFF_MIN=100
ZMS_TICKETPRINTER_LOGGER_BACKOFF_MAX=1000
ZMS_TICKETPRINTER_LOGGER_LOCK_TIMEOUT=5

# Captcha Configuration
CAPTCHA_ENABLED=true
Expand Down
75 changes: 65 additions & 10 deletions .devcontainer/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,71 @@ SOURCE_CACHE_TTL=3600
# Maintenance Mode
MAINTENANCE_ENABLED=false

# Logger Configuration
LOGGER_MAX_REQUESTS=1000
LOGGER_RESPONSE_LENGTH=1048576 # 1MB
LOGGER_STACK_LINES=20
LOGGER_MESSAGE_SIZE=8192 # 8KB
LOGGER_CACHE_TTL=60
LOGGER_MAX_RETRIES=3
LOGGER_BACKOFF_MIN=100
LOGGER_BACKOFF_MAX=1000
LOGGER_LOCK_TIMEOUT=5
# zmscitizenapi Logger Configuration
ZMS_CITIZENAPI_LOGGER_MAX_REQUESTS=1000
ZMS_CITIZENAPI_LOGGER_RESPONSE_LENGTH=1048576 # 1MB
ZMS_CITIZENAPI_LOGGER_STACK_LINES=20
ZMS_CITIZENAPI_LOGGER_MESSAGE_SIZE=8192 # 8KB
ZMS_CITIZENAPI_LOGGER_CACHE_TTL=60
ZMS_CITIZENAPI_LOGGER_MAX_RETRIES=3
ZMS_CITIZENAPI_LOGGER_BACKOFF_MIN=100
ZMS_CITIZENAPI_LOGGER_BACKOFF_MAX=1000
ZMS_CITIZENAPI_LOGGER_LOCK_TIMEOUT=5

# zmsapi Logger Configuration
ZMS_API_LOGGER_MAX_REQUESTS=1000
ZMS_API_LOGGER_RESPONSE_LENGTH=1048576 # 1MB
ZMS_API_LOGGER_STACK_LINES=20
ZMS_API_LOGGER_MESSAGE_SIZE=8192 # 8KB
ZMS_API_LOGGER_CACHE_TTL=60
ZMS_API_LOGGER_MAX_RETRIES=3
ZMS_API_LOGGER_BACKOFF_MIN=100
ZMS_API_LOGGER_BACKOFF_MAX=1000
ZMS_API_LOGGER_LOCK_TIMEOUT=5

# zmsadmin Logger Configuration
ZMS_ADMIN_LOGGER_MAX_REQUESTS=1000
ZMS_ADMIN_LOGGER_RESPONSE_LENGTH=1048576 # 1MB
ZMS_ADMIN_LOGGER_STACK_LINES=20
ZMS_ADMIN_LOGGER_MESSAGE_SIZE=8192 # 8KB
ZMS_ADMIN_LOGGER_CACHE_TTL=60
ZMS_ADMIN_LOGGER_MAX_RETRIES=3
ZMS_ADMIN_LOGGER_BACKOFF_MIN=100
ZMS_ADMIN_LOGGER_BACKOFF_MAX=1000
ZMS_ADMIN_LOGGER_LOCK_TIMEOUT=5

# zmscalldisplay Logger Configuration
ZMS_CALLDISPLAY_LOGGER_MAX_REQUESTS=1000
ZMS_CALLDISPLAY_LOGGER_RESPONSE_LENGTH=1048576 # 1MB
ZMS_CALLDISPLAY_LOGGER_STACK_LINES=20
ZMS_CALLDISPLAY_LOGGER_MESSAGE_SIZE=8192 # 8KB
ZMS_CALLDISPLAY_LOGGER_CACHE_TTL=60
ZMS_CALLDISPLAY_LOGGER_MAX_RETRIES=3
ZMS_CALLDISPLAY_LOGGER_BACKOFF_MIN=100
ZMS_CALLDISPLAY_LOGGER_BACKOFF_MAX=1000
ZMS_CALLDISPLAY_LOGGER_LOCK_TIMEOUT=5

# zmsstatistic Logger Configuration
ZMS_STATISTIC_LOGGER_MAX_REQUESTS=1000
ZMS_STATISTIC_LOGGER_RESPONSE_LENGTH=1048576 # 1MB
ZMS_STATISTIC_LOGGER_STACK_LINES=20
ZMS_STATISTIC_LOGGER_MESSAGE_SIZE=8192 # 8KB
ZMS_STATISTIC_LOGGER_CACHE_TTL=60
ZMS_STATISTIC_LOGGER_MAX_RETRIES=3
ZMS_STATISTIC_LOGGER_BACKOFF_MIN=100
ZMS_STATISTIC_LOGGER_BACKOFF_MAX=1000
ZMS_STATISTIC_LOGGER_LOCK_TIMEOUT=5

# zmsticketprinter Logger Configuration
ZMS_TICKETPRINTER_LOGGER_MAX_REQUESTS=1000
ZMS_TICKETPRINTER_LOGGER_RESPONSE_LENGTH=1048576 # 1MB
ZMS_TICKETPRINTER_LOGGER_STACK_LINES=20
ZMS_TICKETPRINTER_LOGGER_MESSAGE_SIZE=8192 # 8KB
ZMS_TICKETPRINTER_LOGGER_CACHE_TTL=60
ZMS_TICKETPRINTER_LOGGER_MAX_RETRIES=3
ZMS_TICKETPRINTER_LOGGER_BACKOFF_MIN=100
ZMS_TICKETPRINTER_LOGGER_BACKOFF_MAX=1000
ZMS_TICKETPRINTER_LOGGER_LOCK_TIMEOUT=5

# Captcha Configuration
CAPTCHA_ENABLED=true
Expand Down
50 changes: 50 additions & 0 deletions docs/de/operations/monolog-logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,54 @@ const DEBUGLEVEL = ZMS_DEBUGLEVEL;

Ungültige Werte fallen in `Bootstrap::parseDebugLevel()` auf **DEBUG** zurück.

## HTTP-Request-Logging pro Modul

Anders als **`DEBUGLEVEL`** (ein Wert für alle Slim-Module) wird **HTTP-Request-/Response-Logging** **pro Modul** über `ZMS_<MODUL>_LOGGER_*`-Umgebungsvariablen konfiguriert — dasselbe Namensschema wie `ZMS_ADMIN_TWIG_CACHE`, `ZMS_API_TWIG_CACHE` usw.

Module mit `RequestLoggingMiddleware` (über `BO\Slim\Helper\ModuleLoggerInitializer` oder eigenes Bootstrap) schreiben pro verarbeitetem Request eine strukturierte **`HTTP Request`**-Zeile über `BO\Slim\LoggerService::logRequest()` → `App::$log`.

| Modul | Env-Präfix | Typischer Traffic |
| ----- | ---------- | ----------------- |
| zmscitizenapi | `ZMS_CITIZENAPI_LOGGER_*` | Öffentliche Buchungs-API |
| zmsapi | `ZMS_API_LOGGER_*` | Interne REST-API |
| zmsadmin | `ZMS_ADMIN_LOGGER_*` | Mitarbeiter-UI |
| zmscalldisplay | `ZMS_CALLDISPLAY_LOGGER_*` | Aufrufmonitore (häufiges Polling) |
| zmsstatistic | `ZMS_STATISTIC_LOGGER_*` | Statistik-UI |
| zmsticketprinter | `ZMS_TICKETPRINTER_LOGGER_*` | Ticketdrucker (häufiges Polling) |

### LoggerService-Variablen

| Variable | Standard | Rolle |
| -------- | -------- | ----- |
| `…_LOGGER_MAX_REQUESTS` | `1000` | Max. HTTP-Logzeilen pro Rate-Limit-Fenster; danach werden weitere Request-Logs in diesem Fenster unterdrückt |
| `…_LOGGER_RESPONSE_LENGTH` | `1048576` | Max. Response-Body-Bytes bei Fehler-Logs |
| `…_LOGGER_STACK_LINES` | `20` | Stacktrace-Zeilen bei geloggten Exceptions |
| `…_LOGGER_MESSAGE_SIZE` | `8192` | Max. Größe einer einzelnen Log-Nachricht |
| `…_LOGGER_CACHE_TTL` | `60` | Rate-Limit-Fenster in Sekunden (nutzt `CACHE_DIR`) |
| `…_LOGGER_MAX_RETRIES` | `3` | Cache-Lock-Wiederholungen für Rate Limiting |
| `…_LOGGER_BACKOFF_MIN` / `…_LOGGER_BACKOFF_MAX` | `100` / `1000` | Backoff zwischen Wiederholungen (ms) |
| `…_LOGGER_LOCK_TIMEOUT` | `5` | Cache-Lock-Timeout (Sekunden) |

Vollständige Beispiele stehen in `.ddev/.env.template` bzw. `.devcontainer/.env.template`.

### Feinabstimmung bei hoher Request-Frequenz

**zmscalldisplay** und **zmsticketprinter** sind Besonderheiten: Jeder Monitor bzw. Ticketdrucker pollt typischerweise **alle paar Sekunden** den Server. Mit Standard `LOGGER_MAX_REQUESTS=1000` erzeugen schon wenige Geräte viel repetitive Log-Menge — auch bei `DEBUGLEVEL=INFO`.

Für diese Module empfiehlt sich ein **niedrigerer** Wert für `ZMS_CALLDISPLAY_LOGGER_MAX_REQUESTS` und/oder `ZMS_TICKETPRINTER_LOGGER_MAX_REQUESTS`, damit Routine-Polls den Logstrom nicht dominieren. Admin-, API- und Citizen-Module können meist bei den Defaults bleiben.

```bash
# Beispiel: Poll-Logging für Display/Drucker begrenzen, andere Module unverändert
ZMS_CALLDISPLAY_LOGGER_MAX_REQUESTS=120
ZMS_TICKETPRINTER_LOGGER_MAX_REQUESTS=120

# Andere Module weiterhin mit Template-Default (1000)
ZMS_ADMIN_LOGGER_MAX_REQUESTS=1000
ZMS_API_LOGGER_MAX_REQUESTS=1000
```

Ein niedrigeres `…_LOGGER_MAX_REQUESTS` drosselt nur **HTTP-Request-Logs** aus `LoggerService`; `App::$log`-Level für Anwendungsmeldungen (`error`, `warning` usw.) bleiben unverändert.

## Logging im Code

Nach `bootstrap.php` oder `script_bootstrap.php`:
Expand Down Expand Up @@ -127,4 +175,6 @@ Aktualisierung auch bei `npm run docs:dev` / `docs:build`. Nutze die Filter, die

- `zmsslim/src/Slim/Application.php` — `ZMS_DEBUGLEVEL`, `DEBUGLEVEL`, `public static $log`
- `zmsslim/src/Slim/Bootstrap.php` — Logger-Konfiguration
- `zmsslim/src/Slim/LoggerService.php` — HTTP-Request-Logging, Rate Limiting
- `zmsslim/src/Slim/Helper/ModuleLoggerInitializer.php` — Logger-Env und Middleware pro Modul
- `zmsslim/README.md` — Slim-Bootstrap-Übersicht
50 changes: 50 additions & 0 deletions docs/en/operations/monolog-logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,54 @@ const DEBUGLEVEL = ZMS_DEBUGLEVEL;

Invalid values fall back to **DEBUG** (permissive) in `Bootstrap::parseDebugLevel()`.

## Per-module HTTP request logging

Unlike **`DEBUGLEVEL`** (one value for all Slim modules), **HTTP request/response logging** is configured **per module** via `ZMS_<MODULE>_LOGGER_*` environment variables — the same naming pattern as `ZMS_ADMIN_TWIG_CACHE`, `ZMS_API_TWIG_CACHE`, and so on.

Modules that register `RequestLoggingMiddleware` (via `BO\Slim\Helper\ModuleLoggerInitializer` or their own bootstrap) emit one structured **`HTTP Request`** line per handled request through `BO\Slim\LoggerService::logRequest()` → `App::$log`.

| Module | Env prefix | Typical traffic |
| ------ | ---------- | --------------- |
| zmscitizenapi | `ZMS_CITIZENAPI_LOGGER_*` | Public booking API |
| zmsapi | `ZMS_API_LOGGER_*` | Internal REST API |
| zmsadmin | `ZMS_ADMIN_LOGGER_*` | Staff UI |
| zmscalldisplay | `ZMS_CALLDISPLAY_LOGGER_*` | Display monitors (frequent polling) |
| zmsstatistic | `ZMS_STATISTIC_LOGGER_*` | Statistics UI |
| zmsticketprinter | `ZMS_TICKETPRINTER_LOGGER_*` | Ticket printers (frequent polling) |

### LoggerService variables

| Variable | Default | Role |
| -------- | ------- | ---- |
| `…_LOGGER_MAX_REQUESTS` | `1000` | Maximum HTTP log lines per rate-limit window before further request logs in that window are suppressed |
| `…_LOGGER_RESPONSE_LENGTH` | `1048576` | Max response body bytes considered when logging errors |
| `…_LOGGER_STACK_LINES` | `20` | Stack trace lines on logged exceptions |
| `…_LOGGER_MESSAGE_SIZE` | `8192` | Max size of a single log message |
| `…_LOGGER_CACHE_TTL` | `60` | Rate-limit window in seconds (uses `CACHE_DIR`) |
| `…_LOGGER_MAX_RETRIES` | `3` | Cache lock retries for rate limiting |
| `…_LOGGER_BACKOFF_MIN` / `…_LOGGER_BACKOFF_MAX` | `100` / `1000` | Backoff between retries (ms) |
| `…_LOGGER_LOCK_TIMEOUT` | `5` | Cache lock timeout (seconds) |

See `.ddev/.env.template` / `.devcontainer/.env.template` for full examples per module.

### Tuning high-frequency modules

**zmscalldisplay** and **zmsticketprinter** are special: every monitor or ticket printer typically polls the server **every few seconds**. With default `LOGGER_MAX_REQUESTS=1000`, a handful of devices can produce large, repetitive log volume even at `DEBUGLEVEL=INFO`.

For those modules, consider **lowering** `ZMS_CALLDISPLAY_LOGGER_MAX_REQUESTS` and/or `ZMS_TICKETPRINTER_LOGGER_MAX_REQUESTS` so routine poll traffic does not dominate your log stream. Admin, API, and citizen modules usually keep the defaults.

```bash
# Example: cap display/printer poll logging without affecting other modules
ZMS_CALLDISPLAY_LOGGER_MAX_REQUESTS=120
ZMS_TICKETPRINTER_LOGGER_MAX_REQUESTS=120

# Other modules can stay at the template default (1000)
ZMS_ADMIN_LOGGER_MAX_REQUESTS=1000
ZMS_API_LOGGER_MAX_REQUESTS=1000
```

Lowering `…_LOGGER_MAX_REQUESTS` only throttles **HTTP request logs** from `LoggerService`; it does not change `App::$log` levels for application messages (`error`, `warning`, etc.).

## How to log

After `bootstrap.php` or `script_bootstrap.php`:
Expand Down Expand Up @@ -166,4 +214,6 @@ It updates when you run `npm run docs:dev` or `docs:build` (VitePress config run

- `zmsslim/src/Slim/Application.php` — `ZMS_DEBUGLEVEL`, `DEBUGLEVEL`, `public static $log`
- `zmsslim/src/Slim/Bootstrap.php` — `configureLogger()`, `ensureLogger()`, `normalizeLogLevelName()`
- `zmsslim/src/Slim/LoggerService.php` — HTTP request logging, rate limiting
- `zmsslim/src/Slim/Helper/ModuleLoggerInitializer.php` — per-module logger env wiring and middleware registration
- `zmsslim/README.md` — Slim bootstrap overview
1 change: 1 addition & 0 deletions zmsadmin/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

// Set option for environment, routing, logging and templating
\BO\Slim\Bootstrap::init();
\BO\Slim\Helper\ModuleLoggerInitializer::registerHttpMiddleware(false);
\BO\Slim\Bootstrap::addTwigExtension(new \Twig\Extra\Intl\IntlExtension());

\BO\Mellon\ValidMail::$disableDnsChecks = true;
Expand Down
Loading