instana 1.197.0 → 1.198.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a25aa837fcbb248cb39db1f57b7bdc8904810d5e63d87be7e12d912b7b9aea67
4
- data.tar.gz: 836dc1f8d7ffc4c8c19e3fa90867a306fe7d407fb88a14481d44bde1dc482285
3
+ metadata.gz: 0b2d93394311ee04b29279b946a5b2d6bf74e567aecbeccef6ffa13b07224002
4
+ data.tar.gz: ba3febaf1f2089a0547ae9e30596de784bcc7636bb98906c287638233cfdc8a6
5
5
  SHA512:
6
- metadata.gz: b8f3ba0fbf4a015ff1522a3c24e6b219594d2c266bc46427a93979e6ee159272d2c23a8fc53e4720021c5c531ad64ffd1d1f2644b8eb41497aaf8950c99ed8b6
7
- data.tar.gz: 44e5b93aff42f542eaee494128e973a9447210fbffde21c4b361f1b00729c8b3378634241d64039453ea3dda0dc2a0d207473a0c5631f1f09e77726b2a827532
6
+ metadata.gz: 74d25b236d861ec5eb144780a34e7b44b13f747ca843ee7bc25c3387eba63fbe0f3128a63bf19828a17e7bd02ebe51164f9f72c52070bd46a2d291e433ab4caa
7
+ data.tar.gz: 2ce25e5cea1b1a38831a481e571603fe99b67143ee7653c38081e1df5c8989f13f02e6490dad28500c63fff99277937b9be7052d0f7cf679ce0c46ce36cb5c21
@@ -15,7 +15,9 @@ module Instana
15
15
  end
16
16
 
17
17
  def setup
18
- @delegate = if @fargate_metadata_uri && ENV.key?('INSTANA_ENDPOINT_URL')
18
+ @delegate = if ENV.key?('_HANDLER')
19
+ ServerlessAgent.new([Snapshot::LambdaFunction.new])
20
+ elsif @fargate_metadata_uri && ENV.key?('INSTANA_ENDPOINT_URL')
19
21
  ServerlessAgent.new(fargate_snapshots)
20
22
  else
21
23
  HostAgent.new
@@ -33,9 +33,10 @@ module Instana
33
33
  end
34
34
 
35
35
  def initialize(host, port, use_ssl: false)
36
+ timeout = Integer(ENV.fetch('INSTANA_TIMEOUT', 500))
36
37
  @host = host
37
38
  @port = port
38
- @client = Net::HTTP.start(host, port, use_ssl: use_ssl)
39
+ @client = Net::HTTP.start(host, port, use_ssl: use_ssl, read_timeout: timeout)
39
40
  end
40
41
 
41
42
  # Send a request to the backend. If data is a {Hash},
@@ -39,12 +39,10 @@ module Instana
39
39
 
40
40
  # @return [Hash, NilClass] the backend friendly description of the current in process collector
41
41
  def source
42
- return @source if @source
43
-
44
42
  snapshot = @snapshots.detect { |s| s.respond_to?(:source) }
45
43
 
46
44
  if snapshot
47
- @source = snapshot.source
45
+ snapshot.source
48
46
  else
49
47
  @logger.warn('Unable to find a snapshot which provides a source.')
50
48
  {}
@@ -58,21 +56,10 @@ module Instana
58
56
 
59
57
  # @return [Hash] values which are removed from urls sent to the backend
60
58
  def secret_values
61
- # TODO: Parse from env
62
59
  matcher, *keys = @secrets.split(/[:,]/)
63
60
  {'matcher' => matcher, 'list' => keys}
64
61
  end
65
62
 
66
- private
67
-
68
- def request_headers
69
- {
70
- 'X-Instana-Host' => host_name,
71
- 'X-Instana-Key' => ENV['INSTANA_AGENT_KEY'],
72
- 'X-Instana-Time' => (Time.now.to_i * 1000).to_s
73
- }
74
- end
75
-
76
63
  def send_bundle
