rack-action_logger 0.1.1 → 0.1.2

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: c8e8c03cf1b03abb219ce366f186470e1463b076
4
- data.tar.gz: 66ebdaa2cf3853bc60ae5ffcadb06716b38d9558
3
+ metadata.gz: 56b290ce696ada82b2b73deb7d7ddc038de28bbb
4
+ data.tar.gz: 403d7663fb1cc6bb013ac4de372886cb54366b2d
5
5
  SHA512:
6
- metadata.gz: 73a13a6749b1e4da13e799edad40fdda78b61c8b97a172bb806de803a3128667ae9dd5558b1f77046168988505f51feb9759fde290443a4f7c3a72e06ee339a2
7
- data.tar.gz: 84437cfd8af9b5882c525532eb0d94436521b2b99e9dc8fe04e25967794701c94a7fceef1375f8b9c8a0f995c1f2060e145afe534c296b0c0a040ce3bd1d7cb4
6
+ metadata.gz: 10da516b0a30cf0eae2953751c2333e45d2045343b1064fc5df8770241ba9e8f1560466d508bd0795b3da71ad9bf08e9f30f15270eb7ab5e155759cca8c0974e
7
+ data.tar.gz: 6170bfd88ac5231556cee46ad168ada907ad0bad14fe3d574c851e0bf755ba2682375d6c99068f796ecf6b83e6fee779981cdd05caf12e9ec4ea78afcf8f94df
data/Gemfile.lock CHANGED
@@ -1,9 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rack-action_logger (0.1.1)
4
+ rack-action_logger (0.1.2)
5
5
  activesupport
6
6
  fluent-logger (~> 0.5)
7
+ woothee (~> 1.4)
7
8
 
8
9
  GEM
9
10
  remote: https://rubygems.org/
@@ -20,6 +21,9 @@ GEM
20
21
  i18n (0.7.0)
21
22
  minitest (5.9.1)
22
23
  msgpack (1.0.2)
24
+ rack (2.0.1)
25
+ rack-test (0.6.3)
26
+ rack (>= 1.0)
23
27
  rake (10.5.0)
24
28
  rspec (3.5.0)
25
29
  rspec-core (~> 3.5.0)
@@ -37,6 +41,7 @@ GEM
37
41
  thread_safe (0.3.5)
38
42
  tzinfo (1.2.2)
39
43
  thread_safe (~> 0.1)
44
+ woothee (1.5.0)
40
45
 
41
46
  PLATFORMS
42
47
  ruby
@@ -44,6 +49,7 @@ PLATFORMS
44
49
  DEPENDENCIES
45
50
  bundler (~> 1.13)
46
51
  rack-action_logger!
52
+ rack-test (~> 0.6.3)
47
53
  rake (~> 10.0)
48
54
  rspec (~> 3.0)
49
55
 
data/README.md CHANGED
@@ -12,7 +12,60 @@ It is intended to collect user request log, action log and any other custome log
12
12
 
13
13
  ## Sample Logs
14
14
 
15
- ![sample logs](docs/sample_log.png)
15
+ ### Request log
16
+
17
+ ```json
18
+ {
19
+ "message": {
20
+ "path": "/",
21
+ "method": "GET",
22
+ "params": {
23
+ "password": "[FILTERED]"
24
+ },
25
+ "request_headers": {
26
+ "HTTP_VERSION": "HTTP/1.1",
27
+ "HTTP_HOST": "localhost:3000",
28
+ "HTTP_CONNECTION": "keep-alive",
29
+ "HTTP_UPGRADE_INSECURE_REQUESTS": "1",
30
+ "HTTP_USER_AGENT": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36",
31
+ "HTTP_ACCEPT": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
32
+ "HTTP_ACCEPT_ENCODING": "gzip, deflate, sdch, br",
33
+ "HTTP_ACCEPT_LANGUAGE": "ja,en-US;q=0.8,en;q=0.6",
34
+ "HTTP_COOKIE": "xxx"
35
+ },
36
+ "status_code": 200,
37
+ "remote_ip": "127.0.0.1",
38
+ "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36",
39
+ "device": "pc",
40
+ "os": "Mac OSX",
41
+ "browser": "Chrome",
42
+ "browser_version": "54.0.2840.98",
43
+ "request_id": "150a6ac9-0fd9-4a23-a313-d18da1e35911",
44
+ "response_headers": {
45
+ "X-Frame-Options": "SAMEORIGIN",
46
+ "X-XSS-Protection": "1; mode=block",
47
+ "X-Content-Type-Options": "nosniff",
48
+ "Content-Type": "text/html; charset=utf-8"
49
+ },
50
+ "response_json_body": {
51
+ },
52
+ "tag": "action.rack",
53
+ "user_id": 123
54
+ }
55
+ }
56
+ ```
57
+
58
+ ### Append log
59
+
60
+ ```json
61
+ {
62
+ "message": {
63
+ "request_id": "150a6ac9-0fd9-4a23-a313-d18da1e35911",
64
+ "value": "with_tag",
65
+ "tag": "action.activities"
66
+ }
67
+ }
68
+ ```
16
69
 
