instana 1.212.0 → 2.4.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.
Files changed (215) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/lib/instana/activators/action_view.rb +5 -2
  4. data/lib/instana/activators/bunny.rb +23 -0
  5. data/lib/instana/activators/redis.rb +7 -2
  6. data/lib/instana/activators/sequel.rb +20 -0
  7. data/lib/instana/activators/sinatra.rb +3 -0
  8. data/lib/instana/backend/host_agent.rb +17 -4
  9. data/lib/instana/backend/request_client.rb +3 -1
  10. data/lib/instana/base.rb +4 -2
  11. data/lib/instana/config.rb +5 -0
  12. data/lib/instana/frameworks/rails.rb +27 -1
  13. data/lib/instana/instrumentation/action_cable.rb +8 -4
  14. data/lib/instana/instrumentation/action_controller.rb +2 -4
  15. data/lib/instana/instrumentation/action_mailer.rb +1 -1
  16. data/lib/instana/instrumentation/action_view.rb +40 -14
  17. data/lib/instana/instrumentation/active_job.rb +26 -13
  18. data/lib/instana/instrumentation/active_record.rb +2 -2
  19. data/lib/instana/instrumentation/aws_sdk_dynamodb.rb +1 -1
  20. data/lib/instana/instrumentation/aws_sdk_lambda.rb +8 -2
  21. data/lib/instana/instrumentation/aws_sdk_s3.rb +1 -1
  22. data/lib/instana/instrumentation/aws_sdk_sns.rb +1 -1
  23. data/lib/instana/instrumentation/aws_sdk_sqs.rb +1 -1
  24. data/lib/instana/instrumentation/bunny.rb +129 -0
  25. data/lib/instana/instrumentation/dalli.rb +1 -1
  26. data/lib/instana/instrumentation/excon.rb +7 -5
  27. data/lib/instana/instrumentation/graphql.rb +3 -3
  28. data/lib/instana/instrumentation/grpc.rb +14 -13
  29. data/lib/instana/instrumentation/instrumented_request.rb +4 -2
  30. data/lib/instana/instrumentation/mongo.rb +3 -3
  31. data/lib/instana/instrumentation/net-http.rb +15 -7
  32. data/lib/instana/instrumentation/rack.rb +108 -56
  33. data/lib/instana/instrumentation/redis.rb +54 -31
  34. data/lib/instana/instrumentation/resque.rb +10 -8
  35. data/lib/instana/instrumentation/rest-client.rb +4 -4
  36. data/lib/instana/instrumentation/sequel.rb +42 -0
  37. data/lib/instana/instrumentation/shoryuken.rb +4 -1
  38. data/lib/instana/instrumentation/sidekiq-client.rb +21 -19
  39. data/lib/instana/instrumentation/sidekiq-worker.rb +22 -21
  40. data/lib/instana/instrumented_logger.rb +1 -1
  41. data/lib/instana/samplers/result.rb +32 -0
  42. data/lib/instana/samplers/samplers.rb +76 -0
  43. data/lib/instana/serverless.rb +7 -3
  44. data/lib/instana/setup.rb +5 -5
  45. data/lib/instana/span_filtering/condition.rb +134 -0
  46. data/lib/instana/span_filtering/configuration.rb +262 -0
  47. data/lib/instana/span_filtering/filter_rule.rb +31 -0
  48. data/lib/instana/span_filtering.rb +62 -0
  49. data/lib/instana/trace/export.rb +36 -0
  50. data/lib/instana/{tracing → trace}/processor.rb +19 -15
  51. data/lib/instana/trace/span.rb +534 -0
  52. data/lib/instana/trace/span_context.rb +82 -0
  53. data/lib/instana/trace/span_kind.rb +51 -0
  54. data/lib/instana/trace/span_limits.rb +63 -0
  55. data/lib/instana/{tracer.rb → trace/tracer.rb} +88 -56
  56. data/lib/instana/trace/tracer_provider.rb +198 -0
  57. data/lib/instana/trace.rb +74 -0
  58. data/lib/instana/util.rb +35 -2
  59. data/lib/instana/version.rb +1 -1
  60. data/lib/instana.rb +4 -2
  61. metadata +135 -254
  62. data/.circleci/config.yml +0 -430
  63. data/.codeclimate.yml +0 -23
  64. data/.editorconfig +0 -10
  65. data/.fasterer.yml +0 -23
  66. data/.github/ISSUE_TEMPLATE/bug.yml +0 -39
  67. data/.github/ISSUE_TEMPLATE/config.yml +0 -8
  68. data/.github/workflows/pr_commits_signed_off.yml +0 -16
  69. data/.github/workflows/release-notification-on-slack.yml +0 -34
  70. data/.gitignore +0 -19
  71. data/.rubocop.yml +0 -34
  72. data/.rubocop_todo.yml +0 -1140
  73. data/Appraisals +0 -124
  74. data/CONTRIBUTING.md +0 -86
  75. data/Gemfile +0 -21
  76. data/LICENSE +0 -22
  77. data/MAINTAINERS.md +0 -3
  78. data/Rakefile +0 -49
  79. data/bin/announce_release_on_slack.py +0 -103
  80. data/docker-compose.yml +0 -20
  81. data/download.sh +0 -85
  82. data/examples/opentracing.rb +0 -35
  83. data/examples/tracing.rb +0 -84
  84. data/extras/license_header.rb +0 -44
  85. data/gemfiles/.bundle/config +0 -2
  86. data/gemfiles/aws_30.gemfile +0 -23
  87. data/gemfiles/aws_60.gemfile +0 -19
  88. data/gemfiles/coverage_merge.gemfile +0 -9
  89. data/gemfiles/cuba_30.gemfile +0 -19
  90. data/gemfiles/cuba_40.gemfile +0 -16
  91. data/gemfiles/dalli_20.gemfile +0 -18
  92. data/gemfiles/dalli_30.gemfile +0 -15
  93. data/gemfiles/dalli_32.gemfile +0 -15
  94. data/gemfiles/excon_02.gemfile +0 -20
  95. data/gemfiles/excon_021.gemfile +0 -20
  96. data/gemfiles/excon_079.gemfile +0 -20
  97. data/gemfiles/excon_100.gemfile +0 -17
  98. data/gemfiles/graphql_10.gemfile +0 -18
  99. data/gemfiles/graphql_20.gemfile +0 -18
  100. data/gemfiles/grpc_10.gemfile +0 -18
  101. data/gemfiles/mongo_216.gemfile +0 -18
  102. data/gemfiles/mongo_219.gemfile +0 -15
  103. data/gemfiles/net_http_01.gemfile +0 -19
  104. data/gemfiles/rack_16.gemfile +0 -18
  105. data/gemfiles/rack_20.gemfile +0 -18
  106. data/gemfiles/rack_30.gemfile +0 -16
  107. data/gemfiles/rails_42.gemfile +0 -21
  108. data/gemfiles/rails_50.gemfile +0 -22
  109. data/gemfiles/rails_52.gemfile +0 -22
  110. data/gemfiles/rails_60.gemfile +0 -22
  111. data/gemfiles/rails_61.gemfile +0 -22
  112. data/gemfiles/rails_70.gemfile +0 -19
  113. data/gemfiles/rails_71.gemfile +0 -19
  114. data/gemfiles/redis_40.gemfile +0 -18
  115. data/gemfiles/resque_122.gemfile +0 -19
  116. data/gemfiles/resque_20.gemfile +0 -19
  117. data/gemfiles/rest_client_16.gemfile +0 -20
  118. data/gemfiles/rest_client_20.gemfile +0 -20
  119. data/gemfiles/roda_20.gemfile +0 -19
  120. data/gemfiles/roda_30.gemfile +0 -19
  121. data/gemfiles/shoryuken_50.gemfile +0 -19
  122. data/gemfiles/shoryuken_60.gemfile +0 -16
  123. data/gemfiles/sidekiq_42.gemfile +0 -18
  124. data/gemfiles/sidekiq_50.gemfile +0 -18
  125. data/gemfiles/sidekiq_60.gemfile +0 -15
  126. data/gemfiles/sidekiq_65.gemfile +0 -15
  127. data/gemfiles/sidekiq_70.gemfile +0 -15
  128. data/gemfiles/sinatra_14.gemfile +0 -18
  129. data/gemfiles/sinatra_22.gemfile +0 -15
  130. data/gemfiles/sinatra_30.gemfile +0 -15
  131. data/instana.gemspec +0 -46
  132. data/lib/instana/open_tracing/carrier.rb +0 -7
  133. data/lib/instana/open_tracing/instana_tracer.rb +0 -99
  134. data/lib/instana/tracing/span.rb +0 -431
  135. data/lib/instana/tracing/span_context.rb +0 -65
  136. data/lib/opentracing.rb +0 -32
  137. data/log/.keep +0 -0
  138. data/sonar-project.properties +0 -9
  139. data/test/activator_test.rb +0 -50
  140. data/test/backend/agent_test.rb +0 -80
  141. data/test/backend/gc_snapshot_test.rb +0 -11
  142. data/test/backend/host_agent_activation_observer_test.rb +0 -73
  143. data/test/backend/host_agent_lookup_test.rb +0 -78
  144. data/test/backend/host_agent_reporting_observer_test.rb +0 -276
  145. data/test/backend/host_agent_test.rb +0 -75
  146. data/test/backend/process_info_test.rb +0 -83
  147. data/test/backend/request_client_test.rb +0 -39
  148. data/test/backend/serverless_agent_test.rb +0 -83
  149. data/test/benchmarks/bench_id_generation.rb +0 -15
  150. data/test/benchmarks/bench_opentracing.rb +0 -16
  151. data/test/config_test.rb +0 -34
  152. data/test/frameworks/cuba_test.rb +0 -61
  153. data/test/frameworks/roda_test.rb +0 -60
  154. data/test/frameworks/sinatra_test.rb +0 -66
  155. data/test/instana_test.rb +0 -37
  156. data/test/instrumentation/aws_test.rb +0 -197
  157. data/test/instrumentation/dalli_test.rb +0 -292
  158. data/test/instrumentation/excon_test.rb +0 -164
  159. data/test/instrumentation/graphql_test.rb +0 -248
  160. data/test/instrumentation/grpc_test.rb +0 -381
  161. data/test/instrumentation/mongo_test.rb +0 -37
  162. data/test/instrumentation/net_http_test.rb +0 -200
  163. data/test/instrumentation/rack_instrumented_request_test.rb +0 -211
  164. data/test/instrumentation/rack_test.rb +0 -415
  165. data/test/instrumentation/rails_action_cable_test.rb +0 -131
  166. data/test/instrumentation/rails_action_controller_test.rb +0 -191
  167. data/test/instrumentation/rails_action_mailer_test.rb +0 -48
  168. data/test/instrumentation/rails_action_view_test.rb +0 -195
  169. data/test/instrumentation/rails_active_job_test.rb +0 -65
  170. data/test/instrumentation/rails_active_record_database_missing_test.rb +0 -45
  171. data/test/instrumentation/rails_active_record_test.rb +0 -115
  172. data/test/instrumentation/redis_test.rb +0 -129
  173. data/test/instrumentation/resque_test.rb +0 -167
  174. data/test/instrumentation/rest_client_test.rb +0 -64
  175. data/test/instrumentation/shoryuken_test.rb +0 -47
  176. data/test/instrumentation/sidekiq-client_test.rb +0 -135
  177. data/test/instrumentation/sidekiq-worker_test.rb +0 -180
  178. data/test/secrets_test.rb +0 -112
  179. data/test/serverless_test.rb +0 -369
  180. data/test/snapshot/deltable_test.rb +0 -17
  181. data/test/snapshot/docker_container_test.rb +0 -82
  182. data/test/snapshot/fargate_container_test.rb +0 -82
  183. data/test/snapshot/fargate_process_test.rb +0 -35
  184. data/test/snapshot/fargate_task_test.rb +0 -49
  185. data/test/snapshot/google_cloud_run_instance_test.rb +0 -74
  186. data/test/snapshot/google_cloud_run_process_test.rb +0 -33
  187. data/test/snapshot/lambda_function_test.rb +0 -37
  188. data/test/snapshot/ruby_process_test.rb +0 -14
  189. data/test/support/apps/active_record/active_record.rb +0 -24
  190. data/test/support/apps/grpc/boot.rb +0 -23
  191. data/test/support/apps/grpc/grpc_server.rb +0 -84
  192. data/test/support/apps/http_endpoint/boot.rb +0 -28
  193. data/test/support/apps/rails/boot.rb +0 -219
  194. data/test/support/apps/rails/models/block.rb +0 -21
  195. data/test/support/apps/rails/models/block6.rb +0 -21
  196. data/test/support/apps/resque/boot.rb +0 -5
  197. data/test/support/apps/resque/jobs/resque_error_job.rb +0 -22
  198. data/test/support/apps/resque/jobs/resque_fast_job.rb +0 -23
  199. data/test/support/apps/sidekiq/boot.rb +0 -25
  200. data/test/support/apps/sidekiq/jobs/sidekiq_job_1.rb +0 -9
  201. data/test/support/apps/sidekiq/jobs/sidekiq_job_2.rb +0 -10
  202. data/test/support/apps/sidekiq/worker.rb +0 -37
  203. data/test/support/helpers.rb +0 -97
  204. data/test/support/mock_timer.rb +0 -20
  205. data/test/test_helper.rb +0 -67
  206. data/test/tracing/custom_test.rb +0 -226
  207. data/test/tracing/id_management_test.rb +0 -80
  208. data/test/tracing/instrumented_logger_test.rb +0 -39
  209. data/test/tracing/opentracing_test.rb +0 -382
  210. data/test/tracing/processor_test.rb +0 -58
  211. data/test/tracing/span_context_test.rb +0 -22
  212. data/test/tracing/span_test.rb +0 -179
  213. data/test/tracing/tracer_async_test.rb +0 -230
  214. data/test/tracing/tracer_test.rb +0 -354
  215. data/test/util_test.rb +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 332da83974279a02e0ebc35086a412aa2f8640d4e40dd38957bec22c0f8a9ed8
