grape-middleware-logger 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 590ce26a5ad8498e9a23d0d04fb67d145839c3d2
4
- data.tar.gz: 3b14c745464c253f07dc3f1d3114670ef69498f4
3
+ metadata.gz: 5c6903ab2693fd8f2192bcdf3a3d56353cb5954b
4
+ data.tar.gz: bf21e7e9fe1d0730288c412e88ac1c011238316d
5
5
  SHA512:
6
- metadata.gz: 52bbc22b98b568a93abca85bb5037d5c01d21e791d15ed484ea8f03a3a895d15f6a251fd02bbe33d64b0b507db8850a07e52cb8c1244ae162fff67ef2328b94f
7
- data.tar.gz: 2f7471095ee5ac2a94e9f98ca55e23d6656d6ff84126eb3860998b909484442e5adc97eb8b18217880cd10a4c849b7a14c72d68a85750751670f8ed8e51413bb
6
+ metadata.gz: e2682ddacc69dbd6f7300b12d29f05e0350bb0d4b33b4bab108f46abe0b14d652a1f6963a141a9cb31cbdfd11eee4c5e4867af5e088449e5a3df4bc829a70466
7
+ data.tar.gz: d6b82afc9f5f2e2adb7a41eaa1ea81363aefd54da2dbaef4d4bb5b30c7411e7f8cbeedf62e7402719bbd8f4940b34e14bd8388d3db673d4dd32630224f9d1633
data/Gemfile CHANGED
@@ -5,4 +5,5 @@ gemspec
5
5
 
6
6
  group :test do
7
7
  gem 'rake'
8
+ gem "factory_girl", "~> 4.0"
8
9
  end
data/README.md CHANGED
@@ -9,13 +9,14 @@ Simple logger for Grape apps. Logs request path, parameters, status and time tak
9
9
  Add this line to your application's Gemfile:
10
10
 
11
11
  ```ruby
12
- gem 'grape', '>= 0.12.0'
12
+ gem 'grape', '>= 0.14.0'
13
13
  gem 'grape-middleware-logger'
14
14
  ```
15
15
 
16
16
  ## Usage
17
17
  ```ruby
18
18
  class API < Grape::API
19
+ # @note Make sure this above you're first +mount+
19
20
  use Grape::Middleware::Logger
20
21
  end
21
22
  ```
@@ -41,17 +42,23 @@ The `filter` option can be any object that responds to `.filter(params_hash)`
41
42
  Get
42
43
  ```
43
44
  Started GET "/v1/reports/101" at 2015-12-11 15:40:51 -0800
45
+ Processing by ReportsAPI#reports/:id
44
46
  Parameters: {"id"=>"101"}
45
47
  Completed 200 in 6.29ms
46
48
  ```
47
49
  Error
48
50
  ```
49
51
  Started POST "/v1/reports" at 2015-12-11 15:42:33 -0800
52
+ Processing by ReportsAPI#reports
50
53
  Parameters: {"name"=>"foo", "password"=>"[FILTERED]"}
51
54
  Error: {:error=>"undefined something something bad", :detail=>"Whoops"}
52
55
  Completed 422 in 6.29ms
53
56
  ```
54
57
 
58
+ ## Rack
59
+
60
+ If you're using the `rackup` command to run your server in development, pass the `-q` flag to silence the default rack logger.
61
+
55
62
  ## Credits
56
63
 
57
64
  Big thanks to jadent's question/answer on [stackoverflow](http://stackoverflow.com/questions/25048163/grape-using-error-and-grapemiddleware-after-callback)
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'grape-middleware-logger'
5
- spec.version = '1.3.0'
5
+ spec.version = '1.4.0'
6
6
  spec.platform = Gem::Platform::RUBY
7
7
  spec.authors = ['Ryan Buckley']
8
8
  spec.email = ['arebuckley@gmail.com']
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
17
  spec.require_paths = ['lib']
18
18
 
19
- spec.add_dependency 'grape', '>= 0.12', '< 1'
19
+ spec.add_dependency 'grape', '>= 0.14', '< 1'
20
20
 
