Class: Gitlab::PrometheusClient

Inherits:
Object
  • Object
show all
Includes:
Utils::StrongMemoize
Defined in:
lib/gitlab/prometheus_client.rb

Overview

Helper methods to interact with Prometheus network services & resources

Constant Summary collapse

Error =
Class.new(StandardError)
ConnectionError =
Class.new(Gitlab::PrometheusClient::Error)
UnexpectedResponseError =
Class.new(Gitlab::PrometheusClient::Error)
QueryError =
Class.new(Gitlab::PrometheusClient::Error)
HEALTHY_RESPONSE =
"Prometheus is Healthy.\n"
QUERY_RANGE_DATA_POINTS =

Target number of data points for ‘query_range`. Please don’t exceed the limit of 11000 data points See github.com/prometheus/prometheus/blob/91306bdf24f5395e2601773316945a478b4b263d/web/api/v1/api.go#L347

600
QUERY_RANGE_MIN_STEP =

Minimal value of the ‘step` parameter for `query_range` in seconds.

60
RESTCLIENT_GITLAB_HTTP_KEYMAP =

Key translation between RestClient and Gitlab::HTTP (HTTParty)

{
  ssl_cert_store: :cert_store
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_url, options = {}) ⇒ PrometheusClient

Returns a new instance of PrometheusClient.



29
30
31
32
# File 'lib/gitlab/prometheus_client.rb', line 29

def initialize(api_url, options = {})
  @api_url = api_url.chomp('/')
  @options = options
end

Class Method Details

.compute_step(start_time, end_time) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/gitlab/prometheus_client.rb', line 106

def self.compute_step(start_time, end_time)
  diff = end_time - start_time

  step = (diff / QUERY_RANGE_DATA_POINTS).ceil

  [QUERY_RANGE_MIN_STEP, step].max
end

Instance Method Details

#aggregate(aggregate_query, time: Time.now, transform_value: :to_f) ⇒ Hash

Queries Prometheus with the given aggregate query and groups the results by mapping metric labels to their respective values.

Returns:

  • (Hash)

    mapping labels to their aggregate numeric values, or the empty hash if no results were found



89
90
91
92
93
94
95
96
# File 'lib/gitlab/prometheus_client.rb', line 89

def aggregate(aggregate_query, time: Time.now, transform_value: :to_f)
  response = query(aggregate_query, time: time)
  response.to_h do |result|
    key = block_given? ? yield(result['metric']) : result['metric']
    _timestamp, value = result['value']
    [key, value.public_send(transform_value)] # rubocop:disable GitlabSecurity/PublicSend
  end
end

#health_urlObject



114
115
116
# File 'lib/gitlab/prometheus_client.rb', line 114

def health_url
  "#{api_url}/-/healthy"
end

#healthy?Boolean

Returns:

  • (Boolean)


38
39
40
41
42
43
# File 'lib/gitlab/prometheus_client.rb', line 38

def healthy?
  response_body = handle_management_api_response(get(health_url, {}))

  # From Prometheus docs: This endpoint always returns 200 and should be used to check Prometheus health.
  response_body == HEALTHY_RESPONSE
end

#label_values(name = '__name__') ⇒ Object



98
99
100
# File 'lib/gitlab/prometheus_client.rb', line 98

def label_values(name = '__name__')
  json_api_get("label/#{name}/values")
end

#pingObject



34
35
36
# File 'lib/gitlab/prometheus_client.rb', line 34

def ping
  json_api_get('query', query: '1')
end

#proxy(type, args) ⇒ Object



54
55
56
57
58
59
60
61
# File 'lib/gitlab/prometheus_client.rb', line 54

def proxy(type, args)
  path = api_path(type)
  get(path, args)
rescue Gitlab::HTTP::ResponseError => ex
  raise PrometheusClient::ConnectionError, "Network connection error" unless ex.response && ex.response.try(:code)

  handle_querying_api_response(ex.response)
end

#query(query, time: Time.now) ⇒ Object



63
64
65
66
67
# File 'lib/gitlab/prometheus_client.rb', line 63

def query(query, time: Time.now)
  get_result('vector') do
    json_api_get('query', query: query, time: time.to_f)
  end
end

#query_range(query, start_time: 8.hours.ago, end_time: Time.now) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/gitlab/prometheus_client.rb', line 69

def query_range(query, start_time: 8.hours.ago, end_time: Time.now)
  start_time = start_time.to_f
  end_time = end_time.to_f
  step = self.class.compute_step(start_time, end_time)

  get_result('matrix') do
    json_api_get(
      'query_range',
      query: query,
      start: start_time,
      end: end_time,
      step: step
    )
  end
end

#ready?Boolean

Returns:

  • (Boolean)


45
46
47
48
49
50
51
52
# File 'lib/gitlab/prometheus_client.rb', line 45

def ready?
  response = get(ready_url, {})

  # From Prometheus docs: This endpoint returns 200 when Prometheus is ready to serve traffic (i.e. respond to queries).
  response.code == 200
rescue StandardError => e
  raise PrometheusClient::UnexpectedResponseError, "#{e.message}"
end

#ready_urlObject



118
119
120
# File 'lib/gitlab/prometheus_client.rb', line 118

def ready_url
  "#{api_url}/-/ready"
end

#series(*matches, start_time: 8.hours.ago, end_time: Time.now) ⇒ Object



102
103
104
# File 'lib/gitlab/prometheus_client.rb', line 102

def series(*matches, start_time: 8.hours.ago, end_time: Time.now)
  json_api_get('series', 'match': matches, start: start_time.to_f, end: end_time.to_f)
end