17
70
  Under example folder, there are sample Rails applications to see how these sample logs are created.
18
71
 
@@ -54,6 +107,7 @@ Rack::ActionLogger.configure do |config|
54
107
  config.emit_adapter = Rack::ActionLogger::EmitAdapter::FluentAdapter
55
108
  config.wrap_key = :message
56
109
  config.logger = Rails.logger
110
+ config.filters = Rails.application.config.filter_parameters
57
111
  end
58
112
  ```
59
113
 
@@ -63,31 +117,18 @@ If wrap_key is nil, the out put does not have parent key of wrap_key.
63
117
 
64
118
  ### Enable Request Log
65
119
 
66
- Add the following code to 'app/controllers/application_controller.rb'.
67
-
68
- ```ruby
69
- include Rack::ActionLogger::ControllerConcerns::RequestLog
70
- ```
71
-
72
- Request log should looks like this.
73
-
74
- ![request logs](docs/request_log.png)
75
-
76
- Request can be customized by creating new request log concern.
120
+ Request log is automatically enabled
77
121
 
122
+ Request can be customized by creating new class for rack_metrics configuration.
78
123
 
79
124
  ### Add Append Log
80
125
 
81
126
  Add the following code to any code on any times.
82
127
 
83
128
  ```ruby
84
- Rack::ActionLogger::Container.set_append_log({ value: 'ok' }, 'action.activities')
129
+ Rack::ActionLogger::Container.set_append_log({ value: 'ok' }, 'activities')
85
130
  ```
86
131
 
87
- Action log should looks like this.
88
-
89
- ![action log](docs/action_log.png)
90
-
91
132
  ### Override log attributes
92
133
 
93
134
  Overriden attributes are added to both request and append logs.
@@ -96,7 +137,18 @@ Overriden attributes are added to both request and append logs.
96
137
  Rack::ActionLogger::Container.merge_attributes({ user_id: 123 })
97
138
  ```
98
139
 
99
- ![attributed log](docs/attributed_log.png)
140
+ The append log is overrided by user_id attribute.
141
+
142
+ ```json
143
+ {
144
+ "message": {
145
+ "request_id": "150a6ac9-0fd9-4a23-a313-d18da1e35911",
146
+ "value": "with_tag",
147
+ "uer_id": 123,
148
+ "tag": "action.activities"
149
+ }
150
+ }
151
+ ```
100
152
 
101
153
  ### Logs out of request
102
154
 
@@ -111,7 +163,7 @@ class TestWorker < ApplicationController
111
163
 
112
164
  def perform(title, context)
113
165
  Rack::ActionLogger::Emitter.new.emit(context) do
114
- Rack::ActionLogger::Container.set_append_log({ title: title }, 'action.worker')
166
+ Rack::ActionLogger::Container.set_append_log({ title: title }, 'worker')
115
167
  p 'work: title=' + title
116
168
  end
117
169
  end
@@ -5,21 +5,38 @@ require 'logger'
5
5
 
6
6
  module Rack::ActionLogger
7
7
  class Configuration
8
+ DEFAULT_TAG_PREFIX = 'action'
9
+
8
10
  attr_accessor :emit_adapter
9
11
  attr_accessor :wrap_key
10
- attr_accessor :default_tag
11
12
  attr_accessor :tag_prefix
12
13
  attr_accessor :logger
14
+ attr_accessor :filters
15
+ attr_accessor :rack_request_blacklist
16
+ attr_accessor :pretty_print
17
+ attr_accessor :rack_metrics
13
18
 
14
19
  def initialize
15
20
  @emit_adapter = EmitAdapter::LoggerAdapter
16
- @tag_prefix = 'action'
21
+ @tag_prefix = DEFAULT_TAG_PREFIX
17
22
  @logger = Logger.new(STDOUT)
