├── Rakefile ├── Gemfile ├── lib ├── query_trail.rb └── query_trail │ └── log_subscriber.rb ├── .gitignore ├── README.md ├── query_trail.gemspec └── LICENSE.txt /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /lib/query_trail.rb: -------------------------------------------------------------------------------- 1 | ActiveSupport.on_load :active_record do 2 | if Object.const_defined?('Rails::Server') 3 | require 'query_trail/log_subscriber' 4 | QueryTrail::LogSubscriber.attach_to(:active_record) 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | *.bundle 19 | *.so 20 | *.o 21 | *.a 22 | mkmf.log 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## QueryTrail for Rails >= 4.0 2 | 3 | Shows a backtrace of your queries: 4 | 5 | ``` 6 | User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 7 | Query Trail: config/initializers/warden.rb:11:in `block in ' 8 | config/initializers/warden.rb:15:in `block in ' 9 | Doc Load (18.2ms) SELECT `docs`.* FROM `docs` WHERE `docs`.`approved` = 1 10 | Query Trail: app/views/main/_docs.html.erb:2 11 | app/helpers/docs_helper.rb:3:in `render_main_block' 12 | app/views/main/index.html.erb:13 13 | app/views/main/index.html.erb:9 14 | ``` 15 | 16 | ## Installation 17 | 18 | ```ruby 19 | gem 'query_trail', group: :development 20 | ``` 21 | -------------------------------------------------------------------------------- /query_trail.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |spec| 2 | spec.name = 'query_trail' 3 | spec.version = '1.0' 4 | spec.authors = ['Dmitry Vorotilin'] 5 | spec.email = ['d.vorotilin@gmail.com'] 6 | spec.summary = "Shows the trace of your queries when they're fired" 7 | spec.homepage = 'https://github.com/route/query_trail' 8 | spec.license = 'MIT' 9 | 10 | spec.files = `git ls-files -z`.split("\x0") 11 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 12 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 13 | spec.require_paths = ['lib'] 14 | 15 | spec.add_runtime_dependency 'rails', '>= 4.0' 16 | 17 | spec.add_development_dependency 'bundler', '~> 1.6' 18 | spec.add_development_dependency 'rake' 19 | end 20 | -------------------------------------------------------------------------------- /lib/query_trail/log_subscriber.rb: -------------------------------------------------------------------------------- 1 | module QueryTrail 2 | class LogSubscriber < ActiveSupport::LogSubscriber 3 | HEADER = " \e[1m\e[34mQuery Trail:\e[0m " 4 | IGNORE_PAYLOAD_NAMES = ActiveRecord::LogSubscriber::IGNORE_PAYLOAD_NAMES 5 | 6 | def sql(event) 7 | return unless logger.debug? 8 | payload = event.payload 9 | return if IGNORE_PAYLOAD_NAMES.include?(payload[:name]) 10 | 11 | if backtrace = backtrace_cleaner.clean(caller).presence 12 | logger.debug HEADER + backtrace.shift 13 | logger.debug backtrace.map { |line| ' ' * (HEADER.size - 13) + line }.join("\n") 14 | end 15 | end 16 | 17 | private 18 | 19 | def logger 20 | ActiveRecord::Base.logger 21 | end 22 | 23 | def backtrace_cleaner 24 | @backtrace_cleaner ||= begin 25 | backtrace_cleaner = Rails::BacktraceCleaner.new 26 | backtrace_cleaner.add_filter { |line| line.sub(/(app\/views.*:\d+):in.*/, '\1') } 27 | backtrace_cleaner 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Dmitry Vorotilin 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | --------------------------------------------------------------------------------