77
64
  spans = @processor.queued_spans
78
65
  bundle = {
@@ -90,6 +77,16 @@ module Instana
90
77
  @logger.warn("Recived a `#{response.code}` when sending data.")
91
78
  end
92
79
 
80
+ private
81
+
82
+ def request_headers
83
+ {
84
+ 'X-Instana-Host' => host_name,
85
+ 'X-Instana-Key' => ENV['INSTANA_AGENT_KEY'],
86
+ 'X-Instana-Time' => (Time.now.to_i * 1000).to_s
87
+ }
88
+ end
89
+
93
90
  def agent_snapshots
94
91
  @snapshots.map do |snapshot|
95
92
  begin # rubocop:disable Style/RedundantBegin, Lint/RedundantCopDisableDirective
@@ -102,12 +99,10 @@ module Instana
102
99
  end
103
100
 
104
101
  def host_name
105
- return @host_name if @host_name
106
-
107
102
  snapshot = @snapshots.detect { |s| s.respond_to?(:host_name) }
108
103
 
109
104
  if snapshot
110
- @host_name = snapshot.host_name
105
+ snapshot.host_name
111
106
  else
112
107
  @logger.warn('Unable to find a snapshot which provides a host_name.')
113
108
  ''
data/lib/instana/base.rb CHANGED
@@ -13,6 +13,7 @@ module Instana
13
13
  attr_accessor :config
14
14
  attr_accessor :pid
15
15
  attr_reader :secrets
16
+ attr_reader :serverless
16
17
 
17
18
  ##
18
19
  # setup
@@ -25,6 +26,7 @@ module Instana
25
26
  @tracer = ::Instana::Tracer.new
26
27
  @processor = ::Instana::Processor.new
27
28
  @secrets = ::Instana::Secrets.new
29
+ @serverless = ::Instana::Serverless.new
28
30
  end
29
31
 
30
32
  def logger
@@ -0,0 +1,133 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ require 'base64'
5
+ require 'zlib'
6
+
7
+ require 'instana/instrumentation/instrumented_request'
8
+
9
+ module Instana
10
+ # @since 1.198.0
11
+ class Serverless
12
+ def initialize(agent: ::Instana.agent, tracer: ::Instana.tracer, logger: ::Instana.logger)
13
+ @agent = agent
14
+ @tracer = tracer
15
+ @logger = logger
16
+ end
17
+
18
+ def wrap_aws(event, context, &block)
19
+ Thread.current[:instana_function_arn] = [context.invoked_function_arn, context.function_version].join(':')
20
+ trigger, event_tags, span_context = trigger_from_event(event)
21
+
22
+ tags = {
23
+ lambda: {
24
+ arn: context.invoked_function_arn,
25
+ functionName: context.function_name,
26
+ functionVersion: context.function_version,
27
+ runtime: 'ruby',
28
+ trigger: trigger
29
+ }
30
+ }
31
+
32
+ if event_tags.key?(:http)
33
+ tags = tags.merge(event_tags)
34
+ else
35
+ tags[:lambda] = tags[:lambda].merge(event_tags)
36
+ end
37
+
38
+ @tracer.start_or_continue_trace(:'aws.lambda.entry', tags, span_context, &block)
39
+ ensure
40
+ begin
41
+ @agent.send_bundle
42
+ rescue StandardError => e
43
+ @logger.error(e.message)
44
+ end
45
+ Thread.current[:instana_function_arn] = nil
46
+ end
47
+
48
+ private
49
+
50
+ def trigger_from_event(event) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
51
+ case event
52
+ when ->(e) { e.is_a?(Hash) && e.key?('requestContext') && e['requestContext'].key?('elb') }
53
+ request = InstrumentedRequest.new(event_to_rack(event))
54
+ ['aws:application.load.balancer', {http: request.request_tags}, request.incoming_context]
55
+ when ->(e) { e.is_a?(Hash) && e.key?('httpMethod') && e.key?('path') && e.key?('headers') }
56
+ request = InstrumentedRequest.new(event_to_rack(event))
57
+ ['aws:api.gateway', {http: request.request_tags}, request.incoming_context]
58
+ when ->(e) { e.is_a?(Hash) && e['source'] == 'aws.events' && e['detail-type'] == 'Scheduled Event' }
59
+ tags = decode_cloudwatch_events(event)
60
+ ['aws:cloudwatch.events', {cw: tags}, {}]
61
+ when ->(e) { e.is_a?(Hash) && e.key?('awslogs') }
62
+ tags = decode_cloudwatch_logs(event)
63
+ ['aws:cloudwatch.logs', {cw: tags}, {}]
64
+ when ->(e) { e.is_a?(Hash) && e.key?('Records') && e['Records'].is_a?(Array) && e['Records'].first && e['Records'].first['source'] == 'aws:s3' }
65
+ tags = decode_s3(event)
66
+ ['aws:s3', {s3: tags}, {}]
67
+ when ->(e) { e.is_a?(Hash) && e.key?('Records') && e['Records'].is_a?(Array) && e['Records'].first && e['Records'].first['source'] == 'aws:sqs' }
68
+ tags = decode_sqs(event)
69
+ ['aws:sqs', {sqs: tags}, {}]
70
+ else
71
+ ['aws:api.gateway.noproxy', {}, {}]
72
+ end
73
+ end
74
+
75
+ def event_to_rack(event)
76
+ event['headers']
77
+ .transform_keys { |k| "HTTP_#{k.gsub('-', '_').upcase}" }
78
+ .merge(
79
+ 'QUERY_STRING' => URI.encode_www_form(event['queryStringParameters'] || {}),
80
+ 'PATH_INFO' => event['path'],
81
+ 'REQUEST_METHOD' => event['httpMethod']
82
+ )
83
+ end
84
+
85
+ def decode_cloudwatch_events(event)
86
+ {
87
+ events: {
88
+ id: event['id'],
89
+ resources: event['resources']
90
+ }
91
+ }
92
+ end
93
+
94
+ def decode_cloudwatch_logs(event)
95
+ logs = begin
96
+ payload = JSON.parse(Zlib::Inflate.inflate(Base64.decode64(event['awslogs']['data'])))
97
+
98
+ {
99
+ group: payload['logGroup'],
100
+ stream: payload['logStream']
101
+ }
102
+ rescue StandardError => e
103
+ {
104
+ decodingError: e.message
105
+ }
106
+ end
107
+
108
+ {logs: logs}
109
+ end
110
+
111
+ def decode_s3(event)
112
+ span_events = event['Records'].map do |record|
113
+ {
114
+ name: record['eventName'],
115
+ bucket: record['s3'] && record['s3']['bucket'] ? record['s3']['bucket']['name'] : nil,
116
+ object: record['s3'] && record['s3']['object'] ? record['s3']['object']['key'] : nil
117
+ }
118
+ end
119
+
120
+ {events: span_events}
121
+ end
122
+
123
+ def decode_sqs(event)
124
+ span_events = event['Records'].map do |record|
125
+ {
126
+ queue: record['eventSourceARN']
127
+ }
128
+ end
129
+
130
+ {messages: span_events}
131
+ end
132
+ end
133
+ end
data/lib/instana/setup.rb CHANGED
@@ -9,6 +9,8 @@ require "instana/secrets"
9
9
  require "instana/tracer"
10
10
  require "instana/tracing/processor"
11
11
 
12
+ require 'instana/serverless'
13
+
12
14
  require 'instana/activator'
13
15
 
14
16
  require 'instana/backend/request_client'
@@ -21,6 +23,7 @@ require 'instana/snapshot/fargate_process'
21
23
  require 'instana/snapshot/fargate_task'
22
24
  require 'instana/snapshot/fargate_container'
23
25
  require 'instana/snapshot/docker_container'
26
+ require 'instana/snapshot/lambda_function'
24
27
 
25
28
  require 'instana/backend/host_agent_lookup'
26
29
  require 'instana/backend/host_agent_activation_observer'
@@ -1,5 +1,8 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
1
4
  module Instana
2
- module Backend
5
+ module Snapshot
3
6
  # @since 1.198.0
4
7
  class LambdaFunction
5
8
  ID = "com.instana.plugin.aws.lambda".freeze
@@ -22,15 +25,15 @@ module Instana
22
25
 
23
26
  def source
24
27
  {
25
-
28
+ hl: true,
29
+ cp: "aws",
30
+ e: entity_id
26
31
  }
27
32
  end
28
33
 
29
34
  def host_name
30
35
  entity_id
31
36
  end
32
-
33
-
34
37
  end
35
38
  end
36
39
  end
@@ -6,8 +6,8 @@ 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 ].freeze
10
- ENTRY_SPANS = [ :rack, :'resque-worker', :'rpc-server', :'sidekiq-worker', :'graphql.server', :sqs ].freeze
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
11
11
  EXIT_SPANS = [ :activerecord, :excon, :'net-http', :'resque-client',
12
12
  :'rpc-client', :'sidekiq-client', :redis, :dynamodb, :s3, :sns, :sqs ].freeze
