logstasher 0.7.1 → 0.8.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: 6a404ae100e8f031a1c09e559a953cba145d42f3
4
- data.tar.gz: f9e819702e979195dd35c9db988f0d8958b0be23
3
+ metadata.gz: bdbb1f20cf68e8fbe11c54a8f036a4306e3ea298
4
+ data.tar.gz: 13fe5a49bece9ce24864711ab9998e02305d9490
5
5
  SHA512:
6
- metadata.gz: ac8b1f8298cfda5d3b36d5d7b3f584c4041729d157a70319a4809b36ddc5efc85a6eec7c6634888c99b97f8004bb9a642a1c92859a121379f160583f0bb258b2
7
- data.tar.gz: 13bb64bf2662c52248fb24a9bbce296960d29dfefa8e5e5203f93e0f9ed75f874651c8a2f2da1f7c035529b6226acddb80754146b63ecef42e1e1f263f0d45d0
6
+ metadata.gz: d6e0170213a368025a4ec1bc04ce682ed31827006288c28f003cfa469945706017f189f353e35e72310bdc7a78807049b9e4dca38fa0cd80396a7568f1b72176
7
+ data.tar.gz: d36293ed895eac912267708acb408e30815793689cb9f8ef4be78e4c6808ee58e3ef31f6ace71bce7aed61b91ff5735fc650a37a3fd8475f8c0433b07372f9e3
data/lib/logstasher.rb CHANGED
@@ -1,5 +1,9 @@
1
1
  require 'logstasher/version'
2
- require 'logstasher/log_subscriber'
2
+ require 'logstasher/active_support/log_subscriber'
3
+ require 'logstasher/active_support/mailer_log_subscriber'
4
+ require 'logstasher/active_record/log_subscriber'
5
+ require 'logstasher/action_view/log_subscriber'
6
+ require 'logstasher/rails_ext/action_controller/base'
3
7
  require 'request_store'
4
8
  require 'active_support/core_ext/module/attribute_accessors'
5
9
  require 'active_support/core_ext/string/inflections'
@@ -10,14 +14,15 @@ module LogStasher
10
14
  STORE_KEY = :logstasher_data
11
15
  REQUEST_CONTEXT_KEY = :logstasher_request_context
12
16
 
13
- attr_accessor :logger, :logger_path, :enabled, :log_controller_parameters, :source, :backtrace
17
+ attr_accessor :logger, :logger_path, :enabled, :log_controller_parameters, :source, :backtrace,
18
+ :delayed_jobs_support, :controller_monkey_patch
14
19
  # Setting the default to 'unknown' to define the default behaviour
15
20
  @source = 'unknown'
16
21
  # By default log the backtrace of exceptions
17
22
  @backtrace = true
18
23
 
19
24
  def remove_existing_log_subscriptions
20
- ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
25
+ ::ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
21
26
  case subscriber.class.name
22
27
  when 'ActionView::LogSubscriber'
23
28
  unsubscribe(:action_view, subscriber)
@@ -32,9 +37,9 @@ module LogStasher
32
37
  def unsubscribe(component, subscriber)
33
38
  events = subscriber.public_methods(false).reject{ |method| method.to_s == 'call' }
34
39
  events.each do |event|
35
- ActiveSupport::Notifications.notifier.listeners_for("#{event}.#{component}").each do |listener|
40
+ ::ActiveSupport::Notifications.notifier.listeners_for("#{event}.#{component}").each do |listener|
36
41
  if listener.instance_variable_get('@delegate') == subscriber
37
- ActiveSupport::Notifications.unsubscribe listener
42
+ ::ActiveSupport::Notifications.unsubscribe listener
38
43
  end
39
44
  end
40
45
  end
@@ -46,7 +51,7 @@ module LogStasher
46
51
  payload[:request_id] = request.env['action_dispatch.request_id']
47
52
  self.custom_fields += [:ip, :route, :request_id]
48
53
  if self.log_controller_parameters
