Skip to content

Commit b668aaf

Browse files
committed
Split the metrics implementation to separate modules for Influx and Prometheus
1 parent ae8f766 commit b668aaf

File tree

5 files changed

+235
-229
lines changed

5 files changed

+235
-229
lines changed

app/services/metrics_service.rb

-10
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,4 @@ def formatter
3030
def multiprocess_metrics_path
3131
@multiprocess_metrics_path ||= Rails.root.join(ENV['prometheus_multiproc_dir']).freeze
3232
end
33-
34-
def metric_to_prom_line(metric)
35-
labels = metric.labels&.map { |key, value| "#{key}=\"#{value}\"" }&.join(',') || ''
36-
37-
if labels.empty?
38-
"#{metric.name} #{metric.value}"
39-
else
40-
"#{metric.name}{#{labels}} #{metric.value}"
41-
end
42-
end
4333
end
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,40 @@
1-
module Gitlab::HealthChecks
2-
class PrometheusTextFormat
3-
def marshal(metrics)
4-
metrics_with_type_declarations(metrics).join("\n")
5-
end
1+
module Gitlab
2+
module HealthChecks
3+
class PrometheusTextFormat
4+
def marshal(metrics)
5+
metrics_with_type_declarations(metrics).join("\n")
6+
end
67

7-
private
8+
private
89

9-
def metrics_with_type_declarations(metrics)
10-
type_declaration_added = {}
10+
def metrics_with_type_declarations(metrics)
11+
type_declaration_added = {}
1112

12-
metrics.flat_map do |metric|
13-
metric_lines = []
13+
metrics.flat_map do |metric|
14+
metric_lines = []
1415

15-
unless type_declaration_added.has_key?(metric.name)
16-
type_declaration_added[metric.name] = true
17-
metric_lines << metric_type_declaration(metric)
18-
end
16+
unless type_declaration_added.has_key?(metric.name)
17+
type_declaration_added[metric.name] = true
18+
metric_lines << metric_type_declaration(metric)
19+
end
1920

20-
metric_lines << metric_text(metric)
21+
metric_lines << metric_text(metric)
22+
end
2123
end
22-
end
2324

24-
def metric_type_declaration(metric)
25-
"# TYPE #{metric.name} gauge"
26-
end
25+
def metric_type_declaration(metric)
26+
"# TYPE #{metric.name} gauge"
27+
end
2728

28-
def metric_text(metric)
29-
labels = metric.labels&.map { |key, value| "#{key}=\"#{value}\"" }&.join(',') || ''
29+
def metric_text(metric)
30+
labels = metric.labels&.map { |key, value| "#{key}=\"#{value}\"" }&.join(',') || ''
3031

31-
if labels.empty?
32-
"#{metric.name} #{metric.value}"
33-
else
34-
"#{metric.name}{#{labels}} #{metric.value}"
32+
if labels.empty?
33+
"#{metric.name} #{metric.value}"
34+
else
35+
"#{metric.name}{#{labels}} #{metric.value}"
36+
end
3537
end
3638
end
3739
end
38-
end
40+
end

lib/gitlab/metrics.rb

+3-193
Original file line numberDiff line numberDiff line change
@@ -1,200 +1,10 @@
1-
require 'prometheus/client'
2-
31
module Gitlab
42
module Metrics
5-
extend Gitlab::CurrentSettings
6-
7-
RAILS_ROOT = Rails.root.to_s
8-
METRICS_ROOT = Rails.root.join('lib', 'gitlab', 'metrics').to_s
9-
PATH_REGEX = /^#{RAILS_ROOT}\/?/
10-
11-
def self.settings
12-
@settings ||= {
13-
enabled: current_application_settings[:metrics_enabled],
14-
prometheus_metrics_enabled: current_application_settings[:prometheus_metrics_enabled],
15-
pool_size: current_application_settings[:metrics_pool_size],
16-
timeout: current_application_settings[:metrics_timeout],
17-
method_call_threshold: current_application_settings[:metrics_method_call_threshold],
18-
host: current_application_settings[:metrics_host],
19-
port: current_application_settings[:metrics_port],
20-
sample_interval: current_application_settings[:metrics_sample_interval] || 15,
21-
packet_size: current_application_settings[:metrics_packet_size] || 1
22-
}
23-
end
24-
25-
def self.prometheus_metrics_enabled?
26-
settings[:prometheus_metrics_enabled] || false
27-
end
28-
29-
def self.influx_metrics_enabled?
30-
settings[:enabled] || false
31-
end
3+
extend Gitlab::Metrics::InfluxDb
4+
extend Gitlab::Metrics::Prometheus
325

