pingops 0.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +26 -0
- data/README.md +377 -0
- data/lib/pingops/core/body_capture.rb +102 -0
- data/lib/pingops/core/configuration.rb +181 -0
- data/lib/pingops/core/constants.rb +126 -0
- data/lib/pingops/core/context_keys.rb +96 -0
- data/lib/pingops/core/domain_filter.rb +123 -0
- data/lib/pingops/core/header_filter.rb +123 -0
- data/lib/pingops/core/id_generator.rb +78 -0
- data/lib/pingops/core/span_eligibility.rb +56 -0
- data/lib/pingops/core/types.rb +190 -0
- data/lib/pingops/errors.rb +15 -0
- data/lib/pingops/instrumentation/manager.rb +87 -0
- data/lib/pingops/instrumentation/net_http.rb +146 -0
- data/lib/pingops/otel/config_store.rb +101 -0
- data/lib/pingops/otel/span_processor.rb +293 -0
- data/lib/pingops/otel/tracer_provider.rb +93 -0
- data/lib/pingops/register.rb +48 -0
- data/lib/pingops/sdk.rb +291 -0
- data/lib/pingops/version.rb +5 -0
- data/lib/pingops.rb +160 -0
- data/pingops.gemspec +54 -0
- metadata +295 -0
data/lib/pingops/sdk.rb
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'opentelemetry-sdk'
|
|
4
|
+
require 'opentelemetry-api'
|
|
5
|
+
|
|
6
|
+
module Pingops
|
|
7
|
+
# Main SDK module providing the public API
|
|
8
|
+
module SDK
|
|
9
|
+
@initialized = false
|
|
10
|
+
@config = nil
|
|
11
|
+
@span_processor = nil
|
|
12
|
+
@mutex = Mutex.new
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
# Initialize the PingOps SDK
|
|
16
|
+
#
|
|
17
|
+
# @overload initialize(config)
|
|
18
|
+
# @param config [Hash, Core::Configuration] Full processor config object
|
|
19
|
+
# @overload initialize(config_file_path)
|
|
20
|
+
# @param config_file_path [String] Path to a JSON or YAML config file
|
|
21
|
+
# @overload initialize(config)
|
|
22
|
+
# @param config [Hash] Hash with :config_file key pointing to config file
|
|
23
|
+
#
|
|
24
|
+
# @raise [Pingops::ConfigurationError] if required fields are missing
|
|
25
|
+
# @return [void]
|
|
26
|
+
def initialize_pingops(config)
|
|
27
|
+
@mutex.synchronize do
|
|
28
|
+
if @initialized
|
|
29
|
+
log_debug('SDK already initialized, skipping')
|
|
30
|
+
return
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Resolve configuration
|
|
34
|
+
resolved_config = resolve_config(config)
|
|
35
|
+
resolved_config.validate!
|
|
36
|
+
|
|
37
|
+
@config = resolved_config
|
|
38
|
+
log_debug("Configuration resolved: service_name=#{resolved_config.service_name}")
|
|
39
|
+
|
|
40
|
+
# Create resource with service.name
|
|
41
|
+
resource = create_resource(resolved_config)
|
|
42
|
+
|
|
43
|
+
# Create span processor
|
|
44
|
+
@span_processor = Otel::SpanProcessor.new(resolved_config)
|
|
45
|
+
log_debug('Span processor created')
|
|
46
|
+
|
|
47
|
+
# Install instrumentations
|
|
48
|
+
Instrumentation::Manager.install(resolved_config)
|
|
49
|
+
|
|
50
|
+
# Configure OpenTelemetry SDK
|
|
51
|
+
configure_otel_sdk(resource, @span_processor, resolved_config)
|
|
52
|
+
|
|
53
|
+
# Create and register isolated TracerProvider
|
|
54
|
+
isolated_provider = Otel::TracerProvider.create_isolated(
|
|
55
|
+
resource: resource,
|
|
56
|
+
span_processor: @span_processor
|
|
57
|
+
)
|
|
58
|
+
Otel::TracerProvider.set(isolated_provider)
|
|
59
|
+
|
|
60
|
+
# Register as global provider (after main SDK, so it becomes the default)
|
|
61
|
+
OpenTelemetry.tracer_provider = isolated_provider
|
|
62
|
+
|
|
63
|
+
@initialized = true
|
|
64
|
+
log_debug('SDK initialized successfully')
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Shutdown the PingOps SDK
|
|
69
|
+
# Shuts down isolated TracerProvider first, then main OTEL SDK
|
|
70
|
+
#
|
|
71
|
+
# @return [void]
|
|
72
|
+
def shutdown_pingops
|
|
73
|
+
@mutex.synchronize do
|
|
74
|
+
return unless @initialized
|
|
75
|
+
|
|
76
|
+
log_debug('Shutting down SDK...')
|
|
77
|
+
|
|
78
|
+
# 1. Shutdown isolated TracerProvider
|
|
79
|
+
Otel::TracerProvider.shutdown
|
|
80
|
+
|
|
81
|
+
# 2. Shutdown span processor
|
|
82
|
+
@span_processor&.shutdown
|
|
83
|
+
|
|
84
|
+
# 3. Clear instrumentations
|
|
85
|
+
Instrumentation::Manager.reset!
|
|
86
|
+
|
|
87
|
+
# 4. Clear state
|
|
88
|
+
@initialized = false
|
|
89
|
+
@config = nil
|
|
90
|
+
@span_processor = nil
|
|
91
|
+
|
|
92
|
+
log_debug('SDK shutdown complete')
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Start a trace with custom attributes
|
|
97
|
+
#
|
|
98
|
+
# @param options [Hash, Core::StartTraceOptions] Trace options
|
|
99
|
+
# @option options [Hash, Core::TraceAttributes] :attributes Custom attributes
|
|
100
|
+
# @option options [String] :seed Optional seed for deterministic trace ID
|
|
101
|
+
# @yield Block to execute within the trace
|
|
102
|
+
# @return [Object] Result of the block
|
|
103
|
+
#
|
|
104
|
+
# @example
|
|
105
|
+
# Pingops.start_trace(attributes: { user_id: "123" }) do
|
|
106
|
+
# # Make HTTP requests here
|
|
107
|
+
# Net::HTTP.get(URI("https://api.example.com"))
|
|
108
|
+
# end
|
|
109
|
+
def start_trace(options = {}, &block)
|
|
110
|
+
raise ArgumentError, 'Block required for start_trace' unless block_given?
|
|
111
|
+
|
|
112
|
+
# Auto-initialize if not initialized
|
|
113
|
+
auto_initialize_if_needed
|
|
114
|
+
|
|
115
|
+
opts = options.is_a?(Core::StartTraceOptions) ? options : Core::StartTraceOptions.from_hash(options)
|
|
116
|
+
|
|
117
|
+
# Compute trace ID
|
|
118
|
+
trace_id = compute_trace_id(opts)
|
|
119
|
+
span_id = Core::IdGenerator.generate_span_id
|
|
120
|
+
|
|
121
|
+
# Create span context
|
|
122
|
+
span_context = OpenTelemetry::Trace::SpanContext.new(
|
|
123
|
+
trace_id: Core::IdGenerator.trace_id_to_bytes(trace_id),
|
|
124
|
+
span_id: Core::IdGenerator.span_id_to_bytes(span_id),
|
|
125
|
+
trace_flags: OpenTelemetry::Trace::TraceFlags::SAMPLED
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Get current context and set trace ID
|
|
129
|
+
context = OpenTelemetry::Context.current
|
|
130
|
+
context = Core::ContextKeys.set_trace_id(context, trace_id)
|
|
131
|
+
|
|
132
|
+
# Set attributes on context if provided
|
|
133
|
+
context = Core::ContextKeys.set_attributes(context, opts.attributes) if opts.attributes
|
|
134
|
+
|
|
135
|
+
# Get tracer from PingOps provider
|
|
136
|
+
tracer = Otel::TracerProvider.tracer
|
|
137
|
+
|
|
138
|
+
# Create a non-recording span to establish the context
|
|
139
|
+
parent_span = OpenTelemetry::Trace.non_recording_span(span_context)
|
|
140
|
+
context = OpenTelemetry::Trace.context_with_span(parent_span, parent_context: context)
|
|
141
|
+
|
|
142
|
+
# Run the block within the span context
|
|
143
|
+
OpenTelemetry::Context.with_current(context) do
|
|
144
|
+
tracer.in_span(
|
|
145
|
+
Core::Constants::ROOT_SPAN_NAME,
|
|
146
|
+
kind: :internal,
|
|
147
|
+
&block
|
|
148
|
+
)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Get the active trace ID from the current context
|
|
153
|
+
#
|
|
154
|
+
# @return [String, nil] The trace ID or nil if no active span
|
|
155
|
+
def active_trace_id
|
|
156
|
+
span = OpenTelemetry::Trace.current_span
|
|
157
|
+
return nil unless span
|
|
158
|
+
|
|
159
|
+
span_context = span.context
|
|
160
|
+
return nil unless span_context&.valid?
|
|
161
|
+
|
|
162
|
+
Core::IdGenerator.bytes_to_trace_id(span_context.trace_id)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Get the active span ID from the current context
|
|
166
|
+
#
|
|
167
|
+
# @return [String, nil] The span ID or nil if no active span
|
|
168
|
+
def active_span_id
|
|
169
|
+
span = OpenTelemetry::Trace.current_span
|
|
170
|
+
return nil unless span
|
|
171
|
+
|
|
172
|
+
span_context = span.context
|
|
173
|
+
return nil unless span_context&.valid?
|
|
174
|
+
|
|
175
|
+
Core::IdGenerator.bytes_to_span_id(span_context.span_id)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Check if the SDK is initialized
|
|
179
|
+
#
|
|
180
|
+
# @return [Boolean]
|
|
181
|
+
def initialized?
|
|
182
|
+
@mutex.synchronize do
|
|
183
|
+
@initialized
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Get the current configuration
|
|
188
|
+
#
|
|
189
|
+
# @return [Core::Configuration, nil]
|
|
190
|
+
def configuration
|
|
191
|
+
@mutex.synchronize do
|
|
192
|
+
@config
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Reset SDK state (for testing)
|
|
197
|
+
# @api private
|
|
198
|
+
def reset!
|
|
199
|
+
@mutex.synchronize do
|
|
200
|
+
Otel::TracerProvider.clear!
|
|
201
|
+
Otel::ConfigStore.clear!
|
|
202
|
+
Instrumentation::Manager.reset!
|
|
203
|
+
@initialized = false
|
|
204
|
+
@config = nil
|
|
205
|
+
@span_processor = nil
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
private
|
|
210
|
+
|
|
211
|
+
def resolve_config(config)
|
|
212
|
+
case config
|
|
213
|
+
when String
|
|
214
|
+
# File path
|
|
215
|
+
Core::Configuration.load_with_env(config)
|
|
216
|
+
when Hash
|
|
217
|
+
if config[:config_file] || config['configFile']
|
|
218
|
+
# Hash with config_file key
|
|
219
|
+
file_path = config[:config_file] || config['configFile']
|
|
220
|
+
Core::Configuration.load_with_env(file_path)
|
|
221
|
+
else
|
|
222
|
+
# Regular config hash - merge with env
|
|
223
|
+
base_config = Core::Configuration.from_hash(config)
|
|
224
|
+
env_config = Core::Configuration.from_env
|
|
225
|
+
Core::Configuration.merge(base_config, env_config)
|
|
226
|
+
end
|
|
227
|
+
when Core::Configuration
|
|
228
|
+
# Already a Configuration object
|
|
229
|
+
config
|
|
230
|
+
else
|
|
231
|
+
raise ArgumentError, "Invalid config type: #{config.class}"
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def create_resource(config)
|
|
236
|
+
OpenTelemetry::SDK::Resources::Resource.create(
|
|
237
|
+
'service.name' => config.service_name
|
|
238
|
+
)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def configure_otel_sdk(resource, _span_processor, _config)
|
|
242
|
+
OpenTelemetry::SDK.configure do |c|
|
|
243
|
+
c.resource = resource
|
|
244
|
+
|
|
245
|
+
# Get instrumentations
|
|
246
|
+
Instrumentation::Manager.otel_instrumentations.each do |instrumentation|
|
|
247
|
+
c.use(instrumentation.class.name.split('::').last)
|
|
248
|
+
rescue StandardError
|
|
249
|
+
# Ignore if instrumentation can't be used
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def auto_initialize_if_needed
|
|
255
|
+
return if initialized?
|
|
256
|
+
|
|
257
|
+
# Check for required environment variables
|
|
258
|
+
api_key = ENV.fetch('PINGOPS_API_KEY', nil)
|
|
259
|
+
base_url = ENV.fetch('PINGOPS_BASE_URL', nil)
|
|
260
|
+
service_name = ENV.fetch('PINGOPS_SERVICE_NAME', nil)
|
|
261
|
+
|
|
262
|
+
missing = []
|
|
263
|
+
missing << 'PINGOPS_API_KEY' unless api_key
|
|
264
|
+
missing << 'PINGOPS_BASE_URL' unless base_url
|
|
265
|
+
missing << 'PINGOPS_SERVICE_NAME' unless service_name
|
|
266
|
+
|
|
267
|
+
raise ConfigurationError, "Auto-initialization requires: #{missing.join(', ')}" unless missing.empty?
|
|
268
|
+
|
|
269
|
+
# Initialize from environment
|
|
270
|
+
initialize_pingops(Core::Configuration.from_env)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def compute_trace_id(options)
|
|
274
|
+
# Priority: attributes.traceId > seed > random
|
|
275
|
+
if options.attributes&.trace_id
|
|
276
|
+
options.attributes.trace_id
|
|
277
|
+
elsif options.seed
|
|
278
|
+
Core::IdGenerator.generate_trace_id(options.seed)
|
|
279
|
+
else
|
|
280
|
+
Core::IdGenerator.generate_trace_id
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def log_debug(message)
|
|
285
|
+
return unless @config&.debug
|
|
286
|
+
|
|
287
|
+
puts "[Pingops DEBUG] #{message}"
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
data/lib/pingops.rb
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'pingops/version'
|
|
4
|
+
require_relative 'pingops/errors'
|
|
5
|
+
|
|
6
|
+
# Core components (pure logic, no OpenTelemetry dependencies loaded yet)
|
|
7
|
+
require_relative 'pingops/core/constants'
|
|
8
|
+
require_relative 'pingops/core/types'
|
|
9
|
+
require_relative 'pingops/core/configuration'
|
|
10
|
+
require_relative 'pingops/core/id_generator'
|
|
11
|
+
require_relative 'pingops/core/domain_filter'
|
|
12
|
+
require_relative 'pingops/core/header_filter'
|
|
13
|
+
require_relative 'pingops/core/span_eligibility'
|
|
14
|
+
require_relative 'pingops/core/body_capture'
|
|
15
|
+
require_relative 'pingops/core/context_keys'
|
|
16
|
+
|
|
17
|
+
# OpenTelemetry integration
|
|
18
|
+
require_relative 'pingops/otel/config_store'
|
|
19
|
+
require_relative 'pingops/otel/tracer_provider'
|
|
20
|
+
require_relative 'pingops/otel/span_processor'
|
|
21
|
+
|
|
22
|
+
# Instrumentation
|
|
23
|
+
require_relative 'pingops/instrumentation/net_http'
|
|
24
|
+
require_relative 'pingops/instrumentation/manager'
|
|
25
|
+
|
|
26
|
+
# SDK public API
|
|
27
|
+
require_relative 'pingops/sdk'
|
|
28
|
+
|
|
29
|
+
# Main Pingops module
|
|
30
|
+
# Provides a convenient interface to the PingOps SDK
|
|
31
|
+
module Pingops
|
|
32
|
+
class << self
|
|
33
|
+
# Initialize the PingOps SDK
|
|
34
|
+
#
|
|
35
|
+
# @overload initialize(config)
|
|
36
|
+
# @param config [Hash] Full processor config object
|
|
37
|
+
# @overload initialize(config_file_path)
|
|
38
|
+
# @param config_file_path [String] Path to a JSON or YAML config file
|
|
39
|
+
#
|
|
40
|
+
# @example Initialize with a hash
|
|
41
|
+
# Pingops.initialize(
|
|
42
|
+
# api_key: "your-api-key",
|
|
43
|
+
# base_url: "https://api.pingops.com",
|
|
44
|
+
# service_name: "my-service"
|
|
45
|
+
# )
|
|
46
|
+
#
|
|
47
|
+
# @example Initialize with a config file
|
|
48
|
+
# Pingops.initialize("/path/to/pingops.json")
|
|
49
|
+
#
|
|
50
|
+
# @example Initialize with camelCase keys (compatible with JS/Node)
|
|
51
|
+
# Pingops.initialize(
|
|
52
|
+
# apiKey: "your-api-key",
|
|
53
|
+
# baseUrl: "https://api.pingops.com",
|
|
54
|
+
# serviceName: "my-service"
|
|
55
|
+
# )
|
|
56
|
+
#
|
|
57
|
+
# @raise [Pingops::ConfigurationError] if required fields are missing
|
|
58
|
+
# @return [void]
|
|
59
|
+
def initialize(config = nil)
|
|
60
|
+
if config.nil?
|
|
61
|
+
# Try to initialize from environment
|
|
62
|
+
SDK.initialize_pingops(Core::Configuration.from_env)
|
|
63
|
+
else
|
|
64
|
+
SDK.initialize_pingops(config)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Shutdown the PingOps SDK
|
|
69
|
+
#
|
|
70
|
+
# @return [void]
|
|
71
|
+
def shutdown
|
|
72
|
+
SDK.shutdown_pingops
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Start a trace with custom attributes
|
|
76
|
+
#
|
|
77
|
+
# @param options [Hash] Trace options
|
|
78
|
+
# @option options [Hash] :attributes Custom attributes (user_id, session_id, tags, metadata)
|
|
79
|
+
# @option options [String] :seed Optional seed for deterministic trace ID
|
|
80
|
+
# @yield Block to execute within the trace
|
|
81
|
+
# @return [Object] Result of the block
|
|
82
|
+
#
|
|
83
|
+
# @example Basic usage
|
|
84
|
+
# Pingops.start_trace do
|
|
85
|
+
# Net::HTTP.get(URI("https://api.example.com"))
|
|
86
|
+
# end
|
|
87
|
+
#
|
|
88
|
+
# @example With custom attributes
|
|
89
|
+
# Pingops.start_trace(
|
|
90
|
+
# attributes: {
|
|
91
|
+
# user_id: "user-123",
|
|
92
|
+
# session_id: "session-456",
|
|
93
|
+
# tags: ["production", "web"],
|
|
94
|
+
# metadata: { "request_id" => "abc123" }
|
|
95
|
+
# }
|
|
96
|
+
# ) do
|
|
97
|
+
# # Your code here
|
|
98
|
+
# end
|
|
99
|
+
#
|
|
100
|
+
# @example With deterministic trace ID
|
|
101
|
+
# Pingops.start_trace(seed: "my-unique-seed") do
|
|
102
|
+
# # Same seed always produces the same trace ID
|
|
103
|
+
# end
|
|
104
|
+
def start_trace(options = {}, &block)
|
|
105
|
+
SDK.start_trace(options, &block)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Get the active trace ID from the current context
|
|
109
|
+
#
|
|
110
|
+
# @return [String, nil] The trace ID or nil if no active span
|
|
111
|
+
#
|
|
112
|
+
# @example
|
|
113
|
+
# Pingops.start_trace do
|
|
114
|
+
# trace_id = Pingops.active_trace_id
|
|
115
|
+
# puts "Current trace ID: #{trace_id}"
|
|
116
|
+
# end
|
|
117
|
+
def active_trace_id
|
|
118
|
+
SDK.active_trace_id
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Get the active span ID from the current context
|
|
122
|
+
#
|
|
123
|
+
# @return [String, nil] The span ID or nil if no active span
|
|
124
|
+
#
|
|
125
|
+
# @example
|
|
126
|
+
# Pingops.start_trace do
|
|
127
|
+
# span_id = Pingops.active_span_id
|
|
128
|
+
# puts "Current span ID: #{span_id}"
|
|
129
|
+
# end
|
|
130
|
+
def active_span_id
|
|
131
|
+
SDK.active_span_id
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Check if the SDK is initialized
|
|
135
|
+
#
|
|
136
|
+
# @return [Boolean]
|
|
137
|
+
def initialized?
|
|
138
|
+
SDK.initialized?
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Get the current configuration
|
|
142
|
+
#
|
|
143
|
+
# @return [Pingops::Core::Configuration, nil]
|
|
144
|
+
def configuration
|
|
145
|
+
SDK.configuration
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Alias for initialize (follows JS/Node naming convention)
|
|
149
|
+
alias initialize_pingops initialize
|
|
150
|
+
|
|
151
|
+
# Alias for shutdown (follows JS/Node naming convention)
|
|
152
|
+
alias shutdown_pingops shutdown
|
|
153
|
+
|
|
154
|
+
# Alias for active_trace_id (follows JS/Node naming convention)
|
|
155
|
+
alias get_active_trace_id active_trace_id
|
|
156
|
+
|
|
157
|
+
# Alias for active_span_id (follows JS/Node naming convention)
|
|
158
|
+
alias get_active_span_id active_span_id
|
|
159
|
+
end
|
|
160
|
+
end
|
data/pingops.gemspec
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/pingops/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'pingops'
|
|
7
|
+
spec.version = Pingops::VERSION
|
|
8
|
+
spec.authors = ['PingOps']
|
|
9
|
+
spec.email = ['support@pingops.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'PingOps SDK for Ruby - OpenTelemetry-based HTTP tracing'
|
|
12
|
+
spec.description = 'Instruments outgoing HTTP requests, exports spans to PingOps backend via OTLP, ' \
|
|
13
|
+
'and supports manual tracing with custom attributes, domain filtering, and header redaction.'
|
|
14
|
+
spec.homepage = 'https://github.com/pingops/pingops-rb'
|
|
15
|
+
spec.license = 'MIT'
|
|
16
|
+
spec.required_ruby_version = '>= 3.0.0'
|
|
17
|
+
|
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
19
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
|
20
|
+
spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
21
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
22
|
+
|
|
23
|
+
spec.files = Dir.glob('{lib,exe}/**/*') + %w[
|
|
24
|
+
README.md
|
|
25
|
+
CHANGELOG.md
|
|
26
|
+
pingops.gemspec
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
spec.bindir = 'exe'
|
|
30
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
31
|
+
spec.require_paths = ['lib']
|
|
32
|
+
|
|
33
|
+
# OpenTelemetry dependencies
|
|
34
|
+
spec.add_dependency 'opentelemetry-api', '~> 1.2'
|
|
35
|
+
spec.add_dependency 'opentelemetry-exporter-otlp', '~> 0.28'
|
|
36
|
+
spec.add_dependency 'opentelemetry-instrumentation-faraday', '~> 0.24'
|
|
37
|
+
spec.add_dependency 'opentelemetry-instrumentation-http_client', '~> 0.22'
|
|
38
|
+
spec.add_dependency 'opentelemetry-instrumentation-net_http', '~> 0.22'
|
|
39
|
+
spec.add_dependency 'opentelemetry-sdk', '~> 1.4'
|
|
40
|
+
|
|
41
|
+
# Configuration
|
|
42
|
+
spec.add_dependency 'base64', '~> 0.2'
|
|
43
|
+
spec.add_dependency 'json', '~> 2.0'
|
|
44
|
+
|
|
45
|
+
# Development dependencies
|
|
46
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
47
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
48
|
+
spec.add_development_dependency 'rspec', '~> 3.12'
|
|
49
|
+
spec.add_development_dependency 'rubocop', '~> 1.50'
|
|
50
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.20'
|
|
51
|
+
spec.add_development_dependency 'simplecov', '~> 0.22'
|
|
52
|
+
spec.add_development_dependency 'webmock', '~> 3.18'
|
|
53
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
|
54
|
+
end
|