instana 1.195.2 → 1.197.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -2
  3. data/Rakefile +1 -1
  4. data/instana.gemspec +3 -7
  5. data/lib/instana.rb +3 -0
  6. data/lib/instana/activator.rb +2 -0
  7. data/lib/instana/backend/agent.rb +60 -0
  8. data/lib/instana/backend/gc_snapshot.rb +41 -0
  9. data/lib/instana/backend/host_agent.rb +74 -0
  10. data/lib/instana/backend/host_agent_activation_observer.rb +97 -0
  11. data/lib/instana/backend/host_agent_lookup.rb +57 -0
  12. data/lib/instana/backend/host_agent_reporting_observer.rb +106 -0
  13. data/lib/instana/backend/process_info.rb +64 -0
  14. data/lib/instana/backend/request_client.rb +73 -0
  15. data/lib/instana/backend/serverless_agent.rb +118 -0
  16. data/lib/instana/base.rb +8 -27
  17. data/lib/instana/config.rb +8 -22
  18. data/lib/instana/instrumentation/excon.rb +17 -8
  19. data/lib/instana/instrumentation/instrumented_request.rb +62 -7
  20. data/lib/instana/instrumentation/net-http.rb +7 -5
  21. data/lib/instana/instrumentation/rack.rb +12 -7
  22. data/lib/instana/logger_delegator.rb +31 -0
  23. data/lib/instana/{opentracing → open_tracing}/carrier.rb +0 -0
  24. data/lib/instana/open_tracing/instana_tracer.rb +99 -0
  25. data/lib/instana/secrets.rb +6 -2
  26. data/lib/instana/setup.rb +20 -11
  27. data/lib/instana/snapshot/deltable.rb +25 -0
  28. data/lib/instana/snapshot/docker_container.rb +151 -0
  29. data/lib/instana/snapshot/fargate_container.rb +88 -0
  30. data/lib/instana/snapshot/fargate_process.rb +67 -0
  31. data/lib/instana/snapshot/fargate_task.rb +72 -0
  32. data/lib/instana/snapshot/lambda_function.rb +36 -0
  33. data/lib/instana/snapshot/ruby_process.rb +48 -0
  34. data/lib/instana/tracer.rb +25 -143
  35. data/lib/instana/tracing/processor.rb +14 -22
  36. data/lib/instana/tracing/span.rb +31 -34
  37. data/lib/instana/tracing/span_context.rb +15 -10
  38. data/lib/instana/util.rb +8 -69
  39. data/lib/instana/version.rb +1 -1
  40. data/lib/opentracing.rb +26 -3
  41. data/test/backend/agent_test.rb +54 -0
  42. data/test/backend/gc_snapshot_test.rb +11 -0
  43. data/test/backend/host_agent_activation_observer_test.rb +72 -0
  44. data/test/backend/host_agent_lookup_test.rb +78 -0
  45. data/test/backend/host_agent_reporting_observer_test.rb +192 -0
  46. data/test/backend/host_agent_test.rb +47 -0
  47. data/test/backend/process_info_test.rb +63 -0
  48. data/test/backend/request_client_test.rb +39 -0
  49. data/test/backend/serverless_agent_test.rb +73 -0
  50. data/test/config_test.rb +10 -0
  51. data/test/instana_test.rb +11 -4
  52. data/test/instrumentation/excon_test.rb +15 -1
  53. data/test/instrumentation/rack_instrumented_request_test.rb +5 -2
  54. data/test/instrumentation/rack_test.rb +2 -14
  55. data/test/secrets_test.rb +41 -22
  56. data/test/snapshot/deltable_test.rb +17 -0
  57. data/test/snapshot/docker_container_test.rb +82 -0
  58. data/test/snapshot/fargate_container_test.rb +82 -0
  59. data/test/snapshot/fargate_process_test.rb +35 -0
  60. data/test/snapshot/fargate_task_test.rb +49 -0
  61. data/test/snapshot/ruby_process_test.rb +14 -0
  62. data/test/support/mock_timer.rb +20 -0
  63. data/test/test_helper.rb +16 -4
  64. data/test/tracing/custom_test.rb +1 -3
  65. data/test/tracing/id_management_test.rb +4 -0
  66. data/test/tracing/opentracing_test.rb +15 -2
  67. data/test/tracing/processor_test.rb +58 -0
  68. data/test/tracing/span_context_test.rb +21 -0
  69. data/test/tracing/span_test.rb +136 -0
  70. data/test/tracing/tracer_async_test.rb +29 -0
  71. data/test/tracing/tracer_test.rb +82 -16
  72. data/test/util_test.rb +10 -0
  73. metadata +71 -43
  74. data/lib/instana/agent.rb +0 -508
  75. data/lib/instana/agent/helpers.rb +0 -87
  76. data/lib/instana/agent/hooks.rb +0 -44
  77. data/lib/instana/agent/tasks.rb +0 -51
  78. data/lib/instana/collector.rb +0 -119
  79. data/lib/instana/collectors/gc.rb +0 -60
  80. data/lib/instana/collectors/memory.rb +0 -37
  81. data/lib/instana/collectors/thread.rb +0 -33
  82. data/lib/instana/eum/eum-test.js.erb +0 -17
  83. data/lib/instana/eum/eum.js.erb +0 -17
  84. data/lib/instana/helpers.rb +0 -47
  85. data/lib/instana/opentracing/tracer.rb +0 -21
  86. data/lib/instana/thread_local.rb +0 -18
  87. data/lib/oj_check.rb +0 -19
  88. data/test/agent/agent_test.rb +0 -151