18
- @logger.progname = 'rack_action_logger'
23
+ @logger.progname = 'rack-action_logger'
24
+ @filters = ['password']
25
+ @rack_request_blacklist = [:request_headers, :response_headers, :response_json_body]
26
+ @pretty_print = true
27
+ @rack_metrics = Rack::ActionLogger::Metrics::RackMetrics
28
+ end
29
+
30
+ def tag_prefix
31
+ if @tag_prefix.to_s.empty?
32
+ Rack::ActionLogger.logger.error('tag_prefix should not be empty')
33
+ @tag_prefix = DEFAULT_TAG_PREFIX
34
+ end
35
+ @tag_prefix
19
36
  end
20
37
 
21
38
  def default_tag
22
- "#{@tag_prefix}.log"
39
+ [tag_prefix, 'log'].join('.')
23
40
  end
24
41
  end
25
42
  end
@@ -23,7 +23,7 @@ module Rack::ActionLogger
23
23
  store[:rack_action_logger_emit_started] ||= false
24
24
  end
25
25
 
26
- def set_append_log(hash, tag)
26
+ def set_append_log(hash, tag=nil)
27
27
  return unless is_valid_hash hash
28
28
  return unless is_valid_tag tag
29
29
  hash[:tag] = tag
@@ -43,7 +43,7 @@ module Rack::ActionLogger
43
43
  store[:rack_action_logger_attributes] ||= {}
44
44
  end
45
45
 
46
- def set_request_log(hash, tag)
46
+ def set_request_log(hash, tag=nil)
47
47
  return unless is_valid_hash hash
48
48
  return unless is_valid_tag tag
49
49
  hash[:tag] = tag
@@ -82,7 +82,7 @@ module Rack::ActionLogger
82
82
  end
83
83
 
84
84
  def is_valid_tag(tag)
85
- if tag.is_a? String
85
+ if tag.nil? || tag.is_a?(String)
86
86
  true
87
87
  else
88
88
  Rack::ActionLogger.logger.error("invalid tag: #{tag}")
@@ -7,9 +7,17 @@ module Rack::ActionLogger
7
7
 
8
8
  def call(env)
9
9
  Emitter.new.emit do
10
- @app.call(env)
10
+ status_code, headers, body = @app.call(env)
11
+ capture_rack_log(env, status_code, headers, body)
12
+ [status_code, headers, body]
11
13
  end
12
14
  end
13
15
 
16
+ def capture_rack_log(env, status_code, headers, body)
17
+ rack_metrics = Rack::ActionLogger.configuration.rack_metrics.new(env, status_code, headers, body)
18
+ Rack::ActionLogger::Container.set_request_log(rack_metrics.metrics, rack_metrics.tag_suffix)
19
+ Rack::ActionLogger::Container.merge_attributes({ request_id: rack_metrics.request_id })
20
+ end
21
+
14
22
  end
15
23
  end
@@ -1,10 +1,15 @@
1
+ require 'json'
1
2
  require 'rack/action_logger/emit_adapter/base'
2
3
 
3
4
  module Rack::ActionLogger::EmitAdapter
4
5
  class LoggerAdapter < Base
5
6
  def self.emit(hash)
6
7
  hash = wrap(hash)
7
- Rack::ActionLogger.logger.info(hash)
8
+ if Rack::ActionLogger.configuration.pretty_print
9
+ Rack::ActionLogger.logger.info(JSON.pretty_generate(hash))
10
+ else
11
+ Rack::ActionLogger.logger.info(hash)
12
+ end
8
13
  end
9
14
  end
10
15
  end
@@ -32,13 +32,24 @@ module Rack::ActionLogger
32
32
  def emit_request_log
33
33
  return unless (@container.get_request_log.is_a?(Hash) && @container.get_request_log != {})
34
34
  hash = @container.get_request_log.merge @container.get_attributes
35
+ hash = format_tag(hash)
35
36
  @emit_adapter.emit(hash)
36
37
  end
37
38
 
38
39
  def emit_append_logs
39
40
  @container.get_append_logs.each do |hash|
41
+ hash = format_tag(hash)
40
42
  @emit_adapter.emit(@container.get_attributes.merge!(hash))
41
43
  end
42
44
  end
45
+
46
+ def format_tag(hash)
47
+ if hash[:tag]
48
+ hash[:tag] = [Rack::ActionLogger.configuration.tag_prefix, hash[:tag]].join('.')
49
+ else
50
+ hash[:tag] = Rack::ActionLogger.configuration.default_tag
51
+ end
52
+ hash
53
+ end
43
54
  end
