1# frozen_string_literal: true 2 3module PrometheusAdapter 4 extend ActiveSupport::Concern 5 6 # We should choose more conservative timeouts, but some queries we run are now busting our 7 # default timeouts, which are stricter. We should make those queries faster instead. 8 # See https://gitlab.com/gitlab-org/gitlab/-/issues/232786 9 DEFAULT_PROMETHEUS_REQUEST_TIMEOUT_SEC = 60.seconds 10 11 included do 12 include ReactiveCaching 13 14 self.reactive_cache_lease_timeout = 30.seconds 15 self.reactive_cache_refresh_interval = 30.seconds 16 self.reactive_cache_lifetime = 1.minute 17 self.reactive_cache_work_type = :external_dependency 18 19 def prometheus_client 20 raise NotImplementedError 21 end 22 23 def prometheus_client_default_options 24 { 25 timeout: DEFAULT_PROMETHEUS_REQUEST_TIMEOUT_SEC 26 } 27 end 28 29 # Overridden in app/models/clusters/applications/prometheus.rb 30 def managed_prometheus? 31 false 32 end 33 34 # This is a light-weight check if a prometheus client is properly configured. 35 def configured? 36 raise NotImplementedError 37 end 38 39 # This is a heavy-weight check if a prometheus is properly configured and accessible from GitLab. 40 # This actually sends a request to an external service and often it could take a long time, 41 # Please consider using `configured?` instead if the process is running on Puma threads. 42 def can_query? 43 prometheus_client.present? 44 end 45 46 def query(query_name, *args) 47 return unless can_query? 48 49 query_class = query_klass_for(query_name) 50 query_args = build_query_args(*args) 51 52 with_reactive_cache(query_class.name, *query_args, &query_class.method(:transform_reactive_result)) 53 end 54 55 # Cache metrics for specific environment 56 def calculate_reactive_cache(query_class_name, *args) 57 return unless prometheus_client 58 59 data = Object.const_get(query_class_name, false).new(prometheus_client).query(*args) 60 { 61 success: true, 62 data: data, 63 last_update: Time.current.utc 64 } 65 rescue Gitlab::PrometheusClient::Error => err 66 { success: false, result: err.message } 67 end 68 69 def query_klass_for(query_name) 70 Gitlab::Prometheus::Queries.const_get("#{query_name.to_s.classify}Query", false) 71 end 72 73 def build_query_args(*args) 74 args.map { |arg| arg.respond_to?(:id) ? arg.id : arg } 75 end 76 77 def clear_prometheus_reactive_cache!(query_name, *args) 78 query_class = query_klass_for(query_name) 79 query_args = build_query_args(*args) 80 81 clear_reactive_cache!(query_class.name, *query_args) 82 end 83 end 84end 85