13
13
  HTTP_SPANS = [ :rack, :excon, :'net-http' ].freeze
@@ -2,6 +2,6 @@
2
2
  # (c) Copyright Instana Inc. 2016
3
3
 
4
4
  module Instana
5
- VERSION = "1.197.0"
5
+ VERSION = "1.198.0.pre1"
6
6
  VERSION_FULL = "instana-#{VERSION}"
7
7
  end
@@ -43,6 +43,19 @@ class AgentTest < Minitest::Test
43
43
  ENV['ECS_CONTAINER_METADATA_URI'] = nil
44
44
  end
45
45
 
46
+ def test_lambda
47
+ ENV['_HANDLER'] = 'TEST_FUNCTION'
48
+ ENV['INSTANA_ENDPOINT_URL'] = 'http://example.com'
49
+
50
+ subject = Instana::Backend::Agent.new
51
+ assert_nil subject.delegate
52
+ subject.setup
53
+ assert subject.delegate.is_a?(Instana::Backend::ServerlessAgent)
54
+ ensure
55
+ ENV['_HANDLER'] = nil
56
+ ENV['INSTANA_ENDPOINT_URL'] = nil
57
+ end
58
+
46
59
  def test_delegate_super
47
60
  subject = Instana::Backend::Agent.new
48
61
  assert_raises NoMethodError do
