Dumpio

Dokumentace

This page covers the Nette side of the dumpio/client package. Read the PHP library page first for the basics (dio(), Dumpio::dump(), typed helpers) — everything there works in Nette too. Here we add the Dumpio DI extension and its automatic capture.

Setup

Register the extension — dev-only is recommended, so put it in the config your development environment loads:

# config/common.neon (or config/local.neon, loaded only in dev)
extensions:
dumpio: Dumpio\Nette\DumpioExtension

That single line is enough. Everything else has a default, and the connection settings fall back to the environment:

Env var Default Meaning
DUMPIO_HOST localhost Where the Dumpio app listens
DUMPIO_PORT 21234 The port
DUMPIO_TOKEN "" Shared token, if the app requires one
DUMPIO_DISABLE (unset) Set it to turn the client off

You can also set them in NEON, which wins over the environment:

dumpio:
host: localhost
port: 21234
token: secret
enabled: %debugMode%

Why the env fallback matters. Nette compiles the DI container once and caches it. Anything you write in NEON is baked into that cached container; anything you leave out is resolved on every container creation, from the environment. So keep per-machine values (host, port, token) in the environment — or at least out of the config you commit — and the same cached container works for everyone.

What it captures automatically

Once the extension is registered it wires itself into the services your application actually has. Nothing here needs code changes.

Condition What it forwards Dump type / channel
nette/application Unhandled exceptions (Application::$onError), with request context exception
nette/application Every request opens a correlation scope (METHOD /path) — (metadata)
nette/database Every executed SQL statement (SQL + bindings + timing) query (database)
tracy/tracy Everything Tracy logs — exceptions, warnings, Debugger::log() exception / log (tracy)
nette/mail + listenMail: true Every outgoing email, as a rendered preview mail (mail)
nette/caching + listenCache: true Cache hit / missed / written / forgotten / cleaned event (cache)
latte/latte + listenViews: true Each rendered template, with render time measure (views)

Exceptions

Two independent paths, because Nette reports errors in two different places:

  • Application::$onError — every exception that escapes a presenter is forwarded as an exception dump with the request context (URL, method, query, client IP) and the presenter class. It fires whether Tracy shows you a BlueScreen or an error presenter takes over.
  • Tracy's logger — the extension wraps Tracy\Debugger's logger, so everything Tracy records also reaches the viewer: fatal errors, warnings Tracy promotes, exceptions thrown outside the application (bootstrap, CLI commands, cron) and anything you send through Debugger::log() yourself. Throwables arrive as exception dumps, plain messages as log dumps on the tracy channel, with the Tracy severity mapped onto the flag color.

The original logger keeps running exactly as before — Tracy still writes its log files and sends its emails. See the app's Exceptions page for how a parsed exception renders.

Requests

On every request the extension opens a correlation scope labelled METHOD /path (GET /users), and closes it when the application shuts down. Every dump made in between carries the same requestId, so the viewer can group a request's dumps into one collapsible unit instead of a flat stream. It costs nothing — it is metadata on dumps you were already sending, not extra dumps. Console commands have no request and stay ungrouped.

Turn it off with stampRequests: false.

Database queries

Each Nette\Database\Connection in the container gets an onQuery listener that forwards every executed statement as a query dump on the database channel: the SQL, the bound parameters and the execution time. A multi-database app gets one listener per connection, and the connection name (default, analytics, …) rides along on every dump so you can tell them apart.

Failed statements are forwarded too, in red, carrying the driver error — so a broken query is visible right next to the ones that worked, instead of only in the BlueScreen.

Note that Nette's SQL preprocessor inlines values like dates into the statement itself before it reaches PDO; the dump shows the statement Nette actually ran, plus whatever stayed a real bound parameter.

Mail

dumpio:
listenMail: true

The extension puts a decorator in front of your Nette\Mail\Mailer (the same shape Nette's own Interceptor uses), and every outgoing message is previewed in the viewer as a mail dump: rendered HTML and text, subject, from/to/cc/bcc and the attachment list, rendered in the viewer's sandboxed iframe. Delivery is untouched — the message goes to your real mailer exactly as before.

Add interceptMail: true and the real send is swallowed instead (Mailpit-style): dev mail lands in Dumpio only and never reaches a real mailbox.

Off by default, because email payloads are large.

Cache

dumpio:
listenCache: true

The extension decorates Nette\Caching\Storage and forwards every operation as an event dump on the cache channel — cache.hit / cache.missed (with the key), cache.written, cache.forgotten and cache.cleaned. The decorator is a pure passthrough: it never changes what the cache returns and never throws into your app; only the telemetry is added. It implements BulkReader as well, so decorating doesn't cost Cache::bulkLoad() its fast path. This mirrors the Laravel and Symfony cache capture, so all three frameworks land the same shape in the viewer.

Off by default, because it sits in front of every cache call.

Latte templates

dumpio:
listenViews: true

A Latte extension times every rendered template and forwards it as a measure dump on the views channel (template name + render time), so you can see which templates cost what.

Off by default, because it instruments every render.

Configuration reference

dumpio:
# connection — omit to use DUMPIO_HOST / DUMPIO_PORT / DUMPIO_TOKEN / DUMPIO_DISABLE
host: localhost
port: 21234
token: ''
enabled: %debugMode%
 
stampRequests: true # group a request's dumps under one requestId
listenExceptions: true # Application::$onError → exception dumps
listenQueries: true # Nette Database → query dumps
listenLogs: true # Tracy log → exception / log dumps
listenMail: false # outgoing email → mail dumps
interceptMail: false # …and swallow the real send
listenCache: false # cache operations → cache.* events
listenViews: false # Latte renders → measure dumps

Setting a capture to false removes its wiring from the compiled container entirely — no decorator, no listener. Leaving it out keeps the wiring in place and lets the runtime switches decide, which is what makes the toggles below work.

The listenMail / listenCache / listenViews defaults also read DUMPIO_LISTEN_MAIL, DUMPIO_LISTEN_CACHE and DUMPIO_LISTEN_VIEWS, so they can be flipped per machine without touching the config.

Turning capture on and off at runtime

Every capture checks its switch on each call, so you can narrow the stream from inside a presenter, a service, or a console command:

Dumpio::stopShowingQueries(); // quiet the query firehose for a moment
$this->importer->run();
Dumpio::showQueries(); // and back on
 
Dumpio::showAll(); // everything on
Dumpio::stopShowingAll(); // everything off

There's a show…() / stopShowing…() pair for Queries, Exceptions, Logs, Mail, Cache, and Views.

Manual dumps anywhere

The static client and global helpers work from anywhere in your code, independent of the automatic capture:

\Dumpio\Dumpio::query($sql, $bindings, $timeMs);
dumpio($entity, 'entity');
dio($order)->green()->channel('checkout');

Unlike Tracy's dump() and bdump(), they don't need a rendered page or the Tracy bar — a dump from a presenter, a CLI command, a queue worker or an AJAX snippet all land in the same viewer. See the PHP library page for the full set of helpers.