opentelemetry-exporters-datadog 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2020 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ require 'opentelemetry/sdk'
8
+ require 'opentelemetry/context/propagation'
9
+ require 'ddtrace/distributed_tracing/headers/headers'
10
+ require 'ddtrace/distributed_tracing/headers/helpers'
11
+
12
+ module OpenTelemetry
13
+ module Exporters
14
+ module Datadog
15
+ # Injects context into carriers using the W3C Trace Context format
16
+ class Propagator
17
+ include OpenTelemetry::Context::Propagation::DefaultSetter
18
+ include OpenTelemetry::Context::Propagation::DefaultGetter
19
+
20
+ TRACE_ID_KEY = 'x-datadog-trace-id'
21
+ PARENT_ID_KEY = 'x-datadog-parent-id'
22
+ SAMPLING_PRIORITY_KEY = 'x-datadog-sampling-priority'
23
+ ORIGIN_KEY = 'x-datadog-origin'
24
+ DD_ORIGIN = '_dd_origin'
25
+ ORIGIN_REGEX = /#{DD_ORIGIN}\=(.*?)($|,)/.freeze
26
+ DEFAULT_INJECTORS = [
27
+ OpenTelemetry::Trace::Propagation::TraceContext.text_injector,
28
+ OpenTelemetry::CorrelationContext::Propagation.text_injector
29
+ ].freeze
30
+
31
+ DEFAULT_EXTRACTORS = [
32
+ OpenTelemetry::Trace::Propagation::TraceContext.rack_extractor,
33
+ OpenTelemetry::CorrelationContext::Propagation.rack_extractor
34
+ ].freeze
35
+
36
+ # Returns a new Propagator
37
+ def initialize
38
+ # pass
39
+ @truncation_helper = ::Datadog::DistributedTracing::Headers::Headers.new({})
40
+ end
41
+
42
+ # Set the span context on the supplied carrier.
43
+ #
44
+ # @param [Context] context The active {Context}.
45
+ # @param [optional Callable] setter An optional callable that takes a carrier and a key and
46
+ # a value and assigns the key-value pair in the carrier. If omitted the default setter
47
+ # will be used which expects the carrier to respond to [] and []=.
48
+ # @return [Object] the carrier with context injected
49
+ def inject(carrier, context, &setter)
50
+ return carrier unless (span_context = span_context_from(context))
51
+
52
+ sampled = span_context.trace_flags&.sampled? ? 1 : 0
53
+
54
+ origin = get_origin_string(span_context.tracestate)
55
+ setter ||= DEFAULT_SETTER
56
+ setter.call(carrier, PARENT_ID_KEY, @truncation_helper.value_to_id(span_context.span_id.unpack1('H*'), 16).to_s)
57
+ setter.call(carrier, TRACE_ID_KEY, @truncation_helper.value_to_id(span_context.trace_id.unpack1('H*'), 16).to_s)
58
+ setter.call(carrier, SAMPLING_PRIORITY_KEY, sampled.to_s)
59
+ setter.call(carrier, ORIGIN_KEY, origin) if origin
60
+
61
+ carrier
62
+ end
63
+
64
+ # Extract a remote {Trace::SpanContext} from the supplied carrier.
65
+ # Invalid headers will result in a new, valid, non-remote {Trace::SpanContext}.
66
+ #
67
+ # @param [Carrier] carrier The carrier to get the header from.
68
+ # @param [Context] context The context to be updated with extracted context
69
+ # @param [optional Callable] getter An optional callable that takes a carrier and a key and
70
+ # returns the value associated with the key. If omitted the default getter will be used
71
+ # which expects the carrier to respond to [] and []=.
72
+ # @yield [Carrier, String] if an optional getter is provided, extract will yield the carrier
73
+ # and the header key to the getter.
74
+ # @return [Context] Updated context with span context from the header, or the original
75
+ # context if parsing fails.
76
+ def extract(carrier, context, &getter)
77
+ getter ||= default_getter
78
+ trace_id = getter.call(carrier, TRACE_ID_KEY) || getter.call(carrier, rack_helper(TRACE_ID_KEY))
79
+ span_id = getter.call(carrier, PARENT_ID_KEY) || getter.call(carrier, rack_helper(PARENT_ID_KEY))
80
+ sampled = getter.call(carrier, SAMPLING_PRIORITY_KEY) || getter.call(carrier, rack_helper(SAMPLING_PRIORITY_KEY))
81
+ origin = getter.call(carrier, ORIGIN_KEY) || getter.call(carrier, rack_helper(ORIGIN_KEY))
82
+
83
+ is_sampled = sampled.to_i.positive? ? 1 : 0
84
+
85
+ tracestate = origin ? "#{DD_ORIGIN}=#{origin}" : nil
86
+
87
+ return context if trace_id.nil? || span_id.nil?
88
+
89
+ span_context = Trace::SpanContext.new(trace_id: Array(trace_id.to_i.to_s(16)).pack('H*'),
90
+ span_id: Array(span_id.to_i.to_s(16)).pack('H*'),
91
+ trace_flags: OpenTelemetry::Trace::TraceFlags.from_byte(is_sampled),
92
+ tracestate: tracestate,
93
+ remote: true)
94
+
95
+ context.set_value(Trace::Propagation::ContextKeys.extracted_span_context_key, span_context)
96
+ rescue StandardError => e
97
+ OpenTelemetry.logger.debug("error extracting datadog propagation, #{e.message}")
98
+ context
99
+ end
100
+
101
+ def self.auto_configure
102
+ default_propagator = new
103
+ updated_injectors = DEFAULT_INJECTORS + [default_propagator]
104
+ updated_extractors = DEFAULT_EXTRACTORS + [default_propagator]
105
+ OpenTelemetry.propagation.http = OpenTelemetry::Context::Propagation::CompositePropagator.new(
106
+ updated_injectors,
107
+ updated_extractors
108
+ )
109
+ end
110
+
111
+ private
112
+
113
+ # account for rack re-formatting of headers
114
+ def rack_helper(header)
115
+ "HTTP_#{header.to_s.upcase.gsub(/[-\s]/, '_')}"
116
+ end
117
+
118
+ def span_context_from(context)
119
+ context[Trace::Propagation::ContextKeys.current_span_key]&.context ||
120
+ context[Trace::Propagation::ContextKeys.extracted_span_context_key]
121
+ end
122
+
123
+ def get_origin_string(tracestate)
124
+ return if tracestate.nil? || tracestate.index(DD_ORIGIN).nil?
125
+
126
+ # Depending on the edge cases in tracestate values this might be
127
+ # less efficient than mapping string => array => hash.
128
+ origin_value = tracestate.match(ORIGIN_REGEX)
129
+ return if origin_value.nil?
130
+
131
+ origin_value[1]
132
+ rescue StandardError => e
133
+ OpenTelemetry.logger.debug("error getting origin from trace state, #{e.message}")
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Unless explicitly stated otherwise all files in this repository are licensed
4
+ # under the Apache 2.0 license (see LICENSE).
5
+ # This product includes software developed at Datadog (https://www.datadoghq.com/).
6
+ # Copyright 2020 Datadog, Inc.
7
+
8
+ module OpenTelemetry
9
+ module Exporters
10
+ module Datadog
11
+ ## Current OpenTelemetry Datadog exporter version
12
+ VERSION = '0.1.0'
13
+ end
14
+ end
15
+ end
metadata ADDED
@@ -0,0 +1,214 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: opentelemetry-exporters-datadog
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Datadog, Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-07-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ddtrace
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.37'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.37'
27
+ - !ruby/object:Gem::Dependency
28
+ name: opentelemetry-api
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: opentelemetry-sdk
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.5'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '1.17'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '1.17'
69
+ - !ruby/object:Gem::Dependency
70
+ name: faraday
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.13'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.13'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '5.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '12.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '12.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.73.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.73.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.17'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.17'
139
+ - !ruby/object:Gem::Dependency
140
+ name: yard
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.9'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.9'
153
+ - !ruby/object:Gem::Dependency
154
+ name: yard-doctest
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: 0.1.6
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: 0.1.6
167
+ description: |
168
+ opentelemetry-exporters-datadog is Datadog’s trace exporter for the OpenTelemetry
169
+ Ruby tracing library, which is used to trace requests across web servers, databases
170
+ and microservices. The exporter formats and sends these traces to a Datadog Agent so
171
+ that they can be ingested, stored, and analyzed with Datadog.
172
+ email:
173
+ - dev@datadoghq.com
174
+ executables: []
175
+ extensions: []
176
+ extra_rdoc_files: []
177
+ files:
178
+ - ".yardopts"
179
+ - CHANGELOG.md
180
+ - CONTRIBUTING.md
181
+ - LICENSE
182
+ - README.md
183
+ - lib/opentelemetry-exporters-datadog.rb
184
+ - lib/opentelemetry/exporters/datadog.rb
185
+ - lib/opentelemetry/exporters/datadog/datadog_probability_sampler.rb
186
+ - lib/opentelemetry/exporters/datadog/datadog_span_processor.rb
187
+ - lib/opentelemetry/exporters/datadog/exporter.rb
188
+ - lib/opentelemetry/exporters/datadog/exporter/span_encoder.rb
189
+ - lib/opentelemetry/exporters/datadog/propagator.rb
190
+ - lib/opentelemetry/exporters/datadog/version.rb
191
+ homepage: https://github.com/Datadog/dd-opentelemetry-exporter-ruby
192
+ licenses:
193
+ - Apache-2.0
194
+ metadata: {}
195
+ post_install_message:
196
+ rdoc_options: []
197
+ require_paths:
198
+ - lib
199
+ required_ruby_version: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - ">="
202
+ - !ruby/object:Gem::Version
203
+ version: 2.5.0
204
+ required_rubygems_version: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ requirements: []
210
+ rubygems_version: 3.0.3
211
+ signing_key:
212
+ specification_version: 4
213
+ summary: Datadog trace exporter for the OpenTelemetry framework
214
+ test_files: []