"Fossies" - the Fresh Open Source Software Archive

Member "discourse-2.8.3/config/initializers/000-trace_pg_connections.rb" (14 Apr 2022, 2691 Bytes) of package /linux/www/discourse-2.8.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Ruby source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 # frozen_string_literal: true
    2 
    3 # Setting TRACE_PG_CONNECTIONS=1 will cause all pg connections
    4 # to be streamed to files for debugging. The filenames are formatted
    5 # like tmp/pgtrace/{{PID}}_{{CONNECTION_OBJECT_ID}}.txt
    6 #
    7 # Setting TRACE_PG_CONNECTIONS=SIDEKIQ will only trace connections
    8 # on in sidekiq (safer, because there will be minimal user-facing perf impact)
    9 #
   10 # Files will be automatically deleted when the connection is closed gracefully
   11 # (e.g. when activerecord closes it after a period of inactivity)
   12 # Files will not be automatically deleted when closed abruptly
   13 # (e.g. terminating/restarting the app process)
   14 #
   15 # Warning: this could create some very large files!
   16 
   17 if ENV["TRACE_PG_CONNECTIONS"]
   18   PG::Connection.prepend(Module.new do
   19     TRACE_DIR = "tmp/pgtrace"
   20 
   21     def initialize(*args)
   22       super(*args).tap do
   23         next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server?
   24         FileUtils.mkdir_p(TRACE_DIR)
   25         @trace_filename = "#{TRACE_DIR}/#{Process.pid}_#{self.object_id}.txt"
   26         trace File.new(@trace_filename, "w")
   27       end
   28       @access_log_mutex = Mutex.new
   29       @accessor_thread = nil
   30     end
   31 
   32     def close
   33       super.tap do
   34         next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server?
   35         File.delete(@trace_filename)
   36       end
   37     end
   38 
   39     def log_access(&blk)
   40       @access_log_mutex.synchronize do
   41         if !@accessor_thread.nil?
   42           Rails.logger.error <<~STRING
   43             PG Clash: A connection is being accessed from two locations
   44 
   45             #{@accessor_thread} was using the connection. Backtrace:
   46 
   47             #{@accessor_thread&.backtrace&.join("\n")}
   48 
   49             #{Thread.current} is now attempting to use the connection. Backtrace:
   50 
   51             #{Thread.current&.backtrace&.join("\n")}
   52           STRING
   53 
   54           if ENV["ON_PG_CLASH"] == "byebug"
   55             require "byebug"
   56             byebug # rubocop:disable Lint/Debugger
   57           end
   58         end
   59         @accessor_thread = Thread.current
   60       end
   61       yield
   62     ensure
   63       @access_log_mutex.synchronize do
   64         @accessor_thread = nil
   65       end
   66     end
   67 
   68   end)
   69 
   70   class PG::Connection
   71     LOG_ACCESS_METHODS = [:exec, :sync_exec, :async_exec,
   72                           :sync_exec_params, :async_exec_params,
   73                           :sync_prepare, :async_prepare,
   74                           :sync_exec_prepared, :async_exec_prepared,
   75                         ]
   76 
   77     LOG_ACCESS_METHODS.each do |method|
   78       new_method = "#{method}_without_logging".to_sym
   79       alias_method new_method, method
   80 
   81       define_method(method) do |*args, &blk|
   82         log_access { send(new_method, *args, &blk) }
   83       end
   84     end
   85   end
   86 
   87 end