diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 460787a..0c5fe4c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,4 +20,17 @@ jobs: - name: Install dependencies run: bundle install - name: Run tests - run: bundle exec rspec spec/ + run: bundle exec rake spec + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.4" + bundler-cache: true + - name: Install dependencies + run: bundle install + - name: Run RuboCop + run: bundle exec rake rubocop diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..70e2ca4 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,14 @@ +inherit_from: .rubocop_todo.yml + +AllCops: + NewCops: enable + +Metrics/BlockLength: + CountAsOne: [array, hash, heredoc, method_call] + +Metrics/ClassLength: + CountAsOne: [array, hash, heredoc, method_call] + +Metrics/MethodLength: + CountAsOne: [array, hash, heredoc, method_call] + Max: 20 diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..37e25c1 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,160 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2025-07-10 10:25:51 UTC using RuboCop version 1.77.0. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 3 +# Configuration parameters: EnforcedStyle, AllowedGems, Include. +# SupportedStyles: Gemfile, gems.rb, gemspec +# Include: **/*.gemspec, **/Gemfile, **/gems.rb +Gemspec/DevelopmentDependencies: + Exclude: + - "grape_logging.gemspec" + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Severity, Include. +# Include: **/*.gemspec +Gemspec/RequireMFA: + Exclude: + - "grape_logging.gemspec" + +# Offense count: 1 +# Configuration parameters: Severity, Include. +# Include: **/*.gemspec +Gemspec/RequiredRubyVersion: + Exclude: + - "grape_logging.gemspec" + +# Offense count: 1 +# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch. +Lint/DuplicateBranch: + Exclude: + - "lib/grape_logging/util/parameter_filter.rb" + +# Offense count: 1 +# Configuration parameters: AllowedParentClasses. +Lint/MissingSuper: + Exclude: + - "lib/grape_logging/loggers/filter_parameters.rb" + +# Offense count: 3 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. +Metrics/AbcSize: + Max: 38 + +# Offense count: 8 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. +# AllowedMethods: refine +Metrics/BlockLength: + Max: 90 + +# Offense count: 3 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/CyclomaticComplexity: + Max: 18 + +# Offense count: 2 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/PerceivedComplexity: + Max: 19 + +# Offense count: 2 +# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns. +# SupportedStyles: snake_case, normalcase, non_integer +# AllowedIdentifiers: TLS1_1, TLS1_2, capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64 +Naming/VariableNumber: + Exclude: + - "spec/lib/grape_logging/formatters/rails_spec.rb" + +# Offense count: 3 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: MinBranchesCount. +Style/CaseLikeIf: + Exclude: + - "lib/grape_logging/formatters/default.rb" + - "lib/grape_logging/formatters/logstash.rb" + - "lib/grape_logging/formatters/rails.rb" + +# Offense count: 17 +# Configuration parameters: AllowedConstants. +Style/Documentation: + Enabled: false + +# Offense count: 29 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, always_true, never +Style/FrozenStringLiteralComment: + Enabled: false + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/GlobalStdStream: + Exclude: + - "lib/grape_logging/reporters/logger_reporter.rb" + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: literals, strict +Style/MutableConstant: + Exclude: + - "lib/grape_logging/version.rb" + +# Offense count: 10 +Style/OpenStructUse: + Exclude: + - "spec/lib/grape_logging/loggers/client_env_spec.rb" + - "spec/lib/grape_logging/loggers/filter_parameters_spec.rb" + - "spec/lib/grape_logging/loggers/request_headers_spec.rb" + - "spec/lib/grape_logging/loggers/response_spec.rb" + +# Offense count: 3 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. +# AllowedMethods: present?, blank?, presence, try, try! +Style/SafeNavigation: + Exclude: + - "lib/grape_logging/formatters/rails.rb" + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/SlicingWithRange: + Exclude: + - "lib/grape_logging/loggers/request_headers.rb" + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: RequireEnglish, EnforcedStyle. +# SupportedStyles: use_perl_names, use_english_names, use_builtin_english_names +Style/SpecialGlobalVars: + Exclude: + - "spec/spec_helper.rb" + +# Offense count: 3 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: Mode. +Style/StringConcatenation: + Exclude: + - "lib/grape_logging/formatters/json.rb" + - "lib/grape_logging/formatters/lograge.rb" + - "lib/grape_logging/formatters/logstash.rb" + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. +# AllowedMethods: define_method +Style/SymbolProc: + Exclude: + - "lib/grape_logging/util/parameter_filter.rb" + +# Offense count: 11 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings. +# URISchemes: http, https +Layout/LineLength: + Max: 203 diff --git a/Rakefile b/Rakefile index 2efaf1b..e4ebf39 100644 --- a/Rakefile +++ b/Rakefile @@ -1,9 +1,17 @@ require 'bundler/gem_tasks' require 'rspec/core/rake_task' +require 'rubocop/rake_task' -RSpec::Core::RakeTask.new(:spec) +RSpec::Core::RakeTask.new(:spec) do |spec| + spec.rspec_opts = ['-fd -c'] + spec.pattern = FileList['spec/**/*_spec.rb'] +end + +RuboCop::RakeTask.new(:rubocop) do |t| + t.patterns = ['lib/**/*.rb', 'spec/**/*.rb', 'Rakefile', 'Gemfile', 'grape_logging.gemspec'] +end -task default: :spec +task default: %i[spec rubocop] desc 'Release gem and create GitHub release' task github_release: :release do @@ -14,9 +22,9 @@ task github_release: :release do # Check if gh CLI is available unless system('which gh > /dev/null 2>&1') puts "\n⚠️ GitHub CLI (gh) not found" - puts "To create a GitHub release with auto-generated changelog, install gh:" - puts " brew install gh # macOS with Homebrew" - puts " # or visit: https://github.com/cli/cli#installation" + puts 'To create a GitHub release with auto-generated changelog, install gh:' + puts ' brew install gh # macOS with Homebrew' + puts ' # or visit: https://github.com/cli/cli#installation' puts "\nYou can manually create the release with:" puts " gh release create v#{GrapeLogging::VERSION} --generate-notes" next @@ -28,8 +36,8 @@ task github_release: :release do if system('gh', 'release', 'create', version, '--generate-notes', '--verify-tag') puts "✅ GitHub release #{version} created successfully" else - puts "❌ Failed to create GitHub release" - puts "You can manually create it with:" + puts '❌ Failed to create GitHub release' + puts 'You can manually create it with:' puts " gh release create '#{version}' --generate-notes --verify-tag" end end diff --git a/grape_logging.gemspec b/grape_logging.gemspec index c9a2c24..636aaa2 100644 --- a/grape_logging.gemspec +++ b/grape_logging.gemspec @@ -1,4 +1,4 @@ -lib = File.expand_path('../lib', __FILE__) +lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'grape_logging/version' @@ -16,7 +16,7 @@ Gem::Specification.new do |spec| spec.license = 'MIT' spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - spec.bindir = "exe" + spec.bindir = 'exe' spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ['lib'] @@ -25,4 +25,8 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'rake', '~> 13.3' spec.add_development_dependency 'rspec', '~> 3.5' + + # This is pinned to an exact version otherwise we can't know which rules + # are in play at any given time in different environments. + spec.add_development_dependency 'rubocop', '1.77.0' end diff --git a/lib/grape_logging/formatters/default.rb b/lib/grape_logging/formatters/default.rb index 54c1344..7b2d16a 100644 --- a/lib/grape_logging/formatters/default.rb +++ b/lib/grape_logging/formatters/default.rb @@ -18,6 +18,7 @@ def format(data) end private + def format_hash(hash) hash.keys.sort.map { |key| "#{key}=#{hash[key]}" }.join(' ') end diff --git a/lib/grape_logging/formatters/logstash.rb b/lib/grape_logging/formatters/logstash.rb index 51192a2..7bc093f 100644 --- a/lib/grape_logging/formatters/logstash.rb +++ b/lib/grape_logging/formatters/logstash.rb @@ -3,9 +3,9 @@ module Formatters class Logstash def call(severity, datetime, _, data) { - :'@timestamp' => datetime.iso8601, - :'@version' => '1', - :severity => severity + '@timestamp': datetime.iso8601, + '@version': '1', + severity: severity }.merge!(format(data)).to_json + "\n" end diff --git a/lib/grape_logging/formatters/rails.rb b/lib/grape_logging/formatters/rails.rb index 1451862..fdcaab8 100644 --- a/lib/grape_logging/formatters/rails.rb +++ b/lib/grape_logging/formatters/rails.rb @@ -3,7 +3,6 @@ module GrapeLogging module Formatters class Rails - def call(severity, datetime, _, data) if data.is_a?(String) "#{severity[0..0]} [#{datetime}] #{severity} -- : #{data}\n" @@ -24,7 +23,7 @@ def format_exception(exception) [ "#{exception.message} (#{exception.class})", backtrace_array.join("\n") - ].reject{|line| line == ""}.join("\n") + ].reject { |line| line == '' }.join("\n") end def format_hash(hash) @@ -32,7 +31,7 @@ def format_hash(hash) # Completed 200 OK in 958ms (Views: 951.1ms | ActiveRecord: 3.8ms) # See: actionpack/lib/action_controller/log_subscriber.rb - message = "" + message = '' additions = [] status = hash.delete(:status) params = hash.delete(:params) @@ -47,13 +46,12 @@ def format_hash(hash) message << " Parameters: #{params.inspect}\n" if params message << "Completed #{status} #{::Rack::Utils::HTTP_STATUS_CODES[status]} in #{total_time}ms" - message << " (#{additions.join(" | ".freeze)})" if additions.size > 0 + message << " (#{additions.join(' | '.freeze)})" unless additions.empty? message << "\n" message << "\n" if defined?(::Rails.env) && ::Rails.env.development? message end - end end end diff --git a/lib/grape_logging/loggers/base.rb b/lib/grape_logging/loggers/base.rb index d2e9e11..046b9a3 100644 --- a/lib/grape_logging/loggers/base.rb +++ b/lib/grape_logging/loggers/base.rb @@ -1,7 +1,7 @@ module GrapeLogging module Loggers class Base - def parameters(request, response) + def parameters(_request, _response) {} end end diff --git a/lib/grape_logging/loggers/client_env.rb b/lib/grape_logging/loggers/client_env.rb index b8cd027..9d84dd8 100644 --- a/lib/grape_logging/loggers/client_env.rb +++ b/lib/grape_logging/loggers/client_env.rb @@ -2,7 +2,7 @@ module GrapeLogging module Loggers class ClientEnv < GrapeLogging::Loggers::Base def parameters(request, _) - { ip: request.env["HTTP_X_FORWARDED_FOR"] || request.env["REMOTE_ADDR"], ua: request.env["HTTP_USER_AGENT"] } + { ip: request.env['HTTP_X_FORWARDED_FOR'] || request.env['REMOTE_ADDR'], ua: request.env['HTTP_USER_AGENT'] } end end end diff --git a/lib/grape_logging/loggers/filter_parameters.rb b/lib/grape_logging/loggers/filter_parameters.rb index 3a7534a..a169d18 100644 --- a/lib/grape_logging/loggers/filter_parameters.rb +++ b/lib/grape_logging/loggers/filter_parameters.rb @@ -3,7 +3,7 @@ module Loggers class FilterParameters < GrapeLogging::Loggers::Base AD_PARAMS = 'action_dispatch.request.parameters'.freeze - def initialize(filter_parameters = nil, replacement = nil, exceptions = %w(controller action format)) + def initialize(filter_parameters = nil, replacement = nil, exceptions = %w[controller action format]) @filter_parameters = filter_parameters || (defined?(::Rails.application) ? ::Rails.application.config.filter_parameters : []) @replacement = replacement || '[FILTERED]' @exceptions = exceptions @@ -30,8 +30,8 @@ def safe_parameters(request) def clean_parameters(parameters) original_encoding_map = build_encoding_map(parameters) - params = transform_key_encoding(parameters, Hash.new{ |h, _| [Encoding::ASCII_8BIT, h] }) - cleaned_params = parameter_filter.filter(params).reject{ |key, _value| @exceptions.include?(key) } + params = transform_key_encoding(parameters, Hash.new { |h, _| [Encoding::ASCII_8BIT, h] }) + cleaned_params = parameter_filter.filter(params).reject { |key, _value| @exceptions.include?(key) } transform_key_encoding(cleaned_params, original_encoding_map) end diff --git a/lib/grape_logging/loggers/request_headers.rb b/lib/grape_logging/loggers/request_headers.rb index 40c86d4..1d6a637 100644 --- a/lib/grape_logging/loggers/request_headers.rb +++ b/lib/grape_logging/loggers/request_headers.rb @@ -1,7 +1,6 @@ module GrapeLogging module Loggers class RequestHeaders < GrapeLogging::Loggers::Base - HTTP_PREFIX = 'HTTP_'.freeze def parameters(request, _) @@ -16,7 +15,6 @@ def parameters(request, _) { headers: headers } end - end end end diff --git a/lib/grape_logging/loggers/response.rb b/lib/grape_logging/loggers/response.rb index 8b76d12..9bff5f3 100644 --- a/lib/grape_logging/loggers/response.rb +++ b/lib/grape_logging/loggers/response.rb @@ -11,12 +11,11 @@ def parameters(_, response) # For example, if you POST on a PUT endpoint, response.body is egal to """". # It's strange, but it's the Grape behavior... def serialized_response_body(response) - if response.respond_to?(:body) # Rack responses begin - response.body.map{ |body| JSON.parse(body.to_s) } - rescue # No reason to have "=> e" here when we don't use it.. + response.body.map { |body| JSON.parse(body.to_s) } + rescue StandardError # No reason to have "=> e" here when we don't use it.. response.body end else diff --git a/lib/grape_logging/middleware/request_logger.rb b/lib/grape_logging/middleware/request_logger.rb index 22dc678..c9e22ed 100644 --- a/lib/grape_logging/middleware/request_logger.rb +++ b/lib/grape_logging/middleware/request_logger.rb @@ -3,11 +3,12 @@ module GrapeLogging module Middleware class RequestLogger < Grape::Middleware::Base - - ActiveSupport::Notifications.subscribe('sql.active_record') do |*args| - event = ActiveSupport::Notifications::Event.new(*args) - GrapeLogging::Timings.append_db_runtime(event) - end if defined?(ActiveRecord) + if defined?(ActiveRecord) + ActiveSupport::Notifications.subscribe('sql.active_record') do |*args| + event = ActiveSupport::Notifications::Event.new(*args) + GrapeLogging::Timings.append_db_runtime(event) + end + end # Persist response status & response (body) # to use int in parameters @@ -17,11 +18,12 @@ def initialize(app, options = {}) super @included_loggers = @options[:include] || [] - @reporter = if options[:instrumentation_key] - Reporters::ActiveSupportReporter.new(@options[:instrumentation_key]) - else - Reporters::LoggerReporter.new(@options[:logger], @options[:formatter], @options[:log_level]) - end + @reporter = + if options[:instrumentation_key] + Reporters::ActiveSupportReporter.new(@options[:instrumentation_key]) + else + Reporters::LoggerReporter.new(@options[:logger], @options[:formatter], @options[:log_level]) + end end def before @@ -99,7 +101,7 @@ def parameters path: request.path, params: request.params, host: request.host, - request_id: env['action_dispatch.request_id'], + request_id: env['action_dispatch.request_id'] } end diff --git a/lib/grape_logging/multi_io.rb b/lib/grape_logging/multi_io.rb index 5c70c48..2ace6c5 100644 --- a/lib/grape_logging/multi_io.rb +++ b/lib/grape_logging/multi_io.rb @@ -5,11 +5,11 @@ def initialize(*targets) end def write(*args) - @targets.each {|t| t.write(*args)} + @targets.each { |t| t.write(*args) } end def close @targets.each(&:close) end end -end \ No newline at end of file +end diff --git a/lib/grape_logging/reporters/active_support_reporter.rb b/lib/grape_logging/reporters/active_support_reporter.rb index 392f9ae..e48ce3e 100644 --- a/lib/grape_logging/reporters/active_support_reporter.rb +++ b/lib/grape_logging/reporters/active_support_reporter.rb @@ -8,4 +8,4 @@ def perform(params) ActiveSupport::Notifications.instrument @instrumentation_key, params end end -end \ No newline at end of file +end diff --git a/lib/grape_logging/reporters/logger_reporter.rb b/lib/grape_logging/reporters/logger_reporter.rb index 750d94b..422aa92 100644 --- a/lib/grape_logging/reporters/logger_reporter.rb +++ b/lib/grape_logging/reporters/logger_reporter.rb @@ -3,9 +3,7 @@ class LoggerReporter def initialize(logger, formatter, log_level) @logger = logger.clone || Logger.new(STDOUT) @log_level = log_level || :info - if @logger.respond_to?(:formatter=) - @logger.formatter = formatter || @logger.formatter || GrapeLogging::Formatters::Default.new - end + @logger.formatter = formatter || @logger.formatter || GrapeLogging::Formatters::Default.new if @logger.respond_to?(:formatter=) end def perform(params) diff --git a/lib/grape_logging/timings.rb b/lib/grape_logging/timings.rb index 9c1e417..85ddcb0 100644 --- a/lib/grape_logging/timings.rb +++ b/lib/grape_logging/timings.rb @@ -1,21 +1,19 @@ module GrapeLogging module Timings - extend self - - def db_runtime=(value) + def self.db_runtime=(value) Thread.current[:grape_db_runtime] = value end - def db_runtime + def self.db_runtime Thread.current[:grape_db_runtime] ||= 0 end - def reset_db_runtime + def self.reset_db_runtime self.db_runtime = 0 end - def append_db_runtime(event) + def self.append_db_runtime(event) self.db_runtime += event.duration end end -end \ No newline at end of file +end diff --git a/lib/grape_logging/util/parameter_filter.rb b/lib/grape_logging/util/parameter_filter.rb index 1b04fb9..9d009ee 100644 --- a/lib/grape_logging/util/parameter_filter.rb +++ b/lib/grape_logging/util/parameter_filter.rb @@ -1,4 +1,4 @@ -if defined?(::Rails.application) +if defined?(Rails.application) if Gem::Version.new(Rails.version) < Gem::Version.new('6.0.0') class ParameterFilter < ActionDispatch::Http::ParameterFilter def initialize(_replacement, filter_parameters) @@ -6,7 +6,7 @@ def initialize(_replacement, filter_parameters) end end else - require "active_support/parameter_filter" + require 'active_support/parameter_filter' class ParameterFilter < ActiveSupport::ParameterFilter def initialize(_replacement, filter_parameters) @@ -37,9 +37,11 @@ def compiled_filter class CompiledFilter # :nodoc: def self.compile(replacement, filters) - return lambda { |params| params.dup } if filters.empty? + return ->(params) { params.dup } if filters.empty? - strings, regexps, blocks = [], [], [] + strings = [] + regexps = [] + blocks = [] filters.each do |item| case item @@ -52,8 +54,8 @@ def self.compile(replacement, filters) end end - deep_regexps, regexps = regexps.partition { |r| r.to_s.include?("\\.".freeze) } - deep_strings, strings = strings.partition { |s| s.include?("\\.".freeze) } + deep_regexps, regexps = regexps.partition { |r| r.to_s.include?('\\.'.freeze) } + deep_strings, strings = strings.partition { |s| s.include?('\\.'.freeze) } regexps << Regexp.new(strings.join('|'.freeze), true) unless strings.empty? deep_regexps << Regexp.new(deep_strings.join('|'.freeze), true) unless deep_strings.empty? @@ -67,7 +69,7 @@ def initialize(replacement, regexps, deep_regexps, blocks) @replacement = replacement @regexps = regexps @deep_regexps = deep_regexps.any? ? deep_regexps : nil - @blocks = blocks + @blocks = blocks end def call(original_params, parents = []) diff --git a/spec/lib/grape_logging/formatters/rails_spec.rb b/spec/lib/grape_logging/formatters/rails_spec.rb index 03416fe..a44bdf5 100644 --- a/spec/lib/grape_logging/formatters/rails_spec.rb +++ b/spec/lib/grape_logging/formatters/rails_spec.rb @@ -2,11 +2,11 @@ describe GrapeLogging::Formatters::Rails do let(:formatter) { described_class.new } - let(:severity) { "INFO" } + let(:severity) { 'INFO' } let(:datetime) { Time.new('2018', '03', '02', '10', '35', '04', '+13:00') } let(:exception_data) { ArgumentError.new('Message') } - let(:hash_data) { + let(:hash_data) do { status: 200, time: { @@ -14,11 +14,11 @@ db: 40.63, view: 231.76999999999998 }, - method: "GET", - path: "/api/endpoint", - host: "localhost" + method: 'GET', + path: '/api/endpoint', + host: 'localhost' } - } + end describe '#call' do context 'string data' do @@ -36,7 +36,7 @@ message = formatter.call(severity, datetime, nil, exception_data) lines = message.split("\n") - expect(lines[0]).to eq "I [2018-03-02 10:35:04 +1300] INFO -- : Message (ArgumentError)" + expect(lines[0]).to eq 'I [2018-03-02 10:35:04 +1300] INFO -- : Message (ArgumentError)' expect(lines[1]).to include '.rb' expect(lines.size).to be > 1 end @@ -52,9 +52,9 @@ it 'includes params if included (from GrapeLogging::Loggers::FilterParameters)' do hash_data.merge!( params: { - "some_param" => { - value_1: "123", - value_2: "456" + 'some_param' => { + value_1: '123', + value_2: '456' } } ) @@ -62,17 +62,18 @@ message = formatter.call(severity, datetime, nil, hash_data) lines = message.split("\n") - expected_output = if RUBY_VERSION >= '3.4' - ' Parameters: {"some_param" => {value_1: "123", value_2: "456"}}' - else - ' Parameters: {"some_param"=>{:value_1=>"123", :value_2=>"456"}}' - end + expected_output = + if RUBY_VERSION >= '3.4' + ' Parameters: {"some_param" => {value_1: "123", value_2: "456"}}' + else + ' Parameters: {"some_param"=>{:value_1=>"123", :value_2=>"456"}}' + end expect(lines.first).to eq expected_output - expect(lines.last).to eq "Completed 200 OK in 272.4ms (Views: 231.77ms | DB: 40.63ms)" + expect(lines.last).to eq 'Completed 200 OK in 272.4ms (Views: 231.77ms | DB: 40.63ms)' end end - context "unhandled data" do + context 'unhandled data' do it 'returns the #inspect string representation' do message = formatter.call(severity, datetime, nil, [1, 2, 3]) @@ -80,5 +81,4 @@ end end end - end diff --git a/spec/lib/grape_logging/loggers/client_env_spec.rb b/spec/lib/grape_logging/loggers/client_env_spec.rb index f163fe8..3d490fa 100644 --- a/spec/lib/grape_logging/loggers/client_env_spec.rb +++ b/spec/lib/grape_logging/loggers/client_env_spec.rb @@ -4,14 +4,14 @@ describe GrapeLogging::Loggers::ClientEnv do let(:ip) { '10.0.0.1' } let(:user_agent) { 'user agent' } - let(:forwarded_for) { "forwarded for" } - let(:remote_addr) { "remote address" } + let(:forwarded_for) { 'forwarded for' } + let(:remote_addr) { 'remote address' } context 'forwarded for' do let(:mock_request) do OpenStruct.new(env: { - "HTTP_X_FORWARDED_FOR" => forwarded_for - }) + 'HTTP_X_FORWARDED_FOR' => forwarded_for + }) end it 'sets the ip key' do @@ -27,8 +27,8 @@ context 'remote address' do let(:mock_request) do OpenStruct.new(env: { - "REMOTE_ADDR" => remote_addr - }) + 'REMOTE_ADDR' => remote_addr + }) end it 'sets the ip key' do @@ -39,8 +39,8 @@ context 'user agent' do let(:mock_request) do OpenStruct.new(env: { - "HTTP_USER_AGENT" => user_agent - }) + 'HTTP_USER_AGENT' => user_agent + }) end it 'sets the ua key' do diff --git a/spec/lib/grape_logging/loggers/filter_parameters_spec.rb b/spec/lib/grape_logging/loggers/filter_parameters_spec.rb index fb7ad45..5cc81a8 100644 --- a/spec/lib/grape_logging/loggers/filter_parameters_spec.rb +++ b/spec/lib/grape_logging/loggers/filter_parameters_spec.rb @@ -1,27 +1,26 @@ require 'spec_helper' require 'ostruct' - describe GrapeLogging::Loggers::FilterParameters do let(:filtered_parameters) { %w[one four] } let(:mock_request) do OpenStruct.new(params: { - 'this_one' => 'this one', - 'that_one' => 'one', - 'two' => 'two', - 'three' => 'three', - 'four' => 'four', - "\xff" => 'invalid utf8', - }) + 'this_one' => 'this one', + 'that_one' => 'one', + 'two' => 'two', + 'three' => 'three', + 'four' => 'four', + "\xff" => 'invalid utf8' + }) end let(:mock_request_with_deep_nesting) do - deep_clone = lambda { Marshal.load Marshal.dump mock_request.params } + deep_clone = -> { Marshal.load Marshal.dump mock_request.params } OpenStruct.new( params: deep_clone.call.merge( 'five' => deep_clone.call.merge( - deep_clone.call.merge({'six' => {'seven' => 'seven', 'eight' => 'eight', 'one' => 'another one'}}) + deep_clone.call.merge({ 'six' => { 'seven' => 'seven', 'eight' => 'eight', 'one' => 'another one' } }) ) ) ) @@ -36,37 +35,37 @@ shared_examples 'filtering' do it 'filters out sensitive parameters' do expect(subject.parameters(mock_request, nil)).to eq(params: { - 'this_one' => subject.instance_variable_get('@replacement'), - 'that_one' => subject.instance_variable_get('@replacement'), - 'two' => 'two', - 'three' => 'three', - 'four' => subject.instance_variable_get('@replacement'), - "\xff" => 'invalid utf8', - }) + 'this_one' => subject.instance_variable_get('@replacement'), + 'that_one' => subject.instance_variable_get('@replacement'), + 'two' => 'two', + 'three' => 'three', + 'four' => subject.instance_variable_get('@replacement'), + "\xff" => 'invalid utf8' + }) end it 'deeply filters out sensitive parameters' do expect(subject.parameters(mock_request_with_deep_nesting, nil)).to eq(params: { - 'this_one' => subject.instance_variable_get('@replacement'), - 'that_one' => subject.instance_variable_get('@replacement'), - 'two' => 'two', - 'three' => 'three', - 'four' => subject.instance_variable_get('@replacement'), - "\xff" => 'invalid utf8', - 'five' => { - 'this_one' => subject.instance_variable_get('@replacement'), - 'that_one' => subject.instance_variable_get('@replacement'), - 'two' => 'two', - 'three' => 'three', - 'four' => subject.instance_variable_get('@replacement'), - "\xff" => 'invalid utf8', - 'six' => { - 'seven' => 'seven', - 'eight' => 'eight', - 'one' => subject.instance_variable_get('@replacement'), - }, - }, - }) + 'this_one' => subject.instance_variable_get('@replacement'), + 'that_one' => subject.instance_variable_get('@replacement'), + 'two' => 'two', + 'three' => 'three', + 'four' => subject.instance_variable_get('@replacement'), + "\xff" => 'invalid utf8', + 'five' => { + 'this_one' => subject.instance_variable_get('@replacement'), + 'that_one' => subject.instance_variable_get('@replacement'), + 'two' => 'two', + 'three' => 'three', + 'four' => subject.instance_variable_get('@replacement'), + "\xff" => 'invalid utf8', + 'six' => { + 'seven' => 'seven', + 'eight' => 'eight', + 'one' => subject.instance_variable_get('@replacement') + } + } + }) end end @@ -84,8 +83,8 @@ it 'converts keys to strings' do expect(subject.parameters(mock_request, nil)).to eq(params: { - 'sneaky_symbol' => 'hey!', - }) + 'sneaky_symbol' => 'hey!' + }) end end end diff --git a/spec/lib/grape_logging/loggers/request_headers_spec.rb b/spec/lib/grape_logging/loggers/request_headers_spec.rb index 03dd5ca..f34e9b7 100644 --- a/spec/lib/grape_logging/loggers/request_headers_spec.rb +++ b/spec/lib/grape_logging/loggers/request_headers_spec.rb @@ -3,38 +3,44 @@ describe GrapeLogging::Loggers::RequestHeaders do let(:mock_request) do - OpenStruct.new(env: {HTTP_REFERER: 'http://example.com', HTTP_ACCEPT: 'text/plain'}) + OpenStruct.new(env: { HTTP_REFERER: 'http://example.com', HTTP_ACCEPT: 'text/plain' }) end let(:mock_request_with_unhandled_headers) do OpenStruct.new(env: { - HTTP_REFERER: 'http://example.com', - "PATH_INFO"=>"/api/v1/users" - }) + HTTP_REFERER: 'http://example.com', + 'PATH_INFO' => '/api/v1/users' + }) end let(:mock_request_with_long_headers) do OpenStruct.new(env: { - HTTP_REFERER: 'http://example.com', - HTTP_USER_AGENT: "Mozilla/5.0" - }) + HTTP_REFERER: 'http://example.com', + HTTP_USER_AGENT: 'Mozilla/5.0' + }) end it 'strips HTTP_ from the parameter' do - expect(subject.parameters(mock_request, nil)).to eq({ - headers: {'Referer' => 'http://example.com', 'Accept' => 'text/plain'} - }) + expect(subject.parameters(mock_request, nil)).to eq( + { + headers: { 'Referer' => 'http://example.com', 'Accept' => 'text/plain' } + } + ) end it 'only handle things which start with HTTP_' do - expect(subject.parameters(mock_request_with_unhandled_headers, nil)).to eq({ - headers: {'Referer' => 'http://example.com' } - }) + expect(subject.parameters(mock_request_with_unhandled_headers, nil)).to eq( + { + headers: { 'Referer' => 'http://example.com' } + } + ) end it 'substitutes _ with -' do - expect(subject.parameters(mock_request_with_long_headers, nil)).to eq({ - headers: {'Referer' => 'http://example.com', 'User-Agent' => 'Mozilla/5.0' } - }) + expect(subject.parameters(mock_request_with_long_headers, nil)).to eq( + { + headers: { 'Referer' => 'http://example.com', 'User-Agent' => 'Mozilla/5.0' } + } + ) end end diff --git a/spec/lib/grape_logging/loggers/response_spec.rb b/spec/lib/grape_logging/loggers/response_spec.rb index a8ff473..c446135 100644 --- a/spec/lib/grape_logging/loggers/response_spec.rb +++ b/spec/lib/grape_logging/loggers/response_spec.rb @@ -4,25 +4,21 @@ describe GrapeLogging::Loggers::Response do context 'with a parseable JSON body' do let(:response) do - OpenStruct.new(body: [{"one": "two", "three": {"four": 5}}]) + OpenStruct.new(body: [{ one: 'two', three: { four: 5 } }]) end it 'returns an array of parsed JSON objects' do - expect(subject.parameters(nil, response)).to eq({ - response: [response.body.first], - }) + expect(subject.parameters(nil, response)).to eq({ response: [response.body.first] }) end end context 'with a body that is not parseable JSON' do let(:response) do - OpenStruct.new(body: "this is a body") + OpenStruct.new(body: 'this is a body') end it 'just returns the body' do - expect(subject.parameters(nil, response)).to eq({ - response: response.body, - }) + expect(subject.parameters(nil, response)).to eq({ response: response.body }) end end end diff --git a/spec/lib/grape_logging/middleware/request_logger_spec.rb b/spec/lib/grape_logging/middleware/request_logger_spec.rb index 7d11fbd..fb03534 100644 --- a/spec/lib/grape_logging/middleware/request_logger_spec.rb +++ b/spec/lib/grape_logging/middleware/request_logger_spec.rb @@ -4,10 +4,10 @@ describe GrapeLogging::Middleware::RequestLogger do let(:env) { { 'action_dispatch.request_id' => 'request-abc123' } } let(:subject) { request.send(request_method, path, env) } - let(:app) { proc{ [status, {} , ['response body']] } } + let(:app) { proc { [status, {}, ['response body']] } } let(:stack) { described_class.new app, options } let(:request) { Rack::MockRequest.new(stack) } - let(:options) { {include: [], logger: logger} } + let(:options) { { include: [], logger: logger } } let(:logger) { double('logger') } let(:path) { '/' } let(:request_method) { 'get' } @@ -51,7 +51,7 @@ end context 'with a nil response' do - let(:app) { proc{ [500, {} , nil] } } + let(:app) { proc { [500, {}, nil] } } it 'should log "fail" instead of a status' do expect(Rack::MockResponse).to receive(:new) { nil } expect(logger).to receive('info') do |arguments| @@ -66,7 +66,7 @@ options[:include] << GrapeLogging::Loggers::RequestHeaders.new options[:include] << GrapeLogging::Loggers::ClientEnv.new options[:include] << GrapeLogging::Loggers::Response.new - options[:include] << GrapeLogging::Loggers::FilterParameters.new(["replace_me"]) + options[:include] << GrapeLogging::Loggers::FilterParameters.new(['replace_me']) end %w[get put post delete options head patch].each do |the_method| @@ -86,9 +86,9 @@ it 'should filter parameters in the log' do expect(logger).to receive('info') do |arguments| expect(arguments[:params]).to eq( - "replace_me" => '[FILTERED]', - "replace_me_too" => '[FILTERED]', - "cant_touch_this" => 'should see' + 'replace_me' => '[FILTERED]', + 'replace_me_too' => '[FILTERED]', + 'cant_touch_this' => 'should see' ) end parameters = { diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 59d065a..75f6252 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -33,57 +33,55 @@ # triggering implicit auto-inclusion in groups with matching metadata. config.shared_context_metadata_behavior = :apply_to_host_groups -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin - # This allows you to limit a spec run to individual examples or groups - # you care about by tagging them with `:focus` metadata. When nothing - # is tagged with `:focus`, all examples get run. RSpec also provides - # aliases for `it`, `describe`, and `context` that include `:focus` - # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - config.filter_run_when_matching :focus - - # Allows RSpec to persist some state between runs in order to support - # the `--only-failures` and `--next-failure` CLI options. We recommend - # you configure your source control system to ignore this file. - config.example_status_persistence_file_path = "spec/examples.txt" - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ - # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode - config.disable_monkey_patching! - - # This setting enables warnings. It's recommended, but in some cases may - # be too noisy due to issues in dependencies. - config.warnings = true - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = 'doc' - end - - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - config.profile_examples = 10 - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = :random - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -=end + # The settings below are suggested to provide a good initial experience + # with RSpec, but feel free to customize to your heart's content. + # # This allows you to limit a spec run to individual examples or groups + # # you care about by tagging them with `:focus` metadata. When nothing + # # is tagged with `:focus`, all examples get run. RSpec also provides + # # aliases for `it`, `describe`, and `context` that include `:focus` + # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + # config.filter_run_when_matching :focus + # + # # Allows RSpec to persist some state between runs in order to support + # # the `--only-failures` and `--next-failure` CLI options. We recommend + # # you configure your source control system to ignore this file. + # config.example_status_persistence_file_path = "spec/examples.txt" + # + # # Limits the available syntax to the non-monkey patched syntax that is + # # recommended. For more details, see: + # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + # config.disable_monkey_patching! + # + # # This setting enables warnings. It's recommended, but in some cases may + # # be too noisy due to issues in dependencies. + # config.warnings = true + # + # # Many RSpec users commonly either run the entire suite or an individual + # # file, and it's useful to allow more verbose output when running an + # # individual spec file. + # if config.files_to_run.one? + # # Use the documentation formatter for detailed output, + # # unless a formatter has already been configured + # # (e.g. via a command-line flag). + # config.default_formatter = 'doc' + # end + # + # # Print the 10 slowest examples and example groups at the + # # end of the spec run, to help surface which specs are running + # # particularly slow. + # config.profile_examples = 10 + # + # # Run specs in random order to surface order dependencies. If you find an + # # order dependency and want to debug it, you can fix the order by providing + # # the seed, which is printed after each run. + # # --seed 1234 + # config.order = :random + # + # # Seed global randomization in this process using the `--seed` CLI option. + # # Setting this allows you to use `--seed` to deterministically reproduce + # # test failures related to randomization by passing the same `--seed` value + # # as the one that triggered the failure. + # Kernel.srand config.seed end