4
- data.tar.gz: cb3528e5f55e0c76e5069c0d801033d800af6c184101484690d9ead1b9cf7088
3
+ metadata.gz: f3e1c637f9239bf92022943ba9bd659e92fce0a7030a37adc337754e06d08245
4
+ data.tar.gz: c17d71a2c480b163b37c3f18a4fa6a510a94b553d5777b8192535433835b56bc
5
5
  SHA512:
6
- metadata.gz: 4f372d7417bda356f6051fc6d8fb1ceb6f85537ac4c6841a9247f966350c9574335bf8c4fdc567b1c78d54ad95a8f3d0ce53b14126e964bb249c68d648616d11
7
- data.tar.gz: 44ebe7c9b5716b7d323a619561c3732ba8b1145a600601ebbb6c797444db89a82486f94580ac2b20335f3f4877abaf35274abe9a14b740500c894c2b3aecffab
6
+ metadata.gz: 02fd637038f974a35d42f52f52878ccb27f9dd7b177b07e2bfd92b53c7f176fc8dd3ecf4cd40d088023e571c5d6f0976901cc828a7c9e826781d7e361538bc0a
7
+ data.tar.gz: eab1b63483157aa3e58f1aef240e90de08faeaf0edddc5c9905ebaccc89630e27d22e5431c6b3f5be84e135b082e2da8ce1738fbe62bf8eef1561f3b93bc1e77
data/README.md CHANGED
@@ -8,7 +8,8 @@ Any and all feedback is welcome. Happy Ruby visibility.
8
8
 