@@ -0,0 +1,323 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ require 'test_helper'
5
+
6
+ class ServerlessTest < Minitest::Test
7
+ def setup
8
+ @mock_agent = Minitest::Mock.new
9
+ @mock_agent.expect(:send_bundle, true, [])
10
+ @subject = Instana::Serverless.new(agent: @mock_agent)
11
+ end
12
+
13
+ def teardown
14
+ @mock_agent.verify
15
+ end
16
+
17
+ def test_lambda_send_error
18
+ mock_logger = Minitest::Mock.new
19
+ mock_logger.expect(:error, true, [String])
20
+
21
+ @mock_agent.expect(:send_bundle, true) { |_args| raise StandardError, 'error' }
22
+
23
+ mock_context = OpenStruct.new(
24
+ invoked_function_arn: 'test_arn',
25
+ function_name: 'test_function',
26
+ function_version: '$TEST'
27
+ )
28
+
29
+ subject = Instana::Serverless.new(agent: @mock_agent, logger: mock_logger)
30
+ subject.wrap_aws(nil, mock_context) { 0 }
31
+ subject.wrap_aws(nil, mock_context) { 0 }
32
+
33
+ mock_logger.verify
34
+ end
35
+
36
+ def test_lambda_data
37
+ clear_all!
38
+
39
+ mock_context = OpenStruct.new(
40
+ invoked_function_arn: 'test_arn',
41
+ function_name: 'test_function',
42
+ function_version: '$TEST'
43
+ )
44
+
45
+ @subject.wrap_aws(nil, mock_context) { 0 }
46
+
47
+ lambda_span, *rest = Instana.processor.queued_spans
48
+ assert rest.empty?
49
+
50
+ data = lambda_span[:data][:lambda]
51
+
52
+ assert_equal 'aws:api.gateway.noproxy', lambda_span[:data][:lambda][:trigger]
53
+
54
+ assert_equal mock_context.invoked_function_arn, data[:arn]
55
+ assert_equal mock_context.function_name, data[:functionName]
56
+ assert_equal mock_context.function_version, data[:functionVersion]
57
+ assert_equal 'ruby', data[:runtime]
58
+ end
59
+
60
+ def test_lambda_http
61
+ clear_all!
62
+
63
+ mock_id = Instana::Util.generate_id
64
+ mock_context = OpenStruct.new(
65
+ invoked_function_arn: 'test_arn',
66
+ function_name: 'test_function',
67
+ function_version: '$TEST'
68
+ )
69
+ mock_http = {
70
+ "headers" => {
71
+ "Accept" => "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
72
+ "Accept-Encoding" => "gzip, deflate",
73
+ "Accept-Language" => "en-US,en;q=0.5",
74
+ "Connection" => "keep-alive",
75
+ "Host" => "127.0.0.1:3000",
76
+ "Upgrade-Insecure-Requests" => "1",
77
+ "User-Agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:87.0) Gecko/20100101 Firefox/87.0",
78
+ "X-Forwarded-Port" => "3000",
79
+ "X-Forwarded-Proto" => "http",
80
+ 'X-Instana-S' => mock_id,
81
+ 'X-Instana-T' => mock_id,
82
+ 'X-Instana-L' => '1'
83
+ },
84
+ "httpMethod" => "GET",
85
+ "path" => "/hello",
86
+ "queryStringParameters" => {"test" => "abcde"}
87
+ }
88
+
89
+ @subject.wrap_aws(mock_http, mock_context) { 0 }
90
+
91
+ lambda_span, *rest = Instana.processor.queued_spans
92
+ assert rest.empty?
93
+
94
+ data = lambda_span[:data][:http]
95
+
96
+ assert_equal 'aws:api.gateway', lambda_span[:data][:lambda][:trigger]
97
+ assert_equal mock_id, lambda_span[:t]
98
+ assert_equal mock_id, lambda_span[:p]
99
+
100
+ assert_equal 'GET', data[:method]
101
+ assert_equal '/hello', data[:url]
102
+ assert_equal '127.0.0.1:3000', data[:host]
103
+ assert_equal 'test=abcde', data[:params]
104
+ end
105
+
106
+ def test_lambda_alb
107
+ clear_all!
108
+
109
+ mock_id = Instana::Util.generate_id
110
+ mock_context = OpenStruct.new(
111
+ invoked_function_arn: 'test_arn',
112
+ function_name: 'test_function',
113
+ function_version: '$TEST'
114
+ )
115
+ mock_http = {
116
+ "headers" => {
117
+ "Accept" => "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
118
+ "Accept-Encoding" => "gzip, deflate",
119
+ "Accept-Language" => "en-US,en;q=0.5",
120
+ "Connection" => "keep-alive",
121
+ "Host" => "127.0.0.1:3000",
122
+ "Upgrade-Insecure-Requests" => "1",
123
+ "User-Agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:87.0) Gecko/20100101 Firefox/87.0",
124
+ "X-Forwarded-Port" => "3000",
125
+ "X-Forwarded-Proto" => "http",
126
+ 'X-Instana-S' => mock_id,
127
+ 'X-Instana-T' => mock_id,
128
+ 'X-Instana-L' => '1'
129
+ },
130
+ "httpMethod" => "GET",
131
+ "path" => "/hello",
132
+ "requestContext" => { "elb" => {} }
133
+ }
134
+
135
+ @subject.wrap_aws(mock_http, mock_context) { 0 }
136
+
137
+ lambda_span, *rest = Instana.processor.queued_spans
138
+ assert rest.empty?
139
+
140
+ data = lambda_span[:data][:http]
141
+
142
+ assert_equal 'aws:application.load.balancer', lambda_span[:data][:lambda][:trigger]
143
+ assert_equal mock_id, lambda_span[:t]
144
+ assert_equal mock_id, lambda_span[:p]
145
+
146
+ assert_equal 'GET', data[:method]
147
+ assert_equal '/hello', data[:url]
148
+ assert_equal '127.0.0.1:3000', data[:host]
149
+ assert_equal '', data[:params]
150
+ end
151
+
152
+ def test_lambda_cw_event
153
+ clear_all!
154
+
155
+ mock_context = OpenStruct.new(
156
+ invoked_function_arn: 'test_arn',
157
+ function_name: 'test_function',
158
+ function_version: '$TEST'
159
+ )
160
+ mock_event = {
161
+ "detail-type" => "Scheduled Event",
162
+ "source" => "aws.events",
163
+ "id" => "test",
164
+ "resources" => ["test"]
165
+ }
166
+
167
+ @subject.wrap_aws(mock_event, mock_context) { 0 }
168
+
169
+ lambda_span, *rest = Instana.processor.queued_spans
170
+ assert rest.empty?
171
+
172
+ data = lambda_span[:data][:lambda][:cw][:events]
173
+
174
+ assert_equal 'aws:cloudwatch.events', lambda_span[:data][:lambda][:trigger]
175
+ assert_equal 'test', data[:id]
176
+ assert_equal ["test"], data[:resources]
177
+ end
178
+
179
+ def test_lambda_cw_logs
180
+ clear_all!
181
+
182
+ mock_context = OpenStruct.new(
183
+ invoked_function_arn: 'test_arn',
184
+ function_name: 'test_function',
185
+ function_version: '$TEST'
186
+ )
187
+ mock_event = {
188
+ "awslogs" => {"data" => File.read('test/support/serverless/cloudwatch_log.bin')}
189
+ }
190
+
191
+ @subject.wrap_aws(mock_event, mock_context) { 0 }
192
+
193
+ lambda_span, *rest = Instana.processor.queued_spans
194
+ assert rest.empty?
195
+
196
+ data = lambda_span[:data][:lambda][:cw][:logs]
197
+
198
+ assert_equal 'aws:cloudwatch.logs', lambda_span[:data][:lambda][:trigger]
199
+ assert_equal '/aws/lambda/echo-nodejs', data[:group]
200
+ assert_equal '2019/03/13/[$LATEST]94fa867e5374431291a7fc14e2f56ae7', data[:stream]
201
+ end
202
+
203
+ def test_lambda_cw_error
204
+ clear_all!
205
+
206
+ mock_context = OpenStruct.new(
207
+ invoked_function_arn: 'test_arn',
208
+ function_name: 'test_function',
209
+ function_version: '$TEST'
210
+ )
211
+ mock_event = {
212
+ "awslogs" => {"data" => "error"}
213
+ }
214
+
215
+ @subject.wrap_aws(mock_event, mock_context) { 0 }
216
+
217
+ lambda_span, *rest = Instana.processor.queued_spans
218
+ assert rest.empty?
219
+
220
+ data = lambda_span[:data][:lambda][:cw][:logs]
221
+
222
+ assert_equal 'aws:cloudwatch.logs', lambda_span[:data][:lambda][:trigger]
223
+ assert_equal 'incorrect header check', data[:decodingError]
224
+ end
225
+
226
+ def test_lambda_s3
227
+ clear_all!
228
+
229
+ mock_context = OpenStruct.new(
230
+ invoked_function_arn: 'test_arn',
231
+ function_name: 'test_function',
232
+ function_version: '$TEST'
233
+ )
234
+ mock_event = {
235
+ "Records" => [
236
+ {
237
+ "source" => "aws:s3",
238
+ "eventName" => "test",
239
+ "s3" => {
240
+ "bucket" => {"name" => "test_bucket"},
241
+ "object" => {"key" => "test_key"}
242
+ }
243
+ }
244
+ ]
245
+ }
246
+
247
+ @subject.wrap_aws(mock_event, mock_context) { 0 }
248
+
249
+ lambda_span, *rest = Instana.processor.queued_spans
250
+ assert rest.empty?
251
+
252
+ data = lambda_span[:data][:lambda][:s3]
253
+
254
+ assert_equal 'aws:s3', lambda_span[:data][:lambda][:trigger]
255
+ assert_equal 1, data[:events].length
256
+
257
+ assert_equal 'test', data[:events].first[:name]
258
+ assert_equal 'test_bucket', data[:events].first[:bucket]
259
+ assert_equal 'test_key', data[:events].first[:object]
260
+ end
261
+
262
+ def test_lambda_s3_no_object
263
+ clear_all!
264
+
265
+ mock_context = OpenStruct.new(
266
+ invoked_function_arn: 'test_arn',
267
+ function_name: 'test_function',
268
+ function_version: '$TEST'
269
+ )
270
+ mock_event = {
271
+ "Records" => [
272
+ {
273
+ "source" => "aws:s3",
274
+ "eventName" => "test"
275
+ }
276
+ ]
277
+ }
278
+
279
+ @subject.wrap_aws(mock_event, mock_context) { 0 }
280
+
281
+ lambda_span, *rest = Instana.processor.queued_spans
282
+ assert rest.empty?
283
+
284
+ data = lambda_span[:data][:lambda][:s3]
285
+
286
+ assert_equal 'aws:s3', lambda_span[:data][:lambda][:trigger]
287
+ assert_equal 1, data[:events].length
288
+
289
+ assert_equal 'test', data[:events].first[:name]
290
+ assert_nil data[:events].first[:bucket]
291
+ assert_nil data[:events].first[:object]
292
+ end
293
+
294
+ def test_lambda_sqs
295
+ clear_all!
296
+
297
+ mock_context = OpenStruct.new(
298
+ invoked_function_arn: 'test_arn',
299
+ function_name: 'test_function',
300
+ function_version: '$TEST'
301
+ )
302
+ mock_event = {
303
+ "Records" => [
304
+ {
305
+ "source" => "aws:sqs",
306
+ "eventSourceARN" => "test_arn"
307
+ }
308
+ ]
309
+ }
310
+
311
+ @subject.wrap_aws(mock_event, mock_context) { 0 }
312
+
313
+ lambda_span, *rest = Instana.processor.queued_spans
314
+ assert rest.empty?
315
+
316
+ data = lambda_span[:data][:lambda][:sqs]
317
+
318
+ assert_equal 'aws:sqs', lambda_span[:data][:lambda][:trigger]
319
+ assert_equal 1, data[:messages].length
320
+
321
+ assert_equal 'test_arn', data[:messages].first[:queue]
322
+ end
323
+ end
@@ -0,0 +1,37 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ require 'test_helper'
5
+
6
+ class LambdaFunctionTest < Minitest::Test
7
+ def setup
8
+ @subject = Instana::Snapshot::LambdaFunction.new
9
+ end
10
+
11
+ def test_snapshot
12
+ Thread.current[:instana_function_arn] = 'test'
13
+
14
+ assert_equal Instana::Snapshot::LambdaFunction::ID, @subject.snapshot[:name]
15
+ assert_equal Thread.current[:instana_function_arn], @subject.snapshot[:entityId]
16
+ ensure
17
+ Thread.current[:instana_function_arn] = nil
18
+ end
19
+
20
+ def test_source
21
+ Thread.current[:instana_function_arn] = 'test'
22
+
23
+ assert @subject.source[:hl]
24
+ assert_equal 'aws', @subject.source[:cp]
25
+ assert_equal Thread.current[:instana_function_arn], @subject.source[:e]
26
+ ensure
27
+ Thread.current[:instana_function_arn] = nil
28
+ end
29
+
30
+ def test_host_name
31
+ Thread.current[:instana_function_arn] = 'test'
32
+
33
+ assert_equal Thread.current[:instana_function_arn], @subject.host_name
34
+ ensure
35
+ Thread.current[:instana_function_arn] = nil
36
+ end
37
+ end
@@ -68,6 +68,10 @@ class TracerIDMgmtTest < Minitest::Test
68
68
  # Bogus Array arg