44
55
  end
@@ -0,0 +1,98 @@
1
+ require 'rack/action_logger'
2
+ require 'rack/mock'
3
+ require 'woothee'
4
+
5
+ module Rack::ActionLogger::Metrics
6
+ class RackMetrics
7
+ METRICS = [
8
+ :path, :method, :params, :request_headers, :status_code, :remote_ip, :user_agent, :device, :os, :browser,
9
+ :browser_version, :request_id, :response_headers, :response_json_body,
10
+ ]
11
+ RACK_TAG_PREFIX = 'rack'
12
+
13
+ attr_reader :status_code
14
+
15
+ def initialize(env, status_code, headers, body)
16
+ @env = env
17
+ @status_code = status_code
18
+ @headers = headers
19
+ @body = body
20
+ @request = Rack::Request.new(env)
21
+ @ua = Woothee.parse(@request.user_agent)
22
+ filters = Rack::ActionLogger.configuration.filters
23
+ @compiled_filters = Rack::ActionLogger::ParameterFiltering.compile(filters)
24
+ end
25
+
26
+ def tag_suffix
27
+ if @status_code == 404
28
+ tags = ['not_found']
29
+ else
30
+ tags = URI(path).path.split('/').reject { |c| c.empty? }
31
+ end
32
+ (Array(RACK_TAG_PREFIX) + tags).join('.')
33
+ end
34
+
35
+ def metrics
36
+ METRICS.inject({}) do |result, metric|
37
+ result[metric] = self.send(metric) unless
38
+ Rack::ActionLogger.configuration.rack_request_blacklist.include? metric
39
+ result
40
+ end
41
+ end
42
+
43
+ def path
44
+ @request.path
45
+ end
46
+
47
+ def method
48
+ @request.request_method
49
+ end
50
+
51
+ def params
52
+ Rack::ActionLogger::ParameterFiltering.apply_filter(@request.params, @compiled_filters)
53
+ end
54
+
55
+ def request_headers
56
+ @env.select { |v| v.start_with? 'HTTP_' }
57
+ end
58
+
59
+ def remote_ip
60
+ @request.ip
61
+ end
62
+
63
+ def user_agent
64
+ @request.user_agent
65
+ end
66
+
67
+ def device
68
+ @ua[:category]
69
+ end
70
+
71
+ def os
72
+ @ua[:os]
73
+ end
74
+
75
+ def browser
76
+ @ua[:name]
77
+ end
78
+
79
+ def browser_version
80
+ @ua[:version]
81
+ end
82
+
83
+ def request_id
84
+ @env['action_dispatch.request_id']
85
+ end
86
+
87
+ def response_headers
88
+ @headers
89
+ end
90
+
91
+ def response_json_body
92
+ response_bodies = []
93
+ @body.each { |part| response_bodies << part } if @body
94
+ result = JSON.parse(response_bodies.join('')) rescue {}
95
+ Rack::ActionLogger::ParameterFiltering.apply_filter(result, @compiled_filters)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,10 @@
1
+ require 'active_support'
2
+
3
+ module Rack::ActionLogger
4
+ module Metrics
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :RackMetrics
8
+ end
9
+ end
10
+
@@ -0,0 +1,31 @@
1
+ module Rack::ActionLogger
2
+ module ParameterFiltering
3
+ FILTERED = '[FILTERED]'.freeze # :nodoc:
4
+
5
+ class << self
6
+
7
+ def apply_filter(original_params, compiled_filters)
8
+ filtered_params = {}
9
+
10
+ original_params.each do |key, value|
11
+ if compiled_filters.any? { |r| key =~ r }
12
+ value = FILTERED
13
+ elsif value.is_a?(Hash)
14
+ value = apply_filter(value, compiled_filters)
15
+ elsif value.is_a?(Array)
16
+ value = value.map { |v| v.is_a?(Hash) ? apply_filter(v, compiled_filters) : v }
17
+ end
18
+
19
+ filtered_params[key] = value
20
+ end
21
+
22
+ filtered_params
23
+ end
24
+
25
+ def compile(filters)
26
+ filter_strings = filters.map(&:to_s)
27
+ filter_strings.map { |item| Regexp.compile(Regexp.escape(item)) }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  module ActionLogger
3
- VERSION = '0.1.1'
3
+ VERSION = '0.1.2'
4
4
  end
5
5
  end
@@ -25,4 +25,6 @@ module Rack::ActionLogger
25
25
  autoload :Emitter, 'rack/action_logger/emitter'
