Class: Rack::Insight::Instrumentation::Probe

Inherits:
Object
  • Object
show all
Extended by:
Logging
Includes:
Logging
Defined in:
lib/rack/insight/instrumentation/probe.rb

Direct Known Subclasses

ClassProbe, InstanceProbe

Defined Under Namespace

Modules: Interpose, ProbeRunner

Constant Summary collapse

@@class_list =
nil

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logging

logger, verbose, verbosity

Constructor Details

#initialize(const) ⇒ Probe

Returns a new instance of Probe.



84
85
86
87
88
89
# File 'lib/rack/insight/instrumentation/probe.rb', line 84

def initialize(const)
  @const = const
  @probed = {}
  @collectors = Hash.new{|h,k| h[k] = []}
  @probe_orders = []
end

Class Method Details

.all_probesObject



75
76
77
# File 'lib/rack/insight/instrumentation/probe.rb', line 75

def all_probes
  probes.values
end

.class_listObject



36
37
38
39
40
41
42
43
44
# File 'lib/rack/insight/instrumentation/probe.rb', line 36

def class_list
  @@class_list ||= begin
                     classes = []
                     ObjectSpace.each_object(Class) do |klass|
                       classes << klass
                     end
                     classes
                   end
end

.const_from_name(name) ⇒ Object



57
58
59
60
61
62
# File 'lib/rack/insight/instrumentation/probe.rb', line 57

def const_from_name(name)
  parts = name.split("::")
  const = parts.inject(Kernel) do |namespace, part|
    namespace.const_get(part)
  end
end

.get_probe_chain(name) ⇒ Object



46
47
48
49
50
51
52
53
54
55
# File 'lib/rack/insight/instrumentation/probe.rb', line 46

def get_probe_chain(name)
  const = const_from_name(name)
  chain = []
  const.ancestors.each do |mod|
    if probes.has_key?(mod.name)
      chain << probes[mod.name]
    end
  end
  chain
end

.probe_for(const) ⇒ Object



79
80
81
# File 'lib/rack/insight/instrumentation/probe.rb', line 79

def probe_for(const)
  probes[const]
end

.probesObject



64
65
66
67
68
69
70
71
72
73
# File 'lib/rack/insight/instrumentation/probe.rb', line 64

def probes
  @probes ||= Hash.new do |h,k|
    begin
      h[k] = self.new(const_from_name(k))
    rescue NameError
      logger.warn{ "Cannot find constant: #{k}" } if verbose(:med)
      false
    end
  end
end

Instance Method Details

#all_collectorsObject



95
96
97
# File 'lib/rack/insight/instrumentation/probe.rb', line 95

def all_collectors
  @collectors.values
end

#build_tracing_wrappers(target, method_name) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
# File 'lib/rack/insight/instrumentation/probe.rb', line 163

def build_tracing_wrappers(target, method_name)
  return if @probed.has_key?([target,method_name])
  @probed[[target,method_name]] = true

  meth = get_method(target, method_name)

  log{ {:tracing => meth } }
  define_trace_method(target, meth)
rescue NameError => ne
  log{ {:not_tracing => NameError } }
end

#clear_collectorsObject



99
100
101
# File 'lib/rack/insight/instrumentation/probe.rb', line 99

def clear_collectors
  @collectors.clear
end

#collectors(key) ⇒ Object



91
92
93
# File 'lib/rack/insight/instrumentation/probe.rb', line 91

def collectors(key)
  @collectors[key.to_sym]
end

#define_trace_method(target, method) ⇒ Object



153
154
155
156
157
158
159
160
161
# File 'lib/rack/insight/instrumentation/probe.rb', line 153

def define_trace_method(target, method)
  target.class_exec() do
    define_method(method.name) do |*args, &block|
      ProbeRunner::probe_run(self, method.owner.name, :instance, args, caller(0)[0], method.name) do
        method.bind(self).call(*args, &block)
      end
    end
  end
end

#descendantsObject



112
113
114
115
116
# File 'lib/rack/insight/instrumentation/probe.rb', line 112

def descendants
  @descendants ||= self.class.class_list.find_all do |klass|
    klass.ancestors.include?(@const)
  end
end

#descendants_that_define(method_name) ⇒ Object



122
123
124
125
126
127
# File 'lib/rack/insight/instrumentation/probe.rb', line 122

def descendants_that_define(method_name)
  log{{ :descendants => descendants }}
  descendants.find_all do |klass|
    (@const != klass and local_method_defs(klass).include?(method_name))
  end
end

#fulfill_probe_ordersObject



136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/rack/insight/instrumentation/probe.rb', line 136

def fulfill_probe_orders
  log{{:probes_for => @const.name, :type => self.class}}
  @probe_orders.each do |method_name|
    log{{ :method => method_name }}
    build_tracing_wrappers(@const, method_name)
    descendants_that_define(method_name).each do |klass|
      log{{ :subclass => klass.name }}
      build_tracing_wrappers(klass, method_name)
    end
  end
  @probe_orders.clear
end

#get_method(klass, method_name) ⇒ Object



149
150
151
# File 'lib/rack/insight/instrumentation/probe.rb', line 149

def get_method(klass, method_name)
  klass.instance_method(method_name)
end

#local_method_defs(klass) ⇒ Object



118
119
120
# File 'lib/rack/insight/instrumentation/probe.rb', line 118

def local_method_defs(klass)
  klass.instance_methods(false)
end

#log(&block) ⇒ Object



130
131
132
133
134
# File 'lib/rack/insight/instrumentation/probe.rb', line 130

def log &block
  if verbose(:debug)
    logger.debug &block
  end
end

#probe(collector, *methods) ⇒ Object



103
104
105
106
107
108
109
110
# File 'lib/rack/insight/instrumentation/probe.rb', line 103

def probe(collector, *methods)
  methods.each do |name|
    unless @collectors[name.to_sym].include?(collector)
      @collectors[name.to_sym] << collector
    end
    @probe_orders << name
  end
end