summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLin Jen-Shin <godfat@godfat.org>2019-06-28 14:33:37 +0000
committerLin Jen-Shin <godfat@godfat.org>2019-06-28 14:33:37 +0000
commitc5da0b86d298c0d9a9f4e167e4ee2fef884bf286 (patch)
treeb915ff9ea365defce3a4ecfa6c0dc448d0532e1a /lib
parent652e9a77cfb900c45dced24bcc4352361bc389b8 (diff)
parent56ae34e49b80c8c93661e00e490d4c9048e70273 (diff)
downloadgitlab-ce-c5da0b86d298c0d9a9f4e167e4ee2fef884bf286.tar.gz
Merge branch 'transaction-metrics' into 'master'
Monitor database transaction activity for Rails See merge request gitlab-org/gitlab-ce!29928
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/database.rb33
-rw-r--r--lib/gitlab/optimistic_locking.rb1
2 files changed, 34 insertions, 0 deletions
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index e4d4779ba9a..62567be5258 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -2,6 +2,8 @@
module Gitlab
module Database
+ include Gitlab::Metrics::Methods
+
# The max value of INTEGER type is the same between MySQL and PostgreSQL:
# https://www.postgresql.org/docs/9.2/static/datatype-numeric.html
# http://dev.mysql.com/doc/refman/5.7/en/integer-types.html
@@ -11,6 +13,10 @@ module Gitlab
# https://dev.mysql.com/doc/refman/5.7/en/datetime.html
MAX_TIMESTAMP_VALUE = Time.at((1 << 31) - 1).freeze
+ define_histogram :gitlab_database_transaction_seconds do
+ docstring "Time spent in database transactions, in seconds"
+ end
+
def self.config
ActiveRecord::Base.configurations[Rails.env]
end
@@ -286,5 +292,32 @@ module Gitlab
0
end
private_class_method :open_transactions_baseline
+
+ # Monkeypatch rails with upgraded database observability
+ def self.install_monkey_patches
+ ActiveRecord::Base.prepend(ActiveRecordBaseTransactionMetrics)
+ end
+
+ # observe_transaction_duration is called from ActiveRecordBaseTransactionMetrics.transaction and used to
+ # record transaction durations.
+ def self.observe_transaction_duration(duration_seconds)
+ labels = Gitlab::Metrics::Transaction.current&.labels || {}
+ gitlab_database_transaction_seconds.observe(labels, duration_seconds)
+ rescue Prometheus::Client::LabelSetValidator::LabelSetError => err
+ # Ensure that errors in recording these metrics don't affect the operation of the application
+ Rails.logger.error("Unable to observe database transaction duration: #{err}")
+ end
+
+ # MonkeyPatch for ActiveRecord::Base for adding observability
+ module ActiveRecordBaseTransactionMetrics
+ # A monkeypatch over ActiveRecord::Base.transaction.
+ # It provides observability into transactional methods.
+ def transaction(options = {}, &block)
+ start_time = Gitlab::Metrics::System.monotonic_time
+ super(options, &block)
+ ensure
+ Gitlab::Database.observe_transaction_duration(Gitlab::Metrics::System.monotonic_time - start_time)
+ end
+ end
end
end
diff --git a/lib/gitlab/optimistic_locking.rb b/lib/gitlab/optimistic_locking.rb
index 868b2ae641a..0c0f46d3b77 100644
--- a/lib/gitlab/optimistic_locking.rb
+++ b/lib/gitlab/optimistic_locking.rb
@@ -5,6 +5,7 @@ module Gitlab
module_function
def retry_lock(subject, retries = 100, &block)
+ # TODO(Observability): We should be recording details of the number of retries and the duration of the total execution here
ActiveRecord::Base.transaction do
yield(subject)
end