@@ -1,87 +0,0 @@
1
- # (c) Copyright IBM Corp. 2021
2
- # (c) Copyright Instana Inc. 2018
3
-
4
- module AgentHelpers
5
- # Attempts to determine if we're running inside a container.
6
- # The qualifications are:
7
- # 1. Linux based OS
8
- # 2. /proc/self/cpuset exists and contents include a container id
9
- def running_in_container?
10
- return false unless @is_linux
11
-
12
- cpuset_contents = get_cpuset_contents
13
-
14
- if cpuset_contents.nil? or cpuset_contents == '/'
15
- ::Instana.logger.debug "running_in_container? == no"
16
- return false
17
- end
18
- ::Instana.logger.debug "running_in_container? == yes"
19
- true
20
- end
21
-
22
- # Attempts to determine the true process ID by querying the
23
- # /proc/<pid>/sched file. This works on linux currently.
24
- #
25
- def get_sched_pid
26
- sched_file = "/proc/self/sched"
27
- pid = Process.pid
28
-
29
- if File.exist?(sched_file)
30
- v = File.open(sched_file, &:readline)
31
- pid = v.match(/\d+/).to_s.to_i
32
- end
33
- pid
34
- end
35
-
36
- # Open and read /proc/<pid>/cpuset and return as a string. Used as
37
- # part of the announce payload for process differentiation.
38
- #
39
- def get_cpuset_contents
40
- cpuset_file = "/proc/#{Process.pid}/cpuset"
41
- contents = ""
42
-
43
- if File.exist?(cpuset_file)
44
- contents = File.open(cpuset_file, "r").read
45
- end
46
- contents.chomp
47
- rescue Exception => e
48
- Instana.logger.debug { "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" }
49
- return nil
50
- end
51
-
52
- # Returns the PID that we are reporting to
53
- #
54
- def report_pid
55
- @process[:report_pid]
56
- end
57
-
58
- # Determine whether the pid has changed since Agent start.
59
- #
60
- # @ return [Boolean] true or false to indicate if forked
61
- #
62
- def forked?
63
- @process[:pid] != Process.pid
64
- end
65
-
66
- # Indicates if the agent is ready to send metrics
67
- # and/or data.
68
- #
69
- def ready?
70
- # In test, we're always ready :-)
71
- return true if ENV.key?('INSTANA_TEST')
72
-
73
- # Occasionally Run Fork detection
74
- if rand(10) > 8
75
- if !@is_resque_worker && (@process[:pid] != Process.pid)
76
- ::Instana.logger.debug "Instana: detected fork. (this pid: #{Process.pid}/#{Process.ppid}) Calling after_fork"
77
- after_fork
78
- end
79
- end
80
-
81
- @state == :ready || @state == :announced
82
- rescue => e
83
- Instana.logger.debug { "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" }
84
- Instana.logger.debug { e.backtrace.join("\r\n") } unless ENV.key?('INSTANA_TEST')
85
- return false
86
- end
87
- end
@@ -1,44 +0,0 @@
1
- # (c) Copyright IBM Corp. 2021
2
- # (c) Copyright Instana Inc. 2018
3
-
4
- module AgentHooks
5
- # Used post fork to re-initialize state and restart communications with
6
- # the host agent.
7
- #
8
- def after_fork
9
- ::Instana.logger.debug "after_fork hook called. Falling back to unannounced state and spawning a new background agent thread."
10
-
11
- @timers.cancel
12
-
13
- # Reseed the random number generator for this
14
- # new thread.
15
- srand
16
-
17
- transition_to(:unannounced)
18
-
19
- setup
20
- spawn_background_thread
21
- end
22
-
23
- def before_resque_fork
24
- ::Instana.logger.debug "before_resque_fork hook called. pid/ppid: #{Process.pid}/#{Process.ppid}"
25
- @is_resque_worker = true
26
- end
27
-
28
- def after_resque_fork
29
- ::Instana.logger.debug "after_resque_fork hook called. pid/ppid: #{Process.pid}/#{Process.ppid}"
30
-
31
- @timers.cancel
32
-
33
- # Reseed the random number generator for this
34
- # new thread.
35
- srand
36
-
37
- ::Instana.config[:metrics][:enabled] = false
38
-
39
- @process[:pid] = Process.pid
40
-
41
- setup
42
- spawn_background_thread
43
- end
44
- end
@@ -1,51 +0,0 @@
1
- # (c) Copyright IBM Corp. 2021
2
- # (c) Copyright Instana Inc. 2018
3
-
4
- module AgentTasks
5
- # When request(s) are received by the host agent, it is sent here
6
- # for handling & processing.
7
- #
8
- # @param json_string [String] the requests from the host agent
9
- #
10
-
11
- OJ_OPTIONS = {mode: :strict}
12
-
13
- def handle_agent_tasks(json_string)
14
- tasks = Oj.load(json_string, OJ_OPTIONS)
15
-
16
- if tasks.is_a?(Hash)
17
- process_agent_task(tasks)
18
- elsif tasks.is_a?(Array)
19
- tasks.each do |t|
20
- process_agent_task(t)
21
- end
22
- end
23
- end
24
-
25
- # Process a task sent from the host agent.
26
- #
27
- # @param task [String] the request json from the host agent
28
- #
29
- def process_agent_task(task)
30
- if task.key?("action")
31
- if task["action"] == "ruby.source"
32
- payload = ::Instana::Util.get_rb_source(task["args"]["file"])
33
- else
34
- payload = { :error => "Unrecognized action: #{task["action"]}. An newer Instana gem may be required for this. Current version: #{::Instana::VERSION}" }
35
- end
36
- else
37
- payload = { :error => "Instana Ruby: No action specified in request." }
38
- end
39
-
40
- path = "com.instana.plugin.ruby/response.#{@process[:report_pid]}?messageId=#{URI.encode(task['messageId'])}"
41
- uri = URI.parse("http://#{@discovered[:agent_host]}:#{@discovered[:agent_port]}/#{path}")
42
- req = Net::HTTP::Post.new(uri)
43
- req.body = Oj.dump(payload, OJ_OPTIONS)
44
- ::Instana.logger.debug "Responding to agent request: #{req.inspect}"
45
- make_host_agent_request(req)
46
-
47
- rescue StandardError => e
48
- Instana.logger.debug { "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" }
49
- Instana.logger.debug { e.backtrace.join("\r\n") }
50
- end
51
- end
@@ -1,119 +0,0 @@
1
- # (c) Copyright IBM Corp. 2021
2
- # (c) Copyright Instana Inc. 2016
3
-
4
- module Instana
5
- class Collector
6
- attr_accessor :collectors
7
- attr_accessor :last_report_log
8
-
9
- def initialize
10
- @collectors = []
11
-
12
- # Snapshot data is collected once per process but resent
13
- # every 10 minutes along side process metrics.
14
- @snapshot = ::Instana::Util.take_snapshot
15
-
16
- # Set last snapshot to just under 10 minutes ago
17
- # so we send a snapshot sooner than later
18
- @last_snapshot = Time.now - 570
19
-
20
- # We track what we last sent as a metric payload so that
21
- # we can do delta reporting
22
- @last_values = {}
23
- end
24
-
25
- # Register an individual collector.
26
- #
27
- # @param [Object] klass of the collector to register
28
- #
29
- def register(klass)
30
- ::Instana.logger.debug "Adding #{klass} to collectors..."
31
- @collectors << klass.new
32
- end
33
-
34
- # Resets the timer on when to send process snapshot data.
35
- #
36
- def reset_snapshot_timer!
37
- # Set last snapshot to 10 minutes ago
38
- # so that we send a snapshot on first report
39
- @last_snapshot = Time.now - 601
40
- end
41
-
42
- ##
43
- # collect_and_report
44
- #
45
- # Run through each collector, let them collect up
46
- # data and then report what we have via the agent
47
- #
48
- # @return Boolean true on success
49
- #
50
- def collect_and_report
51
- return unless ::Instana.config[:metrics][:enabled]
52
-
53
- payload = {}
54
- with_snapshot = false
55
-
56
- # Run through the registered collectors and
57
- # get all the metrics
58
- #
59
- @collectors.each do |c|
60
- metrics = c.collect
61
- if metrics
62
- payload[c.payload_key] = metrics
63
- else
64
- payload.delete(c.payload_key)
65
- end
66
- end
67
-
68
- # Every 5 minutes, send snapshot data as well
69
- if (Time.now - @last_snapshot) > 600
70
- with_snapshot = true
71
- payload.merge!(@snapshot)
72
-
73
- # Add in process related that could have changed since
74
- # snapshot was taken.
75
- p = { :pid => ::Instana.agent.report_pid }
76
- p[:name] = ::Instana::Util.get_app_name
77
- p[:exec_args] = ::Instana.agent.process[:arguments]
78
- payload.merge!(p)
79
- else
80
- payload = enforce_deltas(payload, @last_values)
81
- end
82
-
83
- if ENV.key?('INSTANA_TEST')
84
- true
85
- else
86
- # Report all the collected goodies
87
- if ::Instana.agent.report_metrics(payload) && with_snapshot
88
- @last_snapshot = Time.now
89
- end
90
- end
91
- end
92
-
93
- # Take two hashes and enforce delta reporting.
94
- # We only report when values change (instead of reporting all of
95
- # the time). This is a recursive method.
96
- #
97
- # @param [Hash] the payload have delta reporting applied to
98
- # @param [Hash] a hash of the last values reported
99
- #
100
- # @return [Hash] the candidate hash with delta reporting applied
101
- #
102
- def enforce_deltas(candidate, last)
103
- candidate.each do |k,v|
104
- if v.is_a?(Hash)
105
- last[k] ||= {}
106
- candidate[k] = enforce_deltas(candidate[k], last[k])
107
- candidate.delete(k) if candidate[k].empty?
108
- else
109
- if last[k] == v
110
- candidate.delete(k)
111
- else
112
- last[k] = candidate[k]
113
- end
114
- end
115
- end
116
- candidate
117
- end
118
- end
119
- end
@@ -1,60 +0,0 @@
1
- # (c) Copyright IBM Corp. 2021
2
- # (c) Copyright Instana Inc. 2016
3
-
4
- module Instana
5
- module Collectors
6
- class GC
7
- attr_accessor :payload_key
8
-
9
- def initialize
10
- @payload_key = :gc
11
- @this_gc = {}
12
- @last_major_count = 0
13
- @last_minor_count = 0
14
- ::GC::Profiler.enable
15
- end
16
-
17
- ##
18
- # collect
19
- #
20
- # To collect garbage collector related metrics.
21
- #
22
- def collect
23
- @this_gc.clear
24
- stats = ::GC.stat
25
-
26
- # Time spent in GC. Report in milliseconds
27
- @this_gc[:totalTime] = ::GC::Profiler.total_time * 1000
28
- ::GC::Profiler.clear
29
-
30
- # GC metrics only available on newer Ruby versions
31
- if RUBY_VERSION >= '2.1'
32
- # GC runs. Calculate how many have occurred since the last call
33
- @this_gc[:minorGcs] = stats[:minor_gc_count] - @last_minor_count
34
- @this_gc[:majorGcs] = stats[:major_gc_count] - @last_major_count
35
-
36
- # Store these counts so that we have something to compare to next
37
- # time around.
38
- @last_major_count = stats[:major_gc_count]
39
- @last_minor_count = stats[:minor_gc_count]
40
-
41
- @this_gc[:heap_live] = stats[:heap_live_slots] || stats[:heap_live_num]
42
- @this_gc[:heap_free] = stats[:heap_free_slots] || stats[:heap_free_num]
43
- else
44
- @this_gc[:heap_live] = stats[:heap_live_slot] || stats[:heap_live_num]
45
- @this_gc[:heap_free] = stats[:heap_free_slot] || stats[:heap_free_num]
46
- end
47
-
48
- @this_gc
49
- rescue => e
50
- ::Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
51
- ::Instana.logger.debug { e.backtrace.join("\r\n") }
52
- end
53
- end
54
- end
55
- end
56
-
57
- # Register the metrics collector if enabled
58
- if ::Instana.config[:metrics][:gc][:enabled]
59
- ::Instana.collector.register(::Instana::Collectors::GC)
60
- end
@@ -1,37 +0,0 @@
1
- # (c) Copyright IBM Corp. 2021
2
- # (c) Copyright Instana Inc. 2016
3
-
4
- require 'get_process_mem'
5
-
6
- module Instana
7
- module Collectors
8
- class Memory
9
- attr_accessor :payload_key
10
-
11
- def initialize
12
- @payload_key = :memory
13
- @this_mem = {}
14
- end
15
-
16
- ##
17
- # collect
18
- #
19
- # To collect process memory usage.
20
- #
21
- # @return [Hash] a collection of metrics (if any)
22
- #
23
- def collect
24
- @this_mem[:rss_size] = ::GetProcessMem.new(Process.pid).kb
25
- @this_mem
26
- rescue => e
27
- ::Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
28
- ::Instana.logger.debug { e.backtrace.join("\r\n") }
29
- end
30
- end
31
- end
32
- end
33
-
34
- # Register the metrics collector if enabled
35
- if ::Instana.config[:metrics][:memory][:enabled]
36
- ::Instana.collector.register(::Instana::Collectors::Memory)
37
- end
@@ -1,33 +0,0 @@
1
- # (c) Copyright IBM Corp. 2021
2
- # (c) Copyright Instana Inc. 2016
3
-
4
- module Instana
5
- module Collectors
6
- class Thread
7
- attr_accessor :payload_key
8
-
9
- def initialize
10
- @payload_key = :thread
11
- @this_count = {}
12
- end
13
-
14
- ##
15
- # collect
16
- #
17
- # To collect thread count
18
- #
19
- def collect
20
- @this_count[:count] = ::Thread.list.count
21
- @this_count
22
- rescue => e
23
- ::Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
24
- ::Instana.logger.debug { e.backtrace.join("\r\n") }
25
- end
26
- end
27
- end
28
- end
29
-
30
- # Register the metrics collector if enabled
31
- if ::Instana.config[:metrics][:thread][:enabled]
32
- ::Instana.collector.register(::Instana::Collectors::Thread)
33
- end
@@ -1,17 +0,0 @@
1
- <script>
2
- (function(c,e,f,k,g,h,b,a,d){c[g]||(c[g]=h,b=c[h]=function(){
3
- b.q.push(arguments)},b.q=[],b.l=1*new Date,a=e.createElement(f),a.async=1,
4
- a.src=k,a.setAttribute("crossorigin", "anonymous"),d=e.getElementsByTagName(f)[0],
5
- d.parentNode.insertBefore(a,d))})(window,document,"script",
6
- "//pink.instana.rocks/eum/eum.min.js","InstanaEumObject","ineum");
7
-
8
- ineum('reportingUrl', 'https://pink.instana.rocks/eum/');
9
- ineum('key', '<%=::Instana.config[:eum_api_key]%>');
10
- ineum('traceId', '<%=::Instana.tracer.trace_id_header%>');
11
-
12
- <% if !::Instana.config[:eum_baggage].empty? %>
13
- <% ::Instana.config[:eum_baggage].each do |k, v| %>
14
- ineum('meta', '<%=k%>', '<%=v%>');
15
- <% end %>
16
- <% end %>
17
- </script>