Devel::DTrace::Provider::Builder - declaratively create DTrace USDT providers


  package MyApp::DTraceProviders;
  use strict;
  use warnings;

  use Devel::DTrace::Provider::Builder;

  provider 'backend' => as {
      probe 'process_start', 'integer';
      probe 'process_end',   'integer';

  provider 'frontend' => as {
      probe 'render_start', 'string';
      probe 'render_end',   'string';

  # elsewhere

  use MyApp::DTraceProviders;


  # Or use probes immediately in the same package.

  use Devel::DTrace::Provider::Builder;
  use strict;
  use warnings;

    provider 'provider1' => as {
      probe 'probe1', 'string';
      probe 'probe2', 'string';

  probe1 { shift->fire('foo') } if probe1_enabled;
  probe2 { shift->fire('foo') } if probe2_enabled;


This module provides a declarative way of creating DTrace providers, in packages which export their probes on import. This is typically what you want when creating a provider for use in a large application:

Providers created with this module may be used on systems where DTrace is not supported: the probes will be optimised away entirely -- see "DISABLED PROBE EFFECT", below.

Declare your provider in its own package
Use the provider in your application
Fire the probes imported

Declare the providers

You can declare any number of providers in a single package: they will all be enabled and their probes imported when the package is used.

The general syntax of a provider declaration is:

  provider 'provider_name' => as {
    probe 'probe_name', [ 'argument-type', ... ];

The supported argument types are 'integer' and 'string', corresponding to native int and char * probe arguments.

Use the provider

Just use the package where you defined the provider:

  use MyApp::DTraceProviders;

This will import all the probe subs defined in the package into your namespace.

Fire the probes

To fire a probe, call the function, passing a coderef in which you call the fire method on $_[0]:

  probe { shift->fire };

The coderef is only called if the probe is enabled by DTrace, so you can do whatever work is necessary to gather probe arguments and know that code will not run when DTrace is not active:

  probe {
    my @args = gather_expensive_args();


Two features allow you to reduce the disabled probe effect:

Argument-gathering coderef
*_enabled functions

Argument-gathering coderef

This applies to code on DTrace enabled systems: the coderef is only executed if the probe is enabled, so you can put code there which only runs when tracing is active.

*_enabled functions

This applies to systems without DTrace: if you form your probe tracepoints with a postfix if, like this:

  fooprobe { shift->fire } if fooprobe_enabled;

on a system without DTrace, fooprobe_enabled will be a constant sub returning 0, and the entire line will be optimised away, which means probes embedded in code have zero overhead. This feature is taken from Tim Bunce's DashProfiler: