Class: Dtrace::Provider

Inherits:
Object
  • Object
show all
Defined in:
lib/dtrace/provider.rb,
lib/dtrace/provider/osx.rb,
lib/dtrace/provider/solaris.rb

Overview

A DTrace provider. Allows creation of USDT probes on a running Ruby program, by dynamically creating an extension module implementing the probes, and compiling and loading it. You can use this with a Ruby interpreter compiled with the core DTrace probes, but you don’t have to.

This requires the DTrace and Ruby toolchains to be available: dtrace(1M), and the compiler and linker used to build Ruby. The process is similar to RubyInline, but the actual RubyInline library is not required (the build process for DTrace USDT probes is sufficiently differnent to a standard Ruby extension that it’s not worth using it).

Both Solaris and OSX 10.5 are supported. Other DTrace-supporting platforms can be added by creating a new class under Dtrace::Provider and implementing or overriding the required steps in the build process.

Firing probes is explained in Dtrace::Probe.

There are some limitations:

You cannot choose all the components of the probe name: you can choose the provider and probe name, but the module and function components will be derived by DTrace, and won’t be meaningful (they’ll refer to the shim extension that gets created, not to anything in your Ruby program). It seems unlikely it’s possible to change this.

You cannot currently set D attributes: they’re hardcoded to a default set. This will change.

The extension will currently be rebuilt every time the provider is created, as there’s not yet any support for packaging the provider in some way. This will change, to something along the lines of what RubyInline does to allow a pre-built extension to be used.

Direct Known Subclasses

OSX, Solaris

Defined Under Namespace

Classes: BuildError, OSX, Solaris

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Provider

Returns a new instance of Provider.



104
105
106
107
108
# File 'lib/dtrace/provider.rb', line 104

def initialize(name)
  @name   = name.to_s
  @class  = camelize(name)
  @probes = {}
end

Class Method Details

.create(name) {|provider| ... } ⇒ Object

Creates a DTrace provider. Causes a shim extension to be built and loaded, implementing the probes.

Example:

Dtrace::Provider.create :action_controller do |p|
  p.probe :process_start,  :string
  p.probe :process_finish, :string, :integer
end

The symbol passed to create becomes the name of the provider, and the class exposed under Dtrace::Probe in Ruby (camelized, so the above statement creates Dtrace::Probe::ActionController).

create yields a Provider for the current platform, on which you can call probe, to create the individual probes.

Yields:

  • (provider)


74
75
76
77
78
79
80
81
82
# File 'lib/dtrace/provider.rb', line 74

def self.create(name)
  if RUBY_PLATFORM =~ /darwin/
    provider = Dtrace::Provider::OSX.new(name)
  else
    provider = Dtrace::Provider::Solaris.new(name)
  end
  yield provider
  provider.enable
end

Instance Method Details

#enableObject



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/dtrace/provider.rb', line 110

def enable
  Tempfile.open("dtrace_probe_#{@name}") do |f|
    p = Pathname.new(f.path)
    @tempdir = "#{p.dirname}/#{@name}" 
    begin
      Dir.mkdir @tempdir
    rescue Errno::EEXIST
      nil
    end

    # Probe setup is split up for easy overriding
    definition
    header
    source
    ruby_object
    dtrace_object
    link
    load
  end
end

#probe(name, *types) ⇒ Object

Creates a DTrace USDT probe. Arguments are the probe name, and then the argument types it will accept. The following argument types are supported:

:string (char *) :integer (int)

The probe will be named based on the provider name and the probe’s name:

provider_name:provider_name.so:probe_name:probe-name

See the limitations explained elsewhere for an explanation of this redundancy in probe names.



99
100
101
102
# File 'lib/dtrace/provider.rb', line 99

def probe(name, *types) 
  typemap = { :string => 'char *', :integer => 'int' } 
  @probes[name] = types.map {|t| typemap[t]} 
end