9
9
  [![Gem Version](https://badge.fury.io/rb/instana.svg)](https://badge.fury.io/rb/instana)
10
10
  [![CircleCI](https://circleci.com/gh/instana/ruby-sensor.svg?style=svg)](https://circleci.com/gh/instana/ruby-sensor)
11
- [![OpenTracing Badge](https://img.shields.io/badge/OpenTracing-enabled-blue.svg)](http://opentracing.io)
11
+ [![OpenTracing Badge](https://img.shields.io/badge/OpenTracing-disabled-red.svg)](http://opentracing.io)
12
+ [![OpenTelemetry Badge](https://img.shields.io/badge/OpenTelemetry-enabled-blue.svg)](http://opentelemetry.io)
12
13
 
13
14
  ## Installation
14
15
 
@@ -12,8 +12,11 @@ module Instana
12
12
  require 'instana/instrumentation/action_view'
13
13
 
14
14
  ::ActionView::PartialRenderer
15
- .prepend(Instana::Instrumentation::ActionView)
16
-
15
+ .prepend(Instana::Instrumentation::ActionView::PartialRenderer)
16
+ if defined?(::ActionView::CollectionRenderer)
17
+ ::ActionView::CollectionRenderer
18
+ .prepend(Instrumentation::ActionView::CollectionRenderer)
19
+ end
17
20
  true
18
21
  end
19
22
  end
@@ -0,0 +1,23 @@
1
+ # (c) Copyright IBM Corp. 2025
2
+
3
+ module Instana
4
+ module Activators
5
+ class Bunny < Activator
6
+ def can_instrument?
7
+ defined?(::Bunny) &&
8
+ defined?(::Bunny::Queue) &&
9
+ defined?(::Bunny::Exchange) &&
10
+ ::Instana.config[:bunny][:enabled]
11
+ end
12
+
13
+ def instrument
14
+ require 'instana/instrumentation/bunny'
15
+
16
+ ::Bunny::Exchange.prepend(::Instana::Instrumentation::BunnyProducer)
17
+ ::Bunny::Queue.prepend(::Instana::Instrumentation::BunnyConsumer)
18
+
19
+ true
20
+ end
21
+ end
22
+ end
23
+ end
@@ -5,13 +5,18 @@ module Instana
5
5
  module Activators
6
6
  class Redis < Activator
7
7
  def can_instrument?
8
- defined?(::Redis) && defined?(::Redis::Client) && ::Instana.config[:redis][:enabled]
8
+ defined?(::Redis) && defined?(::Redis::Client) && ::Instana.config[:redis][:enabled] &&
9
+ (Gem::Specification.find_by_name('redis').version < Gem::Version.new('5.0') || defined?(::RedisClient))
9
10
  end
10
11
 
11
12
  def instrument
12
13
  require 'instana/instrumentation/redis'
13
14
 
14
- ::Redis::Client.prepend(::Instana::RedisInstrumentation)
15
+ if Gem::Specification.find_by_name('redis').version >= Gem::Version.new('5.0')
16
+ ::RedisClient.prepend(::Instana::RedisInstrumentation)
17
+ else
18
+ ::Redis::Client.prepend(::Instana::RedisInstrumentation)
19
+ end
15
20
 
16
21
  true
17
22
  end
@@ -0,0 +1,20 @@
1
+ # (c) Copyright IBM Corp. 2024
2
+
3
+ module Instana
4
+ module Activators
5
+ class Sequel < Activator
6
+ def can_instrument?
7
+ defined?(::Sequel::Database)
8
+ end
9
+
10
+ def instrument
11
+ require 'instana/instrumentation/sequel'
12
+
13
+ ::Sequel::Database
14
+ .prepend(Instana::Instrumentation::Sequel)
15
+
16
+ true
17
+ end
18
+ end
19
+ end
20
+ end
@@ -12,6 +12,9 @@ module Instana
12
12
  require 'instana/frameworks/sinatra'
13
13
 
14
14
  ::Sinatra::Base.use ::Instana::Rack
15
+ unless ::Sinatra::Base.respond_to?(:mustermann_opts)
16
+ ::Sinatra::Base.set :mustermann_opts, {}
17
+ end
15
18
  ::Sinatra::Base.register ::Instana::SinatraPathTemplateExtractor
16
19
 
17
20
  true
@@ -12,6 +12,8 @@ module Instana
12
12
  @logger = logger
13
13
  @future = nil
14
14
  @client = nil
15
+ # Timer task to poll for agent liveliness
16
+ @agent_connection_task = Concurrent::TimerTask.new(execution_interval: 75) { announce }
15
17
  end
16
18
 
17
19
  def setup; end
@@ -27,8 +29,17 @@ module Instana
27
29
  alias start spawn_background_thread
28
30
 
29
31
  def announce
30
- @client = until_not_nil { HostAgentLookup.new.call }
31
- @discovery.delete_observers
32
+ @client = with_timeout { HostAgentLookup.new.call }
33
+ # Shuts down the connection task based on agent connection client.
34
+ @client ? @agent_connection_task.shutdown : @agent_connection_task.execute
35
+ # Do not continue further if the agent is down/connection to the agent is unsuccessfull
36
+ return nil unless @client
37
+
38
+ begin
39
+ @discovery.send(:observers)&.send(:notify_and_delete_observers, Time.now, nil, nil)
40
+ ensure
41
+ @discovery.delete_observers
42
+ end
32
43
  @discovery
33
44
  .with_observer(HostAgentActivationObserver.new(@client, @discovery))
34
45
  .with_observer(HostAgentReportingObserver.new(@client, @discovery))
@@ -70,14 +81,16 @@ module Instana
70
81
 
71
82
  private
72
83
 
73
- def until_not_nil
74
- loop do
84
+ def with_timeout
85
+ 15.times do
75
86
  result = yield
76
87
  return result unless result.nil?
77
88
 
78
89
  @logger.debug("Waiting on a connection to the agent.")
79
90
  sleep(1)
80
91
  end
92
+ @logger.info("Agent connection timed out retrying after 60 seconds")
93
+ nil
81
94
  end
82
95
 
83
96
  def discovery_value
@@ -8,8 +8,10 @@ require 'json'
8
8
  # :nocov:
9
9
  begin
10
10
  require 'oj'
11
+ INSTANA_USE_OJ = true
11
12
  rescue LoadError => _e
12
13
  Instana.logger.warn("Unable to load Oj.")
14
+ INSTANA_USE_OJ = false
13
15
  end
14
16
  # :nocov:
15
17
 
@@ -66,7 +68,7 @@ module Instana
66
68
 
67
69
  def encode_body(data)
68
70
  # :nocov:
69
- defined?(Oj) ? Oj.dump(data, mode: :strict) : JSON.dump(data)
71
+ INSTANA_USE_OJ ? Oj.dump(data, mode: :strict) : JSON.dump(data)
70
72
  # :nocov:
71
73
  end
72
74
  end
data/lib/instana/base.rb CHANGED
@@ -14,6 +14,7 @@ module Instana
14
14
  attr_accessor :pid
15
15
  attr_reader :secrets
16
16
  attr_reader :serverless
17
+ attr_accessor :tracer_provider
17
18
 
18
19
  ##
19
20
  # setup
@@ -22,8 +23,9 @@ module Instana
22
23
  # to run" state.
23
24
  #
24
25
  def setup
25
- @agent = ::Instana::Backend::Agent.new
26
- @tracer = ::Instana::Tracer.new
26
+ @agent = ::Instana::Backend::Agent.new
27
+ @tracer_provider = ::Instana::Trace::TracerProvider.new
28
+ @tracer = @tracer_provider.tracer('instana_tracer')
27
29
  @processor = ::Instana::Processor.new
28
30
  @secrets = ::Instana::Secrets.new
29
31
  @serverless = ::Instana::Serverless.new
@@ -27,6 +27,9 @@ module Instana
27
27
  # Enable/disable tracing (default: enabled)
28
28
  @config[:tracing] = { :enabled => true }
29
29
 
30
+ # Enable/disable tracing exit spans as root spans
31
+ @config[:allow_exit_as_root] = ENV['INSTANA_ALLOW_EXIT_AS_ROOT'] == '1'
32
+
30
33
  # Enable/Disable logging
31
34
  @config[:logging] = { :enabled => true }
32
35
 
@@ -61,6 +64,7 @@ module Instana
61
64
  @config[:action_controller] = { :enabled => true }
62
65
  @config[:action_view] = { :enabled => true }
63
66
  @config[:active_record] = { :enabled => true }
67
+ @config[:bunny] = { :enabled => true }
64
68
  @config[:dalli] = { :enabled => true }
65
69
  @config[:excon] = { :enabled => true }
66
70
  @config[:grpc] = { :enabled => true }
@@ -70,6 +74,7 @@ module Instana
70
74
  @config[:'resque-client'] = { :enabled => true, :propagate => true }
71
75
  @config[:'resque-worker'] = { :enabled => true, :'setup-fork' => true }
72
76
  @config[:'rest-client'] = { :enabled => true }
77
+ @config[:sequel] = { :enabled => true }
73
78
  @config[:'sidekiq-client'] = { :enabled => true }
74
79
  @config[:'sidekiq-worker'] = { :enabled => true }
75
80
  end
@@ -17,7 +17,33 @@ else
17
17
  # Configure the Instrumented Logger
18
18
  if ::Instana.config[:logging][:enabled] && !ENV.key?('INSTANA_TEST')
19
19
  logger = ::Instana::InstrumentedLogger.new('/dev/null')
20
- Rails.logger.extend(ActiveSupport::Logger.broadcast(logger))
20
+ if ::Rails::VERSION::STRING < "7.1"
21
+ # Rails 7.0.3 `tagged_logging.rb` has a number of bugs.
22
+ # What pertains to our instrumentation here is that in
23
+ # https://github.com/rails/rails/blob/v7.0.3/activesupport/lib/active_support/tagged_logging.rb#L100
24
+ # sets the `other_logger.formatter` to `formatter` if `other_logger.formatter` is `nil`
25
+ # but then
26
+ # https://github.com/rails/rails/blob/v7.0.3/activesupport/lib/active_support/tagged_logging.rb#L102
27
+ # redefines `formatter.current_tags` method to a proc calling `formatter.current_tags`, itself.
28
+ # which is an infinite recursion.
29
+ #
30
+ # This bug starts with 7.0.3:
31
+ # https://github.com/rails/rails/compare/v7.0.2...v7.0.3#diff-68f90ba4998610be2f7da027e006e8ddeeb06dece66f41579c94070e12f23011
32
+ # And is already reverted/fixed in 7.0.4
33
+ # https://github.com/rails/rails/compare/v7.0.3...v7.0.4#diff-68f90ba4998610be2f7da027e006e8ddeeb06dece66f41579c94070e12f23011
34
+ # The commit which fixes it is:
35
+ # https://github.com/rails/rails/commit/ff277583e22ddfbcfbd2131789a7cb7c2f868d68
36
+ #
37
+ # Since instana does trigger this bug here we workaround it, by defining the `formatter`,
38
+ # to break the infinite loop. The `formatter` used here is the same as the default used in
39
+ # https://github.com/rails/rails/blob/v7.0.3/activesupport/lib/active_support/tagged_logging.rb#L89C9-L89C70
40
+ if ::Rails::VERSION::STRING == "7.0.3"
41
+ logger.formatter = ActiveSupport::Logger::SimpleFormatter.new
42
+ end
43
+ Rails.logger.extend(ActiveSupport::Logger.broadcast(logger))
44
+ else
45
+ Rails.logger.broadcast_to(logger)
46
+ end
21
47
  end
22
48
 
23
49
  if ::Instana.config[:tracing][:enabled]
@@ -27,8 +27,10 @@ module Instana
27
27
  }
28
28
 
29
29
  context = connection.instana_trace_context
30
- ::Instana.tracer.start_or_continue_trace(:'rpc-server', rpc_tags, context) do
31
- super(data, via: via)
30
+ Trace.with_span(OpenTelemetry::Trace.non_recording_span(context)) do
31
+ ::Instana.tracer.in_span(:'rpc-server', attributes: rpc_tags) do
32
+ super(data, via: via)
33
+ end
32
34
  end
33
35
  end
34
36
 
@@ -44,8 +46,10 @@ module Instana
44
46
  }
45
47
 
46
48
  context = connection.instana_trace_context
47
- ::Instana.tracer.start_or_continue_trace(:'rpc-server', rpc_tags, context) do
48
- super(action, data)
49
+ Trace.with_span(OpenTelemetry::Trace.non_recording_span(context)) do
50
+ ::Instana.tracer.in_span(:'rpc-server', attributes: rpc_tags) do
51
+ super(action, data)
52
+ end
49
53
  end
50
54
  end
51
55
  end
@@ -11,9 +11,8 @@ module Instana
11
11
  action: action_name
12
12
  }
13
13
  }
14
-
15
14
  request.env['INSTANA_HTTP_PATH_TEMPLATE'] = matched_path_template
16
- ::Instana::Tracer.trace(:actioncontroller, call_payload) { super(*args) }
15
+ ::Instana.tracer.in_span(:actioncontroller, attributes: call_payload) { super(*args) }
17
16
  end
18
17
 
19
18
  def render(*args, &block)
@@ -22,8 +21,7 @@ module Instana
22
21
  name: describe_render_options(args.first) || 'Default'
23
22
  }
24
23
  }
25
-
26
- ::Instana::Tracer.trace(:actionview, call_payload) { super(*args, &block) }
24
+ ::Instana.tracer.in_span(:actionview, attributes: call_payload) { super(*args, &block) }
27
25
  end
28
26
 
29
27
  private
@@ -12,7 +12,7 @@ module Instana
12
12
  method: method_name.to_s
13
13
  }
14
14
  }
15
- Instana::Tracer.trace(:'mail.actionmailer', tags) { super }
15
+ Instana.tracer.in_span(:'mail.actionmailer', attributes: tags) { super }
16
16
  else
17
17
  super
18
18
  end
@@ -4,26 +4,52 @@
4
4
  module Instana
5
5
  module Instrumentation
6
6
  module ActionView
7
- def render_partial(*args)
8
- call_payload = {
9
- render: {
10
- type: :partial,
11
- name: @options.is_a?(Hash) ? @options[:partial].to_s : 'Unknown'
7
+ module PartialRenderer
8
+ def render_partial(*args)
9
+ call_payload = {
10
+ render: {
11
+ type: :partial,
12
+ name: @options.is_a?(Hash) ? @options[:partial].to_s : 'Unknown'
13
+ }
12
14
  }
13
- }
14
15
 
15
- ::Instana::Tracer.trace(:render, call_payload) { super(*args) }
16
+ ::Instana.tracer.in_span(:render, attributes: call_payload) { super(*args) }
17
+ end
18
+
19
+ def render_collection(*args)
20
+ call_payload = {
21
+ render: {
22
+ type: :collection,
23
+ name: @path.to_s
24
+ }
25
+ }
26
+
27
+ ::Instana.tracer.in_span(:render, attributes: call_payload) { super(*args) }
28
+ end
29
+
30
+ def render_partial_template(*args)
31
+ call_payload = {
32
+ render: {
33
+ type: :partial,
34
+ name: @options.is_a?(Hash) ? @options[:partial].to_s : 'Unknown'
35
+ }
36
+ }
37
+
38
+ ::Instana.tracer.in_span(:render, attributes: call_payload) { super(*args) }
39
+ end
16
40
  end
17
41
 
18
- def render_collection(*args)
19
- call_payload = {
20
- render: {
21
- type: :collection,
22
- name: @path.to_s
42
+ module CollectionRenderer
43
+ def render_collection(*args)
44
+ call_payload = {
45
+ render: {
46
+ type: :collection,
47
+ name: @options.is_a?(Hash) ? @options[:partial].to_s : 'Unknown'
48
+ }
23
49
  }
24
- }
25
50
 
26
- ::Instana::Tracer.trace(:render, call_payload) { super(*args) }
51
+ ::Instana.tracer.in_span(:render, attributes: call_payload) { super(*args) }
52
+ end
27
53
  end
28
54
  end
29
55
  end
@@ -1,5 +1,19 @@
1
1
  # (c) Copyright IBM Corp. 2021
2
2
  # (c) Copyright Instana Inc. 2021
3
+ module OpenTelemetry
4
+ module Trace
5
+ module Propagation
6
+ module TraceContext
7
+ # A TraceParent is an implementation of the W3C trace context specification
8
+ # https://www.w3.org/TR/trace-context/
9
+ # {Trace::SpanContext}
10
+ class TraceParent
11
+ REGEXP = /^(?<version>[A-Fa-f0-9]{2})-(?<trace_id>[A-Fa-f0-9]{32})-(?<span_id>[A-Fa-f0-9]{32})-(?<flags>[A-Fa-f0-9]{2})(?<ignored>-.*)?$/
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
3
17
 
4
18
  module Instana
5
19
  module Instrumentation
@@ -15,12 +29,11 @@ module Instana
15
29
  }
16
30
  }
17
31
 
18
- ::Instana::Tracer.trace(:activejob, tags) do
32
+ ::Instana.tracer.in_span(:activejob, attributes: tags) do
19
33
  context = ::Instana.tracer.context
20
- job.arguments = [{
21
- given_arguments: job.arguments,
22
- instana_context: context ? context.to_hash : nil
23
- }]
34
+ job.arguments.append({
35
+ instana_context: context ? context.to_hash : nil
36
+ })
24
37
 
25
38
  block.call
26
39
  end
@@ -35,15 +48,15 @@ module Instana
35
48
  job_id: job.job_id
36
49
  }
37
50
  }
