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. rubocop:disable Metrics/ClassLength
Constant Summary collapse
- ALLOWED_SPAN_OPTIONS =
[:service, :resource, :span_type].freeze
- DEFAULT_ON_ERROR =
proc { |span, error| span.set_error(error) unless span.nil? }
Instance Attribute Summary collapse
-
#context_flush ⇒ Object
readonly
Returns the value of attribute context_flush.
-
#default_service ⇒ Object
A default value for service.
-
#enabled ⇒ Object
Returns the value of attribute enabled.
-
#provider ⇒ Object
readonly
Returns the value of attribute provider.
-
#sampler ⇒ Object
readonly
Returns the value of attribute sampler.
-
#tags ⇒ Object
readonly
Returns the value of attribute tags.
-
#writer ⇒ Object
Returns the value of attribute writer.
Instance Method Summary collapse
-
#active_correlation ⇒ Object
Return a CorrelationIdentifier for active span.
-
#active_root_span ⇒ Object
Return the current active root span or
nil. -
#active_span ⇒ Object
Return the current active span or
nil. -
#call_context ⇒ Object
Return the current active Context for this traced execution.
-
#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(context) ⇒ Object
Record the given
context. - #services ⇒ Object
-
#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.
-
#shutdown! ⇒ Object
Shorthand that calls the ‘shutdown!` method of a registered worker.
-
#start_span(name, options = {}) ⇒ Object
Return a span that will trace an operation called name.
-
#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.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/ddtrace/tracer.rb', line 72 def initialize( = {}) @enabled = .fetch(:enabled, true) @writer = .fetch(:writer, Datadog::Writer.new) @sampler = .fetch(:sampler, Datadog::AllSampler.new) @provider = .fetch(:context_provider, Datadog::DefaultContextProvider.new) @provider ||= Datadog::DefaultContextProvider.new # @provider should never be nil @context_flush = if [:partial_flush] Datadog::ContextFlush::Partial.new() else Datadog::ContextFlush::Finished.new end @mutex = Mutex.new = .fetch(:tags, Datadog.configuration.) @default_service = .fetch(:default_service, Datadog.configuration.service) # Enable priority sampling by default activate_priority_sampling!(@sampler) end |
Instance Attribute Details
#context_flush ⇒ Object (readonly)
Returns the value of attribute context_flush.
23 24 25 |
# File 'lib/ddtrace/tracer.rb', line 23 def context_flush @context_flush end |
#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.
142 143 144 145 146 147 148 149 150 151 |
# File 'lib/ddtrace/tracer.rb', line 142 def default_service return @default_service if instance_variable_defined?(:@default_service) && @default_service begin @default_service = File.basename($PROGRAM_NAME, '.*') rescue StandardError => e Datadog::Logger.log.error("unable to guess default service: #{e}") @default_service = 'ruby'.freeze end @default_service end |
#enabled ⇒ Object
Returns the value of attribute enabled.
24 25 26 |
# File 'lib/ddtrace/tracer.rb', line 24 def enabled @enabled end |
#provider ⇒ Object (readonly)
Returns the value of attribute provider.
23 24 25 |
# File 'lib/ddtrace/tracer.rb', line 23 def provider @provider end |
#sampler ⇒ Object (readonly)
Returns the value of attribute sampler.
23 24 25 |
# File 'lib/ddtrace/tracer.rb', line 23 def sampler @sampler end |
#tags ⇒ Object (readonly)
Returns the value of attribute tags.
23 24 25 |
# File 'lib/ddtrace/tracer.rb', line 23 def end |
#writer ⇒ Object
Returns the value of attribute writer.
24 25 26 |
# File 'lib/ddtrace/tracer.rb', line 24 def writer @writer end |
Instance Method Details
#active_correlation ⇒ Object
Return a CorrelationIdentifier for active span
328 329 330 |
# File 'lib/ddtrace/tracer.rb', line 328 def active_correlation Datadog::Correlation.identifier_from_context(call_context) end |
#active_root_span ⇒ Object
Return the current active root span or nil.
323 324 325 |
# File 'lib/ddtrace/tracer.rb', line 323 def active_root_span call_context.current_root_span end |
#active_span ⇒ Object
Return the current active span or nil.
318 319 320 |
# File 'lib/ddtrace/tracer.rb', line 318 def active_span call_context.current_span end |
#call_context ⇒ Object
Return the current active Context for this traced execution. This method is automatically called when calling Tracer.trace or Tracer.start_span, but it can be used in the application code during manual instrumentation.
This method makes use of a ContextProvider that is automatically set during the tracer initialization, or while using a library instrumentation.
63 64 65 |
# File 'lib/ddtrace/tracer.rb', line 63 def call_context @provider.context 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 -
partial_flush: enable partial trace flushing
For instance, if the trace agent runs in a different location, just:
tracer.configure(hostname: 'agent.service.consul', port: '8777')
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/ddtrace/tracer.rb', line 106 def configure( = {}) enabled = .fetch(:enabled, nil) # Those are rare "power-user" options. sampler = .fetch(:sampler, nil) @enabled = enabled unless enabled.nil? @sampler = sampler unless sampler.nil? configure_writer() @context_flush = if [:partial_flush] Datadog::ContextFlush::Partial.new() else Datadog::ContextFlush::Finished.new end end |
#record(context) ⇒ Object
Record the given context. For compatibility with previous versions, context can also be a span. It is similar to the child_of argument, method will figure out what to do, submitting a span for recording is like trying to record its context.
298 299 300 301 302 303 |
# File 'lib/ddtrace/tracer.rb', line 298 def record(context) context = context.context if context.is_a?(Datadog::Span) return if context.nil? record_context(context) end |
#services ⇒ Object
30 31 32 33 34 35 36 37 |
# File 'lib/ddtrace/tracer.rb', line 30 def services # Only log each deprecation warning once (safeguard against log spam) Datadog::Patcher.do_once('Tracer#set_service_info') do Datadog::Logger.log.warn('services: Usage of Tracer.services has been deprecated') end {} 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')
set_service_info is deprecated, no service information needs to be tracked
129 130 131 132 133 134 135 136 137 |
# File 'lib/ddtrace/tracer.rb', line 129 def set_service_info(service, app, app_type) # Only log each deprecation warning once (safeguard against log spam) Datadog::Patcher.do_once('Tracer#set_service_info') do Datadog::Logger.log.warn(%( set_service_info: Usage of set_service_info has been deprecated, service information no longer needs to be reported to the trace agent. )) end 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')
158 159 160 161 |
# File 'lib/ddtrace/tracer.rb', line 158 def () = Hash[.collect { |k, v| [k.to_s, v] }] = .merge() end |
#shutdown! ⇒ Object
Shorthand that calls the ‘shutdown!` method of a registered worker. It’s useful to ensure that the Trace Buffer is properly flushed before shutting down the application.
For instance:
tracer.trace('operation_name', service='rake_tasks') do |span|
span.set_tag('task.name', 'script')
end
tracer.shutdown!
51 52 53 54 55 |
# File 'lib/ddtrace/tracer.rb', line 51 def shutdown! return unless @enabled @writer.stop unless @writer.nil? end |
#start_span(name, options = {}) ⇒ Object
Return a span that will trace an operation called name. This method allows parenting passing child_of as an option. If it’s missing, the newly created span is a root span. Available options are:
-
service: the service name for this span -
resource: the resource this span refers, or name if it’s missing -
span_type: the type of the span (such as http, db and so on) -
child_of: a Span or a Context instance representing the parent for this span. -
start_time: when the span actually starts (defaults to now) -
tags: extra tags which should be added to the span.
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/ddtrace/tracer.rb', line 185 def start_span(name, = {}) start_time = .fetch(:start_time, Time.now.utc) = .fetch(:tags, {}) = .select do |k, _v| # Filter options, we want no side effects with unexpected args. ALLOWED_SPAN_OPTIONS.include?(k) end ctx, parent = guess_context_and_parent([:child_of]) [:context] = ctx unless ctx.nil? span = Span.new(self, name, ) if parent.nil? # root span @sampler.sample!(span) span.set_tag('system.pid', Process.pid) if ctx && ctx.trace_id span.trace_id = ctx.trace_id span.parent_id = ctx.span_id unless ctx.span_id.nil? end else # child span span.parent = parent # sets service, trace_id, parent_id, sampled end .each { |k, v| span.set_tag(k, v) } unless .empty? .each { |k, v| span.set_tag(k, v) } unless .empty? span.start_time = start_time # this could at some point be optional (start_active_span vs start_manual_span) ctx.add_span(span) unless ctx.nil? span 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()
Available options are:
-
service: the service name for this span -
resource: the resource this span refers, or name if it’s missing -
span_type: the type of the span (such as http, db and so on) -
tags: extra tags which should be added to the span.
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/ddtrace/tracer.rb', line 256 def trace(name, = {}) [:child_of] = call_context # 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? span = nil return_value = nil begin begin span = start_span(name, ) # rubocop:disable Lint/UselessAssignment rescue StandardError => e Datadog::Logger.log.debug('Failed to start span: #{e}') ensure return_value = yield(span) end # rubocop:disable Lint/RescueException # Here we really want to catch *any* exception, not only StandardError, # as we really have no clue of what is in the block, # and it is user code which should be executed no matter what. # It's not a problem since we re-raise it afterwards so for example a # SignalException::Interrupt would still bubble up. rescue Exception => e ([:on_error] || DEFAULT_ON_ERROR).call(span, e) raise e ensure span.finish unless span.nil? end return_value else start_span(name, ) end end |