Class: Datadog::Tracing::SpanOperation
- Inherits:
-
Object
- Object
- Datadog::Tracing::SpanOperation
- Includes:
- Metadata
- Defined in:
- lib/datadog/tracing/span_operation.rb
Overview
Represents the act of taking a span measurement. It gives a Span a context which can be used to build a Span. When completed, it yields the Span.
Defined Under Namespace
Classes: AlreadyStartedError, Events
Instance Attribute Summary collapse
-
#end_time ⇒ Object
Span attributes NOTE: In the future, we should drop the me.
-
#id ⇒ Object
readonly
Span attributes NOTE: In the future, we should drop the me.
-
#links ⇒ Object
Returns the value of attribute links.
-
#name ⇒ String
Operation name.
-
#parent_id ⇒ Object
readonly
Span attributes NOTE: In the future, we should drop the me.
-
#resource ⇒ String
Span resource.
-
#service ⇒ String
Service name.
-
#span_events ⇒ Object
Returns the value of attribute span_events.
-
#start_time ⇒ Object
Span attributes NOTE: In the future, we should drop the me.
-
#status ⇒ Object
Returns the value of attribute status.
-
#trace_id ⇒ Object
readonly
Span attributes NOTE: In the future, we should drop the me.
-
#type ⇒ String
Span type.
Instance Method Summary collapse
- #duration ⇒ Object
- #finish(end_time = nil) ⇒ Object
- #finished? ⇒ Boolean
-
#initialize(name, events: nil, on_error: nil, parent_id: 0, resource: name, service: nil, start_time: nil, tags: nil, trace_id: nil, type: nil, links: nil, span_events: nil, id: nil) ⇒ SpanOperation
constructor
A new instance of SpanOperation.
- #measure ⇒ Object
-
#pretty_print(q) ⇒ Object
Return a human readable version of the span.
- #set_error(e) ⇒ Object
- #start(start_time = nil) ⇒ Object
-
#started? ⇒ Boolean
Return whether the duration is started or not.
-
#stop(stop_time = nil) ⇒ Object
Mark the span stopped at the current time.
-
#stopped? ⇒ Boolean
Return whether the duration is stopped or not.
-
#to_hash ⇒ Object
Return the hash representation of the current span.
-
#to_s ⇒ Object
Return a string representation of the span.
Methods included from Metadata
Constructor Details
#initialize(name, events: nil, on_error: nil, parent_id: 0, resource: name, service: nil, start_time: nil, tags: nil, trace_id: nil, type: nil, links: nil, span_events: nil, id: nil) ⇒ SpanOperation
Returns a new instance of SpanOperation.
42 43 44 45 46 47 48 49 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/datadog/tracing/span_operation.rb', line 42 def initialize( name, events: nil, on_error: nil, parent_id: 0, resource: name, service: nil, start_time: nil, tags: nil, trace_id: nil, type: nil, links: nil, span_events: nil, id: nil ) # Ensure dynamically created strings are UTF-8 encoded. # # All strings created in Ruby land are UTF-8. The only sources of non-UTF-8 string are: # * Strings explicitly encoded as non-UTF-8. # * Some natively created string, although most natively created strings are UTF-8. self.name = name self.service = service self.type = type self.resource = resource @id = id.nil? ? Tracing::Utils.next_id : id @parent_id = parent_id || 0 @trace_id = trace_id || Tracing::Utils::TraceId.next_id @status = 0 # stores array of span links @links = links || [] # stores array of span events @span_events = span_events || [] # start_time and end_time track wall clock. In Ruby, wall clock # has less accuracy than monotonic clock, so if possible we look to only use wall clock # to measure duration when a time is supplied by the user, or if monotonic clock # is unsupported. @start_time = nil @end_time = nil # duration_start and duration_end track monotonic clock, and may remain nil in cases where it # is known that we have to use wall clock to measure duration. @duration_start = nil @duration_end = nil # Set tags if provided. () if # Some other SpanOperation-specific behavior @events = events || Events.new @span = nil # Subscribe :on_error event @events.on_error.wrap_default(&on_error) if on_error.is_a?(Proc) # Start the span with start time, if given. start(start_time) if start_time end |
Instance Attribute Details
#end_time ⇒ Object
Span attributes NOTE: In the future, we should drop the me
30 31 32 |
# File 'lib/datadog/tracing/span_operation.rb', line 30 def end_time @end_time end |
#id ⇒ Object (readonly)
Span attributes NOTE: In the future, we should drop the me
30 31 32 |
# File 'lib/datadog/tracing/span_operation.rb', line 30 def id @id end |
#links ⇒ Object
Returns the value of attribute links.
40 41 42 |
# File 'lib/datadog/tracing/span_operation.rb', line 40 def links @links end |
#name ⇒ String
Operation name.
30 31 32 |
# File 'lib/datadog/tracing/span_operation.rb', line 30 def name @name end |
#parent_id ⇒ Object (readonly)
Span attributes NOTE: In the future, we should drop the me
30 31 32 |
# File 'lib/datadog/tracing/span_operation.rb', line 30 def parent_id @parent_id end |
#resource ⇒ String
Span resource.
30 31 32 |
# File 'lib/datadog/tracing/span_operation.rb', line 30 def resource @resource end |
#service ⇒ String
Service name.
30 31 32 |
# File 'lib/datadog/tracing/span_operation.rb', line 30 def service @service end |
#span_events ⇒ Object
Returns the value of attribute span_events.
40 41 42 |
# File 'lib/datadog/tracing/span_operation.rb', line 40 def span_events @span_events end |
#start_time ⇒ Object
Span attributes NOTE: In the future, we should drop the me
30 31 32 |
# File 'lib/datadog/tracing/span_operation.rb', line 30 def start_time @start_time end |
#status ⇒ Object
Returns the value of attribute status.
40 41 42 |
# File 'lib/datadog/tracing/span_operation.rb', line 40 def status @status end |
#trace_id ⇒ Object (readonly)
Span attributes NOTE: In the future, we should drop the me
30 31 32 |
# File 'lib/datadog/tracing/span_operation.rb', line 30 def trace_id @trace_id end |
#type ⇒ String
Span type.
30 31 32 |
# File 'lib/datadog/tracing/span_operation.rb', line 30 def type @type end |
Instance Method Details
#duration ⇒ Object
270 271 272 273 |
# File 'lib/datadog/tracing/span_operation.rb', line 270 def duration return @duration_end - @duration_start if @duration_start && @duration_end return @end_time - @start_time if @start_time && @end_time end |
#finish(end_time = nil) ⇒ Object
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/datadog/tracing/span_operation.rb', line 249 def finish(end_time = nil) # Returned memoized span if already finished return span if finished? # Stop timing stop(end_time) # Build span # Memoize for performance reasons @span = build_span # Trigger after_finish event events.after_finish.publish(span, self) span end |
#finished? ⇒ Boolean
266 267 268 |
# File 'lib/datadog/tracing/span_operation.rb', line 266 def finished? !span.nil? end |
#measure ⇒ Object
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/datadog/tracing/span_operation.rb', line 133 def measure raise ArgumentError, 'Must provide block to measure!' unless block_given? # TODO: Should we just invoke the block and skip tracing instead? raise AlreadyStartedError if started? return_value = nil begin # If span fails to start, don't prevent the operation from # running, to minimize impact on normal application function. begin start 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 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(self) unless e && !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. rescue Exception => e # Stop the span first, so timing is a more accurate. # If the span failed to start, timing may be inaccurate, # but this is not really a serious concern. stop # Trigger the on_error event events.on_error.publish(self, e) # We must finish the span to trigger callbacks, # and build the final span. finish raise e # Use an ensure block here to make sure the span closes. # NOTE: It's not sufficient to use "else": when a function # uses "return", it will skip "else". ensure # Finish the span # NOTE: If an error was raised, this "finish" might be redundant. finish unless finished? end # rubocop:enable Lint/RescueException return_value end |
#pretty_print(q) ⇒ Object
Return a human readable version of the span
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
# File 'lib/datadog/tracing/span_operation.rb', line 309 def pretty_print(q) start_time = (self.start_time.to_f * 1e9).to_i end_time = (self.end_time.to_f * 1e9).to_i q.group 0 do q.breakable q.text "Name: #{@name}\n" q.text "Span ID: #{@id}\n" q.text "Parent ID: #{@parent_id}\n" q.text "Trace ID: #{@trace_id}\n" q.text "Type: #{@type}\n" q.text "Service: #{@service}\n" q.text "Resource: #{@resource}\n" q.text "Error: #{@status}\n" q.text "Start: #{start_time}\n" q.text "End: #{end_time}\n" q.text "Duration: #{duration.to_f if stopped?}\n" q.group(2, 'Tags: [', "]\n") do q.breakable q.seplist .each do |key, value| q.text "#{key} => #{value}" end end q.group(2, 'Metrics: [', ']') do q.breakable q.seplist metrics.each do |key, value| q.text "#{key} => #{value}" end end end end |
#set_error(e) ⇒ Object
275 276 277 278 |
# File 'lib/datadog/tracing/span_operation.rb', line 275 def set_error(e) @status = Metadata::Ext::Errors::STATUS (e) end |
#start(start_time = nil) ⇒ Object
187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/datadog/tracing/span_operation.rb', line 187 def start(start_time = nil) # Span can only be started once return self if started? # Trigger before_start event events.before_start.publish(self) # Start the span @start_time = start_time || Core::Utils::Time.now.utc @duration_start = start_time.nil? ? duration_marker : nil self end |
#started? ⇒ Boolean
Return whether the duration is started or not
230 231 232 |
# File 'lib/datadog/tracing/span_operation.rb', line 230 def started? !@start_time.nil? end |
#stop(stop_time = nil) ⇒ Object
Mark the span stopped at the current time
steep:ignore:start Steep issue fixed in github.com/soutaro/steep/pull/1467
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/datadog/tracing/span_operation.rb', line 205 def stop(stop_time = nil) # A span should not be stopped twice. Note that this is not thread-safe, # stop is called from multiple threads, a given span might be stopped # several times. Again, one should not do this, so this test is more a # fallback to avoid very bad things and protect you in most common cases. return if stopped? now = Core::Utils::Time.now.utc # Provide a default start_time if unset. # Using `now` here causes duration to be 0; this is expected # behavior when start_time is unknown. start(stop_time || now) unless started? @end_time = stop_time || now @duration_end = stop_time.nil? ? duration_marker : nil # Trigger after_stop event events.after_stop.publish(self) self end |
#stopped? ⇒ Boolean
Return whether the duration is stopped or not.
235 236 237 |
# File 'lib/datadog/tracing/span_operation.rb', line 235 def stopped? !@end_time.nil? end |
#to_hash ⇒ Object
Return the hash representation of the current span.
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/datadog/tracing/span_operation.rb', line 286 def to_hash h = { error: @status, id: @id, meta: , metrics: metrics, name: @name, parent_id: @parent_id, resource: @resource, service: @service, trace_id: @trace_id, type: @type } if stopped? h[:start] = start_time_nano h[:duration] = duration_nano end h end |
#to_s ⇒ Object
Return a string representation of the span.
281 282 283 |
# File 'lib/datadog/tracing/span_operation.rb', line 281 def to_s "SpanOperation(name:#{@name},sid:#{@id},tid:#{@trace_id},pid:#{@parent_id})" end |