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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f0ded1c554ab0eb289f72738429db8f92ab18eb091fd7186663bdeb7d861cfc
4
- data.tar.gz: 1b5276133b05752d03c3a58d36602e923cf69b8e040a71a22e194a971ca0bff6
3
+ metadata.gz: d4d14a6537b13d635133bda037b3c0d005c212414affacc546f6ba60cfc433c8
4
+ data.tar.gz: 40b259acc97328cf5a12156b8415308750d1ded3bda89b190aae6b66be66be50
5
5
  SHA512:
6
- metadata.gz: 9e100693a48024f97d9314e2699c39be46a7dad631e3679e136b9477d9f6410a9ef86f346ed8a63777cae8e528332b6bc0adef41a5c8702ec84a62227ddb1e43
7
- data.tar.gz: dd31347725dd09c313f8294238ab5e10faa50bcd2a94496bf77f80eaa1b5ea70bc2c194c4c1cb61991cf63c7a92386111abd7f36140de8d704d92c4e6ae6dc18
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.39.0
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
@@ -1,5 +1,11 @@
1
1
  {
2
- "branches": ["master"],
2
+ "branches": [
3
+ {
4
+ "name": "+([0-9])-+([0-9])-stable",
5
+ "range": "${name.replace(/^(\\d+)-(\\d+)-stable$/, '$1.$2.x')}"
6
+ },
7
+ "master"
8
+ ],
3
9
  "plugins": [
4
10
  [
5
11
  "@semantic-release/commit-analyzer",
@@ -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 when the gem is loaded. No manual initialization is required in most cases.
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
- - All available OpenTelemetry instrumentation enabled by default (`c.use_all()`)
44
- - LabKit-specific instrumentation enabled automatically:
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 when the gem loads:
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 all available OpenTelemetry instrumentation
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
- # Selective instrumentation instead of c.use_all()
218
- c.use 'OpenTelemetry::Instrumentation::Rails'
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 selective instrumentation (not `c.use_all()`)
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 the gem is loaded (`require 'gitlab-labkit'`)
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. Attempts to enable all instrumentation with `c.use_all()`
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`, `use_all`)
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
- # Enable all available OpenTelemetry instrumentation
574
- c.use_all()
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 Selective Instrumentation (Manual Override)
616
+ ### With Custom Instrumentation (Manual Override)
592
617
 
593
- If you want to control exactly which components are instrumented instead of using `c.use_all()`, override tracer initialization:
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 selective OpenTelemetry instrumentation
624
+ # Override auto-initialization for custom OpenTelemetry instrumentation
600
625
  Labkit::Tracing::Factory.create_tracer("my-rails-app", ENV["GITLAB_TRACING"]) do |c|
601
- # Selective OpenTelemetry instrumentation (instead of c.use_all())
602
- c.use 'OpenTelemetry::Instrumentation::Rails'
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
- Labkit::Tracing: Automatically inserted RackMiddleware after Rails::Rack::Logger
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
- scope = Labkit::Tracing::TracingUtils.tracer.start_active_span(span_name(payload))
10
+ span_wrapper = Labkit::Tracing::TracingUtils.tracer.start_active_span(span_name(payload))
11
11
 
12
- scope_stack.push scope
12
+ scope_stack.push span_wrapper
13
13
  end
14
14
 
15
15
  def finish(_name, _id, payload)
16
- scope = scope_stack.pop
17
- span = scope.span
16
+ span_wrapper = scope_stack.pop
18
17
 
19
- Labkit::Tracing::TracingUtils.log_common_fields_on_span(span, span_name(payload))
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
- Labkit::Tracing::TracingUtils.log_exception_on_span(span, exception)
23
+ span_wrapper.set_error(exception)
25
24
 
26
25
  tags(payload).each do |k, v|
27
- span.set_tag(k, v)
26
+ span_wrapper.set_tag(k, v)
28
27
  end
29
28
 
30
- scope.close
29
+ span_wrapper.close
31
30
  end
32
31
 
33
32
  def scope_stack
@@ -40,6 +40,10 @@ module Labkit
40
40
  end
41
41
  end
42
42
 
43
+ def close(**opts)
44
+ finish(**opts)
45
+ end
46
+
43
47
  def context
44
48
  span.context
45
49
  end
@@ -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)
@@ -41,6 +41,10 @@ module Labkit
41
41
  scope&.close
42
42
  end
43
43
 
44
+ def close
45
+ finish
46
+ end
47
+
44
48
  def context
45
49
  span.context
46
50
  end
@@ -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
- OpenTracing.start_active_span(operation_name, tags: tags)
43
- else
44
- OpenTracing.start_active_span(operation_name)
45
- end
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 "cgi"
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
- if connection_string =~ /[?&]service_name=([^&]+)/
13
- CGI.unescape(Regexp.last_match(1))
14
- else
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
- require "opentelemetry/instrumentation/all"
27
- c.use_all
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
- "component" => "external_http",
17
- "method" => payload[:method],
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
- unless payload[:proxy_host].nil?
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
- # Create new provider with sampler, preserving resource from SDK.configure
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 = parse_query(parsed.query)
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: parse_query(parsed.query) }
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, "template.id" => payload[:identifier], "template.layout" => payload[:layout] }
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
- log_exception_on_span(span, e)
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
- log_exception_on_span(span, exception) if exception
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
@@ -30,7 +30,9 @@ module Labkit
30
30
  autoload :OpentracingTracer, "labkit/tracing/adapters/opentracing_tracer"
31
31
  end
32
32
 
33
- DEFAULT_SERVICE_NAME = :'labkit-service'
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-labkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Newdigate