├── .github ├── dependabot.yml └── workflows │ ├── ci.yml │ └── publish.yml ├── .gitignore ├── .rspec ├── .rubocop.yml ├── Gemfile ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── lib └── lograge │ ├── active_record_log_subscriber.rb │ ├── sql.rb │ └── sql │ ├── extension.rb │ ├── railtie.rb │ └── version.rb ├── lograge-sql.gemspec └── spec ├── lograge ├── active_record_log_subscriber_spec.rb └── sql_spec.rb └── spec_helper.rb /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Set update schedule for GitHub Actions 2 | 3 | version: 2 4 | updates: 5 | 6 | - package-ecosystem: "github-actions" 7 | directory: "/" 8 | schedule: 9 | # Check for updates to GitHub Actions every week 10 | interval: "weekly" 11 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | 8 | jobs: 9 | linting: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | - name: Set up Ruby 15 | uses: ruby/setup-ruby@v1 16 | with: 17 | ruby-version: 2.7 18 | bundler-cache: true # 'bundle install' and cache 19 | - name: Rubocop 20 | run: bundle exec rubocop --format progress 21 | - name: Inch 22 | run: "ruby -e \"require 'json'; res = JSON.parse('$(bundle exec inch stats --format=json)')['grade_lists']; exit(1) if res['C'].positive? || res['U'].positive?\"" 23 | 24 | test: 25 | needs: [linting] 26 | runs-on: ubuntu-latest 27 | env: 28 | RAILS_VERSION: '~> ${{ matrix.rails }}' 29 | strategy: 30 | matrix: 31 | ruby: [ '2.7', '3.0', '3.1', '3.2' ] 32 | rails: [ '6.0.0', '6.1.0', '7.0.0', '7.1.0', '7.2.0', '8.0.0' ] 33 | exclude: 34 | - ruby: '2.7' 35 | rails: '7.2.0' 36 | - ruby: '2.7' 37 | rails: '8.0.0' 38 | - ruby: '3.0' 39 | rails: '7.2.0' 40 | - ruby: '3.0' 41 | rails: '8.0.0' 42 | - ruby: '3.1' 43 | rails: '8.0.0' 44 | - ruby: '3.2' 45 | rails: '6.0.0' 46 | 47 | steps: 48 | - uses: actions/checkout@v4 49 | - name: Set up Ruby 50 | uses: ruby/setup-ruby@v1 51 | with: 52 | ruby-version: ${{ matrix.ruby }} 53 | bundler-cache: true # 'bundle install' and cache 54 | - name: Run tests 55 | run: bundle exec rake 56 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build: 9 | name: Publish to Rubygems 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Set up Ruby 2.7 16 | uses: ruby/setup-ruby@v1 17 | with: 18 | ruby-version: 2.7 19 | 20 | - name: Publish to RubyGems 21 | uses: dawidd6/action-publish-gem@v1 22 | with: 23 | api_key: ${{secrets.RUBYGEMS_AUTH_TOKEN}} 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.yardoc 2 | /_yardoc/ 3 | /coverage/ 4 | /doc/ 5 | /pkg/ 6 | /spec/reports/ 7 | /tmp/ 8 | .idea 9 | 10 | ## BUNDLER 11 | *.gem 12 | .bundle 13 | Gemfile.lock 14 | vendor/bundle 15 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | --require spec_helper 4 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | require: 2 | - rubocop-performance 3 | 4 | AllCops: 5 | DisplayCopNames: true 6 | DisplayStyleGuide: true 7 | TargetRubyVersion: 2.5 8 | Exclude: 9 | - vendor/bundle/**/* 10 | - gemfiles/vendor/bundle/**/* 11 | 12 | Metrics/BlockLength: 13 | Exclude: 14 | - spec/**/*.rb 15 | 16 | Metrics/LineLength: 17 | Max: 120 18 | Exclude: 19 | - spec/**/*.rb 20 | 21 | Style/Documentation: 22 | Exclude: 23 | - 'spec/**/*' 24 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | # Specify your gem's dependencies in lograge-sql.gemspec 6 | gemspec 7 | 8 | install_if -> { ENV.fetch('RAILS_VERSION', nil) } do 9 | gem 'rails', ENV.fetch('RAILS_VERSION', nil) 10 | end 11 | 12 | group :development do 13 | gem 'rspec', '~> 3.0' 14 | gem 'simplecov', '~> 0.12' 15 | end 16 | 17 | group :linting do 18 | gem 'inch', '~> 0.8.0' 19 | gem 'rubocop-performance', '~> 1.5' 20 | gem 'rubocop-rails', '~> 2.7' 21 | end 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lograge::Sql 2 | 3 | [![Gem Version](https://badge.fury.io/rb/lograge-sql.svg)](https://badge.fury.io/rb/lograge-sql) 4 | [![CI](https://github.com/iMacTia/lograge-sql/actions/workflows/ci.yml/badge.svg)](https://github.com/iMacTia/lograge-sql/actions/workflows/ci.yml) 5 | 6 | Lograge::Sql is an extension to the famous [Lograge](https://github.com/roidrage/lograge) gem, which adds SQL queries to the Lograge Event and disable default ActiveRecord logging. 7 | This is extremely useful if you're using Lograge together with the ELK stack. 8 | 9 | ## Installation 10 | 11 | Add this line to your application's Gemfile: 12 | 13 | ```ruby 14 | gem 'lograge-sql' 15 | ``` 16 | 17 | ## Usage 18 | 19 | In order to enable SQL logging in your application, you'll simply need to add this on top of your lograge initializer: 20 | 21 | ```ruby 22 | # config/initializers/lograge 23 | require 'lograge/sql/extension' 24 | ``` 25 | 26 | By default, Lograge::Sql disables default logging on ActiveRecord. To preserve default logging, add this to your lograge initializer: 27 | 28 | ```ruby 29 | config.lograge_sql.keep_default_active_record_log = true 30 | ``` 31 | 32 | ## Configuration 33 | 34 | ### Minimum query duration threshold 35 | 36 | By default, `lograge-sql` stores all queries, but you can set a `min_duration_ms` config. 37 | When you do so, only queries that run for AT LEAST `min_duration_ms` milliseconds will be logged, and all others will be ignored. 38 | This can be really helpful if you want to detect `Slow SQL queries`. 39 | 40 | ```ruby 41 | # config/initializers/lograge.rb 42 | Rails.application.configure do 43 | # Defaults is zero 44 | config.lograge_sql.min_duration_ms = 5000 # milliseconds 45 | end 46 | ``` 47 | 48 | ### Filtering sql queries by name 49 | 50 | You can filter out queries using the `query_name_denylist` configuration. 51 | This takes an array of regular expressions to match against the query name. If the query name matches any of the regular expressions, it will be ignored. By default, `lograge-sql` ignores queries named `SCHEMA` and queries from the `SolidCable` namespace. 52 | If you are using Solid Cable in your project, be careful when removing this default value as it will cause a [memory leak](https://github.com/iMacTia/lograge-sql/issues/59). 53 | 54 | ```ruby 55 | # config/initializers/lograge.rb 56 | Rails.application.configure do 57 | # Defaults is [/\ASCHEMA\z/, /\ASolidCable::/] 58 | config.lograge_sql.query_name_denylist << /\AEXACT NAME TO IGNORE\z/ 59 | end 60 | ``` 61 | 62 | ### Output Customization 63 | 64 | By default, the format is a string concatenation of the query name, the query duration and the query itself joined by `\n` newline: 65 | 66 | ``` 67 | method=GET path=/mypath format=html ... 68 | Object Load (0.42) SELECT "objects.*" FROM "objects" 69 | Associations Load (0.42) SELECT "associations.*" FROM "associations" WHERE "associations"."object_id" = "$1" 70 | ``` 71 | 72 | However, having `Lograge::Formatters::Json.new`, the relevant output is 73 | 74 | ```json 75 | { 76 | "sql_queries": "name1 ({duration1}) {query1}\nname2 ({duration2}) query2 ...", 77 | "sql_queries_count": 3 78 | } 79 | ``` 80 | 81 | To customize the output: 82 | 83 | ```ruby 84 | # config/initializers/lograge.rb 85 | Rails.application.configure do 86 | 87 | # Instead of extracting event as Strings, extract as Hash. You can also extract 88 | # additional fields to add to the formatter 89 | config.lograge_sql.extract_event = Proc.new do |event| 90 | { name: event.payload[:name], duration: event.duration.to_f.round(2), sql: event.payload[:sql] } 91 | end 92 | # Format the array of extracted events 93 | config.lograge_sql.formatter = Proc.new do |sql_queries| 94 | sql_queries 95 | end 96 | end 97 | ``` 98 | 99 | ### Filtering out sensitive info in SQL logs 100 | By default, `lograge-sql` will log full query but if you have sensitive data that need to be filtered out, you can set `query_filter` config: 101 | 102 | ```ruby 103 | Rails.application.configure do 104 | config.lograge_sql.query_filter = ->(query) { query.gsub(/custom_regexp/, "[FILTERED]".freeze) } 105 | end 106 | ``` 107 | 108 | ### Thread-safety 109 | 110 | [Depending on the web server in your project](https://github.com/steveklabnik/request_store#the-problem) you might benefit from improved thread-safety by adding [`request_store`](https://github.com/steveklabnik/request_store) to your Gemfile. It will be automatically picked up by `lograge-sql`. 111 | 112 | ## Contributing 113 | 114 | Bug reports and pull requests are welcome on GitHub at https://github.com/iMacTia/lograge-sql. 115 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler/gem_tasks' 4 | require 'rspec/core/rake_task' 5 | 6 | RSpec::Core::RakeTask.new(:spec) 7 | 8 | task default: :spec 9 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'bundler/setup' 5 | require 'lograge/sql' 6 | 7 | # You can add fixtures and/or initialization code here to make experimenting 8 | # with your gem easier. You can also use a different console, if you like. 9 | 10 | # (If you use this, don't forget to add pry to your Gemfile!) 11 | # require "pry" 12 | # Pry.start 13 | 14 | require 'irb' 15 | IRB.start 16 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /lib/lograge/active_record_log_subscriber.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Lograge 4 | # Log subscriber to replace ActiveRecord's default one 5 | class ActiveRecordLogSubscriber < ActiveSupport::LogSubscriber 6 | # Every time there's an SQL query, stores it into the Thread. 7 | # They'll later be accessed from the RequestLogSubscriber. 8 | def sql(event) 9 | increase_runtime_duration(event) 10 | return unless valid?(event) 11 | 12 | filter_query(event) 13 | store(event) 14 | end 15 | 16 | private 17 | 18 | # Add the event duration to the overall ActiveRecord::RuntimeRegistry.sql_runtime; 19 | # note we don't do this when `keep_default_active_record_log` is enabled, 20 | # as ActiveRecord is already adding the duration. 21 | def increase_runtime_duration(event) 22 | return if Rails.application.config.lograge_sql.keep_default_active_record_log 23 | 24 | ActiveRecord::RuntimeRegistry.sql_runtime ||= 0.0 25 | ActiveRecord::RuntimeRegistry.sql_runtime += event.duration 26 | end 27 | 28 | def filter_query(event) 29 | return unless Lograge::Sql.query_filter 30 | 31 | # Filtering out sensitive info in SQL query if custom query_filter is provided 32 | event.payload[:sql] = Lograge::Sql.query_filter.call(event.payload[:sql]) 33 | end 34 | 35 | def valid?(event) 36 | return false if event.payload[:name]&.match?(Lograge::Sql.query_name_denylist) 37 | 38 | # Only store SQL events if `event.duration` is greater than the configured +min_duration+ 39 | # No need to check if +min_duration+ is present before as it defaults to 0 40 | return false if event.duration.to_f.round(2) < Lograge::Sql.min_duration_ms.to_f 41 | 42 | true 43 | end 44 | 45 | def store(event) 46 | Lograge::Sql.store[:lograge_sql_queries] ||= [] 47 | Lograge::Sql.store[:lograge_sql_queries] << Lograge::Sql.extract_event.call(event) 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/lograge/sql.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'lograge/sql/version' 4 | 5 | # Main Lograge module 6 | module Lograge 7 | # Main gem module 8 | module Sql 9 | class << self 10 | # Format SQL log 11 | attr_accessor :formatter 12 | # Extract information from SQL event 13 | attr_accessor :extract_event 14 | # Filter SQL events by duration 15 | attr_accessor :min_duration_ms 16 | # Filter SQL query 17 | attr_accessor :query_filter 18 | # Filter wich SQL queries to store 19 | attr_accessor :query_name_denylist 20 | 21 | # Initialise configuration with fallback to default values 22 | def setup(config) # rubocop:disable Metrics/AbcSize 23 | Lograge::Sql.formatter = config.formatter || default_formatter 24 | Lograge::Sql.extract_event = config.extract_event || default_extract_event 25 | Lograge::Sql.min_duration_ms = config.min_duration_ms || 0 26 | Lograge::Sql.query_filter = config.query_filter 27 | Lograge::Sql.query_name_denylist = Regexp.union(config.query_name_denylist || [/\ASCHEMA\z/, /\ASolidCable::/]) 28 | 29 | # Disable existing ActiveRecord logging 30 | unsubscribe_log_subscribers unless config.keep_default_active_record_log 31 | 32 | return unless defined?(Lograge::ActiveRecordLogSubscriber) 33 | 34 | Lograge::ActiveRecordLogSubscriber.attach_to(:active_record) 35 | end 36 | 37 | # Gets the store, preferring RequestStore if the gem is found. 38 | # @return [Hash, Thread] the RequestStore or the current Thread. 39 | def store 40 | defined?(RequestStore) ? RequestStore.store : Thread.current 41 | end 42 | 43 | private 44 | 45 | # By default, the output is a concatenated string of all extracted events 46 | def default_formatter 47 | proc do |sql_queries| 48 | %('#{sql_queries.join("\n")}') 49 | end 50 | end 51 | 52 | # By default, only extract values required for the default_formatter and 53 | # already convert to a string 54 | def default_extract_event 55 | proc do |event| 56 | "#{event.payload[:name]} (#{event.duration.to_f.round(2)}) #{event.payload[:sql]}" 57 | end 58 | end 59 | 60 | def unsubscribe_log_subscribers 61 | ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber| 62 | Lograge.unsubscribe(:active_record, subscriber) if subscriber.is_a?(ActiveRecord::LogSubscriber) 63 | end 64 | end 65 | end 66 | end 67 | end 68 | 69 | # Rails specific configuration 70 | require 'lograge/sql/railtie' if defined?(Rails) 71 | -------------------------------------------------------------------------------- /lib/lograge/sql/extension.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'lograge/active_record_log_subscriber' 4 | 5 | module Lograge 6 | module Sql 7 | # Module used to extend Lograge 8 | module Extension 9 | # Overrides `Lograge::RequestLogSubscriber#extract_request` do add SQL queries 10 | def extract_request(event, payload) 11 | super.merge!(extract_sql_queries) 12 | end 13 | 14 | # Collects all SQL queries stored in the Thread during request processing 15 | def extract_sql_queries 16 | sql_queries = Lograge::Sql.store[:lograge_sql_queries] 17 | return {} unless sql_queries 18 | 19 | Lograge::Sql.store[:lograge_sql_queries] = nil 20 | { 21 | sql_queries: Lograge::Sql.formatter.call(sql_queries), 22 | sql_queries_count: sql_queries.length 23 | } 24 | end 25 | end 26 | end 27 | end 28 | 29 | if defined?(Lograge::RequestLogSubscriber) 30 | Lograge::RequestLogSubscriber.prepend Lograge::Sql::Extension 31 | else 32 | Lograge::LogSubscribers::ActionController.prepend Lograge::Sql::Extension 33 | end 34 | -------------------------------------------------------------------------------- /lib/lograge/sql/railtie.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'rails/railtie' 4 | require 'active_support/ordered_options' 5 | 6 | module Lograge 7 | module Sql 8 | # Railtie to automatically setup in Rails 9 | class Railtie < Rails::Railtie 10 | # To ensure that configuration is not nil when initialise Lograge::Sql.setup 11 | config.lograge_sql = ActiveSupport::OrderedOptions.new 12 | 13 | config.to_prepare do 14 | Lograge::Sql.setup(Rails.application.config.lograge_sql) 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/lograge/sql/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Lograge 4 | module Sql 5 | # Gem version 6 | VERSION = '2.5.1' 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lograge-sql.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path('lib', __dir__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require 'lograge/sql/version' 6 | 7 | Gem::Specification.new do |spec| 8 | spec.name = 'lograge-sql' 9 | spec.version = Lograge::Sql::VERSION 10 | spec.authors = ['Mattia Giuffrida'] 11 | spec.email = ['giuffrida.mattia@gmail.com'] 12 | 13 | spec.summary = 'An extension for Lograge to log SQL queries' 14 | spec.description = 'An extension for Lograge to log SQL queries' 15 | spec.homepage = 'https://github.com/iMacTia/lograge-sql' 16 | spec.license = 'MIT' 17 | 18 | spec.files = Dir['lib/**/*', 'Rakefile', 'README.md'] 19 | spec.require_paths = ['lib'] 20 | 21 | spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0') 22 | 23 | spec.add_dependency 'activerecord', '>= 5', '< 8.1' 24 | spec.add_dependency 'lograge', '~> 0.11' 25 | 26 | spec.add_development_dependency 'rake', '>= 12.3.3' 27 | end 28 | -------------------------------------------------------------------------------- /spec/lograge/active_record_log_subscriber_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe Lograge::ActiveRecordLogSubscriber do 4 | describe '#sql' do 5 | subject(:log_subscriber) { described_class.new } 6 | let(:event) { instance_double('ActiveSupport::Notification::Event.new', duration: 20, payload: {}) } 7 | let(:rails) { double('rails') } 8 | let(:ar_runtime_registry) { double('ActiveRecord::RuntimeRegistry', sql_runtime: 100.0) } 9 | 10 | before do 11 | stub_const('Rails', rails) 12 | stub_const('ActiveRecord::RuntimeRegistry', ar_runtime_registry) 13 | Lograge::Sql.extract_event = proc {} 14 | Lograge::Sql.store.clear 15 | Lograge::Sql.query_name_denylist = Regexp.union([/\ASCHEMA\z/, /\ASolidCable::/]) 16 | end 17 | 18 | context 'with keep_default_active_record_log not set' do 19 | before do 20 | allow(Rails).to receive_message_chain('application.config.lograge_sql.keep_default_active_record_log') { nil } 21 | end 22 | 23 | it 'adds duration to ActiveRecord::RuntimeRegistry sql_runtime' do 24 | expect(ar_runtime_registry).to receive(:sql_runtime=).with(120.0) 25 | 26 | log_subscriber.sql(event) 27 | end 28 | end 29 | 30 | context 'with keep_default_active_record_log set to true' do 31 | before do 32 | allow(Rails).to receive_message_chain('application.config.lograge_sql.keep_default_active_record_log') { true } 33 | end 34 | 35 | it 'does not add duration to ActiveRecord::RuntimeRegistry sql_runtime' do 36 | expect(ar_runtime_registry).to_not receive(:sql_runtime=) 37 | 38 | log_subscriber.sql(event) 39 | end 40 | end 41 | 42 | context 'with custom min_duration_ms threshold' do 43 | before do 44 | # this is just to avoid setting too many "allows". 45 | allow(Rails).to receive_message_chain('application.config.lograge_sql.keep_default_active_record_log') { true } 46 | Lograge::Sql.min_duration_ms = 500 47 | end 48 | 49 | after do 50 | # reset min_duration_ms after test 51 | Lograge::Sql.min_duration_ms = 0 52 | end 53 | 54 | it 'does not store the event' do 55 | log_subscriber.sql(event) 56 | expect(Lograge::Sql.store[:lograge_sql_queries]).to be_nil 57 | end 58 | end 59 | 60 | context 'with custom filter' do 61 | let(:query_filter) { instance_double(Proc, call: {}) } 62 | 63 | before do 64 | allow(Rails).to receive_message_chain('application.config.lograge_sql.keep_default_active_record_log') { true } 65 | allow(event).to receive(:payload).and_return({ sql: 'foo' }) 66 | Lograge::Sql.query_filter = query_filter 67 | end 68 | 69 | after do 70 | # reset filter after test 71 | Lograge::Sql.query_filter = nil 72 | end 73 | 74 | it 'apply filter to sql payload' do 75 | log_subscriber.sql(event) 76 | expect(query_filter).to have_received(:call).with('foo') 77 | end 78 | end 79 | 80 | context 'with default name denylist' do 81 | before do 82 | allow(Rails).to receive_message_chain('application.config.lograge_sql.keep_default_active_record_log') { true } 83 | end 84 | 85 | context 'with SCHEMA as name' do 86 | before do 87 | allow(event).to receive(:payload).and_return({ name: 'SCHEMA' }) 88 | end 89 | 90 | it 'does not store the event' do 91 | log_subscriber.sql(event) 92 | expect(Lograge::Sql.store[:lograge_sql_queries]).to be_nil 93 | end 94 | end 95 | 96 | context 'with name starting with SCHEMA' do 97 | before do 98 | allow(event).to receive(:payload).and_return({ name: 'SCHEMA foo' }) 99 | end 100 | 101 | it 'stores the event' do 102 | log_subscriber.sql(event) 103 | expect(Lograge::Sql.store[:lograge_sql_queries]).not_to be_nil 104 | end 105 | end 106 | 107 | context 'with name starting with SolidCable::' do 108 | before do 109 | allow(event).to receive(:payload).and_return({ name: 'SolidCable::Message Maximum' }) 110 | end 111 | 112 | it 'does not store the event' do 113 | log_subscriber.sql(event) 114 | expect(Lograge::Sql.store[:lograge_sql_queries]).to be_nil 115 | end 116 | end 117 | end 118 | end 119 | end 120 | -------------------------------------------------------------------------------- /spec/lograge/sql_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe Lograge::Sql do 4 | let(:subscriber) do 5 | if defined?(Lograge::RequestLogSubscriber) 6 | Lograge::RequestLogSubscriber 7 | else 8 | Lograge::LogSubscribers::ActionController 9 | end 10 | end 11 | 12 | it 'has a version number' do 13 | expect(Lograge::Sql::VERSION).not_to be nil 14 | end 15 | 16 | it 'extends lograge' do 17 | require 'lograge/sql/extension' 18 | 19 | expect(subscriber.new).to respond_to(:extract_sql_queries) 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'simplecov' 4 | SimpleCov.start 5 | 6 | $LOAD_PATH.unshift File.expand_path('../lib', __dir__) 7 | require 'delegate' 8 | require 'lograge' 9 | require 'lograge/sql' 10 | require 'lograge/active_record_log_subscriber' 11 | 12 | RSpec.configure do |config| # rubocop:disable Style/SymbolProc 13 | config.disable_monkey_patching! 14 | end 15 | --------------------------------------------------------------------------------