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
Defined Under Namespace
Classes: TraceCompleted
Constant Summary collapse
- SERVICES_DEPRECATION_WARN_ONLY_ONCE =
Datadog::Utils::OnlyOnce.new
- SET_SERVICE_INFO_DEPRECATION_WARN_ONLY_ONCE =
Datadog::Utils::OnlyOnce.new
- 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(key = nil) ⇒ Object
Return a CorrelationIdentifier for active span.
-
#active_root_span(key = nil) ⇒ Object
Return the current active root span or +nil+.
-
#active_span(key = nil) ⇒ Object
Return the current active span or +nil+.
-
#call_context(key = nil) ⇒ 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 +span+ that will trace an operation called +name+.
- #trace_completed ⇒ Object
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.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/ddtrace/tracer.rb', line 76 def initialize( = {}) # Configurable options @context_flush = if [:context_flush] [:context_flush] elsif [:partial_flush] Datadog::ContextFlush::Partial.new() else Datadog::ContextFlush::Finished.new end @default_service = [:default_service] @enabled = .fetch(:enabled, true) @provider = [:context_provider] || Datadog::DefaultContextProvider.new @sampler = .fetch(:sampler, Datadog::AllSampler.new) @tags = .fetch(:tags, {}) @writer = .fetch(:writer) { Datadog::Writer.new } # Instance variables @mutex = Mutex.new # Enable priority sampling by default activate_priority_sampling!(@sampler) end |
Instance Attribute Details
#context_flush ⇒ Object (readonly)
Returns the value of attribute context_flush.
28 29 30 |
# File 'lib/ddtrace/tracer.rb', line 28 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.
151 152 153 |
# File 'lib/ddtrace/tracer.rb', line 151 def default_service @default_service ||= Datadog::Ext::Environment::FALLBACK_SERVICE_NAME end |
#enabled ⇒ Object
Returns the value of attribute enabled.
29 30 31 |
# File 'lib/ddtrace/tracer.rb', line 29 def enabled @enabled end |
#provider ⇒ Object (readonly)
Returns the value of attribute provider.
28 29 30 |
# File 'lib/ddtrace/tracer.rb', line 28 def provider @provider end |
#sampler ⇒ Object (readonly)
Returns the value of attribute sampler.
28 29 30 |
# File 'lib/ddtrace/tracer.rb', line 28 def sampler @sampler end |
#tags ⇒ Object (readonly)
Returns the value of attribute tags.
28 29 30 |
# File 'lib/ddtrace/tracer.rb', line 28 def @tags end |
#writer ⇒ Object
Returns the value of attribute writer.
29 30 31 |
# File 'lib/ddtrace/tracer.rb', line 29 def writer @writer end |
Instance Method Details
#active_correlation(key = nil) ⇒ Object
Return a CorrelationIdentifier for active span
353 354 355 |
# File 'lib/ddtrace/tracer.rb', line 353 def active_correlation(key = nil) Datadog::Correlation.identifier_from_context(call_context(key)) end |
#active_root_span(key = nil) ⇒ Object
Return the current active root span or +nil+.
348 349 350 |
# File 'lib/ddtrace/tracer.rb', line 348 def active_root_span(key = nil) call_context(key).current_root_span end |
#active_span(key = nil) ⇒ Object
Return the current active span or +nil+.
343 344 345 |
# File 'lib/ddtrace/tracer.rb', line 343 def active_span(key = nil) call_context(key).current_span end |
#call_context(key = nil) ⇒ 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.
67 68 69 |
# File 'lib/ddtrace/tracer.rb', line 67 def call_context(key = nil) @provider.context(key) 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')
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/ddtrace/tracer.rb', line 112 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() if .key?(:context_flush) || .key?(:partial_flush) @context_flush = if [:context_flush] [:context_flush] elsif [:partial_flush] Datadog::ContextFlush::Partial.new() else Datadog::ContextFlush::Finished.new end 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+.
323 324 325 326 327 328 |
# File 'lib/ddtrace/tracer.rb', line 323 def record(context) context = context.context if context.is_a?(Datadog::Span) return if context.nil? record_context(context) end |
#services ⇒ Object
35 36 37 38 39 40 41 |
# File 'lib/ddtrace/tracer.rb', line 35 def services SERVICES_DEPRECATION_WARN_ONLY_ONCE.run do Datadog.logger.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
139 140 141 142 143 144 145 146 |
# File 'lib/ddtrace/tracer.rb', line 139 def set_service_info(service, app, app_type) SET_SERVICE_INFO_DEPRECATION_WARN_ONLY_ONCE.run do Datadog.logger.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.set_tags('env' => 'prod', 'component' => 'core')
160 161 162 163 |
# File 'lib/ddtrace/tracer.rb', line 160 def () = .collect { |k, v| [k.to_s, v] }.to_h @tags = @tags.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!
55 56 57 58 59 |
# File 'lib/ddtrace/tracer.rb', line 55 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.
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 221 222 223 |
# File 'lib/ddtrace/tracer.rb', line 187 def start_span(name, = {}) start_time = [:start_time] = .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(Datadog::Ext::Runtime::TAG_PID, Process.pid) span.set_tag(Datadog::Ext::Runtime::TAG_ID, Datadog::Core::Environment::Identity.id) 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 span.(@tags) unless @tags.empty? span.() unless .empty? span.start(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)
- +child_of+: a \Span or a \Context instance representing the parent for this span. If not set, defaults to Tracer.call_context
- +tags+: extra tags which should be added to the span.
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 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/ddtrace/tracer.rb', line 261 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, ) rescue StandardError => e Datadog.logger.debug("Failed to start span: #{e}") ensure # We should yield to the provided block when possible, as this # block is application code that we don't want to hinder. We call: # * `yield(span)` during normal execution. # * `yield(nil)` if `start_span` fails with a runtime error. # * We don't yield during a fatal error, as the application is likely trying to # end its execution (either due to a system error or graceful shutdown). return_value = yield(span) if span || e.is_a?(StandardError) 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. # rubocop:disable Metrics/BlockNesting rescue Exception => e if (on_error_handler = [:on_error]) && on_error_handler.respond_to?(:call) begin on_error_handler.call(span, e) rescue Datadog.logger.debug('Custom on_error handler failed, falling back to default') DEFAULT_ON_ERROR.call(span, e) end else Datadog.logger.debug('Custom on_error handler must be a callable, falling back to default') if on_error_handler DEFAULT_ON_ERROR.call(span, e) end raise e ensure span.finish unless span.nil? end return_value else start_span(name, ) end end |
#trace_completed ⇒ Object
315 316 317 |
# File 'lib/ddtrace/tracer.rb', line 315 def trace_completed @trace_completed ||= TraceCompleted.new end |