38
-
39
- incoming_context = if job.arguments.is_a?(Array) && job.arguments.first.is_a?(Hash)
40
- instana_context = job.arguments.first[:instana_context]
41
- job.arguments = job.arguments.first[:given_arguments]
42
- instana_context ? ::Instana::SpanContext.new(instana_context[:trace_id], instana_context[:span_id]) : nil
51
+ incoming_context = if job.arguments.is_a?(Array) && job.arguments.last.is_a?(Hash) && job.arguments.last.key?(:instana_context)
52
+ instana_context = job.arguments.last[:instana_context]
53
+ job.arguments.pop
54
+ instana_context ? ::Instana::SpanContext.new(trace_id: instana_context[:trace_id], span_id: instana_context[:span_id]) : nil
43
55
  end
44
-
45
- ::Instana::Tracer.start_or_continue_trace(:activejob, tags, incoming_context) do
46
- block.call
56
+ Trace.with_span(OpenTelemetry::Trace.non_recording_span(incoming_context)) do
57
+ ::Instana.tracer.in_span(:activejob, attributes: tags) do
58
+ block.call
59
+ end
47
60
  end
48
61
  end
49
62
  end
@@ -6,7 +6,7 @@ module Instana
6
6
  module ActiveRecord
7
7
  IGNORED_NAMES = %w[SCHEMA EXPLAIN CACHE].freeze
