1# frozen_string_literal: true 2 3module Gitlab 4 module Metrics 5 module Samplers 6 class DatabaseSampler < BaseSampler 7 DEFAULT_SAMPLING_INTERVAL_SECONDS = 5 8 9 METRIC_PREFIX = 'gitlab_database_connection_pool_' 10 11 METRIC_DESCRIPTIONS = { 12 size: 'Total connection pool capacity', 13 connections: 'Current connections in the pool', 14 busy: 'Connections in use where the owner is still alive', 15 dead: 'Connections in use where the owner is not alive', 16 idle: 'Connections not in use', 17 waiting: 'Threads currently waiting on this queue' 18 }.freeze 19 20 def metrics 21 @metrics ||= init_metrics 22 end 23 24 def sample 25 host_stats.each do |host_stat| 26 METRIC_DESCRIPTIONS.each_key do |metric| 27 metrics[metric].set(host_stat[:labels], host_stat[:stats][metric]) 28 end 29 end 30 end 31 32 private 33 34 def init_metrics 35 METRIC_DESCRIPTIONS.to_h do |name, description| 36 [name, ::Gitlab::Metrics.gauge(:"#{METRIC_PREFIX}#{name}", description)] 37 end 38 end 39 40 def host_stats 41 connection_class_stats + replica_host_stats 42 end 43 44 def connection_class_stats 45 Gitlab::Database.database_base_models.each_value.with_object([]) do |base_model, stats| 46 next unless base_model.connected? 47 48 stats << { labels: labels_for_class(base_model), stats: base_model.connection_pool.stat } 49 end 50 end 51 52 def replica_host_stats 53 Gitlab::Database::LoadBalancing.each_load_balancer.with_object([]) do |load_balancer, stats| 54 next if load_balancer.primary_only? 55 56 load_balancer.host_list.hosts.each do |host| 57 stats << { labels: labels_for_replica_host(load_balancer, host), stats: host.connection.pool.stat } 58 end 59 end 60 end 61 62 def labels_for_class(klass) 63 { 64 host: klass.connection_db_config.host, 65 port: klass.connection_db_config.configuration_hash[:port], 66 class: klass.to_s, 67 db_config_name: klass.connection_db_config.name 68 } 69 end 70 71 def labels_for_replica_host(load_balancer, host) 72 { 73 host: host.host, 74 port: host.port, 75 class: load_balancer.configuration.primary_connection_specification_name, 76 db_config_name: Gitlab::Database.db_config_name(host.connection) 77 } 78 end 79 end 80 end 81 end 82end 83 84Gitlab::Metrics::Samplers::DatabaseSampler.prepend_mod_with('Gitlab::Metrics::Samplers::DatabaseSampler') 85