26
26
  autoload :ControllerConcerns, 'rack/action_logger/controller_concerns'
27
27
  autoload :EmitAdapter, 'rack/action_logger/emit_adapter'
28
+ autoload :ParameterFiltering, 'rack/action_logger/parameter_filtering'
29
+ autoload :Metrics, 'rack/action_logger/metrics'
28
30
  end
@@ -6,9 +6,12 @@ require 'rack/action_logger/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'rack-action_logger'
8
8
  spec.version = Rack::ActionLogger::VERSION
9
+ spec.required_ruby_version = '>= 2.0.0'
10
+ spec.required_rubygems_version = '>= 1.3.5'
11
+ spec.rubygems_version = Gem::VERSION
9
12
  spec.authors = ['Koichi Ishida']
10
13
  spec.email = ['wapa5pow@gmail.com']
11
-
14
+ spec.date = Time.now.strftime('%Y-%m-%d')
12
15
  spec.summary = 'Rack::ActionLogger is a tool to log user activity'
13
16
  spec.description = 'Rack::ActionLogger is a tool to log user activity'
14
17
  spec.homepage = 'https://github.com/wapa5pow/rack-action_logger'
@@ -23,8 +26,10 @@ Gem::Specification.new do |spec|
23
26
 
24
27
  spec.add_dependency 'activesupport'
25
28
  spec.add_dependency 'fluent-logger', '~> 0.5'
29
+ spec.add_dependency 'woothee', '~> 1.4'
26
30
 
27
31
  spec.add_development_dependency 'bundler', '~> 1.13'
28
32
  spec.add_development_dependency 'rake', '~> 10.0'
29
33
  spec.add_development_dependency 'rspec', '~> 3.0'
34
+ spec.add_development_dependency 'rack-test', '~> 0.6.3'
30
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-action_logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koichi Ishida
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-16 00:00:00.000000000 Z
11
+ date: 2016-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: woothee
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.4'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,20 @@ dependencies:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
96
  version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rack-test
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.6.3
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.6.3
83
111
  description: Rack::ActionLogger is a tool to log user activity
84
112
  email:
85
113
  - wapa5pow@gmail.com
@@ -104,13 +132,15 @@ files:
104
132
  - lib/rack/action_logger/container.rb
105
133
  - lib/rack/action_logger/context.rb
106
134
  - lib/rack/action_logger/controller_concerns.rb
107
- - lib/rack/action_logger/controller_concerns/request_log.rb
108
135
  - lib/rack/action_logger/emit_adapter.rb
109
136
  - lib/rack/action_logger/emit_adapter/base.rb
110
137
  - lib/rack/action_logger/emit_adapter/fluent_adapter.rb
111
138
  - lib/rack/action_logger/emit_adapter/logger_adapter.rb
112
139
  - lib/rack/action_logger/emit_adapter/null_adapter.rb
113
140
  - lib/rack/action_logger/emitter.rb
141
+ - lib/rack/action_logger/metrics.rb
142
+ - lib/rack/action_logger/metrics/rack_metrics.rb
143
+ - lib/rack/action_logger/parameter_filtering.rb
114
144
  - lib/rack/action_logger/version.rb
115
145
  - rack-action_logger.gemspec
116
146
  homepage: https://github.com/wapa5pow/rack-action_logger
@@ -125,12 +155,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
155
  requirements:
126
156
  - - ">="
127
157
  - !ruby/object:Gem::Version
128
- version: '0'
158
+ version: 2.0.0
129
159
  required_rubygems_version: !ruby/object:Gem::Requirement
130
160
  requirements:
131
161
  - - ">="
132
162
  - !ruby/object:Gem::Version
133
- version: '0'
163
+ version: 1.3.5
134
164
  requirements: []
135
165
  rubyforge_project:
136
166
  rubygems_version: 2.6.7
@@ -1,18 +0,0 @@
1
- require 'rack/action_logger/container'
2
-
3
- module Rack::ActionLogger::ControllerConcerns
4
- module RequestLog
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- before_action :set_request_log
9
- end
10
-
11
- def set_request_log
12
- Rack::ActionLogger::Container.set_request_log({ path_info: request.path_info, request_method: request.request_method }, 'action.request')
13
-
14
- request_id = Rails::VERSION::MAJOR >= 5 ? request.request_id : request.uuid
15
- Rack::ActionLogger::Container.merge_attributes({ request_id: request_id })
16
- end
17
- end
18
- end