debian-mirror-gitlab/lib/gitlab/database/transaction/context.rb
2021-10-27 15:23:28 +05:30

125 lines
2.9 KiB
Ruby

# frozen_string_literal: true
module Gitlab
module Database
module Transaction
class Context
attr_reader :context
LOG_DEPTH_THRESHOLD = 8
LOG_SAVEPOINTS_THRESHOLD = 32
LOG_DURATION_S_THRESHOLD = 300
LOG_THROTTLE_DURATION = 1
def initialize
@context = {}
end
def set_start_time
@context[:start_time] = current_timestamp
end
def increment_savepoints
@context[:savepoints] = @context[:savepoints].to_i + 1
end
def increment_rollbacks
@context[:rollbacks] = @context[:rollbacks].to_i + 1
end
def increment_releases
@context[:releases] = @context[:releases].to_i + 1
end
def set_depth(depth)
@context[:depth] = [@context[:depth].to_i, depth].max
end
def track_sql(sql)
(@context[:queries] ||= []).push(sql)
end
def duration
return unless @context[:start_time].present?
current_timestamp - @context[:start_time]
end
def depth_threshold_exceeded?
@context[:depth].to_i > LOG_DEPTH_THRESHOLD
end
def savepoints_threshold_exceeded?
@context[:savepoints].to_i > LOG_SAVEPOINTS_THRESHOLD
end
def duration_threshold_exceeded?
duration.to_i > LOG_DURATION_S_THRESHOLD
end
def log_savepoints?
depth_threshold_exceeded? || savepoints_threshold_exceeded?
end
def log_duration?
duration_threshold_exceeded?
end
def should_log?
!logged_already? && (log_savepoints? || log_duration?)
end
def commit
log(:commit)
end
def rollback
log(:rollback)
end
private
def queries
@context[:queries].to_a.join("\n")
end
def current_timestamp
::Gitlab::Metrics::System.monotonic_time
end
def logged_already?
return false if @context[:last_log_timestamp].nil?
(current_timestamp - @context[:last_log_timestamp].to_i) < LOG_THROTTLE_DURATION
end
def set_last_log_timestamp
@context[:last_log_timestamp] = current_timestamp
end
def log(operation)
return unless should_log?
set_last_log_timestamp
attributes = {
class: self.class.name,
result: operation,
duration_s: duration,
depth: @context[:depth].to_i,
savepoints_count: @context[:savepoints].to_i,
rollbacks_count: @context[:rollbacks].to_i,
releases_count: @context[:releases].to_i,
sql: queries
}
application_info(attributes)
end
def application_info(attributes)
Gitlab::AppJsonLogger.info(attributes)
end
end
end
end
end