69
69
  bogus_result = Instana::Util.header_to_id([1234])
70
70
  assert_equal '', bogus_result
71
+
72
+ # Invalid characters/length
73
+ bogus_result = Instana::Util.header_to_id('qwerty')
74
+ assert_equal '', bogus_result
71
75
  end
72
76
 
73
77
  def test_long_id_trim
@@ -15,7 +15,8 @@ class SpanContextTest < Minitest::Test
15
15
  end
16
16
 
17
17
  def test_flags_level_zero
18
- subject = Instana::SpanContext.new('trace', 'span', 0)
18
+ subject = Instana::SpanContext.new('trace', 'span', 0, {external_state: 'cn=test'})
19
19
  assert_equal '00-000000000000000000000000000trace-000000000000span-00', subject.trace_parent_header
20
+ assert_equal 'cn=test', subject.trace_state_header
20
21
  end
21
22
  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.197.0
4
+ version: 1.198.0.pre1
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-04-06 00:00:00.000000000 Z
11
+ date: 2021-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -255,6 +255,7 @@ files:
255
255
  - lib/instana/open_tracing/instana_tracer.rb
256
256
  - lib/instana/rack.rb
257
257
  - lib/instana/secrets.rb
258
+ - lib/instana/serverless.rb
258
259
  - lib/instana/setup.rb
