datadog-lambda 2.20.0 → 2.21.0

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: 7190d039044c87a9835b29f812e930cc6c3fee9cdc5348226df7fe603b15a7bf
4
- data.tar.gz: 35c495079f2b934ba036008084765d92a376f6924f7a4c5468ad34303ee1912c
3
+ metadata.gz: 6c867a4e0858e0ba773829993e4c60b2d84b26f8afe4e69a766ac75f6ef454c5
4
+ data.tar.gz: feaa85e2d5d998b32602b74958792a656f692eab4950fdc7da0cccb7d12542bd
5
5
  SHA512:
6
- metadata.gz: c51f7c325e147d68a713d763c9550f2bf11b3ba9f7492f48c4b5195302f4c5fd4c0da20a9893ea19c27be24c4adf8740186f394250f830cfe8b6d8890c861d7b
7
- data.tar.gz: 58f67b709d96a5b9e8ce628c4c1d0c02385508de007772a2560da26dc8cc7e90d23562063e3a8e73a5c90f73e71fd7c0cc0fac305c36cca6d901977d39c3fd6f
6
+ metadata.gz: cd5062d00ae5f88a8c5021f6c76c3b87fa9236d035508e04dbd33113cf51a5b7bec006060ab6dc12ea27da46feaf78ae3eb98d9bd4c907b5a972c7176ca40ee7
7
+ data.tar.gz: 823cc2efc44cfefd3e0829ca038e966f6b999fd5c2648131a91a2b8b805dbd8ae5aeb5cdba1c14d3c8579aafffb719679b8e1bdd60306f37c80c3bc176f154d2
@@ -20,6 +20,7 @@ module Datadog
20
20
  DD_XRAY_SUBSEGMENT_NAME = 'datadog-metadata'
21
21
  DD_XRAY_SUBSEGMENT_KEY = 'trace'
22
22
  DD_XRAY_SUBSEGMENT_NAMESPACE = 'datadog'
23
+ DD_TRACE_MANAGED_SERVICES = 'DD_TRACE_MANAGED_SERVICES'
23
24
  SOURCE_XRAY = 'XRAY'
24
25
  SOURCE_EVENT = 'EVENT'
25
26
  XRAY_ENV_VAR = '_X_AMZN_TRACE_ID'
@@ -16,6 +16,7 @@ module Datadog
16
16
  module Trace
17
17
  # TraceListener tracks tracing context information
18
18
  class Listener
19
+ @trace = nil
19
20
  def initialize(handler_name:, function_name:, patch_http:,
20
21
  merge_xray_traces:)
21
22
  @handler_name = handler_name
@@ -25,18 +26,11 @@ module Datadog
25
26
  Datadog::Trace.patch_http if patch_http
26
27
  end
27
28
 
28
- def on_start(event:)
29
- trace_context = Datadog::Trace.extract_trace_context(event,
30
- @merge_xray_traces)
29
+ # rubocop:disable Metrics/AbcSize
30
+ def on_start(event:, request_context:, cold_start:)
31
+ trace_context = Datadog::Trace.extract_trace_context(event, @merge_xray_traces)
31
32
  Datadog::Trace.trace_context = trace_context
32
33
  Datadog::Utils.logger.debug "extracted trace context #{trace_context}"