49
- payload[:parameters] = payload[:params].except(*ActionController::LogSubscriber::INTERNAL_PARAMS)
54
+ payload[:parameters] = payload[:params].except(*::ActionController::LogSubscriber::INTERNAL_PARAMS)
50
55
  self.custom_fields += [:parameters]
51
56
  end
52
57
  end
@@ -56,8 +61,8 @@ module LogStasher
56
61
  LogStasher.custom_fields.concat(LogStasher.store.keys)
57
62
  instance_exec(fields, &block)
58
63
  end
59
- ActionController::Metal.send(:define_method, :logtasher_add_custom_fields_to_payload, &wrapped_block)
60
- ActionController::Base.send(:define_method, :logtasher_add_custom_fields_to_payload, &wrapped_block)
64
+ ::ActionController::Metal.send(:define_method, :logtasher_add_custom_fields_to_payload, &wrapped_block)
65
+ ::ActionController::Base.send(:define_method, :logtasher_add_custom_fields_to_payload, &wrapped_block)
61
66
  end
62
67
 
63
68
  def add_custom_fields_to_request_context(&block)
@@ -65,8 +70,8 @@ module LogStasher
65
70
  instance_exec(fields, &block)
66
71
  LogStasher.custom_fields.concat(fields.keys)
67
72
  end
68
- ActionController::Metal.send(:define_method, :logstasher_add_custom_fields_to_request_context, &wrapped_block)
69
- ActionController::Base.send(:define_method, :logstasher_add_custom_fields_to_request_context, &wrapped_block)
73
+ ::ActionController::Metal.send(:define_method, :logstasher_add_custom_fields_to_request_context, &wrapped_block)
74
+ ::ActionController::Base.send(:define_method, :logstasher_add_custom_fields_to_request_context, &wrapped_block)
70
75
  end
71
76
 
72
77
  def add_default_fields_to_request_context(request)
@@ -77,33 +82,65 @@ module LogStasher
77
82
  request_context.clear
78
83
  end
79
84
 
80
- def setup(app)
81
- app.config.action_dispatch.rack_cache[:verbose] = false if app.config.action_dispatch.rack_cache
82
- # Path instrumentation class to insert our hook
83
- require 'logstasher/rails_ext/action_controller/metal/instrumentation'
85
+ def setup_before(config)
84
86
  require 'logstash-event'
85
- self.suppress_app_logs(app)
86
- LogStasher::RequestLogSubscriber.attach_to :action_controller
87
- LogStasher::MailerLogSubscriber.attach_to :action_mailer
88
- self.logger_path = app.config.logstasher.logger_path || "#{Rails.root}/log/logstash_#{Rails.env}.log"
89
- self.logger = app.config.logstasher.logger || new_logger(self.logger_path)
90
- self.logger.level = app.config.logstasher.log_level || Logger::WARN
91
- self.source = app.config.logstasher.source unless app.config.logstasher.source.nil?
92
- self.enabled = true
93
- self.log_controller_parameters = !! app.config.logstasher.log_controller_parameters
94
- self.backtrace = !! app.config.logstasher.backtrace unless app.config.logstasher.backtrace.nil?
95
- end
96
-
97
- def suppress_app_logs(app)
98
- if configured_to_suppress_app_logs?(app)
87
+ self.enabled = config.enabled
88
+ LogStasher::ActiveSupport::LogSubscriber.attach_to :action_controller
89
+ LogStasher::ActiveSupport::MailerLogSubscriber.attach_to :action_mailer
90
+ LogStasher::ActiveRecord::LogSubscriber.attach_to :active_record
91
+ LogStasher::ActionView::LogSubscriber.attach_to :action_view
92
+ end
93
+
94
+ def setup(config)
95
+ # Path instrumentation class to insert our hook
96
+ if (! config.controller_monkey_patch && config.controller_monkey_patch != false) || config.controller_monkey_patch == true
97
+ require 'logstasher/rails_ext/action_controller/metal/instrumentation'
98
+ end
99
+ self.delayed_plugin(config)
100
+ self.suppress_app_logs(config)
101
+ self.logger_path = config.logger_path || "#{Rails.root}/log/logstash_#{Rails.env}.log"
102
+ self.logger = config.logger || new_logger(self.logger_path)
103
+ self.logger.level = config.log_level || Logger::WARN
104
+ self.source = config.source unless config.source.nil?
105
+ self.log_controller_parameters = !! config.log_controller_parameters
106
+ self.backtrace = !! config.backtrace unless config.backtrace.nil?
107
+ self.set_data_for_rake
108
+ self.set_data_for_console
109
+ end
110
+
111
+ def set_data_for_rake
112
+ self.request_context['request_id'] = ::Rake.application.top_level_tasks if self.called_as_rake?
113
+ end
114
+
115
+ def set_data_for_console
116
+ self.request_context['request_id'] = "#{Process.pid}" if self.called_as_console?
117
+ end
118
+
119
+ def called_as_rake?
120
+ File.basename($0) == 'rake'
121
+ end
122
+
123
+ def called_as_console?
124
+ defined?(Rails::Console) && true || false
125
+ end
126
+
127
+ def delayed_plugin(config)
128
+ if config.delayed_jobs_support || false
129
+ require 'logstasher/delayed/plugin'
130
+ ::Delayed::Worker.plugins << ::LogStasher::Delayed::Plugin
131
+ end
132
+ end
133
+
134
+ def suppress_app_logs(config)
135
+ if configured_to_suppress_app_logs?(config)
99
136
  require 'logstasher/rails_ext/rack/logger'