8
8
  IGNORED_SQL = %w[BEGIN COMMIT SET].freeze
9
- SANITIZE_REGEXP = /('[\s\S][^']*'|\d*\.\d+|\d+|NULL)/i.freeze
9
+ SANITIZE_REGEXP = /('[\s\S][^']*'|\d*\.\d+|\d+|NULL)/i
10
10
 
11
11
  def log(sql, name = 'SQL', binds = [], *args, **kwargs, &block)
12
12
  call_payload = {
@@ -35,7 +35,7 @@ module Instana
35
35
 
36
36
  def maybe_trace(call_payload, name, &blk)
37
37
  if ::Instana.tracer.tracing? && !ignored?(call_payload, name)
38
- ::Instana.tracer.trace(:activerecord, call_payload, &blk)
38
+ ::Instana.tracer.in_span(:activerecord, attributes: call_payload, &blk)
39
39
  else
40
40
  yield
41
41
  end
@@ -11,7 +11,7 @@ module Instana
11
11
  table: table_name_from(context)
12
12
  }
13
13
 
14
- ::Instana.tracer.trace(:dynamodb, {dynamodb: dynamo_tags}) { @handler.call(context) }
14
+ ::Instana.tracer.in_span(:dynamodb, attributes: {dynamodb: dynamo_tags}) { @handler.call(context) }
15
15
  end
