"Fossies" - the Fresh Open Source Software Archive

Member "discourse-3.1.3/config/initializers/000-trace_pg_connections.rb" (9 Nov 2023, 2667 Bytes) of package /linux/www/discourse-3.1.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(
   19     Module.new do
   20       TRACE_DIR = "tmp/pgtrace"
   21 
   22       def initialize(*args)
   23         super(*args).tap do
   24           next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server?
   25           FileUtils.mkdir_p(TRACE_DIR)
   26           @trace_filename = "#{TRACE_DIR}/#{Process.pid}_#{self.object_id}.txt"
   27           trace File.new(@trace_filename, "w")
   28         end
   29         @access_log_mutex = Mutex.new
   30         @accessor_thread = nil
   31       end
   32 
   33       def close
   34         super.tap do
   35           next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server?
   36           File.delete(@trace_filename)
   37         end
   38       end
   39 
   40       def log_access(&blk)
   41         @access_log_mutex.synchronize do
   42           if !@accessor_thread.nil?
   43             Rails.logger.error <<~TEXT
   44             PG Clash: A connection is being accessed from two locations
   45 
   46             #{@accessor_thread} was using the connection. Backtrace:
   47 
   48             #{@accessor_thread&.backtrace&.join("\n")}
   49 
   50             #{Thread.current} is now attempting to use the connection. Backtrace:
   51 
   52             #{Thread.current&.backtrace&.join("\n")}
   53           TEXT
   54 
   55             if ENV["ON_PG_CLASH"] == "byebug"
   56               require "byebug"
   57               byebug # rubocop:disable Lint/Debugger
   58             end
   59           end
   60           @accessor_thread = Thread.current
   61         end
   62         yield
   63       ensure
   64         @access_log_mutex.synchronize { @accessor_thread = nil }
   65       end
   66     end,
   67   )
   68 
   69   class PG::Connection
   70     LOG_ACCESS_METHODS = %i[
   71       exec
   72       sync_exec
   73       async_exec
   74       sync_exec_params
   75       async_exec_params
   76       sync_prepare
   77       async_prepare
   78       sync_exec_prepared
   79       async_exec_prepared
   80     ]
   81 
   82     LOG_ACCESS_METHODS.each do |method|
   83       new_method = "#{method}_without_logging".to_sym
   84       alias_method new_method, method
   85 
   86       define_method(method) { |*args, &blk| log_access { send(new_method, *args, &blk) } }
   87     end
   88   end
   89 end