summaryrefslogtreecommitdiff
path: root/lib/gitlab/instrumentation/elasticsearch_transport.rb
blob: 4bef043ecb034d268c23e9639d6965b1bb79de8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# frozen_string_literal: true

require 'elasticsearch-transport'

module Gitlab
  module Instrumentation
    module ElasticsearchTransportInterceptor
      def perform_request(method, path, params = {}, body = nil, headers = nil)
        start = Time.now
        headers = (headers || {})
          .reverse_merge({ 'X-Opaque-Id': Labkit::Correlation::CorrelationId.current_or_new_id })
        response = super
      ensure
        if ::Gitlab::SafeRequestStore.active?
          duration = (Time.now - start)

          ::Gitlab::Instrumentation::ElasticsearchTransport.increment_request_count

          if response&.body && response.body.is_a?(Hash) && response.body['timed_out']
            ::Gitlab::Instrumentation::ElasticsearchTransport.increment_timed_out_count
          end

          ::Gitlab::Instrumentation::ElasticsearchTransport.add_duration(duration)
          ::Gitlab::Instrumentation::ElasticsearchTransport.add_call_details(duration, method, path, params, body)
        end
      end
    end

    class ElasticsearchTransport
      ELASTICSEARCH_REQUEST_COUNT = :elasticsearch_request_count
      ELASTICSEARCH_CALL_DURATION = :elasticsearch_call_duration
      ELASTICSEARCH_CALL_DETAILS = :elasticsearch_call_details
      ELASTICSEARCH_TIMED_OUT_COUNT = :elasticsearch_timed_out_count

      def self.get_request_count
        ::Gitlab::SafeRequestStore[ELASTICSEARCH_REQUEST_COUNT] || 0
      end

      def self.increment_request_count
        ::Gitlab::SafeRequestStore[ELASTICSEARCH_REQUEST_COUNT] ||= 0
        ::Gitlab::SafeRequestStore[ELASTICSEARCH_REQUEST_COUNT] += 1
      end

      def self.detail_store
        ::Gitlab::SafeRequestStore[ELASTICSEARCH_CALL_DETAILS] ||= []
      end

      def self.query_time
        query_time = ::Gitlab::SafeRequestStore[ELASTICSEARCH_CALL_DURATION] || 0
        query_time.round(::Gitlab::InstrumentationHelper::DURATION_PRECISION)
      end

      def self.add_duration(duration)
        ::Gitlab::SafeRequestStore[ELASTICSEARCH_CALL_DURATION] ||= 0
        ::Gitlab::SafeRequestStore[ELASTICSEARCH_CALL_DURATION] += duration
      end

      def self.increment_timed_out_count
        ::Gitlab::SafeRequestStore[ELASTICSEARCH_TIMED_OUT_COUNT] ||= 0
        ::Gitlab::SafeRequestStore[ELASTICSEARCH_TIMED_OUT_COUNT] += 1
      end

      def self.get_timed_out_count
        ::Gitlab::SafeRequestStore[ELASTICSEARCH_TIMED_OUT_COUNT] || 0
      end

      def self.add_call_details(duration, method, path, params, body)
        return unless Gitlab::PerformanceBar.enabled_for_request?

        detail_store << {
          method: method,
          path: path,
          params: params,
          body: body,
          duration: duration,
          backtrace: ::Gitlab::BacktraceCleaner.clean_backtrace(caller)
        }
      end
    end
  end
end

class ::Elasticsearch::Transport::Client
  prepend ::Gitlab::Instrumentation::ElasticsearchTransportInterceptor
end