Module: ScoutApm::Tracer::ClassMethods

Defined in:
lib/scout_apm/tracer.rb

Instance Method Summary collapse

Instance Method Details

#instrument(metric_name, options = {}, &block) ⇒ Object

Options:

  • :scope - If specified, sets the sub-scope for the metric. We allow additional scope level. This is used

  • uri - the request uri

  • :ignore_children - will not instrument any method calls beneath this call. Example use case: InfluxDB uses Net::HTTP, which is instrumented. However, we can provide more specific data if we know we’re doing an influx call, so we’d rather just instrument the Influx call and ignore Net::HTTP.

when rendering the transaction tree in the UI.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/scout_apm/tracer.rb', line 50

def instrument(metric_name, options={}, &block)
  # don't instrument if (1) NOT inside a transaction and (2) NOT a Controller metric.
  if !Thread::current[:scout_apm_scope_name] and metric_name !~ /\AController\//
    return yield
  elsif Thread::current[:scout_ignore_children]
    return yield
  end

  if options.delete(:scope)
    Thread::current[:scout_apm_sub_scope] = metric_name
  end

  if options[:ignore_children]
    Thread::current[:scout_ignore_children] = true
  end
  stack_item = ScoutApm::Agent.instance.store.record(metric_name)

  begin
    yield
  ensure
    Thread::current[:scout_apm_sub_scope] = nil if Thread::current[:scout_apm_sub_scope] == metric_name
    if options[:ignore_children]
      Thread::current[:scout_ignore_children] = nil
    end

    ScoutApm::Agent.instance.store.stop_recording(stack_item,options)
  end
end

#instrument_method(method, options = {}) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/scout_apm/tracer.rb', line 79

def instrument_method(method, options = {})
  ScoutApm::Agent.instance.logger.info "Instrumenting #{method}"
  metric_name = options[:metric_name] || default_metric_name(method)
  return if !instrumentable?(method) or instrumented?(method,metric_name)

  class_eval(instrumented_method_string(
    method,
    {:metric_name => metric_name, :scope => options[:scope] }),
    __FILE__, __LINE__
  )

  alias_method _uninstrumented_method_name(method, metric_name), method
  alias_method method, _instrumented_method_name(method, metric_name)
end

#scout_apm_trace(metric_name, options = {}, &block) ⇒ Object

Use to trace a method call, possibly reporting slow transaction traces to Scout. Options:

  • uri - the request uri

  • ip - the remote ip of the user. This is merged into the User context.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/scout_apm/tracer.rb', line 21

def scout_apm_trace(metric_name, options = {}, &block)
  # TODO - wrap a lot of this into a Trace class, store that as a Thread var.
  ScoutApm::Agent.instance.store.reset_transaction!
  ScoutApm::Context.current.add_user(:ip => options[:ip]) if options[:ip]
  Thread::current[:scout_apm_trace_time] = Time.now.utc
  ScoutApm::Agent.instance.capacity.start_transaction!
  e = nil
  instrument(metric_name, options) do
    Thread::current[:scout_apm_scope_name] = metric_name
    begin
      yield
    rescue Exception => e
      ScoutApm::Agent.instance.store.track!("Errors/#{metric_name}",1, :scope => nil)
    end
    Thread::current[:scout_apm_scope_name] = nil
  end
  Thread::current[:scout_apm_trace_time] = nil
  ScoutApm::Agent.instance.capacity.finish_transaction!
  # The context is cleared after instrumentation (rather than before) as tracing controller-actions doesn't occur until the controller-action is called.
  # It does not trace before filters, which is a likely spot to add context. This means that any context applied during before_filters would be cleared.
  ScoutApm::Context.clear!
  raise e if e
end