instana 1.217.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +101 -225
- data/.tekton/.currency/scripts/generate_report.py +194 -22
- data/.tekton/pipeline.yaml +65 -152
- data/.tekton/prepuller-restart-service-account.yaml +31 -0
- data/.tekton/ruby-tracer-prepuller-cronjob.yaml +20 -0
- data/.tekton/ruby-tracer-prepuller.yaml +27 -26
- data/.tekton/task.yaml +31 -27
- data/Gemfile +5 -0
- data/README.md +2 -1
- data/Rakefile +1 -1
- data/examples/otel.rb +98 -0
- data/examples/tracing.rb +1 -0
- data/gemfiles/rails_61.gemfile +1 -0
- data/gemfiles/rails_70.gemfile +1 -0
- data/instana.gemspec +5 -0
- data/lib/instana/base.rb +4 -2
- data/lib/instana/instrumentation/action_cable.rb +8 -4
- data/lib/instana/instrumentation/action_controller.rb +2 -4
- data/lib/instana/instrumentation/action_mailer.rb +1 -1
- data/lib/instana/instrumentation/action_view.rb +4 -4
- data/lib/instana/instrumentation/active_job.rb +26 -13
- data/lib/instana/instrumentation/active_record.rb +1 -1
- data/lib/instana/instrumentation/aws_sdk_dynamodb.rb +1 -1
- data/lib/instana/instrumentation/aws_sdk_lambda.rb +1 -1
- data/lib/instana/instrumentation/aws_sdk_s3.rb +1 -1
- data/lib/instana/instrumentation/aws_sdk_sns.rb +1 -1
- data/lib/instana/instrumentation/aws_sdk_sqs.rb +1 -1
- data/lib/instana/instrumentation/dalli.rb +1 -1
- data/lib/instana/instrumentation/excon.rb +2 -2
- data/lib/instana/instrumentation/graphql.rb +3 -3
- data/lib/instana/instrumentation/grpc.rb +14 -13
- data/lib/instana/instrumentation/mongo.rb +3 -3
- data/lib/instana/instrumentation/net-http.rb +5 -4
- data/lib/instana/instrumentation/rack.rb +36 -4
- data/lib/instana/instrumentation/redis.rb +1 -1
- data/lib/instana/instrumentation/resque.rb +10 -8
- data/lib/instana/instrumentation/rest-client.rb +4 -4
- data/lib/instana/instrumentation/sequel.rb +3 -3
- data/lib/instana/instrumentation/shoryuken.rb +4 -1
- data/lib/instana/instrumentation/sidekiq-client.rb +21 -19
- data/lib/instana/instrumentation/sidekiq-worker.rb +22 -21
- data/lib/instana/instrumented_logger.rb +1 -1
- data/lib/instana/samplers/result.rb +32 -0
- data/lib/instana/samplers/samplers.rb +76 -0
- data/lib/instana/serverless.rb +4 -2
- data/lib/instana/setup.rb +4 -5
- data/lib/instana/trace/export.rb +36 -0
- data/lib/instana/{tracing → trace}/processor.rb +19 -15
- data/lib/instana/trace/span.rb +532 -0
- data/lib/instana/{tracing → trace}/span_context.rb +17 -8
- data/lib/instana/trace/span_kind.rb +51 -0
- data/lib/instana/trace/span_limits.rb +63 -0
- data/lib/instana/{tracer.rb → trace/tracer.rb} +106 -54
- data/lib/instana/trace/tracer_provider.rb +198 -0
- data/lib/instana/trace.rb +74 -0
- data/lib/instana/util.rb +11 -0
- data/lib/instana/version.rb +1 -1
- data/test/frameworks/sinatra_test.rb +2 -1
- data/test/instrumentation/aws_test.rb +7 -7
- data/test/instrumentation/dalli_test.rb +8 -8
- data/test/instrumentation/excon_test.rb +3 -3
- data/test/instrumentation/graphql_test.rb +4 -4
- data/test/instrumentation/grpc_test.rb +8 -8
- data/test/instrumentation/mongo_test.rb +1 -1
- data/test/instrumentation/net_http_test.rb +6 -6
- data/test/instrumentation/rails_action_cable_test.rb +2 -2
- data/test/instrumentation/rails_action_mailer_test.rb +1 -1
- data/test/instrumentation/rails_active_job_test.rb +1 -1
- data/test/instrumentation/rails_active_record_database_missing_test.rb +2 -3
- data/test/instrumentation/rails_active_record_test.rb +8 -7
- data/test/instrumentation/redis_test.rb +7 -7
- data/test/instrumentation/resque_test.rb +5 -5
- data/test/instrumentation/rest_client_test.rb +1 -2
- data/test/instrumentation/sequel_test.rb +12 -6
- data/test/instrumentation/sidekiq-client_test.rb +2 -2
- data/test/instrumentation/sidekiq-worker_test.rb +2 -2
- data/test/{tracing → trace}/custom_test.rb +32 -25
- data/test/{tracing → trace}/id_management_test.rb +0 -2
- data/test/{tracing → trace}/instrumented_logger_test.rb +1 -1
- data/test/{tracing → trace}/processor_test.rb +6 -6
- data/test/{tracing → trace}/span_context_test.rb +3 -3
- data/test/{tracing → trace}/span_test.rb +7 -7
- data/test/{tracing → trace}/tracer_async_test.rb +43 -30
- data/test/trace/tracer_provider_test.rb +148 -0
- data/test/{tracing → trace}/tracer_test.rb +48 -37
- metadata +105 -32
- data/examples/opentracing.rb +0 -35
- data/lib/instana/open_tracing/carrier.rb +0 -7
- data/lib/instana/open_tracing/instana_tracer.rb +0 -99
- data/lib/instana/tracing/span.rb +0 -431
- data/lib/opentracing.rb +0 -32
- data/test/tracing/opentracing_test.rb +0 -382
@@ -0,0 +1,532 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2025
|
2
|
+
|
3
|
+
require 'opentelemetry'
|
4
|
+
require 'instana/trace/span_kind'
|
5
|
+
|
6
|
+
module Instana
|
7
|
+
class Span < OpenTelemetry::Trace::Span
|
8
|
+
include SpanKind
|
9
|
+
|
10
|
+
attr_accessor :parent, :baggage, :is_root, :context
|
11
|
+
|
12
|
+
def initialize(name, parent_ctx = nil, _context = nil, parent_span = nil, _kind = nil, parent_span_id = nil, _span_limits = nil, _span_processors = nil, attributes = nil, _links = nil, start_timestamp = ::Instana::Util.now_in_ms, _resource = nil, _instrumentation_scope = nil) # rubocop:disable Lint/MissingSuper, Metrics/ParameterLists, Layout/LineLength
|
13
|
+
@attributes = {}
|
14
|
+
|
15
|
+
@ended = false
|
16
|
+
if parent_span.is_a?(::Instana::Span)
|
17
|
+
@parent = parent_span
|
18
|
+
end
|
19
|
+
if parent_ctx.is_a?(::Instana::Span)
|
20
|
+
@parent = parent_ctx
|
21
|
+
parent_ctx = parent_ctx.context
|
22
|
+
end
|
23
|
+
|
24
|
+
if parent_ctx.is_a?(::Instana::SpanContext)
|
25
|
+
@is_root = false
|
26
|
+
|
27
|
+
# If we have a parent trace, link to it
|
28
|
+
if parent_ctx.trace_id
|
29
|
+
@attributes[:t] = parent_ctx.trace_id # Trace ID
|
30
|
+
@attributes[:p] = parent_span_id || parent_ctx.span_id # Parent ID
|
31
|
+
else
|
32
|
+
@attributes[:t] = ::Instana::Trace.generate_trace_id
|
33
|
+
end
|
34
|
+
|
35
|
+
@attributes[:s] = ::Instana::Trace.generate_span_id # Span ID
|
36
|
+
|
37
|
+
@baggage = parent_ctx.baggage.dup
|
38
|
+
@level = parent_ctx.level
|
39
|
+
else
|
40
|
+
# No parent specified so we're starting a new Trace - this will be the root span
|
41
|
+
@is_root = true
|
42
|
+
@level = 1
|
43
|
+
|
44
|
+
id = ::Instana::Trace.generate_span_id
|
45
|
+
@attributes[:t] = id # Trace ID
|
46
|
+
@attributes[:s] = id # Span ID
|
47
|
+
end
|
48
|
+
|
49
|
+
@attributes[:data] = {}
|
50
|
+
|
51
|
+
if ENV.key?('INSTANA_SERVICE_NAME')
|
52
|
+
@attributes[:data][:service] = ENV['INSTANA_SERVICE_NAME']
|
53
|
+
end
|
54
|
+
|
55
|
+
# Entity Source
|
56
|
+
@attributes[:f] = ::Instana.agent.source
|
57
|
+
# Start time
|
58
|
+
@attributes[:ts] = if start_timestamp.is_a?(Time)
|
59
|
+
::Instana::Util.time_to_ms(start_timestamp)
|
60
|
+
else
|
61
|
+
start_timestamp
|
62
|
+
end
|
63
|
+
|
64
|
+
# Check for custom tracing
|
65
|
+
if REGISTERED_SPANS.include?(name&.to_sym) # Todo remove the safe & operator once all the tests are adapted to new init structure
|
66
|
+
@attributes[:n] = name.to_sym
|
67
|
+
else
|
68
|
+
configure_custom(name)
|
69
|
+
end
|
70
|
+
set_tags(attributes)
|
71
|
+
::Instana.processor.on_start(self)
|
72
|
+
# Attach a backtrace to all exit spans
|
73
|
+
add_stack if ::Instana.config[:collect_backtraces] && exit_span?
|
74
|
+
end
|
75
|
+
|
76
|
+
# Adds a backtrace to this span
|
77
|
+
#
|
78
|
+
# @param limit [Integer] Limit the backtrace to the top <limit> frames
|
79
|
+
#
|
80
|
+
def add_stack(limit: 30, stack: Kernel.caller)
|
81
|
+
cleaner = ::Instana.config[:backtrace_cleaner]
|
82
|
+
stack = cleaner.call(stack) if cleaner
|
83
|
+
|
84
|
+
@attributes[:stack] = stack
|
85
|
+
.map do |call|
|
86
|
+
file, line, *method = call.split(':')
|
87
|
+
|
88
|
+
{
|
89
|
+
c: file,
|
90
|
+
n: line,
|
91
|
+
m: method.join(' ')
|
92
|
+
}
|
93
|
+
end.take(limit > 40 ? 40 : limit)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Log an error into the span
|
97
|
+
#
|
98
|
+
# @param e [Exception] The exception to be logged
|
99
|
+
#
|
100
|
+
def record_exception(error)
|
101
|
+
@attributes[:error] = true
|
102
|
+
|
103
|
+
@attributes[:ec] = if @attributes.key?(:ec)
|
104
|
+
@attributes[:ec] + 1
|
105
|
+
else
|
106
|
+
1
|
107
|
+
end
|
108
|
+
|
109
|
+
# If a valid exception has been passed in, log the information about it
|
110
|
+
# In case of just logging an error for things such as HTTP client 5xx
|
111
|
+
# responses, an exception/backtrace may not exist.
|
112
|
+
if error
|
113
|
+
if error.backtrace.is_a?(Array)
|
114
|
+
add_stack(stack: error.backtrace)
|
115
|
+
end
|
116
|
+
|
117
|
+
if HTTP_SPANS.include?(@attributes[:n])
|
118
|
+
set_tags(:http => { :error => "#{error.class}: #{error.message}" })
|
119
|
+
elsif @attributes[:n] == :activerecord
|
120
|
+
@attributes[:data][:activerecord][:error] = error.message
|
121
|
+
else
|
122
|
+
log(:error, Time.now, message: error.message, parameters: error.class.to_s)
|
123
|
+
end
|
124
|
+
error.instance_variable_set(:@instana_logged, true)
|
125
|
+
end
|
126
|
+
self
|
127
|
+
end
|
128
|
+
|
129
|
+
# Configure this span to be a custom span per the
|
130
|
+
# SDK generic span type.
|
131
|
+
#
|
132
|
+
# Default to an intermediate kind span. Can be overridden by
|
133
|
+
# setting a span.kind tag.
|
134
|
+
#
|
135
|
+
# @param name [String] name of the span
|
136
|
+
# @param kvs [Hash] list of key values to be reported in the span
|
137
|
+
#
|
138
|
+
def configure_custom(name)
|
139
|
+
@attributes[:n] = :sdk
|
140
|
+
@attributes[:data] = { :sdk => { :name => name&.to_sym } } # Todo remove safe operator once other tests adapt to new init structure
|
141
|
+
@attributes[:data][:sdk][:custom] = { :tags => {}, :logs => {} }
|
142
|
+
|
143
|
+
if @is_root
|
144
|
+
# For custom root spans (via SDK or opentracing), default to entry type
|
145
|
+
@attributes[:k] = 1
|
146
|
+
@attributes[:data][:sdk][:type] = :entry
|
147
|
+
else
|
148
|
+
@attributes[:k] = 3
|
149
|
+
@attributes[:data][:sdk][:type] = :intermediate
|
150
|
+
end
|
151
|
+
self
|
152
|
+
end
|
153
|
+
|
154
|
+
# Closes out the span. This difference between this and
|
155
|
+
# the finish method tells us how the tracing is being
|
156
|
+
# performed (with OpenTracing or Instana default)
|
157
|
+
#
|
158
|
+
# @param end_time [Time] custom end time, if not now
|
159
|
+
# @return [Span]
|
160
|
+
#
|
161
|
+
def close(end_time = ::Instana::Util.now_in_ms)
|
162
|
+
if end_time.is_a?(Time)
|
163
|
+
end_time = ::Instana::Util.time_to_ms(end_time)
|
164
|
+
end
|
165
|
+
|
166
|
+
@attributes[:d] = end_time - @attributes[:ts]
|
167
|
+
@ended = true
|
168
|
+
# Add this span to the queue for reporting
|
169
|
+
::Instana.processor.on_finish(self)
|
170
|
+
|
171
|
+
self
|
172
|
+
end
|
173
|
+
|
174
|
+
#############################################################
|
175
|
+
# Accessors
|
176
|
+
#############################################################
|
177
|
+
|
178
|
+
# Retrieve the context of this span.
|
179
|
+
#
|
180
|
+
# @return [Instana::SpanContext]
|
181
|
+
#
|
182
|
+
def context # rubocop:disable Lint/DuplicateMethods
|
183
|
+
@context ||= ::Instana::SpanContext.new(trace_id: @attributes[:t], span_id: @attributes[:s], level: @level, baggage: @baggage)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Retrieve the ID for this span
|
187
|
+
#
|
188
|
+
# @return [Integer] the span ID
|
189
|
+
def id
|
190
|
+
@attributes[:s]
|
191
|
+
end
|
192
|
+
|
193
|
+
# Retrieve the Trace ID for this span
|
194
|
+
#
|
195
|
+
# @return [Integer] the Trace ID
|
196
|
+
def trace_id
|
197
|
+
@attributes[:t]
|
198
|
+
end
|
199
|
+
|
200
|
+
# Retrieve the parent ID of this span
|
201
|
+
#
|
202
|
+
# @return [Integer] parent span ID
|
203
|
+
def parent_id
|
204
|
+
@attributes[:p]
|
205
|
+
end
|
206
|
+
|
207
|
+
# Set the parent ID of this span
|
208
|
+
#
|
209
|
+
# @return [Integer] parent span ID
|
210
|
+
def parent_id=(id)
|
211
|
+
@attributes[:p] = id
|
212
|
+
end
|
213
|
+
|
214
|
+
# Get the name (operation) of this Span
|
215
|
+
#
|
216
|
+
# @return [String] or [Symbol] representing the span name
|
217
|
+
def name
|
218
|
+
if custom?
|
219
|
+
@attributes[:data][:sdk][:name]
|
220
|
+
else
|
221
|
+
@attributes[:n]
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# Set the name (operation) for this Span
|
226
|
+
#
|
227
|
+
# @params name [String] or [Symbol]
|
228
|
+
#
|
229
|
+
def name=(name)
|
230
|
+
if custom?
|
231
|
+
@attributes[:data][:sdk][:name] = name
|
232
|
+
else
|
233
|
+
@attributes[:n] = name
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# Get the duration value for this Span
|
238
|
+
#
|
239
|
+
# @return [Integer] the duration in milliseconds
|
240
|
+
def duration
|
241
|
+
@attributes[:d]
|
242
|
+
end
|
243
|
+
|
244
|
+
# Hash accessor to the internal @attributes hash
|
245
|
+
#
|
246
|
+
def [](key)
|
247
|
+
@attributes[key.to_sym]
|
248
|
+
end
|
249
|
+
|
250
|
+
# Hash setter to the internal @attributes hash
|
251
|
+
#
|
252
|
+
def []=(key, value)
|
253
|
+
@attributes[key.to_sym] = value
|
254
|
+
end
|
255
|
+
|
256
|
+
# Hash key query to the internal @attributes hash
|
257
|
+
#
|
258
|
+
def key?(key)
|
259
|
+
@attributes.key?(key.to_sym)
|
260
|
+
end
|
261
|
+
|
262
|
+
# Get the raw @attributes hash that summarizes this span
|
263
|
+
#
|
264
|
+
def raw
|
265
|
+
@attributes
|
266
|
+
end
|
267
|
+
|
268
|
+
# Indicates whether this span is a custom or registered Span
|
269
|
+
def custom?
|
270
|
+
@attributes[:n] == :sdk
|
271
|
+
end
|
272
|
+
|
273
|
+
def inspect
|
274
|
+
@attributes.inspect
|
275
|
+
end
|
276
|
+
|
277
|
+
# Check to see if the current span indicates an exit from application
|
278
|
+
# code and into an external service
|
279
|
+
def exit_span?
|
280
|
+
EXIT_SPANS.include?(@attributes[:n])
|
281
|
+
end
|
282
|
+
|
283
|
+
#############################################################
|
284
|
+
# OpenTracing Compatibility Methods
|
285
|
+
#############################################################
|
286
|
+
|
287
|
+
# Set the name of the operation
|
288
|
+
# Spec: OpenTracing API
|
289
|
+
#
|
290
|
+
# @params name [String] or [Symbol]
|
291
|
+
#
|
292
|
+
def operation_name=(name)
|
293
|
+
@attributes[:n] = name
|
294
|
+
end
|
295
|
+
|
296
|
+
# Set a tag value on this span
|
297
|
+
# Spec: OpenTracing API
|
298
|
+
#
|
299
|
+
# @param key [String] the key of the tag
|
300
|
+
# @param value [String, Numeric, Boolean] the value of the tag. If it's not
|
301
|
+
# a String, Numeric, or Boolean it will be encoded with to_s
|
302
|
+
#
|
303
|
+
def set_tag(key, value)
|
304
|
+
unless [Symbol, String].include?(key.class)
|
305
|
+
key = key.to_s
|
306
|
+
end
|
307
|
+
|
308
|
+
# If <value> is not a Symbol, String, Array, Hash or Numeric - convert to string
|
309
|
+
if ![Symbol, String, Array, TrueClass, FalseClass, Hash].include?(value.class) && !value.is_a?(Numeric)
|
310
|
+
value = value.to_s
|
311
|
+
end
|
312
|
+
|
313
|
+
if custom?
|
314
|
+
@attributes[:data][:sdk][:custom] ||= {}
|
315
|
+
@attributes[:data][:sdk][:custom][:tags] ||= {}
|
316
|
+
@attributes[:data][:sdk][:custom][:tags][key] = value
|
317
|
+
|
318
|
+
if key.to_sym == :'span.kind'
|
319
|
+
case value.to_sym
|
320
|
+
when ENTRY, SERVER, CONSUMER
|
321
|
+
@attributes[:data][:sdk][:type] = ENTRY
|
322
|
+
@attributes[:k] = 1
|
323
|
+
when EXIT, CLIENT, PRODUCER
|
324
|
+
@attributes[:data][:sdk][:type] = EXIT
|
325
|
+
@attributes[:k] = 2
|
326
|
+
else
|
327
|
+
@attributes[:data][:sdk][:type] = INTERMEDIATE
|
328
|
+
@attributes[:k] = 3
|
329
|
+
end
|
330
|
+
end
|
331
|
+
elsif value.is_a?(Hash) && @attributes[:data][key].is_a?(Hash)
|
332
|
+
@attributes[:data][key].merge!(value)
|
333
|
+
else
|
334
|
+
@attributes[:data][key] = value
|
335
|
+
end
|
336
|
+
self
|
337
|
+
end
|
338
|
+
|
339
|
+
# Helper method to add multiple tags to this span
|
340
|
+
#
|
341
|
+
# @params tags [Hash]
|
342
|
+
# @return [Span]
|
343
|
+
#
|
344
|
+
def set_tags(tags) # rubocop:disable Naming
|
345
|
+
return unless tags.is_a?(Hash)
|
346
|
+
|
347
|
+
tags.each do |k, v|
|
348
|
+
set_tag(k, v)
|
349
|
+
end
|
350
|
+
self
|
351
|
+
end
|
352
|
+
|
353
|
+
# Set a baggage item on the span
|
354
|
+
# Spec: OpenTracing API
|
355
|
+
#
|
356
|
+
# @param key [String] the key of the baggage item
|
357
|
+
# @param value [String] the value of the baggage item
|
358
|
+
# Todo Evalute if baggage is used anywhere in instana
|
359
|
+
def set_baggage_item(key, value)
|
360
|
+
@baggage ||= {}
|
361
|
+
@baggage[key] = value
|
362
|
+
|
363
|
+
# Init/Update the SpanContext item
|
364
|
+
if @context
|
365
|
+
@context.baggage = @baggage
|
366
|
+
else
|
367
|
+
@context ||= ::Instana::SpanContext.new(trace_id: @attributes[:t], span_id: @attributes[:s], level: @level, baggage: @baggage)
|
368
|
+
end
|
369
|
+
self
|
370
|
+
end
|
371
|
+
|
372
|
+
# Get a baggage item
|
373
|
+
# Spec: OpenTracing API
|
374
|
+
#
|
375
|
+
# @param key [String] the key of the baggage item
|
376
|
+
# @return Value of the baggage item
|
377
|
+
#
|
378
|
+
def get_baggage_item(key)
|
379
|
+
@baggage[key]
|
380
|
+
end
|
381
|
+
|
382
|
+
# Retrieve the hash of tags for this span
|
383
|
+
#
|
384
|
+
def tags(key = nil)
|
385
|
+
tags = if custom?
|
386
|
+
@attributes[:data][:sdk][:custom][:tags]
|
387
|
+
else
|
388
|
+
@attributes[:data]
|
389
|
+
end
|
390
|
+
key ? tags[key] : tags
|
391
|
+
end
|
392
|
+
|
393
|
+
# Add a log entry to this span
|
394
|
+
# Spec: OpenTracing API
|
395
|
+
#
|
396
|
+
# @param event [String] event name for the log
|
397
|
+
# @param timestamp [Time] time of the log
|
398
|
+
# @param fields [Hash] Additional information to log
|
399
|
+
#
|
400
|
+
def log(event = nil, timestamp = Time.now, **fields)
|
401
|
+
ts = ::Instana::Util.time_to_ms(timestamp).to_s
|
402
|
+
if custom?
|
403
|
+
@attributes[:data][:sdk][:custom][:logs][ts] = fields
|
404
|
+
@attributes[:data][:sdk][:custom][:logs][ts][:event] = event
|
405
|
+
else
|
406
|
+
set_tags(:log => fields)
|
407
|
+
end
|
408
|
+
rescue StandardError => e
|
409
|
+
Instana.logger.debug { "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" }
|
410
|
+
end
|
411
|
+
|
412
|
+
# Finish the {Span}
|
413
|
+
# Spec: OpenTracing API
|
414
|
+
#
|
415
|
+
# @param end_time [Time] custom end time, if not now
|
416
|
+
#
|
417
|
+
def finish(end_time = ::Instana::Util.now_in_ms)
|
418
|
+
close(end_time)
|
419
|
+
::Instana.tracer.current_span = ::Instana.tracer.current_span&.parent || nil
|
420
|
+
self
|
421
|
+
end
|
422
|
+
|
423
|
+
# Return the flag whether this span is recording events
|
424
|
+
#
|
425
|
+
# @return [Boolean] true if this Span is active and recording information
|
426
|
+
# like events with the #add_event operation and attributes using
|
427
|
+
# #set_attribute.
|
428
|
+
def recording?
|
429
|
+
!@ended
|
430
|
+
end
|
431
|
+
|
432
|
+
# Set attribute
|
433
|
+
#
|
434
|
+
# Note that the OpenTelemetry project
|
435
|
+
# {https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
|
436
|
+
# documents} certain "standard attributes" that have prescribed semantic
|
437
|
+
# meanings.
|
438
|
+
#
|
439
|
+
# @param [String] key
|
440
|
+
# @param [String, Boolean, Numeric, Array<String, Numeric, Boolean>] value
|
441
|
+
# Values must be non-nil and (array of) string, boolean or numeric type.
|
442
|
+
# Array values must not contain nil elements and all elements must be of
|
443
|
+
# the same basic type (string, numeric, boolean).
|
444
|
+
#
|
445
|
+
# @return [self] returns itself
|
446
|
+
def set_attribute(key, value)
|
447
|
+
@attributes ||= {}
|
448
|
+
@attributes[key] = value
|
449
|
+
self
|
450
|
+
end
|
451
|
+
# alias []= set_attribute
|
452
|
+
|
453
|
+
# Add attributes
|
454
|
+
#
|
455
|
+
# Note that the OpenTelemetry project
|
456
|
+
# {https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
|
457
|
+
# documents} certain "standard attributes" that have prescribed semantic
|
458
|
+
# meanings.
|
459
|
+
#
|
460
|
+
# @param [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}] attributes
|
461
|
+
# Values must be non-nil and (array of) string, boolean or numeric type.
|
462
|
+
# Array values must not contain nil elements and all elements must be of
|
463
|
+
# the same basic type (string, numeric, boolean).
|
464
|
+
#
|
465
|
+
# @return [self] returns itself
|
466
|
+
def add_attributes(attributes)
|
467
|
+
@attributes ||= {}
|
468
|
+
@attributes.merge!(attributes)
|
469
|
+
self
|
470
|
+
end
|
471
|
+
|
472
|
+
# Add a link to a {Span}.
|
473
|
+
#
|
474
|
+
# Adding links at span creation using the `links` option is preferred
|
475
|
+
# to calling add_link later, because head sampling decisions can only
|
476
|
+
# consider information present during span creation.
|
477
|
+
#
|
478
|
+
# Example:
|
479
|
+
#
|
480
|
+
# span.add_link(OpenTelemetry::Trace::Link.new(span_to_link_from.context))
|
481
|
+
#
|
482
|
+
# Note that the OpenTelemetry project
|
483
|
+
# {https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
|
484
|
+
# documents} certain "standard attributes" that have prescribed semantic
|
485
|
+
# meanings.
|
486
|
+
#
|
487
|
+
# @param [OpenTelemetry::Trace::Link] the link object to add on the {Span}.
|
488
|
+
#
|
489
|
+
# @return [self] returns itself
|
490
|
+
# Todo add link logic later
|
491
|
+
def add_link(_link)
|
492
|
+
self
|
493
|
+
end
|
494
|
+
|
495
|
+
# Add an event to a {Span}.
|
496
|
+
#
|
497
|
+
# Example:
|
498
|
+
#
|
499
|
+
# span.add_event('event', attributes: {'eager' => true})
|
500
|
+
#
|
501
|
+
# Note that the OpenTelemetry project
|
502
|
+
# {https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
|
503
|
+
# documents} certain "standard event names and keys" which have
|
504
|
+
# prescribed semantic meanings.
|
505
|
+
#
|
506
|
+
# @param [String] name Name of the event.
|
507
|
+
# @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
|
508
|
+
# attributes One or more key:value pairs, where the keys must be
|
509
|
+
# strings and the values may be (array of) string, boolean or numeric
|
510
|
+
# type.
|
511
|
+
# @param [optional Time] timestamp Optional timestamp for the event.
|
512
|
+
#
|
513
|
+
# @return [self] returns itself
|
514
|
+
# Todo Add the vent logic later
|
515
|
+
def add_event(_name, attributes: nil, timestamp: nil) # rubocop:disable Lint/UnusedMethodArgument
|
516
|
+
self
|
517
|
+
end
|
518
|
+
|
519
|
+
# Sets the Status to the Span
|
520
|
+
#
|
521
|
+
# If used, this will override the default Span status. Default status is unset.
|
522
|
+
#
|
523
|
+
# Only the value of the last call will be recorded, and implementations
|
524
|
+
# are free to ignore previous calls.
|
525
|
+
#
|
526
|
+
# @param [Status] status The new status, which overrides the default Span
|
527
|
+
# status, which is OK.
|
528
|
+
#
|
529
|
+
# @return [void]
|
530
|
+
def status=(status); end
|
531
|
+
end
|
532
|
+
end
|
@@ -2,10 +2,8 @@
|
|
2
2
|
# (c) Copyright Instana Inc. 2017
|
3
3
|
|
4
4
|
module Instana
|
5
|
-
class SpanContext
|
6
|
-
attr_accessor :trace_id
|
7
|
-
attr_accessor :span_id
|
8
|
-
attr_accessor :baggage
|
5
|
+
class SpanContext < OpenTelemetry::Trace::SpanContext
|
6
|
+
attr_accessor :trace_id, :span_id, :baggage
|
9
7
|
attr_reader :level
|
10
8
|
|
11
9
|
# Create a new SpanContext
|
@@ -15,9 +13,20 @@ module Instana
|
|
15
13
|
# @param level [Integer] default 1
|
16
14
|
# @param baggage [Hash] baggage applied to this trace
|
17
15
|
#
|
18
|
-
def initialize(
|
19
|
-
|
20
|
-
|
16
|
+
def initialize( # rubocop:disable Lint/MissingSuper, Metrics/ParameterLists
|
17
|
+
trace_id: Trace.generate_trace_id,
|
18
|
+
span_id: Trace.generate_span_id,
|
19
|
+
trace_flags: OpenTelemetry::Trace::TraceFlags::DEFAULT, # Todo - implement traceflags
|
20
|
+
tracestate: OpenTelemetry::Trace::Tracestate::DEFAULT, # Todo - implement tracestates
|
21
|
+
remote: false,
|
22
|
+
level: 1,
|
23
|
+
baggage: {}
|
24
|
+
)
|
25
|
+
@trace_id = trace_id
|
26
|
+
@span_id = span_id
|
27
|
+
@trace_flags = trace_flags
|
28
|
+
@tracestate = tracestate
|
29
|
+
@remote = remote
|
21
30
|
@level = Integer(level || 1)
|
22
31
|
@baggage = baggage || {}
|
23
32
|
end
|
@@ -55,7 +64,7 @@ module Instana
|
|
55
64
|
end
|
56
65
|
|
57
66
|
def valid?
|
58
|
-
@baggage && @trace_id && !@trace_id.
|
67
|
+
@baggage && @trace_id && !@trace_id.empty?
|
59
68
|
end
|
60
69
|
|
61
70
|
def active?
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2025
|
2
|
+
|
3
|
+
module Instana
|
4
|
+
# Type of span. Can be used to specify additional relationships between spans in addition to a
|
5
|
+
# parent/child relationship. For API ergonomics, use of the symbols rather than the constants
|
6
|
+
# may be preferred. For example:
|
7
|
+
#
|
8
|
+
# span = tracer.on_start('op', kind: :client)
|
9
|
+
module SpanKind
|
10
|
+
# Instana specific spans
|
11
|
+
REGISTERED_SPANS = [:actioncontroller, :actionview, :activerecord, :excon,
|
12
|
+
:memcache, :'net-http', :rack, :render, :'rpc-client',
|
13
|
+
:'rpc-server', :'sidekiq-client', :'sidekiq-worker',
|
14
|
+
:redis, :'resque-client', :'resque-worker', :'graphql.server', :dynamodb, :s3, :sns, :sqs, :'aws.lambda.entry', :activejob, :log, :"mail.actionmailer",
|
15
|
+
:"aws.lambda.invoke", :mongo, :sequel].freeze
|
16
|
+
ENTRY_SPANS = [:rack, :'resque-worker', :'rpc-server', :'sidekiq-worker', :'graphql.server', :sqs,
|
17
|
+
:'aws.lambda.entry'].freeze
|
18
|
+
EXIT_SPANS = [:activerecord, :excon, :'net-http', :'resque-client',
|
19
|
+
:'rpc-client', :'sidekiq-client', :redis, :dynamodb, :s3, :sns, :sqs, :log, :"mail.actionmailer",
|
20
|
+
:"aws.lambda.invoke", :mongo, :sequel].freeze
|
21
|
+
HTTP_SPANS = [:rack, :excon, :'net-http'].freeze
|
22
|
+
|
23
|
+
# Default value. Indicates that the span is used internally.
|
24
|
+
INTERNAL = :internal
|
25
|
+
|
26
|
+
# Indicates that the span covers server-side handling of an RPC or other remote request.
|
27
|
+
SERVER = :server
|
28
|
+
|
29
|
+
# Indicates that the span covers the client-side wrapper around an RPC or other remote request.
|
30
|
+
CLIENT = :client
|
31
|
+
|
32
|
+
# Indicates that the span describes producer sending a message to a broker. Unlike client and
|
33
|
+
# server, there is no direct critical path latency relationship between producer and consumer
|
34
|
+
# spans.
|
35
|
+
PRODUCER = :producer
|
36
|
+
|
37
|
+
# Indicates that the span describes consumer receiving a message from a broker. Unlike client
|
38
|
+
# and server, there is no direct critical path latency relationship between producer and
|
39
|
+
# consumer spans.
|
40
|
+
CONSUMER = :consumer
|
41
|
+
|
42
|
+
# Indicates an entry span. Equivalant to Server or Consumer
|
43
|
+
ENTRY = :entry
|
44
|
+
|
45
|
+
# Indicates an exit span. Equivalant to Client or Producer
|
46
|
+
EXIT = :exit
|
47
|
+
|
48
|
+
# Indicates an intermediate span. This used when sdk is used to produce intermediate traces
|
49
|
+
INTERMEDIATE = :intermediate
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2025
|
2
|
+
|
3
|
+
require 'opentelemetry-common'
|
4
|
+
|
5
|
+
module Instana
|
6
|
+
module Trace
|
7
|
+
# Class that holds global trace parameters.
|
8
|
+
class SpanLimits
|
9
|
+
# The global default max number of attributes per {Span}.
|
10
|
+
attr_reader :attribute_count_limit
|
11
|
+
|
12
|
+
# The global default max length of attribute value per {Span}.
|
13
|
+
attr_reader :attribute_length_limit
|
14
|
+
|
15
|
+
# The global default max number of {OpenTelemetry::SDK::Trace::Event}s per {Span}.
|
16
|
+
attr_reader :event_count_limit
|
17
|
+
|
18
|
+
# The global default max number of {OpenTelemetry::Trace::Link} entries per {Span}.
|
19
|
+
attr_reader :link_count_limit
|
20
|
+
|
21
|
+
# The global default max number of attributes per {OpenTelemetry::SDK::Trace::Event}.
|
22
|
+
attr_reader :event_attribute_count_limit
|
23
|
+
|
24
|
+
# The global default max length of attribute value per {OpenTelemetry::SDK::Trace::Event}.
|
25
|
+
attr_reader :event_attribute_length_limit
|
26
|
+
|
27
|
+
# The global default max number of attributes per {OpenTelemetry::Trace::Link}.
|
28
|
+
attr_reader :link_attribute_count_limit
|
29
|
+
|
30
|
+
# Returns a {SpanLimits} with the desired values.
|
31
|
+
#
|
32
|
+
# @return [SpanLimits] with the desired values.
|
33
|
+
# @raise [ArgumentError] if any of the max numbers are not positive.
|
34
|
+
def initialize(attribute_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT', 'OTEL_ATTRIBUTE_COUNT_LIMIT', default: 128)), # rubocop:disable Metrics/ParameterLists
|
35
|
+
attribute_length_limit: OpenTelemetry::Common::Utilities.config_opt('OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT', 'OTEL_RUBY_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT',
|
36
|
+
'OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT'),
|
37
|
+
event_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_SPAN_EVENT_COUNT_LIMIT', default: 128)),
|
38
|
+
link_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_SPAN_LINK_COUNT_LIMIT', default: 128)),
|
39
|
+
event_attribute_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT', default: 128)),
|
40
|
+
event_attribute_length_limit: OpenTelemetry::Common::Utilities.config_opt('OTEL_EVENT_ATTRIBUTE_VALUE_LENGTH_LIMIT', 'OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT'),
|
41
|
+
link_attribute_count_limit: Integer(OpenTelemetry::Common::Utilities.config_opt('OTEL_LINK_ATTRIBUTE_COUNT_LIMIT', default: 128)))
|
42
|
+
raise ArgumentError, 'attribute_count_limit must be positive' unless attribute_count_limit.positive?
|
43
|
+
raise ArgumentError, 'attribute_length_limit must not be less than 32' unless attribute_length_limit.nil? || Integer(attribute_length_limit) >= 32
|
44
|
+
raise ArgumentError, 'event_count_limit must be positive' unless event_count_limit.positive?
|
45
|
+
raise ArgumentError, 'link_count_limit must be positive' unless link_count_limit.positive?
|
46
|
+
raise ArgumentError, 'event_attribute_count_limit must be positive' unless event_attribute_count_limit.positive?
|
47
|
+
raise ArgumentError, 'event_attribute_length_limit must not be less than 32' unless event_attribute_length_limit.nil? || Integer(event_attribute_length_limit) >= 32
|
48
|
+
raise ArgumentError, 'link_attribute_count_limit must be positive' unless link_attribute_count_limit.positive?
|
49
|
+
|
50
|
+
@attribute_count_limit = attribute_count_limit
|
51
|
+
@attribute_length_limit = attribute_length_limit.nil? ? nil : Integer(attribute_length_limit)
|
52
|
+
@event_count_limit = event_count_limit
|
53
|
+
@link_count_limit = link_count_limit
|
54
|
+
@event_attribute_count_limit = event_attribute_count_limit
|
55
|
+
@event_attribute_length_limit = event_attribute_length_limit.nil? ? nil : Integer(event_attribute_length_limit)
|
56
|
+
@link_attribute_count_limit = link_attribute_count_limit
|
57
|
+
end
|
58
|
+
|
59
|
+
# The default {SpanLimits}.
|
60
|
+
DEFAULT = new
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|