loga 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +25 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +19 -0
  5. data/.rubocop_todo.yml +33 -0
  6. data/Appraisals +14 -0
  7. data/Gemfile +8 -0
  8. data/README.md +147 -0
  9. data/Rakefile +9 -0
  10. data/circle.yml +23 -0
  11. data/gemfiles/rails32.gemfile +11 -0
  12. data/gemfiles/rails40.gemfile +11 -0
  13. data/gemfiles/sinatra14.gemfile +11 -0
  14. data/gemfiles/unit.gemfile +9 -0
  15. data/lib/loga.rb +33 -0
  16. data/lib/loga/configuration.rb +96 -0
  17. data/lib/loga/event.rb +21 -0
  18. data/lib/loga/ext/rails/rack/logger3.rb +21 -0
  19. data/lib/loga/ext/rails/rack/logger4.rb +13 -0
  20. data/lib/loga/formatter.rb +104 -0
  21. data/lib/loga/parameter_filter.rb +65 -0
  22. data/lib/loga/rack/logger.rb +102 -0
  23. data/lib/loga/rack/request.rb +77 -0
  24. data/lib/loga/rack/request_id.rb +44 -0
  25. data/lib/loga/railtie.rb +139 -0
  26. data/lib/loga/tagged_logging.rb +76 -0
  27. data/lib/loga/utilities.rb +7 -0
  28. data/lib/loga/version.rb +3 -0
  29. data/loga.gemspec +31 -0
  30. data/spec/fixtures/README.md +8 -0
  31. data/spec/fixtures/rails32/Rakefile +7 -0
  32. data/spec/fixtures/rails32/app/controllers/application_controller.rb +28 -0
  33. data/spec/fixtures/rails32/app/helpers/application_helper.rb +2 -0
  34. data/spec/fixtures/rails32/app/views/layouts/application.html.erb +14 -0
  35. data/spec/fixtures/rails32/app/views/user.html.erb +1 -0
  36. data/spec/fixtures/rails32/config.ru +4 -0
  37. data/spec/fixtures/rails32/config/application.rb +71 -0
  38. data/spec/fixtures/rails32/config/boot.rb +6 -0
  39. data/spec/fixtures/rails32/config/environment.rb +5 -0
  40. data/spec/fixtures/rails32/config/environments/development.rb +26 -0
  41. data/spec/fixtures/rails32/config/environments/production.rb +50 -0
  42. data/spec/fixtures/rails32/config/environments/test.rb +35 -0
  43. data/spec/fixtures/rails32/config/initializers/backtrace_silencers.rb +7 -0
  44. data/spec/fixtures/rails32/config/initializers/inflections.rb +15 -0
  45. data/spec/fixtures/rails32/config/initializers/mime_types.rb +5 -0
  46. data/spec/fixtures/rails32/config/initializers/secret_token.rb +7 -0
  47. data/spec/fixtures/rails32/config/initializers/session_store.rb +8 -0
  48. data/spec/fixtures/rails32/config/initializers/wrap_parameters.rb +10 -0
  49. data/spec/fixtures/rails32/config/locales/en.yml +5 -0
  50. data/spec/fixtures/rails32/config/routes.rb +64 -0
  51. data/spec/fixtures/rails32/public/404.html +26 -0
  52. data/spec/fixtures/rails32/public/422.html +26 -0
  53. data/spec/fixtures/rails32/public/500.html +25 -0
  54. data/spec/fixtures/rails32/public/favicon.ico +0 -0
  55. data/spec/fixtures/rails32/public/index.html +241 -0
  56. data/spec/fixtures/rails32/public/robots.txt +5 -0
  57. data/spec/fixtures/rails32/script/rails +6 -0
  58. data/spec/fixtures/rails40/Rakefile +6 -0
  59. data/spec/fixtures/rails40/app/controllers/application_controller.rb +30 -0
  60. data/spec/fixtures/rails40/app/helpers/application_helper.rb +2 -0
  61. data/spec/fixtures/rails40/app/views/layouts/application.html.erb +14 -0
  62. data/spec/fixtures/rails40/app/views/user.html.erb +1 -0
  63. data/spec/fixtures/rails40/bin/bundle +3 -0
  64. data/spec/fixtures/rails40/bin/rails +4 -0
  65. data/spec/fixtures/rails40/bin/rake +4 -0
  66. data/spec/fixtures/rails40/config.ru +4 -0
  67. data/spec/fixtures/rails40/config/application.rb +37 -0
  68. data/spec/fixtures/rails40/config/boot.rb +4 -0
  69. data/spec/fixtures/rails40/config/environment.rb +5 -0
  70. data/spec/fixtures/rails40/config/environments/development.rb +24 -0
  71. data/spec/fixtures/rails40/config/environments/production.rb +65 -0
  72. data/spec/fixtures/rails40/config/environments/test.rb +39 -0
  73. data/spec/fixtures/rails40/config/initializers/backtrace_silencers.rb +7 -0
  74. data/spec/fixtures/rails40/config/initializers/filter_parameter_logging.rb +4 -0
  75. data/spec/fixtures/rails40/config/initializers/inflections.rb +16 -0
  76. data/spec/fixtures/rails40/config/initializers/mime_types.rb +5 -0
  77. data/spec/fixtures/rails40/config/initializers/secret_token.rb +12 -0
  78. data/spec/fixtures/rails40/config/initializers/session_store.rb +3 -0
  79. data/spec/fixtures/rails40/config/initializers/wrap_parameters.rb +9 -0
  80. data/spec/fixtures/rails40/config/locales/en.yml +23 -0
  81. data/spec/fixtures/rails40/config/routes.rb +62 -0
  82. data/spec/fixtures/rails40/public/404.html +58 -0
  83. data/spec/fixtures/rails40/public/422.html +58 -0
  84. data/spec/fixtures/rails40/public/500.html +57 -0
  85. data/spec/fixtures/rails40/public/favicon.ico +0 -0
  86. data/spec/fixtures/rails40/public/robots.txt +5 -0
  87. data/spec/integration/rails/railtie_spec.rb +64 -0
  88. data/spec/integration/rails/request_spec.rb +42 -0
  89. data/spec/integration/sinatra_spec.rb +54 -0
  90. data/spec/spec_helper.rb +39 -0
  91. data/spec/support/helpers.rb +16 -0
  92. data/spec/support/request_spec.rb +183 -0
  93. data/spec/support/timecop_shared.rb +7 -0
  94. data/spec/unit/loga/configuration_spec.rb +123 -0
  95. data/spec/unit/loga/event_spec.rb +20 -0
  96. data/spec/unit/loga/formatter_spec.rb +186 -0
  97. data/spec/unit/loga/parameter_filter_spec.rb +76 -0
  98. data/spec/unit/loga/rack/logger_spec.rb +114 -0
  99. data/spec/unit/loga/rack/request_spec.rb +70 -0
  100. data/spec/unit/loga/utilities_spec.rb +16 -0
  101. data/spec/unit/loga_spec.rb +41 -0
  102. metadata +357 -0
