ddtrace 1.3.0 → 1.4.1

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -2
  3. data/README.md +1 -1
  4. data/ext/ddtrace_profiling_loader/ddtrace_profiling_loader.c +10 -1
  5. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +5 -4
  6. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.h +1 -1
  7. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +391 -0
  8. data/ext/ddtrace_profiling_native_extension/extconf.rb +2 -0
  9. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +9 -0
  10. data/ext/ddtrace_profiling_native_extension/profiling.c +2 -0
  11. data/ext/ddtrace_profiling_native_extension/stack_recorder.c +2 -1
  12. data/ext/ddtrace_profiling_native_extension/stack_recorder.h +8 -7
  13. data/lib/datadog/ci/contrib/cucumber/integration.rb +1 -1
  14. data/lib/datadog/ci/contrib/rspec/integration.rb +1 -1
  15. data/lib/datadog/core/configuration/base.rb +9 -0
  16. data/lib/datadog/core/configuration/components.rb +26 -6
  17. data/lib/datadog/core/configuration/settings.rb +25 -0
  18. data/lib/datadog/core/configuration.rb +4 -1
  19. data/lib/datadog/core/telemetry/client.rb +79 -0
  20. data/lib/datadog/core/telemetry/collector.rb +234 -0
  21. data/lib/datadog/core/telemetry/emitter.rb +48 -0
  22. data/lib/datadog/core/telemetry/event.rb +71 -0
  23. data/lib/datadog/core/telemetry/ext.rb +11 -0
  24. data/lib/datadog/core/telemetry/heartbeat.rb +37 -0
  25. data/lib/datadog/core/telemetry/http/adapters/net.rb +113 -0
  26. data/lib/datadog/core/telemetry/http/env.rb +20 -0
  27. data/lib/datadog/core/telemetry/http/ext.rb +20 -0
  28. data/lib/datadog/core/telemetry/http/response.rb +68 -0
  29. data/lib/datadog/core/telemetry/http/transport.rb +53 -0
  30. data/lib/datadog/core/telemetry/v1/app_event.rb +52 -0
  31. data/lib/datadog/core/telemetry/v1/application.rb +86 -0
  32. data/lib/datadog/core/telemetry/v1/configuration.rb +25 -0
  33. data/lib/datadog/core/telemetry/v1/dependency.rb +36 -0
  34. data/lib/datadog/core/telemetry/v1/host.rb +51 -0
  35. data/lib/datadog/core/telemetry/v1/integration.rb +58 -0
  36. data/lib/datadog/core/telemetry/v1/product.rb +28 -0
  37. data/lib/datadog/core/telemetry/v1/telemetry_request.rb +100 -0
  38. data/lib/datadog/core/utils/sequence.rb +5 -0
  39. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +74 -0
  40. data/lib/datadog/profiling/stack_recorder.rb +1 -1
  41. data/lib/datadog/profiling.rb +1 -0
  42. data/lib/datadog/tracing/contrib/extensions.rb +2 -0
  43. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +9 -0
  44. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  45. data/lib/datadog/tracing/contrib/patcher.rb +11 -0
  46. data/lib/datadog/tracing/contrib/rack/patcher.rb +8 -0
  47. data/lib/datadog/tracing/trace_operation.rb +1 -1
  48. data/lib/ddtrace/auto_instrument.rb +7 -0
  49. data/lib/ddtrace/transport/ext.rb +0 -1
  50. data/lib/ddtrace/transport/http/adapters/net.rb +1 -0
  51. data/lib/ddtrace/version.rb +2 -2
  52. metadata +26 -5