16
16
 
17
17
  private
@@ -17,7 +17,7 @@ module Instana
17
17
  'X-INSTANA-L' => span_context.level.to_s
18
18
  }
19
19
 
20
- context.params[:client_context] = JSON.dump(payload)
20
+ context.params[:client_context] = Base64.strict_encode64(JSON.dump(payload))
21
21
  end
22
22
 
23
23
  tags = {
@@ -25,7 +25,13 @@ module Instana
25
25
  type: context.params[:invocation_type]
26
26
  }.reject { |_, v| v.nil? }
27
27
 
28
- ::Instana.tracer.trace(:"aws.lambda.invoke", {aws: {lambda: {invoke: tags}}}) { @handler.call(context) }
28
+ ::Instana.tracer.in_span(:"aws.lambda.invoke", attributes: {aws: {lambda: {invoke: tags}}}) do
29
+ response = @handler.call(context)
30
+ if response.respond_to? :status_code
31
+ ::Instana.tracer.log_info(:http => {:status => response.status_code })
32
+ end
33
+ response
34
+ end
29
35
  end
30
36
  end
31
37
 
@@ -12,7 +12,7 @@ module Instana
12
12
  key: key_from_context(context)
13
13
  }.reject { |_, v| v.nil? }
14
14
 
15
- ::Instana.tracer.trace(:s3, {s3: s3_tags}) { @handler.call(context) }
15
+ ::Instana.tracer.in_span(:s3, attributes: {s3: s3_tags}) { @handler.call(context) }
16
16
  end
