aubes / ecs-logging-bundle
Symfony bundle providing the Ecs log format
Installs: 356
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Type:symfony-bundle
Requires
- php: >=7.4
- elastic/ecs-logging: ^1.0.3
- monolog/monolog: ^2.0
- symfony/http-foundation: ^5.4 | ^6.0
- symfony/http-kernel: ^5.4 | ^6.0
- symfony/polyfill-php80: ^1.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.1
- phpmd/phpmd: ^2.10
- phpspec/prophecy-phpunit: >=v2.0.1
- phpunit/phpunit: >=9.6
- symfony/security-bundle: ^5.4 | ^6.0
- vimeo/psalm: ^5.9
README
This Symfony bundle provides the Ecs log format for Monolog.
It uses elastic/ecs-logging.
It is compatible with :
- PHP 7.4 and 8.x
- Symfony 5.4 and 6.x
- Monolog 2.x
Installation
composer require aubes/ecs-logging-bundle
Configuration
Formatter
First, you need to configure the Ecs formatter in monolog:
# config/packages/monolog.yaml monolog: handlers: ecs: # [...] formatter: 'monolog.formatter.ecs'
Then configure the bundle, the configuration looks as follows :
# config/packages/ecs-logging.yaml ecs_logging: monolog: # Register the processors on channels or handlers, not both # To configure channels or handlers is recommended # Default logging channels the processors should be pushed to handlers: [] # Default logging handlers the processors should be pushed to #channels: [] processor: # https://www.elastic.co/guide/en/ecs/current/ecs-service.html service: enabled: false name: ~ # Name of the service data is collected from. version: ~ # Version of the service the data was collected from. ephemeral_id: ~ # Ephemeral identifier of this service (if one exists). id: ~ # Unique identifier of the running service. node_name: ~ # Name of a service node. state: ~ # Current state of the service. type: ~ # The type of the service data is collected from. #handlers: [] # Logging channels the processor should be pushed to #channels: [] # Logging handlers the processor should be pushed to error: enabled: false field_name: 'error' #handlers: [] # Logging channels the processor should be pushed to #channels: [] # Logging handlers the processor should be pushed to tracing: enabled: false field_name: 'tracing' #handlers: [] # Logging channels the processor should be pushed to #channels: [] # Logging handlers the processor should be pushed to user: enabled: false domain: ~ # Ecs user domain, example: ldap provider: ~ # Service Id of the Ecs user provider, default: Aubes\EcsLoggingBundle\Security\EcsUserProvider #handlers: [] # Logging channels the processor should be pushed to #channels: [] # Logging handlers the processor should be pushed to auto_label: enabled: false fields: [] # Name of internal fields, these fields will not be moved #handlers: [] # Logging channels the processor should be pushed to #channels: [] # Logging handlers the processor should be pushed to
Configuration example
# config/packages/ecs-logging.yaml ecs_logging: monolog: handlers: ['ecs'] processor: service: enabled: true name: 'MyApp' version: '%env(string:ECS_LOGGING_SERVICE_VERSION)%' # [...] user: enabled: true domain: ~ # Ecs user domain, example: ldap
# config/packages/monolog.yaml monolog: handlers: # [...] ecs: type: stream path: "%kernel.logs_dir%/%kernel.environment%.ecs.log" level: info channels: [ "app" ] formatter: 'monolog.formatter.ecs'
Usage
Service processor
Without service processor
use Elastic\Types\Service; $service = new Service() $service->setName(/* [...] */); $service->setVersion(/* [...] */); $logger->info('exception.message', [ 'service' => new Service(), ]);
With service processor
Enable the processor:
# config/packages/ecs-logging.yaml ecs_logging: # [...] processor: service: enabled: true name: # [...] version: # [...]
$logger->info('message');
Log error
Without error processor
use Elastic\Types\Error as EcsError; try { // [...] } catch (\Exception $e) { $logger->info('exception.message', [ 'error' => new EcsError($e), ]); }
With error processor
Enable the processor:
# config/packages/ecs-logging.yaml ecs_logging: # [...] processor: error: enabled: true
try { // [...] } catch (\Exception $e) { $logger->info('exception.message', [ 'error' => $e, ]); }
Tracing
Without tracing processor
use Elastic\Types\Tracing; // [...] $logger->info('tracing.message', [ 'tracing' => new Tracing($traceId, $transactionId), ]);
With tracing processor
Enable the processor:
# config/packages/ecs-logging.yaml ecs_logging: # [...] processor: tracing: enabled: true
// [...] $logger->info('tracing.message', [ 'tracing' => [ 'trace_id' => $traceId, 'transaction_id' => $transactionId, ], ]);
User
Without user processor
use Elastic\Types\User; // [...] $ecsUser = new User(); $ecsUser->setId($userId); $ecsUser->setName($userName); $logger->info('exception.message', [ 'user' => $ecsUser, ]);
With user processor
Enable the processor:
# config/packages/ecs-logging.yaml ecs_logging: # [...] processor: user: enabled: true
// [...] $logger->info('message');
Auto label
To automatically move all additional fields into the Ecs labels
field, useful for internal Symfony bundle log.
For example without the processor, a Symfony log contains these fields :
{ "route": "_wdt", "route_parameters": { "_route": "_wdt", "_controller": "web_profiler.controller.profiler::toolbarAction", "token": "..." }, "request_uri": "...", "method": "GET" }
With the processor, the Symfony log looks like :
{ "labels": { "route": "_wdt", "route_parameters": { "_route": "_wdt", "_controller": "web_profiler.controller.profiler::toolbarAction", "token": "..." }, "request_uri": "...", "method": "GET" } }
Warning, this processor can impact performance.
Configuration
First, you need to configure the processor:
# config/packages/ecs-logging.yaml ecs_logging: # [...] processor: auto_label: enabled: true fields: [] # Name of internal fields, these fields will not be moved #fields: !php/const Aubes\EcsLoggingBundle\Logger\AutoLabelProcessor::FIELDS_MINIMAL #fields: !php/const Aubes\EcsLoggingBundle\Logger\AutoLabelProcessor::FIELDS_BUNDLE #fields: !php/const Aubes\EcsLoggingBundle\Logger\AutoLabelProcessor::FIELDS_ALL
You can define a custom list or use the built-in constant:
Aubes\EcsLoggingBundle\Logger\AutoLabelProcessor::FIELDS_MINIMAL
: minimal fields supported by the bundleAubes\EcsLoggingBundle\Logger\AutoLabelProcessor::FIELDS_BUNDLE
: all fields supported by the bundleAubes\EcsLoggingBundle\Logger\AutoLabelProcessor::FIELDS_ALL
: all Ecs fields and all bundle fields
For performance reasons, use only necessary fields.
Configuration example
# config/packages/ecs-logging.yaml ecs_logging: monolog: handlers: ['app', 'main'] processor: # [...] auto_label: enabled: true fields: !php/const Aubes\EcsLoggingBundle\Logger\AutoLabelProcessor::FIELDS_BUNDLE handlers: ['main'] # do not apply on ecs channel
# config/packages/monolog.yaml monolog: handlers: main: type: stream path: "%kernel.logs_dir%/%kernel.environment%.log" level: warning channels: [ "!event", "!app" ] formatter: 'monolog.formatter.ecs' app: type: stream path: "%kernel.logs_dir%/%kernel.environment%.log" level: info channels: [ "app" ] formatter: 'monolog.formatter.ecs'
Custom Ecs user provider
The default Ecs user provider is Aubes\EcsLoggingBundle\Security\EcsUserProvider, but you can use your own provider.
First you need to create an Ecs User Provider class and implement EcsUserProviderInterface :
// src/Security/CustomEcsUserProvider.php namespace App\Security; use Elastic\Types\User; use Symfony\Component\Security\Core\Security; class CustomEcsUserProvider implements EcsUserProviderInterface { public function getUser(): ?User { // [...] } public function getDomain(): ?string { return 'custom_user_provider'; } }
Next, register your class as a service :
# config/services.yaml services: App\Security\CustomEcsUserProvider: ~
Then, configure the provider :
# config/packages/ecs-logging.yaml ecs_logging: # [...] processor: user: enabled: true provider: 'App\Security\CustomEcsUserProvider'