Verified Commit 89eec0bd authored by Hercules Merscher's avatar Hercules Merscher 🌴
Browse files

feat: Tracing adapters

parent 14c9ff5d
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -18,6 +18,15 @@ module Labkit
    autoload :Sidekiq, "labkit/tracing/sidekiq"
    autoload :TracingUtils, "labkit/tracing/tracing_utils"

    module Adapters
      autoload :BaseSpan, "labkit/tracing/adapters/base_span"
      autoload :OpentelemetrySpan, "labkit/tracing/adapters/opentelemetry_span"
      autoload :OpentracingSpan, "labkit/tracing/adapters/opentracing_span"
      autoload :BaseTracer, "labkit/tracing/adapters/base_tracer"
      autoload :OpentelemetryTracer, "labkit/tracing/adapters/opentelemetry_tracer"
      autoload :OpentracingTracer, "labkit/tracing/adapters/opentracing_tracer"
    end

    # Tracing is only enabled when the `GITLAB_TRACING` env var is configured.
    def self.enabled?
      connection_string.present?
@@ -33,7 +42,7 @@ module Labkit

    # Check if the current request is being traced.
    def self.sampled?
      context = OpenTracing.active_span&.context
      context = TracingUtils.tracer.active_span&.context
      context&.respond_to?(:sampled?) && context&.sampled?
    end

+1 −5
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@ module Labkit
    # https://edgeapi.rubyonrails.org/classes/ActiveSupport/Notifications/Instrumenter.html#method-c-new
    class AbstractInstrumenter
      def start(_name, _id, payload)
        scope = OpenTracing.start_active_span(span_name(payload))
        scope = Labkit::Tracing::TracingUtils.tracer.start_active_span(span_name(payload))

        scope_stack.push scope
      end
@@ -24,12 +24,8 @@ module Labkit
        Labkit::Tracing::TracingUtils.log_exception_on_span(span, exception)

        tags(payload).each do |k, v|
          if Labkit::Tracing::TracingUtils.opentelemetry_span?(span)
            span.set_attribute(k, v)
          else
          span.set_tag(k, v)
        end
        end

        scope.close
      end
+35 −0
Original line number Diff line number Diff line
# frozen_string_literal: true

module Labkit
  module Tracing
    module Adapters
      class BaseSpan
        attr_reader :span

        def initialize(span)
          @span = span
        end

        def set_tag(_key, _value)
          raise NotImplementedError, "#{self.class.name}#set_tag must be implemented"
        end

        def log_event(_name, **_attributes)
          raise NotImplementedError, "#{self.class.name}#log_event must be implemented"
        end

        def set_error(_exception)
          raise NotImplementedError, "#{self.class.name}#set_error must be implemented"
        end

        def finish(**_opts)
          raise NotImplementedError, "#{self.class.name}#finish must be implemented"
        end

        def context
          raise NotImplementedError, "#{self.class.name}#context must be implemented"
        end
      end
    end
  end
end
+39 −0
Original line number Diff line number Diff line
# frozen_string_literal: true

module Labkit
  module Tracing
    module Adapters
      class BaseTracer
        attr_reader :tracer

        def initialize(tracer)
          @tracer = tracer
        end

        def start_span(_operation_name, child_of: nil, tags: {}, start_time: nil)
          raise NotImplementedError, "#{self.class.name}#start_span must be implemented"
        end

        def in_span(_operation_name, child_of: nil, tags: {}, &_block)
          raise NotImplementedError, "#{self.class.name}#in_span must be implemented"
        end

        def extract_context(_format, _carrier)
          raise NotImplementedError, "#{self.class.name}#extract_context must be implemented"
        end

        def inject_context(_span_context, _format, _carrier)
          raise NotImplementedError, "#{self.class.name}#inject_context must be implemented"
        end

        def active_span
          raise NotImplementedError, "#{self.class.name}#active_span must be implemented"
        end

        def start_active_span(_operation_name, tags: nil)
          raise NotImplementedError, "#{self.class.name}#start_active_span must be implemented"
        end
      end
    end
  end
end
+60 −0
Original line number Diff line number Diff line
# frozen_string_literal: true

module Labkit
  module Tracing
    module Adapters
      class OpentelemetrySpan < BaseSpan
        def set_tag(key, value)
          span.set_attribute(key, value)
        end

        def log_event(name, **attributes)
          span.add_event(name, attributes: stringify_keys(attributes))
        end

        def set_error(exception)
          return if exception.blank?

          span.set_attribute("error", true)
          span.add_event("exception", attributes: stringify_keys(kv_tags_for_exception(exception)))
        end

        def finish(**opts)
          if opts[:end_timestamp]
            span.finish(end_timestamp: opts[:end_timestamp])
          else
            span.finish
          end
        end

        def context
          span.context
        end

        private

        def stringify_keys(hash)
          hash.transform_keys(&:to_s)
        end

        def kv_tags_for_exception(exception)
          case exception
          when Exception
            {
              event: "error",
              'error.kind': exception.class.to_s,
              message: Labkit::Logging::Sanitizer.sanitize_field(exception.message),
              stack: exception.backtrace&.join('\n')
            }
          else
            {
              event: "error",
              'error.kind': exception.class.to_s,
              'error.object': Labkit::Logging::Sanitizer.sanitize_field(exception.to_s)
            }
          end
        end
      end
    end
  end
end
Loading