instana 1.201.0.pre1 → 1.203.2

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +14 -5
  3. data/.github/ISSUE_TEMPLATE/bug.yml +39 -0
  4. data/.github/ISSUE_TEMPLATE/config.yml +5 -0
  5. data/Appraisals +1 -0
  6. data/README.md +1 -1
  7. data/gemfiles/aws_30.gemfile +1 -0
  8. data/lib/instana/activator.rb +2 -0
  9. data/lib/instana/activators/action_mailer.rb +22 -0
  10. data/lib/instana/activators/active_job.rb +21 -0
  11. data/lib/instana/activators/aws_sdk_lambda.rb +20 -0
  12. data/lib/instana/backend/host_agent_reporting_observer.rb +2 -4
  13. data/lib/instana/config.rb +4 -1
  14. data/lib/instana/frameworks/rails.rb +5 -5
  15. data/lib/instana/instrumentation/action_mailer.rb +22 -0
  16. data/lib/instana/instrumentation/active_job.rb +52 -0
  17. data/lib/instana/instrumentation/aws_sdk_lambda.rb +37 -0
  18. data/lib/instana/instrumentation/resque.rb +11 -1
  19. data/lib/instana/instrumented_logger.rb +26 -0
  20. data/lib/instana/serverless.rb +24 -3
  21. data/lib/instana/setup.rb +2 -0
  22. data/lib/instana/tracing/processor.rb +1 -0
  23. data/lib/instana/tracing/span.rb +6 -3
  24. data/lib/instana/version.rb +1 -1
  25. data/test/instrumentation/aws_test.rb +35 -0
  26. data/test/instrumentation/rails_action_mailer_test.rb +37 -0
  27. data/test/instrumentation/rails_active_job_test.rb +65 -0
  28. data/test/instrumentation/rails_active_record_database_missing_test.rb +43 -0
  29. data/test/instrumentation/resque_test.rb +57 -6
  30. data/test/serverless_test.rb +46 -0
  31. data/test/support/apps/resque/jobs/resque_fast_job.rb +3 -1
  32. data/test/test_helper.rb +10 -1
  33. data/test/tracing/instrumented_logger_test.rb +39 -0
  34. metadata +21 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a69d1f908c617f99a74724260ecf5f1d32ed9dc16d3630abf9b93d05a4c3a0b
4
- data.tar.gz: 8dd9c2a52af9267fdb12af599c50e19bc7fed2fe7012dd19f2b61f66234e7489
3
+ metadata.gz: b2eef31bcb3f06d8ec7323f4e9093d6e332f73e101c1faf1f73e5d07a5593512
4
+ data.tar.gz: c5d1af0df01f2c5f99955996cfe6f2fe969f47407522cecb945d47776ea053ee
5
5
  SHA512:
6
- metadata.gz: 1646aca3f210450cb60d00f679737ea54a9b72ab4822c9e60ca2ad012430dd8e05f86dab0e3cc5959276fcf42fe54206b26018ab5f257e361312830bf30824c8
7
- data.tar.gz: 324e040afb6e61d5815dd35599ad0af0cab11be1470b08c95e18fcd99e8e325aec1528689fe1b0f07ad986784428ddff0484a3d92547c4d94885b5744b76ec2d
6
+ metadata.gz: daca4cc08bbe967dbae87795dc90e5b54e72447ee05aa8ceafd1166bc8ada1f873d682c452e83d9bd47fff6fccf9b941adb82476acbf2bc96df110e488261640
7
+ data.tar.gz: 971f5af221ccc75e6ad199e962a34e528cd1adaa07cf1cc7c5681a903cfefb8cf5aa536b97fb708cc0c40b969adc5cb330aa5e8f7c37de65a2bb3c1d6495c3ad
data/.circleci/config.yml CHANGED
@@ -132,12 +132,12 @@ commands:
132
132
  name: Install Depdendecies
133
133
  command: |
134
134
  bundle check || bundle install
135
- run_tests:
135
+ run_sonarqube:
136
136
  steps:
137
137
  - run:
138
- name: Run Tests
138
+ name: Install Java
139
139
  command: |
140
- bundle exec rake
140
+ sudo apt-get install openjdk-11-jdk
141
141
  - run:
142
142
  name: Run SonarQube to capture coverage
143
143
  command: |
@@ -147,8 +147,16 @@ commands:
147
147
  -Dsonar.projectKey=ruby-sensor \
148
148
  -Dsonar.sources=. \
149
149
  -Dsonar.host.url="${SONARQUBE_URL}" \
150
- -Dsonar.login="${SONARQUBE_LOGIN}" \
151
- -Dsonar.ruby.coverage.reportPaths=coverage/coverage.json
150
+ -Dsonar.login="${SONARQUBE_LOGIN}"
151
+ run_tests:
152
+ steps:
153
+ - run:
154
+ name: Run Tests
155
+ command: |
156
+ mkdir _junit
157
+ bundle exec rake
158
+ - store_test_results:
159
+ path: ~/_junit
152
160
  run_rubocop:
153
161
  steps:
154
162
  - run:
@@ -201,6 +209,7 @@ jobs:
201
209
  - checkout
202
210
  - setup
203
211
  - run_rubocop
212
+ - run_sonarqube
204
213
  publish:
205
214
  executor: ruby_27
206
215
  steps:
