2017-08-17 22:00:37 +05:30
|
|
|
module Gitlab
|
|
|
|
PrometheusError = Class.new(StandardError)
|
|
|
|
|
|
|
|
# Helper methods to interact with Prometheus network services & resources
|
2017-09-10 17:25:29 +05:30
|
|
|
class PrometheusClient
|
2018-03-17 18:26:18 +05:30
|
|
|
attr_reader :rest_client, :headers
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
def initialize(rest_client)
|
|
|
|
@rest_client = rest_client
|
2017-08-17 22:00:37 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def ping
|
|
|
|
json_api_get('query', query: '1')
|
|
|
|
end
|
|
|
|
|
|
|
|
def query(query, time: Time.now)
|
|
|
|
get_result('vector') do
|
2017-09-10 17:25:29 +05:30
|
|
|
json_api_get('query', query: query, time: time.to_f)
|
2017-08-17 22:00:37 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def query_range(query, start: 8.hours.ago, stop: Time.now)
|
|
|
|
get_result('matrix') do
|
|
|
|
json_api_get('query_range',
|
|
|
|
query: query,
|
|
|
|
start: start.to_f,
|
|
|
|
end: stop.to_f,
|
|
|
|
step: 1.minute.to_i)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
def label_values(name = '__name__')
|
|
|
|
json_api_get("label/#{name}/values")
|
|
|
|
end
|
|
|
|
|
|
|
|
def series(*matches, start: 8.hours.ago, stop: Time.now)
|
|
|
|
json_api_get('series', 'match': matches, start: start.to_f, end: stop.to_f)
|
|
|
|
end
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
private
|
|
|
|
|
|
|
|
def json_api_get(type, args = {})
|
2018-03-17 18:26:18 +05:30
|
|
|
path = ['api', 'v1', type].join('/')
|
|
|
|
get(path, args)
|
|
|
|
rescue JSON::ParserError
|
|
|
|
raise PrometheusError, 'Parsing response failed'
|
2017-08-17 22:00:37 +05:30
|
|
|
rescue Errno::ECONNREFUSED
|
|
|
|
raise PrometheusError, 'Connection refused'
|
|
|
|
end
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
def get(path, args)
|
|
|
|
response = rest_client[path].get(params: args)
|
|
|
|
handle_response(response)
|
2017-08-17 22:00:37 +05:30
|
|
|
rescue SocketError
|
2018-03-17 18:26:18 +05:30
|
|
|
raise PrometheusError, "Can't connect to #{rest_client.url}"
|
2017-08-17 22:00:37 +05:30
|
|
|
rescue OpenSSL::SSL::SSLError
|
2018-03-17 18:26:18 +05:30
|
|
|
raise PrometheusError, "#{rest_client.url} contains invalid SSL data"
|
|
|
|
rescue RestClient::ExceptionWithResponse => ex
|
|
|
|
handle_exception_response(ex.response)
|
|
|
|
rescue RestClient::Exception
|
2017-08-17 22:00:37 +05:30
|
|
|
raise PrometheusError, "Network connection error"
|
|
|
|
end
|
|
|
|
|
|
|
|
def handle_response(response)
|
2018-03-17 18:26:18 +05:30
|
|
|
json_data = JSON.parse(response.body)
|
|
|
|
if response.code == 200 && json_data['status'] == 'success'
|
|
|
|
json_data['data'] || {}
|
|
|
|
else
|
|
|
|
raise PrometheusError, "#{response.code} - #{response.body}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def handle_exception_response(response)
|
|
|
|
if response.code == 400
|
|
|
|
json_data = JSON.parse(response.body)
|
|
|
|
raise PrometheusError, json_data['error'] || 'Bad data received'
|
2017-08-17 22:00:37 +05:30
|
|
|
else
|
|
|
|
raise PrometheusError, "#{response.code} - #{response.body}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_result(expected_type)
|
|
|
|
data = yield
|
|
|
|
data['result'] if data['resultType'] == expected_type
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|