Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/database/query_analyzer.rb')
-rw-r--r--lib/gitlab/database/query_analyzer.rb60
1 files changed, 60 insertions, 0 deletions
diff --git a/lib/gitlab/database/query_analyzer.rb b/lib/gitlab/database/query_analyzer.rb
new file mode 100644
index 00000000000..830ad1383c0
--- /dev/null
+++ b/lib/gitlab/database/query_analyzer.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ # The purpose of this class is to implement a various query analyzers based on `pg_query`
+ # And process them all via `Gitlab::Database::QueryAnalyzers::*`
+ class QueryAnalyzer
+ ANALYZERS = [].freeze
+
+ Parsed = Struct.new(
+ :sql, :connection, :pg
+ )
+
+ def hook!
+ @subscriber = ActiveSupport::Notifications.subscribe('sql.active_record') do |event|
+ process_sql(event.payload[:sql], event.payload[:connection])
+ end
+ end
+
+ private
+
+ def process_sql(sql, connection)
+ analyzers = enabled_analyzers(connection)
+ return unless analyzers.any?
+
+ parsed = parse(sql, connection)
+ return unless parsed
+
+ analyzers.each do |analyzer|
+ analyzer.analyze(parsed)
+ rescue => e # rubocop:disable Style/RescueStandardError
+ # We catch all standard errors to prevent validation errors to introduce fatal errors in production
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
+ end
+ end
+
+ def enabled_analyzers(connection)
+ ANALYZERS.select do |analyzer|
+ analyzer.enabled?(connection)
+ rescue StandardError => e # rubocop:disable Style/RescueStandardError
+ # We catch all standard errors to prevent validation errors to introduce fatal errors in production
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
+ end
+ end
+
+ def parse(sql, connection)
+ parsed = PgQuery.parse(sql)
+ return unless parsed
+
+ normalized = PgQuery.normalize(sql)
+ Parsed.new(normalized, connection, parsed)
+ rescue PgQuery::ParseError => e
+ # Ignore PgQuery parse errors (due to depth limit or other reasons)
+ Gitlab::ErrorTracking.track_exception(e)
+
+ nil
+ end
+ end
+ end
+end