Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compatibility with peek-mysql2 #451

Merged
merged 2 commits into from
Jan 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ gem 'rack-mini-profiler', require: ['prepend_net_http_patch']

This conflict happens when a ruby method is patched twice, once using module prepend, and once using method aliasing. See this [ruby issue](https://bugs.ruby-lang.org/issues/11120) for details. The fix is to apply all patches the same way. Mini Profiler by default will apply its patch using method aliasing, but you can change that to module prepend by adding `require: ['prepend_net_http_patch']` to the gem line as shown above.

#### `peek-mysql2` stack level too deep errors

If you use peek-mysql2 with Rails >= 5, you'll need to use this gem spec in your Gemfile:

```ruby
gem 'rack-mini-profiler', require: ['prepend_mysql2_patch', 'rack-mini-profiler']
```

This should not be necessary with Rails < 5 because peek-mysql2 hooks into mysql2 gem in different ways depending on your Rails version.

#### Rails and manual initialization

In case you need to make sure rack_mini_profiler is initialized after all other gems, or you want to execute some code before rack_mini_profiler required:
Expand Down
31 changes: 4 additions & 27 deletions lib/patches/db/mysql2.rb
Original file line number Diff line number Diff line change
@@ -1,30 +1,7 @@
# frozen_string_literal: true

# The best kind of instrumentation is in the actual db provider, however we don't want to double instrument

class Mysql2::Result
alias_method :each_without_profiling, :each
def each(*args, &blk)
return each_without_profiling(*args, &blk) unless defined?(@miniprofiler_sql_id)

start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
result = each_without_profiling(*args, &blk)
elapsed_time = SqlPatches.elapsed_time(start)

@miniprofiler_sql_id.report_reader_duration(elapsed_time)
result
end
end

class Mysql2::Client
alias_method :query_without_profiling, :query
def query(*args, &blk)
return query_without_profiling(*args, &blk) unless SqlPatches.should_measure?

result, record = SqlPatches.record_sql(args[0]) do
query_without_profiling(*args, &blk)
end
result.instance_variable_set("@miniprofiler_sql_id", record) if result
result
end
if defined?(Rack::MINI_PROFILER_PREPEND_MYSQL2_PATCH)
require "patches/db/mysql2/prepend"
else
require "patches/db/mysql2/alias_method"
end
30 changes: 30 additions & 0 deletions lib/patches/db/mysql2/alias_method.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

# The best kind of instrumentation is in the actual db provider, however we don't want to double instrument

class Mysql2::Result
alias_method :each_without_profiling, :each
def each(*args, &blk)
return each_without_profiling(*args, &blk) unless defined?(@miniprofiler_sql_id)

start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
result = each_without_profiling(*args, &blk)
elapsed_time = SqlPatches.elapsed_time(start)

@miniprofiler_sql_id.report_reader_duration(elapsed_time)
result
end
end

class Mysql2::Client
alias_method :query_without_profiling, :query
def query(*args, &blk)
return query_without_profiling(*args, &blk) unless SqlPatches.should_measure?

result, record = SqlPatches.record_sql(args[0]) do
query_without_profiling(*args, &blk)
end
result.instance_variable_set("@miniprofiler_sql_id", record) if result
result
end
end
34 changes: 34 additions & 0 deletions lib/patches/db/mysql2/prepend.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

class Mysql2::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 Mysql2::Client
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
5 changes: 5 additions & 0 deletions lib/prepend_mysql2_patch.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# frozen_string_literal: true

module Rack
MINI_PROFILER_PREPEND_MYSQL2_PATCH = true
end