Commit 805e4096 authored by Dylan Griffith's avatar Dylan Griffith

Change to db_config.name for logging metrics per database

As GitLab is planning on moving `ci_*` tables to a separate database we
need to start expanding our observability/logging/metrics to allow us to
distinguish between the different databases being queried.

We had already implemented logging per database by including the
database name (ie. what Postgres calls the database) in the log
statements in
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63490 but later we
learnt this wasn't a good idea because we may want to use 2 different
Postgres servers with the same Database name (in fact that's what our
current migration plan involves). As such we need to use the name that
the GitLab application uses to distinguish between the 2 different
databases. This is the name used to configure the `config/database.yml`
and must be unique.

In the default case it does not have a name and Rails will call it
`primary`. This has the unfortunate result that this MR will add JSON
log keys `db_replica_primary_duration_s` and
`db_primary_primary_duration_s` because we already use the words
`primary/replica` to distinguish between our read-write primary and
read-only replicas. We plan to eventually force the
`config/database.yml` to name these `main` and `ci` and at that time
these log statements will be a little clearer. In the meantime this is
behind a feature flag so should not bother people that aren't intending
to try and make sense of these metrics.
parent cec62d8b
......@@ -352,11 +352,11 @@ module Gitlab
end
end
def self.dbname(ar_connection)
def self.db_config_name(ar_connection)
if ar_connection.respond_to?(:pool) &&
ar_connection.pool.respond_to?(:db_config) &&
ar_connection.pool.db_config.respond_to?(:database)
return ar_connection.pool.db_config.database
ar_connection.pool.db_config.respond_to?(:name)
return ar_connection.pool.db_config.name
end
'unknown'
......
......@@ -74,9 +74,9 @@ module Gitlab
end
if Feature.enabled?(:multiple_database_metrics, default_enabled: :yaml)
::Gitlab::SafeRequestStore[:duration_by_database]&.each do |dbname, duration_by_role|
::Gitlab::SafeRequestStore[:duration_by_database]&.each do |name, duration_by_role|
duration_by_role.each do |db_role, duration|
payload[:"db_#{db_role}_#{dbname}_duration_s"] = duration.to_f.round(3)
payload[:"db_#{db_role}_#{name}_duration_s"] = duration.to_f.round(3)
end
end
end
......@@ -113,11 +113,11 @@ module Gitlab
::Gitlab::SafeRequestStore[duration_key] = (::Gitlab::SafeRequestStore[duration_key].presence || 0) + duration
# Per database metrics
dbname = ::Gitlab::Database.dbname(event.payload[:connection])
name = ::Gitlab::Database.db_config_name(event.payload[:connection])
::Gitlab::SafeRequestStore[:duration_by_database] ||= {}
::Gitlab::SafeRequestStore[:duration_by_database][dbname] ||= {}
::Gitlab::SafeRequestStore[:duration_by_database][dbname][db_role] ||= 0
::Gitlab::SafeRequestStore[:duration_by_database][dbname][db_role] += duration
::Gitlab::SafeRequestStore[:duration_by_database][name] ||= {}
::Gitlab::SafeRequestStore[:duration_by_database][name][db_role] ||= 0
::Gitlab::SafeRequestStore[:duration_by_database][name][db_role] += duration
end
def ignored_query?(payload)
......
......@@ -487,19 +487,19 @@ RSpec.describe Gitlab::Database do
end
end
describe '.dbname' do
it 'returns the dbname for the connection' do
describe '.db_config_name' do
it 'returns the db_config name for the connection' do
connection = ActiveRecord::Base.connection
expect(described_class.dbname(connection)).to be_a(String)
expect(described_class.dbname(connection)).to eq(connection.pool.db_config.database)
expect(described_class.db_config_name(connection)).to be_a(String)
expect(described_class.db_config_name(connection)).to eq(connection.pool.db_config.name)
end
context 'when the pool is a NullPool' do
it 'returns unknown' do
connection = double(:active_record_connection, pool: ActiveRecord::ConnectionAdapters::NullPool.new)
expect(described_class.dbname(connection)).to eq('unknown')
expect(described_class.db_config_name(connection)).to eq('unknown')
end
end
end
......
......@@ -298,7 +298,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
end
let(:dbname) { ::Gitlab::Database.dbname(ActiveRecord::Base.connection) }
let(:db_config_name) { ::Gitlab::Database.db_config_name(ActiveRecord::Base.connection) }
let(:expected_end_payload_with_db) do
expected_end_payload.merge(
......@@ -314,7 +314,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
'db_primary_cached_count' => 0,
'db_primary_wal_count' => 0,
'db_primary_duration_s' => a_value > 0,
"db_primary_#{dbname}_duration_s" => a_value > 0,
"db_primary_#{db_config_name}_duration_s" => a_value > 0,
'db_primary_wal_cached_count' => 0,
'db_replica_wal_cached_count' => 0
)
......
......@@ -23,7 +23,7 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
db_replica_wal_cached_count: 0,
db_replica_wal_count: 0
}
expected[:"db_primary_#{::Gitlab::Database.dbname(connection)}_duration_s"] = 0.002 if record_query
expected[:"db_primary_#{::Gitlab::Database.db_config_name(connection)}_duration_s"] = 0.002 if record_query
elsif db_role == :replica
expected = {
db_count: record_query ? 1 : 0,
......@@ -40,7 +40,7 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
db_primary_wal_cached_count: 0,
db_primary_wal_count: 0
}
expected[:"db_replica_#{::Gitlab::Database.dbname(connection)}_duration_s"] = 0.002 if record_query
expected[:"db_replica_#{::Gitlab::Database.db_config_name(connection)}_duration_s"] = 0.002 if record_query
else
expected = {
db_count: record_query ? 1 : 0,
......@@ -64,7 +64,7 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
subscriber.sql(event)
connection = event.payload[:connection]
expect(described_class.db_counter_payload).not_to include(:"db_replica_#{::Gitlab::Database.dbname(connection)}_duration_s")
expect(described_class.db_counter_payload).not_to include(:"db_replica_#{::Gitlab::Database.db_config_name(connection)}_duration_s")
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