100
137
  LogStasher.remove_existing_log_subscriptions
101
138
  end
102
139
  end
103
140
 
104
- def configured_to_suppress_app_logs?(app)
141
+ def configured_to_suppress_app_logs?(config)
105
142
  # This supports both spellings: "suppress_app_log" and "supress_app_log"
106
- !!(app.config.logstasher.suppress_app_log.nil? ? app.config.logstasher.supress_app_log : app.config.logstasher.suppress_app_log)
143
+ !!(config.suppress_app_log.nil? ? config.supress_app_log : config.suppress_app_log)
107
144
  end
108
145
 
109
146
  def custom_fields
@@ -127,7 +164,7 @@ module LogStasher
127
164
  end
128
165
 
129
166
  def build_logstash_event(data, tags)
130
- LogStash::Event.new(data.merge('source' => self.source, 'tags' => tags))
167
+ ::LogStash::Event.new(data.merge('source' => self.source, 'tags' => tags))
131
168
  end
132
169
 
133
170
  def store
@@ -144,7 +181,7 @@ module LogStasher
144
181
 
145
182
  def watch(event, opts = {}, &block)
146
183
  event_group = opts[:event_group] || event
147
- ActiveSupport::Notifications.subscribe(event) do |*args|
184
+ ::ActiveSupport::Notifications.subscribe(event) do |*args|
148
185
  # Calling the processing block with the Notification args and the store
149
186
  block.call(*args, store[event_group])
150
187
  end
@@ -159,7 +196,7 @@ module LogStasher
159
196
  end
160
197
 
161
198
  def enabled?
162
- self.enabled
199
+ self.enabled || false
163
200
  end
164
201
 
165
202
  private
