Module: Gitlab::InstrumentationHelper

Extended by:
InstrumentationHelper
Included in:
GrapeLogging::Loggers::PerfLogger, InstrumentationHelper
Defined in:
lib/gitlab/instrumentation_helper.rb

Constant Summary collapse

DURATION_PRECISION =

microseconds

6

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.enqueue_latency_for_scheduled_job(job) ⇒ Object

Returns the time it took for a scheduled job to be enqueued in seconds, as a float, if the ‘scheduled_at` and `enqueued_at` fields are available.

  • If the job doesn’t contain sufficient information, returns nil

  • If the job has a start time in the future, returns 0

  • If the job contains an invalid start time value, returns nil

Parameters:

  • job (Hash)

    a Sidekiq job, represented as a hash



177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/gitlab/instrumentation_helper.rb', line 177

def self.enqueue_latency_for_scheduled_job(job)
  scheduled_at = job['scheduled_at']
  enqueued_at = job['enqueued_at']

  return unless scheduled_at && enqueued_at

  scheduled_at_time = convert_to_time(scheduled_at)
  enqueued_at_time = convert_to_time(enqueued_at)

  return unless scheduled_at_time && enqueued_at_time

  round_elapsed_time(scheduled_at_time, enqueued_at_time)
end

.queue_duration_for_job(job) ⇒ Object

Returns the queuing duration for a Sidekiq job in seconds, as a float, if the ‘enqueued_at` field or `created_at` field is available.

  • If the job doesn’t contain sufficient information, returns nil

  • If the job has a start time in the future, returns 0

  • If the job contains an invalid start time value, returns nil

Parameters:

  • job (Hash)

    a Sidekiq job, represented as a hash



159
160
161
162
163
164
165
166
167
168
# File 'lib/gitlab/instrumentation_helper.rb', line 159

def self.queue_duration_for_job(job)
  # Old gitlab-shell messages don't provide enqueued_at/created_at attributes
  enqueued_at = job['enqueued_at'] || job['created_at']
  return unless enqueued_at

  enqueued_at_time = convert_to_time(enqueued_at)
  return unless enqueued_at_time

  round_elapsed_time(enqueued_at_time)
end

.round_elapsed_time(start, end_time = Time.now) ⇒ Object



191
192
193
194
195
196
# File 'lib/gitlab/instrumentation_helper.rb', line 191

def self.round_elapsed_time(start, end_time = Time.now)
  # It's possible that if there is clock-skew between two nodes this
  # value may be less than zero. In that event, we record the value
  # as zero.
  [elapsed_by_absolute_time(start, end_time), 0].max.round(DURATION_PRECISION)
end

Instance Method Details

#add_instrumentation_data(payload) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/gitlab/instrumentation_helper.rb', line 13

def add_instrumentation_data(payload)
  instrument_gitaly(payload)
  instrument_rugged(payload)
  instrument_redis(payload)
  instrument_elasticsearch(payload)
  instrument_zoekt(payload)
  instrument_throttle(payload)
  instrument_active_record(payload)
  instrument_external_http(payload)
  instrument_rack_attack(payload)
  instrument_cpu(payload)
  instrument_thread_memory_allocations(payload)
  instrument_load_balancing(payload)
  instrument_pid(payload)
  instrument_worker_id(payload)
  instrument_uploads(payload)
  instrument_rate_limiting_gates(payload)
  instrument_global_search_api(payload)
  instrument_ldap(payload)
end

#init_instrumentation_dataObject



9
10
11
# File 'lib/gitlab/instrumentation_helper.rb', line 9

def init_instrumentation_data
  Gitlab::RequestContext.start_thread_context
end

#instrument_active_record(payload) ⇒ Object



92
93
94
95
96
# File 'lib/gitlab/instrumentation_helper.rb', line 92

def instrument_active_record(payload)
  db_counters = ::Gitlab::Metrics::Subscribers::ActiveRecord.db_counter_payload

  payload.merge!(db_counters)
end

#instrument_cpu(payload) ⇒ Object



105
106
107
108
109
110
# File 'lib/gitlab/instrumentation_helper.rb', line 105

def instrument_cpu(payload)
  cpu_s = ::Gitlab::Metrics::System.thread_cpu_duration(
    ::Gitlab::RequestContext.instance.start_thread_cpu_time)

  payload[:cpu_s] = cpu_s.round(DURATION_PRECISION) if cpu_s
end

#instrument_elasticsearch(payload) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/gitlab/instrumentation_helper.rb', line 56

def instrument_elasticsearch(payload)
  # Elasticsearch integration is only available in EE but instrumentation
  # only depends on the Gem which is also available in FOSS.
  elasticsearch_calls = Gitlab::Instrumentation::ElasticsearchTransport.get_request_count

  return if elasticsearch_calls == 0

  payload[:elasticsearch_calls] = elasticsearch_calls
  payload[:elasticsearch_duration_s] = Gitlab::Instrumentation::ElasticsearchTransport.query_time
  payload[:elasticsearch_timed_out_count] = Gitlab::Instrumentation::ElasticsearchTransport.get_timed_out_count
end

#instrument_external_http(payload) ⇒ Object



79
80
81
82
83
84
85
# File 'lib/gitlab/instrumentation_helper.rb', line 79

