logstasher 0.7.1 → 0.8.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 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