detail_parser 0.1.4 → 0.1.6
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/README.md +30 -2
- data/detail_parser.gemspec +0 -1
- data/lib/detail_parser.rb +53 -13
- data/lib/detail_parser/formatters/json.rb +10 -0
- data/lib/detail_parser/log_subscriber.rb +112 -0
- data/lib/detail_parser/railtie.rb +3 -6
- data/lib/detail_parser/version.rb +1 -1
- data/lib/generators/templates/detail_parser.rb +28 -0
- metadata +4 -17
- data/lib/detail_parser/logger.rb +0 -77
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ecc2873defe2bafcd5ff9b8bcf6d28eae5bec1cd
|
4
|
+
data.tar.gz: c03868e6c7ae52de8ead1759fca9fb02e37d77e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b659f3f708f90d2d0d194a7920df436db8f0b23a41b9bf9da4db84fefa627b082998ad27ab566f7a5c5294b81d2ea929825340d9397327595907869185d9600
|
7
|
+
data.tar.gz: b927ead95370548c07a508ad0b032a2235fef6deb27fbb892eb56f032e84d69f8b1135a8d88c4992ee9bb4a0a2742bf1d6f141c5651af0222950ba83daaa6533
|
data/README.md
CHANGED
@@ -20,9 +20,38 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
$ gem install detail_parser
|
22
22
|
|
23
|
+
Next to config, To run
|
24
|
+
|
25
|
+
$ rails g detail_parser:install
|
26
|
+
|
27
|
+
That will create file in `config/initializers/detail_parser.rb`
|
28
|
+
|
23
29
|
## Usage
|
24
30
|
|
25
|
-
|
31
|
+
- 默认是开启detail_parser的模式,可以通过配置文件来关闭
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
config.detail_parser.enabled = false
|
35
|
+
```
|
36
|
+
|
37
|
+
- 默认的日志等级是 `:info`,可以通过配置文件修改
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
DetailParser.log_level = :debug
|
41
|
+
```
|
42
|
+
|
43
|
+
- 默认是关闭了rails自身的Log输出,如需开启,需要进行如下配置
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
config.detail_parser.keep_original_log = true
|
47
|
+
```
|
48
|
+
|
49
|
+
- 默认的请求用户是开启的,但是内容被注释了.这个可以根据自己项目的情况修改.使用的时候去除注释就可以.
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
payload[:current_user] = "User Id #{current_user.id} | User name #{current_user.name}"
|
53
|
+
```
|
54
|
+
|
26
55
|
|
27
56
|
## Development
|
28
57
|
|
@@ -38,4 +67,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERN
|
|
38
67
|
## License
|
39
68
|
|
40
69
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
41
|
-
|
data/detail_parser.gemspec
CHANGED
@@ -33,7 +33,6 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_development_dependency "bundler", "~> 1.14"
|
34
34
|
spec.add_development_dependency "rake", "~> 10.0"
|
35
35
|
spec.add_development_dependency "rspec", "~> 3.0"
|
36
|
-
spec.add_development_dependency "pry"
|
37
36
|
|
38
37
|
spec.add_runtime_dependency 'activesupport', '>= 4', '<= 5.1.0.rc2'
|
39
38
|
spec.add_runtime_dependency 'actionpack', '>= 4', '<= 5.1.0.rc2'
|
data/lib/detail_parser.rb
CHANGED
@@ -1,29 +1,32 @@
|
|
1
1
|
require "detail_parser/version"
|
2
|
-
require "detail_parser/
|
2
|
+
require "detail_parser/log_subscriber"
|
3
3
|
require 'detail_parser/configurable'
|
4
|
+
require 'detail_parser/railtie' if defined?(Rails)
|
5
|
+
require 'detail_parser/formatters/json'
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
7
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
8
|
+
require 'active_support/core_ext/string/inflections'
|
9
|
+
require 'active_support/ordered_options'
|
9
10
|
|
10
11
|
module DetailParser
|
11
12
|
|
12
|
-
|
13
|
+
class << self
|
14
|
+
attr_accessor :logger, :filter, :application
|
15
|
+
end
|
16
|
+
|
13
17
|
# Your code goes here...
|
14
18
|
module_function
|
19
|
+
|
15
20
|
def setup(app)
|
16
|
-
puts "detail_parser setup"
|
17
21
|
self.application = app
|
22
|
+
keep_original_log
|
18
23
|
|
19
|
-
|
20
|
-
|
21
|
-
# support_deprecated_config
|
22
|
-
# set_formatter
|
23
|
-
# set_ignores
|
24
|
-
# Logger.setup
|
24
|
+
attach_to_action_controller
|
25
|
+
set_formatter
|
25
26
|
end
|
26
27
|
|
28
|
+
mattr_accessor :log_level
|
29
|
+
self.log_level = :info
|
27
30
|
|
28
31
|
mattr_writer :before_format
|
29
32
|
self.before_format = nil
|
@@ -35,5 +38,42 @@ module DetailParser
|
|
35
38
|
end
|
36
39
|
|
37
40
|
mattr_accessor :formatter
|
41
|
+
def set_formatter
|
42
|
+
DetailParser.formatter = detail_config.formatter || DetailParser::Formatters::Json.new
|
43
|
+
end
|
44
|
+
|
45
|
+
def keep_original_log
|
46
|
+
return if detail_config.keep_original_log
|
47
|
+
remove_existing_log_subscriptions
|
48
|
+
end
|
49
|
+
|
50
|
+
def remove_existing_log_subscriptions
|
51
|
+
ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
|
52
|
+
case subscriber
|
53
|
+
when ActionController::LogSubscriber
|
54
|
+
unsubscribe(:action_controller, subscriber)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
private_class_method :remove_existing_log_subscriptions
|
59
|
+
|
60
|
+
def unsubscribe(component, subscriber)
|
61
|
+
events = subscriber.public_methods(false).reject { |method| method.to_s == 'call' }
|
62
|
+
events.each do |event|
|
63
|
+
ActiveSupport::Notifications.notifier.listeners_for("#{event}.#{component}").each do |listener|
|
64
|
+
if listener.instance_variable_get('@delegate') == subscriber
|
65
|
+
ActiveSupport::Notifications.unsubscribe listener
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def attach_to_action_controller
|
72
|
+
DetailParser::LogSubscriber.attach_to :action_controller
|
73
|
+
end
|
74
|
+
|
75
|
+
def detail_config
|
76
|
+
application.config.detail_parser
|
77
|
+
end
|
38
78
|
|
39
79
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'action_pack'
|
3
|
+
require 'active_support/core_ext/class/attribute'
|
4
|
+
require 'active_support/log_subscriber'
|
5
|
+
|
6
|
+
# require 'active_support/tagged_logging'
|
7
|
+
|
8
|
+
module DetailParser
|
9
|
+
class LogSubscriber < ActiveSupport::LogSubscriber
|
10
|
+
|
11
|
+
def process_action(event)
|
12
|
+
payload = event.payload
|
13
|
+
request_data = extract_request(event, payload)
|
14
|
+
request_log(request_data)
|
15
|
+
response_log(extract_response(event, payload)) unless html_format?(payload)
|
16
|
+
end
|
17
|
+
|
18
|
+
def request_log(data)
|
19
|
+
logger.send(DetailParser.log_level, data)
|
20
|
+
end
|
21
|
+
|
22
|
+
def response_log(data)
|
23
|
+
logger.send(DetailParser.log_level, data)
|
24
|
+
end
|
25
|
+
|
26
|
+
def start_log(data)
|
27
|
+
logger.send(DetailParser.log_level, data)
|
28
|
+
end
|
29
|
+
|
30
|
+
def logger
|
31
|
+
DetailParser.logger.presence || super
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def extract_request(event, payload)
|
36
|
+
payload = event.payload
|
37
|
+
data = initial_data(payload)
|
38
|
+
data.merge!(extract_status(payload))
|
39
|
+
data.merge!(extract_runtimes(event, payload))
|
40
|
+
data.merge!(extract_userinfo(payload))
|
41
|
+
end
|
42
|
+
|
43
|
+
def extract_response(event, payload)
|
44
|
+
"Response is #{payload[:response].body}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def format_time
|
48
|
+
Time.current.localtime
|
49
|
+
end
|
50
|
+
|
51
|
+
def initial_data(payload)
|
52
|
+
{
|
53
|
+
method: payload[:method],
|
54
|
+
request_id: payload[:request].uuid,
|
55
|
+
path: extract_path(payload),
|
56
|
+
format: extract_format(payload),
|
57
|
+
params: payload[:params]
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def logged_ip
|
62
|
+
Thread.current[:logged_ip]
|
63
|
+
end
|
64
|
+
|
65
|
+
def extract_path(payload)
|
66
|
+
path = payload[:path]
|
67
|
+
index = path.index('?')
|
68
|
+
index ? path[0, index] : path
|
69
|
+
end
|
70
|
+
|
71
|
+
def extract_format(payload)
|
72
|
+
payload[:format]
|
73
|
+
end
|
74
|
+
|
75
|
+
def extract_status(payload)
|
76
|
+
if (status = payload[:status])
|
77
|
+
{ status: status.to_i }
|
78
|
+
elsif (error = payload[:exception])
|
79
|
+
exception, message = error
|
80
|
+
{ status: get_error_status_code(exception), error: "#{exception}: #{message}" }
|
81
|
+
else
|
82
|
+
{ status: 0 }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def extract_runtimes(event, payload)
|
87
|
+
data = { duration: event.duration.to_f.round(2) }
|
88
|
+
data[:Views] = payload[:view_runtime].to_f.round(2) if payload.key?(:view_runtime)
|
89
|
+
data[:DB] = payload[:db_runtime].to_f.round(2) if payload.key?(:db_runtime)
|
90
|
+
data
|
91
|
+
end
|
92
|
+
|
93
|
+
def extract_userinfo(payload)
|
94
|
+
{request_user: payload[:current_user]} if DetailParser.detail_config.current_user
|
95
|
+
end
|
96
|
+
|
97
|
+
def before_format(data, payload)
|
98
|
+
DetailParser.before_format(data, payload)
|
99
|
+
end
|
100
|
+
|
101
|
+
def get_error_status_code(exception)
|
102
|
+
status = ActionDispatch::ExceptionWrapper.rescue_responses[exception]
|
103
|
+
Rack::Utils.status_code(status)
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
def html_format?(payload)
|
108
|
+
payload[:format].to_s == "html"
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
@@ -5,19 +5,16 @@ require 'action_controller/log_subscriber'
|
|
5
5
|
class DetailParser::Railtie < Rails::Railtie
|
6
6
|
env = Rails.env.to_sym || :development
|
7
7
|
|
8
|
-
puts " ====== in Rails railtile"
|
9
8
|
|
10
9
|
config.detail_parser = ActiveSupport::OrderedOptions.new
|
11
10
|
config.detail_parser.enabled = false
|
12
11
|
|
13
|
-
# DetailParser::Logger.logger = Rails.application.config.logger || Rails.logger.presence
|
14
|
-
|
15
12
|
initializer 'detail parser logger', after: :load_config_initializers do
|
16
|
-
DetailParser
|
17
|
-
DetailParser
|
13
|
+
DetailParser.logger = Rails.application.config.logger || Rails.logger.presence
|
14
|
+
DetailParser.filter = ActionDispatch::Http::ParameterFilter.new Rails.application.config.filter_parameters
|
18
15
|
end
|
19
16
|
|
20
17
|
config.after_initialize do |app|
|
21
|
-
DetailParser.setup(app)
|
18
|
+
DetailParser.setup(app) if app.config.detail_parser.enabled
|
22
19
|
end
|
23
20
|
end
|
@@ -1,3 +1,31 @@
|
|
1
1
|
Rails.application.configure do
|
2
2
|
config.detail_parser.enabled = true
|
3
|
+
config.detail_parser.current_user = true
|
4
|
+
end
|
5
|
+
|
6
|
+
|
7
|
+
ActionController::Instrumentation.class_eval do
|
8
|
+
def process_action(*args)
|
9
|
+
raw_payload = {
|
10
|
+
controller: self.class.name,
|
11
|
+
action: self.action_name,
|
12
|
+
params: request.filtered_parameters,
|
13
|
+
format: request.format.try(:ref),
|
14
|
+
method: request.method,
|
15
|
+
path: (request.fullpath rescue "unknown"),
|
16
|
+
request: request,
|
17
|
+
response: response,
|
18
|
+
session: session
|
19
|
+
}
|
20
|
+
|
21
|
+
ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload.dup)
|
22
|
+
|
23
|
+
ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
|
24
|
+
result = super
|
25
|
+
payload[:status] = response.status
|
26
|
+
# payload[:current_user] = "User Id #{current_user.id} | User name #{current_user.name}"
|
27
|
+
append_info_to_payload(payload)
|
28
|
+
result
|
29
|
+
end
|
30
|
+
end
|
3
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: detail_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Issue
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04
|
11
|
+
date: 2017-05-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,20 +52,6 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: pry
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: activesupport
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -146,7 +132,8 @@ files:
|
|
146
132
|
- detail_parser.gemspec
|
147
133
|
- lib/detail_parser.rb
|
148
134
|
- lib/detail_parser/configurable.rb
|
149
|
-
- lib/detail_parser/
|
135
|
+
- lib/detail_parser/formatters/json.rb
|
136
|
+
- lib/detail_parser/log_subscriber.rb
|
150
137
|
- lib/detail_parser/railtie.rb
|
151
138
|
- lib/detail_parser/version.rb
|
152
139
|
- lib/generators/detail_parser/install_generator.rb
|
data/lib/detail_parser/logger.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/class/attribute'
|
2
|
-
require 'active_support/log_subscriber'
|
3
|
-
|
4
|
-
# require 'active_support/tagged_logging'
|
5
|
-
|
6
|
-
module DetailParser
|
7
|
-
class Logger < ActiveSupport::LogSubscriber
|
8
|
-
|
9
|
-
def process_action(event)
|
10
|
-
payload = event.payload
|
11
|
-
data = extract_request(event, payload)
|
12
|
-
data = before_format(data, payload)
|
13
|
-
formatted_message = DetailParser.formatter.call(data)
|
14
|
-
# logger.send(Lograge.log_level, formatted_message)
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.setup(app)
|
18
|
-
self.application = app
|
19
|
-
# Lograge::RequestLogSubscriber.attach_to :action_controller
|
20
|
-
puts "NOTICE: Gem is ok"
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
def extract_request(event, payload)
|
25
|
-
payload = event.payload
|
26
|
-
data = initial_data(payload)
|
27
|
-
data.merge!(extract_status(payload))
|
28
|
-
data.merge!(extract_runtimes(event, payload))
|
29
|
-
# data.merge!(extract_location)
|
30
|
-
# data.merge!(extract_unpermitted_params)
|
31
|
-
# data.merge!(custom_options(event))
|
32
|
-
end
|
33
|
-
|
34
|
-
def initial_data(payload)
|
35
|
-
{
|
36
|
-
method: payload[:method],
|
37
|
-
path: extract_path(payload),
|
38
|
-
format: extract_format(payload),
|
39
|
-
controller: payload[:controller],
|
40
|
-
action: payload[:action]
|
41
|
-
}
|
42
|
-
end
|
43
|
-
|
44
|
-
def extract_path(payload)
|
45
|
-
path = payload[:path]
|
46
|
-
index = path.index('?')
|
47
|
-
index ? path[0, index] : path
|
48
|
-
end
|
49
|
-
|
50
|
-
def extract_format(payload)
|
51
|
-
payload[:format]
|
52
|
-
end
|
53
|
-
|
54
|
-
def extract_status(payload)
|
55
|
-
if (status = payload[:status])
|
56
|
-
{ status: status.to_i }
|
57
|
-
elsif (error = payload[:exception])
|
58
|
-
exception, message = error
|
59
|
-
{ status: get_error_status_code(exception), error: "#{exception}: #{message}" }
|
60
|
-
else
|
61
|
-
{ status: 0 }
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def extract_runtimes(event, payload)
|
66
|
-
data = { duration: event.duration.to_f.round(2) }
|
67
|
-
data[:view] = payload[:view_runtime].to_f.round(2) if payload.key?(:view_runtime)
|
68
|
-
data[:db] = payload[:db_runtime].to_f.round(2) if payload.key?(:db_runtime)
|
69
|
-
data
|
70
|
-
end
|
71
|
-
|
72
|
-
def before_format(data, payload)
|
73
|
-
DetailParser.before_format(data, payload)
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|
77
|
-
end
|