259
260
  - lib/instana/snapshot/deltable.rb
260
261
  - lib/instana/snapshot/docker_container.rb
@@ -307,11 +308,13 @@ files:
307
308
  - test/instrumentation/sidekiq-client_test.rb
308
309
  - test/instrumentation/sidekiq-worker_test.rb
309
310
  - test/secrets_test.rb
311
+ - test/serverless_test.rb
310
312
  - test/snapshot/deltable_test.rb
311
313
  - test/snapshot/docker_container_test.rb
312
314
  - test/snapshot/fargate_container_test.rb
313
315
  - test/snapshot/fargate_process_test.rb
314
316
  - test/snapshot/fargate_task_test.rb
317
+ - test/snapshot/lambda_function_test.rb
315
318
  - test/snapshot/ruby_process_test.rb
316
319
  - test/support/apps/active_record/active_record.rb
317
320
  - test/support/apps/grpc/boot.rb
@@ -358,9 +361,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
358
361
  version: '2.1'
359
362
  required_rubygems_version: !ruby/object:Gem::Requirement
360
363
  requirements:
361
- - - ">="
364
+ - - ">"
362
365
  - !ruby/object:Gem::Version
363
- version: '0'
366
+ version: 1.3.1
364
367
  requirements: []
365
368
  rubygems_version: 3.2.6
366
369
  signing_key:
@@ -368,6 +371,7 @@ specification_version: 4
368
371
  summary: Ruby Distributed Tracing & Metrics Sensor for Instana
369
372
  test_files:
370
373
  - test/config_test.rb
374
+ - test/serverless_test.rb
371
375
  - test/activator_test.rb
372
376
  - test/tracing/span_context_test.rb
373
377
  - test/tracing/span_test.rb
@@ -382,6 +386,7 @@ test_files:
382
386
  - test/snapshot/deltable_test.rb
383
387
  - test/snapshot/fargate_task_test.rb
384
388
  - test/snapshot/ruby_process_test.rb
389
+ - test/snapshot/lambda_function_test.rb
385
390
  - test/snapshot/fargate_container_test.rb
386
391
  - test/backend/host_agent_activation_observer_test.rb
387
392
  - test/backend/host_agent_reporting_observer_test.rb