Commit e5bda2a5 authored by Z.J. van de Weg's avatar Z.J. van de Weg
Browse files

Add ability to query row counts

This commit allows for queries which only request for row counts to be
gathered and written for Prometheus to gather.

At this time 3 simple queries are added which monitor how many projects
are orphaned and/or pending_delete, though the structure of the code
allows for easily adding more queries which do
SELECT COUNT(<whatever>) FROM <whatever>;
parent 95b908cd
......@@ -244,6 +244,48 @@ module GitLab
end
end
# Database row counts query runner.
#
# This will take the database connection and print the result to STDOUT
class DatabaseRowCounts
COMMAND_NAME = "row-counts".freeze
def initialize(args)
@options = options(args)
@options.parse!
@target = args.shift || STDOUT
@target = File.open(@target, "a") if @target.is_a?(String)
end
def options(args)
args.options do |opts|
opts.banner = "Usage: #{EXECUTABLE_NAME} #{COMMAND_NAME} [options]"
opts.on("--db-conn=\"dbname=test port=5432\"", "Database connection string") do |val|
@db_connection_string = val
end
end
end
def help
@options.help
end
def run
validate!
::GitLab::Monitor::Database::RowCountProber.new(connection_string: @db_connection_string)
.probe_db
.write_to(@target)
end
private
def validate!
fail InvalidCLICommand.new(help) unless @db_connection_string
end
end
# Run a web server that exposes the metrics specified in a config file
class Server
COMMAND_NAME = "web".freeze
......@@ -378,6 +420,7 @@ module GitLab
DatabaseBlockedQueries,
DatabaseSlowQueries,
DatabaseVacuumQueries,
DatabaseRowCounts,
Process,
SidekiqRunner,
Server
......
......@@ -7,6 +7,7 @@ module GitLab
autoload :SlowQueriesProber, "gitlab_monitor/database/slow_queries"
autoload :DeadTuplesProber, "gitlab_monitor/database/dead_tuples"
autoload :VacuumQueriesProber, "gitlab_monitor/database/vacuum_queries"
autoload :RowCountProber, "gitlab_monitor/database/row_count"
end
end
end
module GitLab
module Monitor
module Database
# A helper class that executes the query its given and returns an int of
# the row count
# This class works under the assumption you do COUNT(*) queries
class RowCountCollector < Base
QUERIES = [
:orphaned_projects,
:soft_deleted_projects,
:orphaned_soft_deleted_projects
].freeze
def run
results = Hash.new(0)
QUERIES.each do |query|
results[query] = execute(query)
end
results
end
private
def execute(query)
connection.exec(send(query))[0]["count"]
end
def orphaned_projects
<<-SQL
SELECT COUNT(*) FROM projects
WHERE namespace_id IS NULL;
SQL
end
def soft_deleted_projects
<<-SQL
SELECT COUNT(*) FROM projects
WHERE pending_delete=true;
SQL
end
def orphaned_soft_deleted_projects
<<-SQL
SELECT COUNT(*) FROM projects
WHERE pending_delete=true AND namespace_id IS NULL;
SQL
end
end
# The prober which is called when gathering metrics
class RowCountProber
def initialize(opts, metrics: PrometheusMetrics.new)
@metrics = metrics
@collector = RowCountCollector.new(connection_string: opts[:connection_string])
end
def probe_db
return self unless @collector.connected?
results = @collector.run
results.each do |key, value|
@metrics.add("#{key}_count", value.to_i)
end
self
end
def write_to(target)
target.write(@metrics.to_s)
end
end
end
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment