# Docker JSON Logging Dokumentation für strukturierte JSON-Logs in Docker Containern für Log-Aggregation. ## Übersicht Das Framework verwendet automatisch strukturierte JSON-Logs in Production Docker-Umgebungen, um die Integration mit Log-Aggregatoren (Elasticsearch, Datadog, CloudWatch, etc.) zu ermöglichen. ## Automatische Handler-Aktivierung ### Development Mode (Standard) ``` PHP CLI in Docker → DockerJsonHandler (Pretty-Printed) - Strukturiertes JSON mit Einrückung für bessere Lesbarkeit - Alle Log-Aggregator-Felder enthalten - Debugging-freundlich - Lokale Docker-Entwicklung optimiert ``` **Beispiel-Output**: ```json { "timestamp": "2025-10-22T17:14:25+00:00", "@timestamp": "2025-10-22T17:14:25+00:00", "level": "INFO", "level_value": 200, "severity": 6, "channel": "app", "message": "Development test message", "environment": "development", "host": "3be143247465", "service": "dev-service", "context": { "user_id": 123, "action": "test" } } ``` ### Production Mode ``` PHP CLI in Docker → DockerJsonHandler (Compact) - Kompakte JSON-Ausgabe (eine Zeile pro Log) - Alle Log-Aggregator-Felder enthalten - Optimiert für maschinelle Verarbeitung und Log-Aggregatoren ``` **Beispiel-Output**: ```json {"timestamp":"2025-10-22T17:14:25+00:00","@timestamp":"2025-10-22T17:14:25+00:00","level":"INFO","level_value":200,"severity":6,"channel":"app","message":"Production log","environment":"production","host":"3be143247465","service":"api-service","context":{"user_id":123}} ``` ### Lokale Entwicklung (ohne Docker) ``` PHP CLI lokal → ConsoleHandler - Farbige, interaktive Console-Ausgabe - Optimiert für lokale Terminal-Sessions ``` ## Detection-Logik ```php // Automatische Docker-Erkennung $inDocker = file_exists('/.dockerenv') || getenv('DOCKER_CONTAINER') === 'true'; if ($inDocker && $config->app->isProduction()) { // DockerJsonHandler für Production } else { // ConsoleHandler für Development } ``` ## JSON-Format Jeder Log-Eintrag wird als **eine Zeile JSON** ausgegeben: ```json { "timestamp": "2025-10-22T19:08:43+02:00", "@timestamp": "2025-10-22T19:08:43+02:00", "level": "INFO", "level_value": 200, "severity": 6, "channel": "app", "message": "User logged in", "environment": "production", "host": "3be143247465", "service": "api-service", "context": { "user_id": 12345, "ip_address": "192.168.1.1" } } ``` ## Standard-Felder | Feld | Typ | Beschreibung | |------|-----|--------------| | `timestamp` | string | ISO 8601 Zeitstempel | | `@timestamp` | string | Elasticsearch-konformer Zeitstempel | | `level` | string | Log-Level Name (DEBUG, INFO, WARNING, ERROR, etc.) | | `level_value` | int | Numerischer Log-Level Wert (100-600) | | `severity` | int | RFC 5424 Severity Level (0-7) | | `channel` | string\|null | Log-Channel (app, security, database, etc.) | | `message` | string | Log-Nachricht | | `environment` | string | Deployment-Umgebung (production, staging, development) | | `host` | string | Container/Server Hostname | | `service` | string | Service-Name (aus APP_NAME env var) | | `context` | object | Strukturierte Kontext-Daten | | `extra` | object | Zusätzliche Metadaten (optional) | ## Docker Logs Verwendung ### Basis-Kommandos ```bash # Letzte 50 Logs anzeigen docker logs php --tail 50 # Logs live verfolgen docker logs php --follow # Logs seit bestimmter Zeit docker logs php --since 10m docker logs php --since "2025-10-22T18:00:00" ``` ### Mit jq formatieren ```bash # Pretty-print JSON docker logs php 2>&1 | jq . # Nur ERROR Logs docker logs php 2>&1 | jq 'select(.level == "ERROR")' # Nur CRITICAL und höher docker logs php 2>&1 | jq 'select(.severity <= 2)' # Als TSV (Tab-separated) docker logs php 2>&1 | jq -r '[.timestamp, .level, .message] | @tsv' # Gruppierung nach Level docker logs php 2>&1 | jq -s 'group_by(.level) | map({level: .[0].level, count: length})' # Fehler mit Context docker logs php 2>&1 | jq 'select(.level == "ERROR") | {timestamp, message, context}' ``` ### Erweiterte Filterung ```bash # Logs von bestimmtem Service docker logs php 2>&1 | jq 'select(.service == "api-service")' # Logs mit bestimmtem User docker logs php 2>&1 | jq 'select(.context.user_id == 12345)' # Performance-Logs (> 1 Sekunde) docker logs php 2>&1 | jq 'select(.context.duration_ms > 1000)' # Security-Channel Logs docker logs php 2>&1 | jq 'select(.channel == "security")' ``` ## Log-Aggregator Integration ### Elasticsearch Die JSON-Logs sind direkt Elasticsearch-kompatibel: ```json { "@timestamp": "2025-10-22T19:08:43+02:00", // Elasticsearch convention "severity": 6, // RFC 5424 numeric "environment": "production", "host": "3be143247465", "service": "api-service" } ``` **Filebeat Konfiguration**: ```yaml filebeat.inputs: - type: container paths: - '/var/lib/docker/containers/*/*.log' json.keys_under_root: true json.add_error_key: true processors: - add_docker_metadata: ~ ``` ### Datadog **Docker Compose Konfiguration**: ```yaml services: php: labels: - "com.datadoghq.ad.logs=[{\"source\":\"php\",\"service\":\"api-service\"}]" logging: driver: "json-file" options: max-size: "10m" max-file: "3" ``` ### CloudWatch **Fluent Bit Konfiguration**: ```ini [INPUT] Name tail Path /var/lib/docker/containers/*/*.log Parser docker Tag php.* [OUTPUT] Name cloudwatch_logs Match php.* region eu-central-1 log_group_name /aws/ecs/php-service log_stream_prefix app/ ``` ## Environment-Konfiguration ### Production Aktivierung ```env # .env APP_ENV=production APP_DEBUG=false APP_NAME=api-service ``` ### Docker Environment Variable Optional kann Docker-Detection explizit aktiviert werden: ```yaml # docker-compose.yml services: php: environment: - DOCKER_CONTAINER=true ``` ## Testing ### Manueller Test ```bash # In Container ausführen docker exec php php tests/debug/test-docker-json-logging.php # Output prüfen docker exec php php tests/debug/test-docker-json-logging.php 2>&1 | jq . ``` ### Unit Tests ```bash # Logging Tests ausführen ./vendor/bin/pest tests/Unit/Framework/Logging/ ``` ## Performance **Charakteristiken**: - **Latenz**: <1ms pro Log-Eintrag - **Overhead**: ~5% gegenüber einfacher String-Ausgabe - **Throughput**: >10,000 Logs/Sekunde - **Memory**: Konstanter Speicherverbrauch (kein Buffering) **Optimierungen**: - Kompakte JSON-Ausgabe (keine Pretty-Print Formatierung) - Direkte STDOUT-Ausgabe ohne Buffering - Minimaler Serialisierungs-Overhead durch JsonSerializer ## Troubleshooting ### JSON-Logs erscheinen nicht in docker logs **Mögliche Ursachen**: 1. APP_ENV ist nicht auf "production" gesetzt 2. Logs werden nicht in CLI-Mode generiert (nur Web-Requests) 3. Docker-Detection schlägt fehl **Lösung**: ```bash # Environment prüfen docker exec php php -r "echo getenv('APP_ENV') . PHP_EOL;" # Docker-Detection prüfen docker exec php php -r "var_dump(file_exists('/.dockerenv'));" # SAPI prüfen docker exec php php -r "echo PHP_SAPI . PHP_EOL;" ``` ### JSON ist nicht valide **Ursache**: Multi-line Ausgabe von anderen Komponenten **Lösung**: Nur JSON-Zeilen filtern ```bash docker logs php 2>&1 | grep '^{' | jq . ``` ### Zu viele Logs **Lösung**: Log-Level erhöhen ```env # .env LOG_LEVEL=WARNING # Nur WARNING und höher ``` ## Best Practices ### 1. Strukturierte Kontext-Daten ✅ **Good**: ```php $logger->info('User action', LogContext::withData([ 'user_id' => $userId, 'action' => 'login', 'ip_address' => $ipAddress ])); ``` ❌ **Bad**: ```php $logger->info("User $userId logged in from $ipAddress"); ``` ### 2. Konsistente Field-Names Verwende snake_case für Context-Keys: ```php LogContext::withData([ 'user_id' => 123, // ✅ snake_case 'request_id' => 'abc', // ✅ snake_case 'userId' => 123 // ❌ camelCase ]); ``` ### 3. Sensitive Daten vermeiden Niemals Passwörter, Tokens oder PII in Logs: ```php // ❌ Schlecht $logger->info('Login', ['password' => $password]); // ✅ Gut $logger->info('Login', ['user_id' => $userId]); ``` ### 4. Richtige Log-Levels - **DEBUG**: Detaillierte Debugging-Informationen - **INFO**: Informative Ereignisse (User-Login, API-Calls) - **WARNING**: Warnungen (Deprecated-API-Usage) - **ERROR**: Fehler (Database-Errors, External-API-Failures) - **CRITICAL**: Kritische Fehler (System-Ausfall) ## Weiterführende Dokumentation - [Log-Aggregator-Felder](./aggregator-fields.md) - [Structured Logging Best Practices](./structured-logging.md) - [Performance Tuning](./performance.md)