hypertrace-agent 0.2.2 → 0.3.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 +4 -4
- data/lib/hypertrace/otlp_http_exporter.rb +118 -0
- data/lib/hypertrace/ruby_agent.rb +89 -44
- data/lib/hypertrace/version.rb +1 -1
- data/lib/hypertrace.rb +1 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f6326f5fd71561a9650dd5c9ad8098a9da9cf8d1632d86a4a708f4ef53d0c0d
|
4
|
+
data.tar.gz: 5e97a94ab436dfcf90a0f5d2c6b835fc4b5700798b0ce697a1ecc8d8a6ac3c4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 042e6e70677f70145a1f6acd60e59af6f560a0f1b496fd04833b0015ca0204b95a00d168d0a051207629cafc5843b3ae22fa54d0ab15a9fdf5d0b88c1e420c84
|
7
|
+
data.tar.gz: 0ac7871f61b712e9a85cb77e4bda7654bf7419b0444fcb17ecd180f8da58869ff941832556ae85b5d07861f34afb8b8477396330a53afbd2350af4f5a94e2461
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'opentelemetry/sdk'
|
2
|
+
require 'opentelemetry/exporter/otlp'
|
3
|
+
require 'opentelemetry/exporter/otlp/exporter'
|
4
|
+
|
5
|
+
class Hypertrace::OtlpHttpExporter < OpenTelemetry::Exporter::OTLP::Exporter
|
6
|
+
|
7
|
+
def initialize(endpoint: config_opt('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', 'OTEL_EXPORTER_OTLP_ENDPOINT', default: 'https://localhost:4318/v1/traces'), # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
8
|
+
certificate_file: config_opt('OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE', 'OTEL_EXPORTER_OTLP_CERTIFICATE'),
|
9
|
+
ssl_verify_mode: self.class.ssl_verify_mode,
|
10
|
+
headers: config_opt('OTEL_EXPORTER_OTLP_TRACES_HEADERS', 'OTEL_EXPORTER_OTLP_HEADERS', default: {}),
|
11
|
+
compression: config_opt('OTEL_EXPORTER_OTLP_TRACES_COMPRESSION', 'OTEL_EXPORTER_OTLP_COMPRESSION', default: 'gzip'),
|
12
|
+
timeout: config_opt('OTEL_EXPORTER_OTLP_TRACES_TIMEOUT', 'OTEL_EXPORTER_OTLP_TIMEOUT', default: 10),
|
13
|
+
metrics_reporter: nil,
|
14
|
+
allowed_request_headers: [],
|
15
|
+
allowed_response_headers: [],
|
16
|
+
drop_attributes: [],
|
17
|
+
supported_instrumentation_libraries: [],
|
18
|
+
use_all: false,
|
19
|
+
is_hypertrace: false,
|
20
|
+
custom_resource: nil
|
21
|
+
|
22
|
+
)
|
23
|
+
|
24
|
+
super(
|
25
|
+
endpoint: endpoint,
|
26
|
+
certificate_file: certificate_file,
|
27
|
+
ssl_verify_mode: ssl_verify_mode,
|
28
|
+
headers: headers,
|
29
|
+
compression: compression,
|
30
|
+
timeout: timeout,
|
31
|
+
metrics_reporter: metrics_reporter
|
32
|
+
)
|
33
|
+
|
34
|
+
# If a user specifies use_all that means we need to keep all spans
|
35
|
+
# If a user specifies supported libraries that means we should drop spans that aren't from those libraries
|
36
|
+
if use_all && supported_instrumentation_libraries.length > 0
|
37
|
+
raise ArgumentError.new("Must use either use_all or supported_instrumentation_libraries, cannot specify both")
|
38
|
+
end
|
39
|
+
|
40
|
+
# if passed is_hypertrace all spans + attributes will be kept, we should be the only one passing this
|
41
|
+
@is_hypertrace = is_hypertrace
|
42
|
+
# List of request headers to allow, not used by hypertrace
|
43
|
+
@allowed_request_headers = []
|
44
|
+
# List of response headers to allow, not used by hypertrace
|
45
|
+
@allowed_response_headers = []
|
46
|
+
allowed_request_headers.each do |req_header|
|
47
|
+
@allowed_request_headers << "http.request.header.#{req_header}"
|
48
|
+
end
|
49
|
+
allowed_response_headers.each do |res_header|
|
50
|
+
@allowed_response_headers << "http.response.header.#{res_header}"
|
51
|
+
end
|
52
|
+
# List of instrumentation libraries to report for this exporter
|
53
|
+
@supported_instrumentation_libraries = supported_instrumentation_libraries
|
54
|
+
# If c.use_all is used to configure OTEL sdk this option should be used
|
55
|
+
# We won't drop any spans based on Instrumentation library
|
56
|
+
@use_all = use_all
|
57
|
+
# List of attributes to always drop
|
58
|
+
@drop_attributes = drop_attributes
|
59
|
+
# An override resource object to override default configured resource
|
60
|
+
@custom_resource = custom_resource
|
61
|
+
end
|
62
|
+
|
63
|
+
def export(span_data, timeout: nil)
|
64
|
+
# Drop spans if not from a supported library
|
65
|
+
span_data = drop_extra_spans(span_data)
|
66
|
+
# Remove any attributes that shouldn't be reported
|
67
|
+
span_data = drop_attributes(span_data)
|
68
|
+
# Override the default configured resource - only used by Hypertrace
|
69
|
+
span_data = customize_resource(span_data)
|
70
|
+
super
|
71
|
+
end
|
72
|
+
|
73
|
+
def drop_extra_spans(span_data)
|
74
|
+
return span_data if @use_all
|
75
|
+
filtered_spans = span_data.select do |span|
|
76
|
+
name = span.instrumentation_library.name
|
77
|
+
# If a user uses a manually created span we should keep it, ex: instrumentation_library.name = "My-tracer"
|
78
|
+
# If a user is using an OTel Library the value will be like: OpenTelemetry::Instrumentation::Rack
|
79
|
+
!name.include?("OpenTelemetry") || @supported_instrumentation_libraries.include?(name)
|
80
|
+
end
|
81
|
+
filtered_spans
|
82
|
+
end
|
83
|
+
|
84
|
+
def drop_attributes span_data
|
85
|
+
return span_data if @is_hypertrace
|
86
|
+
span_data.each do |span|
|
87
|
+
new_attributes = {}
|
88
|
+
|
89
|
+
span[:attributes].each do |key, value|
|
90
|
+
if @drop_attributes.include?(key)
|
91
|
+
next
|
92
|
+
elsif key.start_with?('http.request.header.')
|
93
|
+
if @allowed_request_headers.include?(key)
|
94
|
+
new_attributes[key] = value
|
95
|
+
end
|
96
|
+
next
|
97
|
+
elsif key.start_with?('http.response.header.')
|
98
|
+
if @allowed_response_headers.include?(key)
|
99
|
+
new_attributes[key] = value
|
100
|
+
end
|
101
|
+
next
|
102
|
+
else
|
103
|
+
new_attributes[key] = value
|
104
|
+
end
|
105
|
+
end
|
106
|
+
span[:attributes] = new_attributes
|
107
|
+
end
|
108
|
+
span_data
|
109
|
+
end
|
110
|
+
|
111
|
+
def customize_resource span_data
|
112
|
+
return span_data unless @custom_resource
|
113
|
+
span_data.each do |span|
|
114
|
+
span.resource = @custom_resource
|
115
|
+
end
|
116
|
+
span_data
|
117
|
+
end
|
118
|
+
end
|
@@ -32,21 +32,48 @@ class Hypertrace::RubyAgent
|
|
32
32
|
include Hypertrace::Logging
|
33
33
|
include Singleton
|
34
34
|
|
35
|
+
SUPPORTED_INSTRUMENTATIONS = [
|
36
|
+
'OpenTelemetry::Instrumentation::ActionPack',
|
37
|
+
'OpenTelemetry::Instrumentation::ActionView',
|
38
|
+
'OpenTelemetry::Instrumentation::ActiveRecord',
|
39
|
+
'OpenTelemetry::Instrumentation::ActiveSupport',
|
40
|
+
'OpenTelemetry::Instrumentation::Faraday',
|
41
|
+
'OpenTelemetry::Instrumentation::Mongo',
|
42
|
+
'OpenTelemetry::Instrumentation::Mysql2',
|
43
|
+
'OpenTelemetry::Instrumentation::PG',
|
44
|
+
'OpenTelemetry::Instrumentation::Rack',
|
45
|
+
'OpenTelemetry::Instrumentation::Sinatra',
|
46
|
+
'OpenTelemetry::Instrumentation::Net::HTTP',
|
47
|
+
'OpenTelemetry::Instrumentation::HTTP',
|
48
|
+
'OpenTelemetry::Instrumentation::RestClient'
|
49
|
+
].freeze
|
50
|
+
|
51
|
+
SUPPORTED_INSTRUMENTATIONS_ADDITIONAL_PATCH = {
|
52
|
+
'OpenTelemetry::Instrumentation::Faraday' => ['./instrumentation/faraday_patch'],
|
53
|
+
'OpenTelemetry::Instrumentation::Rack' => ['./instrumentation/rack', './instrumentation/rack_env_getter'],
|
54
|
+
'OpenTelemetry::Instrumentation::Net::HTTP' => ['./instrumentation/net_http_patch'],
|
55
|
+
'OpenTelemetry::Instrumentation::HTTP' => ['./instrumentation/http_patch'],
|
56
|
+
'OpenTelemetry::Instrumentation::RestClient' => ['./instrumentation/rest_client_patch'],
|
57
|
+
}
|
58
|
+
|
35
59
|
def self.instrument!
|
36
60
|
self.instance.instrument!
|
37
61
|
end
|
38
62
|
|
63
|
+
def self.instrument_as_additional!
|
64
|
+
self.instance.instrument_as_additional!
|
65
|
+
end
|
66
|
+
|
39
67
|
def self.config
|
40
68
|
self.instance.config
|
41
69
|
end
|
42
70
|
|
43
71
|
def initialize(version = Hypertrace::VERSION)
|
44
|
-
log.info {"Initializing Hypertrace"}
|
45
|
-
configure_otel_logger!
|
72
|
+
log.info { "Initializing Hypertrace" }
|
46
73
|
@config = Hypertrace::Config::Config.new
|
47
74
|
@version = version
|
48
|
-
log.info {"Hypertrace version: #{Hypertrace::VERSION}"}
|
49
|
-
log.info {"Ruby version: #{RUBY_VERSION}"}
|
75
|
+
log.info { "Hypertrace version: #{Hypertrace::VERSION}" }
|
76
|
+
log.info { "Ruby version: #{RUBY_VERSION}" }
|
50
77
|
end
|
51
78
|
|
52
79
|
def config
|
@@ -57,47 +84,71 @@ class Hypertrace::RubyAgent
|
|
57
84
|
initalize_tracer
|
58
85
|
end
|
59
86
|
|
60
|
-
def
|
87
|
+
def instrument_as_additional!
|
61
88
|
resource = OpenTelemetry::SDK::Resources::Resource.create(create_resource_attributes)
|
89
|
+
exporter = create_resource_customized_exporter resource
|
90
|
+
span_processor = create_span_processor exporter
|
62
91
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
span_processor = OpenTelemetry::SDK::Trace::Export::SimpleSpanProcessor.new(EXPORTER)
|
68
|
-
c.add_span_processor span_processor
|
69
|
-
else
|
70
|
-
c.add_span_processor OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(exporter)
|
71
|
-
end
|
72
|
-
c.resource = resource
|
73
|
-
|
74
|
-
c.use 'OpenTelemetry::Instrumentation::ActionPack'
|
75
|
-
c.use 'OpenTelemetry::Instrumentation::ActionView'
|
76
|
-
c.use 'OpenTelemetry::Instrumentation::ActiveRecord'
|
77
|
-
c.use 'OpenTelemetry::Instrumentation::ActiveSupport'
|
78
|
-
c.use 'OpenTelemetry::Instrumentation::Faraday'
|
79
|
-
c.use 'OpenTelemetry::Instrumentation::Mongo'
|
80
|
-
c.use 'OpenTelemetry::Instrumentation::Mysql2'
|
81
|
-
c.use 'OpenTelemetry::Instrumentation::PG'
|
82
|
-
c.use 'OpenTelemetry::Instrumentation::Rack'
|
83
|
-
c.use 'OpenTelemetry::Instrumentation::Sinatra'
|
84
|
-
c.use 'OpenTelemetry::Instrumentation::Net::HTTP'
|
85
|
-
c.use 'OpenTelemetry::Instrumentation::HTTP'
|
86
|
-
c.use 'OpenTelemetry::Instrumentation::RestClient'
|
92
|
+
existing_processors = OpenTelemetry.tracer_provider.instance_variable_get(:"@span_processors")
|
93
|
+
if existing_processors.nil? || existing_processors&.empty?
|
94
|
+
log.error("No existing tracer_provider found, continuing without Hypertrace instrumentation")
|
95
|
+
return
|
87
96
|
end
|
97
|
+
existing_processors << span_processor
|
98
|
+
OpenTelemetry.tracer_provider.instance_variable_set(:'@span_processors', existing_processors)
|
99
|
+
# We don't pass a span_processor or resource because we have to add it to the already configured tracer provider
|
100
|
+
# The resource will be added at the export phase
|
101
|
+
configure_instrumentation nil, nil
|
102
|
+
configure_propagators
|
103
|
+
end
|
88
104
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
apply_custom_patch './instrumentation/rest_client_patch'
|
94
|
-
apply_custom_patch './instrumentation/rack_env_getter'
|
105
|
+
def create_span_processor exporter
|
106
|
+
return OpenTelemetry::SDK::Trace::Export::SimpleSpanProcessor.new(EXPORTER) if ENV['HT_CI_TEST'] != nil
|
107
|
+
return OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(exporter)
|
108
|
+
end
|
95
109
|
|
110
|
+
def initalize_tracer
|
111
|
+
resource = OpenTelemetry::SDK::Resources::Resource.create(create_resource_attributes)
|
112
|
+
exporter = create_exporter
|
113
|
+
span_processor = create_span_processor(exporter)
|
114
|
+
# TODO: Extra resource Attributes From Config
|
115
|
+
configure_instrumentation span_processor, resource
|
96
116
|
configure_propagators
|
97
117
|
end
|
98
118
|
|
119
|
+
def configure_instrumentation span_processor, resource
|
120
|
+
OpenTelemetry::SDK.configure do |c|
|
121
|
+
c.add_span_processor span_processor if span_processor
|
122
|
+
c.resource = resource if resource
|
123
|
+
|
124
|
+
SUPPORTED_INSTRUMENTATIONS.each do |instrumentation_string|
|
125
|
+
c.use instrumentation_string
|
126
|
+
additional_patches = SUPPORTED_INSTRUMENTATIONS_ADDITIONAL_PATCH[instrumentation_string]
|
127
|
+
if additional_patches
|
128
|
+
additional_patches.each do |patch_file|
|
129
|
+
apply_custom_patch patch_file
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
99
136
|
private
|
100
137
|
|
138
|
+
def create_resource_customized_exporter resource
|
139
|
+
exporter = nil
|
140
|
+
if config.reporting.trace_reporter_type == :OTLP
|
141
|
+
verify_mode = config.reporting.secure.value ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
142
|
+
exporter = Hypertrace::OtlpHttpExporter.new(endpoint: config.reporting.endpoint.value,
|
143
|
+
ssl_verify_mode: verify_mode,
|
144
|
+
is_hypertrace: true,
|
145
|
+
supported_instrumentation_libraries: SUPPORTED_INSTRUMENTATIONS,
|
146
|
+
custom_resource: resource)
|
147
|
+
return exporter
|
148
|
+
end
|
149
|
+
log.error "Resource customized exporter not supported for zipkin, only OTLP HTTP"
|
150
|
+
end
|
151
|
+
|
101
152
|
def create_exporter
|
102
153
|
exporter = nil
|
103
154
|
if config.reporting.trace_reporter_type == :OTLP
|
@@ -123,7 +174,7 @@ class Hypertrace::RubyAgent
|
|
123
174
|
end
|
124
175
|
end
|
125
176
|
if propagator_list.empty?
|
126
|
-
log.warn{"No propagators were added!"}
|
177
|
+
log.warn { "No propagators were added!" }
|
127
178
|
end
|
128
179
|
OpenTelemetry.propagation = OpenTelemetry::Context::Propagation::CompositeTextMapPropagator.compose_propagators(propagator_list.compact)
|
129
180
|
end
|
@@ -133,9 +184,9 @@ class Hypertrace::RubyAgent
|
|
133
184
|
def apply_custom_patch file
|
134
185
|
begin
|
135
186
|
require_relative file
|
136
|
-
log.debug{"Applied patch for #{file}"}
|
187
|
+
log.debug { "Applied patch for #{file}" }
|
137
188
|
rescue => _e
|
138
|
-
log.debug{"Unable to apply patch for #{file} this is most likely because the library is unavailable or an unsupported version"}
|
189
|
+
log.debug { "Unable to apply patch for #{file} this is most likely because the library is unavailable or an unsupported version" }
|
139
190
|
end
|
140
191
|
end
|
141
192
|
|
@@ -148,10 +199,4 @@ class Hypertrace::RubyAgent
|
|
148
199
|
'telemetry.sdk.language': 'ruby'
|
149
200
|
}.transform_keys(&:to_s)
|
150
201
|
end
|
151
|
-
|
152
|
-
NULL_LOGGER = Logger.new(File::NULL)
|
153
|
-
|
154
|
-
def configure_otel_logger!
|
155
|
-
OpenTelemetry.logger = NULL_LOGGER
|
156
|
-
end
|
157
202
|
end
|
data/lib/hypertrace/version.rb
CHANGED
data/lib/hypertrace.rb
CHANGED
@@ -8,6 +8,5 @@ require_relative './hypertrace/version'
|
|
8
8
|
require_relative './hypertrace/env_var_settings'
|
9
9
|
require_relative './hypertrace/logging'
|
10
10
|
require_relative './hypertrace/config'
|
11
|
+
require_relative './hypertrace/otlp_http_exporter'
|
11
12
|
require_relative './hypertrace/ruby_agent'
|
12
|
-
|
13
|
-
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hypertrace-agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- prodion23
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-protobuf
|
@@ -257,6 +257,7 @@ files:
|
|
257
257
|
- lib/hypertrace/instrumentation/rest_client_patch.rb
|
258
258
|
- lib/hypertrace/instrumentation/sinatra.rb
|
259
259
|
- lib/hypertrace/logging.rb
|
260
|
+
- lib/hypertrace/otlp_http_exporter.rb
|
260
261
|
- lib/hypertrace/ruby_agent.rb
|
261
262
|
- lib/hypertrace/version.rb
|
262
263
|
- release.sh
|