instana 1.217.1 → 2.1.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/README.md +2 -1
- 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 +20 -5
- 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 +5 -5
- data/lib/instana/span_filtering/condition.rb +134 -0
- data/lib/instana/span_filtering/configuration.rb +262 -0
- data/lib/instana/span_filtering/filter_rule.rb +31 -0
- data/lib/instana/span_filtering.rb +62 -0
- data/lib/instana/trace/export.rb +36 -0
- data/lib/instana/{tracing → trace}/processor.rb +19 -15
- data/lib/instana/trace/span.rb +534 -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
- metadata +89 -267
- data/.circleci/config.yml +0 -485
- data/.codeclimate.yml +0 -23
- data/.editorconfig +0 -10
- data/.fasterer.yml +0 -23
- data/.github/ISSUE_TEMPLATE/bug.yml +0 -39
- data/.github/ISSUE_TEMPLATE/config.yml +0 -8
- data/.github/workflows/pr_commits_signed_off.yml +0 -16
- data/.github/workflows/release-notification-on-slack.yml +0 -34
- data/.gitignore +0 -19
- data/.rubocop.yml +0 -34
- data/.rubocop_todo.yml +0 -1140
- data/.tekton/.currency/docs/report.md +0 -20
- data/.tekton/.currency/resources/requirements.txt +0 -4
- data/.tekton/.currency/resources/table.json +0 -100
- data/.tekton/.currency/scripts/generate_report.py +0 -136
- data/.tekton/README.md +0 -278
- data/.tekton/github-interceptor-secret.yaml +0 -8
- data/.tekton/github-pr-eventlistener.yaml +0 -104
- data/.tekton/github-pr-pipeline.yaml.part +0 -38
- data/.tekton/github-set-status-task.yaml +0 -43
- data/.tekton/github-webhook-ingress.yaml +0 -20
- data/.tekton/pipeline.yaml +0 -571
- data/.tekton/pipelinerun.yaml +0 -21
- data/.tekton/ruby-tracer-prepuller.yaml +0 -87
- data/.tekton/run_unittests.sh +0 -87
- data/.tekton/scheduled-eventlistener.yaml +0 -108
- data/.tekton/task.yaml +0 -449
- data/.tekton/tekton-triggers-eventlistener-serviceaccount.yaml +0 -29
- data/Appraisals +0 -124
- data/CONTRIBUTING.md +0 -86
- data/Gemfile +0 -17
- data/LICENSE +0 -22
- data/MAINTAINERS.md +0 -3
- data/Rakefile +0 -49
- data/bin/announce_release_on_slack.py +0 -103
- data/docker-compose.yml +0 -20
- data/download.sh +0 -85
- data/examples/opentracing.rb +0 -35
- data/examples/tracing.rb +0 -84
- data/extras/license_header.rb +0 -44
- data/gemfiles/.bundle/config +0 -2
- data/gemfiles/aws_30.gemfile +0 -21
- data/gemfiles/aws_60.gemfile +0 -16
- data/gemfiles/cuba_30.gemfile +0 -16
- data/gemfiles/cuba_40.gemfile +0 -13
- data/gemfiles/dalli_20.gemfile +0 -15
- data/gemfiles/dalli_30.gemfile +0 -12
- data/gemfiles/dalli_32.gemfile +0 -12
- data/gemfiles/excon_0100.gemfile +0 -14
- data/gemfiles/excon_021.gemfile +0 -17
- data/gemfiles/excon_079.gemfile +0 -17
- data/gemfiles/excon_100.gemfile +0 -14
- data/gemfiles/graphql_10.gemfile +0 -16
- data/gemfiles/graphql_20.gemfile +0 -15
- data/gemfiles/grpc_10.gemfile +0 -15
- data/gemfiles/mongo_216.gemfile +0 -15
- data/gemfiles/mongo_219.gemfile +0 -12
- data/gemfiles/net_http_01.gemfile +0 -17
- data/gemfiles/rack_16.gemfile +0 -15
- data/gemfiles/rack_20.gemfile +0 -15
- data/gemfiles/rack_30.gemfile +0 -13
- data/gemfiles/rails_42.gemfile +0 -18
- data/gemfiles/rails_50.gemfile +0 -19
- data/gemfiles/rails_52.gemfile +0 -19
- data/gemfiles/rails_60.gemfile +0 -19
- data/gemfiles/rails_61.gemfile +0 -20
- data/gemfiles/rails_70.gemfile +0 -17
- data/gemfiles/rails_71.gemfile +0 -17
- data/gemfiles/rails_80.gemfile +0 -17
- data/gemfiles/redis_40.gemfile +0 -15
- data/gemfiles/redis_50.gemfile +0 -13
- data/gemfiles/redis_51.gemfile +0 -13
- data/gemfiles/resque_122.gemfile +0 -16
- data/gemfiles/resque_1274_3scale.gemfile +0 -17
- data/gemfiles/resque_20.gemfile +0 -16
- data/gemfiles/rest_client_16.gemfile +0 -17
- data/gemfiles/rest_client_20.gemfile +0 -17
- data/gemfiles/roda_20.gemfile +0 -16
- data/gemfiles/roda_30.gemfile +0 -16
- data/gemfiles/rubocop_162.gemfile +0 -6
- data/gemfiles/sequel_56.gemfile +0 -16
- data/gemfiles/sequel_57.gemfile +0 -16
- data/gemfiles/sequel_58.gemfile +0 -16
- data/gemfiles/shoryuken_50.gemfile +0 -16
- data/gemfiles/shoryuken_60.gemfile +0 -13
- data/gemfiles/sidekiq_42.gemfile +0 -15
- data/gemfiles/sidekiq_50.gemfile +0 -15
- data/gemfiles/sidekiq_60.gemfile +0 -12
- data/gemfiles/sidekiq_65.gemfile +0 -12
- data/gemfiles/sidekiq_70.gemfile +0 -12
- data/gemfiles/sinatra_14.gemfile +0 -15
- data/gemfiles/sinatra_22.gemfile +0 -12
- data/gemfiles/sinatra_30.gemfile +0 -12
- data/gemfiles/sinatra_40.gemfile +0 -12
- data/instana.gemspec +0 -48
- 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/log/.keep +0 -0
- data/sonar-project.properties +0 -9
- data/test/activator_test.rb +0 -50
- data/test/backend/agent_test.rb +0 -80
- data/test/backend/gc_snapshot_test.rb +0 -11
- data/test/backend/host_agent_activation_observer_test.rb +0 -73
- data/test/backend/host_agent_lookup_test.rb +0 -78
- data/test/backend/host_agent_reporting_observer_test.rb +0 -276
- data/test/backend/host_agent_test.rb +0 -89
- data/test/backend/process_info_test.rb +0 -83
- data/test/backend/request_client_test.rb +0 -39
- data/test/backend/serverless_agent_test.rb +0 -83
- data/test/benchmarks/bench_id_generation.rb +0 -15
- data/test/benchmarks/bench_opentracing.rb +0 -16
- data/test/config_test.rb +0 -34
- data/test/frameworks/cuba_test.rb +0 -61
- data/test/frameworks/roda_test.rb +0 -60
- data/test/frameworks/sinatra_test.rb +0 -71
- data/test/instana_test.rb +0 -37
- data/test/instrumentation/aws_test.rb +0 -241
- data/test/instrumentation/dalli_test.rb +0 -325
- data/test/instrumentation/excon_test.rb +0 -204
- data/test/instrumentation/graphql_test.rb +0 -289
- data/test/instrumentation/grpc_test.rb +0 -420
- data/test/instrumentation/mongo_test.rb +0 -68
- data/test/instrumentation/net_http_test.rb +0 -220
- data/test/instrumentation/rack_instrumented_request_test.rb +0 -211
- data/test/instrumentation/rack_test.rb +0 -415
- data/test/instrumentation/rails_action_cable_test.rb +0 -135
- data/test/instrumentation/rails_action_controller_test.rb +0 -218
- data/test/instrumentation/rails_action_mailer_test.rb +0 -66
- data/test/instrumentation/rails_action_view_test.rb +0 -154
- data/test/instrumentation/rails_active_job_test.rb +0 -65
- data/test/instrumentation/rails_active_record_database_missing_test.rb +0 -45
- data/test/instrumentation/rails_active_record_test.rb +0 -115
- data/test/instrumentation/redis_test.rb +0 -152
- data/test/instrumentation/resque_test.rb +0 -188
- data/test/instrumentation/rest_client_test.rb +0 -107
- data/test/instrumentation/sequel_test.rb +0 -105
- data/test/instrumentation/shoryuken_test.rb +0 -47
- data/test/instrumentation/sidekiq-client_test.rb +0 -169
- data/test/instrumentation/sidekiq-worker_test.rb +0 -180
- data/test/secrets_test.rb +0 -112
- data/test/serverless_test.rb +0 -369
- data/test/snapshot/deltable_test.rb +0 -17
- data/test/snapshot/docker_container_test.rb +0 -82
- data/test/snapshot/fargate_container_test.rb +0 -82
- data/test/snapshot/fargate_process_test.rb +0 -35
- data/test/snapshot/fargate_task_test.rb +0 -49
- data/test/snapshot/google_cloud_run_instance_test.rb +0 -74
- data/test/snapshot/google_cloud_run_process_test.rb +0 -33
- data/test/snapshot/lambda_function_test.rb +0 -37
- data/test/snapshot/ruby_process_test.rb +0 -32
- data/test/support/apps/active_record/active_record.rb +0 -24
- data/test/support/apps/grpc/boot.rb +0 -23
- data/test/support/apps/grpc/grpc_server.rb +0 -84
- data/test/support/apps/http_endpoint/boot.rb +0 -28
- data/test/support/apps/rails/boot.rb +0 -219
- data/test/support/apps/rails/models/block.rb +0 -21
- data/test/support/apps/rails/models/block6.rb +0 -21
- data/test/support/apps/resque/boot.rb +0 -5
- data/test/support/apps/resque/jobs/resque_error_job.rb +0 -22
- data/test/support/apps/resque/jobs/resque_fast_job.rb +0 -23
- data/test/support/apps/sidekiq/boot.rb +0 -25
- data/test/support/apps/sidekiq/jobs/sidekiq_job_1.rb +0 -9
- data/test/support/apps/sidekiq/jobs/sidekiq_job_2.rb +0 -10
- data/test/support/apps/sidekiq/worker.rb +0 -37
- data/test/support/helpers.rb +0 -85
- data/test/support/mock_timer.rb +0 -20
- data/test/test_helper.rb +0 -69
- data/test/tracing/custom_test.rb +0 -226
- data/test/tracing/id_management_test.rb +0 -80
- data/test/tracing/instrumented_logger_test.rb +0 -39
- data/test/tracing/opentracing_test.rb +0 -382
- data/test/tracing/processor_test.rb +0 -58
- data/test/tracing/span_context_test.rb +0 -22
- data/test/tracing/span_test.rb +0 -179
- data/test/tracing/tracer_async_test.rb +0 -230
- data/test/tracing/tracer_test.rb +0 -352
- data/test/util_test.rb +0 -10
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (c) Copyright IBM Corp. 2025
|
4
|
+
|
5
|
+
require 'instana/span_filtering/configuration'
|
6
|
+
require 'instana/span_filtering/filter_rule'
|
7
|
+
require 'instana/span_filtering/condition'
|
8
|
+
|
9
|
+
module Instana
|
10
|
+
# SpanFiltering module provides functionality to filter spans based on configured rules
|
11
|
+
module SpanFiltering
|
12
|
+
class << self
|
13
|
+
attr_reader :configuration
|
14
|
+
|
15
|
+
# Initialize the span filtering configuration
|
16
|
+
# @return [Configuration] The span filtering configuration
|
17
|
+
def initialize
|
18
|
+
@configuration = Configuration.new
|
19
|
+
end
|
20
|
+
|
21
|
+
# Check if span filtering is deactivated
|
22
|
+
# @return [Boolean] True if span filtering is deactivated
|
23
|
+
def deactivated?
|
24
|
+
@configuration&.deactivated || false
|
25
|
+
end
|
26
|
+
|
27
|
+
# Check if a span should be filtered out
|
28
|
+
# @param span [Hash] The span to check
|
29
|
+
# @return [Hash, nil] A result hash with filtered and suppression keys if filtered, nil if not filtered
|
30
|
+
def filter_span(span)
|
31
|
+
return nil if deactivated?
|
32
|
+
return nil unless @configuration
|
33
|
+
|
34
|
+
# Check include rules first (whitelist)
|
35
|
+
if @configuration.include_rules.any?
|
36
|
+
# If we have include rules, only keep spans that match at least one include rule
|
37
|
+
unless @configuration.include_rules.any? { |rule| rule.matches?(span) }
|
38
|
+
return { filtered: true, suppression: false }
|
39
|
+
end
|
40
|
+
# If it matches an include rule, continue to exclude rules
|
41
|
+
end
|
42
|
+
|
43
|
+
# Check exclude rules (blacklist)
|
44
|
+
@configuration.exclude_rules.each do |rule|
|
45
|
+
if rule.matches?(span)
|
46
|
+
return { filtered: true, suppression: rule.suppression }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
nil # Keep the span if no rules match
|
51
|
+
end
|
52
|
+
|
53
|
+
# Reset the configuration (mainly for testing)
|
54
|
+
def reset
|
55
|
+
@configuration = nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Initialize on module load
|
60
|
+
initialize
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2025
|
2
|
+
|
3
|
+
module Instana
|
4
|
+
module Trace
|
5
|
+
# The Export module contains the built-in exporters and span processors for the OpenTelemetry
|
6
|
+
# reference implementation.
|
7
|
+
module Export
|
8
|
+
# Raised when an export fails; spans are available via :spans accessor
|
9
|
+
class ExportError < OpenTelemetry::Error
|
10
|
+
# Returns the {Span} array for this exception
|
11
|
+
#
|
12
|
+
# @return [Array<OpenTelemetry::SDK::Trace::Span>]
|
13
|
+
attr_reader :spans
|
14
|
+
|
15
|
+
# @param [Array<OpenTelemetry::SDK::Trace::Span>] spans the array of spans that failed to export
|
16
|
+
def initialize(spans)
|
17
|
+
super("Unable to export #{spans.size} spans")
|
18
|
+
@spans = spans
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Result codes for the SpanExporter#export method and the SpanProcessor#force_flush and SpanProcessor#shutdown methods.
|
23
|
+
|
24
|
+
# The operation finished successfully.
|
25
|
+
SUCCESS = 0
|
26
|
+
|
27
|
+
# The operation finished with an error.
|
28
|
+
FAILURE = 1
|
29
|
+
|
30
|
+
# Additional result code for the SpanProcessor#force_flush and SpanProcessor#shutdown methods.
|
31
|
+
|
32
|
+
# The operation timed out.
|
33
|
+
TIMEOUT = 2
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# (c) Copyright IBM Corp. 2021
|
2
2
|
# (c) Copyright Instana Inc. 2016
|
3
3
|
|
4
|
-
require 'thread'
|
5
4
|
require 'forwardable'
|
6
5
|
|
7
6
|
module Instana
|
@@ -25,10 +24,13 @@ module Instana
|
|
25
24
|
@spans_closed = Concurrent::AtomicFixnum.new(0)
|
26
25
|
end
|
27
26
|
|
28
|
-
#
|
29
|
-
#
|
30
|
-
|
31
|
-
|
27
|
+
# Note that we've started a new span. Used to
|
28
|
+
# generate monitoring metrics.
|
29
|
+
def on_start(_)
|
30
|
+
@spans_opened.increment
|
31
|
+
end
|
32
|
+
|
33
|
+
def on_finish(span)
|
32
34
|
# :nocov:
|
33
35
|
if @pid != Process.pid
|
34
36
|
@logger.info("Proces `#{@pid}` has forked into #{Process.pid}. Running post fork hook.")
|
@@ -41,12 +43,6 @@ module Instana
|
|
41
43
|
@queue.push(span)
|
42
44
|
end
|
43
45
|
|
44
|
-
# Note that we've started a new span. Used to
|
45
|
-
# generate monitoring metrics.
|
46
|
-
def start_span(_)
|
47
|
-
@spans_opened.increment
|
48
|
-
end
|
49
|
-
|
50
46
|
# Clears and retrieves metrics associated with span creation and submission
|
51
47
|
def span_metrics
|
52
48
|
response = {
|
@@ -94,9 +90,13 @@ module Instana
|
|
94
90
|
return [] if @queue.empty?
|
95
91
|
|
96
92
|
spans = []
|
97
|
-
until @queue.empty?
|
93
|
+
until @queue.empty?
|
98
94
|
# Non-blocking pop; ignore exception
|
99
|
-
span =
|
95
|
+
span = begin
|
96
|
+
@queue.pop(true)
|
97
|
+
rescue
|
98
|
+
nil
|
99
|
+
end
|
100
100
|
spans << span.raw if span.is_a?(Span) && span.context.level == 1
|
101
101
|
end
|
102
102
|
|
@@ -110,9 +110,13 @@ module Instana
|
|
110
110
|
@spans_opened.value = 0
|
111
111
|
@spans_closed.value = 0
|
112
112
|
|
113
|
-
until @queue.empty?
|
113
|
+
until @queue.empty?
|
114
114
|
# Non-blocking pop; ignore exception
|
115
|
-
|
115
|
+
begin
|
116
|
+
@queue.pop(true)
|
117
|
+
rescue
|
118
|
+
nil
|
119
|
+
end
|
116
120
|
end
|
117
121
|
end
|
118
122
|
end
|
@@ -0,0 +1,534 @@
|
|
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
|
+
result = ::Instana::SpanFiltering.filter_span(self)
|
163
|
+
if end_time.is_a?(Time)
|
164
|
+
end_time = ::Instana::Util.time_to_ms(end_time)
|
165
|
+
end
|
166
|
+
@attributes[:d] = end_time - @attributes[:ts]
|
167
|
+
@ended = true
|
168
|
+
|
169
|
+
if result.nil?
|
170
|
+
# Add this span to the queue for reporting
|
171
|
+
::Instana.processor.on_finish(self)
|
172
|
+
end
|
173
|
+
self
|
174
|
+
end
|
175
|
+
|
176
|
+
#############################################################
|
177
|
+
# Accessors
|
178
|
+
#############################################################
|
179
|
+
|
180
|
+
# Retrieve the context of this span.
|
181
|
+
#
|
182
|
+
# @return [Instana::SpanContext]
|
183
|
+
#
|
184
|
+
def context # rubocop:disable Lint/DuplicateMethods
|
185
|
+
@context ||= ::Instana::SpanContext.new(trace_id: @attributes[:t], span_id: @attributes[:s], level: @level, baggage: @baggage)
|
186
|
+
end
|
187
|
+
|
188
|
+
# Retrieve the ID for this span
|
189
|
+
#
|
190
|
+
# @return [Integer] the span ID
|
191
|
+
def id
|
192
|
+
@attributes[:s]
|
193
|
+
end
|
194
|
+
|
195
|
+
# Retrieve the Trace ID for this span
|
196
|
+
#
|
197
|
+
# @return [Integer] the Trace ID
|
198
|
+
def trace_id
|
199
|
+
@attributes[:t]
|
200
|
+
end
|
201
|
+
|
202
|
+
# Retrieve the parent ID of this span
|
203
|
+
#
|
204
|
+
# @return [Integer] parent span ID
|
205
|
+
def parent_id
|
206
|
+
@attributes[:p]
|
207
|
+
end
|
208
|
+
|
209
|
+
# Set the parent ID of this span
|
210
|
+
#
|
211
|
+
# @return [Integer] parent span ID
|
212
|
+
def parent_id=(id)
|
213
|
+
@attributes[:p] = id
|
214
|
+
end
|
215
|
+
|
216
|
+
# Get the name (operation) of this Span
|
217
|
+
#
|
218
|
+
# @return [String] or [Symbol] representing the span name
|
219
|
+
def name
|
220
|
+
if custom?
|
221
|
+
@attributes[:data][:sdk][:name]
|
222
|
+
else
|
223
|
+
@attributes[:n]
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# Set the name (operation) for this Span
|
228
|
+
#
|
229
|
+
# @params name [String] or [Symbol]
|
230
|
+
#
|
231
|
+
def name=(name)
|
232
|
+
if custom?
|
233
|
+
@attributes[:data][:sdk][:name] = name
|
234
|
+
else
|
235
|
+
@attributes[:n] = name
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# Get the duration value for this Span
|
240
|
+
#
|
241
|
+
# @return [Integer] the duration in milliseconds
|
242
|
+
def duration
|
243
|
+
@attributes[:d]
|
244
|
+
end
|
245
|
+
|
246
|
+
# Hash accessor to the internal @attributes hash
|
247
|
+
#
|
248
|
+
def [](key)
|
249
|
+
@attributes[key.to_sym]
|
250
|
+
end
|
251
|
+
|
252
|
+
# Hash setter to the internal @attributes hash
|
253
|
+
#
|
254
|
+
def []=(key, value)
|
255
|
+
@attributes[key.to_sym] = value
|
256
|
+
end
|
257
|
+
|
258
|
+
# Hash key query to the internal @attributes hash
|
259
|
+
#
|
260
|
+
def key?(key)
|
261
|
+
@attributes.key?(key.to_sym)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Get the raw @attributes hash that summarizes this span
|
265
|
+
#
|
266
|
+
def raw
|
267
|
+
@attributes
|
268
|
+
end
|
269
|
+
|
270
|
+
# Indicates whether this span is a custom or registered Span
|
271
|
+
def custom?
|
272
|
+
@attributes[:n] == :sdk
|
273
|
+
end
|
274
|
+
|
275
|
+
def inspect
|
276
|
+
@attributes.inspect
|
277
|
+
end
|
278
|
+
|
279
|
+
# Check to see if the current span indicates an exit from application
|
280
|
+
# code and into an external service
|
281
|
+
def exit_span?
|
282
|
+
EXIT_SPANS.include?(@attributes[:n])
|
283
|
+
end
|
284
|
+
|
285
|
+
#############################################################
|
286
|
+
# OpenTracing Compatibility Methods
|
287
|
+
#############################################################
|
288
|
+
|
289
|
+
# Set the name of the operation
|
290
|
+
# Spec: OpenTracing API
|
291
|
+
#
|
292
|
+
# @params name [String] or [Symbol]
|
293
|
+
#
|
294
|
+
def operation_name=(name)
|
295
|
+
@attributes[:n] = name
|
296
|
+
end
|
297
|
+
|
298
|
+
# Set a tag value on this span
|
299
|
+
# Spec: OpenTracing API
|
300
|
+
#
|
301
|
+
# @param key [String] the key of the tag
|
302
|
+
# @param value [String, Numeric, Boolean] the value of the tag. If it's not
|
303
|
+
# a String, Numeric, or Boolean it will be encoded with to_s
|
304
|
+
#
|
305
|
+
def set_tag(key, value)
|
306
|
+
unless [Symbol, String].include?(key.class)
|
307
|
+
key = key.to_s
|
308
|
+
end
|
309
|
+
|
310
|
+
# If <value> is not a Symbol, String, Array, Hash or Numeric - convert to string
|
311
|
+
if ![Symbol, String, Array, TrueClass, FalseClass, Hash].include?(value.class) && !value.is_a?(Numeric)
|
312
|
+
value = value.to_s
|
313
|
+
end
|
314
|
+
|
315
|
+
if custom?
|
316
|
+
@attributes[:data][:sdk][:custom] ||= {}
|
317
|
+
@attributes[:data][:sdk][:custom][:tags] ||= {}
|
318
|
+
@attributes[:data][:sdk][:custom][:tags][key] = value
|
319
|
+
|
320
|
+
if key.to_sym == :'span.kind'
|
321
|
+
case value.to_sym
|
322
|
+
when ENTRY, SERVER, CONSUMER
|
323
|
+
@attributes[:data][:sdk][:type] = ENTRY
|
324
|
+
@attributes[:k] = 1
|
325
|
+
when EXIT, CLIENT, PRODUCER
|
326
|
+
@attributes[:data][:sdk][:type] = EXIT
|
327
|
+
@attributes[:k] = 2
|
328
|
+
else
|
329
|
+
@attributes[:data][:sdk][:type] = INTERMEDIATE
|
330
|
+
@attributes[:k] = 3
|
331
|
+
end
|
332
|
+
end
|
333
|
+
elsif value.is_a?(Hash) && @attributes[:data][key].is_a?(Hash)
|
334
|
+
@attributes[:data][key].merge!(value)
|
335
|
+
else
|
336
|
+
@attributes[:data][key] = value
|
337
|
+
end
|
338
|
+
self
|
339
|
+
end
|
340
|
+
|
341
|
+
# Helper method to add multiple tags to this span
|
342
|
+
#
|
343
|
+
# @params tags [Hash]
|
344
|
+
# @return [Span]
|
345
|
+
#
|
346
|
+
def set_tags(tags) # rubocop:disable Naming
|
347
|
+
return unless tags.is_a?(Hash)
|
348
|
+
|
349
|
+
tags.each do |k, v|
|
350
|
+
set_tag(k, v)
|
351
|
+
end
|
352
|
+
self
|
353
|
+
end
|
354
|
+
|
355
|
+
# Set a baggage item on the span
|
356
|
+
# Spec: OpenTracing API
|
357
|
+
#
|
358
|
+
# @param key [String] the key of the baggage item
|
359
|
+
# @param value [String] the value of the baggage item
|
360
|
+
# Todo Evalute if baggage is used anywhere in instana
|
361
|
+
def set_baggage_item(key, value)
|
362
|
+
@baggage ||= {}
|
363
|
+
@baggage[key] = value
|
364
|
+
|
365
|
+
# Init/Update the SpanContext item
|
366
|
+
if @context
|
367
|
+
@context.baggage = @baggage
|
368
|
+
else
|
369
|
+
@context ||= ::Instana::SpanContext.new(trace_id: @attributes[:t], span_id: @attributes[:s], level: @level, baggage: @baggage)
|
370
|
+
end
|
371
|
+
self
|
372
|
+
end
|
373
|
+
|
374
|
+
# Get a baggage item
|
375
|
+
# Spec: OpenTracing API
|
376
|
+
#
|
377
|
+
# @param key [String] the key of the baggage item
|
378
|
+
# @return Value of the baggage item
|
379
|
+
#
|
380
|
+
def get_baggage_item(key)
|
381
|
+
@baggage[key]
|
382
|
+
end
|
383
|
+
|
384
|
+
# Retrieve the hash of tags for this span
|
385
|
+
#
|
386
|
+
def tags(key = nil)
|
387
|
+
tags = if custom?
|
388
|
+
@attributes[:data][:sdk][:custom][:tags]
|
389
|
+
else
|
390
|
+
@attributes[:data]
|
391
|
+
end
|
392
|
+
key ? tags[key] : tags
|
393
|
+
end
|
394
|
+
|
395
|
+
# Add a log entry to this span
|
396
|
+
# Spec: OpenTracing API
|
397
|
+
#
|
398
|
+
# @param event [String] event name for the log
|
399
|
+
# @param timestamp [Time] time of the log
|
400
|
+
# @param fields [Hash] Additional information to log
|
401
|
+
#
|
402
|
+
def log(event = nil, timestamp = Time.now, **fields)
|
403
|
+
ts = ::Instana::Util.time_to_ms(timestamp).to_s
|
404
|
+
if custom?
|
405
|
+
@attributes[:data][:sdk][:custom][:logs][ts] = fields
|
406
|
+
@attributes[:data][:sdk][:custom][:logs][ts][:event] = event
|
407
|
+
else
|
408
|
+
set_tags(:log => fields)
|
409
|
+
end
|
410
|
+
rescue StandardError => e
|
411
|
+
Instana.logger.debug { "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" }
|
412
|
+
end
|
413
|
+
|
414
|
+
# Finish the {Span}
|
415
|
+
# Spec: OpenTracing API
|
416
|
+
#
|
417
|
+
# @param end_time [Time] custom end time, if not now
|
418
|
+
#
|
419
|
+
def finish(end_time = ::Instana::Util.now_in_ms)
|
420
|
+
close(end_time)
|
421
|
+
::Instana.tracer.current_span = ::Instana.tracer.current_span&.parent || nil
|
422
|
+
self
|
423
|
+
end
|
424
|
+
|
425
|
+
# Return the flag whether this span is recording events
|
426
|
+
#
|
427
|
+
# @return [Boolean] true if this Span is active and recording information
|
428
|
+
# like events with the #add_event operation and attributes using
|
429
|
+
# #set_attribute.
|
430
|
+
def recording?
|
431
|
+
!@ended
|
432
|
+
end
|
433
|
+
|
434
|
+
# Set attribute
|
435
|
+
#
|
436
|
+
# Note that the OpenTelemetry project
|
437
|
+
# {https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
|
438
|
+
# documents} certain "standard attributes" that have prescribed semantic
|
439
|
+
# meanings.
|
440
|
+
#
|
441
|
+
# @param [String] key
|
442
|
+
# @param [String, Boolean, Numeric, Array<String, Numeric, Boolean>] value
|
443
|
+
# Values must be non-nil and (array of) string, boolean or numeric type.
|
444
|
+
# Array values must not contain nil elements and all elements must be of
|
445
|
+
# the same basic type (string, numeric, boolean).
|
446
|
+
#
|
447
|
+
# @return [self] returns itself
|
448
|
+
def set_attribute(key, value)
|
449
|
+
@attributes ||= {}
|
450
|
+
@attributes[key] = value
|
451
|
+
self
|
452
|
+
end
|
453
|
+
# alias []= set_attribute
|
454
|
+
|
455
|
+
# Add attributes
|
456
|
+
#
|
457
|
+
# Note that the OpenTelemetry project
|
458
|
+
# {https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
|
459
|
+
# documents} certain "standard attributes" that have prescribed semantic
|
460
|
+
# meanings.
|
461
|
+
#
|
462
|
+
# @param [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}] attributes
|
463
|
+
# Values must be non-nil and (array of) string, boolean or numeric type.
|
464
|
+
# Array values must not contain nil elements and all elements must be of
|
465
|
+
# the same basic type (string, numeric, boolean).
|
466
|
+
#
|
467
|
+
# @return [self] returns itself
|
468
|
+
def add_attributes(attributes)
|
469
|
+
@attributes ||= {}
|
470
|
+
@attributes.merge!(attributes)
|
471
|
+
self
|
472
|
+
end
|
473
|
+
|
474
|
+
# Add a link to a {Span}.
|
475
|
+
#
|
476
|
+
# Adding links at span creation using the `links` option is preferred
|
477
|
+
# to calling add_link later, because head sampling decisions can only
|
478
|
+
# consider information present during span creation.
|
479
|
+
#
|
480
|
+
# Example:
|
481
|
+
#
|
482
|
+
# span.add_link(OpenTelemetry::Trace::Link.new(span_to_link_from.context))
|
483
|
+
#
|
484
|
+
# Note that the OpenTelemetry project
|
485
|
+
# {https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
|
486
|
+
# documents} certain "standard attributes" that have prescribed semantic
|
487
|
+
# meanings.
|
488
|
+
#
|
489
|
+
# @param [OpenTelemetry::Trace::Link] the link object to add on the {Span}.
|
490
|
+
#
|
491
|
+
# @return [self] returns itself
|
492
|
+
# Todo add link logic later
|
493
|
+
def add_link(_link)
|
494
|
+
self
|
495
|
+
end
|
496
|
+
|
497
|
+
# Add an event to a {Span}.
|
498
|
+
#
|
499
|
+
# Example:
|
500
|
+
#
|
501
|
+
# span.add_event('event', attributes: {'eager' => true})
|
502
|
+
#
|
503
|
+
# Note that the OpenTelemetry project
|
504
|
+
# {https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
|
505
|
+
# documents} certain "standard event names and keys" which have
|
506
|
+
# prescribed semantic meanings.
|
507
|
+
#
|
508
|
+
# @param [String] name Name of the event.
|
509
|
+
# @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
|
510
|
+
# attributes One or more key:value pairs, where the keys must be
|
511
|
+
# strings and the values may be (array of) string, boolean or numeric
|
512
|
+
# type.
|
513
|
+
# @param [optional Time] timestamp Optional timestamp for the event.
|
514
|
+
#
|
515
|
+
# @return [self] returns itself
|
516
|
+
# Todo Add the vent logic later
|
517
|
+
def add_event(_name, attributes: nil, timestamp: nil) # rubocop:disable Lint/UnusedMethodArgument
|
518
|
+
self
|
519
|
+
end
|
520
|
+
|
521
|
+
# Sets the Status to the Span
|
522
|
+
#
|
523
|
+
# If used, this will override the default Span status. Default status is unset.
|
524
|
+
#
|
525
|
+
# Only the value of the last call will be recorded, and implementations
|
526
|
+
# are free to ignore previous calls.
|
527
|
+
#
|
528
|
+
# @param [Status] status The new status, which overrides the default Span
|
529
|
+
# status, which is OK.
|
530
|
+
#
|
531
|
+
# @return [void]
|
532
|
+
def status=(status); end
|
533
|
+
end
|
534
|
+
end
|