Commit 55a59997 authored by Ben Kochie's avatar Ben Kochie

Refactor per-runner metrics

* Combine all running workers into one query
* Update specs.
parent 1988413c
......@@ -29,30 +29,27 @@ module GitLab
" AND ci_builds.status = 'running' " \
" AND ci_builds.updated_at < NOW() - INTERVAL '1 hour'".freeze
RUNNING_PER_SHARED_RUNNER_QUERY =
PER_RUNNER_QUERY =
"SELECT " \
" ci_builds.runner_id, " \
" ci_runners.is_shared, " \
" projects.mirror, " \
" projects.pending_delete, " \
" projects.mirror_trigger_builds, " \
" COUNT(*) AS count " \
" FROM ci_builds " \
" WHERE ci_builds.type = 'Ci::Build' " \
" AND ci_builds.status = 'running' " \
" AND ci_builds.runner_id IN (%s) " \
" GROUP BY " \
" ci_builds.runner_id".freeze
RUNNING_FOR_MIRRORS_PER_SHARED_RUNNER_QUERY =
"SELECT ci_builds.runner_id, COUNT(*) AS count " \
" FROM ci_builds " \
" JOIN ci_runners " \
" ON ci_runners.id = ci_builds.runner_id " \
" JOIN projects " \
" ON projects.id = ci_builds.gl_project_id " \
" AND projects.pending_delete = 'f' " \
" AND projects.mirror = 't' " \
" AND projects.mirror_trigger_builds = 't' " \
" WHERE ci_builds.type = 'Ci::Build' " \
" AND ci_builds.status = 'running' " \
" AND ci_builds.runner_id IN (%s) " \
" GROUP BY " \
" ci_builds.runner_id".freeze
" ci_builds.runner_id, " \
" projects.mirror, " \
" projects.pending_delete, " \
" projects.mirror_trigger_builds, " \
" ci_runners.is_shared".freeze
def run
results = {}
......@@ -60,30 +57,29 @@ module GitLab
results.merge!(get_builds(BUILDS_QUERY))
results[:not_updated_last_hour] = get_general(NOT_UPDATED_RUNNING_BUILDS_QUERY)
results[:per_runner] = get_per_shared_runner(RUNNING_PER_SHARED_RUNNER_QUERY)
results[:per_runner_mirrors] = get_per_shared_runner(RUNNING_FOR_MIRRORS_PER_SHARED_RUNNER_QUERY)
results[:per_runner] = get_per_runner(PER_RUNNER_QUERY)
results
end
private
def get_per_shared_runner(query)
return {} unless shared_runners_ids.count > 0
query = query % shared_runners_ids.join(", ")
builds = begin
result = connection.exec(query)
result.map { |v| [v["runner_id"].to_i, v["count"].to_i] }.to_h
rescue PG::UndefinedTable, PG::UndefinedColumn
{}
end
def get_per_runner(query)
results = []
results = {}
shared_runners_ids.each do |id|
results[id] = builds[id] || 0
connection.exec(query).each do |row|
results.push(
runner: row["runner_id"].to_s,
shared_runner: row["is_shared"] == "t" ? "yes" : "no",
mirror: row["mirror"] == "t" ? "yes" : "no",
pending_delete: row["pending_delete"] == "t" ? "yes" : "no",
mirror_trigger_builds: row["mirror_trigger_builds"] == "t" ? "yes" : "no",
value: row["count"].to_i
)
end
results
rescue PG::UndefinedTable, PG::UndefinedColumn
[]
end
def get_general(query)
......@@ -111,16 +107,6 @@ module GitLab
rescue PG::UndefinedTable, PG::UndefinedColumn
{}
end
def shared_runners_ids
@shared_runners_ids ||= find_shared_runners_ids
end
def find_shared_runners_ids
shared_runners_result = connection.exec("SELECT id FROM ci_runners WHERE ci_runners.is_shared = 't'")
return [] unless shared_runners_result.count > 0
shared_runners_result.map { |v| v["id"].to_i }
end
end
# The prober which is called when gathering metrics
......@@ -172,12 +158,14 @@ module GitLab
end
def metrics_per_runner
@results[:per_runner].each do |key, value|
all = value
for_mirrors = @results[:per_runner_mirrors][key]
not_for_mirrors = all - for_mirrors
@metrics.add("ci_builds_per_runner", not_for_mirrors, status: "running", runner: key, mirrors: 0)
@metrics.add("ci_builds_per_runner", for_mirrors, status: "running", runner: key, mirrors: 1)
@results[:per_runner].each do |metric|
@metrics.add("ci_running_builds",
metric[:value],
runner: metric[:runner],
shared_runner: metric[:shared_runner],
mirror: metric[:mirror],
pending_delete: metric[:pending_delete],
mirror_trigger_builds: metric[:mirror_trigger_builds])
end
end
end
......
require "spec_helper"
require "gitlab_monitor/database/ci_builds"
# rubocop:disable Metrics/LineLength
describe GitLab::Monitor::Database do
let(:builds_query) { "SELECT BUILDS" }
let(:not_updated_running_builds_query) { "SELECT NOT UPDATED RUNNING" }
let(:per_runner_query) { "SELECT ALL RUNNING PER RUNNER %s" }
let(:mirrors_per_runner_query) { "SELECT MIRRORS RUNNING PER RUNNER %s" }
let(:per_runner_query) { "SELECT ALL RUNNING PER RUNNER" }
let(:connection) { double("connection") }
before do
stub_const("GitLab::Monitor::Database::CiBuildsCollector::BUILDS_QUERY", builds_query)
stub_const("GitLab::Monitor::Database::CiBuildsCollector::NOT_UPDATED_RUNNING_BUILDS_QUERY",
not_updated_running_builds_query)
stub_const("GitLab::Monitor::Database::CiBuildsCollector::RUNNING_PER_SHARED_RUNNER_QUERY", per_runner_query)
stub_const("GitLab::Monitor::Database::CiBuildsCollector::RUNNING_FOR_MIRRORS_PER_SHARED_RUNNER_QUERY",
mirrors_per_runner_query)
stub_const("GitLab::Monitor::Database::CiBuildsCollector::PER_RUNNER_QUERY", per_runner_query)
allow_any_instance_of(GitLab::Monitor::Database::CiBuildsCollector).to receive(:connection).and_return(connection)
allow_any_instance_of(GitLab::Monitor::Database::CiBuildsCollector).to receive(:shared_runners_ids)
.and_return([1, 2])
allow(connection).to receive(:exec).with(builds_query)
.and_return([{ "shared_runners_enabled" => "f", "status" => "created", "path" => "foo", "count" => 10 },
......@@ -28,18 +24,29 @@ describe GitLab::Monitor::Database do
{ "shared_runners_enabled" => "t", "status" => "pending", "path" => "baz", "count" => 1 },
{ "shared_runners_enabled" => "t", "status" => "pending", "path" => "bob", "count" => 2 }])
allow(connection).to receive(:exec).with(not_updated_running_builds_query).and_return([{ "count" => 2 }])
allow(connection).to receive(:exec).with(per_runner_query % "1, 2")
.and_return([{ "runner_id" => 2, "count" => 15 }])
allow(connection).to receive(:exec).with(mirrors_per_runner_query % "1, 2")
.and_return([{ "runner_id" => 2, "count" => 10 }])
allow(connection).to receive(:exec).with(per_runner_query)
.and_return([{ "runner_id" => 1,
"is_shared" => "t",
"mirror" => "f",
"pending_delete" => "f",
"mirror_trigger_builds" => "f",
"count" => 15 },
{ "runner_id" => 2,
"is_shared" => "f",
"mirror" => "t",
"pending_delete" => "f",
"mirror_trigger_builds" => "t",
"count" => 5 }])
end
describe GitLab::Monitor::Database::CiBuildsCollector do
let(:collector) { described_class.new(connection_string: "host=localhost") }
it "executes the query" do
expect(collector.run).to eq(per_runner: { 1 => 0, 2 => 15 },
per_runner_mirrors: { 1 => 0, 2 => 10 },
expect(collector.run).to eq(per_runner: [
{ runner: "1", shared_runner: "yes", mirror: "no", pending_delete: "no", mirror_trigger_builds: "no", value: 15 },
{ runner: "2", shared_runner: "no", mirror: "yes", pending_delete: "no", mirror_trigger_builds: "yes", value: 5 }
],
pending_builds: [
{ namespace: "foo", shared_runners: "yes", value: 30 },
{ namespace: "bar", shared_runners: "yes", value: 50 },
......@@ -75,10 +82,8 @@ describe GitLab::Monitor::Database do
expect(writer.string).to match(/ci_pending_builds{namespace="bar",shared_runners="yes"} 50/)
expect(writer.string).to match(/ci_pending_builds{namespace="",shared_runners="yes"} 3/)
expect(writer.string).to match(/ci_builds_stale{status="running",when="last_hour"} 2/)
expect(writer.string).to match(/ci_builds_per_runner{status="running",runner="1",mirrors="0"} 0/)
expect(writer.string).to match(/ci_builds_per_runner{status="running",runner="2",mirrors="0"} 5/)
expect(writer.string).to match(/ci_builds_per_runner{status="running",runner="1",mirrors="1"} 0/)
expect(writer.string).to match(/ci_builds_per_runner{status="running",runner="2",mirrors="1"} 10/)
expect(writer.string).to match(/ci_running_builds{runner="1",shared_runner="yes",mirror="no",pending_delete="no",mirror_trigger_builds="no"} 15/)
expect(writer.string).to match(/ci_running_builds{runner="2",shared_runner="no",mirror="yes",pending_delete="no",mirror_trigger_builds="yes"} 5/)
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