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

Methods included from Utils::StrongMemoize

#clear_memoization, #strong_memoize, #strong_memoized?

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


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

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


80
81
82
83
84
85
86
87
# File 'lib/gitlab/prometheus_client.rb', line 80

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


105
106
107
# File 'lib/gitlab/prometheus_client.rb', line 105

def health_url
  [api_url, '-/healthy'].join('/')
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


89
90
91
# File 'lib/gitlab/prometheus_client.rb', line 89

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


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

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


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

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


60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/gitlab/prometheus_client.rb', line 60

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

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


93
94
95
# File 'lib/gitlab/prometheus_client.rb', line 93

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