@@ -0,0 +1,70 @@
1
+ require 'active_support/notifications'
2
+ require 'action_view/log_subscriber'
3
+
4
+ module LogStasher
5
+ module ActionView
6
+ class LogSubscriber < ::ActionView::LogSubscriber
7
+ def render_template(event)
8
+ logstash_event(event)
9
+ end
10
+ alias :render_partial :render_template
11
+ alias :render_collection :render_template
12
+
13
+ def logger
14
+ LogStasher.logger
15
+ end
16
+
17
+ private
18
+
19
+ def logstash_event(event)
20
+ data = event.payload
21
+
22
+ data.merge! event_data(event)
23
+ data.merge! runtimes(event)
24
+ data.merge! extract_data(data)
25
+ data.merge! request_context
26
+ # data.merge! store
27
+ data.merge! extract_custom_fields(data)
28
+
29
+ tags = []
30
+ tags.push('exception') if data[:exception]
31
+ logger << LogStasher.build_logstash_event(data, tags).to_json + "\n"
32
+ end
33
+
34
+ def extract_data(data)
35
+ { identifier: from_rails_root(data[:identifier]) }
36
+ end
37
+
38
+ def request_context
39
+ LogStasher.request_context
40
+ end
41
+
42
+ def store
43
+ LogStasher.store
44
+ end
45
+
46
+ def event_data(event)
47
+ {
48
+ name: event.name,
49
+ transaction_id: event.transaction_id,
50
+ }
51
+ end
52
+
53
+ def runtimes(event)
54
+ {
55
+ duration: event.duration,
56
+ }.inject({}) do |runtimes, (name, runtime)|
57
+ runtimes[name] = runtime.to_f.round(2) if runtime
58
+ runtimes
59
+ end
60
+
61
+ end
62
+
63
+ def extract_custom_fields(data)
64
+ custom_fields = (!LogStasher.custom_fields.empty? && data.extract!(*LogStasher.custom_fields)) || {}
65
+ LogStasher.custom_fields.clear
66
+ custom_fields
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,59 @@
1
+ require 'active_support/notifications'
2
+ require 'active_record/log_subscriber'
3
+
4
+ module LogStasher
5
+ module ActiveRecord
6
+ class LogSubscriber < ::ActiveRecord::LogSubscriber
7
+ def identity(event)
8
+ if logger
9
+ logger << logstash_event(event).to_json + "\n"
10
+ end
11
+ end
12
+ alias :sql :identity
13
+
14
+ def logger
15
+ LogStasher.logger
16
+ end
17
+
18
+ private
19
+
20
+ def logstash_event(event)
21
+ data = event.payload
22
+
23
+ return unless logger.debug?
24
+ return if 'SCHEMA' == data[:name]
25
+
26
+ data.merge! runtimes(event)
27
+ data.merge! extract_sql(data)
28
+ data.merge! request_context
29
+ data.merge! extract_custom_fields(data)
30
+
31
+ tags = ['request']
32
+ tags.push('exception') if payload[:exception]
33
+ LogStasher.build_logstash_event(data, tags)
34
+ end
35
+
36
+ def request_context
37
+ LogStasher.request_context
38
+ end
39
+
40
+ def runtimes(event)
41
+ if event.duration
42
+ { duration: event.duration.to_f.round(2) }
43
+ else
44
+ { }
45
+ end
46
+ end
47
+
48
+ def extract_sql(data)
49
+ { sql: data[:sql].squeeze(' ') }
50
+ end
51
+
52
+ def extract_custom_fields(data)
53
+ custom_fields = (!LogStasher.custom_fields.empty? && data.extract!(*LogStasher.custom_fields)) || {}
54
+ LogStasher.custom_fields.clear
55
+ custom_fields
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,106 @@
1
+ require 'active_support/core_ext/class/attribute'
2
+ require 'active_support/log_subscriber'
3
+
4
+ module LogStasher
5
+ module ActiveSupport
6
+ class LogSubscriber < ::ActiveSupport::LogSubscriber
7
+ def process_action(event)
8
+ payload = event.payload
9
+
10
+ data = extract_request(payload)
11
+ data.merge! extract_status(payload)
12
+ data.merge! runtimes(event)
13
+ data.merge! location(event)
14
+ data.merge! extract_exception(payload)
15
+ data.merge! extract_custom_fields(payload)
16
+
17
+ tags = ['request']
18
+ tags.push('exception') if payload[:exception]
19
+ logger << LogStasher.build_logstash_event(data, tags).to_json + "\n"
20
+ end
21
+
22
+ def redirect_to(event)
23
+ Thread.current[:logstasher_location] = event.payload[:location]
24
+ end
25
+
26
+ def logger
27
+ LogStasher.logger
28
+ end
29
+
30
+ private
31
+
32
+ def extract_request(payload)
33
+ {
34
+ method: payload[:method],
35
+ path: extract_path(payload),
36
+ format: extract_format(payload),
37
+ controller: payload[:params]['controller'],
38
+ action: payload[:params]['action']
39
+ }
40
+ end
41
+
42
+ def extract_path(payload)
43
+ payload[:path].split("?").first
44
+ end
45
+
46
+ def extract_format(payload)
47
+ if ::ActionPack::VERSION::MAJOR == 3 && ::ActionPack::VERSION::MINOR == 0
48
+ payload[:formats].first
49
+ else
50
+ payload[:format]
51
+ end
52
+ end
53
+
54
+ def extract_status(payload)
55
+ if payload[:status]
56
+ { :status => payload[:status].to_i }
57
+ else
58
+ { :status => 0 }
59
+ end
60
+ end
61
+
62
+ def runtimes(event)
63
+ {
64
+ :duration => event.duration,
65
+ :view => event.payload[:view_runtime],
66
+ :db => event.payload[:db_runtime]
67
+ }.inject({}) do |runtimes, (name, runtime)|
68
+ runtimes[name] = runtime.to_f.round(2) if runtime
69
+ runtimes
70
+ end
71
+ end
72
+
73
+ def location(event)
74
+ if location = Thread.current[:logstasher_location]
75
+ Thread.current[:logstasher_location] = nil
76
+ { :location => location }
77
+ else
78
+ {}
79
+ end
80
+ end
81
+
82
+ # Monkey patching to enable exception logging
83
+ def extract_exception(payload)
84
+ if payload[:exception]
85
+ exception, message = payload[:exception]
86
+ status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception)
87
+ if LogStasher.backtrace
88
+ backtrace = $!.backtrace.join("\n")
89
+ else
90
+ backtrace = $!.backtrace.first
91
+ end
92
+ message = "#{exception}\n#{message}\n#{backtrace}"
93
+ { :status => status, :error => message }
94
+ else
95
+ {}
96
+ end
97
+ end
98
+
99
+ def extract_custom_fields(payload)
100
+ custom_fields = (!LogStasher.custom_fields.empty? && payload.extract!(*LogStasher.custom_fields)) || {}
101
+ LogStasher.custom_fields.clear
102
+ custom_fields
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,37 @@
1
+ require 'active_support/core_ext/class/attribute'
2
+ require 'active_support/log_subscriber'
3
+
4
+ module LogStasher
5
+ module ActiveSupport
6
+ class MailerLogSubscriber < ::ActiveSupport::LogSubscriber
7
+ MAILER_FIELDS = [:mailer, :action, :message_id, :from, :to]
8
+
9
+ def deliver(event)
10
+ process_event(event, ['mailer', 'deliver'])
11
+ end
12
+
13
+ def receive(event)
14
+ process_event(event, ['mailer', 'receive'])
15
+ end
16
+
17
+ def process(event)
18
+ process_event(event, ['mailer', 'process'])
19
+ end
20
+
21
+ def logger
22
+ LogStasher.logger
23
+ end
24
+
25
+ private
26
+
27
+ def process_event(event, tags)
28
+ data = LogStasher.request_context.merge(extract_metadata(event.payload))
29
+ logger << LogStasher.build_logstash_event(data, tags).to_json + "\n"
30
+ end
31
+
32
+ def extract_metadata(payload)
33
+ payload.slice(*MAILER_FIELDS)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,16 @@
1
+ require 'delayed_job'
2
+ module LogStasher
3
+ module Delayed
4
+ class Plugin < ::Delayed::Plugin
5
+ callbacks do |lifecycle|
6
+ lifecycle.before(:invoke_job) do |job, *args, &block|
7
+ ::LogStasher.request_context[:request_id] = job.id
8
+ # perhaps handler#object.first_line and method_name would be interesting too (in store??)
9
+ end
10
+ lifecycle.after(:invoke_job) do |job, *args, &block|
11
+ ::LogStasher.request_context[:request_id] = nil
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,48 @@
1
+ module LogStasher
2
+ module ActionController
3
+ module Instrumentation
4
+ def process_action(*args)
5
+ add_custom_fields_to_store
6
+ LogStasher.clear_request_context
7
+ LogStasher.add_default_fields_to_request_context(request)
8
+
9
+ super(*args)
10
+ end
11
+
12
+ private
13
+
14
+ # this method is called from within super of process_action.
15
+ def append_info_to_payload(payload) #:nodoc:
16
+ LogStasher.add_default_fields_to_payload(payload, request)
17
+ if self.respond_to?(:logstasher_add_custom_fields_to_request_context)
18
+ logstasher_add_custom_fields_to_request_context(LogStasher.request_context)
19
+ end
20
+
21
+ if self.respond_to?(:logtasher_add_custom_fields_to_payload)
22
+ before_keys = payload.keys.clone
23
+ logtasher_add_custom_fields_to_payload(payload)
24
+ after_keys = payload.keys
25
+ # Store all extra keys added to payload hash in payload itself. This is a thread safe way
26
+ LogStasher.custom_fields += after_keys - before_keys
27
+ end
28
+
29
+ payload[:status] = response.status
30
+ super(payload)
31
+
32
+ LogStasher.store.each do |key, value|
33
+ payload[key] = value
34
+ end
35
+
36
+ LogStasher.request_context.each do |key, value|
37
+ payload[key] = value
38
+ end
39
+ end
40
+
41
+ def add_custom_fields_to_store
42
+ LogStasher.store[:ip] = request.remote_ip
43
+ LogStasher.store[:route] = "#{request.params[:controller]}##{request.params[:action]}"
44
+ LogStasher.request_context[:request_id] = request.env['action_dispatch.request_id']
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,5 +1,6 @@
1
1
  module ActionController