17
17
 
18
18
  private
@@ -14,7 +14,7 @@ module Instana
14
14
  }.reject { |_, v| v.nil? }
15
15
 
16
16
  if context.operation_name == :publish
17
- ::Instana.tracer.trace(:sns, {sns: sns_tags}) { @handler.call(context) }
17
+ ::Instana.tracer.in_span(:sns, attributes: {sns: sns_tags}) { @handler.call(context) }
18
18
  else
19
19
  @handler.call(context)
20
20
  end
@@ -15,7 +15,7 @@ module Instana
15
15
 
16
16
  span_tags = tags_for(context.operation_name, context.params).reject { |_, v| v.nil? }
17
17
 
18
- ::Instana.tracer.trace(:sqs, {sqs: span_tags}) do |span|
18
+ ::Instana.tracer.in_span(:sqs, attributes: {sqs: span_tags}) do |span|
19
19
  case context.operation_name
20
20
  when :send_message
21
21
  inject_instana_headers(span, context.params)
@@ -0,0 +1,129 @@
1
+ # (c) Copyright IBM Corp. 2025
2
+
3
+ module Instana
4
+ module Instrumentation
5
+ module BunnyProducer
6
+ def publish(payload, options = {})
7
+ if ::Instana.tracer.tracing?
8
+ exchange_name = name.empty? ? 'default' : name
9
+ routing_key = options[:routing_key] || ''
10
+
11
+ kvs = {
12
+ rabbitmq: {
13
+ sort: 'publish',
14
+ address: channel.connection.host,
15
+ key: routing_key,
16
+ exchange: exchange_name
17
+ }
18
+ }
19
+
20
+ ::Instana.tracer.in_span(:rabbitmq, attributes: kvs) do |span|
21
+ # Inject trace context into message headers
22
+ options[:headers] ||= {}
23
+ options[:headers]['X-Instana-T'] = span.context.trace_id
24
+ options[:headers]['X-Instana-S'] = span.context.span_id
25
+ options[:headers]['X-Instana-L'] = span.context.level.to_s
26
+
27
+ super(payload, options)
28
+ end
29
+ else
30
+ super(payload, options)
31
+ end
32
+ rescue => e
33
+ ::Instana.logger.debug { "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" }
34
+ raise
35
+ end
36
+ end
37
+
38
+ module BunnyConsumer
39
+ def pop(options = {})
40
+ delivery_info, properties, payload = super(options)
41
+
42
+ return [delivery_info, properties, payload] unless delivery_info
43
+
44
+ trace_rabbitmq_consume(delivery_info, properties) do
45
+ [delivery_info, properties, payload]
46
+ end
47
+ rescue => e
48
+ log_error(e)
49
+ raise
50
+ end
51
+
52
+ def subscribe(options = {}, &block)
53
+ if block_given?
54
+ wrapped_block = lambda do |delivery_info, properties, payload|
55
+ trace_rabbitmq_consume(delivery_info, properties) do
56
+ block.call(delivery_info, properties, payload)
57
+ end
58
+ end
59
+
60
+ super(options, &wrapped_block)
61
+ else
62
+ super(options, &block)
63
+ end
64
+ rescue => e
65
+ log_error(e)
66
+ raise
67
+ end
68
+
69
+ private
70
+
71
+ def trace_rabbitmq_consume(delivery_info, properties, &block)
72
+ return yield unless ::Instana.tracer.tracing? || extract_context_from_headers(properties)
73
+
74
+ kvs = build_consume_attributes(delivery_info)
75
+ context = extract_context_from_headers(properties)
76
+
77
+ if context[:trace_id]
78
+ trace_with_context(context, kvs, &block)
79
+ else
80
+ ::Instana.tracer.in_span(:rabbitmq, attributes: kvs, &block)
81
+ end
82
+ end
83
+
84
+ def build_consume_attributes(delivery_info)
85
+ queue_name = name
86
+ exchange_name = delivery_info.exchange.empty? ? 'default' : delivery_info.exchange
87
+
88
+ {
89
+ rabbitmq: {
90
+ sort: 'consume',
91
+ address: channel.connection.host,
92
+ queue: queue_name,
93
+ exchange: exchange_name,
94
+ key: delivery_info.routing_key
95
+ }
96
+ }
97
+ end
98
+
99
+ def trace_with_context(context, kvs, &block)
100
+ instana_context = ::Instana::SpanContext.new(
101
+ trace_id: context[:trace_id],
102
+ span_id: context[:span_id],
103
+ level: context[:level]
104
+ )
105
+ span = OpenTelemetry::Trace.non_recording_span(instana_context)
106
+
107
+ Trace.with_span(span) do
108
+ ::Instana.tracer.in_span(:rabbitmq, attributes: kvs, &block)
109
+ end
110
+ end
111
+
112
+ def extract_context_from_headers(properties)
113
+ return {} unless properties && properties.headers
114
+
115
+ headers = properties.headers
116
+ {
117
+ trace_id: headers['X-Instana-T'],
118
+ span_id: headers['X-Instana-S'],
119
+ level: headers['X-Instana-L']&.to_i
120
+ }.reject { |_, v| v.nil? }
121
+ end
122
+
123
+ def log_error(error)
124
+ # Log errors on to console if INSTANA_DEBUG is enabled
125
+ ::Instana.logger.debug { "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{error.message}" }
126
+ end
127
+ end
128
+ end
129
+ end