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
@@ -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
|
@@ -1,14 +1,14 @@
|
|
1
|
-
# (c) Copyright IBM Corp.
|
2
|
-
# (c) Copyright Instana Inc. 2016
|
1
|
+
# (c) Copyright IBM Corp. 2025
|
3
2
|
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require 'opentelemetry/trace/tracer'
|
4
|
+
require 'instana/trace/span'
|
5
|
+
require "instana/trace/span_context"
|
6
|
+
require 'opentelemetry/context'
|
6
7
|
|
7
8
|
module Instana
|
8
|
-
class Tracer
|
9
|
-
# Support ::Instana::Tracer.xxx call style for the instantiated tracer
|
9
|
+
class Tracer < OpenTelemetry::Trace::Tracer
|
10
10
|
class << self
|
11
|
-
def method_missing(method, *args, &block)
|
11
|
+
def method_missing(method, *args, &block) # rubocop:disable Style/MissingRespondToMissing
|
12
12
|
if ::Instana.tracer.respond_to?(method)
|
13
13
|
::Instana.tracer.send(method, *args, &block)
|
14
14
|
else
|
@@ -17,7 +17,9 @@ module Instana
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def initialize(logger
|
20
|
+
def initialize(_name, _version, tracer_provider, logger = Instana.logger)
|
21
|
+
super()
|
22
|
+
@tracer_provider = tracer_provider
|
21
23
|
@current_span = Concurrent::ThreadLocalVar.new
|
22
24
|
@logger = logger
|
23
25
|
end
|
@@ -29,8 +31,8 @@ module Instana
|
|
29
31
|
|
30
32
|
# @param [Instana::Span, NilClas] v the new current span
|
31
33
|
# Set the value of the current span
|
32
|
-
def current_span=(
|
33
|
-
@current_span.value =
|
34
|
+
def current_span=(value)
|
35
|
+
@current_span.value = value
|
34
36
|
end
|
35
37
|
|
36
38
|
#######################################
|
@@ -48,10 +50,10 @@ module Instana
|
|
48
50
|
# :span_id the ID of the parent span (must be an unsigned hex-string)
|
49
51
|
# :level specifies data collection level (optional)
|
50
52
|
#
|
51
|
-
def start_or_continue_trace(name, kvs = {}, incoming_context = nil
|
53
|
+
def start_or_continue_trace(name, kvs = {}, incoming_context = nil)
|
52
54
|
span = log_start_or_continue(name, kvs, incoming_context)
|
53
55
|
yield(span)
|
54
|
-
rescue Exception => e
|
56
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
55
57
|
log_error(e)
|
56
58
|
raise
|
57
59
|
ensure
|
@@ -69,10 +71,10 @@ module Instana
|
|
69
71
|
# @param name [String, Symbol] the name of the span to start
|
70
72
|
# @param kvs [Hash] list of key values to be reported in this new span
|
71
73
|
#
|
72
|
-
def trace(name, kvs = {}
|
74
|
+
def trace(name, kvs = {})
|
73
75
|
span = log_entry(name, kvs)
|
74
76
|
yield(span)
|
75
|
-
rescue Exception => e
|
77
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
76
78
|
log_error(e)
|
77
79
|
raise
|
78
80
|
ensure
|
@@ -100,12 +102,12 @@ module Instana
|
|
100
102
|
# Handle the potential variations on `incoming_context`
|
101
103
|
if incoming_context
|
102
104
|
if incoming_context.is_a?(Hash)
|
103
|
-
|
105
|
+
unless incoming_context.empty?
|
104
106
|
parent_context = SpanContext.new(
|
105
|
-
incoming_context[:trace_id],
|
106
|
-
incoming_context[:span_id],
|
107
|
-
incoming_context[:level],
|
108
|
-
{
|
107
|
+
trace_id: incoming_context[:trace_id],
|
108
|
+
span_id: incoming_context[:span_id],
|
109
|
+
level: incoming_context[:level],
|
110
|
+
baggage: {
|
109
111
|
external_trace_id: incoming_context[:external_trace_id],
|
110
112
|
external_state: incoming_context[:external_state]
|
111
113
|
}
|
@@ -116,14 +118,14 @@ module Instana
|
|
116
118
|
end
|
117
119
|
end
|
118
120
|
|
119
|
-
if parent_context
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
121
|
+
self.current_span = if parent_context
|
122
|
+
Span.new(name, parent_context)
|
123
|
+
else
|
124
|
+
Span.new(name)
|
125
|
+
end
|
124
126
|
|
125
|
-
|
126
|
-
|
127
|
+
current_span.set_tags(kvs) unless kvs.empty?
|
128
|
+
current_span
|
127
129
|
end
|
128
130
|
|
129
131
|
# Will establish a new span as a child of the current span
|
@@ -132,13 +134,13 @@ module Instana
|
|
132
134
|
# @param name [String, Symbol] the name of the span to create
|
133
135
|
# @param kvs [Hash] list of key values to be reported in the span
|
134
136
|
#
|
135
|
-
def log_entry(name, kvs = nil,
|
137
|
+
def log_entry(name, kvs = nil, _start_time = ::Instana::Util.now_in_ms, child_of = nil)
|
136
138
|
return unless tracing? || child_of
|
137
139
|
|
138
|
-
new_span = if child_of.nil? && !
|
139
|
-
Span.new(name,
|
140
|
+
new_span = if child_of.nil? && !current_span.nil?
|
141
|
+
Span.new(name, current_span)
|
140
142
|
else
|
141
|
-
Span.new(name,
|
143
|
+
Span.new(name, child_of)
|
142
144
|
end
|
143
145
|
new_span.set_tags(kvs) if kvs
|
144
146
|
self.current_span = new_span
|
@@ -149,17 +151,19 @@ module Instana
|
|
149
151
|
# @param kvs [Hash] list of key values to be reported in the span
|
150
152
|
#
|
151
153
|
def log_info(kvs)
|
152
|
-
return unless
|
153
|
-
|
154
|
+
return unless current_span
|
155
|
+
|
156
|
+
current_span.set_tags(kvs)
|
154
157
|
end
|
155
158
|
|
156
159
|
# Add an error to the current span
|
157
160
|
#
|
158
161
|
# @param e [Exception] Add exception to the current span
|
159
162
|
#
|
160
|
-
def log_error(
|
161
|
-
return unless
|
162
|
-
|
163
|
+
def log_error(error)
|
164
|
+
return unless current_span
|
165
|
+
|
166
|
+
current_span.record_exception(error)
|
163
167
|
end
|
164
168
|
|
165
169
|
# Closes out the current span
|
@@ -171,16 +175,16 @@ module Instana
|
|
171
175
|
# @param kvs [Hash] list of key values to be reported in the span
|
172
176
|
#
|
173
177
|
def log_exit(name, kvs = {})
|
174
|
-
return unless
|
178
|
+
return unless current_span
|
175
179
|
|
176
|
-
if
|
177
|
-
@logger.warn "Span mismatch: Attempt to end #{name} span but #{
|
180
|
+
if current_span.name != name
|
181
|
+
@logger.warn "Span mismatch: Attempt to end #{name} span but #{current_span.name} is active."
|
178
182
|
end
|
179
183
|
|
180
|
-
|
181
|
-
|
184
|
+
current_span.set_tags(kvs)
|
185
|
+
current_span.close
|
182
186
|
|
183
|
-
self.current_span =
|
187
|
+
self.current_span = current_span.parent || nil
|
184
188
|
end
|
185
189
|
|
186
190
|
# Closes out the current span in the current trace
|
@@ -193,14 +197,14 @@ module Instana
|
|
193
197
|
# @param kvs [Hash] list of key values to be reported in the span
|
194
198
|
#
|
195
199
|
def log_end(name, kvs = {}, end_time = ::Instana::Util.now_in_ms)
|
196
|
-
return unless
|
200
|
+
return unless current_span
|
197
201
|
|
198
|
-
if
|
199
|
-
@logger.warn "Span mismatch: Attempt to end #{name} span but #{
|
202
|
+
if current_span.name != name
|
203
|
+
@logger.warn "Span mismatch: Attempt to end #{name} span but #{current_span.name} is active."
|
200
204
|
end
|
201
205
|
|
202
|
-
|
203
|
-
|
206
|
+
current_span.set_tags(kvs)
|
207
|
+
current_span.close(end_time)
|
204
208
|
self.current_span = nil
|
205
209
|
end
|
206
210
|
|
@@ -220,7 +224,7 @@ module Instana
|
|
220
224
|
def log_async_entry(name, kvs)
|
221
225
|
return unless tracing?
|
222
226
|
|
223
|
-
new_span = Span.new(name,
|
227
|
+
new_span = Span.new(name, current_span)
|
224
228
|
new_span.set_tags(kvs) unless kvs.empty?
|
225
229
|
new_span
|
226
230
|
end
|
@@ -239,8 +243,8 @@ module Instana
|
|
239
243
|
# @param e [Exception] Add exception to the current span
|
240
244
|
# @param span [Span] the span for this Async op (previously returned from `log_async_entry`)
|
241
245
|
#
|
242
|
-
def log_async_error(
|
243
|
-
span.
|
246
|
+
def log_async_error(error, span)
|
247
|
+
span.record_exception(error)
|
244
248
|
end
|
245
249
|
|
246
250
|
# Closes out an asynchronous span
|
@@ -268,7 +272,7 @@ module Instana
|
|
268
272
|
# The non-nil value of this instance variable
|
269
273
|
# indicates if we are currently tracing
|
270
274
|
# in this thread or not.
|
271
|
-
(
|
275
|
+
(current_span ? true : false) ||
|
272
276
|
(::Instana.config[:allow_exit_as_root] && ::Instana.config[:tracing][:enabled])
|
273
277
|
end
|
274
278
|
|
@@ -280,9 +284,10 @@ module Instana
|
|
280
284
|
# @return [Boolean]
|
281
285
|
#
|
282
286
|
def tracing_span?(name)
|
283
|
-
if
|
284
|
-
return
|
287
|
+
if current_span
|
288
|
+
return current_span.name == name
|
285
289
|
end
|
290
|
+
|
286
291
|
false
|
287
292
|
end
|
288
293
|
|
@@ -291,8 +296,9 @@ module Instana
|
|
291
296
|
# @return [SpanContext] or nil if not tracing
|
292
297
|
#
|
293
298
|
def context
|
294
|
-
return unless
|
295
|
-
|
299
|
+
return unless current_span
|
300
|
+
|
301
|
+
current_span.context
|
296
302
|
end
|
297
303
|
|
298
304
|
# Used in the test suite, this resets the tracer to non-tracing state.
|
@@ -300,5 +306,51 @@ module Instana
|
|
300
306
|
def clear!
|
301
307
|
self.current_span = nil
|
302
308
|
end
|
309
|
+
|
310
|
+
# Creates a span that is active during the execution of the provided block.
|
311
|
+
# The span is automatically closed when the block completes, whether it completes
|
312
|
+
# normally or with an exception.
|
313
|
+
#
|
314
|
+
# @param name [String, Symbol] the name of the span to create
|
315
|
+
# @param attributes [Hash, nil] optional attributes to set on the span
|
316
|
+
# @param links [Array<Link>, nil] optional links to associate with the span
|
317
|
+
# @param start_timestamp [Integer, nil] optional start time for the span in milliseconds
|
318
|
+
# @param kind [Symbol, nil] optional span kind (e.g., :internal, :client, :server)
|
319
|
+
#
|
320
|
+
# @return [Object] the return value of the block
|
321
|
+
#
|
322
|
+
# @note This method is a wrapper around the parent class implementation and
|
323
|
+
# will only create a span if the Instana agent is ready and tracing is enabled.
|
324
|
+
#
|
325
|
+
def in_span(name, attributes: nil, links: nil, start_timestamp: nil, kind: nil)
|
326
|
+
return if !::Instana.agent.ready? || !::Instana.config[:tracing][:enabled]
|
327
|
+
|
328
|
+
super
|
329
|
+
end
|
330
|
+
|
331
|
+
# Starts a new span with the given parameters.
|
332
|
+
#
|
333
|
+
# @param name [String, Symbol] the name of the span to create (defaults to 'empty' if nil)
|
334
|
+
# @param with_parent [Context, nil] the parent context for the span (defaults to current context if nil)
|
335
|
+
# @param attributes [Hash, nil] optional attributes to set on the span
|
336
|
+
# @param links [Array<Link>, nil] optional links to associate with the span
|
337
|
+
# @param start_timestamp [Integer, nil] optional start time for the span in milliseconds
|
338
|
+
# @param kind [Symbol, nil] optional span kind (defaults to :internal if nil)
|
339
|
+
#
|
340
|
+
# @return [Span] the newly created span
|
341
|
+
#
|
342
|
+
# @note This method will only create a span if the Instana agent is ready and tracing is enabled.
|
343
|
+
# Default values are set for nil parameters: name='empty', kind=:internal,
|
344
|
+
# with_parent=current context, start_timestamp=current time.
|
345
|
+
#
|
346
|
+
def start_span(name, with_parent: nil, attributes: nil, links: nil, start_timestamp: ::Instana::Util.now_in_ms, kind: nil) # rubocop:disable Metrics/ParameterLists
|
347
|
+
return if !::Instana.agent.ready? || !::Instana.config[:tracing][:enabled]
|
348
|
+
|
349
|
+
with_parent ||= OpenTelemetry::Context.current
|
350
|
+
name ||= 'empty'
|
351
|
+
kind ||= :internal
|
352
|
+
start_timestamp ||= ::Instana::Util.now_in_ms
|
353
|
+
self.current_span = @tracer_provider.internal_start_span(name, kind, attributes, links, start_timestamp, with_parent, @instrumentation_scope)
|
354
|
+
end
|
303
355
|
end
|
304
356
|
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
# (c) Copyright IBM Corp. 2025
|
2
|
+
|
3
|
+
require 'opentelemetry/trace/tracer_provider'
|
4
|
+
require 'instana/samplers/samplers'
|
5
|
+
require 'instana/trace/span_limits'
|
6
|
+
require 'instana/trace/export'
|
7
|
+
|
8
|
+
module Instana
|
9
|
+
module Trace
|
10
|
+
# {TracerProvider} is the Instana implementation of {OpenTelemetry::Trace::TracerProvider}.
|
11
|
+
class TracerProvider < OpenTelemetry::Trace::TracerProvider
|
12
|
+
Key = Struct.new(:name, :version)
|
13
|
+
private_constant(:Key)
|
14
|
+
|
15
|
+
attr_accessor :span_limits, :id_generator, :sampler
|
16
|
+
attr_reader :resource
|
17
|
+
|
18
|
+
# Returns a new {TracerProvider} instance.
|
19
|
+
#
|
20
|
+
# @param [optional Sampler] sampler The sampling policy for new spans
|
21
|
+
# @param [optional Resource] resource The resource to associate with spans
|
22
|
+
# created by Tracers created by this TracerProvider
|
23
|
+
# @param [optional IDGenerator] id_generator The trace and span ID generation
|
24
|
+
# policy
|
25
|
+
# @param [optional SpanLimits] span_limits The limits to apply to attribute,
|
26
|
+
# event and link counts for Spans created by Tracers created by this
|
27
|
+
# TracerProvider
|
28
|
+
#
|
29
|
+
# @return [TracerProvider]
|
30
|
+
# def initialize
|
31
|
+
# super()
|
32
|
+
# end
|
33
|
+
|
34
|
+
def initialize(sampler: sampler_from_environment(Samplers.parent_based(root: Samplers::ALWAYS_ON)),
|
35
|
+
resource: nil, # Instana::Resources::Resource.create
|
36
|
+
id_generator: ::Instana::Trace,
|
37
|
+
span_limits: SpanLimits::DEFAULT)
|
38
|
+
super()
|
39
|
+
@mutex = Mutex.new
|
40
|
+
@registry = {}
|
41
|
+
@registry_mutex = Mutex.new
|
42
|
+
@span_processors = []
|
43
|
+
@span_limits = span_limits
|
44
|
+
@sampler = sampler
|
45
|
+
@id_generator = id_generator
|
46
|
+
@stopped = false
|
47
|
+
@resource = resource
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns a {Tracer} instance.
|
51
|
+
#
|
52
|
+
# @param [optional String] name Instrumentation package name
|
53
|
+
# @param [optional String] version Instrumentation package version
|
54
|
+
#
|
55
|
+
# @return [Tracer]
|
56
|
+
def tracer(name = nil, version = nil)
|
57
|
+
name ||= ''
|
58
|
+
version ||= ''
|
59
|
+
::Instana.logger.warn 'calling TracerProvider#tracer without providing a tracer name.' if name.empty?
|
60
|
+
@registry_mutex.synchronize { @registry[Key.new(name, version)] ||= Tracer.new(name, version, self) }
|
61
|
+
end
|
62
|
+
|
63
|
+
# Attempts to stop all the activity for this {TracerProvider}. Calls
|
64
|
+
# SpanProcessor#shutdown for all registered SpanProcessors.
|
65
|
+
#
|
66
|
+
# This operation may block until all the Spans are processed. Must be
|
67
|
+
# called before turning off the main application to ensure all data are
|
68
|
+
# processed and exported.
|
69
|
+
#
|
70
|
+
# After this is called all the newly created {Span}s will be no-op.
|
71
|
+
#
|
72
|
+
# @param [optional Numeric] timeout An optional timeout in seconds.
|
73
|
+
# @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
|
74
|
+
# a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
|
75
|
+
def shutdown(timeout: nil)
|
76
|
+
@mutex.synchronize do
|
77
|
+
if @stopped
|
78
|
+
::Instana.logger.warn('calling Tracer#shutdown multiple times.')
|
79
|
+
return Export::FAILURE
|
80
|
+
end
|
81
|
+
|
82
|
+
start_time = Instana::Util.timeout_timestamp
|
83
|
+
results = @span_processors.map do |processor|
|
84
|
+
remaining_timeout = Instana::Util.maybe_timeout(timeout, start_time)
|
85
|
+
break [Export::TIMEOUT] if remaining_timeout&.zero?
|
86
|
+
|
87
|
+
processor.shutdown(timeout: remaining_timeout)
|
88
|
+
end
|
89
|
+
@stopped = true
|
90
|
+
results.max || Export::SUCCESS
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Immediately export all spans that have not yet been exported for all the
|
95
|
+
# registered SpanProcessors.
|
96
|
+
#
|
97
|
+
# This method should only be called in cases where it is absolutely
|
98
|
+
# necessary, such as when using some FaaS providers that may suspend
|
99
|
+
# the process after an invocation, but before the `Processor` exports
|
100
|
+
# the completed spans.
|
101
|
+
#
|
102
|
+
# @param [optional Numeric] timeout An optional timeout in seconds.
|
103
|
+
# @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
|
104
|
+
# a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
|
105
|
+
def force_flush(timeout: nil)
|
106
|
+
@mutex.synchronize do
|
107
|
+
return Export::SUCCESS if @stopped
|
108
|
+
|
109
|
+
start_time = Instana::Util.timeout_timestamp
|
110
|
+
results = @span_processors.map do |processor|
|
111
|
+
remaining_timeout = Instana::Util.maybe_timeout(timeout, start_time)
|
112
|
+
return Export::TIMEOUT if remaining_timeout&.zero?
|
113
|
+
|
114
|
+
processor.force_flush(timeout: remaining_timeout)
|
115
|
+
end
|
116
|
+
results.max || Export::SUCCESS
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Adds a new SpanProcessor to this {Tracer}.
|
121
|
+
#
|
122
|
+
# @param span_processor the new SpanProcessor to be added.
|
123
|
+
def add_span_processor(span_processor)
|
124
|
+
@mutex.synchronize do
|
125
|
+
if @stopped
|
126
|
+
::Instana.logger.warn('calling Tracer#add_span_processor after shutdown.')
|
127
|
+
return
|
128
|
+
end
|
129
|
+
@span_processors = @span_processors.dup.push(span_processor)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# This method serves as the primary entry point for span creation. It initializes
|
134
|
+
# an Instana span, handles context, and manages sampling before returning the created span.
|
135
|
+
def internal_start_span(name, kind, attributes, links, start_timestamp, parent_context, instrumentation_scope) # rubocop:disable Metrics/ParameterLists
|
136
|
+
parent_span = OpenTelemetry::Trace.current_span(parent_context)
|
137
|
+
parent_span_context = parent_span.context if parent_span
|
138
|
+
if parent_span_context&.valid?
|
139
|
+
parent_span_id = parent_span_context.span_id
|
140
|
+
trace_id = parent_span_context.trace_id
|
141
|
+
span_id = @id_generator.generate_span_id
|
142
|
+
end
|
143
|
+
trace_id ||= @id_generator.generate_trace_id
|
144
|
+
|
145
|
+
if OpenTelemetry::Common::Utilities.untraced?(parent_context)
|
146
|
+
span_id = parent_span_id || @id_generator.generate_span_id
|
147
|
+
return OpenTelemetry::Trace.non_recording_span(OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id, span_id: span_id))
|
148
|
+
end
|
149
|
+
|
150
|
+
result = @sampler.should_sample?(trace_id: trace_id, parent_context: parent_context, links: links, name: name, kind: kind, attributes: attributes)
|
151
|
+
span_id ||= @id_generator.generate_span_id
|
152
|
+
if !@stopped && result.recording? && !@stopped
|
153
|
+
trace_flags = result.sampled? ? OpenTelemetry::Trace::TraceFlags::SAMPLED : OpenTelemetry::Trace::TraceFlags::DEFAULT
|
154
|
+
context = Instana::SpanContext.new(trace_id: trace_id, span_id: span_id, trace_flags: trace_flags, tracestate: result.tracestate)
|
155
|
+
attributes = attributes&.merge(result.attributes) || result.attributes.dup
|
156
|
+
Instana::Span.new(
|
157
|
+
name,
|
158
|
+
parent_span_context,
|
159
|
+
context,
|
160
|
+
parent_span,
|
161
|
+
kind,
|
162
|
+
parent_span_id,
|
163
|
+
@span_limits,
|
164
|
+
@span_processors,
|
165
|
+
attributes,
|
166
|
+
links,
|
167
|
+
start_timestamp,
|
168
|
+
@resource,
|
169
|
+
instrumentation_scope
|
170
|
+
)
|
171
|
+
else
|
172
|
+
Instana::Trace.non_recording_span(Instana::Trace::SpanContext.new(trace_id: trace_id, span_id: span_id, tracestate: result.tracestate)) # Todo add tracestate so that the trcing doesnot happen for this span # rubocop:disable Layout/LineLength
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def sampler_from_environment(default_sampler)
|
179
|
+
case ENV['OTEL_TRACES_SAMPLER']
|
180
|
+
when 'always_on' then Samplers::ALWAYS_ON
|
181
|
+
when 'always_off' then Samplers::ALWAYS_OFF
|
182
|
+
when 'traceidratio' then Samplers.trace_id_ratio_based(Float(ENV.fetch('OTEL_TRACES_SAMPLER_ARG', 1.0)))
|
183
|
+
when 'parentbased_always_on' then Samplers.parent_based(root: Samplers::ALWAYS_ON)
|
184
|
+
when 'parentbased_always_off' then Samplers.parent_based(root: Samplers::ALWAYS_OFF)
|
185
|
+
when 'parentbased_traceidratio' then Samplers.parent_based(root: Samplers.trace_id_ratio_based(Float(ENV.fetch('OTEL_TRACES_SAMPLER_ARG', 1.0))))
|
186
|
+
else default_sampler
|
187
|
+
end
|
188
|
+
rescue StandardError => e
|
189
|
+
OpenTelemetry.handle_error(exception: e, message: "installing default sampler #{default_sampler.description}")
|
190
|
+
default_sampler
|
191
|
+
end
|
192
|
+
|
193
|
+
def timeout_timestamp
|
194
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|