def instrument_external_http(payload)
  external_http_count = Gitlab::Metrics::Subscribers::ExternalHttp.request_count

  return if external_http_count == 0

  payload.merge! Gitlab::Metrics::Subscribers::ExternalHttp.payload
end

#instrument_gitaly(payload) ⇒ Object



34
35
36
37
38
39
40
41
# File 'lib/gitlab/instrumentation_helper.rb', line 34

def instrument_gitaly(payload)
  gitaly_calls = Gitlab::GitalyClient.get_request_count

  return if gitaly_calls == 0

  payload[:gitaly_calls] = gitaly_calls
  payload[:gitaly_duration_s] = Gitlab::GitalyClient.query_time
end

#instrument_global_search_api(payload) ⇒ Object



140
141
142
# File 'lib/gitlab/instrumentation_helper.rb', line 140

def instrument_global_search_api(payload)
  payload.merge!(::Gitlab::Instrumentation::GlobalSearchApi.payload)
end

#instrument_ldap(payload) ⇒ Object



144
145
146
147
148
149
150
# File 'lib/gitlab/instrumentation_helper.rb', line 144

def instrument_ldap(payload)
  ldap_count = Gitlab::Metrics::Subscribers::Ldap.count

  return if ldap_count == 0

  payload.merge! Gitlab::Metrics::Subscribers::Ldap.payload
end

#instrument_load_balancing(payload) ⇒ Object



126
127
128
129
130
# File 'lib/gitlab/instrumentation_helper.rb', line 126

def instrument_load_balancing(payload)
  load_balancing_payload = ::Gitlab::Metrics::Subscribers::LoadBalancing.load_balancing_payload

  payload.merge!(load_balancing_payload)
end

#instrument_pid(payload) ⇒ Object



112
113
114
# File 'lib/gitlab/instrumentation_helper.rb', line 112

def instrument_pid(payload)
  payload[:pid] = Process.pid
end

#instrument_rack_attack(payload) ⇒ Object



98
99
100
101
102
103
# File 'lib/gitlab/instrumentation_helper.rb', line 98

def instrument_rack_attack(payload)
  rack_attack_redis_count = ::Gitlab::Metrics::Subscribers::RackAttack.payload[:rack_attack_redis_count]
  return if rack_attack_redis_count == 0

  payload.merge!(::Gitlab::Metrics::Subscribers::RackAttack.payload)
end

#instrument_rate_limiting_gates(payload) ⇒ Object



136
137
138
# File 'lib/gitlab/instrumentation_helper.rb', line 136

def instrument_rate_limiting_gates(payload)
  payload.merge!(::Gitlab::Instrumentation::RateLimitingGates.payload)
end

#instrument_redis(payload) ⇒ Object



52
53
54
# File 'lib/gitlab/instrumentation_helper.rb', line 52

def instrument_redis(payload)
  payload.merge! ::Gitlab::Instrumentation::Redis.payload
end

#instrument_rugged(payload) ⇒ Object



43
44
45
46
47
48
49
50
# File 'lib/gitlab/instrumentation_helper.rb', line 43

def instrument_rugged(payload)
  rugged_calls = Gitlab::RuggedInstrumentation.query_count

  return if rugged_calls == 0

  payload[:rugged_calls] = rugged_calls
  payload[:rugged_duration_s] = Gitlab::RuggedInstrumentation.query_time
end

#instrument_thread_memory_allocations(payload) ⇒ Object



120
121
122
123
124
# File 'lib/gitlab/instrumentation_helper.rb', line 120

def instrument_thread_memory_allocations(payload)
  counters = ::Gitlab::Memory::Instrumentation.measure_thread_memory_allocations(
    ::Gitlab::RequestContext.instance.thread_memory_allocations)
  payload.merge!(counters) if counters
end

#instrument_throttle(payload) ⇒ Object



87
88
89
90
# File 'lib/gitlab/instrumentation_helper.rb', line 87

def instrument_throttle(payload)
  safelist = Gitlab::Instrumentation::Throttle.safelist
  payload[:throttle_safelist] = safelist if safelist.present?
end

#instrument_uploads(payload) ⇒ Object



132
133
134
# File 'lib/gitlab/instrumentation_helper.rb', line 132

def instrument_uploads(payload)
  payload.merge! ::Gitlab::Instrumentation::Uploads.payload
end

#instrument_worker_id(payload) ⇒ Object



116
117
118
# File 'lib/gitlab/instrumentation_helper.rb', line 116

def instrument_worker_id(payload)
  payload[:worker_id] = ::Prometheus::PidProvider.worker_id
end

#instrument_zoekt(payload) ⇒ Object



68
69
70
71
72
73
74
75
76
77
# File 'lib/gitlab/instrumentation_helper.rb', line 68

def instrument_zoekt(payload)
  # Zoekt integration is only available in EE but instrumentation
  # only depends on the Gem which is also available in FOSS.
  zoekt_calls = Gitlab::Instrumentation::Zoekt.get_request_count

  return if zoekt_calls == 0

  payload[:zoekt_calls] = zoekt_calls
  payload[:zoekt_duration_s] = Gitlab::Instrumentation::Zoekt.query_time
end