Class: Datadog::Tracer
- Inherits:
-
Object
- Object
- Datadog::Tracer
- 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
-
#default_service ⇒ Object
A default value for service.
-
#enabled ⇒ Object
Returns the value of attribute enabled.
-
#sampler ⇒ Object
readonly
Returns the value of attribute sampler.
-
#services ⇒ Object
readonly
Returns the value of attribute services.
-
#tags ⇒ Object
readonly
Returns the value of attribute tags.
-
#writer ⇒ Object
readonly
Returns the value of attribute writer.
Class Method Summary collapse
-
.debug_logging ⇒ Object
Return if the debug mode is activated or not.
-
.debug_logging=(value) ⇒ Object
Activate the debug mode providing more information related to tracer usage.
-
.log ⇒ Object
Global, memoized, lazy initialized instance of a logger that is used within the the Datadog namespace.
-
.log=(logger) ⇒ Object
Override the default logger with a custom one.
Instance Method Summary collapse
-
#active_span ⇒ Object
Return the current active span or
nil. -
#configure(options = {}) ⇒ Object
Updates the current Tracer instance, so that the tracer can be configured after the initialization.
-
#initialize(options = {}) ⇒ Tracer
constructor
Initialize a new Tracer used to create, sample and submit spans that measure the time of sections of code.
-
#record(span) ⇒ Object
Record the given finished span in the
spanslist. -
#set_service_info(service, app, app_type) ⇒ Object
Set the information about the given service.
-
#set_tags(tags) ⇒ Object
Set the given key / value tag pair at the tracer level.
-
#trace(name, options = {}) ⇒ Object
Return a
spanthat will trace an operation calledname.
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.
63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/ddtrace/tracer.rb', line 63 def initialize( = {}) @enabled = .fetch(:enabled, true) @writer = .fetch(:writer, Datadog::Writer.new) @sampler = .fetch(:sampler, Datadog::AllSampler.new) @buffer = Datadog::SpanBuffer.new() @mutex = Mutex.new @spans = [] @services = {} @tags = {} end |
Instance Attribute Details
#default_service ⇒ Object
A default value for service. One should really override this one for non-root spans which have a parent. However, root spans without a service would be invalid and rejected.
115 116 117 118 119 120 121 122 123 124 |
# File 'lib/ddtrace/tracer.rb', line 115 def default_service return @default_service if @default_service begin @default_service = File.basename($PROGRAM_NAME, '.*') rescue => e Datadog::Tracer.log.error("unable to guess default service: #{e}") @default_service = 'ruby'.freeze end @default_service end |
#enabled ⇒ Object
Returns the value of attribute enabled.
20 21 22 |
# File 'lib/ddtrace/tracer.rb', line 20 def enabled @enabled end |
#sampler ⇒ Object (readonly)
Returns the value of attribute sampler.
19 20 21 |
# File 'lib/ddtrace/tracer.rb', line 19 def sampler @sampler end |
#services ⇒ Object (readonly)
Returns the value of attribute services.
19 20 21 |
# File 'lib/ddtrace/tracer.rb', line 19 def services @services end |
#tags ⇒ Object (readonly)
Returns the value of attribute tags.
19 20 21 |
# File 'lib/ddtrace/tracer.rb', line 19 def @tags end |
#writer ⇒ Object (readonly)
Returns the value of attribute writer.
19 20 21 |
# File 'lib/ddtrace/tracer.rb', line 19 def writer @writer end |
Class Method Details
.debug_logging ⇒ Object
Return if the debug mode is activated or not
54 55 56 |
# File 'lib/ddtrace/tracer.rb', line 54 def self.debug_logging log.level == Logger::DEBUG end |
.debug_logging=(value) ⇒ Object
Activate the debug mode providing more information related to tracer usage
49 50 51 |
# File 'lib/ddtrace/tracer.rb', line 49 def self.debug_logging=(value) log.level = value ? Logger::DEBUG : Logger::WARN end |
.log ⇒ Object
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.
25 26 27 28 29 30 31 |
# File 'lib/ddtrace/tracer.rb', line 25 def self.log unless defined? @logger @logger = Datadog::Logger.new(STDOUT) @logger.level = Logger::WARN end @logger end |
.log=(logger) ⇒ Object
Override the default logger with a custom one.
34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/ddtrace/tracer.rb', line 34 def self.log=(logger) return unless logger return unless logger.respond_to? :methods return unless logger.respond_to? :error if logger.respond_to? :methods unimplemented = Logger.new(STDOUT).methods - logger.methods unless unimplemented.empty? logger.error("logger #{logger} does not implement #{unimplemented}") return end end @logger = logger end |
Instance Method Details
#active_span ⇒ Object
Return the current active span or nil.
237 238 239 |
# File 'lib/ddtrace/tracer.rb', line 237 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')
87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/ddtrace/tracer.rb', line 87 def configure( = {}) enabled = .fetch(:enabled, nil) hostname = .fetch(:hostname, nil) port = .fetch(:port, nil) sampler = .fetch(:sampler, nil) @enabled = enabled unless enabled.nil? @writer.transport.hostname = hostname unless hostname.nil? @writer.transport.port = port unless port.nil? @sampler = sampler unless sampler.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.
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/ddtrace/tracer.rb', line 199 def record(span) span.service ||= default_service 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? # In general, all spans within the buffer belong to the same trace. # But in heavily multithreaded contexts and/or when using lots of callbacks # hooks and other non-linear programming style, one can technically # end up in different situations. So we only extract the spans which # are associated to the root span that just finished, and save the # others for later. trace_spans = [] alien_spans = [] @spans.each do |s| if s.trace_id == span.trace_id trace_spans << s else alien_spans << s end end spans = trace_spans @spans = alien_spans end return if spans.empty? || !span.sampled 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')
102 103 104 105 106 107 108 109 110 |
# File 'lib/ddtrace/tracer.rb', line 102 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 |
#set_tags(tags) ⇒ Object
Set the given key / value tag pair at the tracer level. These tags will be appended to each span created by the tracer. Keys and values must be strings. A valid example is:
tracer.('env' => 'prod', 'component' => 'core')
131 132 133 |
# File 'lib/ddtrace/tracer.rb', line 131 def () @tags.update() 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()
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/ddtrace/tracer.rb', line 163 def trace(name, = {}) span = Span.new(self, name, ) # set up inheritance parent = @buffer.get() span.set_parent(parent) @buffer.set(span) @tags.each { |k, v| span.set_tag(k, v) } unless @tags.empty? # sampling if parent.nil? @sampler.sample(span) else span.sampled = span.parent.sampled end # 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 |