monitorkit/symfony

APM + infrastructure monitoring for Symfony applications. Zero config, automatic tracing.

Maintainers

Package info

github.com/gestiondesarrolloinnovacion/monitorkit-symfony

Homepage

Type:symfony-bundle

pkg:composer/monitorkit/symfony

Transparency log

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.1.2 2026-07-25 16:29 UTC

This package is auto-updated.

Last update: 2026-07-26 14:55:04 UTC


README

APM + infrastructure monitoring for Symfony applications. Zero configuration, automatic tracing.

Compatible with: Symfony 3.4, 4.x, 5.x, 6.x, 7.x · PHP 7.4, 8.0, 8.1, 8.2, 8.3

What it traces automatically

What How it appears in MonitorKit
Every HTTP request Root trace with method, path, status, duration
Doctrine queries Child spans with SQL and duration (DBAL 2.x and 3.x)
Unhandled exceptions Trace marked as error with exception class + message
Messenger messages Standalone trace per worker message

Installation

composer require monitorkit/symfony

1. Register the bundle

Symfony 4+ (Flex — automatic): The bundle is registered automatically via Flex recipes.

Symfony 3.4 / manual registration: Add to app/AppKernel.php:

public function registerBundles(): array
{
    return [
        // ...
        new \MonitorKit\Symfony\MonitorKitBundle(),
    ];
}

Symfony 4+ without Flex: Add to config/bundles.php:

return [
    // ...
    MonitorKit\Symfony\MonitorKitBundle::class => ['all' => true],
];

2. Create the config file

config/packages/monitorkit.yaml:

monitorkit:
    server: '%env(MONITORKIT_SERVER)%'
    api_key: '%env(MONITORKIT_KEY)%'
    service: '%env(default:kernel.project_dir:MONITORKIT_SERVICE)%'
    enabled: '%env(bool:default::MONITORKIT_ENABLED)%'

3. Add environment variables

MONITORKIT_SERVER=https://app.monitorkit.co
MONITORKIT_KEY=mk_your_agent_key_here
MONITORKIT_SERVICE=my-symfony-app
MONITORKIT_ENABLED=true

Get your agent key from MonitorKit dashboard → Settings → Agent Keys → New Key.

That's it. All requests are now traced automatically.

Configuration

Option Default Description
server Your MonitorKit server URL (required)
api_key Agent API key (required)
service symfony-app Service name shown in traces
enabled true Set to false to disable in local/CI
sample_rate 0.2 Fraction of requests to trace (0.1 = 10%). Raise only for low-traffic services or short debug windows.
slow_query_threshold_ms 0 Only trace queries slower than N ms (0 = all)
max_spans 200 Max spans per trace (prevents huge payloads)
timeout 2 HTTP timeout for sending traces (seconds)
exclude_paths ['#^/_profiler#', '#^/_wdt#', ...] Regex patterns for paths to skip

Full example:

monitorkit:
    server: '%env(MONITORKIT_SERVER)%'
    api_key: '%env(MONITORKIT_KEY)%'
    service: my-app
    enabled: true
    sample_rate: 0.2
    slow_query_threshold_ms: 0
    max_spans: 200
    timeout: 2
    exclude_paths:
        - '#^/_profiler#'
        - '#^/_wdt#'
        - '#^/health$#'
        - '#\.(ico|css|js|png)$#i'

Doctrine database tracing

Database query spans are captured automatically, no configuration needed, on both:

  • Doctrine DBAL 2.x — via a SQLLogger (QueryLogger) injected into the default connection's configuration.
  • Doctrine DBAL 3.x — via a doctrine.middleware-tagged service (QueryMiddleware). DoctrineBundle 2.4+ auto-collects tagged middleware services (along with its own, e.g. the web profiler's DB panel) into a single call, so nothing needs to be added to doctrine.yaml. On a DoctrineBundle older than 2.4, which doesn't scan for that tag, DBAL 3.x query tracing won't attach — upgrade doctrine/doctrine-bundle to get it.

Only one of the two ever registers — the extension checks which DBAL major version is installed and picks accordingly.

Symfony Messenger tracing

Async messages handled by workers are traced automatically as standalone traces (separate from HTTP). Each message appears in MonitorKit as:

message CreateOrderMessage  [worker]  38ms
  └── db SELECT ...         [db]      12ms

No additional configuration needed — the listener is auto-registered when symfony/messenger is detected.

Manual instrumentation

For code blocks not traced automatically:

use MonitorKit\Symfony\MonitorKit;

// Start a span, do work, finish it
$span = MonitorKit::startSpan('stripe.charge', 'payment');
$charge = $stripe->charges->create([...]);
MonitorKit::finishSpan($span);

// Wrap a callable (auto-finishes even on exception)
$result = MonitorKit::trace('redis.get', function () use ($key) {
    return $this->redis->get($key);
}, 'cache');

// Mark as error
try {
    // ...
} catch (\Exception $e) {
    MonitorKit::finishSpan($span, true, $e->getMessage());
    throw $e;
}

Excluding paths

Edit exclude_paths in config/packages/monitorkit.yaml:

monitorkit:
    exclude_paths:
        - '#^/_profiler#'
        - '#^/_wdt#'
        - '#^/health$#'
        - '#^/api/internal/ping$#'
        - '#\.(css|js|png|ico)$#i'

Disable in test / local environments

# config/packages/test/monitorkit.yaml
monitorkit:
    enabled: false

Or via env var:

MONITORKIT_ENABLED=false

How it works

  1. MonitorKitBundle registers MonitorKitExtension as the DI extension
  2. The extension registers:
    • RequestListener — subscribes to kernel.request (start) and kernel.terminate (finish + ship)
    • ExceptionListener — subscribes to kernel.exception to mark traces as errors
    • QueryLogger — wired into Doctrine's default connection configuration by a compiler pass (DoctrineLoggerPass), not the extension itself (DBAL 2.x)
    • QueryMiddleware — tagged doctrine.middleware for DoctrineBundle's own compiler pass to collect (DBAL 3.x)
    • MessageListener — subscribes to Messenger worker events (when symfony/messenger is present)
  3. kernel.terminate fires after the response is sent to the client, so sending the trace adds zero latency to HTTP response time

Symfony 3.4 notes

  • Use app/AppKernel.php to register the bundle (see Installation)
  • The config file goes in app/config/config.yml under the monitorkit: key
  • kernel.terminate fires after fastcgi_finish_request() in PHP-FPM (zero latency) or after the script ends in CGI mode

Support