336
def self.enabled?
347
influx_metrics_enabled? || prometheus_metrics_enabled?
358
end
36-
37-
def self.mri?
38-
RUBY_ENGINE == 'ruby'
39-
end
40-
41-
def self.method_call_threshold
42-
# This is memoized since this method is called for every instrumented
43-
# method. Loading data from an external cache on every method call slows
44-
# things down too much.
45-
@method_call_threshold ||= settings[:method_call_threshold]
46-
end
47-
48-
def self.pool
49-
@pool
50-
end
51-
52-
def self.registry
53-
@registry ||= ::Prometheus::Client.registry
54-
end
55-
56-
def self.counter(name, docstring, base_labels = {})
57-
provide_metric(name) || registry.counter(name, docstring, base_labels)
58-
end
59-
60-
def self.summary(name, docstring, base_labels = {})
61-
provide_metric(name) || registry.summary(name, docstring, base_labels)
62-
end
63-
64-
def self.gauge(name, docstring, base_labels = {})
65-
provide_metric(name) || registry.gauge(name, docstring, base_labels)
66-
end
67-
68-
def self.histogram(name, docstring, base_labels = {}, buckets = ::Prometheus::Client::Histogram::DEFAULT_BUCKETS)
69-
provide_metric(name) || registry.histogram(name, docstring, base_labels, buckets)
70-
end
71-
72-
def self.provide_metric(name)
73-
if prometheus_metrics_enabled?
74-
registry.get(name)
75-
else
76-
NullMetric.new
77-
end
78-
end
79-
80-
def self.submit_metrics(metrics)
81-
prepared = prepare_metrics(metrics)
82-
83-
pool&.with do |connection|
84-
prepared.each_slice(settings[:packet_size]) do |slice|
85-
begin
86-
connection.write_points(slice)
87-
rescue StandardError
88-
end
89-
end
90-
end
91-
rescue Errno::EADDRNOTAVAIL, SocketError => ex
92-
Gitlab::EnvironmentLogger.error('Cannot resolve InfluxDB address. GitLab Performance Monitoring will not work.')
93-
Gitlab::EnvironmentLogger.error(ex)
94-
end
95-
96-
def self.prepare_metrics(metrics)
97-
metrics.map do |hash|
98-
new_hash = hash.symbolize_keys
99-
100-
new_hash[:tags].each do |key, value|
101-
if value.blank?
102-
new_hash[:tags].delete(key)
103-
else
104-
new_hash[:tags][key] = escape_value(value)
105-
end
106-
end
107-
108-
new_hash
109-
end
110-
end
111-
112-
def self.escape_value(value)
113-
value.to_s.gsub('=', '\\=')
114-
end
115-
116-
# Measures the execution time of a block.
117-
#
118-
# Example:
119-
#
120-
# Gitlab::Metrics.measure(:find_by_username_duration) do
121-
# User.find_by_username(some_username)
122-
# end
123-
#
124-
# name - The name of the field to store the execution time in.
125-
#
126-
# Returns the value yielded by the supplied block.
127-
def self.measure(name)
128-
trans = current_transaction
129-
130-
return yield unless trans
131-
132-
real_start = Time.now.to_f
133-
cpu_start = System.cpu_time
134-
135-
retval = yield
136-
137-
cpu_stop = System.cpu_time
138-
real_stop = Time.now.to_f
139-
140-
real_time = (real_stop - real_start) * 1000.0
141-
cpu_time = cpu_stop - cpu_start
142-
143-
trans.increment("#{name}_real_time", real_time)
144-
trans.increment("#{name}_cpu_time", cpu_time)
145-
trans.increment("#{name}_call_count", 1)
146-
147-
retval
148-
end
149-
150-
# Adds a tag to the current transaction (if any)
151-
#
152-
# name - The name of the tag to add.
153-
# value - The value of the tag.
154-
def self.tag_transaction(name, value)
155-
trans = current_transaction
156-
157-
trans&.add_tag(name, value)
158-
end
159-
160-
# Sets the action of the current transaction (if any)
161-
#
162-
# action - The name of the action.
163-
def self.action=(action)
164-
trans = current_transaction
165-
166-
trans&.action = action
167-
end
168-
169-
# Tracks an event.
170-
#
171-
# See `Gitlab::Metrics::Transaction#add_event` for more details.
172-
def self.add_event(*args)
173-
trans = current_transaction
174-
175-
trans&.add_event(*args)
176-
end
177-
178-
# Returns the prefix to use for the name of a series.
179-
def self.series_prefix
180-
@series_prefix ||= Sidekiq.server? ? 'sidekiq_' : 'rails_'
181-
end
182-
183-
# Allow access from other metrics related middlewares
184-
def self.current_transaction
185-
Transaction.current
186-
end
187-
188-
# When enabled this should be set before being used as the usual pattern
189-
# "@foo ||= bar" is _not_ thread-safe.
190-
if influx_metrics_enabled?
191-
@pool = ConnectionPool.new(size: settings[:pool_size], timeout: settings[:timeout]) do
192-
host = settings[:host]
193-
port = settings[:port]
194-
195-
InfluxDB::Client.
196-
new(udp: { host: host, port: port })
197-
end
198-
end
1999
end
200-
end
10+
end

0 commit comments

Comments
 (0)