@@ -0,0 +1,58 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style>
6
+ body {
7
+ background-color: #EFEFEF;
8
+ color: #2E2F30;
9
+ text-align: center;
10
+ font-family: arial, sans-serif;
11
+ }
12
+
13
+ div.dialog {
14
+ width: 25em;
15
+ margin: 4em auto 0 auto;
16
+ border: 1px solid #CCC;
17
+ border-right-color: #999;
18
+ border-left-color: #999;
19
+ border-bottom-color: #BBB;
20
+ border-top: #B00100 solid 4px;
21
+ border-top-left-radius: 9px;
22
+ border-top-right-radius: 9px;
23
+ background-color: white;
24
+ padding: 7px 4em 0 4em;
25
+ }
26
+
27
+ h1 {
28
+ font-size: 100%;
29
+ color: #730E15;
30
+ line-height: 1.5em;
31
+ }
32
+
33
+ body > p {
34
+ width: 33em;
35
+ margin: 0 auto 1em;
36
+ padding: 1em 0;
37
+ background-color: #F7F7F7;
38
+ border: 1px solid #CCC;
39
+ border-right-color: #999;
40
+ border-bottom-color: #999;
41
+ border-bottom-left-radius: 4px;
42
+ border-bottom-right-radius: 4px;
43
+ border-top-color: #DADADA;
44
+ color: #666;
45
+ box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
46
+ }
47
+ </style>
48
+ </head>
49
+
50
+ <body>
51
+ <!-- This file lives in public/422.html -->
52
+ <div class="dialog">
53
+ <h1>The change you wanted was rejected.</h1>
54
+ <p>Maybe you tried to change something you didn't have access to.</p>
55
+ </div>
56
+ <p>If you are the application owner check the logs for more information.</p>
57
+ </body>
58
+ </html>
@@ -0,0 +1,57 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style>
6
+ body {
7
+ background-color: #EFEFEF;
8
+ color: #2E2F30;
9
+ text-align: center;
10
+ font-family: arial, sans-serif;
11
+ }
12
+
13
+ div.dialog {
14
+ width: 25em;
15
+ margin: 4em auto 0 auto;
16
+ border: 1px solid #CCC;
17
+ border-right-color: #999;
18
+ border-left-color: #999;
19
+ border-bottom-color: #BBB;
20
+ border-top: #B00100 solid 4px;
21
+ border-top-left-radius: 9px;
22
+ border-top-right-radius: 9px;
23
+ background-color: white;
24
+ padding: 7px 4em 0 4em;
25
+ }
26
+
27
+ h1 {
28
+ font-size: 100%;
29
+ color: #730E15;
30
+ line-height: 1.5em;
31
+ }
32
+
33
+ body > p {
34
+ width: 33em;
35
+ margin: 0 auto 1em;
36
+ padding: 1em 0;
37
+ background-color: #F7F7F7;
38
+ border: 1px solid #CCC;
39
+ border-right-color: #999;
40
+ border-bottom-color: #999;
41
+ border-bottom-left-radius: 4px;
42
+ border-bottom-right-radius: 4px;
43
+ border-top-color: #DADADA;
44
+ color: #666;
45
+ box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
46
+ }
47
+ </style>
48
+ </head>
49
+
50
+ <body>
51
+ <!-- This file lives in public/500.html -->
52
+ <div class="dialog">
53
+ <h1>We're sorry, but something went wrong.</h1>
54
+ </div>
55
+ <p>If you are the application owner check the logs for more information.</p>
56
+ </body>
57
+ </html>
@@ -0,0 +1,5 @@
1
+ # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2
+ #
3
+ # To ban all spiders from the entire site uncomment the next two lines:
4
+ # User-agent: *
5
+ # Disallow: /
@@ -0,0 +1,64 @@
1
+ require 'ostruct'
2
+
3
+ RSpec.describe Loga::Railtie do
4
+ let(:app) { Rails.application }
5
+ let(:middlewares) { app.middleware.middlewares }
6
+ let(:initializers) { described_class.initializers }
7
+
8
+ describe 'loga_initialize_logger' do
9
+ let(:initializer) { initializers.find { |i| i.name == :loga_initialize_logger } }
10
+
11
+ let(:app) { OpenStruct.new(config: config) }
12
+ let(:config) { OpenStruct.new(loga: loga, log_level: :info) }
13
+
14
+ before { initializer.run(app) }
15
+
16
+ context 'when loga is disabled' do
17
+ let(:loga) { Loga::Configuration.new.tap { |c| c.enabled = false } }
18
+
19
+ it 'is not initialized' do
20
+ expect(config.logger).to be_nil
21
+ end
22
+ end
23
+
24
+ context 'when loga is enabled' do
25
+ let(:loga) { Loga::Configuration.new }
26
+
27
+ it 'initializes the logger' do
28
+ expect(config.logger).to be_a(Logger)
29
+ end
30
+ end
31
+ end
32
+
33
+ it 'inserts Loga::Rack::Logger middleware after Rails::Rack::Logger' do
34
+ expect(middlewares.index(Loga::Rack::Logger))
35
+ .to eq(middlewares.index(Rails::Rack::Logger) + 1)
36
+ end
37
+
38
+ it 'disables colorized logging' do
39
+ expect(app.config.colorize_logging).to eq(false)
40
+ end
41
+
42
+ describe 'instrumentation' do
43
+ let(:listeners) do
44
+ ActiveSupport::Notifications.notifier.listeners_for(notification)
45
+ end
46
+ let(:subscribers) do
47
+ listeners.map { |l| l.instance_variable_get(:@delegate).class }
48
+ end
49
+
50
+ context 'ActionView' do
51
+ [
52
+ 'render_collection.action_view',
53
+ 'render_partial.action_view',
54
+ 'render_template.action_view',
55
+ ].each do |notification|
56
+ let(:notification) { notification }
57
+
58
+ it 'removes ActionView::LogSubscriber' do
59
+ expect(subscribers).to_not include(ActionView::LogSubscriber)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Integration with Rails', timecop: true do
4
+ let(:app) { Rails.application }
5
+
6
+ let(:json_entries) do
7
+ [].tap do |entries|
8
+ STREAM.tap do |s|
9
+ s.rewind
10
+ s.read.split("\n").each do |line|
11
+ entries << JSON.parse(line)
12
+ end
13
+ s.close
14
+ s.reopen
15
+ end
16
+ end
17
+ end
18
+
19
+ let(:json) { json_entries.last }
20
+ let(:json_response) { JSON.parse(last_response.body) }
21
+
22
+ include_examples 'request logger'
23
+
24
+ it 'preserves rails parameters' do
25
+ get '/show'
26
+ expect(json_response).to eq('action' => 'show', 'controller' => 'application')
27
+ end
28
+
29
+ context 'when a template is rendered' do
30
+ let(:action_view_notifications) do
31
+ json_entries.select { |e| e.to_json =~ /Rendered/ }
32
+ end
33
+
34
+ before { put '/users/5' }
35
+
36
+ specify { expect(last_response.status).to eq(200) }
37
+
38
+ it 'silences ActionView::LogSubscriber' do
39
+ expect(action_view_notifications).to be_empty
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Rack request logger with Sinatra', timecop: true do
4
+ let(:io) { StringIO.new }
5
+ before do
6
+ Loga.reset
7
+ Loga.configure do |config|
8
+ config.service_name = 'hello_world_app'
9
+ config.service_version = '1.0'
10
+ config.filter_parameters = [:password]
11
+ config.device = io
12
+ end
13
+ Loga.initialize!
14
+ end
15
+ let(:json) do
16
+ io.rewind
17
+ JSON.parse(io.read)
18
+ end
19
+
20
+ let(:app) do
21
+ Class.new(Sinatra::Base) do
22
+ # Disable show_exceptions and rely on user defined exception handlers
23
+ # (e.i. the error blocks)
24
+ set :show_exceptions, false
25
+
26
+ use Loga::Rack::RequestId
27
+ use Loga::Rack::Logger, Loga.logger, [:uuid]
28
+
29
+ error do
30
+ status 500
31
+ body 'Ooops'
32
+ end
33
+
34
+ get '/ok' do
35
+ 'Hello Sinatra'
36
+ end
37
+
38
+ get '/error' do
39
+ nil.name
40
+ end
41
+
42
+ post '/users' do
43
+ content_type :json
44
+ params.to_json
45
+ end
46
+
47
+ get '/new' do
48
+ redirect '/ok'
49
+ end
50
+ end
51
+ end
52
+
53
+ include_examples 'request logger'
54
+ end
@@ -0,0 +1,39 @@
1
+ require 'codeclimate-test-reporter'
2
+ require 'pry'
3
+ require 'support/helpers'
4
+ require 'support/timecop_shared'
5
+ require 'support/request_spec'
6
+ require 'rack/test'
7
+
8
+ CodeClimate::TestReporter.start if ENV.fetch('CODECLIMATE_REPO_TOKEN', nil)
9
+
10
+ class Socket
11
+ def self.gethostname
12
+ 'bird.example.com'
13
+ end
14
+ end
15
+
16
+ case ENV['BUNDLE_GEMFILE']
17
+ when /rails/
18
+ rspec_pattern = 'integration/rails/**/*_spec.rb'
19
+ /(?<appraisal>rails\d{2})\.gemfile/ =~ ENV['BUNDLE_GEMFILE']
20
+ require 'rails'
21
+ require File.expand_path("../fixtures/#{appraisal}/config/environment.rb", __FILE__)
22
+ when /sinatra/
23
+ rspec_pattern = 'integration/sinatra_spec.rb'
24
+ require 'json'
25
+ require 'sinatra'
26
+ require 'loga'
27
+ when /unit/
28
+ rspec_pattern = 'unit/**/*_spec.rb'
29
+ require 'loga'
30
+ else
31
+ fail 'BUNDLE_GEMFILE is unknown. Ensure the appraisal is present in Appraisals'
32
+ end
33
+
34
+ RSpec.configure do |config|
35
+ config.include Helpers
36
+ config.include Rack::Test::Methods
37
+
38
+ config.pattern = rspec_pattern
39
+ end
@@ -0,0 +1,16 @@
1
+ require 'bigdecimal'
2
+
3
+ module Helpers
4
+ # Time used when testing timestamp
5
+ def time_anchor
6
+ Time.new(2015, 12, 15, 9, 30, 5.123, '+06:00')
7
+ end
8
+
9
+ def time_anchor_unix
10
+ BigDecimal.new('1450150205.123')
11
+ end
12
+
13
+ def hostname_anchor
14
+ 'bird.example.com'
15
+ end
16
+ end
@@ -0,0 +1,183 @@
1
+ RSpec.shared_examples 'request logger' do
2
+ context 'get request' do
3
+ it 'logs the request' do
4
+ get '/ok',
5
+ { username: 'yoshi' },
6
+ 'HTTP_USER_AGENT' => 'Chrome', 'HTTP_X_REQUEST_ID' => '471a34dc'
7
+
8
+ expect(json).to match(
9
+ 'version' => '1.1',
10
+ 'host' => 'bird.example.com',
11
+ 'short_message' => 'GET /ok?username=yoshi 200 in 0ms',
12
+ 'timestamp' => 1_450_150_205.123,
13
+ 'level' => 6,
14
+ '_type' => 'request',
15
+ '_service.name' => 'hello_world_app',
16
+ '_service.version' => '1.0',
17
+ '_request.method' => 'GET',
18
+ '_request.path' => '/ok',
19
+ '_request.params' => { 'username' => 'yoshi' },
20
+ '_request.request_ip' => '127.0.0.1',
21
+ '_request.user_agent' => 'Chrome',
22
+ '_request.status' => 200,
23
+ '_request.request_id' => '471a34dc',
24
+ '_request.duration' => 0,
25
+ '_tags' => ['471a34dc'],
26
+ )
27
+ end
28
+ end
29
+
30
+ context 'post request' do
31
+ let(:json_response) { JSON.parse(last_response.body) }
32
+
33
+ it 'logs the request' do
34
+ post '/users?username=yoshi',
35
+ { email: 'hello@world.com' },
36
+ 'HTTP_USER_AGENT' => 'Chrome', 'HTTP_X_REQUEST_ID' => '471a34dc'
37
+
38
+ expect(json).to match(
39
+ 'version' => '1.1',
40
+ 'host' => 'bird.example.com',
41
+ 'short_message' => 'POST /users?username=yoshi 200 in 0ms',
42
+ 'timestamp' => 1_450_150_205.123,
43
+ 'level' => 6,
44
+ '_type' => 'request',
45
+ '_service.name' => 'hello_world_app',
46
+ '_service.version' => '1.0',
47
+ '_request.method' => 'POST',
48
+ '_request.path' => '/users',
49
+ '_request.params' => { 'username' => 'yoshi', 'email' => 'hello@world.com' },
50
+ '_request.request_ip' => '127.0.0.1',
51
+ '_request.user_agent' => 'Chrome',
52
+ '_request.status' => 200,
53
+ '_request.request_id' => '471a34dc',
54
+ '_request.duration' => 0,
55
+ '_tags' => ['471a34dc'],
56
+ )
57
+ end
58
+
59
+ it 'preseves request parameters' do
60
+ post '/users?username=yoshi', email: 'hello@world.com'
61
+ expect(json_response).to include('email' => 'hello@world.com', 'username' => 'yoshi')
62
+ end
63
+ end
64
+
65
+ context 'request with redirect' do
66
+ it 'specifies the original path' do
67
+ get '/new', {}, 'HTTP_USER_AGENT' => 'Chrome', 'HTTP_X_REQUEST_ID' => '471a34dc'
68
+
69
+ expect(json).to match(
70
+ 'version' => '1.1',
71
+ 'host' => 'bird.example.com',
72
+ 'short_message' => 'GET /new 302 in 0ms',
73
+ 'timestamp' => 1_450_150_205.123,
74
+ 'level' => 6,
75
+ '_type' => 'request',
76
+ '_service.name' => 'hello_world_app',
77
+ '_service.version' => '1.0',
78
+ '_request.method' => 'GET',
79
+ '_request.path' => '/new',
80
+ '_request.params' => {},
81
+ '_request.request_ip' => '127.0.0.1',
82
+ '_request.user_agent' => 'Chrome',
83
+ '_request.status' => 302,
84
+ '_request.request_id' => '471a34dc',
85
+ '_request.duration' => 0,
86
+ '_tags' => ['471a34dc'],
87
+ )
88
+ end
89
+ end
90
+
91
+ context 'when the request raises an exception' do
92
+ it 'logs the request with the exception' do
93
+ get '/error',
94
+ { username: 'yoshi' },
95
+ 'HTTP_USER_AGENT' => 'Chrome', 'HTTP_X_REQUEST_ID' => '471a34dc'
96
+
97
+ expect(json).to match(
98
+ 'version' => '1.1',
99
+ 'host' => 'bird.example.com',
100
+ 'short_message' => 'GET /error?username=yoshi 500 in 0ms',
101
+ 'timestamp' => 1_450_150_205.123,
102
+ 'level' => 3,
103
+ '_type' => 'request',
104
+ '_service.name' => 'hello_world_app',
105
+ '_service.version' => '1.0',
106
+ '_request.method' => 'GET',
107
+ '_request.path' => '/error',
108
+ '_request.params' => { 'username' => 'yoshi' },
109
+ '_request.request_ip' => '127.0.0.1',
110
+ '_request.user_agent' => 'Chrome',
111
+ '_request.status' => 500,
112
+ '_request.request_id' => '471a34dc',
113
+ '_request.duration' => 0,
114
+ '_exception.klass' => 'NoMethodError',
115
+ '_exception.message' => "undefined method `name' for nil:NilClass",
116
+ '_exception.backtrace' => be_a(String),
117
+ '_tags' => ['471a34dc'],
118
+ )
119
+ end
120
+ end
121
+
122
+ describe 'when request causes 404' do
123
+ it 'does not log the framework exception' do
124
+ get '/not_found', {}, 'HTTP_X_REQUEST_ID' => '471a34dc'
125
+
126
+ expect(json).to match(
127
+ 'version' => '1.1',
128
+ 'host' => 'bird.example.com',
129
+ 'short_message' => 'GET /not_found 404 in 0ms',
130
+ 'timestamp' => 1_450_150_205.123,
131
+ 'level' => 6,
132
+ '_type' => 'request',
133
+ '_service.name' => 'hello_world_app',
134
+ '_service.version' => '1.0',
135
+ '_request.method' => 'GET',
136
+ '_request.path' => '/not_found',
137
+ '_request.params' => {},
138
+ '_request.request_ip' => '127.0.0.1',
139
+ '_request.user_agent' => nil,
140
+ '_request.status' => 404,
141
+ '_request.request_id' => '471a34dc',
142
+ '_request.duration' => 0,
143
+ '_tags' => ['471a34dc'],
144
+ )
145
+ end
146
+ end
147
+
148
+ describe 'when the request includes a filtered parameter' do
149
+ before { get '/ok', params }
150
+
151
+ context 'when params is shallow' do
152
+ let(:params) { { password: 'password123' } }
153
+
154
+ it 'filters the parameter from the params hash' do
155
+ expect(json).to include(
156
+ '_request.params' => { 'password' => '[FILTERED]' },
157
+ )
158
+ end
159
+
160
+ it 'filters the parameter from the message' do
161
+ expect(json).to include(
162
+ 'short_message' => 'GET /ok?password=[FILTERED] 200 in 0ms',
163
+ )
164
+ end
165
+ end
166
+
167
+ context 'when params is nested' do
168
+ let(:params) { { users: [password: 'password123'] } }
169
+
170
+ it 'filters the parameter from the params hash' do
171
+ expect(json).to include(
172
+ '_request.params' => { 'users' => ['password' => '[FILTERED]'] },
173
+ )
174
+ end
175
+
176
+ it 'filters the parameter from the message' do
177
+ expect(json).to include(
178
+ 'short_message' => 'GET /ok?users[][password]=[FILTERED] 200 in 0ms',
179
+ )
180
+ end
181
+ end
182
+ end
183
+ end