gitlab-labkit 1.6.0 → 1.6.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 +4 -4
- data/.copier-answers.yml +2 -1
- data/.releaserc.json +7 -1
- data/lib/labkit/net_http_publisher.rb +20 -1
- data/lib/labkit/tracing/README.md +50 -25
- data/lib/labkit/tracing/abstract_instrumenter.rb +7 -8
- data/lib/labkit/tracing/adapters/opentelemetry_span.rb +4 -0
- data/lib/labkit/tracing/adapters/opentelemetry_tracer.rb +12 -0
- data/lib/labkit/tracing/adapters/opentracing_span.rb +4 -0
- data/lib/labkit/tracing/adapters/opentracing_tracer.rb +9 -6
- data/lib/labkit/tracing/auto_initialize.rb +28 -6
- data/lib/labkit/tracing/external_http/request_instrumenter.rb +4 -13
- data/lib/labkit/tracing/open_telemetry_factory.rb +2 -12
- data/lib/labkit/tracing/open_tracing_factory.rb +1 -10
- data/lib/labkit/tracing/rails/action_view/render_template_instrumenter.rb +6 -1
- data/lib/labkit/tracing/rails/active_record/sql_instrumenter.rb +9 -4
- data/lib/labkit/tracing/tracing_utils.rb +9 -7
- data/lib/labkit/tracing.rb +3 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d4d14a6537b13d635133bda037b3c0d005c212414affacc546f6ba60cfc433c8
|
|
4
|
+
data.tar.gz: 40b259acc97328cf5a12156b8415308750d1ded3bda89b190aae6b66be66be50
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 41fa558041ba46e4b3280fe37273e8a819b19c62a9c5539cfcb6200dc94b5f25dc2ed5f0dde861c8653dd02d0d91a0a948220729cd022ea346de7cb94cc64acc
|
|
7
|
+
data.tar.gz: a9966f49707dd37b1aa730e14745eb8f2181c5505e643531114e92d6c154c93ed3b185b1b5ab991663ed069a9ab4228a9ca8e8c64019f4a79d048130ef049086
|
data/.copier-answers.yml
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# See the project for instructions on how to update the project
|
|
4
4
|
#
|
|
5
5
|
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
|
|
6
|
-
_commit: v1.
|
|
6
|
+
_commit: v1.41.2
|
|
7
7
|
_src_path: https://gitlab.com/gitlab-com/gl-infra/common-template-copier.git
|
|
8
8
|
ee_licensed: false
|
|
9
9
|
golang: false
|
|
@@ -11,6 +11,7 @@ helm: false
|
|
|
11
11
|
initial_codeowners: '@reprazent @andrewn @mkaeppler @ayufan'
|
|
12
12
|
jsonnet: false
|
|
13
13
|
project_name: labkit-ruby
|
|
14
|
+
release_platform: false
|
|
14
15
|
ruby: true
|
|
15
16
|
rubygem: true
|
|
16
17
|
terraform: false
|
data/.releaserc.json
CHANGED
|
@@ -41,6 +41,8 @@ module Labkit
|
|
|
41
41
|
|
|
42
42
|
start_time = ::Labkit::System.monotonic_time
|
|
43
43
|
|
|
44
|
+
inject_trace_context(request)
|
|
45
|
+
|
|
44
46
|
ActiveSupport::Notifications.instrument ::Labkit::EXTERNAL_HTTP_NOTIFICATION_TOPIC, create_request_payload(request) do |payload|
|
|
45
47
|
response =
|
|
46
48
|
begin
|
|
@@ -57,7 +59,7 @@ module Labkit
|
|
|
57
59
|
|
|
58
60
|
def create_request_payload(request)
|
|
59
61
|
payload = {
|
|
60
|
-
method: request.method
|
|
62
|
+
method: request.method
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
if request.uri.nil?
|
|
@@ -84,5 +86,22 @@ module Labkit
|
|
|
84
86
|
|
|
85
87
|
payload
|
|
86
88
|
end
|
|
89
|
+
|
|
90
|
+
def inject_trace_context(request)
|
|
91
|
+
return unless Labkit::Tracing.enabled?
|
|
92
|
+
|
|
93
|
+
tracer = Labkit::Tracing::TracingUtils.tracer
|
|
94
|
+
span = tracer.active_span
|
|
95
|
+
return if span.nil?
|
|
96
|
+
|
|
97
|
+
carrier = {}
|
|
98
|
+
tracer.inject_context(span, carrier)
|
|
99
|
+
|
|
100
|
+
carrier.each do |key, value|
|
|
101
|
+
request[key] = value
|
|
102
|
+
end
|
|
103
|
+
rescue StandardError
|
|
104
|
+
warn "Labkit::NetHttpPublisher: trace context propagation failed"
|
|
105
|
+
end
|
|
87
106
|
end
|
|
88
107
|
end
|
|
@@ -35,13 +35,18 @@ export GITLAB_TRACING="otlp://localhost:4318"
|
|
|
35
35
|
|
|
36
36
|
**Automatic Initialization**
|
|
37
37
|
|
|
38
|
-
When `GITLAB_TRACING` is set, LabKit automatically creates and configures a tracer
|
|
38
|
+
When `GITLAB_TRACING` is set, LabKit automatically creates and configures a tracer:
|
|
39
|
+
|
|
40
|
+
- **Rails applications**: Railtie automatically inserts Labkit::Tracing::RackMiddleware into the middleware stack
|
|
41
|
+
- **Non-Rails applications**: Tracer is auto-initialized, but `Labkit::Tracing::RackMiddleware` must be manually added to your middleware stack for HTTP request tracing (see [Rack Middleware](#rack-middleware))
|
|
39
42
|
|
|
40
43
|
Auto-initialization provides:
|
|
41
|
-
- Automatic tracer creation with connection string settings
|
|
44
|
+
- Automatic tracer creation with connection string settings (sampler, exporter, service name)
|
|
42
45
|
- Service name from `service_name` query parameter (defaults to `"labkit-service"`)
|
|
43
|
-
-
|
|
44
|
-
-
|
|
46
|
+
- Selective OpenTelemetry instrumentation for components that don't conflict with LabKit:
|
|
47
|
+
- `ConcurrentRuby`, `Net::HTTP`, `ActionPack`, `ActionMailer`, `ActiveJob`
|
|
48
|
+
- LabKit's own instrumentation for components it handles directly:
|
|
49
|
+
- HTTP request tracing (RackMiddleware for Rails)
|
|
45
50
|
- Rails components (ActiveRecord, ActionView, ActiveSupport) - if Rails is available
|
|
46
51
|
- Redis instrumentation - if Redis gem is loaded
|
|
47
52
|
- External HTTP instrumentation (Net::HTTP, Excon, HTTPClient)
|
|
@@ -73,6 +78,7 @@ The following connection string formats and query parameters are supported:
|
|
|
73
78
|
- **Behavior**: Outputs spans immediately to stdout with no remote export
|
|
74
79
|
- **Benefits**: No external collector required, instant feedback, simple debugging
|
|
75
80
|
|
|
81
|
+
|
|
76
82
|
### Sampling
|
|
77
83
|
|
|
78
84
|
**Default Behavior:** When no sampler is specified, probabilistic sampling is used with a **0.1% sample rate** (1 in 1000 traces).
|
|
@@ -159,7 +165,7 @@ This seamless integration means you can:
|
|
|
159
165
|
|
|
160
166
|
### Automatic Initialization (Default Behavior)
|
|
161
167
|
|
|
162
|
-
When `GITLAB_TRACING` is set, LabKit automatically creates and configures a tracer
|
|
168
|
+
When `GITLAB_TRACING` is set, LabKit automatically creates and configures a tracer:
|
|
163
169
|
|
|
164
170
|
```bash
|
|
165
171
|
# Set environment variable with service name
|
|
@@ -169,14 +175,23 @@ export GITLAB_TRACING="otlp://localhost:4318?service_name=my-api&sampler=probabi
|
|
|
169
175
|
export GITLAB_TRACING="otlp://localhost:4318"
|
|
170
176
|
```
|
|
171
177
|
|
|
178
|
+
**Rails Applications:**
|
|
179
|
+
- Initialization happens automatically during Rails boot via Railtie
|
|
180
|
+
- Runs after all other gem initializers (including `opentelemetry-instrumentation-rails`)
|
|
181
|
+
- LabKit's TracerProvider is the final configuration used by the application
|
|
182
|
+
- **No application code changes required** - just set the environment variable
|
|
183
|
+
|
|
184
|
+
**Non-Rails Applications (Sinatra, Grape, standalone Ruby):**
|
|
185
|
+
- Tracer auto-initialization happens automatically when `require 'gitlab-labkit'` is called.
|
|
186
|
+
- However, you must manually add `Labkit::Tracing::RackMiddleware` to your middleware stack for HTTP request tracing. See the [Rack Middleware](#rack-middleware) section for details.
|
|
187
|
+
|
|
172
188
|
Auto-initialization:
|
|
173
189
|
- Creates tracer with connection string settings (sampler, exporter, endpoints)
|
|
174
190
|
- Uses service name from `service_name` query parameter (defaults to `"labkit-service"`)
|
|
175
|
-
- Enables
|
|
191
|
+
- Enables selective OpenTelemetry instrumentation (non-conflicting with LabKit's own)
|
|
192
|
+
- Enables LabKit instrumentation for ActiveRecord, ActionView, ActiveSupport, Redis, and External HTTP
|
|
176
193
|
- Sets up the global `OpenTelemetry.tracer_provider`
|
|
177
194
|
|
|
178
|
-
**No application code changes required** - just set the environment variable.
|
|
179
|
-
|
|
180
195
|
### Automatic Rails Middleware Insertion
|
|
181
196
|
|
|
182
197
|
When using Rails, the `Labkit::Tracing::RackMiddleware` is automatically inserted into your middleware stack when `GITLAB_TRACING` is set. No manual configuration needed!
|
|
@@ -214,8 +229,8 @@ You can override auto-initialization by calling `Factory.create_tracer` in your
|
|
|
214
229
|
# config/initializers/tracing.rb
|
|
215
230
|
# Override auto-initialization with custom configuration
|
|
216
231
|
Labkit::Tracing::Factory.create_tracer("my-custom-service", ENV["GITLAB_TRACING"]) do |c|
|
|
217
|
-
#
|
|
218
|
-
c.use 'OpenTelemetry::Instrumentation::
|
|
232
|
+
# Custom OTel instrumentation
|
|
233
|
+
c.use 'OpenTelemetry::Instrumentation::ConcurrentRuby'
|
|
219
234
|
c.use 'OpenTelemetry::Instrumentation::Sidekiq'
|
|
220
235
|
|
|
221
236
|
# Add custom span processors
|
|
@@ -232,7 +247,7 @@ end
|
|
|
232
247
|
```
|
|
233
248
|
|
|
234
249
|
**When to use manual initialization:**
|
|
235
|
-
- You need
|
|
250
|
+
- You need different OTel instrumentations than the defaults
|
|
236
251
|
- You need custom span processors
|
|
237
252
|
- You need to add resource attributes
|
|
238
253
|
- You want to override the service name from code instead of the connection string
|
|
@@ -289,11 +304,16 @@ end
|
|
|
289
304
|
|
|
290
305
|
### Initialization Order and Precedence
|
|
291
306
|
|
|
292
|
-
**Auto-initialization:**
|
|
293
|
-
1. Runs when
|
|
307
|
+
**Auto-initialization (all applications):**
|
|
308
|
+
1. Runs automatically when `require 'gitlab-labkit'` is called
|
|
294
309
|
2. Only runs if `GITLAB_TRACING` environment variable is set
|
|
295
310
|
3. Uses `service_name` query parameter or defaults to `"labkit-service"`
|
|
296
|
-
4.
|
|
311
|
+
4. Enables selective OpenTelemetry instrumentation (ConcurrentRuby, Net::HTTP, ActionPack, ActionMailer, ActiveJob) to avoid conflicts with LabKit's own instrumentation
|
|
312
|
+
5. Enables LabKit instrumentation for ActiveRecord, ActionView, ActiveSupport, Redis, and External HTTP
|
|
313
|
+
|
|
314
|
+
**Additional Rails behavior:**
|
|
315
|
+
1. Railtie runs after user config initializers (via `initializer ... after: :load_config_initializers`)
|
|
316
|
+
2. Automatically inserts `Labkit::Tracing::RackMiddleware` into the middleware stack
|
|
297
317
|
|
|
298
318
|
**Manual initialization:**
|
|
299
319
|
1. Runs in your application initializer (e.g., `config/initializers/tracing.rb`)
|
|
@@ -308,7 +328,7 @@ end
|
|
|
308
328
|
- Span processors with OTLP exporter
|
|
309
329
|
|
|
310
330
|
2. **Configuration block** runs second and can:
|
|
311
|
-
- Add automatic instrumentation (`use
|
|
331
|
+
- Add automatic instrumentation (`use`)
|
|
312
332
|
- Add additional span processors
|
|
313
333
|
- Merge additional resource attributes
|
|
314
334
|
- Override service_name if explicitly set in the block
|
|
@@ -570,8 +590,13 @@ If you need to add custom metadata (deployment environment, version, etc.), over
|
|
|
570
590
|
# config/initializers/tracing.rb
|
|
571
591
|
|
|
572
592
|
Labkit::Tracing::Factory.create_tracer("my-rails-app", ENV["GITLAB_TRACING"]) do |c|
|
|
573
|
-
#
|
|
574
|
-
|
|
593
|
+
# Selective instrumentation (avoid conflicting with LabKit's own instrumentation
|
|
594
|
+
# for ActiveRecord, ActionView, ActiveSupport, Redis, Rack, and Sidekiq)
|
|
595
|
+
c.use("OpenTelemetry::Instrumentation::ConcurrentRuby")
|
|
596
|
+
c.use("OpenTelemetry::Instrumentation::Net::HTTP")
|
|
597
|
+
c.use("OpenTelemetry::Instrumentation::ActionPack") if defined?(ActionPack)
|
|
598
|
+
c.use("OpenTelemetry::Instrumentation::ActionMailer") if defined?(ActionMailer)
|
|
599
|
+
c.use("OpenTelemetry::Instrumentation::ActiveJob") if defined?(ActiveJob)
|
|
575
600
|
|
|
576
601
|
# Add deployment metadata
|
|
577
602
|
c.resource = c.resource.merge(
|
|
@@ -588,18 +613,18 @@ end
|
|
|
588
613
|
|
|
589
614
|
Note: Middleware is still automatically inserted even with custom tracer initialization.
|
|
590
615
|
|
|
591
|
-
### With
|
|
616
|
+
### With Custom Instrumentation (Manual Override)
|
|
592
617
|
|
|
593
|
-
If you want to control exactly which components are instrumented
|
|
618
|
+
If you want to control exactly which OTel components are instrumented, override tracer initialization:
|
|
594
619
|
|
|
595
620
|
**Important:** When you manually call `Factory.create_tracer`, auto-initialization still runs but is replaced by your manual configuration. The LabKit-specific instrumentation (Rails, Redis, ExternalHttp) is still automatically enabled unless you explicitly disable auto-initialization.
|
|
596
621
|
|
|
597
622
|
```ruby
|
|
598
623
|
# config/initializers/tracing.rb
|
|
599
|
-
# Override auto-initialization for
|
|
624
|
+
# Override auto-initialization for custom OpenTelemetry instrumentation
|
|
600
625
|
Labkit::Tracing::Factory.create_tracer("my-rails-app", ENV["GITLAB_TRACING"]) do |c|
|
|
601
|
-
#
|
|
602
|
-
c.use 'OpenTelemetry::Instrumentation::
|
|
626
|
+
# Only enable the OTel instrumentations you need
|
|
627
|
+
c.use 'OpenTelemetry::Instrumentation::ConcurrentRuby'
|
|
603
628
|
c.use 'OpenTelemetry::Instrumentation::Sidekiq'
|
|
604
629
|
end
|
|
605
630
|
|
|
@@ -642,9 +667,9 @@ If you're not seeing HTTP request traces in Rails:
|
|
|
642
667
|
```
|
|
643
668
|
|
|
644
669
|
2. Check Rails logs for auto-insertion message:
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
670
|
+
```
|
|
671
|
+
Labkit::Tracing::RackMiddleware automatically inserted after Labkit::Middleware::Rack
|
|
672
|
+
```
|
|
648
673
|
|
|
649
674
|
3. If using custom middleware positioning, verify the order is correct:
|
|
650
675
|
```bash
|
|
@@ -7,27 +7,26 @@ module Labkit
|
|
|
7
7
|
# https://edgeapi.rubyonrails.org/classes/ActiveSupport/Notifications/Instrumenter.html#method-c-new
|
|
8
8
|
class AbstractInstrumenter
|
|
9
9
|
def start(_name, _id, payload)
|
|
10
|
-
|
|
10
|
+
span_wrapper = Labkit::Tracing::TracingUtils.tracer.start_active_span(span_name(payload))
|
|
11
11
|
|
|
12
|
-
scope_stack.push
|
|
12
|
+
scope_stack.push span_wrapper
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def finish(_name, _id, payload)
|
|
16
|
-
|
|
17
|
-
span = scope.span
|
|
16
|
+
span_wrapper = scope_stack.pop
|
|
18
17
|
|
|
19
|
-
Labkit::Tracing::TracingUtils.log_common_fields_on_span(
|
|
18
|
+
Labkit::Tracing::TracingUtils.log_common_fields_on_span(span_wrapper, span_name(payload))
|
|
20
19
|
|
|
21
20
|
# exception_object is the standard exception payload from ActiveSupport::Notifications
|
|
22
21
|
# https://github.com/rails/rails/blob/v6.0.3.1/activesupport/lib/active_support/notifications/instrumenter.rb#L26
|
|
23
22
|
exception = payload[:exception_object].presence || payload[:exception].presence
|
|
24
|
-
|
|
23
|
+
span_wrapper.set_error(exception)
|
|
25
24
|
|
|
26
25
|
tags(payload).each do |k, v|
|
|
27
|
-
|
|
26
|
+
span_wrapper.set_tag(k, v)
|
|
28
27
|
end
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
span_wrapper.close
|
|
31
30
|
end
|
|
32
31
|
|
|
33
32
|
def scope_stack
|
|
@@ -91,6 +91,18 @@ module Labkit
|
|
|
91
91
|
@token = token
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
+
def set_tag(key, value)
|
|
95
|
+
span.set_tag(key, value)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def set_error(exception)
|
|
99
|
+
span.set_error(exception)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def log_event(name, **attributes)
|
|
103
|
+
span.log_event(name, **attributes)
|
|
104
|
+
end
|
|
105
|
+
|
|
94
106
|
def close
|
|
95
107
|
@raw_span.finish
|
|
96
108
|
OpenTelemetry::Context.detach(@token)
|
|
@@ -34,15 +34,18 @@ module Labkit
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def active_span
|
|
37
|
-
OpenTracing.active_span
|
|
37
|
+
span = OpenTracing.active_span
|
|
38
|
+
OpentracingSpan.new(span) if span
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
def start_active_span(operation_name, tags: nil)
|
|
41
|
-
if tags
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
scope = if tags
|
|
43
|
+
OpenTracing.start_active_span(operation_name, tags: tags)
|
|
44
|
+
else
|
|
45
|
+
OpenTracing.start_active_span(operation_name)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
OpentracingSpan.new(scope)
|
|
46
49
|
end
|
|
47
50
|
end
|
|
48
51
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
3
|
+
require "uri"
|
|
4
4
|
require "active_support/core_ext/object/blank"
|
|
5
5
|
|
|
6
6
|
module Labkit
|
|
@@ -9,9 +9,16 @@ module Labkit
|
|
|
9
9
|
def self.detect_service_name(connection_string)
|
|
10
10
|
return Labkit::Tracing::DEFAULT_SERVICE_NAME unless connection_string
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
begin
|
|
13
|
+
parsed = URI.parse(connection_string)
|
|
14
|
+
options = TracingUtils.parse_query_string(parsed.query)
|
|
15
|
+
|
|
16
|
+
return options[:service_name] if options[:service_name]
|
|
17
|
+
|
|
18
|
+
warn "Labkit::Tracing: service_name not found in connection string, using default: '#{Labkit::Tracing::DEFAULT_SERVICE_NAME}'"
|
|
19
|
+
Labkit::Tracing::DEFAULT_SERVICE_NAME
|
|
20
|
+
rescue URI::InvalidURIError => e
|
|
21
|
+
warn "Labkit::Tracing: Invalid connection string (#{e.message}), using default service name: '#{Labkit::Tracing::DEFAULT_SERVICE_NAME}'"
|
|
15
22
|
Labkit::Tracing::DEFAULT_SERVICE_NAME
|
|
16
23
|
end
|
|
17
24
|
end
|
|
@@ -22,9 +29,24 @@ module Labkit
|
|
|
22
29
|
|
|
23
30
|
service_name = detect_service_name(connection_string)
|
|
24
31
|
|
|
32
|
+
require "opentelemetry/instrumentation/concurrent_ruby"
|
|
33
|
+
require "opentelemetry/instrumentation/net/http"
|
|
34
|
+
require "opentelemetry/instrumentation/action_pack" if defined?(ActionPack)
|
|
35
|
+
require "opentelemetry/instrumentation/action_mailer" if defined?(ActionMailer)
|
|
36
|
+
require "opentelemetry/instrumentation/active_job" if defined?(ActiveJob)
|
|
37
|
+
|
|
25
38
|
Factory.create_tracer(service_name, connection_string) do |c|
|
|
26
|
-
|
|
27
|
-
|
|
39
|
+
# Enable only non-conflicting instrumentations
|
|
40
|
+
# Exclude: ActiveSupport, ActiveRecord, ActionView, Redis, Rack, Sidekiq
|
|
41
|
+
# (LabKit provides its own instrumentation for these via AbstractInstrumenter)
|
|
42
|
+
|
|
43
|
+
# Core instrumentations
|
|
44
|
+
c.use("OpenTelemetry::Instrumentation::ConcurrentRuby")
|
|
45
|
+
|
|
46
|
+
# Rails components that don't conflict with LabKit
|
|
47
|
+
c.use("OpenTelemetry::Instrumentation::ActionPack") if defined?(ActionPack)
|
|
48
|
+
c.use("OpenTelemetry::Instrumentation::ActionMailer") if defined?(ActionMailer)
|
|
49
|
+
c.use("OpenTelemetry::Instrumentation::ActiveJob") if defined?(ActiveJob)
|
|
28
50
|
end
|
|
29
51
|
|
|
30
52
|
enable_labkit_instrumentation
|
|
@@ -12,20 +12,11 @@ module Labkit
|
|
|
12
12
|
def tags(payload)
|
|
13
13
|
# Duration is calculated by start and end time
|
|
14
14
|
# Exception is already captured in lib/labkit/tracing/tracing_utils.rb
|
|
15
|
-
tags =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"code" => payload[:code],
|
|
19
|
-
"host" => payload[:host],
|
|
20
|
-
"port" => payload[:port],
|
|
21
|
-
"path" => payload[:path],
|
|
22
|
-
"scheme" => payload[:scheme],
|
|
23
|
-
}
|
|
15
|
+
tags = payload.slice(:method, :code, :host, :port, :path, :scheme, :proxy_host, :proxy_port)
|
|
16
|
+
tags.transform_keys!(&:name)
|
|
17
|
+
tags["component"] = "external_http"
|
|
24
18
|
|
|
25
|
-
|
|
26
|
-
tags["proxy_host"] = payload[:proxy_host]
|
|
27
|
-
tags["proxy_port"] = payload[:proxy_port]
|
|
28
|
-
end
|
|
19
|
+
tags.compact!
|
|
29
20
|
|
|
30
21
|
tags
|
|
31
22
|
end
|
|
@@ -79,14 +79,10 @@ module Labkit
|
|
|
79
79
|
yield(c)
|
|
80
80
|
end
|
|
81
81
|
|
|
82
|
-
# SDK.configure doesn't expose sampler configuration directly
|
|
83
|
-
# We need to replace the tracer provider to set the sampler
|
|
84
|
-
# This is a known limitation of the OpenTelemetry Ruby SDK
|
|
85
82
|
current_provider = OpenTelemetry.tracer_provider
|
|
86
83
|
return unless current_provider.is_a?(OpenTelemetry::SDK::Trace::TracerProvider)
|
|
87
84
|
|
|
88
|
-
|
|
89
|
-
create_and_configure_provider(current_provider.resource, sampler, exporter)
|
|
85
|
+
current_provider.sampler = sampler
|
|
90
86
|
else
|
|
91
87
|
create_and_configure_provider(base_resource, sampler, exporter)
|
|
92
88
|
end
|
|
@@ -175,7 +171,7 @@ module Labkit
|
|
|
175
171
|
parsed = URI.parse(connection_string)
|
|
176
172
|
|
|
177
173
|
# Parse query parameters for additional options
|
|
178
|
-
options =
|
|
174
|
+
options = TracingUtils.parse_query_string(parsed.query)
|
|
179
175
|
|
|
180
176
|
# Handle console exporter (special case - no endpoint needed)
|
|
181
177
|
if parsed.host == "console"
|
|
@@ -206,12 +202,6 @@ module Labkit
|
|
|
206
202
|
|
|
207
203
|
endpoint
|
|
208
204
|
end
|
|
209
|
-
|
|
210
|
-
def parse_query(query)
|
|
211
|
-
return {} unless query
|
|
212
|
-
|
|
213
|
-
CGI.parse(query).symbolize_keys.transform_values(&:first)
|
|
214
|
-
end
|
|
215
205
|
end
|
|
216
206
|
end
|
|
217
207
|
end
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "cgi"
|
|
4
|
-
|
|
5
3
|
module Labkit
|
|
6
4
|
module Tracing
|
|
7
5
|
class OpenTracingFactory
|
|
@@ -26,17 +24,10 @@ module Labkit
|
|
|
26
24
|
|
|
27
25
|
raise "Invalid tracing connection string" unless valid_uri?(parsed)
|
|
28
26
|
|
|
29
|
-
{ driver_name: parsed.host, options:
|
|
27
|
+
{ driver_name: parsed.host, options: TracingUtils.parse_query_string(parsed.query) }
|
|
30
28
|
end
|
|
31
29
|
private_class_method :parse_connection_string
|
|
32
30
|
|
|
33
|
-
def self.parse_query(query)
|
|
34
|
-
return {} unless query
|
|
35
|
-
|
|
36
|
-
CGI.parse(query).symbolize_keys.transform_values(&:first)
|
|
37
|
-
end
|
|
38
|
-
private_class_method :parse_query
|
|
39
|
-
|
|
40
31
|
def self.valid_uri?(uri)
|
|
41
32
|
return false unless uri
|
|
42
33
|
|
|
@@ -16,7 +16,12 @@ module Labkit
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def tags(payload)
|
|
19
|
-
{ "component" => COMPONENT_TAG
|
|
19
|
+
tags = { "component" => COMPONENT_TAG }
|
|
20
|
+
# OpenTelemetry rejects nil attributes, and error templates may not
|
|
21
|
+
# have a layout (e.g., public/406-unsupported-browser.html).
|
|
22
|
+
tags["template.id"] = payload[:identifier] if payload[:identifier]
|
|
23
|
+
tags["template.layout"] = payload[:layout] if payload[:layout]
|
|
24
|
+
tags
|
|
20
25
|
end
|
|
21
26
|
end
|
|
22
27
|
end
|
|
@@ -19,15 +19,20 @@ module Labkit
|
|
|
19
19
|
fingerprint = Labkit::Logging::Sanitizer.sql_fingerprint(sql)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
{
|
|
22
|
+
tags = {
|
|
23
23
|
"component" => COMPONENT_TAG,
|
|
24
24
|
"span.kind" => "client",
|
|
25
25
|
"db.type" => "sql",
|
|
26
|
-
"db.connection_id" => payload[:connection_id],
|
|
27
26
|
"db.cached" => payload[:cached] || false,
|
|
28
|
-
"db.statement" => sql,
|
|
29
|
-
"db.statement_fingerprint" => fingerprint,
|
|
30
27
|
}
|
|
28
|
+
|
|
29
|
+
# OpenTelemetry rejects nil attributes, so only add statement fields
|
|
30
|
+
# when ActiveRecord supplies SQL (schema events may omit it).
|
|
31
|
+
tags["db.statement"] = sql if sql
|
|
32
|
+
tags["db.statement_fingerprint"] = fingerprint if fingerprint
|
|
33
|
+
tags["db.connection_id"] = payload[:connection_id] if payload[:connection_id]
|
|
34
|
+
|
|
35
|
+
tags
|
|
31
36
|
end
|
|
32
37
|
end
|
|
33
38
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "cgi"
|
|
3
4
|
require "active_support/core_ext/string/starts_ends_with"
|
|
4
5
|
require "opentracing"
|
|
5
6
|
|
|
@@ -16,7 +17,7 @@ module Labkit
|
|
|
16
17
|
begin
|
|
17
18
|
yield span
|
|
18
19
|
rescue StandardError => e
|
|
19
|
-
|
|
20
|
+
span.set_error(e)
|
|
20
21
|
raise e
|
|
21
22
|
end
|
|
22
23
|
end
|
|
@@ -55,7 +56,7 @@ module Labkit
|
|
|
55
56
|
span = tracer.start_span(operation_name, child_of: child_of, tags: tags, start_time: start_time)
|
|
56
57
|
|
|
57
58
|
log_common_fields_on_span(span, operation_name)
|
|
58
|
-
|
|
59
|
+
span.set_error(exception)
|
|
59
60
|
|
|
60
61
|
span.finish(end_timestamp: end_time)
|
|
61
62
|
end
|
|
@@ -68,11 +69,6 @@ module Labkit
|
|
|
68
69
|
span.log_event("stack", stack: caller.join('\n')) if include_stacktrace?(operation_name)
|
|
69
70
|
end
|
|
70
71
|
|
|
71
|
-
# Add exception logging to a span
|
|
72
|
-
def self.log_exception_on_span(span, exception)
|
|
73
|
-
span.set_error(exception)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
72
|
def self.include_stacktrace?(operation_name)
|
|
77
73
|
@include_stacktrace ||= Hash.new do |result, name|
|
|
78
74
|
result[name] = Tracing.stacktrace_operations.any? { |stacktrace_operation| name.starts_with?(stacktrace_operation) }
|
|
@@ -80,6 +76,12 @@ module Labkit
|
|
|
80
76
|
|
|
81
77
|
@include_stacktrace[operation_name]
|
|
82
78
|
end
|
|
79
|
+
|
|
80
|
+
def self.parse_query_string(query)
|
|
81
|
+
return {} unless query
|
|
82
|
+
|
|
83
|
+
CGI.parse(query).symbolize_keys.transform_values(&:first)
|
|
84
|
+
end
|
|
83
85
|
end
|
|
84
86
|
end
|
|
85
87
|
end
|
data/lib/labkit/tracing.rb
CHANGED
|
@@ -30,7 +30,9 @@ module Labkit
|
|
|
30
30
|
autoload :OpentracingTracer, "labkit/tracing/adapters/opentracing_tracer"
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
# Must be a String, not Symbol, as OpenTelemetry requires resource attribute values
|
|
34
|
+
# to be strings, integers, floats, or booleans
|
|
35
|
+
DEFAULT_SERVICE_NAME = "labkit-service"
|
|
34
36
|
|
|
35
37
|
# Module-level attribute for storing the configured service name
|
|
36
38
|
# Set by Factory.create_tracer when a tracer is created
|