21
21
  spec.add_development_dependency 'bundler', '~> 1.7'
22
22
  spec.add_development_dependency 'rake', '~> 10.0'
@@ -8,7 +8,7 @@ class Grape::Middleware::Logger < Grape::Middleware::Globals
8
8
  super
9
9
  @logger = options[:logger]
10
10
  @logger ||= Rails.logger if defined?(Rails) && Rails.logger.present?
11
- @logger ||= Logger.new(STDOUT)
11
+ @logger ||= default_logger
12
12
  end
13
13
 
14
14
  def before
@@ -16,10 +16,11 @@ class Grape::Middleware::Logger < Grape::Middleware::Globals
16
16
  super # sets env['grape.*']
17
17
  logger.info ''
18
18
  logger.info %Q(Started %s "%s" at %s) % [
19
- env['grape.request'].request_method,
20
- env['grape.request'].path,
19
+ env[Grape::Env::GRAPE_REQUEST].request_method,
20
+ env[Grape::Env::GRAPE_REQUEST].path,
21
21
  start_time.to_s
22
22
  ]
23
+ logger.info %Q(Processing by #{processed_by})
23
24
  logger.info %Q( Parameters: #{parameters})
24
25
  end
25
26
 
@@ -73,7 +74,7 @@ class Grape::Middleware::Logger < Grape::Middleware::Globals
73
74
  end
74
75
 
75
76
  def parameters
76
- request_params = env['grape.request.params'].to_hash
77
+ request_params = env[Grape::Env::GRAPE_REQUEST_PARAMS].to_hash
77
78
  request_params.merge!(env['action_dispatch.request.request_parameters'] || {}) # for Rails
78
79
  if @options[:filter]
79
80
  @options[:filter].filter(request_params)
@@ -85,4 +86,24 @@ class Grape::Middleware::Logger < Grape::Middleware::Globals
85
86
  def start_time
86
87
  @start_time ||= Time.now
87
88
  end
89
+
90
+ def processed_by
91
+ endpoint = env[Grape::Env::API_ENDPOINT]
92
+ parts = endpoint.options[:for].to_s
93
+ parts << endpoint.namespace if endpoint.namespace != '/'
94
+ parts << '#' << endpoint.options[:path].map { |path| path.to_s.sub('/', '') }.join('/')
95
+ parts
96
+ end
97
+
98
+ def default_logger
99
+ default = Logger.new(STDOUT)
100
+ default.formatter = LogFormatter.new
101
+ default
102
+ end
103
+
104
+ class LogFormatter
105
+ def call(*args)
106
+ args.last.to_s << "\n"
107
+ end
108
+ end
88
109
  end
@@ -0,0 +1,90 @@
1
+ FactoryGirl.define do
2
+ class ExpectedEnv < Hash
3
+ attr_accessor :grape_request, :params, :post_params, :grape_endpoint
4
+ end
5
+
6
+ class ParamFilter
7
+ def filter(opts)
8
+ opts.each_pair { |key, val| val[0..-1] = '[FILTERED]' if key == 'password' }
9
+ end
10
+ end
11
+
12
+ class TestAPI
13
+ end
14
+
15
+ class App
16
+ attr_accessor :response
17
+
18
+ def call(_env)
19
+ response
20
+ end
21
+ end
22
+
23
+ factory :param_filter
24
+
25
+ require 'rack/rewindable_input'
26
+
27
+ factory :expected_env do
28
+ grape_request { build :grape_request }
29
+ params { grape_request.params }
30
+ post_params { { 'name' => 'foo', 'password' => 'access' } }
31
+ grape_endpoint { build(:grape_endpoint) }
32
+
33
+ initialize_with do
34
+ new.merge(
35
+ 'REQUEST_METHOD' => 'POST',
36
+ 'PATH_INFO' => '/api/1.0/users',
37
+ 'action_dispatch.request.request_parameters' => post_params,
38
+ Grape::Env::GRAPE_REQUEST => grape_request,
39
+ Grape::Env::GRAPE_REQUEST_PARAMS => params,
40
+ Grape::Env::API_ENDPOINT => grape_endpoint
41
+ )
42
+ end
43
+ end
44
+
45
+ factory :grape_endpoint, class: Grape::Endpoint do
46
+ settings { Grape::Util::InheritableSetting.new }
47
+ options {
48
+ {
49
+ path: [:users],
50
+ method: 'get',
51
+ for: TestAPI
52
+ }
53
+ }
54
+
55
+ initialize_with { new(settings, options) }
56
+
57
+ trait :complex do
58
+ options {
59
+ {
60
+ path: ['/users/:name/profile'],
61
+ method: 'put',
62
+ for: TestAPI
63
+ }
64
+ }
65
+ end
66
+ end
67
+
68
+ factory :namespaced_endpoint, parent: :grape_endpoint do
69
+ initialize_with do
70
+ new(settings, options).tap do |me|
71
+ me.namespace_stackable(:namespace, Grape::Namespace.new('/admin', {}))
72
+ end
73
+ end
74
+ end
75
+
76
+ factory :app_response, class: Rack::Response do
77
+ initialize_with { new('Hello World', 200, {}) }
78
+ end
79
+
80
+ factory :grape_request, class: OpenStruct do
81
+ initialize_with {
82
+ new(request_method: 'POST', path: '/api/1.0/users', headers: {}, params: { 'id' => '101001' })
83
+ }
84
+ end
85
+
86
+ factory :app do
87
+ response { build :app_response }
88
+ end
89
+
90
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'grape/middleware/logger'
3
+
4
+ describe Grape::Middleware::Logger, type: :integration do
5
+ let(:app) { build :app }
6
+ let(:options) { { filter: build(:param_filter), logger: Logger.new(Tempfile.new('logger')) } }
7
+
8
+ subject { described_class.new(app, options) }
9
+
10
+ let(:app_response) { build :app_response }
11
+ let(:grape_request) { build :grape_request }
12
+ let(:grape_endpoint) { build(:grape_endpoint) }
13
+ let(:env) { build(:expected_env, grape_endpoint: grape_endpoint) }
14
+
15
+ it 'logs all parts of the request' do
16
+ expect(subject.logger).to receive(:info).with ''
17
+ expect(subject.logger).to receive(:info).with %Q(Started POST "/api/1.0/users" at #{subject.start_time})
18
+ expect(subject.logger).to receive(:info).with %Q(Processing by TestAPI#users)
19
+ expect(subject.logger).to receive(:info).with %Q( Parameters: {"id"=>"101001", "name"=>"foo", "password"=>"[FILTERED]"})
20
+ expect(subject.logger).to receive(:info).with /Completed 200 in \d.\d+ms/
21
+ expect(subject.logger).to receive(:info).with ''
22
+ subject.call!(env)
23
+ end
24
+
25
+ describe 'the "processing by" section' do
26
+ before { subject.call!(env) }
27
+
28
+ context 'namespacing' do
29
+ let(:grape_endpoint) { build(:namespaced_endpoint) }
30
+
31
+ it 'designates the namespace with a slash' do
32
+ expect(subject.processed_by).to eq 'TestAPI/admin#users'
33
+ end
34
+
35
+ context 'with more complex route' do
36
+ let(:grape_endpoint) { build(:namespaced_endpoint, :complex) }
37
+
38
+ it 'only escapes the first slash and leaves the rest of the untouched' do
39
+ expect(subject.processed_by).to eq 'TestAPI/admin#users/:name/profile'
40
+ end
41
+ end
42
+ end
43
+
44
+ context 'with more complex route' do
45
+ let(:grape_endpoint) { build(:grape_endpoint, :complex) }
46
+
47
+ it 'only escapes the first slash and leaves the rest of the untouched' do
48
+ expect(subject.processed_by).to eq 'TestAPI#users/:name/profile'
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,25 +1,14 @@
1
1
  require 'spec_helper'
2
- require 'grape/middleware/logger'
3
2
 
4
3
  describe Grape::Middleware::Logger do
5
4
  let(:app) { double('app') }
6
- let(:options) { { filter: ParamFilter.new, logger: Object.new } }
5
+ let(:options) { { filter: build(:param_filter), logger: Object.new } }
7
6
 
8
7
  subject { described_class.new(app, options) }
9
8
 
10
- let(:app_response) { Rack::Response.new 'Hello World', 200, {} }
11
- let(:grape_request) { OpenStruct.new(request_method: 'POST', path: '/api/1.0/users', headers: {}, params: { 'id' => '101001' }) }
12
- let(:env) {
13
- {
14
- 'grape.request' => grape_request,
15
- 'grape.request.params' => grape_request.params,
16
- 'action_dispatch.request.request_parameters' => {
17
- 'name' => 'foo',
18
- 'password' => 'access'
19
- },
20
- 'rack.input' => OpenStruct.new
21
- }
22
- }
9
+ let(:app_response) { build :app_response }
10
+ let(:grape_request) { build :grape_request }
11
+ let(:env) { build(:expected_env) }
23
12
 
24
13
  describe '#call!' do
25
14
  context 'when calling the app results in an error response' do
@@ -128,6 +117,10 @@ describe Grape::Middleware::Logger do
128
117
  expect(subject.logger).to be_a(Logger)
129
118
  end
130
119
 
120
+ it 'logs each message in the correct format' do
121
+ expect(subject.logger.formatter.call('foo')).to eq "foo\n"
122
+ end
123
+
131
124
  context 'when Rails.logger is defined' do
132
125
  before do
133
126
  Rails.logger = double('rails_logger')
@@ -154,26 +147,4 @@ describe Grape::Middleware::Logger do
154
147
  end
155
148
  end
156
149
  end
157
-
158
- describe 'integration' do
159
- it 'properly logs requests' do
160
- expect(app).to receive(:call).with(env).and_return(app_response)
161
- expect(Grape::Request).to receive(:new).and_return(grape_request)
162
- expect(subject.logger).to receive(:info).with('')
163
- expect(subject.logger).to receive(:info).with(%Q(Started POST "/api/1.0/users" at #{subject.start_time}))
164
- expect(subject.logger).to receive(:info).with(%Q( Parameters: {"id"=>"101001", "name"=>"foo", "password"=>"[FILTERED]"}))
165
- expect(subject.logger).to receive(:info).with(/Completed 200 in \d.\d+ms/)
166
- expect(subject.logger).to receive(:info).with('')
167
- subject.call!(env)
168
- end
169
- end
170
-
171
- #
172
- # Test class
173
- #
174
- class ParamFilter
175
- def filter(opts)
176
- opts.each_pair { |key, val| val[0..-1] = '[FILTERED]' if key == 'password' }
177
- end
178
- end
179
150
  end
@@ -2,7 +2,12 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
 
4
4
  require 'ostruct'
5
+ require 'factory_girl'
6
+ require 'grape/middleware/logger'
7
+
8
+ FactoryGirl.find_definitions
5
9
 
6
10
  RSpec.configure do |config|
7
11
  config.raise_errors_for_deprecations!
12
+ config.include FactoryGirl::Syntax::Methods
8
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-middleware-logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Buckley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-11 00:00:00.000000000 Z
11
+ date: 2015-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grape
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0.12'
19
+ version: '0.14'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '1'
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '0.12'
29
+ version: '0.14'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '1'
@@ -93,6 +93,8 @@ files:
93
93
  - Rakefile
94
94
  - grape-middleware-logger.gemspec
95
95
  - lib/grape/middleware/logger.rb
96
+ - spec/factories.rb
97
+ - spec/integration/lib/grape/middleware/logger_spec.rb
96
98
  - spec/lib/grape/middleware/logger_spec.rb
97
99
  - spec/spec_helper.rb
98
100
  homepage: ''
@@ -120,5 +122,7 @@ signing_key:
120
122
  specification_version: 4
121
123
  summary: A logger for the Grape framework
122
124
  test_files:
125
+ - spec/factories.rb
126
+ - spec/integration/lib/grape/middleware/logger_spec.rb
123
127
  - spec/lib/grape/middleware/logger_spec.rb
124
128
  - spec/spec_helper.rb