Commit 0cca2912 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Instrument sub-transactions created using ApplicationRecord

parent cf6e08a6
......@@ -86,4 +86,17 @@ class ApplicationRecord < ActiveRecord::Base
values = enum_mod.definition.transform_values { |v| v[:value] }
enum(enum_mod.key => values)
end
def self.transaction(**options, &block)
if options[:requires_new] && track_subtransactions?
::Gitlab::Database::Metrics.subtransactions_increment(self.name)
end
super(**options, &block)
end
def self.track_subtransactions?
::Feature.enabled?(:active_record_subtransactions_counter, type: :ops, default_enabled: :yaml) &&
connection.transaction_open?
end
end
---
name: active_record_subtransactions_counter
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66477
rollout_issue_url:
milestone: '14.1'
type: ops
group: group::pipeline execution
default_enabled: false
......@@ -42,9 +42,9 @@ module Gitlab
# timeout - The time after which the pool should be forcefully
# disconnected.
def disconnect!(timeout = 120)
start_time = Metrics::System.monotonic_time
start_time = ::Gitlab::Metrics::System.monotonic_time
while (Metrics::System.monotonic_time - start_time) <= timeout
while (::Gitlab::Metrics::System.monotonic_time - start_time) <= timeout
break if pool.connections.none?(&:in_use?)
sleep(2)
......
# frozen_string_literal: true
module Gitlab
module Database
class Metrics
extend ::Gitlab::Utils::StrongMemoize
class << self
def subtransactions_increment(model_name)
subtransactions_counter.increment(model: model_name)
end
private
def subtransactions_counter
strong_memoize(:subtransactions_counter) do
name = :gitlab_active_record_subtransactions_total
comment = 'Total amount of subtransactions created by ActiveRecord'
::Gitlab::Metrics.counter(name, comment)
end
end
end
end
end
end
......@@ -105,6 +105,50 @@ RSpec.describe ApplicationRecord do
end
end
describe '.transaction', :delete do
it 'opens a new transaction' do
expect(described_class.connection.transaction_open?).to be false
Project.transaction do
expect(Project.connection.transaction_open?).to be true
Project.transaction(requires_new: true) do
expect(Project.connection.transaction_open?).to be true
end
end
end
it 'does not increment a counter when a transaction is not nested' do
expect(described_class.connection.transaction_open?).to be false
expect(::Gitlab::Database::Metrics)
.not_to receive(:subtransactions_increment)
Project.transaction do
expect(Project.connection.transaction_open?).to be true
end
Project.transaction(requires_new: true) do
expect(Project.connection.transaction_open?).to be true
end
end
it 'increments a counter when a nested transaction is created' do
expect(described_class.connection.transaction_open?).to be false
expect(::Gitlab::Database::Metrics)
.to receive(:subtransactions_increment)
.with('Project')
.once
Project.transaction do
Project.transaction(requires_new: true) do
expect(Project.connection.transaction_open?).to be true
end
end
end
end
describe '.with_fast_read_statement_timeout' do
context 'when the query runs faster than configured timeout' do
it 'executes the query without error' do
......
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