@@ -0,0 +1,113 @@
1
+ # typed: true
2
+
3
+ require_relative '../response'
4
+
5
+ module Datadog
6
+ module Core
7
+ module Telemetry
8
+ module Http
9
+ module Adapters
10
+ # Class defining methods to make http requests via NET
11
+ class Net
12
+ attr_reader \
13
+ :hostname,
14
+ :port,
15
+ :timeout,
16
+ :ssl
17
+
18
+ DEFAULT_TIMEOUT = 30
19
+
20
+ def initialize(hostname:, port: nil, timeout: DEFAULT_TIMEOUT, ssl: true)
21
+ @hostname = hostname
22
+ @port = port
23
+ @timeout = timeout
24
+ @ssl = ssl.nil? ? true : ssl
25
+ end
26
+
27
+ def open(&block)
28
+ req = ::Net::HTTP.new(@hostname, @port)
29
+
30
+ req.use_ssl = @ssl
31
+ req.open_timeout = req.read_timeout = @timeout
32
+
33
+ req.start(&block)
34
+ end
35
+
36
+ def post(env)
37
+ begin
38
+ post = ::Net::HTTP::Post.new(env.path, env.headers)
39
+ post.body = env.body
40
+
41
+ http_response = open do |http|
42
+ http.request(post)
43
+ end
44
+
45
+ Response.new(http_response)
46
+ rescue StandardError => e
47
+ Datadog.logger.debug("Unable to send telemetry event to agent: #{e}")
48
+ Telemetry::Http::InternalErrorResponse.new(e)
49
+ end
50
+ end
51
+
52
+ # Data structure for an HTTP Response
53
+ class Response
54
+ include Datadog::Core::Telemetry::Http::Response
55
+
56
+ attr_reader :http_response
57
+
58
+ def initialize(http_response)
59
+ @http_response = http_response
60
+ end
61
+
62
+ def payload
63
+ return super if http_response.nil?
64
+
65
+ http_response.body
66
+ end
67
+
68
+ def code
69
+ return super if http_response.nil?
70
+
71
+ http_response.code.to_i
72
+ end
73
+
74
+ def ok?
75
+ return super if http_response.nil?
76
+
77
+ code.between?(200, 299)
78
+ end
79
+
80
+ def unsupported?
81
+ return super if http_response.nil?
82
+
83
+ code == 415
84
+ end
85
+
86
+ def not_found?
87
+ return super if http_response.nil?
88
+
89
+ code == 404
90
+ end
91
+
92
+ def client_error?
93
+ return super if http_response.nil?
94
+
95
+ code.between?(400, 499)
96
+ end
97
+
98
+ def server_error?
99
+ return super if http_response.nil?
100
+
101
+ code.between?(500, 599)
102
+ end
103
+
104
+ def inspect
105
+ "#{super}, http_response:#{http_response}"
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,20 @@
1
+ # typed: true
2
+
3
+ module Datadog
4
+ module Core
5
+ module Telemetry
6
+ module Http
7
+ # Data structure for an HTTP request
8
+ class Env
9
+ attr_accessor :path, :body
10
+
11
+ attr_writer :headers
12
+
13
+ def headers
14
+ @headers ||= {}
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module Datadog
2
+ module Core
3
+ module Telemetry
4
+ module Http
5
+ module Ext
6
+ HEADER_DD_API_KEY = 'DD-API-KEY'.freeze
7
+ HEADER_CONTENT_TYPE = 'Content-Type'.freeze
8
+ HEADER_CONTENT_LENGTH = 'Content-Length'.freeze
9
+ HEADER_DD_TELEMETRY_API_VERSION = 'DD-Telemetry-API-Version'.freeze
10
+ HEADER_DD_TELEMETRY_REQUEST_TYPE = 'DD-Telemetry-Request-Type'.freeze
11
+
12
+ CONTENT_TYPE_APPLICATION_JSON = 'application/json'.freeze
13
+ API_VERSION = 'v1'.freeze
14
+
15
+ AGENT_ENDPOINT = '/telemetry/proxy/api/v2/apmtelemetry'.freeze
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,68 @@
1
+ # typed: true
2
+
3
+ module Datadog
4
+ module Core
5
+ module Telemetry
6
+ module Http
7
+ # Module for base HTTP response
8
+ module Response
9
+ include Kernel
10
+
11
+ def payload
12
+ nil
13
+ end
14
+
15
+ def ok?
16
+ nil
17
+ end
18
+
19
+ def unsupported?
20
+ nil
21
+ end
22
+
23
+ def not_found?
24
+ nil
25
+ end
26
+
27
+ def client_error?
28
+ nil
29
+ end
30
+
31
+ def server_error?
32
+ nil
33
+ end
34
+
35
+ def internal_error?
36
+ nil
37
+ end
38
+
39
+ def inspect
40
+ "#{self.class} ok?:#{ok?} unsupported?:#{unsupported?}, " \
41
+ "not_found?:#{not_found?}, client_error?:#{client_error?}, " \
42
+ "server_error?:#{server_error?}, internal_error?:#{internal_error?}, " \
43
+ "payload:#{payload}"
44
+ end
45
+ end
46
+
47
+ # A generic error response for internal errors
48
+ class InternalErrorResponse
49
+ include Response
50
+
51
+ attr_reader :error
52
+
53
+ def initialize(error)
54
+ @error = error
55
+ end
56
+
57
+ def internal_error?
58
+ true
59
+ end
60
+
61
+ def inspect
62
+ "#{super}, error_type:#{error.class} error:#{error}"
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,53 @@
1
+ # typed: true
2
+
3
+ require_relative '../../configuration/settings'
4
+ require_relative 'env'
5
+ require_relative 'ext'
6
+ require_relative 'adapters/net'
7
+
8
+ module Datadog
9
+ module Core
10
+ module Telemetry
11
+ module Http
12
+ # Class to send telemetry data to Telemetry API
13
+ class Transport
14
+ attr_reader \
15
+ :host,
16
+ :port,
17
+ :ssl,
18
+ :path
19
+
20
+ def initialize
21
+ agent_settings = Configuration::AgentSettingsResolver.call(Datadog.configuration)
22
+ @host = agent_settings.hostname
23
+ @port = agent_settings.port
24
+ @ssl = false
25
+ @path = Http::Ext::AGENT_ENDPOINT
26
+ end
27
+
28
+ def request(request_type:, payload:)
29
+ env = Http::Env.new
30
+ env.path = @path
31
+ env.body = payload
32
+ env.headers = headers(request_type: request_type)
33
+ adapter.post(env)
34
+ end
35
+
36
+ private
37
+
38
+ def headers(request_type:, api_version: Http::Ext::API_VERSION)
39
+ {
40
+ Http::Ext::HEADER_CONTENT_TYPE => Http::Ext::CONTENT_TYPE_APPLICATION_JSON,
41
+ Http::Ext::HEADER_DD_TELEMETRY_API_VERSION => api_version,
42
+ Http::Ext::HEADER_DD_TELEMETRY_REQUEST_TYPE => request_type,
43
+ }
44
+ end
45
+
46
+ def adapter
47
+ @adapter ||= Http::Adapters::Net.new(hostname: @host, port: @port, ssl: @ssl)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,52 @@
1
+ module Datadog
2
+ module Core
3
+ module Telemetry
4
+ module V1
5
+ # Describes payload for telemetry V1 API app-integrations-change event
6
+ class AppEvent
7
+ include Kernel
8
+
9
+ attr_reader \
10
+ :additional_payload,
11
+ :configuration,
12
+ :dependencies,
13
+ :integrations
14
+
15
+ # @param additional_payload [Array<Telemetry::V1::Configuration>] List of Additional payload to track (any key
16
+ # value not mentioned and doesn't fit under a metric)
17
+ # @param configuration [Array<Telemetry::V1::Configuration>] List of Tracer related configuration data
18
+ # @param dependencies [Array<Telemetry::V1::Dependency>] List of all loaded modules requested by the app
19
+ # @param integrations [Array<Telemetry::V1::Integration>] List of integrations that are available within the app
20
+ # and applicable to be traced
21
+ def initialize(additional_payload: nil, configuration: nil, dependencies: nil, integrations: nil)
22
+ @additional_payload = additional_payload
23
+ @configuration = configuration
24
+ @dependencies = dependencies
25
+ @integrations = integrations
26
+ end
27
+
28
+ def to_h
29
+ {}.tap do |hash|
30
+ hash[:additional_payload] = map_hash(@additional_payload) if @additional_payload
31
+ hash[:configuration] = map_hash(@configuration) if @configuration
32
+ hash[:dependencies] = map_array(@dependencies) if @dependencies
33
+ hash[:integrations] = map_array(@integrations) if @integrations
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def map_hash(hash)
40
+ hash.map do |k, v|
41
+ { name: k.to_s, value: v }
42
+ end
43
+ end
44
+
45
+ def map_array(arr)
46
+ arr.map(&:to_h)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,86 @@
1
+ module Datadog
2
+ module Core
3
+ module Telemetry
4
+ module V1
5
+ # Describes attributes for application environment object
6
+ class Application
7
+ ERROR_NIL_LANGUAGE_NAME_MESSAGE = ':language_name must not be nil'.freeze
8
+ ERROR_NIL_LANGUAGE_VERSION_MESSAGE = ':language_version must not be nil'.freeze
9
+ ERROR_NIL_SERVICE_NAME_MESSAGE = ':service_name must not be nil'.freeze
10
+ ERROR_NIL_TRACER_VERSION_MESSAGE = ':tracer_version must not be nil'.freeze
11
+
12
+ attr_reader \
13
+ :env,
14
+ :language_name,
15
+ :language_version,
16
+ :products,
17
+ :runtime_name,
18
+ :runtime_patches,
19
+ :runtime_version,
20
+ :service_name,
21
+ :service_version,
22
+ :tracer_version
23
+
24
+ # @param env [String] Service's environment
25
+ # @param language_name [String] 'ruby'
26
+ # @param language_version [String] Version of language used
27
+ # @param products [Telemetry::V1::Product] Contains information about specific products added to the environment
28
+ # @param runtime_name [String] Runtime being used
29
+ # @param runtime_patches [String] String of patches applied to the runtime
30
+ # @param runtime_version [String] Runtime version; potentially the same as :language_version
31
+ # @param service_name [String] Service’s name (DD_SERVICE)
32
+ # @param service_version [String] Service’s version (DD_VERSION)
33
+ # @param tracer_version [String] Version of the used tracer
34
+ def initialize(
35
+ language_name:, language_version:, service_name:, tracer_version:, env: nil, products: nil,
36
+ runtime_name: nil, runtime_patches: nil, runtime_version: nil, service_version: nil
37
+ )
38
+ validate(
39
+ language_name: language_name,
40
+ language_version: language_version,
41
+ service_name: service_name,
42
+ tracer_version: tracer_version
43
+ )
44
+ @env = env
45
+ @language_name = language_name
46
+ @language_version = language_version
47
+ @products = products
48
+ @runtime_name = runtime_name
49
+ @runtime_patches = runtime_patches
50
+ @runtime_version = runtime_version
51
+ @service_name = service_name
52
+ @service_version = service_version
53
+ @tracer_version = tracer_version
54
+ end
55
+
56
+ def to_h
57
+ {
58
+ env: @env,
59
+ language_name: @language_name,
60
+ language_version: @language_version,
61
+ products: @products.to_h,
62
+ runtime_name: @runtime_name,
63
+ runtime_patches: @runtime_patches,
64
+ runtime_version: @runtime_version,
65
+ service_name: @service_name,
66
+ service_version: @service_version,
67
+ tracer_version: @tracer_version
68
+ }
69
+ end
70
+
71
+ private
72
+
73
+ # Validates required arguments passed to the class on initialization are not nil
74
+ #
75
+ # @!visibility private
76
+ def validate(language_name:, language_version:, service_name:, tracer_version:)
77
+ raise ArgumentError, ERROR_NIL_LANGUAGE_NAME_MESSAGE if language_name.nil?
78
+ raise ArgumentError, ERROR_NIL_LANGUAGE_VERSION_MESSAGE if language_version.nil?
79
+ raise ArgumentError, ERROR_NIL_SERVICE_NAME_MESSAGE if service_name.nil?
80
+ raise ArgumentError, ERROR_NIL_TRACER_VERSION_MESSAGE if tracer_version.nil?
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,25 @@
1
+ module Datadog
2
+ module Core
3
+ module Telemetry
4
+ module V1
5
+ # Describes attributes for additional payload or configuration object
6
+ class Configuration
7
+ ERROR_NIL_NAME_MESSAGE = ':name must not be nil'.freeze
8
+
9
+ attr_reader \
10
+ :name,
11
+ :value
12
+
13
+ # @param name [String] Configuration/additional payload attribute name
14
+ # @param value [String, Integer, Boolean] Corresponding value
15
+ def initialize(name:, value: nil)
16
+ raise ArgumentError, ERROR_NIL_NAME_MESSAGE if name.nil?
17
+
18
+ @name = name
19
+ @value = value
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ module Datadog
2
+ module Core
3
+ module Telemetry
4
+ module V1
5
+ # Describes attributes for dependency object
6
+ class Dependency
7
+ ERROR_NIL_NAME_MESSAGE = ':name must not be nil'.freeze
8
+
9
+ attr_reader \
10
+ :hash,
11
+ :name,
12
+ :version
13
+
14
+ # @param name [String] Module name
15
+ # @param version [String] Version of resolved module
16
+ # @param hash [String] Dependency hash
17
+ def initialize(name:, version: nil, hash: nil)
18
+ raise ArgumentError, ERROR_NIL_NAME_MESSAGE if name.nil?
19
+
20
+ @hash = hash
21
+ @name = name
22
+ @version = version
23
+ end
24
+
25
+ def to_h
26
+ {
27
+ hash: @hash,
28
+ name: @name,
29
+ version: @version
30
+ }
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,51 @@
1
+ module Datadog
2
+ module Core
3
+ module Telemetry
4
+ module V1
5
+ # Describes attributes for host object
6
+ class Host
7
+ attr_reader \
8
+ :container_id,
9
+ :hostname,
10
+ :kernel_name,
11
+ :kernel_release,
12
+ :kernel_version,
13
+ :os_version,
14
+ :os
15
+
16
+ # @param container_id [String] Docker container ID
17
+ # @param hostname [String] uname -n
18
+ # @param kernel_name [String] uname -s
19
+ # @param kernel_release [String] uname -r
20
+ # @param kernel_version [String] uname -v
21
+ # @param os [String] uname -o
22
+ # @param os_version [String] Version of OS running
23
+ def initialize(
24
+ container_id: nil, hostname: nil, kernel_name: nil, kernel_release: nil, kernel_version: nil,
25
+ os_version: nil, os: nil
26
+ )
27
+ @container_id = container_id
28
+ @hostname = hostname
29
+ @kernel_name = kernel_name
30
+ @kernel_release = kernel_release
31
+ @kernel_version = kernel_version
32
+ @os = os
33
+ @os_version = os_version
34
+ end
35
+
36
+ def to_h
37
+ {
38
+ container_id: @container_id,
39
+ hostname: @hostname,
40
+ kernel_name: @kernel_name,
41
+ kernel_release: @kernel_release,
42
+ kernel_version: @kernel_version,
43
+ os: @os,
44
+ os_version: @os_version,
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,58 @@
1
+ module Datadog
2
+ module Core
3
+ module Telemetry
4
+ module V1
5
+ # Describes attributes for integration object
6
+ class Integration
7
+ ERROR_NIL_ENABLED_MESSAGE = ':enabled must not be nil'.freeze
8
+ ERROR_NIL_NAME_MESSAGE = ':name must not be nil'.freeze
9
+
10
+ attr_reader \
11
+ :auto_enabled,
12
+ :compatible,
13
+ :enabled,
14
+ :error,
15
+ :name,
16
+ :version
17
+
18
+ # @param enabled [Boolean] Whether integration is enabled at time of request
19
+ # @param name [String] Integration name
20
+ # @param auto_enabled [Boolean] If integration is not enabled by default, but by user choice
21
+ # @param compatible [Boolean] If integration is available, but incompatible
22
+ # @param error [String] Error message if integration fails to load
23
+ # @param version [String] Integration version (if specified in app-started, it should be for other events too)
24
+ def initialize(enabled:, name:, auto_enabled: nil, compatible: nil, error: nil, version: nil)
25
+ validate(enabled: enabled, name: name)
26
+ @auto_enabled = auto_enabled
27
+ @compatible = compatible
28
+ @enabled = enabled
29
+ @error = error
30
+ @name = name
31
+ @version = version
32
+ end
33
+
34
+ def to_h
35
+ {
36
+ auto_enabled: @auto_enabled,
37
+ compatible: @compatible,
38
+ enabled: @enabled,
39
+ error: @error,
40
+ name: @name,
41
+ version: @version
42
+ }
43
+ end
44
+
45
+ private
46
+
47
+ # Validates all required arguments passed to the class on initialization are not nil
48
+ #
49
+ # @!visibility private
50
+ def validate(enabled:, name:)
51
+ raise ArgumentError, ERROR_NIL_ENABLED_MESSAGE if enabled.nil?
52
+ raise ArgumentError, ERROR_NIL_NAME_MESSAGE if name.nil?
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,28 @@
1
+ module Datadog
2
+ module Core
3
+ module Telemetry
4
+ module V1
5
+ # Describes attributes for products object
6
+ class Product
7
+ attr_reader \
8
+ :appsec,
9
+ :profiler
10
+
11
+ # @param appsec [Telemetry::V1::AppSec] Holds custom information about the appsec product
12
+ # @param profiler [Telemetry::V1::Profiler] Holds custom information about the profiler product
13
+ def initialize(appsec: nil, profiler: nil)
14
+ @appsec = appsec
15
+ @profiler = profiler
16
+ end
17
+
18
+ def to_h
19
+ {
20
+ appsec: @appsec,
21
+ profiler: @profiler
22
+ }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end