Skip to content

Latest commit

 

History

History
113 lines (87 loc) · 4.41 KB

guide-symfony.md

File metadata and controls

113 lines (87 loc) · 4.41 KB

Symfony guide

Note It was written for Symfony 6.1+

This guide proposed an opinionated solution to integrate Sentry in a Symfony project.

It provides the following benefits:

  • Log Monolog records of the request lifecycle (Handled message for Messenger) in Sentry breadcrumbs
  • Resolve log PSR placeholders
  • Remove deprecation logs from production logs and thus in Sentry breadcrumbs
  • Enable only high value integrations like RequestIntegration default; Thus ExceptionListenerIntegration, FatalErrorListenerIntegration, etc. are disabled as these features are already managed by Symfony.

An implementation example of this guide has been created if you want to quickly test the behavior of the handler.

Table of contents (generated with DocToc)

Step 1: Configure Sentry Bundle

Install required libs:

composer require bgalati/monolog-sentry-handler sentry/sentry-symfony symfony/http-client nyholm/psr7

Let's configure Sentry bundle and Monolog:

# config/packages/sentry.yaml
sentry:
    dsn: '%env(SENTRY_DSN)%'
    register_error_listener: false # Disabled to avoid duplicated Sentry events
    register_error_handler: false # Disabled to avoid duplicated Sentry events, see https://github.com/getsentry/sentry-symfony/pull/687
    tracing: false
    messenger: false # Duplicates Sentry events as it is already managed through Monolog.
    options:
        attach_stacktrace: false # Disabled to avoid stacktrace on pure logs
        default_integrations: false
        integrations:
            - 'Sentry\Integration\RequestIntegration'
            - 'Sentry\Integration\EnvironmentIntegration'
            - 'Sentry\Integration\FrameContextifierIntegration'

monolog:
    handlers:
        sentry:
            type: fingers_crossed
            action_level: error
            handler: sentry_buffer
            include_stacktraces: true
            excluded_http_codes: [ 400, 401, 403, 404, 405 ]
            channels: [ "!event" ]
        sentry_buffer:
            type: buffer
            handler: sentry_handler
            level: info
            process_psr_3_messages: true
        sentry_handler:
            type: service
            id: BGalati\MonologSentryHandler\SentryHandler

services:
    _defaults:
        autowire: true
        autoconfigure: true

    BGalati\MonologSentryHandler\SentryHandler:
    Sentry\Integration\RequestIntegration:
    Sentry\Integration\EnvironmentIntegration:
    Sentry\Integration\FrameContextifierIntegration:
    Sentry\Integration\RequestFetcherInterface:
        class: Sentry\Integration\RequestFetcher

Let's explain the Monolog config:

  • FingersCrossedHandler: buffers all records until a certain level is reached
  • BufferHandler: keeps buffering message if the FingersCrossedHandler is triggered so that we have all logs for a given request
  • SentryHandler: sends log records in batch to Sentry

Step 2: Flush logs on each message handled by Symfony Messenger worker

The usage of FingersCrossedHandler and BufferHandler prevents long-running process like Symfony Messenger worker to send captured events to Sentry.

It works in an HTTP Request context because these handlers are automatically flushed by Monolog on PHP script shutdown, but it's not how a worker works.

👉 To fix this behavior set framework.messenger.reset_on_message option to true. Note that this is default value of Messenger since version 6.1.

Step 3: Filter deprecation logs

To avoid having deprecation to be logged, add this config:

#api/config/packages/prod/framework.yaml
framework:
    php_errors:
        # @see https://symfony.com/doc/master/reference/configuration/framework.html#log
        log: 8191 # php -r "echo E_ALL & ~E_USER_DEPRECATED & ~E_DEPRECATED;"