diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-10 15:06:19 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-10 15:06:19 +0300 |
commit | 69849c280c5525d132ebaddb1200c390a42ecc06 (patch) | |
tree | 2c6ffc6fd6dc4fa719305f25b475391730389747 /app/services | |
parent | c157f963db87a40a3ba7b94b339530ee83194bc8 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services')
-rw-r--r-- | app/services/grafana/proxy_service.rb | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/app/services/grafana/proxy_service.rb b/app/services/grafana/proxy_service.rb new file mode 100644 index 00000000000..74fcdc750b0 --- /dev/null +++ b/app/services/grafana/proxy_service.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +# Proxies calls to a Grafana-integrated Prometheus instance +# through the Grafana proxy API + +# This allows us to fetch and render metrics in GitLab from a Prometheus +# instance for which dashboards are configured in Grafana +module Grafana + class ProxyService < BaseService + include ReactiveCaching + + self.reactive_cache_key = ->(service) { service.cache_key } + self.reactive_cache_lease_timeout = 30.seconds + self.reactive_cache_refresh_interval = 30.seconds + self.reactive_cache_worker_finder = ->(_id, *args) { from_cache(*args) } + + attr_accessor :project, :datasource_id, :proxy_path, :query_params + + # @param project_id [Integer] Project id for which grafana is configured. + # + # See #initialize for other parameters. + def self.from_cache(project_id, datasource_id, proxy_path, query_params) + project = Project.find(project_id) + + new(project, datasource_id, proxy_path, query_params) + end + + # @param project [Project] Project for which grafana is configured. + # @param datasource_id [String] Grafana datasource id for Prometheus instance + # @param proxy_path [String] Path to Prometheus endpoint; EX) 'api/v1/query_range' + # @param query_params [Hash<String, String>] Supported params: [query, start, end, step] + def initialize(project, datasource_id, proxy_path, query_params) + @project = project + @datasource_id = datasource_id + @proxy_path = proxy_path + @query_params = query_params + end + + def execute + return cannot_proxy_response unless client + + with_reactive_cache(*cache_key) { |result| result } + end + + def calculate_reactive_cache(*) + return cannot_proxy_response unless client + + response = client.proxy_datasource( + datasource_id: datasource_id, + proxy_path: proxy_path, + query: query_params + ) + + success(http_status: response.code, body: response.body) + rescue ::Grafana::Client::Error => error + service_unavailable_response(error) + end + + # Required for ReactiveCaching; Usage overridden by + # self.reactive_cache_worker_finder + def id + nil + end + + def cache_key + [project.id, datasource_id, proxy_path, query_params] + end + + private + + def client + project.grafana_integration&.client + end + + def service_unavailable_response(exception) + error(exception.message, :service_unavailable) + end + + def cannot_proxy_response + error('Proxy support for this API is not available currently') + end + end +end |