semantic_logger 4.6.1 → 4.10.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 +4 -4
- data/README.md +50 -20
- data/Rakefile +7 -7
- data/lib/semantic_logger/appender/async.rb +10 -9
- data/lib/semantic_logger/appender/async_batch.rb +7 -3
- data/lib/semantic_logger/appender/bugsnag.rb +43 -30
- data/lib/semantic_logger/appender/elasticsearch.rb +32 -14
- data/lib/semantic_logger/appender/elasticsearch_http.rb +4 -4
- data/lib/semantic_logger/appender/file.rb +249 -67
- data/lib/semantic_logger/appender/graylog.rb +12 -10
- data/lib/semantic_logger/appender/honeybadger.rb +3 -3
- data/lib/semantic_logger/appender/http.rb +20 -18
- data/lib/semantic_logger/appender/io.rb +68 -0
- data/lib/semantic_logger/appender/kafka.rb +9 -5
- data/lib/semantic_logger/appender/mongodb.rb +6 -6
- data/lib/semantic_logger/appender/new_relic.rb +2 -2
- data/lib/semantic_logger/appender/rabbitmq.rb +5 -5
- data/lib/semantic_logger/appender/sentry.rb +7 -7
- data/lib/semantic_logger/appender/sentry_ruby.rb +138 -0
- data/lib/semantic_logger/appender/splunk.rb +6 -5
- data/lib/semantic_logger/appender/splunk_http.rb +6 -6
- data/lib/semantic_logger/appender/syslog.rb +23 -15
- data/lib/semantic_logger/appender/tcp.rb +5 -5
- data/lib/semantic_logger/appender/udp.rb +2 -2
- data/lib/semantic_logger/appender/wrapper.rb +3 -2
- data/lib/semantic_logger/appender.rb +42 -36
- data/lib/semantic_logger/appenders.rb +34 -30
- data/lib/semantic_logger/base.rb +57 -27
- data/lib/semantic_logger/formatters/base.rb +9 -3
- data/lib/semantic_logger/formatters/color.rb +12 -8
- data/lib/semantic_logger/formatters/default.rb +18 -5
- data/lib/semantic_logger/formatters/fluentd.rb +3 -3
- data/lib/semantic_logger/formatters/json.rb +1 -1
- data/lib/semantic_logger/formatters/logfmt.rb +72 -0
- data/lib/semantic_logger/formatters/raw.rb +31 -7
- data/lib/semantic_logger/formatters/signalfx.rb +10 -9
- data/lib/semantic_logger/formatters/syslog.rb +8 -6
- data/lib/semantic_logger/formatters/syslog_cee.rb +8 -6
- data/lib/semantic_logger/formatters.rb +12 -13
- data/lib/semantic_logger/jruby/garbage_collection_logger.rb +4 -2
- data/lib/semantic_logger/levels.rb +9 -7
- data/lib/semantic_logger/log.rb +51 -61
- data/lib/semantic_logger/loggable.rb +8 -1
- data/lib/semantic_logger/logger.rb +19 -11
- data/lib/semantic_logger/metric/new_relic.rb +3 -3
- data/lib/semantic_logger/metric/signalfx.rb +3 -3
- data/lib/semantic_logger/metric/statsd.rb +7 -7
- data/lib/semantic_logger/processor.rb +9 -7
- data/lib/semantic_logger/reporters/minitest.rb +4 -4
- data/lib/semantic_logger/semantic_logger.rb +40 -19
- data/lib/semantic_logger/subscriber.rb +16 -5
- data/lib/semantic_logger/sync.rb +12 -0
- data/lib/semantic_logger/sync_processor.rb +43 -0
- data/lib/semantic_logger/test/capture_log_events.rb +34 -0
- data/lib/semantic_logger/utils.rb +32 -13
- data/lib/semantic_logger/version.rb +1 -1
- data/lib/semantic_logger.rb +27 -22
- metadata +15 -10
@@ -1,7 +1,7 @@
|
|
1
1
|
begin
|
2
|
-
require
|
2
|
+
require "bunny"
|
3
3
|
rescue LoadError
|
4
|
-
raise LoadError
|
4
|
+
raise LoadError, 'Gem bunny is required for logging to RabbitMQ. Please add the gem "bunny" to your Gemfile.'
|
5
5
|
end
|
6
6
|
|
7
7
|
# Forward all log messages to RabbitMQ.
|
@@ -14,7 +14,7 @@ end
|
|
14
14
|
# # Name of the queue in RabbitMQ where to publish the logs. This queue will be bound to "amqp.direct" exchange.
|
15
15
|
# queue: 'semantic_logger',
|
16
16
|
#
|
17
|
-
# # This host will be used for RabbitMQ connection.
|
17
|
+
# # This host will be used for RabbitMQ connection.
|
18
18
|
# # NOTE this is different than :host option which is used by the logger directly.
|
19
19
|
# rabbitmq_host: '127.0.0.1',
|
20
20
|
#
|
@@ -63,7 +63,7 @@ module SemanticLogger
|
|
63
63
|
# RabbitMQ Parameters:
|
64
64
|
#
|
65
65
|
# rabbitmq_host: [String]
|
66
|
-
# Host for AMQP connection. in Bunny this is called :host but here it has
|
66
|
+
# Host for AMQP connection. in Bunny this is called :host but here it has
|
67
67
|
# been remapped to avoid conflicting with SemanticLogger's :host param.
|
68
68
|
# Default: localhost
|
69
69
|
#
|
@@ -76,7 +76,7 @@ module SemanticLogger
|
|
76
76
|
# Default: nil
|
77
77
|
#
|
78
78
|
# more parameters supported by Bunny: http://rubybunny.info/articles/connecting.html
|
79
|
-
def initialize(queue_name:
|
79
|
+
def initialize(queue_name: "semantic_logger", rabbitmq_host: nil, metrics: false, **args, &block)
|
80
80
|
@queue_name = queue_name
|
81
81
|
@rabbitmq_args = args.dup
|
82
82
|
@rabbitmq_args[:host] = rabbitmq_host
|
@@ -1,7 +1,7 @@
|
|
1
1
|
begin
|
2
|
-
require
|
2
|
+
require "sentry-raven"
|
3
3
|
rescue LoadError
|
4
|
-
raise LoadError
|
4
|
+
raise LoadError, 'Gem sentry-raven is required for logging purposes. Please add the gem "sentry-raven" to your Gemfile.'
|
5
5
|
end
|
6
6
|
|
7
7
|
# Send log messages to sentry
|
@@ -46,12 +46,12 @@ module SemanticLogger
|
|
46
46
|
# Send an error notification to sentry
|
47
47
|
def log(log)
|
48
48
|
# Ignore logs coming from Raven itself
|
49
|
-
return false if log.name ==
|
49
|
+
return false if log.name == "Raven"
|
50
50
|
|
51
|
-
context
|
52
|
-
user
|
53
|
-
tags
|
54
|
-
attrs
|
51
|
+
context = formatter.call(log, self)
|
52
|
+
user = context.delete(:user)
|
53
|
+
tags = context.delete(:tags)
|
54
|
+
attrs = {
|
55
55
|
level: context.delete(:level),
|
56
56
|
extra: context
|
57
57
|
}
|
@@ -0,0 +1,138 @@
|
|
1
|
+
begin
|
2
|
+
require "sentry-ruby"
|
3
|
+
rescue LoadError
|
4
|
+
raise LoadError, 'Gem sentry-ruby is required for logging purposes. Please add the gem "sentry-ruby" to your Gemfile.'
|
5
|
+
end
|
6
|
+
|
7
|
+
# Send log messages to sentry
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
# SemanticLogger.add_appender(appender: :sentry_ruby)
|
11
|
+
#
|
12
|
+
module SemanticLogger
|
13
|
+
module Appender
|
14
|
+
class SentryRuby < SemanticLogger::Subscriber
|
15
|
+
# Create Appender
|
16
|
+
#
|
17
|
+
# Parameters
|
18
|
+
# level: [:trace | :debug | :info | :warn | :error | :fatal]
|
19
|
+
# Override the log level for this appender.
|
20
|
+
# Default: :error
|
21
|
+
#
|
22
|
+
# formatter: [Object|Proc|Symbol|Hash]
|
23
|
+
# An instance of a class that implements #call, or a Proc to be used to format
|
24
|
+
# the output from this appender
|
25
|
+
# Default: Use the built-in formatter (See: #call)
|
26
|
+
#
|
27
|
+
# filter: [Regexp|Proc]
|
28
|
+
# RegExp: Only include log messages where the class name matches the supplied.
|
29
|
+
# regular expression. All other messages will be ignored.
|
30
|
+
# Proc: Only include log messages where the supplied Proc returns true
|
31
|
+
# The Proc must return true or false.
|
32
|
+
#
|
33
|
+
# host: [String]
|
34
|
+
# Name of this host to appear in log messages.
|
35
|
+
# Default: SemanticLogger.host
|
36
|
+
#
|
37
|
+
# application: [String]
|
38
|
+
# Name of this application to appear in log messages.
|
39
|
+
# Default: SemanticLogger.application
|
40
|
+
def initialize(level: :error, **args, &block)
|
41
|
+
# Replace the Sentry Ruby logger so that we can identify its log
|
42
|
+
# messages and not forward them to Sentry
|
43
|
+
::Sentry.init { |config| config.logger = SemanticLogger[::Sentry] }
|
44
|
+
super(level: level, **args, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Send an error notification to sentry
|
48
|
+
def log(log)
|
49
|
+
# Ignore logs coming from Sentry itself
|
50
|
+
return false if log.name == "Sentry"
|
51
|
+
|
52
|
+
context = formatter.call(log, self)
|
53
|
+
payload = context.delete(:payload) || {}
|
54
|
+
named_tags = context[:named_tags] || {}
|
55
|
+
transaction_name = named_tags.delete(:transaction_name)
|
56
|
+
|
57
|
+
user = extract_user!(named_tags, payload)
|
58
|
+
tags = extract_tags!(context)
|
59
|
+
|
60
|
+
fingerprint = payload.delete(:fingerprint)
|
61
|
+
|
62
|
+
::Sentry.with_scope do |scope|
|
63
|
+
scope.set_user(user) if user
|
64
|
+
scope.set_level(context.delete(:level)) if context[:level]
|
65
|
+
scope.set_fingerprint(fingerprint) if fingerprint
|
66
|
+
scope.set_transaction_name(transaction_name) if transaction_name
|
67
|
+
scope.set_tags(tags)
|
68
|
+
scope.set_extras(context)
|
69
|
+
scope.set_extras(payload)
|
70
|
+
|
71
|
+
if log.exception
|
72
|
+
::Sentry.capture_exception(log.exception)
|
73
|
+
elsif log.backtrace
|
74
|
+
::Sentry.capture_message(context[:message], backtrace: log.backtrace)
|
75
|
+
else
|
76
|
+
::Sentry.capture_message(context[:message])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
true
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# Use Raw Formatter by default
|
86
|
+
def default_formatter
|
87
|
+
SemanticLogger::Formatters::Raw.new
|
88
|
+
end
|
89
|
+
|
90
|
+
# Extract user data from named tags or payload.
|
91
|
+
#
|
92
|
+
# Keys :user_id and :user_email will be used as :id and :email respectively.
|
93
|
+
# Keys :username and :ip_address will be used verbatim.
|
94
|
+
#
|
95
|
+
# Any additional value nested in a :user key will be added, provided any of
|
96
|
+
# the above keys is already present.
|
97
|
+
#
|
98
|
+
def extract_user!(*sources)
|
99
|
+
keys = {user_id: :id, username: :username, user_email: :email, ip_address: :ip_address}
|
100
|
+
|
101
|
+
user = {}
|
102
|
+
|
103
|
+
sources.each do |source|
|
104
|
+
keys.each do |source_key, target_key|
|
105
|
+
value = source.delete(source_key)
|
106
|
+
user[target_key] = value if value
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
return if user.empty?
|
111
|
+
|
112
|
+
sources.each do |source|
|
113
|
+
extras = source.delete(:user)
|
114
|
+
user.merge!(extras) if extras.is_a?(Hash)
|
115
|
+
end
|
116
|
+
|
117
|
+
user
|
118
|
+
end
|
119
|
+
|
120
|
+
# Extract tags.
|
121
|
+
#
|
122
|
+
# Named tags will be stringified (both key and value).
|
123
|
+
# Unnamed tags will be stringified and joined with a comma. Then they will
|
124
|
+
# be used as a "tag" named tag. If such a tag already exists, it is also
|
125
|
+
# joined with a comma.
|
126
|
+
#
|
127
|
+
# Finally, the tag names are limited to 32 characters and the tag values to 256.
|
128
|
+
#
|
129
|
+
def extract_tags!(context)
|
130
|
+
named_tags = context.delete(:named_tags) || {}
|
131
|
+
named_tags = named_tags.map { |k, v| [k.to_s, v.to_s] }.to_h
|
132
|
+
tags = context.delete(:tags)
|
133
|
+
named_tags.merge!("tag" => tags.join(", ")) { |_, v1, v2| "#{v1}, #{v2}" } if tags
|
134
|
+
named_tags.map { |k, v| [k[0...32], v[0...256]] }.to_h
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
begin
|
2
|
-
require
|
2
|
+
require "splunk-sdk-ruby"
|
3
3
|
rescue LoadError
|
4
|
-
raise LoadError
|
4
|
+
raise LoadError,
|
5
|
+
'Gem splunk-sdk-ruby is required for logging to Splunk. Please add the gem "splunk-sdk-ruby" to your Gemfile.'
|
5
6
|
end
|
6
7
|
|
7
8
|
# Splunk log appender.
|
@@ -88,7 +89,7 @@ module SemanticLogger
|
|
88
89
|
# regular expression. All other messages will be ignored.
|
89
90
|
# Proc: Only include log messages where the supplied Proc returns true
|
90
91
|
# The Proc must return true or false.
|
91
|
-
def initialize(index:
|
92
|
+
def initialize(index: "main", source_type: nil, **args, &block)
|
92
93
|
@index = index
|
93
94
|
@source_type = source_type
|
94
95
|
|
@@ -120,7 +121,7 @@ module SemanticLogger
|
|
120
121
|
def call(log, logger)
|
121
122
|
h = SemanticLogger::Formatters::Raw.new.call(log, logger)
|
122
123
|
h.delete(:time)
|
123
|
-
message
|
124
|
+
message = {
|
124
125
|
source: logger.application,
|
125
126
|
host: logger.host,
|
126
127
|
time: log.time.utc.to_f,
|
@@ -128,7 +129,7 @@ module SemanticLogger
|
|
128
129
|
event: h
|
129
130
|
}
|
130
131
|
message[:environment] = logger.environment if logger.environment
|
131
|
-
message[:sourcetype]
|
132
|
+
message[:sourcetype] = source_type if source_type
|
132
133
|
message
|
133
134
|
end
|
134
135
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "json"
|
2
2
|
# Splunk log appender using the Splunk HTTP(S) listener.
|
3
3
|
#
|
4
4
|
# Use the newer, faster and more complete JSON over HTTP interface for Splunk.
|
@@ -81,22 +81,22 @@ module SemanticLogger
|
|
81
81
|
super(compress: compress, **args, &block)
|
82
82
|
|
83
83
|
# Put splunk auth token in the header of every HTTP post.
|
84
|
-
@header[
|
84
|
+
@header["Authorization"] = "Splunk #{token}"
|
85
85
|
end
|
86
86
|
|
87
87
|
# Returns [String] JSON to send to Splunk.
|
88
88
|
#
|
89
89
|
# For splunk format requirements see:
|
90
|
-
#
|
90
|
+
# https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector
|
91
91
|
def call(log, logger)
|
92
|
-
h
|
93
|
-
|
92
|
+
h = SemanticLogger::Formatters::Raw.new(time_format: :seconds).call(log, logger)
|
93
|
+
h.delete(:host)
|
94
|
+
message = {
|
94
95
|
source: logger.application,
|
95
96
|
host: logger.host,
|
96
97
|
time: h.delete(:time),
|
97
98
|
event: h
|
98
99
|
}
|
99
|
-
message[:environment] = logger.environment if logger.environment
|
100
100
|
message[:sourcetype] = source_type if source_type
|
101
101
|
message[:index] = index if index
|
102
102
|
message.to_json
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "syslog"
|
2
|
+
require "uri"
|
3
|
+
require "socket"
|
4
4
|
# Send log messages to local syslog, or remote syslog servers over TCP or UDP.
|
5
5
|
#
|
6
6
|
# Example:
|
@@ -31,7 +31,7 @@ require 'socket'
|
|
31
31
|
module SemanticLogger
|
32
32
|
module Appender
|
33
33
|
class Syslog < SemanticLogger::Subscriber
|
34
|
-
attr_reader :remote_syslog, :url, :server, :port, :protocol, :facility, :options, :level_map
|
34
|
+
attr_reader :remote_syslog, :url, :server, :port, :protocol, :facility, :options, :level_map, :max_size
|
35
35
|
|
36
36
|
# Create a Syslog appender instance.
|
37
37
|
#
|
@@ -57,7 +57,7 @@ module SemanticLogger
|
|
57
57
|
# Only used with the TCP protocol.
|
58
58
|
# Specify custom parameters to pass into Net::TCPClient.new
|
59
59
|
# For a list of options see the net_tcp_client documentation:
|
60
|
-
# https://github.com/
|
60
|
+
# https://github.com/reidmorrison/net_tcp_client/blob/master/lib/net/tcp_client/tcp_client.rb
|
61
61
|
#
|
62
62
|
# level: [:trace | :debug | :info | :warn | :error | :fatal]
|
63
63
|
# Override the log level for this appender.
|
@@ -73,6 +73,10 @@ module SemanticLogger
|
|
73
73
|
# Identity of the program.
|
74
74
|
# Default: SemanticLogger.application
|
75
75
|
#
|
76
|
+
# max_size: [Integer]
|
77
|
+
# Set your own packet size.
|
78
|
+
# Default: 1024 bytes
|
79
|
+
#
|
76
80
|
# options: [Integer]
|
77
81
|
# Default: ::Syslog::LOG_PID | ::Syslog::LOG_CONS
|
78
82
|
# Any of the following (options can be logically OR'd together)
|
@@ -119,8 +123,9 @@ module SemanticLogger
|
|
119
123
|
# Example:
|
120
124
|
# # Change the warn level to LOG_NOTICE level instead of a the default of LOG_WARNING.
|
121
125
|
# SemanticLogger.add_appender(appender: :syslog, level_map: {warn: ::Syslog::LOG_NOTICE})
|
122
|
-
def initialize(url:
|
126
|
+
def initialize(url: "syslog://localhost",
|
123
127
|
facility: ::Syslog::LOG_USER,
|
128
|
+
max_size: 1024,
|
124
129
|
level_map: SemanticLogger::Formatters::Syslog::LevelMap.new,
|
125
130
|
options: ::Syslog::LOG_PID | ::Syslog::LOG_CONS,
|
126
131
|
tcp_client: {},
|
@@ -129,13 +134,14 @@ module SemanticLogger
|
|
129
134
|
|
130
135
|
@options = options
|
131
136
|
@facility = facility
|
137
|
+
@max_size = max_size
|
132
138
|
@level_map = level_map
|
133
139
|
@url = url
|
134
140
|
uri = URI(@url)
|
135
|
-
@server = uri.host ||
|
141
|
+
@server = uri.host || "localhost"
|
136
142
|
@protocol = (uri.scheme || :syslog).to_sym
|
137
143
|
@port = uri.port || 514
|
138
|
-
@server =
|
144
|
+
@server = "localhost" if @protocol == :syslog
|
139
145
|
@tcp_client_options = tcp_client
|
140
146
|
|
141
147
|
raise "Unknown protocol #{@protocol}!" unless %i[syslog tcp udp].include?(@protocol)
|
@@ -143,17 +149,19 @@ module SemanticLogger
|
|
143
149
|
# The syslog_protocol gem is required when logging over TCP or UDP.
|
144
150
|
if %i[tcp udp].include?(@protocol)
|
145
151
|
begin
|
146
|
-
require
|
152
|
+
require "syslog_protocol"
|
147
153
|
rescue LoadError
|
148
|
-
raise LoadError
|
154
|
+
raise LoadError,
|
155
|
+
"Missing gem: syslog_protocol. This gem is required when logging over TCP or UDP. To fix this error: gem install syslog_protocol"
|
149
156
|
end
|
150
157
|
|
151
158
|
# The net_tcp_client gem is required when logging over TCP.
|
152
159
|
if protocol == :tcp
|
153
160
|
begin
|
154
|
-
require
|
161
|
+
require "net/tcp_client"
|
155
162
|
rescue LoadError
|
156
|
-
raise LoadError
|
163
|
+
raise LoadError,
|
164
|
+
"Missing gem: net_tcp_client. This gem is required when logging over TCP. To fix this error: gem install net_tcp_client"
|
157
165
|
end
|
158
166
|
end
|
159
167
|
end
|
@@ -171,7 +179,7 @@ module SemanticLogger
|
|
171
179
|
::Syslog.send(method, application, options, facility)
|
172
180
|
when :tcp
|
173
181
|
@tcp_client_options[:server] = "#{@server}:#{@port}"
|
174
|
-
@remote_syslog = Net::TCPClient.new(
|
182
|
+
@remote_syslog = Net::TCPClient.new(**@tcp_client_options)
|
175
183
|
# Use the local logger for @remote_syslog so errors with the remote logger can be recorded locally.
|
176
184
|
@remote_syslog.logger = logger
|
177
185
|
when :udp
|
@@ -186,7 +194,7 @@ module SemanticLogger
|
|
186
194
|
case @protocol
|
187
195
|
when :syslog
|
188
196
|
# Since the Ruby Syslog API supports sprintf format strings, double up all existing '%'
|
189
|
-
message = formatter.call(log, self).gsub
|
197
|
+
message = formatter.call(log, self).gsub "%", "%%"
|
190
198
|
::Syslog.log @level_map[log.level], message
|
191
199
|
when :tcp
|
192
200
|
@remote_syslog.retry_on_connection_failure { @remote_syslog.write("#{formatter.call(log, self)}\r\n") }
|
@@ -209,7 +217,7 @@ module SemanticLogger
|
|
209
217
|
# Format is text output without the time
|
210
218
|
SemanticLogger::Formatters::Default.new(time_format: nil)
|
211
219
|
else
|
212
|
-
SemanticLogger::Formatters::Syslog.new(facility: facility, level_map: level_map)
|
220
|
+
SemanticLogger::Formatters::Syslog.new(facility: facility, level_map: level_map, max_size: max_size)
|
213
221
|
end
|
214
222
|
end
|
215
223
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
begin
|
2
|
-
require
|
2
|
+
require "net/tcp_client"
|
3
3
|
rescue LoadError
|
4
|
-
raise LoadError
|
4
|
+
raise LoadError, 'Gem net_tcp_client is required for logging over TCP. Please add the gem "net_tcp_client" to your Gemfile.'
|
5
5
|
end
|
6
6
|
|
7
|
-
raise
|
7
|
+
raise "Net::TCPClient v2.0 or greater is required to log over TCP" unless Net::TCPClient::VERSION.to_f >= 2.0
|
8
8
|
|
9
9
|
module SemanticLogger
|
10
10
|
module Appender
|
@@ -189,7 +189,7 @@ module SemanticLogger
|
|
189
189
|
|
190
190
|
# Use the internal logger so that errors with remote logging are only written locally.
|
191
191
|
Net::TCPClient.logger = logger
|
192
|
-
Net::TCPClient.logger.name =
|
192
|
+
Net::TCPClient.logger.name = "Net::TCPClient"
|
193
193
|
|
194
194
|
super(level: level, formatter: formatter, filter: filter, application: application, environment: environment, host: host, &block)
|
195
195
|
reopen
|
@@ -198,7 +198,7 @@ module SemanticLogger
|
|
198
198
|
# After forking an active process call #reopen to re-open the handles to resources.
|
199
199
|
def reopen
|
200
200
|
close
|
201
|
-
@tcp_client = Net::TCPClient.new(
|
201
|
+
@tcp_client = Net::TCPClient.new(**@tcp_client_args)
|
202
202
|
end
|
203
203
|
|
204
204
|
# Write the log using the specified protocol and server.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "socket"
|
2
2
|
module SemanticLogger
|
3
3
|
module Appender
|
4
4
|
# UDP log appender.
|
@@ -74,7 +74,7 @@ module SemanticLogger
|
|
74
74
|
def reopen
|
75
75
|
close
|
76
76
|
@socket = UDPSocket.new
|
77
|
-
host, port = server.split(
|
77
|
+
host, port = server.split(":")
|
78
78
|
@socket.connect(host, port.to_i)
|
79
79
|
end
|
80
80
|
|
@@ -32,7 +32,7 @@ module SemanticLogger
|
|
32
32
|
# require 'logger'
|
33
33
|
# require 'semantic_logger'
|
34
34
|
#
|
35
|
-
# ruby_logger = Logger.new(
|
35
|
+
# ruby_logger = Logger.new($stdout)
|
36
36
|
# SemanticLogger.add_appender(logger: ruby_logger)
|
37
37
|
#
|
38
38
|
# logger = SemanticLogger['test']
|
@@ -45,7 +45,8 @@ module SemanticLogger
|
|
45
45
|
# Check if the custom appender responds to all the log levels. For example Ruby ::Logger
|
46
46
|
does_not_implement = LEVELS[1..-1].find { |i| !@logger.respond_to?(i) }
|
47
47
|
if does_not_implement
|
48
|
-
raise(ArgumentError,
|
48
|
+
raise(ArgumentError,
|
49
|
+
"Supplied logger does not implement:#{does_not_implement}. It must implement all of #{LEVELS[1..-1].inspect}")
|
49
50
|
end
|
50
51
|
|
51
52
|
super(**args, &block)
|
@@ -1,35 +1,36 @@
|
|
1
1
|
module SemanticLogger
|
2
2
|
module Appender
|
3
3
|
# @formatter:off
|
4
|
-
autoload :Async,
|
5
|
-
autoload :AsyncBatch,
|
6
|
-
autoload :Bugsnag,
|
7
|
-
autoload :Elasticsearch,
|
8
|
-
autoload :ElasticsearchHttp,
|
9
|
-
autoload :File,
|
10
|
-
autoload :Graylog,
|
11
|
-
autoload :Honeybadger,
|
12
|
-
autoload :
|
13
|
-
autoload :
|
14
|
-
autoload :
|
15
|
-
autoload :
|
16
|
-
autoload :
|
17
|
-
autoload :
|
18
|
-
autoload :
|
19
|
-
autoload :
|
20
|
-
autoload :
|
21
|
-
autoload :
|
22
|
-
autoload :
|
23
|
-
autoload :
|
4
|
+
autoload :Async, "semantic_logger/appender/async"
|
5
|
+
autoload :AsyncBatch, "semantic_logger/appender/async_batch"
|
6
|
+
autoload :Bugsnag, "semantic_logger/appender/bugsnag"
|
7
|
+
autoload :Elasticsearch, "semantic_logger/appender/elasticsearch"
|
8
|
+
autoload :ElasticsearchHttp, "semantic_logger/appender/elasticsearch_http"
|
9
|
+
autoload :File, "semantic_logger/appender/file"
|
10
|
+
autoload :Graylog, "semantic_logger/appender/graylog"
|
11
|
+
autoload :Honeybadger, "semantic_logger/appender/honeybadger"
|
12
|
+
autoload :IO, "semantic_logger/appender/io"
|
13
|
+
autoload :Kafka, "semantic_logger/appender/kafka"
|
14
|
+
autoload :Sentry, "semantic_logger/appender/sentry"
|
15
|
+
autoload :Http, "semantic_logger/appender/http"
|
16
|
+
autoload :MongoDB, "semantic_logger/appender/mongodb"
|
17
|
+
autoload :NewRelic, "semantic_logger/appender/new_relic"
|
18
|
+
autoload :Rabbitmq, "semantic_logger/appender/rabbitmq"
|
19
|
+
autoload :Splunk, "semantic_logger/appender/splunk"
|
20
|
+
autoload :SplunkHttp, "semantic_logger/appender/splunk_http"
|
21
|
+
autoload :Syslog, "semantic_logger/appender/syslog"
|
22
|
+
autoload :Tcp, "semantic_logger/appender/tcp"
|
23
|
+
autoload :Udp, "semantic_logger/appender/udp"
|
24
|
+
autoload :Wrapper, "semantic_logger/appender/wrapper"
|
25
|
+
autoload :SentryRuby, "semantic_logger/appender/sentry_ruby"
|
24
26
|
# @formatter:on
|
25
27
|
|
26
28
|
# Returns [SemanticLogger::Subscriber] appender for the supplied options
|
27
29
|
def self.factory(async: false, batch: nil,
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
)
|
30
|
+
max_queue_size: 10_000, lag_check_interval: 1_000, lag_threshold_s: 30,
|
31
|
+
batch_size: 300, batch_seconds: 5,
|
32
|
+
**args,
|
33
|
+
&block)
|
33
34
|
appender = build(**args, &block)
|
34
35
|
|
35
36
|
# If appender implements #batch, then it should use the batch proxy by default.
|
@@ -37,11 +38,11 @@ module SemanticLogger
|
|
37
38
|
|
38
39
|
if batch == true
|
39
40
|
Appender::AsyncBatch.new(
|
40
|
-
appender:
|
41
|
-
max_queue_size:
|
42
|
-
lag_threshold_s:
|
43
|
-
batch_size:
|
44
|
-
batch_seconds:
|
41
|
+
appender: appender,
|
42
|
+
max_queue_size: max_queue_size,
|
43
|
+
lag_threshold_s: lag_threshold_s,
|
44
|
+
batch_size: batch_size,
|
45
|
+
batch_seconds: batch_seconds
|
45
46
|
)
|
46
47
|
elsif async == true
|
47
48
|
Appender::Async.new(
|
@@ -57,8 +58,10 @@ module SemanticLogger
|
|
57
58
|
|
58
59
|
# Returns [Subscriber] instance from the supplied options.
|
59
60
|
def self.build(io: nil, file_name: nil, appender: nil, metric: nil, logger: nil, **args, &block)
|
60
|
-
if
|
61
|
-
SemanticLogger::Appender::File.new(
|
61
|
+
if file_name
|
62
|
+
SemanticLogger::Appender::File.new(file_name, **args, &block)
|
63
|
+
elsif io
|
64
|
+
SemanticLogger::Appender::IO.new(io, **args, &block)
|
62
65
|
elsif logger
|
63
66
|
SemanticLogger::Appender::Wrapper.new(logger: logger, **args, &block)
|
64
67
|
elsif appender
|
@@ -67,18 +70,21 @@ module SemanticLogger
|
|
67
70
|
elsif appender.is_a?(Subscriber)
|
68
71
|
appender
|
69
72
|
else
|
70
|
-
raise(ArgumentError,
|
73
|
+
raise(ArgumentError,
|
74
|
+
"Parameter :appender must be either a Symbol or an object derived from SemanticLogger::Subscriber, not: #{appender.inspect}")
|
71
75
|
end
|
72
76
|
elsif metric
|
73
77
|
if metric.is_a?(Symbol)
|
74
|
-
SemanticLogger::Utils.constantize_symbol(metric,
|
78
|
+
SemanticLogger::Utils.constantize_symbol(metric, "SemanticLogger::Metric").new(**args)
|
75
79
|
elsif metric.is_a?(Subscriber)
|
76
80
|
metric
|
77
81
|
else
|
78
|
-
raise(ArgumentError,
|
82
|
+
raise(ArgumentError,
|
83
|
+
"Parameter :metric must be either a Symbol or an object derived from SemanticLogger::Subscriber, not: #{appender.inspect}")
|
79
84
|
end
|
80
85
|
else
|
81
|
-
raise(ArgumentError,
|
86
|
+
raise(ArgumentError,
|
87
|
+
"To create an appender it must supply one of the following: :io, :file_name, :appender, :metric, or :logger")
|
82
88
|
end
|
83
89
|
end
|
84
90
|
|