@@ -0,0 +1,39 @@
1
+ name: Bug Report
2
+ description: File a bug report
3
+ title: "[Bug]: "
4
+ labels: [bug]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thank you for taking the time to fill out this report. Remember that these issues are public and if you need to discuss implementation specific issues securely, please [use our support portal](https://support.instana.com/hc/en-us).
10
+ - type: textarea
11
+ id: problem-description
12
+ attributes:
13
+ label: Problem Description
14
+ description: What was the issue that caused you to file this bug?
15
+ validations:
16
+ required: true
17
+ - type: textarea
18
+ id: mcve
19
+ attributes:
20
+ label: Minimal, Complete, Verifiable, Example
21
+ description: Can you provide steps needed to reproduce this issue outside of your application?
22
+ validations:
23
+ required: false
24
+ - type: textarea
25
+ id: gemfile-lock
26
+ attributes:
27
+ label: Gemfile.lock
28
+ description: Please paste the contents of the Gemfile.lock for the application that was affected by this bug.
29
+ render: shell
30
+ validations:
31
+ required: true
32
+ - type: textarea
33
+ id: ruby-version
34
+ attributes:
35
+ label: Ruby Version
36
+ description: What version of Ruby was the application running under when it encountered this bug?
37
+ render: shell
38
+ validations:
39
+ required: true
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Instana Support Portal
4
+ url: https://support.instana.com
5
+ about: Please ask questions related to your installation there.
data/Appraisals CHANGED
@@ -6,6 +6,7 @@ appraise 'aws-30' do
6
6
  gem 'aws-sdk-s3', '~> 1.59'
7
7
  gem 'aws-sdk-sns', '~> 1.38'
8
8
  gem 'aws-sdk-sqs', '~> 1.36'
9
+ gem 'aws-sdk-lambda', '~> 1.62'
9
10
  end
10
11
 
11
12
  appraise 'cuba-30' do
data/README.md CHANGED
@@ -77,5 +77,5 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/instan
77
77
 
78
78
  ## More
79
79
 
80
- Want to instrument other languages? See our [Node.js](https://github.com/instana/nodejs-sensor), [Go](https://github.com/instana/golang-sensor), [Python](https://github.com/instana/python-sensor) repositories or [many other supported technologies](https://www.instana.com/supported-technologies/).
80
+ Want to instrument other languages? See our [Node.js](https://github.com/instana/nodejs), [Go](https://github.com/instana/golang-sensor), [Python](https://github.com/instana/python-sensor) repositories or [many other supported technologies](https://www.instana.com/supported-technologies/).
81
81
 
@@ -17,5 +17,6 @@ gem "aws-sdk-dynamodb", "~> 1.59"
17
17
  gem "aws-sdk-s3", "~> 1.59"
18
18
  gem "aws-sdk-sns", "~> 1.38"
19
19
  gem "aws-sdk-sqs", "~> 1.36"
20
+ gem "aws-sdk-lambda", "~> 1.62"
20
21
 
21
22
  gemspec path: "../"
@@ -46,11 +46,13 @@ end
46
46
  Dir["#{__dir__}/activators/*.rb"]
47
47
  .sort
48
48
  .select do |f|
49
+ # :nocov:
49
50
  if ENV['INSTANA_ACTIVATE_SET']
50
51
  base = File.basename(f, '.rb')
51
52
  ENV.fetch('INSTANA_ACTIVATE_SET', '').split(',').include?(base)
52
53
  else
53
54
  true
54
55
  end
56
+ # :nocov:
55
57
  end
56
58
  .each { |f| require(f) }
@@ -0,0 +1,22 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ module Instana
5
+ module Activators
6
+ class ActionMailer < Activator
7
+ def can_instrument?
8
+ defined?(::ActionMailer::Base)
9
+ end
10
+
11
+ def instrument
12
+ require 'instana/instrumentation/action_mailer'
13
+
14
+ ::ActionMailer::Base
15
+ .singleton_class
16
+ .prepend(Instana::Instrumentation::ActionMailer)
17
+
18
+ true
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ module Instana
5
+ module Activators
6
+ class ActiveJob < Activator
7
+ def can_instrument?
8
+ defined?(::ActiveJob::Base)
9
+ end
10
+
11
+ def instrument
12
+ require 'instana/instrumentation/active_job'
13
+
14
+ ::ActiveJob::Base
15
+ .prepend(Instana::Instrumentation::ActiveJob)
16
+
17
+ true
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ module Instana
5
+ module Activators
6
+ class AwsSdkLambda < Activator
7
+ def can_instrument?
8
+ defined?(::Aws::Lambda::Client) && ::Aws::Lambda::Client.respond_to?(:add_plugin)
9
+ end
10
+
11
+ def instrument
12
+ require 'instana/instrumentation/aws_sdk_lambda'
13
+
14
+ ::Aws::Lambda::Client.add_plugin(Instana::Instrumentation::Lambda)
15
+
16
+ true
17
+ end
18
+ end
19
+ end
20
+ end
@@ -49,11 +49,10 @@ module Instana
49
49
  response = @client.send_request('POST', path, spans)
50
50
 
51
51
  unless response.ok?
52
+ @logger.debug("Sent `#{spans.count}` spans to `#{path}` and got `#{response.code}`.")
52
53
  @discovery.swap { nil }
53
54
  break
54
55
  end
55
-
56
- @logger.debug("Sent `#{spans.count}` spans to `#{path}` and got `#{response.code}`.")
57
56
  end
58
57
  end
59
58
 
@@ -68,10 +67,9 @@ module Instana
68
67
  if response.ok?
69
68
  handle_agent_tasks(response, discovery) unless response.body.empty?
70
69
  else
70
+ @logger.debug("Sent `#{payload}` to `#{path}` and got `#{response.code}`.")
71
71
  @discovery.swap { nil }
72
72
  end
73
-
74
- @logger.debug("Sent `#{payload}` to `#{path}` and got `#{response.code}`.")
75
73
  end
76
74
 
77
75
  def handle_agent_tasks(response, discovery)
@@ -27,6 +27,9 @@ module Instana
27
27
  # Enable/disable tracing (default: enabled)
28
28
  @config[:tracing] = { :enabled => true }
29
29
 
30
+ # Enable/Disable logging
31
+ @config[:logging] = { :enabled => true }
32
+
30
33
  # Collector interval
31
34
  @config[:collector] = { :enabled => true, :interval => 1 }
32
35
 
@@ -64,7 +67,7 @@ module Instana
64
67
  @config[:graphql] = { :enabled => true }
65
68
  @config[:nethttp] = { :enabled => true }
66
69
  @config[:redis] = { :enabled => true }
67
- @config[:'resque-client'] = { :enabled => true }
70
+ @config[:'resque-client'] = { :enabled => true, :propagate => true }
68
71
  @config[:'resque-worker'] = { :enabled => true, :'setup-fork' => true }
69
72
  @config[:'rest-client'] = { :enabled => true }
70
73
  @config[:'sidekiq-client'] = { :enabled => true }
@@ -3,9 +3,6 @@
3
3
 
4
4
  if ::Rails::VERSION::MAJOR < 3
5
5
  ::Rails.configuration.after_initialize do
6
- # In Rails, let's use the Rails logger
7
- ::Instana.logger = ::Rails.logger if ::Rails.logger
8
-
9
6
  if ::Instana.config[:tracing][:enabled]
10
7
  ::Instana.logger.debug "Instrumenting Rack"
11
8
  ::Rails.configuration.middleware.insert 0, ::Instana::Rack
@@ -17,8 +14,11 @@ else
17
14
  module ::Instana
18
15
  class Railtie < ::Rails::Railtie
19
16
  initializer 'instana.rack' do |app|
20
- # In Rails, let's use the Rails logger
21
- ::Instana.logger = ::Rails.logger if ::Rails.logger
17
+ # Configure the Instrumented Logger
18
+ if ::Instana.config[:logging][:enabled] && !ENV.key?('INSTANA_TEST')
19
+ logger = ::Instana::InstrumentedLogger.new('/dev/null')
20
+ Rails.logger.extend(ActiveSupport::Logger.broadcast(logger))
21
+ end
22
22
 
23
23
  if ::Instana.config[:tracing][:enabled]
24
24
  ::Instana.logger.debug "Instrumenting Rack"
@@ -0,0 +1,22 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ module Instana
5
+ module Instrumentation
6
+ module ActionMailer
7
+ def method_missing(method_name, *args) # rubocop:disable Style/MissingRespondToMissing
8
+ if action_methods.include?(method_name.to_s)
9
+ tags = {
10
+ actionmailer: {
11
+ class: to_s,
12
+ method: method_name.to_s
13
+ }
14
+ }
15
+ Instana::Tracer.trace(:'mail.actionmailer', tags) { super }
16
+ else
17
+ super
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,52 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ module Instana
5
+ module Instrumentation
6
+ module ActiveJob
7
+ def self.prepended(target)
8
+ target.around_enqueue do |job, block|
9
+ tags = {
10
+ activejob: {
11
+ queue: job.queue_name,
12
+ job: job.class.to_s,
13
+ action: :enqueue,
14
+ job_id: job.job_id
15
+ }
16
+ }
17
+
18
+ ::Instana::Tracer.trace(:activejob, tags) do
19
+ context = ::Instana.tracer.context
20
+ job.arguments = [{
21
+ given_arguments: job.arguments,
22
+ instana_context: context ? context.to_hash : nil
23
+ }]
24
+
25
+ block.call
26
+ end
27
+ end
28
+
29
+ target.around_perform do |job, block|
30
+ tags = {
31
+ activejob: {
32
+ queue: job.queue_name,
33
+ job: job.class.to_s,
34
+ action: :perform,
35
+ job_id: job.job_id
36
+ }
37
+ }
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
43
+ end
44
+
45
+ ::Instana::Tracer.start_or_continue_trace(:activejob, tags, incoming_context) do
46
+ block.call
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,37 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+ require 'base64'
4
+
5
+ module Instana
6
+ module Instrumentation
7
+ class Lambda < Seahorse::Client::Plugin
8
+ class Handler < Seahorse::Client::Handler
9
+ def call(context)
10
+ return @handler.call(context) unless [:invoke_async, :invoke].include?(context.operation_name)
11
+
12
+ if context.params[:client_context].nil? && ::Instana.tracer.tracing? && context.operation_name == :invoke
13
+ span_context = ::Instana.tracer.context
14
+ payload = {
15
+ 'X-INSTANA-T' => span_context.trace_id,
16
+ 'X-INSTANA-S' => span_context.span_id,
17
+ 'X-INSTANA-L' => span_context.level.to_s
18
+ }
19
+
20
+ context.params[:client_context] = JSON.dump(payload)
21
+ end
22
+
23
+ tags = {
24
+ function: context.params[:function_name],
25
+ type: context.params[:invocation_type]
26
+ }.reject { |_, v| v.nil? }
27
+
28
+ ::Instana.tracer.trace(:"aws.lambda.invoke", {aws: {lambda: {invoke: tags}}}) { @handler.call(context) }
29
+ end
30
+ end
31
+
32
+ def add_handlers(handlers, _config)
33
+ handlers.add(Handler, step: :initialize)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -28,6 +28,7 @@ module Instana
28
28
  kvs = collect_kvs(:enqueue, klass, args)
29
29
 
30
30
  Instana.tracer.trace(:'resque-client', kvs) do
31
+ args.push(::Instana.tracer.context.to_hash) if ::Instana.config[:'resque-client'][:propagate]
31
32
  super(klass, *args)
32
33
  end
33
34
  else
@@ -41,6 +42,7 @@ module Instana
41
42
  kvs[:Queue] = queue.to_s if queue
42
43
 
43
44
  Instana.tracer.trace(:'resque-client', kvs) do
45
+ args.push(::Instana.tracer.context.to_hash) if ::Instana.config[:'resque-client'][:propagate]
44
46
  super(queue, klass, *args)
45
47
  end
46
48
  else
@@ -76,7 +78,15 @@ module Instana
76
78
  ::Instana.logger.debug { "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" } if Instana::Config[:verbose]
77
79
  end
78
80
 
79
- Instana.tracer.start_or_continue_trace(:'resque-worker', kvs) do
81
+ trace_context = if ::Instana.config[:'resque-client'][:propagate] && job.payload['args'][-1].is_a?(Hash) && job.payload['args'][-1].keys.include?('trace_id')
82
+ context_from_wire = job.payload['args'].pop
83
+ ::Instana::SpanContext.new(
84
+ context_from_wire['trace_id'],
85
+ context_from_wire['span_id']
86
+ )
87
+ end
88
+
89
+ Instana.tracer.start_or_continue_trace(:'resque-worker', kvs, trace_context) do
80
90
  super(job)
81
91
  end
82
92
  end
@@ -0,0 +1,26 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ module Instana
5
+ class InstrumentedLogger < Logger
6
+ LEVEL_LABELS = %w[Debug Info Warn Error Fatal Any].freeze
7
+
8
+ def instana_log_level
9
+ WARN
10
+ end
11
+
12
+ def add(severity, message = nil, progname = nil)
13
+ severity ||= UNKNOWN
14
+
15
+ if severity >= instana_log_level && ::Instana.tracer.tracing?
16
+ tags = {
17
+ level: LEVEL_LABELS[severity],
18
+ message: "#{message} #{progname}".strip
19
+ }
20
+ Instana::Tracer.trace(:log, {log: tags}) {}
21
+ end
22
+
23
+ super(severity, message, progname)
24
+ end
25
+ end
26
+ end
@@ -23,7 +23,7 @@ module Instana
23
23
 
24
24
  def wrap_aws(event, context, &block)
25
25
  Thread.current[:instana_function_arn] = [context.invoked_function_arn, context.function_version].join(':')
26
- trigger, event_tags, span_context = trigger_from_event(event)
26
+ trigger, event_tags, span_context = trigger_from_event(event, context)
27
27
 
28
28
  tags = {
29
29
  lambda: {
@@ -53,7 +53,7 @@ module Instana
53
53
 
54
54
  private
55
55
 
56
- def trigger_from_event(event) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
56
+ def trigger_from_event(event, context) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
57
57
  case event
58
58
  when ->(e) { defined?(::Instana::InstrumentedRequest) && e.is_a?(Hash) && e.key?('requestContext') && e['requestContext'].key?('elb') }
59
59
  request = InstrumentedRequest.new(event_to_rack(event))
@@ -74,7 +74,28 @@ module Instana
74
74
  tags = decode_sqs(event)
75
75
  ['aws:sqs', {sqs: tags}, {}]
76
76
  else
77
- ['aws:api.gateway.noproxy', {}, {}]
77
+ ctx = context_from_lambda_context(context)
78
+ if ctx.empty?
79
+ ['aws:api.gateway.noproxy', {}, {}]
80
+ else
81
+ ['aws.lambda.invoke', {}, ctx]
82
+ end
83
+ end
84
+ end
85
+
86
+ def context_from_lambda_context(context)
87
+ return {} unless context.client_context
88
+
89
+ begin
90
+ context = JSON.parse(Base64.decode64(context.client_context))
91
+
92
+ {
93
+ trace_id: context['X-INSTANA-T'],
94
+ span_id: context['X-INSTANA-S'],
95
+ level: Integer(context['X-INSTANA-L'])
96
+ }
97
+ rescue TypeError, JSON::ParserError, NoMethodError => _e
98
+ {}
78
99
  end
79
100
  end
80
101
 
data/lib/instana/setup.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  # (c) Copyright IBM Corp. 2021
2
2
  # (c) Copyright Instana Inc. 2016
3
3
 
4
+ require 'logger'
4
5
  require 'concurrent'
5
6
  require 'sys-proctable'
6
7
 
7
8
  require 'instana/logger_delegator'
9
+ require 'instana/instrumented_logger'
8
10
 
9
11
  require "instana/base"
10
12
  require "instana/config"
@@ -2,6 +2,7 @@
2
2
  # (c) Copyright Instana Inc. 2016
3
3
 
4
4
  require 'thread'
5
+ require 'forwardable'
5
6
 
6
7
  module Instana
7
8
  class Processor
@@ -6,10 +6,13 @@ module Instana
6
6
  REGISTERED_SPANS = [ :actioncontroller, :actionview, :activerecord, :excon,
7
7
  :memcache, :'net-http', :rack, :render, :'rpc-client',
8
8
  :'rpc-server', :'sidekiq-client', :'sidekiq-worker',
9
- :redis, :'resque-client', :'resque-worker', :'graphql.server', :dynamodb, :s3, :sns, :sqs, :'aws.lambda.entry' ].freeze
10
- ENTRY_SPANS = [ :rack, :'resque-worker', :'rpc-server', :'sidekiq-worker', :'graphql.server', :sqs, :'aws.lambda.entry' ].freeze
9
+ :redis, :'resque-client', :'resque-worker', :'graphql.server', :dynamodb, :s3, :sns, :sqs, :'aws.lambda.entry', :activejob, :log, :"mail.actionmailer",
10
+ :"aws.lambda.invoke" ].freeze
11
+ ENTRY_SPANS = [ :rack, :'resque-worker', :'rpc-server', :'sidekiq-worker', :'graphql.server', :sqs,
12
+ :'aws.lambda.entry' ].freeze
11
13
  EXIT_SPANS = [ :activerecord, :excon, :'net-http', :'resque-client',
12
- :'rpc-client', :'sidekiq-client', :redis, :dynamodb, :s3, :sns, :sqs ].freeze
14
+ :'rpc-client', :'sidekiq-client', :redis, :dynamodb, :s3, :sns, :sqs, :log, :"mail.actionmailer",
15
+ :"aws.lambda.invoke" ].freeze
13
16
  HTTP_SPANS = [ :rack, :excon, :'net-http' ].freeze
14
17
 
15
18
  attr_accessor :parent
@@ -2,6 +2,6 @@
2
2
  # (c) Copyright Instana Inc. 2016
3
3
 
4
4
  module Instana
5
- VERSION = "1.201.0.pre1"
5
+ VERSION = "1.203.2"
6
6
  VERSION_FULL = "instana-#{VERSION}"
7
7
  end
@@ -158,4 +158,39 @@ class AwsTest < Minitest::Test
158
158
  assert_equal send_span[:s], message.message_attributes['X_INSTANA_S'].string_value
159
159
  assert_equal 'Sample', message.body
160
160
  end
161
+
162
+ def test_lambda
163
+ stub_request(:post, "https://lambda.local.amazonaws.com/2015-03-31/functions/Test/invocations")
164
+ .with(
165
+ body: "data",
166
+ headers: {
167
+ 'X-Amz-Client-Context' => /.+/
168
+ }
169
+ )
170
+ .to_return(status: 200, body: "", headers: {})
171
+
172
+ lambda = Aws::Lambda::Client.new(
173
+ endpoint: 'https://lambda.local.amazonaws.com',
174
+ region: 'local',
175
+ access_key_id: "test",
176
+ secret_access_key: "test"
177
+ )
178
+
179
+ Instana::Tracer.start_or_continue_trace(:lambda_test, {}) do
180
+ lambda.invoke(
181
+ function_name: 'Test',
182
+ invocation_type: 'Event',
183
+ payload: 'data'
184
+ )
185
+ end
186
+
187
+ spans = ::Instana.processor.queued_spans
188
+ lambda_span, _entry_span, *rest = spans
189
+
190
+ assert rest.empty?
191
+
192
+ assert_equal :"aws.lambda.invoke", lambda_span[:n]
193
+ assert_equal 'Test', lambda_span[:data][:aws][:lambda][:invoke][:function]
194
+ assert_equal 'Event', lambda_span[:data][:aws][:lambda][:invoke][:type]
195
+ end
161
196
  end
@@ -0,0 +1,37 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ require 'test_helper'
5
+ require 'action_mailer'
6
+
7
+ class RailsActionMailerTest < Minitest::Test
8
+ class TestMailer < ActionMailer::Base
9
+ def sample_email
10
+ mail(
11
+ from: 'test@example.com',
12
+ to: 'test@example.com',
13
+ subject: 'Test Email',
14
+ body: 'Hello',
15
+ content_type: "text/html"
16
+ )
17
+ end
18
+ end
19
+
20
+ def setup
21
+ TestMailer.delivery_method = :sendmail
22
+
23
+ clear_all!
24
+ end
25
+
26
+ def test_mailer
27
+ Instana.tracer.start_or_continue_trace(:test) do
28
+ TestMailer.sample_email.deliver_now
29
+ end
30
+
31
+ mail_span, = *::Instana.processor.queued_spans
32
+
33
+ assert_equal :"mail.actionmailer", mail_span[:n]
34
+ assert_equal 'RailsActionMailerTest::TestMailer', mail_span[:data][:actionmailer][:class]
35
+ assert_equal 'sample_email', mail_span[:data][:actionmailer][:method]
36
+ end
37
+ end
@@ -0,0 +1,65 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ require 'test_helper'
5
+
6
+ require 'rails'
7
+ require 'active_job'
8
+
9
+ class RailsActiveJobTest < Minitest::Test
10
+ class SampleJob < ActiveJob::Base
11
+ queue_as :test_queue
12
+
13
+ def perform(*args); end
14
+ end
15
+
16
+ def setup
17
+ @test_adapter = ActiveJob::Base.queue_adapter = ActiveJob::QueueAdapters::TestAdapter.new
18
+ ActiveJob::Base.logger = Logger.new('/dev/null')
19
+
20
+ clear_all!
21
+ end
22
+
23
+ def test_perform_now
24
+ SampleJob.perform_now("test_perform_now")
25
+ spans = ::Instana.processor.queued_spans
26
+
27
+ server_span, *rest = spans
28
+ assert_equal [], rest
29
+
30
+ assert_equal :activejob, server_span[:n]
31
+ assert_equal 'RailsActiveJobTest::SampleJob', server_span[:data][:activejob][:job]
32
+ assert_equal :perform, server_span[:data][:activejob][:action]
33
+ assert_equal 'test_queue', server_span[:data][:activejob][:queue]
34
+ end
35
+
36
+ def test_enqueue_perform
37
+ # ActiveJob::QueueAdapters::TestAdapter.new doesn't work for this test on any version less than 6
38
+ skip unless Rails::VERSION::MAJOR >= 6
39
+
40
+ Instana.tracer.start_or_continue_trace(:peform_test) do
41
+ SampleJob.perform_later("test_enqueue_perform")
42
+ end
43
+
44
+ job, *rest_jobs = @test_adapter.enqueued_jobs
45
+ assert_equal [], rest_jobs
46
+
47
+ ActiveJob::Base.execute(job)
48
+
49
+ spans = ::Instana.processor.queued_spans
50
+ client_span, _test_span, server_span, *rest = spans
51
+ assert_equal [], rest
52
+
53
+ assert_equal :activejob, server_span[:n]
54
+ assert_equal 'RailsActiveJobTest::SampleJob', server_span[:data][:activejob][:job]
55
+ assert_equal :perform, server_span[:data][:activejob][:action]
56
+
57
+ assert_equal :activejob, client_span[:n]
58
+ assert_equal 'RailsActiveJobTest::SampleJob', client_span[:data][:activejob][:job]
59
+ assert_equal :enqueue, client_span[:data][:activejob][:action]
60
+ assert_equal 'test_queue', server_span[:data][:activejob][:queue]
61
+
62
+ assert_equal client_span[:t], server_span[:t]
63
+ assert_equal client_span[:s], server_span[:p]
64
+ end
65
+ end
@@ -0,0 +1,43 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ require 'test_helper'
5
+ require 'support/apps/active_record/active_record'
6
+ require 'fileutils'
7
+
8
+ class RailsActiveRecordDatabaseMissingTest < Minitest::Test
9
+ def setup
10
+ skip unless ENV['DATABASE_URL']
11
+
12
+ @old_url = ENV['DATABASE_URL']
13
+ SQLite3::Database.new('/tmp/test.db')
14
+ ENV['DATABASE_URL'] = 'sqlite3:///tmp/test.db'
15
+
16
+ @connection = ActiveRecord::Base.establish_connection(ENV['DATABASE_URL'])
17
+ ActiveRecord::Migration.suppress_messages do
18
+ ActiveRecord::Migration.run(CreateBlocks, direction: :up)
19
+ end
20
+ end
21
+
22
+ def teardown
23
+ ActiveRecord::Base.remove_connection(@connection)
24
+ ENV['DATABASE_URL'] = @old_url
25
+ end
26
+
27
+ def test_error_on_missing_database
28
+ assert_raises(ActiveRecord::StatementInvalid) do
29
+ Instana::Tracer.start_or_continue_trace(:ar_test, {}) do
30
+ b = Block.new
31
+ FileUtils.rm('/tmp/test.db')
32
+ b.save!
33
+ end
34
+ end
35
+
36
+ spans = ::Instana.processor.queued_spans
37
+ assert_equal 3, spans.length
38
+ span = find_first_span_by_name(spans, :activerecord)
39
+
40
+ assert_equal 1, span[:ec]
41
+ assert span[:data][:activerecord][:error].include?("SQLite3::ReadOnlyException: attempt to write a readonly database")
42
+ end
43
+ end
@@ -22,6 +22,7 @@ class ResqueClientTest < Minitest::Test
22
22
  ::Resque.enqueue(FastJob)
23
23
  end
24
24
 
25
+ resque_job = Resque.reserve('critical')
25
26
  spans = ::Instana.processor.queued_spans
26
27
  assert_equal 2, spans.length
27
28
 
@@ -34,6 +35,9 @@ class ResqueClientTest < Minitest::Test
34
35
  assert_equal "FastJob", resque_span[:data][:'resque-client'][:job]
35
36
  assert_equal :critical, resque_span[:data][:'resque-client'][:queue]
36
37
  assert_equal false, resque_span[:data][:'resque-client'].key?(:error)
38
+
39
+ assert_equal resque_job.args.first['trace_id'], resque_span[:t]
40
+ assert_equal resque_job.args.first['span_id'], resque_span[:s]
37
41
  end
38
42
 
39
43
  def test_enqueue_to
@@ -41,6 +45,7 @@ class ResqueClientTest < Minitest::Test
41
45
  ::Resque.enqueue_to(:critical, FastJob)
42
46
  end
43
47
 
48
+ resque_job = Resque.reserve('critical')
44
49
  spans = ::Instana.processor.queued_spans
45
50
  assert_equal 2, spans.length
46
51
 
@@ -52,6 +57,9 @@ class ResqueClientTest < Minitest::Test
52
57
  assert_equal "FastJob", resque_span[:data][:'resque-client'][:job]
53
58
  assert_equal :critical, resque_span[:data][:'resque-client'][:queue]
54
59
  assert_equal false, resque_span[:data][:'resque-client'].key?(:error)
60
+
61
+ assert_equal resque_job.args.first['trace_id'], resque_span[:t]
62
+ assert_equal resque_job.args.first['span_id'], resque_span[:s]
55
63
  end
56
64
 
57
65
  def test_dequeue
@@ -73,17 +81,58 @@ class ResqueClientTest < Minitest::Test
73
81
  end
74
82
 
75
83
  def test_worker_job
76
- Resque::Job.create(:critical, FastJob)
77
- @worker.work(0)
84
+ ::Instana.tracer.start_or_continue_trace(:'resque-client_test') do
85
+ ::Resque.enqueue_to(:critical, FastJob)
86
+ end
87
+
88
+ resque_job = Resque.reserve('critical')
89
+ @worker.work_one_job(resque_job)
90
+
91
+ spans = ::Instana.processor.queued_spans
92
+ assert_equal 5, spans.length
93
+
94
+ client_span = spans[0]
95
+ resque_span = spans[4]
96
+ redis1_span = spans[3]
97
+ redis2_span = spans[2]
98
+
99
+ assert_equal :'resque-client', client_span[:n]
100
+
101
+ assert_equal :'resque-worker', resque_span[:n]
102
+ assert_equal client_span[:s], resque_span[:p]
103
+ assert_equal false, resque_span.key?(:error)
104
+ assert_equal false, resque_span.key?(:ec)
105
+ assert_equal "FastJob", resque_span[:data][:'resque-worker'][:job]
106
+ assert_equal "critical", resque_span[:data][:'resque-worker'][:queue]
107
+ assert_equal false, resque_span[:data][:'resque-worker'].key?(:error)
108
+
109
+ assert_equal :redis, redis1_span[:n]
110
+ assert_equal "SET", redis1_span[:data][:redis][:command]
111
+ assert_equal :redis, redis2_span[:n]
112
+ assert_equal "SET", redis2_span[:data][:redis][:command]
113
+ end
114
+
115
+ def test_worker_job_no_propagate
116
+ ::Instana.config[:'resque-client'][:propagate] = false
117
+ ::Instana.tracer.start_or_continue_trace(:'resque-client_test') do
118
+ ::Resque.enqueue_to(:critical, FastJob)
119
+ end
120
+
121
+ resque_job = Resque.reserve('critical')
122
+ @worker.work_one_job(resque_job)
78
123
 
79
124
  spans = ::Instana.processor.queued_spans
80
- assert_equal 3, spans.length
125
+ assert_equal 5, spans.length
126
+
127
+ client_span = spans[0]
128
+ resque_span = spans[4]
129
+ redis1_span = spans[3]
130
+ redis2_span = spans[2]
81
131
 
82
- resque_span = spans[2]
83
- redis1_span = spans[1]
84
- redis2_span = spans[0]
132
+ assert_equal :'resque-client', client_span[:n]
85
133
 
86
134
  assert_equal :'resque-worker', resque_span[:n]
135
+ refute_equal client_span[:s], resque_span[:p]
87
136
  assert_equal false, resque_span.key?(:error)
88
137
  assert_equal false, resque_span.key?(:ec)
89
138
  assert_equal "FastJob", resque_span[:data][:'resque-worker'][:job]
@@ -94,6 +143,8 @@ class ResqueClientTest < Minitest::Test
94
143
  assert_equal "SET", redis1_span[:data][:redis][:command]
95
144
  assert_equal :redis, redis2_span[:n]
96
145
  assert_equal "SET", redis2_span[:data][:redis][:command]
146
+ ensure
147
+ ::Instana.config[:'resque-client'][:propagate] = true
97
148
  end
98
149
 
99
150
  def test_worker_error_job
@@ -320,4 +320,50 @@ class ServerlessTest < Minitest::Test
320
320
 
321
321
  assert_equal 'test_arn', data[:messages].first[:queue]
322
322
  end
323
+
324
+ def test_lambda_client_context
325
+ clear_all!
326
+
327
+ mock_context = OpenStruct.new(
328
+ invoked_function_arn: 'test_arn',
329
+ function_name: 'test_function',
330
+ function_version: '$TEST',
331
+ client_context: "eyJYLUlOU1RBTkEtVCI6IjEyMyIsIlgtSU5TVEFOQS1TIjoiNDU2IiwiWC1J\nTlNUQU5BLUwiOiIxIn0=\n"
332
+ )
333
+ mock_event = {
334
+ "Invoked" => true
335
+ }
336
+
337
+ @subject.wrap_aws(mock_event, mock_context) { 0 }
338
+
339
+ lambda_span, *rest = Instana.processor.queued_spans
340
+ assert rest.empty?
341
+
342
+ assert_equal 'aws.lambda.invoke', lambda_span[:data][:lambda][:trigger]
343
+ assert_equal '123', lambda_span[:t]
344
+ assert_equal '456', lambda_span[:p]
345
+ end
346
+
347
+ def test_lambda_client_context_error
348
+ clear_all!
349
+
350
+ mock_context = OpenStruct.new(
351
+ invoked_function_arn: 'test_arn',
352
+ function_name: 'test_function',
353
+ function_version: '$TEST',
354
+ client_context: "eyJYLUlOU1RBkEtVCI6IjEyMyIsIlgtSU5TVEFOQS1TIjoiNDU2IiwiWC1J\nTlNUQU5BLUwiOiIxIn0=\n"
355
+ )
356
+ mock_event = {
357
+ "Invoked" => true
358
+ }
359
+
360
+ @subject.wrap_aws(mock_event, mock_context) { 0 }
361
+
362
+ lambda_span, *rest = Instana.processor.queued_spans
363
+ assert rest.empty?
364
+
365
+ refute_equal 'aws.lambda.invoke', lambda_span[:data][:lambda][:trigger]
366
+ refute_equal '123', lambda_span[:t]
367
+ refute_equal '456', lambda_span[:p]
368
+ end
323
369
  end
@@ -7,7 +7,9 @@ require "net/http"
7
7
  class FastJob
8
8
  @queue = :critical
9
9
 
10
- def self.perform
10
+ def self.perform(*args)
11
+ raise 'Invalid Args' unless args.empty?
12
+
11
13
  if ENV.key?('REDIS_URL')
12
14
  redis = Redis.new(:url => ENV['REDIS_URL'])
13
15
  elsif ENV.key?('REDIS_URL')
data/test/test_helper.rb CHANGED
@@ -50,5 +50,14 @@ WebMock.disable_net_connect!(
50
50
 
51
51
  Dir['test/support/*.rb'].each { |f| load(f) }
52
52
 
53
- Minitest::Reporters.use! MiniTest::Reporters::SpecReporter.new
53
+ if ENV['CI']
54
+ Minitest::Reporters.use!([
55
+ Minitest::Reporters::JUnitReporter.new('_junit', false),
56
+ Minitest::Reporters::SpecReporter.new
57
+ ])
58
+ else
59
+ Minitest::Reporters.use!([
60
+ MiniTest::Reporters::SpecReporter.new
61
+ ])
62
+ end
54
63
  Minitest::Test.include(Instana::TestHelpers)
@@ -0,0 +1,39 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ require 'test_helper'
5
+
6
+ class InstrumentedLoggerTest < Minitest::Test
7
+ def setup
8
+ clear_all!
9
+ end
10
+
11
+ def test_log_warn_error
12
+ subject = Instana::InstrumentedLogger.new('/dev/null')
13
+
14
+ Instana::Tracer.start_or_continue_trace(:test_logging) do
15
+ subject.warn('warn')
16
+ subject.debug('test')
17
+ subject.error('error')
18
+ end
19
+
20
+ spans = ::Instana.processor.queued_spans
21
+
22
+ warn_span, error_span, = *spans
23
+
24
+ assert_equal :log, warn_span[:n]
25
+ assert_equal 'warn', warn_span[:data][:log][:message]
26
+ assert_equal 'Warn', warn_span[:data][:log][:level]
27
+
28
+ assert_equal :log, error_span[:n]
29
+ assert_equal 'error', error_span[:data][:log][:message]
30
+ assert_equal 'Error', error_span[:data][:log][:level]
31
+ end
32
+
33
+ def test_no_trace
34
+ subject = Instana::InstrumentedLogger.new('/dev/null')
35
+ subject.warn('warn')
36
+
37
+ assert_equal [], ::Instana.processor.queued_spans
38
+ end
39
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: instana
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.201.0.pre1
4
+ version: 1.203.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Giacomo Lombardo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-08 00:00:00.000000000 Z
11
+ date: 2021-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -135,6 +135,8 @@ files:
135
135
  - ".codeclimate.yml"
136
136
  - ".editorconfig"
137
137
  - ".fasterer.yml"
138
+ - ".github/ISSUE_TEMPLATE/bug.yml"
139
+ - ".github/ISSUE_TEMPLATE/config.yml"
138
140
  - ".gitignore"
139
141
  - ".rubocop.yml"
140
142
  - ".rubocop_todo.yml"
@@ -182,9 +184,12 @@ files:
182
184
  - lib/instana/activators/action_cable.rb
183
185
  - lib/instana/activators/action_controller_api.rb
184
186
  - lib/instana/activators/action_controller_base.rb
187
+ - lib/instana/activators/action_mailer.rb
185
188
  - lib/instana/activators/action_view.rb
189
+ - lib/instana/activators/active_job.rb
186
190
  - lib/instana/activators/active_record.rb
187
191
  - lib/instana/activators/aws_sdk_dynamodb.rb
192
+ - lib/instana/activators/aws_sdk_lambda.rb
188
193
  - lib/instana/activators/aws_sdk_s3.rb
189
194
  - lib/instana/activators/aws_sdk_sns.rb
190
195
  - lib/instana/activators/aws_sdk_sqs.rb
@@ -223,9 +228,12 @@ files:
223
228
  - lib/instana/frameworks/sinatra.rb
224
229
  - lib/instana/instrumentation/action_cable.rb
225
230
  - lib/instana/instrumentation/action_controller.rb
231
+ - lib/instana/instrumentation/action_mailer.rb
226
232
  - lib/instana/instrumentation/action_view.rb
233
+ - lib/instana/instrumentation/active_job.rb
227
234
  - lib/instana/instrumentation/active_record.rb
228
235
  - lib/instana/instrumentation/aws_sdk_dynamodb.rb
236
+ - lib/instana/instrumentation/aws_sdk_lambda.rb
229
237
  - lib/instana/instrumentation/aws_sdk_s3.rb
230
238
  - lib/instana/instrumentation/aws_sdk_sns.rb
231
239
  - lib/instana/instrumentation/aws_sdk_sqs.rb
@@ -242,6 +250,7 @@ files:
242
250
  - lib/instana/instrumentation/shoryuken.rb
243
251
  - lib/instana/instrumentation/sidekiq-client.rb
244
252
  - lib/instana/instrumentation/sidekiq-worker.rb
253
+ - lib/instana/instrumented_logger.rb
245
254
  - lib/instana/logger_delegator.rb
246
255
  - lib/instana/open_tracing/carrier.rb
247
256
  - lib/instana/open_tracing/instana_tracer.rb
@@ -293,7 +302,10 @@ files:
293
302
  - test/instrumentation/rack_test.rb
294
303
  - test/instrumentation/rails_action_cable_test.rb
295
304
  - test/instrumentation/rails_action_controller_test.rb
305
+ - test/instrumentation/rails_action_mailer_test.rb
296
306
  - test/instrumentation/rails_action_view_test.rb
307
+ - test/instrumentation/rails_active_job_test.rb
308
+ - test/instrumentation/rails_active_record_database_missing_test.rb
297
309
  - test/instrumentation/rails_active_record_test.rb
298
310
  - test/instrumentation/redis_test.rb
299
311
  - test/instrumentation/resque_test.rb
@@ -331,6 +343,7 @@ files:
331
343
  - test/test_helper.rb
332
344
  - test/tracing/custom_test.rb
333
345
  - test/tracing/id_management_test.rb
346
+ - test/tracing/instrumented_logger_test.rb
334
347
  - test/tracing/opentracing_test.rb
335
348
  - test/tracing/processor_test.rb
336
349
  - test/tracing/span_context_test.rb
@@ -357,9 +370,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
357
370
  version: '2.1'
358
371
  required_rubygems_version: !ruby/object:Gem::Requirement
359
372
  requirements:
360
- - - ">"
373
+ - - ">="
361
374
  - !ruby/object:Gem::Version
362
- version: 1.3.1
375
+ version: '0'
363
376
  requirements: []
364
377
  rubygems_version: 3.1.6
365
378
  signing_key:
@@ -393,7 +406,10 @@ test_files:
393
406
  - test/instrumentation/rack_test.rb
394
407
  - test/instrumentation/rails_action_cable_test.rb
395
408
  - test/instrumentation/rails_action_controller_test.rb
409
+ - test/instrumentation/rails_action_mailer_test.rb
396
410
  - test/instrumentation/rails_action_view_test.rb
411
+ - test/instrumentation/rails_active_job_test.rb
412
+ - test/instrumentation/rails_active_record_database_missing_test.rb
397
413
  - test/instrumentation/rails_active_record_test.rb
398
414
  - test/instrumentation/redis_test.rb
399
415
  - test/instrumentation/resque_test.rb
@@ -431,6 +447,7 @@ test_files:
431
447
  - test/test_helper.rb
432
448
  - test/tracing/custom_test.rb
433
449
  - test/tracing/id_management_test.rb
450
+ - test/tracing/instrumented_logger_test.rb
434
451
  - test/tracing/opentracing_test.rb
435
452
  - test/tracing/processor_test.rb
436
453
  - test/tracing/span_context_test.rb