grape_logging 1.3.0 → 1.4.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +6 -0
- data/README.md +49 -41
- data/grape_logging.gemspec +3 -1
- data/lib/grape_logging.rb +2 -0
- data/lib/grape_logging/formatters/logstash.rb +35 -0
- data/lib/grape_logging/loggers/filter_parameters.rb +21 -9
- data/lib/grape_logging/middleware/request_logger.rb +2 -1
- data/lib/grape_logging/reporters/logger_reporter.rb +3 -1
- data/lib/grape_logging/util/parameter_filter.rb +90 -0
- data/lib/grape_logging/version.rb +1 -1
- metadata +34 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb1521644b8ec276a0cd7eeb3cadcc75c98d88f5
|
4
|
+
data.tar.gz: 815eaa0bf94e7f282ac99be2f0746ba31abdb4e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 66614c057b039c188ed42a0058d178ffc128e2f3a04fa03e2df2c98558063f5161236f348251ca2aa7b03cabbc35a5894fcde074e2a8257121cbaf627bc92831
|
7
|
+
data.tar.gz: 4af96b697baed8d4cb03d958133a18ad9ed66e7e601397330cd80960a19871c1c295b64de3c4d90b115ca6a23c6b4b3cc4bf7982ee6aa79812ee14a9fdf3f702
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# grape_logging
|
2
2
|
|
3
3
|
[](https://codeclimate.com/github/aserafin/grape_logging)
|
4
|
+
[](https://travis-ci.org/aserafin/grape_logging)
|
4
5
|
|
5
6
|
## Installation
|
6
7
|
|
@@ -20,9 +21,11 @@ Or install it yourself as:
|
|
20
21
|
|
21
22
|
In your api file (somewhere on the top)
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
```ruby
|
25
|
+
require 'grape_logging'
|
26
|
+
logger.formatter = GrapeLogging::Formatters::Default.new
|
27
|
+
use GrapeLogging::Middleware::RequestLogger, { logger: logger }
|
28
|
+
```
|
26
29
|
|
27
30
|
**ProTip:** If your logger doesn't support setting formatter you can remove this line - it's optional
|
28
31
|
|
@@ -37,23 +40,25 @@ With the default configuration you will get nice log message
|
|
37
40
|
If you prefer some other format I strongly encourage you to do pull request with new formatter class ;)
|
38
41
|
|
39
42
|
You can change the formatter like so
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
```ruby
|
44
|
+
class MyAPI < Grape::API
|
45
|
+
use GrapeLogging::Middleware::RequestLogger, logger: logger, formatter: MyFormatter.new
|
46
|
+
end
|
47
|
+
```
|
44
48
|
|
45
49
|
### Customising What Is Logged
|
46
50
|
|
47
51
|
You can include logging of other parts of the request / response cycle by including subclasses of `GrapeLogging::Loggers::Base`
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
```ruby
|
53
|
+
class MyAPI < Grape::API
|
54
|
+
use GrapeLogging::Middleware::RequestLogger,
|
55
|
+
logger: logger,
|
56
|
+
include: [ GrapeLogging::Loggers::Response.new,
|
57
|
+
GrapeLogging::Loggers::FilterParameters.new,
|
58
|
+
GrapeLogging::Loggers::ClientEnv.new,
|
59
|
+
GrapeLogging::Loggers::RequestHeaders.new ]
|
60
|
+
end
|
61
|
+
```
|
57
62
|
|
58
63
|
#### FilterParameters
|
59
64
|
The `FilterParameters` logger will filter out sensitive parameters from your logs. If mounted inside rails, will use the `Rails.application.config.filter_parameters` by default. Otherwise, you must specify a list of keys to filter out.
|
@@ -67,45 +72,48 @@ The `RequestHeaders` logger will add `request headers` in your log.
|
|
67
72
|
### Logging to file and STDOUT
|
68
73
|
|
69
74
|
You can log to file and STDOUT at the same time, you just need to assign new logger
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
75
|
+
```ruby
|
76
|
+
log_file = File.open('path/to/your/logfile.log', 'a')
|
77
|
+
log_file.sync = true
|
78
|
+
logger Logger.new GrapeLogging::MultiIO.new(STDOUT, log_file)
|
79
|
+
```
|
74
80
|
|
75
81
|
### Logging via Rails instrumentation
|
76
82
|
|
77
83
|
You can choose to not pass the logger to ```grape_logging``` but instead send logs to Rails instrumentation in order to let Rails and its configured Logger do the log job, for example.
|
78
84
|
First, config ```grape_logging```, like that:
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
85
|
+
```ruby
|
86
|
+
class MyAPI < Grape::API
|
87
|
+
use GrapeLogging::Middleware::RequestLogger,
|
88
|
+
instrumentation_key: 'grape_key',
|
89
|
+
include: [ GrapeLogging::Loggers::Response.new,
|
90
|
+
GrapeLogging::Loggers::FilterParameters.new ]
|
91
|
+
end
|
92
|
+
```
|
86
93
|
|
87
94
|
and then add an initializer in your Rails project:
|
95
|
+
```ruby
|
96
|
+
# config/initializers/instrumentation.rb
|
88
97
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
end
|
98
|
+
# Subscribe to grape request and log with Rails.logger
|
99
|
+
ActiveSupport::Notifications.subscribe('grape_key') do |name, starts, ends, notification_id, payload|
|
100
|
+
Rails.logger.info payload
|
101
|
+
end
|
102
|
+
```
|
95
103
|
|
96
104
|
The idea come from here: https://gist.github.com/teamon/e8ae16ffb0cb447e5b49
|
97
105
|
|
98
106
|
### Logging exceptions
|
99
107
|
|
100
108
|
If you want to log exceptions you can do it like this
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
+
```ruby
|
110
|
+
class MyAPI < Grape::API
|
111
|
+
rescue_from :all do |e|
|
112
|
+
MyAPI.logger.error e
|
113
|
+
#do here whatever you originally planned to do :)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
```
|
109
117
|
## Development
|
110
118
|
|
111
119
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/grape_logging.gemspec
CHANGED
@@ -23,4 +23,6 @@ Gem::Specification.new do |spec|
|
|
23
23
|
|
24
24
|
spec.add_development_dependency 'bundler', '~> 1.8'
|
25
25
|
spec.add_development_dependency 'rake', '~> 10.0'
|
26
|
-
|
26
|
+
spec.add_development_dependency 'rspec', '~> 3.5'
|
27
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.4.2'
|
28
|
+
end
|
data/lib/grape_logging.rb
CHANGED
@@ -2,6 +2,7 @@ require 'grape_logging/multi_io'
|
|
2
2
|
require 'grape_logging/version'
|
3
3
|
require 'grape_logging/formatters/default'
|
4
4
|
require 'grape_logging/formatters/json'
|
5
|
+
require 'grape_logging/formatters/logstash'
|
5
6
|
require 'grape_logging/loggers/base'
|
6
7
|
require 'grape_logging/loggers/response'
|
7
8
|
require 'grape_logging/loggers/filter_parameters'
|
@@ -11,3 +12,4 @@ require 'grape_logging/reporters/active_support_reporter'
|
|
11
12
|
require 'grape_logging/reporters/logger_reporter'
|
12
13
|
require 'grape_logging/timings'
|
13
14
|
require 'grape_logging/middleware/request_logger'
|
15
|
+
require 'grape_logging/util/parameter_filter'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module GrapeLogging
|
2
|
+
module Formatters
|
3
|
+
class Logstash
|
4
|
+
def call(severity, datetime, _, data)
|
5
|
+
{
|
6
|
+
:'@timestamp' => datetime.iso8601,
|
7
|
+
:'@version' => '1',
|
8
|
+
:severity => severity
|
9
|
+
}.merge!(format(data)).to_json
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def format(data)
|
15
|
+
if data.is_a?(Hash)
|
16
|
+
data
|
17
|
+
elsif data.is_a?(String)
|
18
|
+
{ message: data }
|
19
|
+
elsif data.is_a?(Exception)
|
20
|
+
format_exception(data)
|
21
|
+
else
|
22
|
+
{ message: data.inspect }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def format_exception(exception)
|
27
|
+
{
|
28
|
+
exception: {
|
29
|
+
message: exception.message
|
30
|
+
}
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,23 +1,35 @@
|
|
1
1
|
module GrapeLogging
|
2
2
|
module Loggers
|
3
3
|
class FilterParameters < GrapeLogging::Loggers::Base
|
4
|
-
|
4
|
+
AD_PARAMS = 'action_dispatch.request.parameters'.freeze
|
5
|
+
|
6
|
+
def initialize(filter_parameters = nil, replacement = nil, exceptions = %w(controller action format))
|
5
7
|
@filter_parameters = filter_parameters || (defined?(Rails.application) ? Rails.application.config.filter_parameters : [])
|
6
|
-
@replacement = replacement
|
8
|
+
@replacement = replacement || '[FILTERED]'
|
9
|
+
@exceptions = exceptions
|
7
10
|
end
|
8
11
|
|
9
12
|
def parameters(request, _)
|
10
|
-
{ params:
|
13
|
+
{ params: safe_parameters(request) }
|
11
14
|
end
|
12
15
|
|
13
16
|
private
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
|
18
|
+
def parameter_filter
|
19
|
+
@parameter_filter ||= ParameterFilter.new(@replacement, @filter_parameters)
|
20
|
+
end
|
21
|
+
|
22
|
+
def safe_parameters(request)
|
23
|
+
# Now this logger can work also over Rails requests
|
24
|
+
if request.params.empty?
|
25
|
+
clean_parameters(request.env[AD_PARAMS] || {})
|
26
|
+
else
|
27
|
+
clean_parameters(request.params)
|
19
28
|
end
|
20
|
-
|
29
|
+
end
|
30
|
+
|
31
|
+
def clean_parameters(parameters)
|
32
|
+
parameter_filter.filter(parameters).reject{ |key, _value| @exceptions.include?(key) }
|
21
33
|
end
|
22
34
|
end
|
23
35
|
end
|
@@ -2,7 +2,9 @@ module Reporters
|
|
2
2
|
class LoggerReporter
|
3
3
|
def initialize(logger, formatter)
|
4
4
|
@logger = logger || Logger.new(STDOUT)
|
5
|
-
|
5
|
+
if @logger.respond_to?(:formatter=)
|
6
|
+
@logger.formatter = formatter || @logger.formatter || GrapeLogging::Formatters::Default.new
|
7
|
+
end
|
6
8
|
end
|
7
9
|
|
8
10
|
def perform(params)
|
@@ -0,0 +1,90 @@
|
|
1
|
+
if defined?(Rails.application)
|
2
|
+
class ParameterFilter < ActionDispatch::Http::ParameterFilter
|
3
|
+
def initialize(_replacement, filter_parameters)
|
4
|
+
super(filter_parameters)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
else
|
8
|
+
#
|
9
|
+
# lifted from https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/http/parameter_filter.rb
|
10
|
+
# we could depend on Rails specifically, but that would us way to hefty!
|
11
|
+
#
|
12
|
+
class ParameterFilter
|
13
|
+
def initialize(replacement, filters = [])
|
14
|
+
@replacement = replacement
|
15
|
+
@filters = filters
|
16
|
+
end
|
17
|
+
|
18
|
+
def filter(params)
|
19
|
+
compiled_filter.call(params)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def compiled_filter
|
25
|
+
@compiled_filter ||= CompiledFilter.compile(@replacement, @filters)
|
26
|
+
end
|
27
|
+
|
28
|
+
class CompiledFilter # :nodoc:
|
29
|
+
def self.compile(replacement, filters)
|
30
|
+
return lambda { |params| params.dup } if filters.empty?
|
31
|
+
|
32
|
+
strings, regexps, blocks = [], [], []
|
33
|
+
|
34
|
+
filters.each do |item|
|
35
|
+
case item
|
36
|
+
when Proc
|
37
|
+
blocks << item
|
38
|
+
when Regexp
|
39
|
+
regexps << item
|
40
|
+
else
|
41
|
+
strings << Regexp.escape(item.to_s)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
deep_regexps, regexps = regexps.partition { |r| r.to_s.include?("\\.".freeze) }
|
46
|
+
deep_strings, strings = strings.partition { |s| s.include?("\\.".freeze) }
|
47
|
+
|
48
|
+
regexps << Regexp.new(strings.join('|'.freeze), true) unless strings.empty?
|
49
|
+
deep_regexps << Regexp.new(deep_strings.join('|'.freeze), true) unless deep_strings.empty?
|
50
|
+
|
51
|
+
new replacement, regexps, deep_regexps, blocks
|
52
|
+
end
|
53
|
+
|
54
|
+
attr_reader :regexps, :deep_regexps, :blocks
|
55
|
+
|
56
|
+
def initialize(replacement, regexps, deep_regexps, blocks)
|
57
|
+
@replacement = replacement
|
58
|
+
@regexps = regexps
|
59
|
+
@deep_regexps = deep_regexps.any? ? deep_regexps : nil
|
60
|
+
@blocks = blocks
|
61
|
+
end
|
62
|
+
|
63
|
+
def call(original_params, parents = [])
|
64
|
+
filtered_params = {}
|
65
|
+
|
66
|
+
original_params.each do |key, value|
|
67
|
+
parents.push(key) if deep_regexps
|
68
|
+
if regexps.any? { |r| key =~ r }
|
69
|
+
value = @replacement
|
70
|
+
elsif deep_regexps && (joined = parents.join('.')) && deep_regexps.any? { |r| joined =~ r }
|
71
|
+
value = @replacement
|
72
|
+
elsif value.is_a?(Hash)
|
73
|
+
value = call(value, parents)
|
74
|
+
elsif value.is_a?(Array)
|
75
|
+
value = value.map { |v| v.is_a?(Hash) ? call(v, parents) : v }
|
76
|
+
elsif blocks.any?
|
77
|
+
key = key.dup if key.duplicable?
|
78
|
+
value = value.dup if value.duplicable?
|
79
|
+
blocks.each { |b| b.call(key, value) }
|
80
|
+
end
|
81
|
+
parents.pop if deep_regexps
|
82
|
+
|
83
|
+
filtered_params[key] = value
|
84
|
+
end
|
85
|
+
|
86
|
+
filtered_params
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grape_logging
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aserafin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: grape
|
@@ -52,6 +52,34 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.5'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.5'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry-byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.4.2
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.4.2
|
55
83
|
description: This gem provides simple request logging for Grape with just few lines
|
56
84
|
of code you have to put in your project! In return you will get response codes,
|
57
85
|
paths, parameters and more!
|
@@ -62,6 +90,7 @@ extensions: []
|
|
62
90
|
extra_rdoc_files: []
|
63
91
|
files:
|
64
92
|
- ".gitignore"
|
93
|
+
- ".travis.yml"
|
65
94
|
- Gemfile
|
66
95
|
- LICENSE.txt
|
67
96
|
- README.md
|
@@ -72,6 +101,7 @@ files:
|
|
72
101
|
- lib/grape_logging.rb
|
73
102
|
- lib/grape_logging/formatters/default.rb
|
74
103
|
- lib/grape_logging/formatters/json.rb
|
104
|
+
- lib/grape_logging/formatters/logstash.rb
|
75
105
|
- lib/grape_logging/loggers/base.rb
|
76
106
|
- lib/grape_logging/loggers/client_env.rb
|
77
107
|
- lib/grape_logging/loggers/filter_parameters.rb
|
@@ -82,6 +112,7 @@ files:
|
|
82
112
|
- lib/grape_logging/reporters/active_support_reporter.rb
|
83
113
|
- lib/grape_logging/reporters/logger_reporter.rb
|
84
114
|
- lib/grape_logging/timings.rb
|
115
|
+
- lib/grape_logging/util/parameter_filter.rb
|
85
116
|
- lib/grape_logging/version.rb
|
86
117
|
homepage: http://github.com/aserafin/grape_logging
|
87
118
|
licenses:
|
@@ -103,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
134
|
version: '0'
|
104
135
|
requirements: []
|
105
136
|
rubyforge_project:
|
106
|
-
rubygems_version: 2.
|
137
|
+
rubygems_version: 2.5.1
|
107
138
|
signing_key:
|
108
139
|
specification_version: 4
|
109
140
|
summary: Out of the box request logging for Grape!
|