2
2
  module Instrumentation
3
+ alias :orig_process_action :process_action
3
4
  def process_action(*args)
4
5
  raw_payload = {
5
6
  :controller => self.class.name,
@@ -44,6 +45,7 @@ module ActionController
44
45
  result
45
46
  end
46
47
  end
48
+ alias :logstasher_process_action :process_action
47
49
 
48
50
  end
49
51
  end
@@ -4,11 +4,18 @@ require 'action_controller/log_subscriber'
4
4
 
5
5
  module LogStasher
6
6
  class Railtie < Rails::Railtie
7
- config.logstasher = ActiveSupport::OrderedOptions.new
7
+ config.logstasher = ::ActiveSupport::OrderedOptions.new
8
8
  config.logstasher.enabled = false
9
9
 
10
10
  initializer :logstasher, :before => :load_config_initializers do |app|
11
- LogStasher.setup(app) if app.config.logstasher.enabled
11
+ app.config.action_dispatch.rack_cache[:verbose] = false if app.config.action_dispatch.rack_cache
12
+ LogStasher.setup_before(app.config.logstasher) if app.config.logstasher.enabled
13
+ end
14
+
15
+ initializer :logstasher do
16
+ config.after_initialize do
17
+ LogStasher.setup(config.logstasher) if config.logstasher.enabled
18
+ end
12
19
  end
13
20
  end
14
21
  end
@@ -1,3 +1,3 @@
1
1
  module LogStasher
2
- VERSION = "0.7.1"
2
+ VERSION = "0.8.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstasher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shadab Ahmed
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-22 00:00:00.000000000 Z
11
+ date: 2015-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logstash-event
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: delayed_job
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 4.0.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 4.0.2
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: request_store
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - ">="
53
67
  - !ruby/object:Gem::Version
54
68
  version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: activerecord
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: rspec
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -102,8 +130,13 @@ extensions: []
102
130
  extra_rdoc_files: []
103
131
  files:
104
132
  - lib/logstasher.rb
133
+ - lib/logstasher/action_view/log_subscriber.rb
134
+ - lib/logstasher/active_record/log_subscriber.rb
135
+ - lib/logstasher/active_support/log_subscriber.rb
136
+ - lib/logstasher/active_support/mailer_log_subscriber.rb
137
+ - lib/logstasher/delayed/plugin.rb
105
138
  - lib/logstasher/device/redis.rb
106
- - lib/logstasher/log_subscriber.rb
139
+ - lib/logstasher/rails_ext/action_controller/base.rb
107
140
  - lib/logstasher/rails_ext/action_controller/metal/instrumentation.rb
108
141
  - lib/logstasher/rails_ext/rack/logger.rb
109
142
  - lib/logstasher/railtie.rb
@@ -1,132 +0,0 @@
1
- require 'active_support/core_ext/class/attribute'
2
- require 'active_support/log_subscriber'
3
-
4
- module LogStasher
5
- class RequestLogSubscriber < ActiveSupport::LogSubscriber
6
- def process_action(event)
7
- payload = event.payload
8
-
9
- data = extract_request(payload)
10
- data.merge! extract_status(payload)
11
- data.merge! runtimes(event)
12
- data.merge! location(event)
13
- data.merge! extract_exception(payload)
14
- data.merge! extract_custom_fields(payload)
15
-
16
- tags = ['request']
17
- tags.push('exception') if payload[:exception]
18
-
19
- LogStasher.logger << LogStasher.build_logstash_event(data, tags).to_json + "\n"
20
- end
21
-
22
- def redirect_to(event)
23
- Thread.current[:logstasher_location] = event.payload[:location]
24
- end
25
-
26
- private
27
-
28
- def extract_request(payload)
29
- {
30
- :method => payload[:method],
31
- :path => extract_path(payload),
32
- :format => extract_format(payload),
33
- :controller => payload[:params]['controller'],
34
- :action => payload[:params]['action']
35
- }
36
- end
37
-
38
- def extract_path(payload)
39
- payload[:path].split("?").first
40
- end
41
-
42
- def extract_format(payload)
43
- if ::ActionPack::VERSION::MAJOR == 3 && ::ActionPack::VERSION::MINOR == 0
44
- payload[:formats].first
45
- else
46
- payload[:format]
47
- end
48
- end
49
-
50
- def extract_status(payload)
51
- if payload[:status]
52
- { :status => payload[:status].to_i }
53
- else
54
- { :status => 0 }
55
- end
56
- end
57
-
58
- def runtimes(event)
59
- {
60
- :duration => event.duration,
61
- :view => event.payload[:view_runtime],
62
- :db => event.payload[:db_runtime]
63
- }.inject({}) do |runtimes, (name, runtime)|
64
- runtimes[name] = runtime.to_f.round(2) if runtime
65
- runtimes
66
- end
67
- end
68
-
69
- def location(event)
70
- if location = Thread.current[:logstasher_location]
71
- Thread.current[:logstasher_location] = nil
72
- { :location => location }
73
- else
74
- {}
75
- end
76
- end
77
-
78
- # Monkey patching to enable exception logging
79
- def extract_exception(payload)
80
- if payload[:exception]
81
- exception, message = payload[:exception]
82
- status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception)
83
- if LogStasher.backtrace
84
- backtrace = $!.backtrace.join("\n")
85
- else
86
- backtrace = $!.backtrace.first
87
- end
88
- message = "#{exception}\n#{message}\n#{backtrace}"
89
- { :status => status, :error => message }
90
- else
91
- {}
92
- end
93
- end
94
-
95
- def extract_custom_fields(payload)
96
- custom_fields = (!LogStasher.custom_fields.empty? && payload.extract!(*LogStasher.custom_fields)) || {}
97
- LogStasher.custom_fields.clear
98
- custom_fields
99
- end
100
- end
101
-
102
- class MailerLogSubscriber < ActiveSupport::LogSubscriber
103
- MAILER_FIELDS = [:mailer, :action, :message_id, :from, :to]
104
-
105
- def deliver(event)
106
- process_event(event, ['mailer', 'deliver'])
107
- end
108
-
109
- def receive(event)
110
- process_event(event, ['mailer', 'receive'])
111
- end
112
-
113
- def process(event)
114
- process_event(event, ['mailer', 'process'])
115
- end
116
-
117
- def logger
118
- LogStasher.logger
119
- end
120
-
121
- private
122
-
123
- def process_event(event, tags)
124
- data = LogStasher.request_context.merge(extract_metadata(event.payload))
125
- logger << LogStasher.build_logstash_event(data, tags).to_json + "\n"
126
- end
127
-
128
- def extract_metadata(payload)
129
- payload.slice(*MAILER_FIELDS)
130
- end
131
- end
132
- end