logstasher 1.2.2 → 2.1.5
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 +5 -5
- data/lib/logstasher/action_view/log_subscriber.rb +9 -8
- data/lib/logstasher/active_job/log_subscriber.rb +21 -14
- data/lib/logstasher/active_record/log_subscriber.rb +13 -8
- data/lib/logstasher/active_support/log_subscriber.rb +21 -20
- data/lib/logstasher/active_support/mailer_log_subscriber.rb +12 -5
- data/lib/logstasher/custom_fields.rb +3 -1
- data/lib/logstasher/device/redis.rb +7 -6
- data/lib/logstasher/event.rb +34 -0
- data/lib/logstasher/rails_ext/action_controller/base.rb +6 -4
- data/lib/logstasher/rails_ext/action_controller/metal/instrumentation.rb +18 -12
- data/lib/logstasher/rails_ext/rack/logger.rb +3 -2
- data/lib/logstasher/railtie.rb +28 -17
- data/lib/logstasher/version.rb +3 -1
- data/lib/logstasher.rb +42 -38
- metadata +17 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7af8fd26cf9b944ead0bf8b8b2df3a75aa405ca1e726529e7cccb1a38ae30e8d
|
4
|
+
data.tar.gz: aec3c7b2e41fefcb6f9c8b378c91d332537387685da9951cf741ab4ff2a0d9e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b65801d4d765f1f75f8939ee77e0ac88a5831e126f4428741097bce1b01b2c1ffe90a926aee5617bfe3355c9bfc80825299cfefd9666e52da008a22ad43368f7
|
7
|
+
data.tar.gz: 0d9bc2de4e965343f0ab12241d76e62a3e661b9bafa824cb532ee4df9768562ec83055af0c8462277b62efc8a0afdfc154b940bc38919500ec8a693bfce5009d
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/notifications'
|
2
4
|
require 'action_view/log_subscriber'
|
3
5
|
require 'logstasher/custom_fields'
|
@@ -10,8 +12,8 @@ module LogStasher
|
|
10
12
|
def render_template(event)
|
11
13
|
logstash_event(event)
|
12
14
|
end
|
13
|
-
alias
|
14
|
-
alias
|
15
|
+
alias render_partial render_template
|
16
|
+
alias render_collection render_template
|
15
17
|
|
16
18
|
def logger
|
17
19
|
LogStasher.logger
|
@@ -31,11 +33,11 @@ module LogStasher
|
|
31
33
|
|
32
34
|
tags = []
|
33
35
|
tags.push('exception') if data[:exception]
|
34
|
-
logger << LogStasher.build_logstash_event(data, tags).to_json
|
36
|
+
logger << "#{LogStasher.build_logstash_event(data, tags).to_json}\n"
|
35
37
|
end
|
36
38
|
|
37
39
|
def extract_data(data)
|
38
|
-
{
|
40
|
+
{ identifier: from_rails_root(data[:identifier]) }
|
39
41
|
end
|
40
42
|
|
41
43
|
def request_context
|
@@ -49,16 +51,15 @@ module LogStasher
|
|
49
51
|
def event_data(event)
|
50
52
|
{
|
51
53
|
name: event.name,
|
52
|
-
transaction_id: event.transaction_id
|
54
|
+
transaction_id: event.transaction_id
|
53
55
|
}
|
54
56
|
end
|
55
57
|
|
56
58
|
def runtimes(event)
|
57
59
|
{
|
58
|
-
duration: event.duration
|
59
|
-
}.
|
60
|
+
duration: event.duration
|
61
|
+
}.each_with_object({}) do |(name, runtime), runtimes|
|
60
62
|
runtimes[name] = runtime.to_f.round(2) if runtime
|
61
|
-
runtimes
|
62
63
|
end
|
63
64
|
end
|
64
65
|
end
|
@@ -1,13 +1,21 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# For Rails 6.0 or below, require the logging module which contains LogSubscriber
|
4
|
+
if ActiveJob::VERSION::MAJOR < 6 || (ActiveJob::VERSION::MAJOR == 6 && ActiveJob::VERSION::MINOR.zero?)
|
3
5
|
require 'active_job/logging'
|
4
|
-
|
6
|
+
else
|
7
|
+
require 'active_job/log_subscriber'
|
5
8
|
end
|
6
9
|
|
7
10
|
module LogStasher
|
8
11
|
module ActiveJob
|
9
|
-
|
12
|
+
BASE_SUBSCRIBER = if defined?(::ActiveJob::LogSubscriber)
|
13
|
+
::ActiveJob::LogSubscriber
|
14
|
+
else
|
15
|
+
::ActiveJob::Logging::LogSubscriber
|
16
|
+
end
|
10
17
|
|
18
|
+
class LogSubscriber < BASE_SUBSCRIBER
|
11
19
|
def enqueue(event)
|
12
20
|
process_event(event, 'enqueue')
|
13
21
|
end
|
@@ -54,20 +62,20 @@ module LogStasher
|
|
54
62
|
|
55
63
|
tags = ['job', type]
|
56
64
|
tags.push('exception') if data[:exception]
|
57
|
-
logger << LogStasher.build_logstash_event(data, tags).to_json
|
65
|
+
logger << "#{LogStasher.build_logstash_event(data, tags).to_json}\n"
|
58
66
|
end
|
59
67
|
|
60
68
|
def extract_metadata(event)
|
61
69
|
{
|
62
|
-
:
|
63
|
-
:
|
64
|
-
:
|
65
|
-
:
|
70
|
+
job_id: event.payload[:job].job_id,
|
71
|
+
queue_name: queue_name(event),
|
72
|
+
job_class: event.payload[:job].class.to_s,
|
73
|
+
job_args: args_info(event.payload[:job])
|
66
74
|
}
|
67
75
|
end
|
68
76
|
|
69
77
|
def extract_duration(event)
|
70
|
-
{ :
|
78
|
+
{ duration: event.duration.to_f.round(2) }
|
71
79
|
end
|
72
80
|
|
73
81
|
def extract_exception(event)
|
@@ -75,7 +83,7 @@ module LogStasher
|
|
75
83
|
end
|
76
84
|
|
77
85
|
def extract_scheduled_at(event)
|
78
|
-
{ :
|
86
|
+
{ scheduled_at: scheduled_at(event) }
|
79
87
|
end
|
80
88
|
|
81
89
|
def request_context
|
@@ -84,9 +92,8 @@ module LogStasher
|
|
84
92
|
|
85
93
|
# The default args_info makes a string. We need objects to turn into JSON.
|
86
94
|
def args_info(job)
|
87
|
-
job.arguments
|
95
|
+
::ActiveJob::Arguments.serialize(job.arguments)
|
88
96
|
end
|
89
|
-
|
90
97
|
end
|
91
98
|
end
|
92
|
-
end
|
99
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/notifications'
|
2
4
|
require 'active_record/log_subscriber'
|
3
5
|
require 'logstasher/custom_fields'
|
@@ -9,11 +11,9 @@ module LogStasher
|
|
9
11
|
|
10
12
|
def identity(event)
|
11
13
|
lsevent = logstash_event(event)
|
12
|
-
if logger && lsevent
|
13
|
-
logger << lsevent.to_json + "\n"
|
14
|
-
end
|
14
|
+
logger << "#{lsevent.to_json}\n" if logger && lsevent
|
15
15
|
end
|
16
|
-
alias
|
16
|
+
alias sql identity
|
17
17
|
|
18
18
|
def logger
|
19
19
|
LogStasher.logger
|
@@ -22,9 +22,14 @@ module LogStasher
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def logstash_event(event)
|
25
|
-
|
25
|
+
self.class.runtime += event.duration
|
26
|
+
data = event.payload.dup
|
27
|
+
|
28
|
+
return if data[:name] == 'SCHEMA'
|
26
29
|
|
27
|
-
|
30
|
+
# A connection cannot be converted to JSON as it fails with
|
31
|
+
# SystemStackError when running against ActiveSupport JSON patches.
|
32
|
+
data.delete(:connection)
|
28
33
|
|
29
34
|
data.merge! runtimes(event)
|
30
35
|
data.merge! extract_sql(data)
|
@@ -32,7 +37,7 @@ module LogStasher
|
|
32
37
|
data.merge! LogStasher.store
|
33
38
|
data.merge! extract_custom_fields(data)
|
34
39
|
|
35
|
-
tags = [
|
40
|
+
tags = ['request']
|
36
41
|
tags.push('exception') if data[:exception]
|
37
42
|
LogStasher.build_logstash_event(data, tags)
|
38
43
|
end
|
@@ -45,7 +50,7 @@ module LogStasher
|
|
45
50
|
if event.duration
|
46
51
|
{ duration: event.duration.to_f.round(2) }
|
47
52
|
else
|
48
|
-
{
|
53
|
+
{}
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/core_ext/class/attribute'
|
2
4
|
require 'active_support/log_subscriber'
|
3
5
|
require 'logstasher/custom_fields'
|
@@ -20,7 +22,7 @@ module LogStasher
|
|
20
22
|
|
21
23
|
tags = ['request']
|
22
24
|
tags.push('exception') if payload[:exception]
|
23
|
-
logger << LogStasher.build_logstash_event(data, tags).to_json
|
25
|
+
logger << "#{LogStasher.build_logstash_event(data, tags).to_json}\n"
|
24
26
|
end
|
25
27
|
|
26
28
|
def redirect_to(event)
|
@@ -44,40 +46,35 @@ module LogStasher
|
|
44
46
|
end
|
45
47
|
|
46
48
|
def extract_path(payload)
|
47
|
-
payload[:path].split(
|
49
|
+
payload[:path].split('?').first
|
48
50
|
end
|
49
51
|
|
50
52
|
def extract_format(payload)
|
51
|
-
|
52
|
-
payload[:formats].first
|
53
|
-
else
|
54
|
-
payload[:format]
|
55
|
-
end
|
53
|
+
payload[:format]
|
56
54
|
end
|
57
55
|
|
58
56
|
def extract_status(payload)
|
59
57
|
if payload[:status]
|
60
|
-
{ :
|
58
|
+
{ status: payload[:status].to_i }
|
61
59
|
else
|
62
|
-
{ :
|
60
|
+
{ status: 0 }
|
63
61
|
end
|
64
62
|
end
|
65
63
|
|
66
64
|
def runtimes(event)
|
67
65
|
{
|
68
|
-
:
|
69
|
-
:
|
70
|
-
:
|
71
|
-
}.
|
66
|
+
duration: event.duration,
|
67
|
+
view: event.payload[:view_runtime],
|
68
|
+
db: event.payload[:db_runtime]
|
69
|
+
}.each_with_object({}) do |(name, runtime), runtimes|
|
72
70
|
runtimes[name] = runtime.to_f.round(2) if runtime
|
73
|
-
runtimes
|
74
71
|
end
|
75
72
|
end
|
76
73
|
|
77
|
-
def location(
|
74
|
+
def location(_event)
|
78
75
|
if location = Thread.current[:logstasher_location]
|
79
76
|
Thread.current[:logstasher_location] = nil
|
80
|
-
{ :
|
77
|
+
{ location: location }
|
81
78
|
else
|
82
79
|
{}
|
83
80
|
end
|
@@ -88,13 +85,17 @@ module LogStasher
|
|
88
85
|
if payload[:exception]
|
89
86
|
exception, message = payload[:exception]
|
90
87
|
status = ::ActionDispatch::ExceptionWrapper.status_code_for_exception(exception)
|
91
|
-
if LogStasher.backtrace
|
92
|
-
|
88
|
+
backtrace = if LogStasher.backtrace
|
89
|
+
if LogStasher.backtrace_filter.respond_to?(:call)
|
90
|
+
LogStasher.backtrace_filter.call($!.backtrace).join("\n")
|
91
|
+
else
|
92
|
+
$!.backtrace.join("\n")
|
93
|
+
end
|
93
94
|
else
|
94
|
-
|
95
|
+
$!.backtrace.first
|
95
96
|
end
|
96
97
|
message = "#{exception}\n#{message}\n#{backtrace}"
|
97
|
-
{ :
|
98
|
+
{ status: status, error: message }
|
98
99
|
else
|
99
100
|
{}
|
100
101
|
end
|
@@ -1,21 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/core_ext/class/attribute'
|
2
4
|
require 'active_support/log_subscriber'
|
3
5
|
|
4
6
|
module LogStasher
|
5
7
|
module ActiveSupport
|
6
8
|
class MailerLogSubscriber < ::ActiveSupport::LogSubscriber
|
7
|
-
MAILER_FIELDS = [
|
9
|
+
MAILER_FIELDS = %i[mailer action message_id from to].freeze
|
8
10
|
|
9
11
|
def deliver(event)
|
10
|
-
process_event(event, [
|
12
|
+
process_event(event, %w[mailer deliver])
|
11
13
|
end
|
12
14
|
|
15
|
+
# This method will only be invoked on Rails 6.0 and prior.
|
16
|
+
# Starting in Rails 6.0 the receive method was deprecated in
|
17
|
+
# favor of ActionMailbox. The receive method was removed
|
18
|
+
# from ActionMailer in Rails 6.1, and there doesn't appear to
|
19
|
+
# be corresponding instrumentation for ActionMailbox.
|
13
20
|
def receive(event)
|
14
|
-
process_event(event, [
|
21
|
+
process_event(event, %w[mailer receive])
|
15
22
|
end
|
16
23
|
|
17
24
|
def process(event)
|
18
|
-
process_event(event, [
|
25
|
+
process_event(event, %w[mailer process])
|
19
26
|
end
|
20
27
|
|
21
28
|
def logger
|
@@ -26,7 +33,7 @@ module LogStasher
|
|
26
33
|
|
27
34
|
def process_event(event, tags)
|
28
35
|
data = LogStasher.request_context.merge(extract_metadata(event.payload))
|
29
|
-
logger << LogStasher.build_logstash_event(data, tags).to_json
|
36
|
+
logger << "#{LogStasher.build_logstash_event(data, tags).to_json}\n"
|
30
37
|
end
|
31
38
|
|
32
39
|
def extract_metadata(payload)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module LogStasher
|
2
4
|
module CustomFields
|
3
5
|
module LogSubscriber
|
@@ -5,7 +7,7 @@ module LogStasher
|
|
5
7
|
(!CustomFields.custom_fields.empty? && data.extract!(*CustomFields.custom_fields)) || {}
|
6
8
|
end
|
7
9
|
end
|
8
|
-
|
10
|
+
|
9
11
|
def self.clear
|
10
12
|
Thread.current[:logstasher_custom_fields] = []
|
11
13
|
end
|
@@ -1,9 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'redis'
|
2
4
|
|
3
5
|
module LogStasher
|
4
6
|
module Device
|
5
7
|
class Redis
|
6
|
-
|
7
8
|
attr_reader :options, :redis
|
8
9
|
|
9
10
|
def initialize(options = {})
|
@@ -23,7 +24,7 @@ module LogStasher
|
|
23
24
|
def redis_options
|
24
25
|
unless @redis_options
|
25
26
|
default_keys = default_options.keys
|
26
|
-
@redis_options = options.
|
27
|
+
@redis_options = options.reject { |k, _v| default_keys.include?(k) }
|
27
28
|
end
|
28
29
|
|
29
30
|
@redis_options
|
@@ -36,7 +37,7 @@ module LogStasher
|
|
36
37
|
when 'channel'
|
37
38
|
redis.publish(key, log)
|
38
39
|
else
|
39
|
-
|
40
|
+
raise "Unknown data type #{data_type}"
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
@@ -51,12 +52,12 @@ module LogStasher
|
|
51
52
|
end
|
52
53
|
|
53
54
|
def default_options
|
54
|
-
|
55
|
+
{ key: 'logstash', data_type: 'list' }
|
55
56
|
end
|
56
57
|
|
57
58
|
def validate_options
|
58
|
-
unless [
|
59
|
-
|
59
|
+
unless %w[list channel].include?(options[:data_type])
|
60
|
+
raise 'Expected :data_type to be either "list" or "channel"'
|
60
61
|
end
|
61
62
|
end
|
62
63
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'time'
|
5
|
+
require 'date'
|
6
|
+
|
7
|
+
module LogStasher
|
8
|
+
class Event
|
9
|
+
def initialize(data = {})
|
10
|
+
@cancelled = false
|
11
|
+
|
12
|
+
@data = data
|
13
|
+
if data.include?('@timestamp')
|
14
|
+
t = data['@timestamp']
|
15
|
+
data['@timestamp'] = Time.parse(t).gmtime.iso8601(3) if t.is_a?(String)
|
16
|
+
else
|
17
|
+
data['@timestamp'] = ::Time.now.utc.iso8601(3)
|
18
|
+
end
|
19
|
+
data['@version'] = '1' unless @data.include?('@version')
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
to_json.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_json(*args)
|
27
|
+
@data.to_json(*args)
|
28
|
+
end
|
29
|
+
|
30
|
+
def [](key)
|
31
|
+
@data[key]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module LogStasher
|
2
4
|
module ActionController
|
3
5
|
module Instrumentation
|
@@ -9,17 +11,17 @@ module LogStasher
|
|
9
11
|
super(*args)
|
10
12
|
LogStasher::CustomFields.clear
|
11
13
|
end
|
12
|
-
|
14
|
+
|
13
15
|
private
|
14
16
|
|
15
17
|
# this method is called from within super of process_action.
|
16
18
|
def append_info_to_payload(payload) #:nodoc:
|
17
19
|
LogStasher.add_default_fields_to_payload(payload, request)
|
18
|
-
if
|
20
|
+
if respond_to?(:logstasher_add_custom_fields_to_request_context)
|
19
21
|
logstasher_add_custom_fields_to_request_context(LogStasher.request_context)
|
20
22
|
end
|
21
23
|
|
22
|
-
if
|
24
|
+
if respond_to?(:logstasher_add_custom_fields_to_payload)
|
23
25
|
before_keys = payload.keys.clone
|
24
26
|
logstasher_add_custom_fields_to_payload(payload)
|
25
27
|
after_keys = payload.keys
|
@@ -38,7 +40,7 @@ module LogStasher
|
|
38
40
|
payload[key] = value
|
39
41
|
end
|
40
42
|
end
|
41
|
-
|
43
|
+
|
42
44
|
def add_custom_fields_to_store
|
43
45
|
LogStasher.store[:ip] = request.remote_ip
|
44
46
|
LogStasher.store[:route] = "#{request.params[:controller]}##{request.params[:action]}"
|
@@ -1,14 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionController
|
2
4
|
module Instrumentation
|
3
|
-
alias
|
5
|
+
alias orig_process_action process_action
|
4
6
|
def process_action(*args)
|
5
7
|
raw_payload = {
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
controller: self.class.name,
|
9
|
+
action: action_name,
|
10
|
+
params: request.filtered_parameters,
|
11
|
+
format: request.format.try(:ref),
|
12
|
+
method: request.method,
|
13
|
+
path: begin
|
14
|
+
request.fullpath
|
15
|
+
rescue StandardError
|
16
|
+
'unknown'
|
17
|
+
end
|
12
18
|
}
|
13
19
|
|
14
20
|
LogStasher.add_default_fields_to_payload(raw_payload, request)
|
@@ -16,14 +22,14 @@ module ActionController
|
|
16
22
|
LogStasher.clear_request_context
|
17
23
|
LogStasher.add_default_fields_to_request_context(request)
|
18
24
|
|
19
|
-
ActiveSupport::Notifications.instrument(
|
25
|
+
ActiveSupport::Notifications.instrument('start_processing.action_controller', raw_payload.dup)
|
20
26
|
|
21
|
-
ActiveSupport::Notifications.instrument(
|
22
|
-
if
|
27
|
+
ActiveSupport::Notifications.instrument('process_action.action_controller', raw_payload) do |payload|
|
28
|
+
if respond_to?(:logstasher_add_custom_fields_to_request_context)
|
23
29
|
logstasher_add_custom_fields_to_request_context(LogStasher.request_context)
|
24
30
|
end
|
25
31
|
|
26
|
-
if
|
32
|
+
if respond_to?(:logstasher_add_custom_fields_to_payload)
|
27
33
|
before_keys = raw_payload.keys.clone
|
28
34
|
logstasher_add_custom_fields_to_payload(raw_payload)
|
29
35
|
after_keys = raw_payload.keys
|
@@ -45,6 +51,6 @@ module ActionController
|
|
45
51
|
result
|
46
52
|
end
|
47
53
|
end
|
48
|
-
alias
|
54
|
+
alias logstasher_process_action process_action
|
49
55
|
end
|
50
56
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rails/rack/logger'
|
2
4
|
|
3
5
|
module Rails
|
@@ -17,8 +19,7 @@ module Rails
|
|
17
19
|
end
|
18
20
|
|
19
21
|
# Overwrites Rails 3.0/3.1 code that logs new requests
|
20
|
-
def before_dispatch(env)
|
21
|
-
end
|
22
|
+
def before_dispatch(env); end
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
data/lib/logstasher/railtie.rb
CHANGED
@@ -1,9 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rails/railtie'
|
2
4
|
require 'action_view/log_subscriber'
|
3
5
|
require 'action_controller/log_subscriber'
|
4
6
|
require 'socket'
|
5
7
|
|
6
8
|
module LogStasher
|
9
|
+
def default_source
|
10
|
+
case RUBY_PLATFORM
|
11
|
+
when /darwin/
|
12
|
+
# NOTE: MacOS Sierra and later are setting `.local`
|
13
|
+
# hostnames that even as real hostnames without the `.local` part,
|
14
|
+
# are still unresolvable. One reliable way to get an IP is to
|
15
|
+
# get all available IP address lists and use the first one.
|
16
|
+
# This will always be `127.0.0.1`.
|
17
|
+
address_info = Socket.ip_address_list.first
|
18
|
+
address_info&.ip_address
|
19
|
+
else
|
20
|
+
IPSocket.getaddress(Socket.gethostname)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
7
24
|
class Railtie < Rails::Railtie
|
8
25
|
config.logstasher = ::ActiveSupport::OrderedOptions.new
|
9
26
|
config.logstasher.enabled = false
|
@@ -14,15 +31,16 @@ module LogStasher
|
|
14
31
|
config.logstasher.record_enabled = false
|
15
32
|
config.logstasher.view_enabled = true
|
16
33
|
config.logstasher.job_enabled = true
|
34
|
+
config.logstasher.source = LogStasher.default_source
|
17
35
|
|
18
36
|
# Try loading the config/logstasher.yml if present
|
19
37
|
env = Rails.env.to_sym || :development
|
20
|
-
config_file = File.expand_path
|
38
|
+
config_file = File.expand_path './config/logstasher.yml'
|
21
39
|
|
22
40
|
# Load and ERB templating of YAML files
|
23
|
-
LOGSTASHER = File.
|
41
|
+
LOGSTASHER = File.exist?(config_file) ? YAML.safe_load(ERB.new(File.read(config_file)).result).symbolize_keys : nil
|
24
42
|
|
25
|
-
initializer :logstasher, :
|
43
|
+
initializer :logstasher, before: :load_config_initializers do |app|
|
26
44
|
if LOGSTASHER.present?
|
27
45
|
# process common configs
|
28
46
|
LogStasher.process_config(app.config.logstasher, LOGSTASHER)
|
@@ -30,7 +48,8 @@ module LogStasher
|
|
30
48
|
LogStasher.process_config(app.config.logstasher, LOGSTASHER[env].symbolize_keys) if LOGSTASHER.key? env
|
31
49
|
end
|
32
50
|
|
33
|
-
app.config.action_dispatch.rack_cache[:verbose] = false if app
|
51
|
+
app.config.action_dispatch.rack_cache[:verbose] = false if rack_cache_hashlike?(app)
|
52
|
+
|
34
53
|
LogStasher.setup_before(app.config.logstasher) if app.config.logstasher.enabled
|
35
54
|
end
|
36
55
|
|
@@ -39,20 +58,9 @@ module LogStasher
|
|
39
58
|
LogStasher.setup(config.logstasher) if config.logstasher.enabled
|
40
59
|
end
|
41
60
|
end
|
42
|
-
end
|
43
61
|
|
44
|
-
|
45
|
-
|
46
|
-
when /darwin/
|
47
|
-
# NOTE: MacOS Sierra and later are setting `.local`
|
48
|
-
# hostnames that even as real hostnames without the `.local` part,
|
49
|
-
# are still unresolvable. One reliable way to get an IP is to
|
50
|
-
# get all available IP address lists and use the first one.
|
51
|
-
# This will always be `127.0.0.1`.
|
52
|
-
address_info = Socket.ip_address_list.first
|
53
|
-
address_info && address_info.ip_address
|
54
|
-
else
|
55
|
-
IPSocket.getaddress(Socket.gethostname)
|
62
|
+
def rack_cache_hashlike?(app)
|
63
|
+
app.config.action_dispatch.rack_cache&.respond_to?(:[]=)
|
56
64
|
end
|
57
65
|
end
|
58
66
|
|
@@ -74,5 +82,8 @@ module LogStasher
|
|
74
82
|
config.backtrace = yml_config[:backtrace] if yml_config.key? :backtrace
|
75
83
|
config.logger_path = yml_config[:logger_path] if yml_config.key? :logger_path
|
76
84
|
config.log_level = yml_config[:log_level] if yml_config.key? :log_level
|
85
|
+
if yml_config.key? :log_controller_parameters
|
86
|
+
config.log_controller_parameters = yml_config[:log_controller_parameters]
|
87
|
+
end
|
77
88
|
end
|
78
89
|
end
|
data/lib/logstasher/version.rb
CHANGED
data/lib/logstasher.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'logstasher/version'
|
2
4
|
require 'logstasher/active_support/log_subscriber'
|
3
5
|
require 'logstasher/active_support/mailer_log_subscriber'
|
@@ -6,6 +8,7 @@ require 'logstasher/action_view/log_subscriber' if defined?(ActionView)
|
|
6
8
|
require 'logstasher/active_job/log_subscriber' if defined?(ActiveJob)
|
7
9
|
require 'logstasher/rails_ext/action_controller/base'
|
8
10
|
require 'logstasher/custom_fields'
|
11
|
+
require 'logstasher/event'
|
9
12
|
require 'request_store'
|
10
13
|
require 'active_support/core_ext/module/attribute_accessors'
|
11
14
|
require 'active_support/core_ext/string/inflections'
|
@@ -17,7 +20,8 @@ module LogStasher
|
|
17
20
|
REQUEST_CONTEXT_KEY = :logstasher_request_context
|
18
21
|
|
19
22
|
attr_accessor :logger, :logger_path, :enabled, :log_controller_parameters, :source, :backtrace,
|
20
|
-
|
23
|
+
:controller_monkey_patch, :field_renaming, :backtrace_filter
|
24
|
+
|
21
25
|
# Setting the default to 'unknown' to define the default behaviour
|
22
26
|
@source = 'unknown'
|
23
27
|
# By default log the backtrace of exceptions
|
@@ -26,27 +30,27 @@ module LogStasher
|
|
26
30
|
def remove_existing_log_subscriptions
|
27
31
|
::ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
|
28
32
|
case subscriber.class.name
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
when 'ActionView::LogSubscriber'
|
34
|
+
unsubscribe(:action_view, subscriber)
|
35
|
+
when 'ActionController::LogSubscriber'
|
36
|
+
unsubscribe(:action_controller, subscriber)
|
37
|
+
when 'ActionMailer::LogSubscriber'
|
38
|
+
unsubscribe(:action_mailer, subscriber)
|
39
|
+
when 'ActiveRecord::LogSubscriber'
|
40
|
+
unsubscribe(:active_record, subscriber)
|
41
|
+
when 'ActiveJob::LogSubscriber' # For Rails 6
|
42
|
+
unsubscribe(:active_job, subscriber)
|
43
|
+
when 'ActiveJob::Logging::LogSubscriber' # For Rails 5
|
44
|
+
unsubscribe(:active_job, subscriber)
|
39
45
|
end
|
40
46
|
end
|
41
47
|
end
|
42
48
|
|
43
49
|
def unsubscribe(component, subscriber)
|
44
|
-
events = subscriber.public_methods(false).reject{ |method| method.to_s == 'call' }
|
50
|
+
events = subscriber.public_methods(false).reject { |method| method.to_s == 'call' }
|
45
51
|
events.each do |event|
|
46
52
|
::ActiveSupport::Notifications.notifier.listeners_for("#{event}.#{component}").each do |listener|
|
47
|
-
if listener.instance_variable_get('@delegate') == subscriber
|
48
|
-
::ActiveSupport::Notifications.unsubscribe listener
|
49
|
-
end
|
53
|
+
::ActiveSupport::Notifications.unsubscribe listener if listener.instance_variable_get('@delegate') == subscriber
|
50
54
|
end
|
51
55
|
end
|
52
56
|
end
|
@@ -56,14 +60,14 @@ module LogStasher
|
|
56
60
|
payload[:route] = "#{request.params[:controller]}##{request.params[:action]}"
|
57
61
|
payload[:request_id] = request.env['action_dispatch.request_id']
|
58
62
|
LogStasher::CustomFields.add(:ip, :route, :request_id)
|
59
|
-
if
|
63
|
+
if log_controller_parameters
|
60
64
|
payload[:parameters] = payload[:params].except(*::ActionController::LogSubscriber::INTERNAL_PARAMS)
|
61
65
|
LogStasher::CustomFields.add(:parameters)
|
62
66
|
end
|
63
67
|
end
|
64
68
|
|
65
69
|
def add_custom_fields(&block)
|
66
|
-
wrapped_block =
|
70
|
+
wrapped_block = proc do |fields|
|
67
71
|
LogStasher::CustomFields.add(*LogStasher.store.keys)
|
68
72
|
instance_exec(fields, &block)
|
69
73
|
end
|
@@ -72,7 +76,7 @@ module LogStasher
|
|
72
76
|
end
|
73
77
|
|
74
78
|
def add_custom_fields_to_request_context(&block)
|
75
|
-
wrapped_block =
|
79
|
+
wrapped_block = proc do |fields|
|
76
80
|
instance_exec(fields, &block)
|
77
81
|
LogStasher::CustomFields.add(*fields.keys)
|
78
82
|
end
|
@@ -89,7 +93,6 @@ module LogStasher
|
|
89
93
|
end
|
90
94
|
|
91
95
|
def setup_before(config)
|
92
|
-
require 'logstash-event'
|
93
96
|
self.enabled = config.enabled
|
94
97
|
LogStasher::ActiveSupport::LogSubscriber.attach_to :action_controller if config.controller_enabled
|
95
98
|
LogStasher::ActiveSupport::MailerLogSubscriber.attach_to :action_mailer if config.mailer_enabled
|
@@ -100,31 +103,32 @@ module LogStasher
|
|
100
103
|
|
101
104
|
def setup(config)
|
102
105
|
# Path instrumentation class to insert our hook
|
103
|
-
if (!
|
106
|
+
if (!config.controller_monkey_patch && config.controller_monkey_patch != false) || config.controller_monkey_patch == true
|
104
107
|
require 'logstasher/rails_ext/action_controller/metal/instrumentation'
|
105
108
|
end
|
106
|
-
|
109
|
+
suppress_app_logs(config)
|
107
110
|
self.logger_path = config.logger_path || "#{Rails.root}/log/logstash_#{Rails.env}.log"
|
108
|
-
self.logger = config.logger || new_logger(
|
109
|
-
|
111
|
+
self.logger = config.logger || new_logger(logger_path)
|
112
|
+
logger.level = config.log_level || Logger::WARN
|
110
113
|
self.source = config.source unless config.source.nil?
|
111
|
-
self.log_controller_parameters =
|
112
|
-
self.backtrace =
|
113
|
-
self.
|
114
|
-
|
114
|
+
self.log_controller_parameters = !config.log_controller_parameters.nil?
|
115
|
+
self.backtrace = !config.backtrace.nil? unless config.backtrace.nil?
|
116
|
+
self.backtrace_filter = config.backtrace_filter
|
117
|
+
set_data_for_rake
|
118
|
+
set_data_for_console
|
115
119
|
self.field_renaming = Hash(config.field_renaming)
|
116
120
|
end
|
117
121
|
|
118
122
|
def set_data_for_rake
|
119
|
-
|
123
|
+
request_context['request_id'] = ::Rake.application.top_level_tasks if called_as_rake?
|
120
124
|
end
|
121
125
|
|
122
126
|
def set_data_for_console
|
123
|
-
|
127
|
+
request_context['request_id'] = Process.pid.to_s if called_as_console?
|
124
128
|
end
|
125
129
|
|
126
130
|
def called_as_rake?
|
127
|
-
File.basename($
|
131
|
+
File.basename($PROGRAM_NAME) == 'rake'
|
128
132
|
end
|
129
133
|
|
130
134
|
def called_as_console?
|
@@ -158,10 +162,10 @@ module LogStasher
|
|
158
162
|
# LogStasher.info("message", tags:["tag1", "tag2"])
|
159
163
|
# LogStasher.info("message", timing:1234)
|
160
164
|
# LogStasher.info(custom1:"yes", custom2:"no")
|
161
|
-
def log(severity, message, additional_fields={})
|
162
|
-
if
|
165
|
+
def log(severity, message, additional_fields = {})
|
166
|
+
if logger&.send("#{severity}?")
|
163
167
|
|
164
|
-
data = {'level' => severity}
|
168
|
+
data = { 'level' => severity }
|
165
169
|
if message.respond_to?(:to_hash)
|
166
170
|
data.merge!(message.to_hash)
|
167
171
|
else
|
@@ -172,16 +176,16 @@ module LogStasher
|
|
172
176
|
tags = Array(additional_fields.delete(:tags) || 'log')
|
173
177
|
|
174
178
|
data.merge!(additional_fields)
|
175
|
-
|
179
|
+
logger << "#{build_logstash_event(data, tags).to_json}\n"
|
176
180
|
|
177
181
|
end
|
178
182
|
end
|
179
183
|
|
180
184
|
def build_logstash_event(data, tags)
|
181
185
|
field_renaming.each do |old_name, new_name|
|
182
|
-
|
186
|
+
data[new_name] = data.delete(old_name) if data.key?(old_name)
|
183
187
|
end
|
184
|
-
|
188
|
+
Event.new(data.merge('source' => source, 'tags' => tags))
|
185
189
|
end
|
186
190
|
|
187
191
|
def store
|
@@ -204,7 +208,7 @@ module LogStasher
|
|
204
208
|
end
|
205
209
|
end
|
206
210
|
|
207
|
-
%w
|
211
|
+
%w[fatal error warn info debug unknown].each do |severity|
|
208
212
|
eval <<-EOM, nil, __FILE__, __LINE__ + 1
|
209
213
|
def #{severity}(message=nil, additional_fields={})
|
210
214
|
self.log(:#{severity}, message, additional_fields)
|
@@ -213,7 +217,7 @@ module LogStasher
|
|
213
217
|
end
|
214
218
|
|
215
219
|
def enabled?
|
216
|
-
|
220
|
+
enabled || false
|
217
221
|
end
|
218
222
|
|
219
223
|
private
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstasher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 2.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shadab Ahmed
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '5.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '5.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: request_store
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,34 +38,6 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: activesupport
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '4.0'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '4.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: '2.14'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '2.14'
|
69
41
|
- !ruby/object:Gem::Dependency
|
70
42
|
name: bundler
|
71
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,28 +58,28 @@ dependencies:
|
|
86
58
|
requirements:
|
87
59
|
- - ">="
|
88
60
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
61
|
+
version: '5.2'
|
90
62
|
type: :development
|
91
63
|
prerelease: false
|
92
64
|
version_requirements: !ruby/object:Gem::Requirement
|
93
65
|
requirements:
|
94
66
|
- - ">="
|
95
67
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
68
|
+
version: '5.2'
|
97
69
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
70
|
+
name: rspec
|
99
71
|
requirement: !ruby/object:Gem::Requirement
|
100
72
|
requirements:
|
101
73
|
- - ">="
|
102
74
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
75
|
+
version: '2.14'
|
104
76
|
type: :development
|
105
77
|
prerelease: false
|
106
78
|
version_requirements: !ruby/object:Gem::Requirement
|
107
79
|
requirements:
|
108
80
|
- - ">="
|
109
81
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
82
|
+
version: '2.14'
|
111
83
|
description: Awesome rails logs
|
112
84
|
email:
|
113
85
|
- shadab.ansari@gmail.com
|
@@ -123,6 +95,7 @@ files:
|
|
123
95
|
- lib/logstasher/active_support/mailer_log_subscriber.rb
|
124
96
|
- lib/logstasher/custom_fields.rb
|
125
97
|
- lib/logstasher/device/redis.rb
|
98
|
+
- lib/logstasher/event.rb
|
126
99
|
- lib/logstasher/rails_ext/action_controller/base.rb
|
127
100
|
- lib/logstasher/rails_ext/action_controller/metal/instrumentation.rb
|
128
101
|
- lib/logstasher/rails_ext/rack/logger.rb
|
@@ -132,7 +105,7 @@ homepage: https://github.com/shadabahmed/logstasher
|
|
132
105
|
licenses:
|
133
106
|
- MIT
|
134
107
|
metadata: {}
|
135
|
-
post_install_message:
|
108
|
+
post_install_message:
|
136
109
|
rdoc_options: []
|
137
110
|
require_paths:
|
138
111
|
- lib
|
@@ -147,9 +120,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
120
|
- !ruby/object:Gem::Version
|
148
121
|
version: '0'
|
149
122
|
requirements: []
|
150
|
-
|
151
|
-
|
152
|
-
signing_key:
|
123
|
+
rubygems_version: 3.1.4
|
124
|
+
signing_key:
|
153
125
|
specification_version: 4
|
154
126
|
summary: Awesome rails logs
|
155
127
|
test_files: []
|