bloat.rb 1.86 KB
Newer Older
Andreas Brandl's avatar
Andreas Brandl committed
1
module GitLab
2
  module Exporter
Andreas Brandl's avatar
Andreas Brandl committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
    module Database
      # Helper to collect bloat metrics.
      class BloatCollector < Base
        def run(type = :btree)
          execute(self.class.query_for(type)).each_with_object({}) do |row, h|
            h[row["object_name"]] = row
          end
        end

        private

        def execute(query)
          with_connection_pool do |conn|
            conn.exec(query)
          end
        end

        class << self
          def query_for(type)
            @queries ||= {}

            return @queries[type] if @queries[type]

            file = File.join(__dir__, "bloat_#{type}.sql")
            fail "Unknown bloat query file: #{file}" unless File.exist?(file)

            @queries[type] = File.read(file)
          end
        end
      end

      # Prober class to gather bloat metrics
      class BloatProber
        METRIC_KEYS = %w(bloat_ratio bloat_size extra_size real_size).freeze

        attr_reader :metrics, :collector, :bloat_types

        def initialize(opts,
                       metrics: PrometheusMetrics.new,
                       collector: BloatCollector.new(connection_string: opts[:connection_string]))
          @metrics = metrics
          @collector = collector
          @bloat_types = opts[:bloat_types] || %i(btree table)
        end

        def probe_db
          bloat_types.each do |type|
            probe_for_type(type)
          end
        end

        def write_to(target)
          target.write(metrics.to_s)
        end

        private

        def probe_for_type(type)
          collector.run(type).each do |query_name, data|
            METRIC_KEYS.each do |key|
63
              metrics.add("gitlab_database_bloat_#{type}_#{key}", data[key].to_f, query_name: query_name)
Andreas Brandl's avatar
Andreas Brandl committed
64 65 66 67 68 69 70 71 72 73 74
            end
          end

          self
        rescue PG::ConnectionBad
          self
        end
      end
    end
  end
end