-
Notifications
You must be signed in to change notification settings - Fork 407
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Similar to the mysql2 patch, this workaround is for PG (Postgresql) u…
…sers who are experiencing conflict between rack-mini-profiler and another gem that does the same patching.
- Loading branch information
Showing
5 changed files
with
180 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,122 +1,7 @@ | ||
# frozen_string_literal: true | ||
|
||
# PG patches, keep in mind exec and async_exec have a exec{|r| } semantics that is yet to be implemented | ||
class PG::Result | ||
alias_method :each_without_profiling, :each | ||
alias_method :values_without_profiling, :values | ||
|
||
def values(*args, &blk) | ||
return values_without_profiling(*args, &blk) unless defined?(@miniprofiler_sql_id) | ||
mp_report_sql do | ||
values_without_profiling(*args , &blk) | ||
end | ||
end | ||
|
||
def each(*args, &blk) | ||
return each_without_profiling(*args, &blk) unless defined?(@miniprofiler_sql_id) | ||
mp_report_sql do | ||
each_without_profiling(*args, &blk) | ||
end | ||
end | ||
|
||
def mp_report_sql(&block) | ||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = yield | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
@miniprofiler_sql_id.report_reader_duration(elapsed_time) | ||
result | ||
end | ||
end | ||
|
||
class PG::Connection | ||
alias_method :exec_without_profiling, :exec | ||
alias_method :async_exec_without_profiling, :async_exec | ||
alias_method :exec_prepared_without_profiling, :exec_prepared | ||
alias_method :send_query_prepared_without_profiling, :send_query_prepared | ||
alias_method :prepare_without_profiling, :prepare | ||
|
||
if Gem::Version.new(PG::VERSION) >= Gem::Version.new("1.1.0") | ||
alias_method :exec_params_without_profiling, :exec_params | ||
end | ||
|
||
def prepare(*args, &blk) | ||
# we have no choice but to do this here, | ||
# if we do the check for profiling first, our cache may miss critical stuff | ||
|
||
@prepare_map ||= {} | ||
@prepare_map[args[0]] = args[1] | ||
# dont leak more than 10k ever | ||
@prepare_map = {} if @prepare_map.length > 1000 | ||
|
||
return prepare_without_profiling(*args, &blk) unless SqlPatches.should_measure? | ||
prepare_without_profiling(*args, &blk) | ||
end | ||
|
||
def exec(*args, &blk) | ||
return exec_without_profiling(*args, &blk) unless SqlPatches.should_measure? | ||
|
||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = exec_without_profiling(*args, &blk) | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time) | ||
result.instance_variable_set("@miniprofiler_sql_id", record) if result | ||
|
||
result | ||
end | ||
|
||
if Gem::Version.new(PG::VERSION) >= Gem::Version.new("1.1.0") | ||
def exec_params(*args, &blk) | ||
return exec_params_without_profiling(*args, &blk) unless SqlPatches.should_measure? | ||
|
||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = exec_params_without_profiling(*args, &blk) | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time) | ||
result.instance_variable_set("@miniprofiler_sql_id", record) if result | ||
|
||
result | ||
end | ||
end | ||
|
||
def exec_prepared(*args, &blk) | ||
return exec_prepared_without_profiling(*args, &blk) unless SqlPatches.should_measure? | ||
|
||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = exec_prepared_without_profiling(*args, &blk) | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
mapped = args[0] | ||
mapped = @prepare_map[mapped] || args[0] if @prepare_map | ||
record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time) | ||
result.instance_variable_set("@miniprofiler_sql_id", record) if result | ||
|
||
result | ||
end | ||
|
||
def send_query_prepared(*args, &blk) | ||
return send_query_prepared_without_profiling(*args, &blk) unless SqlPatches.should_measure? | ||
|
||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = send_query_prepared_without_profiling(*args, &blk) | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
mapped = args[0] | ||
mapped = @prepare_map[mapped] || args[0] if @prepare_map | ||
record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time) | ||
result.instance_variable_set("@miniprofiler_sql_id", record) if result | ||
|
||
result | ||
end | ||
|
||
def async_exec(*args, &blk) | ||
return async_exec_without_profiling(*args, &blk) unless SqlPatches.should_measure? | ||
|
||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = exec_without_profiling(*args, &blk) | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time) | ||
result.instance_variable_set("@miniprofiler_sql_id", record) if result | ||
|
||
result | ||
end | ||
|
||
alias_method :query, :exec | ||
if defined?(Rack::MINI_PROFILER_PREPEND_PG_PATCH) | ||
require "patches/db/pg/prepend" | ||
else | ||
require "patches/db/pg/alias_method" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
# frozen_string_literal: true | ||
|
||
# The best kind of instrumentation is in the actual db provider, however we don't want to double instrument | ||
|
||
class PG::Result | ||
alias_method :each_without_profiling, :each | ||
alias_method :values_without_profiling, :values | ||
|
||
def values(*args, &blk) | ||
return values_without_profiling(*args, &blk) unless defined?(@miniprofiler_sql_id) | ||
mp_report_sql do | ||
values_without_profiling(*args , &blk) | ||
end | ||
end | ||
|
||
def each(*args, &blk) | ||
return each_without_profiling(*args, &blk) unless defined?(@miniprofiler_sql_id) | ||
mp_report_sql do | ||
each_without_profiling(*args, &blk) | ||
end | ||
end | ||
|
||
def mp_report_sql(&block) | ||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = yield | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
@miniprofiler_sql_id.report_reader_duration(elapsed_time) | ||
result | ||
end | ||
end | ||
|
||
class PG::Connection | ||
alias_method :exec_without_profiling, :exec | ||
alias_method :async_exec_without_profiling, :async_exec | ||
alias_method :exec_prepared_without_profiling, :exec_prepared | ||
alias_method :send_query_prepared_without_profiling, :send_query_prepared | ||
alias_method :prepare_without_profiling, :prepare | ||
|
||
if Gem::Version.new(PG::VERSION) >= Gem::Version.new("1.1.0") | ||
alias_method :exec_params_without_profiling, :exec_params | ||
end | ||
|
||
def prepare(*args, &blk) | ||
# we have no choice but to do this here, | ||
# if we do the check for profiling first, our cache may miss critical stuff | ||
|
||
@prepare_map ||= {} | ||
@prepare_map[args[0]] = args[1] | ||
# dont leak more than 10k ever | ||
@prepare_map = {} if @prepare_map.length > 1000 | ||
|
||
return prepare_without_profiling(*args, &blk) unless SqlPatches.should_measure? | ||
prepare_without_profiling(*args, &blk) | ||
end | ||
|
||
def exec(*args, &blk) | ||
return exec_without_profiling(*args, &blk) unless SqlPatches.should_measure? | ||
|
||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = exec_without_profiling(*args, &blk) | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time) | ||
result.instance_variable_set("@miniprofiler_sql_id", record) if result | ||
|
||
result | ||
end | ||
|
||
if Gem::Version.new(PG::VERSION) >= Gem::Version.new("1.1.0") | ||
def exec_params(*args, &blk) | ||
return exec_params_without_profiling(*args, &blk) unless SqlPatches.should_measure? | ||
|
||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = exec_params_without_profiling(*args, &blk) | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time) | ||
result.instance_variable_set("@miniprofiler_sql_id", record) if result | ||
|
||
result | ||
end | ||
end | ||
|
||
def exec_prepared(*args, &blk) | ||
return exec_prepared_without_profiling(*args, &blk) unless SqlPatches.should_measure? | ||
|
||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = exec_prepared_without_profiling(*args, &blk) | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
mapped = args[0] | ||
mapped = @prepare_map[mapped] || args[0] if @prepare_map | ||
record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time) | ||
result.instance_variable_set("@miniprofiler_sql_id", record) if result | ||
|
||
result | ||
end | ||
|
||
def send_query_prepared(*args, &blk) | ||
return send_query_prepared_without_profiling(*args, &blk) unless SqlPatches.should_measure? | ||
|
||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = send_query_prepared_without_profiling(*args, &blk) | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
mapped = args[0] | ||
mapped = @prepare_map[mapped] || args[0] if @prepare_map | ||
record = ::Rack::MiniProfiler.record_sql(mapped, elapsed_time) | ||
result.instance_variable_set("@miniprofiler_sql_id", record) if result | ||
|
||
result | ||
end | ||
|
||
def async_exec(*args, &blk) | ||
return async_exec_without_profiling(*args, &blk) unless SqlPatches.should_measure? | ||
|
||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = exec_without_profiling(*args, &blk) | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
record = ::Rack::MiniProfiler.record_sql(args[0], elapsed_time) | ||
result.instance_variable_set("@miniprofiler_sql_id", record) if result | ||
|
||
result | ||
end | ||
|
||
alias_method :query, :exec | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# frozen_string_literal: true | ||
|
||
class PG::Result | ||
module MiniProfiler | ||
def each(*args, &blk) | ||
return super unless defined?(@miniprofiler_sql_id) | ||
|
||
start = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
result = super | ||
elapsed_time = SqlPatches.elapsed_time(start) | ||
|
||
@miniprofiler_sql_id.report_reader_duration(elapsed_time) | ||
result | ||
end | ||
end | ||
|
||
prepend MiniProfiler | ||
end | ||
|
||
class PG::Connection | ||
module MiniProfiler | ||
def query(*args, &blk) | ||
return super unless SqlPatches.should_measure? | ||
|
||
result, record = SqlPatches.record_sql(args[0]) do | ||
super | ||
end | ||
result.instance_variable_set("@miniprofiler_sql_id", record) if result | ||
result | ||
end | ||
end | ||
|
||
prepend MiniProfiler | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
module Rack | ||
MINI_PROFILER_PREPEND_PG_PATCH = true | ||
end |