datadog-lambda 2.20.0 → 2.21.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.
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