Class: Datadog::Tracer

Inherits:
Object
  • Object
show all
Defined in:
lib/ddtrace/tracer.rb

Overview

A Tracer keeps track of the time spent by an application processing a single operation. For example, a trace can be used to track the entire time spent processing a complicated web request. Even though the request may require multiple resources and machines to handle the request, all of these function calls and sub-requests would be encapsulated within a single trace.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Tracer

Initialize a new Tracer used to create, sample and submit spans that measure the time of sections of code. Available options are:

  • enabled: set if the tracer submits or not spans to the local agent. It’s enabled by default.



44
45
46
47
48
49
50
51
52
# File 'lib/ddtrace/tracer.rb', line 44

def initialize(options = {})
  @enabled = options.fetch(:enabled, true)
  @writer = options.fetch(:writer, Datadog::Writer.new)
  @buffer = Datadog::SpanBuffer.new()

  @mutex = Mutex.new
  @spans = []
  @services = {}
end

Instance Attribute Details

#enabledObject

Returns the value of attribute enabled.



17
18
19
# File 'lib/ddtrace/tracer.rb', line 17

def enabled
  @enabled
end

#servicesObject (readonly)

Returns the value of attribute services.



16
17
18
# File 'lib/ddtrace/tracer.rb', line 16

def services
  @services
end

#writerObject (readonly)

Returns the value of attribute writer.



16
17
18
# File 'lib/ddtrace/tracer.rb', line 16

def writer
  @writer
end

Class Method Details

.debug_loggingObject

Return if the debug mode is activated or not



35
36
37
# File 'lib/ddtrace/tracer.rb', line 35

def self.debug_logging
  log.level == Logger::DEBUG
end

.debug_logging=(value) ⇒ Object

Activate the debug mode providing more information related to tracer usage



30
31
32
# File 'lib/ddtrace/tracer.rb', line 30

def self.debug_logging=(value)
  log.level = value ? Logger::DEBUG : Logger::INFO
end

.logObject

Global, memoized, lazy initialized instance of a logger that is used within the the Datadog namespace. This logger outputs to STDOUT by default, and is considered thread-safe.



21
22
23
24
25
26
27
# File 'lib/ddtrace/tracer.rb', line 21

def self.log
  unless defined? @logger
    @logger = Logger.new(STDOUT)
    @logger.level = Logger::INFO
  end
  @logger
end

Instance Method Details

#active_spanObject

Return the current active span or nil.



163
164
165
# File 'lib/ddtrace/tracer.rb', line 163

def active_span
  @buffer.get()
end

#configure(options = {}) ⇒ Object

Updates the current Tracer instance, so that the tracer can be configured after the initialization. Available options are:

  • enabled: set if the tracer submits or not spans to the trace agent

  • hostname: change the location of the trace agent

  • port: change the port of the trace agent

For instance, if the trace agent runs in a different location, just:

tracer.configure(hostname: 'agent.service.consul', port: '8777')


65
66
67
68
69
70
71
72
73
# File 'lib/ddtrace/tracer.rb', line 65

def configure(options = {})
  enabled = options.fetch(:enabled, nil)
  hostname = options.fetch(:hostname, nil)
  port = options.fetch(:port, nil)

  @enabled = enabled unless enabled.nil?
  @writer.transport.hostname = hostname unless hostname.nil?
  @writer.transport.port = port unless port.nil?
end

#record(span) ⇒ Object

Record the given finished span in the spans list. When a span is recorded, it will be sent to the Datadog trace agent as soon as the trace is finished.



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/ddtrace/tracer.rb', line 143

def record(span)
  spans = []
  @mutex.synchronize do
    @spans << span
    parent = span.parent
    # Bubble up until we find a non-finished parent. This is necessary for
    # the case when the parent finished after its parent.
    parent = parent.parent while !parent.nil? && parent.finished?
    @buffer.set(parent)

    return unless parent.nil?
    spans = @spans
    @spans = []
  end

  return if spans.empty?
  write(spans)
end

#set_service_info(service, app, app_type) ⇒ Object

Set the information about the given service. A valid example is:

tracer.set_service_info('web-application', 'rails', 'web')


78
79
80
81
82
83
84
85
86
# File 'lib/ddtrace/tracer.rb', line 78

def set_service_info(service, app, app_type)
  @services[service] = {
    'app' => app,
    'app_type' => app_type
  }

  return unless Datadog::Tracer.debug_logging
  Datadog::Tracer.log.debug("set_service_info: service: #{service} app: #{app} type: #{app_type}")
end

#trace(name, options = {}) ⇒ Object

Return a span that will trace an operation called name. You could trace your code using a do-block like:

tracer.trace('web.request') do |span|
  span.service = 'my-web-site'
  span.resource = '/'
  span.set_tag('http.method', request.request_method)
  do_something()
end

The tracer.trace() method can also be used without a block in this way:

span = tracer.trace('web.request', service: 'my-web-site')
do_something()
span.finish()

Remember that in this case, calling span.finish() is mandatory.

When a Trace is started, trace() will store the created span; subsequent spans will become it’s children and will inherit some properties:

parent = tracer.trace('parent')     # has no parent span
child  = tracer.trace('child')      # is a child of 'parent'
child.finish()
parent.finish()
parent2 = tracer.trace('parent2')   # has no parent span
parent2.finish()


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/ddtrace/tracer.rb', line 116

def trace(name, options = {})
  span = Span.new(self, name, options)

  # set up inheritance
  parent = @buffer.get()
  span.set_parent(parent)
  @buffer.set(span)

  # call the finish only if a block is given; this ensures
  # that a call to tracer.trace() without a block, returns
  # a span that should be manually finished.
  if block_given?
    begin
      yield(span)
    rescue StandardError => e
      span.set_error(e)
      raise
    ensure
      span.finish()
    end
  else
    span
  end
end