33
- rescue StandardError => e
34
- Datadog::Utils.logger.error "couldn't read tracing context #{e}"
35
- end
36
-
37
- def on_end; end
38
-
39
- def on_wrap(request_context:, cold_start:, &block)
40
34
  options = get_option_tags(
41
35
  request_context: request_context,
42
36
  cold_start: cold_start
@@ -48,9 +42,14 @@ module Datadog
48
42
  options[:service] = 'aws.lambda'
49
43
  options[:span_type] = 'serverless'
50
44
  Datadog::Trace.apply_datadog_trace_context(Datadog::Trace.trace_context)
51
- Datadog::Trace.wrap_datadog(options) do
52
- block.call
53
- end
45
+ @trace = Datadog::Tracing.trace('aws.lambda', **options)
46
+ Datadog::Utils.send_start_invocation_request(event: event)
47
+ end
48
+ # rubocop:enable Metrics/AbcSize
49
+
50
+ def on_end(response:)
51
+ Datadog::Utils.send_end_invocation_request(response: response)
52
+ @trace&.finish
54
53
  end
55
54
 
56
55
  private
@@ -12,12 +12,14 @@ require 'net/http'
12
12
  module Datadog
13
13
  # Utils contains utility functions shared between modules
14
14
  module Utils
15
- AGENT_URL = 'http://127.0.0.1:8124'
16
- HELLO_PATH = '/lambda/hello'
17
- EXTENSION_CHECK_URI = URI(AGENT_URL + HELLO_PATH).freeze
18
15
  EXTENSION_PATH = '/opt/extensions/datadog-agent'
16
+ EXTENSION_BASE_URL = 'http://127.0.0.1:8124'
19
17
 
20
- @is_extension_running = nil
18
+ START_INVOCATION_PATH = '/lambda/start-invocation'
19
+ END_INVOCATION_PATH = '/lambda/end-invocation'
20
+
21
+ START_INVOCATION_URI = URI(EXTENSION_BASE_URL + START_INVOCATION_PATH).freeze
22
+ END_INVOCATION_URI = URI(EXTENSION_BASE_URL + END_INVOCATION_PATH).freeze
21
23
 
22
24
  def self.extension_running?
23
25
  return @is_extension_running unless @is_extension_running.nil?
@@ -26,16 +28,44 @@ module Datadog
26
28
  end
27
29
 
28
30
  def self.check_extension_running
29
- return false unless File.exist?(EXTENSION_PATH)
31
+ File.exist?(EXTENSION_PATH)
32
+ end
33
+
34
+ def self.send_start_invocation_request(event:)
35
+ return unless extension_running?
30
36
 
31
- begin
32
- Net::HTTP.get(EXTENSION_CHECK_URI)
33
- rescue StandardError => e
34
- Datadog::Utils.logger.debug "extension is not running, returned with error #{e}"
35
- return false
37
+ response = Net::HTTP.post(START_INVOCATION_URI, event.to_json, request_headers)
38
+
39
+ trace_digest = Tracing::Propagation::HTTP.extract(response)
40
+ # Only continue trace from a new one if it exist, or else,
41
+ # it will create a new trace, which is not ideal here.
42
+ Tracing.continue_trace!(trace_digest) if trace_digest
43
+ rescue StandardError => e
44
+ Datadog::Utils.logger.debug "failed on start invocation request to extension: #{e}"
45
+ end
46
+
47
+ def self.send_end_invocation_request(response:)
48
+ return unless extension_running?
49
+
50
+ request = Net::HTTP::Post.new(END_INVOCATION_URI)
51
+ request.body = response.to_json
52
+ request[Datadog::Core::Transport::Ext::HTTP::HEADER_DD_INTERNAL_UNTRACED_REQUEST] = 1
53
+
54
+ trace = Datadog::Tracing.active_trace
55
+ Tracing::Propagation::HTTP.inject!(trace, request)
56
+ Net::HTTP.start(END_INVOCATION_URI.host, END_INVOCATION_URI.port) do |http|
57
+ http.request(request)
36
58
  end
59
+ rescue StandardError => e
60
+ Datadog::Utils.logger.debug "failed on end invocation request to extension: #{e}"
61
+ end
37
62
 
38
- true
63
+ def self.request_headers
64
+ {
65
+ # Header used to avoid tracing requests that are internal to
66
+ # Datadog products.
67
+ Datadog::Core::Transport::Ext::HTTP::HEADER_DD_INTERNAL_UNTRACED_REQUEST.to_sym => 'true'
68
+ }
39
69
  end
40
70
  end
41
71
  end
@@ -12,7 +12,7 @@ module Datadog
12
12
  module Lambda
13
13
  module VERSION
14
14
  MAJOR = 2
15
- MINOR = 20
15
+ MINOR = 21
16
16
  PATCH = 0
17
17
  PRE = nil
18
18
 
@@ -21,6 +21,7 @@ module Datadog
21
21
  # Instruments AWS Lambda functions with Datadog distributed tracing and
22
22
  # custom metrics
23
23
  module Lambda
24
+ @response = nil
24
25
  @is_cold_start = true
25
26
  @patch_http = true
26
27
  @metrics_client = Metrics::Client.instance
@@ -30,7 +31,7 @@ module Datadog
30
31
  # See https://github.com/DataDog/dd-trace-rb/blob/master/docs/GettingStarted.md#quickstart-for-ruby-applications
31
32
  def self.configure_apm
32
33
  require 'datadog/tracing'
33
- require 'ddtrace/transport/io'
34
+ require 'datadog/tracing/transport/io'
34
35
 
35
36
  @patch_http = false
36
37
  # Needed to keep trace flushes on a single line
@@ -39,10 +40,13 @@ module Datadog
39
40
  Datadog.configure do |c|
40
41
  unless Datadog::Utils.extension_running?
41
42
  c.tracing.writer = Datadog::Tracing::SyncWriter.new(
42
- transport: Datadog::Transport::IO.default
43
+ transport: Datadog::Tracing::Transport::IO.default
43
44
  )
44
45
  end
45
46
  c.tags = { "_dd.origin": 'lambda' }
47
+ # Enable AWS SDK instrumentation
48
+ c.tracing.instrument :aws if trace_managed_services?
49
+
46
50
  yield(c) if block_given?
47
51
  end
48
52
  end
@@ -54,28 +58,25 @@ module Datadog
54
58
  def self.wrap(event, context, &block)
55
59
  Datadog::Utils.update_log_level
56
60
  @listener ||= initialize_listener
57
- @listener.on_start(event: event)
58
61
  record_enhanced('invocations', context)
59
62
  begin
60
63
  cold = @is_cold_start
61
- res = @listener.on_wrap(request_context: context, cold_start: cold) do
62
- block.call
63
- end
64
+ @listener&.on_start(event: event, request_context: context, cold_start: cold)
65
+ @response = block.call
64
66
  rescue StandardError => e
65
67
  record_enhanced('errors', context)
66
68
  raise e
67
69
  ensure
68
- @listener.on_end
70
+ @listener&.on_end(response: @response)
69
71
  @is_cold_start = false
70
72
  @metrics_client.close
71
73
  end
72
- res
74
+ @response
73
75
  end
74
76
 
75
77
  # Gets the current tracing context
76
78
  def self.trace_context
77
- context = Hash[Datadog::Trace.trace_context]
78
- context
79
+ Hash[Datadog::Trace.trace_context]
79
80
  end
80
81
 
81
82
  # Send a custom distribution metric
@@ -166,6 +167,15 @@ module Datadog
166
167
  dd_enhanced_metrics.downcase == 'true'
167
168
  end
168
169
 
170
+ # Read DD_TRACE_MANAGED_SERVICES environment variable
171
+ # @return [boolean] true if we should trace AWS services
172
+ def self.trace_managed_services?
173
+ dd_trace_managed_services = ENV[Trace::DD_TRACE_MANAGED_SERVICES]
174
+ return true if dd_trace_managed_services.nil?
175
+
176
+ dd_trace_managed_services.downcase == 'true'
177
+ end
178
+
169
179
  def self.initialize_listener
170
180
  handler = ENV['_HANDLER'].nil? ? 'handler' : ENV['_HANDLER']
171
181
  function = ENV['AWS_LAMBDA_FUNCTION_NAME']
@@ -176,10 +186,18 @@ module Datadog
176
186
  Datadog::Utils.logger.debug("Setting merge traces #{merge_xray_traces}")
177
187
  end
178
188
 
179
- Trace::Listener.new(handler_name: handler,
180
- function_name: function,
181
- patch_http: @patch_http,
182
- merge_xray_traces: merge_xray_traces)
189
+ # Only initialize listener if Tracing enabled.
190
+ unless Datadog::Tracing.enabled?
191
+ Datadog::Utils.logger.debug 'dd-trace unavailable'
192
+ return nil
193
+ end
194
+
195
+ Trace::Listener.new(
196
+ handler_name: handler,
197
+ function_name: function,
198
+ patch_http: @patch_http,
199
+ merge_xray_traces: merge_xray_traces
200
+ )
183
201
  end
184
202
  end
185
203
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datadog-lambda
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.20.0
4
+ version: 2.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-08-08 00:00:00.000000000 Z
11
+ date: 2023-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-xray-sdk
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.12.0
47
+ version: 1.15.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.12.0
54
+ version: 1.15.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement