Commit 23f4c414 authored by Bob Van Landuyt's avatar Bob Van Landuyt 💬
Browse files

Merge branch 'tracing-redis-backtrace' into 'master'

tracing: log a backtrace for selected calls

See merge request gitlab-org/labkit-ruby!31
parents 05859e6a 9863a0af
Loading
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -28,6 +28,10 @@ module Labkit
      ENV["GITLAB_TRACING_URL"]
    end

    def self.stacktrace_operations
      @stacktrace_operations ||= Set.new(ENV["GITLAB_TRACING_INCLUDE_STACKTRACE"].to_s.split(",").map(&:strip))
    end

    def self.tracing_url_enabled?
      enabled? && tracing_url_template.present?
    end
+2 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@ module Labkit
          scope = scope_stack.pop
          span = scope.span

          Labkit::Tracing::TracingUtils.log_common_fields_on_span(span, span_name(payload))

          exception = payload[:exception]
          Labkit::Tracing::TracingUtils.log_exception_on_span(span, exception) if exception

+17 −3
Original line number Diff line number Diff line
@@ -12,9 +12,7 @@ module Labkit
        scope = tracer.start_active_span(operation_name, child_of: child_of, tags: tags)
        span = scope.span

        # Add correlation details to the span if we have them
        correlation_id = Labkit::Correlation::CorrelationId.current_id
        span.set_tag("correlation_id", correlation_id) if correlation_id
        log_common_fields_on_span(span, operation_name)

        begin
          yield span
@@ -35,11 +33,19 @@ module Labkit
      def self.postnotify_span(operation_name, start_time, end_time, tags: nil, child_of: nil, exception: nil)
        span = OpenTracing.start_span(operation_name, start_time: start_time, tags: tags, child_of: child_of)

        log_common_fields_on_span(span, operation_name)
        log_exception_on_span(span, exception) if exception

        span.finish(end_time: end_time)
      end

      # Add common fields to a span
      def self.log_common_fields_on_span(span, operation_name)
        correlation_id = Labkit::Correlation::CorrelationId.current_id
        span.set_tag("correlation_id", correlation_id) if correlation_id
        span.log_kv(stack: caller.join('\n')) if include_stacktrace?(operation_name)
      end

      # Add exception logging to a span
      def self.log_exception_on_span(span, exception)
        span.set_tag("error", true)
@@ -60,6 +66,14 @@ module Labkit
          { :"event" => "error", :"error.kind" => exception.class.to_s, :"error.object" => Labkit::Logging::Sanitizer.sanitize_field(exception.to_s) }
        end
      end

      def self.include_stacktrace?(operation_name)
        @include_stacktrace ||= Hash.new do |result, name|
          result[name] = Tracing.stacktrace_operations.any? { |stacktrace_operation| name.starts_with?(stacktrace_operation) }
        end

        @include_stacktrace[operation_name]
      end
    end
  end
end
+32 −0
Original line number Diff line number Diff line
@@ -74,5 +74,37 @@ describe Labkit::Tracing do

      expect { |b| described_class.with_tracing(params, &b) }.to yield_control
    end

    let(:fake_span) { double("OpenTracing span") }
    let(:fake_scope) { double("OpenTracing scope", span: fake_span) }

    it "should generate a backtrace when backtrace is enabled" do
      allow(OpenTracing.global_tracer).to receive(:start_active_span).and_return(fake_scope)
      allow(fake_scope).to receive(:close)
      allow(fake_span).to receive(:set_tag)

      expect(described_class).to receive(:stacktrace_operations).and_return(Set.new(["example"]))
      expect(fake_span).to receive(:log_kv).with(stack: be_a(String))

      params = { operation_name: "example: name", tags: { foo: :bar } }

      described_class.with_tracing(params) { }
    end
  end

  describe ".stacktrace_operations" do
    before do
      Labkit::Tracing.instance_variable_set(:@stacktrace_operations, nil)
    end

    it "should return an empty set by default" do
      expect(Labkit::Tracing.stacktrace_operations).to eq(Set.new)
    end

    it "should parse comma-separated values from the env" do
      expect(ENV).to receive(:[]).with("GITLAB_TRACING_INCLUDE_STACKTRACE").and_return("redis, active_record")

      expect(Labkit::Tracing.stacktrace_operations).to eq(Set.new(["redis", "active_record"]))
    end
  end
end