semlogr 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +7 -0
- data/Gemfile +2 -0
- data/README.md +1 -1
- data/Rakefile +2 -0
- data/bin/console +1 -0
- data/lib/semlogr/component_registry.rb +2 -0
- data/lib/semlogr/config/logger_config.rb +10 -1
- data/lib/semlogr/config/sink_config.rb +10 -1
- data/lib/semlogr/enrichers/event_type.rb +2 -0
- data/lib/semlogr/enrichers/host.rb +2 -0
- data/lib/semlogr/enrichers/log_context.rb +2 -0
- data/lib/semlogr/enrichers/property.rb +2 -0
- data/lib/semlogr/enrichers/thread.rb +2 -0
- data/lib/semlogr/error.rb +2 -0
- data/lib/semlogr/events/log_event.rb +3 -1
- data/lib/semlogr/formatters/json_formatter.rb +2 -0
- data/lib/semlogr/formatters/property_value_formatter.rb +13 -12
- data/lib/semlogr/formatters/text_formatter.rb +4 -2
- data/lib/semlogr/log_context.rb +2 -0
- data/lib/semlogr/log_severity.rb +2 -0
- data/lib/semlogr/logger.rb +2 -0
- data/lib/semlogr/null_logger.rb +2 -0
- data/lib/semlogr/properties/output_properties.rb +2 -0
- data/lib/semlogr/self_logger.rb +56 -0
- data/lib/semlogr/sinks/aggregate.rb +9 -1
- data/lib/semlogr/sinks/batching.rb +86 -0
- data/lib/semlogr/sinks/colored_console.rb +4 -2
- data/lib/semlogr/sinks/console.rb +2 -0
- data/lib/semlogr/sinks/enriching.rb +12 -1
- data/lib/semlogr/sinks/file.rb +2 -0
- data/lib/semlogr/sinks/filtering.rb +13 -1
- data/lib/semlogr/templates/parser.rb +19 -5
- data/lib/semlogr/templates/property_token.rb +32 -11
- data/lib/semlogr/templates/template.rb +2 -0
- data/lib/semlogr/templates/template_cache.rb +2 -0
- data/lib/semlogr/templates/text_token.rb +2 -0
- data/lib/semlogr/utils/bounded_queue.rb +41 -0
- data/lib/semlogr/version.rb +3 -1
- data/lib/semlogr.rb +6 -2
- data/samples/basic.rb +2 -0
- data/samples/context.rb +2 -0
- data/samples/enrichment.rb +2 -0
- data/samples/filtering.rb +2 -0
- data/samples/log_context.rb +2 -0
- data/samples/self_logger.rb +27 -0
- data/samples/sinks.rb +2 -0
- data/semlogr.gemspec +3 -0
- metadata +20 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72f3e3b75d0a87bbfaba4006891ae607b6ede75a90eb6abd1df4c63e61154197
|
4
|
+
data.tar.gz: c94f6f1201b911f7a4882d41b71b557ae5a9d3bafc6e37328b57bf35b6fd3181
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37d8e017fb82402551aa2a43440b6eea26bc7127cf452a815762911d84def00640be109774d8032571e9f6d3dce433448235e7f884cc7cff823efbfe2ade9d41
|
7
|
+
data.tar.gz: f570b3e43ae0e442c3723ab73fbf36d6915509cb87e9478303502b04f3bc9b99840a98bc3df815c3db189bee9767a108af0cb16e5c9bf6fd87e76e72f369f48d
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
### 0.3.1
|
4
|
+
|
5
|
+
* Added batching sink providing ability to create sinks that reliably emit batches of events.
|
6
|
+
* Added initial version of property formatting, allowing standard Ruby format strings to be used to format property values.
|
7
|
+
* Added self logger to provide internal diagnostic information.
|
8
|
+
* Made it so that errors raised by sinks/enrichers/filters will not to crash the entire application. Instead they are swallowed and the error is written to the self log.
|
9
|
+
|
3
10
|
### 0.3.0
|
4
11
|
|
5
12
|
* Moved LogContext
|
data/Gemfile
CHANGED
data/README.md
CHANGED
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'semlogr/component_registry'
|
2
4
|
require 'semlogr/sinks/aggregate'
|
3
5
|
require 'semlogr/sinks/enriching'
|
@@ -25,7 +27,7 @@ module Semlogr
|
|
25
27
|
end
|
26
28
|
|
27
29
|
def enrich_with(enricher, *params)
|
28
|
-
enricher =
|
30
|
+
enricher = resolve_enricher(enricher, params)
|
29
31
|
@enrichers << enricher
|
30
32
|
end
|
31
33
|
|
@@ -43,6 +45,13 @@ module Semlogr
|
|
43
45
|
|
44
46
|
Logger.new(@min_severity, sink)
|
45
47
|
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def resolve_enricher(enricher, params)
|
52
|
+
return enricher unless enricher.is_a?(Symbol)
|
53
|
+
ComponentRegistry.resolve(:enricher, enricher, *params)
|
54
|
+
end
|
46
55
|
end
|
47
56
|
end
|
48
57
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'semlogr/component_registry'
|
2
4
|
require 'semlogr/sinks/enriching'
|
3
5
|
require 'semlogr/sinks/filtering'
|
@@ -21,7 +23,7 @@ module Semlogr
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def enrich_with(enricher, *params)
|
24
|
-
enricher =
|
26
|
+
enricher = resolve_enricher(enricher, params)
|
25
27
|
@enrichers << enricher
|
26
28
|
end
|
27
29
|
|
@@ -39,6 +41,13 @@ module Semlogr
|
|
39
41
|
sink = Sinks::Enriching.new(@enrichers, sink) if @enrichers.any?
|
40
42
|
sink
|
41
43
|
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def resolve_enricher(enricher, params)
|
48
|
+
return enricher unless enricher.is_a?(Symbol)
|
49
|
+
ComponentRegistry.resolve(:enricher, enricher, *params)
|
50
|
+
end
|
42
51
|
end
|
43
52
|
end
|
44
53
|
end
|
data/lib/semlogr/error.rb
CHANGED
@@ -1,26 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Semlogr
|
2
4
|
module Formatters
|
3
5
|
class PropertyValueFormatter
|
4
|
-
|
6
|
+
NO_VALUE = '(nil)'
|
7
|
+
NEW_LINE = "\n"
|
5
8
|
|
6
|
-
def self.format(
|
7
|
-
case
|
9
|
+
def self.format(value)
|
10
|
+
case value
|
8
11
|
when nil
|
9
|
-
|
12
|
+
NO_VALUE
|
10
13
|
when String
|
11
|
-
|
12
|
-
output << property_value
|
13
|
-
output << QUOTE
|
14
|
+
"\"#{value}\""
|
14
15
|
when StandardError
|
15
|
-
|
16
|
+
formatted_error = +"#{value.class}: #{value.message}"
|
16
17
|
|
17
|
-
if
|
18
|
-
|
18
|
+
if value.backtrace&.any?
|
19
|
+
formatted_error << "\n\s\s#{value.backtrace.join("\n\s\s")}"
|
19
20
|
end
|
20
21
|
|
21
|
-
|
22
|
+
formatted_error << NEW_LINE
|
22
23
|
else
|
23
|
-
|
24
|
+
value.to_s
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'semlogr/templates/parser'
|
2
4
|
require 'semlogr/properties/output_properties'
|
3
5
|
require 'semlogr/templates/property_token'
|
@@ -5,14 +7,14 @@ require 'semlogr/templates/property_token'
|
|
5
7
|
module Semlogr
|
6
8
|
module Formatters
|
7
9
|
class TextFormatter
|
8
|
-
DEFAULT_TEMPLATE = "[{timestamp}] {severity}: {message}\n{error}"
|
10
|
+
DEFAULT_TEMPLATE = "[{timestamp}] {severity}: {message}\n{error}"
|
9
11
|
|
10
12
|
def initialize(template: DEFAULT_TEMPLATE)
|
11
13
|
@template = Templates::Parser.parse(template)
|
12
14
|
end
|
13
15
|
|
14
16
|
def format(log_event)
|
15
|
-
output = ''
|
17
|
+
output = +''
|
16
18
|
output_properties = Properties::OutputProperties.create(log_event)
|
17
19
|
|
18
20
|
@template.tokens.each do |token|
|
data/lib/semlogr/log_context.rb
CHANGED
data/lib/semlogr/log_severity.rb
CHANGED
data/lib/semlogr/logger.rb
CHANGED
data/lib/semlogr/null_logger.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Semlogr
|
4
|
+
class SelfLogger
|
5
|
+
def self.debug(message, error = nil)
|
6
|
+
log(:debug, message, error)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.info(message, error = nil)
|
10
|
+
log(:info, message, error)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.warn(message, error = nil)
|
14
|
+
log(:warn, message, error)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.error(message, error = nil)
|
18
|
+
log(:error, message, error)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.fatal(message, error = nil)
|
22
|
+
log(:fatal, message, error)
|
23
|
+
end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
attr_accessor :logger
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def log(severity, message, error)
|
31
|
+
return unless logger
|
32
|
+
|
33
|
+
logger << format_message(severity, message, error)
|
34
|
+
end
|
35
|
+
|
36
|
+
def format_message(severity, message, error)
|
37
|
+
formatted = +"[#{Time.now.iso8601(3)}] #{severity.upcase}: #{message}"
|
38
|
+
|
39
|
+
if error
|
40
|
+
case error
|
41
|
+
when StandardError
|
42
|
+
formatted << "\n#{error.class}: #{error.message}"
|
43
|
+
|
44
|
+
if error.backtrace&.any?
|
45
|
+
formatted << "\n\s\s#{error.backtrace.join("\n\s\s")}"
|
46
|
+
end
|
47
|
+
else
|
48
|
+
formatted << "\n#{error}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
formatted << "\n"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'semlogr/self_logger'
|
4
|
+
|
1
5
|
module Semlogr
|
2
6
|
module Sinks
|
3
7
|
class Aggregate
|
@@ -7,7 +11,11 @@ module Semlogr
|
|
7
11
|
|
8
12
|
def emit(log_event)
|
9
13
|
@sinks.each do |sink|
|
10
|
-
|
14
|
+
begin
|
15
|
+
sink.emit(log_event)
|
16
|
+
rescue StandardError => e
|
17
|
+
SelfLogger.error("Failed to emit log event to sink #{sink.class}", e)
|
18
|
+
end
|
11
19
|
end
|
12
20
|
end
|
13
21
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'semlogr/utils/bounded_queue'
|
4
|
+
require 'timeout'
|
5
|
+
|
6
|
+
module Semlogr
|
7
|
+
module Sinks
|
8
|
+
class Batching
|
9
|
+
MAX_FLUSH_ATTEMPTS = 6
|
10
|
+
|
11
|
+
def initialize(opts = {})
|
12
|
+
@flush_interval = opts[:flush_interval] || 3
|
13
|
+
@final_flush_timeout = opts[:final_flush_timeout] || 60
|
14
|
+
@batch_size = opts[:batch_size] || 1_000
|
15
|
+
@queue_max_size = opts[:queue_max_size] || 100_000
|
16
|
+
@queue = Utils::BoundedQueue.new(@queue_max_size)
|
17
|
+
@flush_mutex = Mutex.new
|
18
|
+
@running = false
|
19
|
+
|
20
|
+
start_flush_thread
|
21
|
+
|
22
|
+
at_exit { stop_flush_thread }
|
23
|
+
end
|
24
|
+
|
25
|
+
def emit(log_event)
|
26
|
+
return unless @running
|
27
|
+
|
28
|
+
@queue.push(log_event)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def flush
|
34
|
+
@flush_mutex.synchronize do
|
35
|
+
loop do
|
36
|
+
log_events = @queue.pop_count(@batch_size)
|
37
|
+
success = emit_batch_with_retries(log_events)
|
38
|
+
|
39
|
+
break unless success
|
40
|
+
break if log_events.empty? || log_events.size < @batch_size
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def emit_batch_with_retries(log_events)
|
46
|
+
return true if log_events.empty?
|
47
|
+
|
48
|
+
flush_attempts = 0
|
49
|
+
|
50
|
+
begin
|
51
|
+
emit_batch(log_events)
|
52
|
+
rescue StandardError
|
53
|
+
flush_attempts += 1
|
54
|
+
|
55
|
+
if flush_attempts <= MAX_FLUSH_ATTEMPTS
|
56
|
+
sleep 2**flush_attempts
|
57
|
+
retry
|
58
|
+
end
|
59
|
+
|
60
|
+
return false
|
61
|
+
end
|
62
|
+
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
def start_flush_thread
|
67
|
+
@running = true
|
68
|
+
|
69
|
+
Thread.new do
|
70
|
+
loop do
|
71
|
+
break unless @running
|
72
|
+
|
73
|
+
sleep @flush_interval
|
74
|
+
flush
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def stop_flush_thread
|
80
|
+
@running = false
|
81
|
+
|
82
|
+
Timeout.timeout(@final_flush_timeout) { flush }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'semlogr/sinks/console'
|
2
4
|
require 'semlogr/properties/output_properties'
|
3
5
|
|
4
6
|
module Semlogr
|
5
7
|
module Sinks
|
6
8
|
class ColoredConsole
|
7
|
-
DEFAULT_TEMPLATE = "[{timestamp}] {severity}: {message}\n{error}"
|
9
|
+
DEFAULT_TEMPLATE = "[{timestamp}] {severity}: {message}\n{error}"
|
8
10
|
|
9
11
|
LOG_SEVERITY_COLORS = {
|
10
12
|
LogSeverity::DEBUG => :white,
|
@@ -26,7 +28,7 @@ module Semlogr
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def emit(log_event)
|
29
|
-
output = ''
|
31
|
+
output = +''
|
30
32
|
output_properties = Properties::OutputProperties.create(log_event)
|
31
33
|
|
32
34
|
@template.tokens.each do |token|
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'semlogr/self_logger'
|
4
|
+
|
1
5
|
module Semlogr
|
2
6
|
module Sinks
|
3
7
|
class Enriching
|
@@ -7,7 +11,14 @@ module Semlogr
|
|
7
11
|
end
|
8
12
|
|
9
13
|
def emit(log_event)
|
10
|
-
@enrichers.each
|
14
|
+
@enrichers.each do |enricher|
|
15
|
+
begin
|
16
|
+
enricher.enrich(log_event)
|
17
|
+
rescue StandardError => e
|
18
|
+
SelfLogger.error("Failed to enrich log event using enricher #{enricher.class}", e)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
11
22
|
@sink.emit(log_event)
|
12
23
|
end
|
13
24
|
end
|
data/lib/semlogr/sinks/file.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'semlogr/self_logger'
|
4
|
+
|
1
5
|
module Semlogr
|
2
6
|
module Sinks
|
3
7
|
class Filtering
|
@@ -7,7 +11,15 @@ module Semlogr
|
|
7
11
|
end
|
8
12
|
|
9
13
|
def emit(log_event)
|
10
|
-
filtered = @filters.any?
|
14
|
+
filtered = @filters.any? do |filter|
|
15
|
+
begin
|
16
|
+
filter.call(log_event)
|
17
|
+
rescue StandardError => e
|
18
|
+
SelfLogger.error("Failed to filter log event using filter #{filter.class}", e)
|
19
|
+
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
11
23
|
|
12
24
|
@sink.emit(log_event) unless filtered
|
13
25
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'semlogr/templates/template'
|
2
4
|
require 'semlogr/templates/text_token'
|
3
5
|
require 'semlogr/templates/property_token'
|
@@ -8,8 +10,9 @@ module Semlogr
|
|
8
10
|
class Parser
|
9
11
|
@template_cache = TemplateCache.new(1000)
|
10
12
|
|
11
|
-
PROPERTY_TOKEN_START = '{'
|
12
|
-
PROPERTY_TOKEN_END = '}'
|
13
|
+
PROPERTY_TOKEN_START = '{'
|
14
|
+
PROPERTY_TOKEN_END = '}'
|
15
|
+
FILTER_TOKEN_START = ':'
|
13
16
|
|
14
17
|
def self.parse(template)
|
15
18
|
return Template::EMPTY unless template && !template.empty?
|
@@ -54,14 +57,25 @@ module Semlogr
|
|
54
57
|
|
55
58
|
token = nil
|
56
59
|
pos = start
|
60
|
+
filter_start = nil
|
57
61
|
|
58
62
|
while pos < template.size
|
59
|
-
|
63
|
+
case template[pos]
|
64
|
+
when PROPERTY_TOKEN_END
|
60
65
|
raw_text = template[start..pos]
|
61
|
-
|
62
|
-
|
66
|
+
filter = nil
|
67
|
+
|
68
|
+
if filter_start.nil?
|
69
|
+
property_name = template[start + 1..pos - 1]
|
70
|
+
else
|
71
|
+
property_name = template[start + 1..filter_start - 1]
|
72
|
+
filter = template[filter_start + 1..pos - 1]
|
73
|
+
end
|
63
74
|
|
75
|
+
token = PropertyToken.new(raw_text, property_name.to_sym, filter)
|
64
76
|
return [token, pos + 1]
|
77
|
+
when FILTER_TOKEN_START
|
78
|
+
filter_start ||= pos
|
65
79
|
end
|
66
80
|
|
67
81
|
pos += 1
|
@@ -1,30 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'semlogr/formatters/property_value_formatter'
|
4
|
+
require 'semlogr/self_logger'
|
2
5
|
|
3
6
|
module Semlogr
|
4
7
|
module Templates
|
5
8
|
class PropertyToken
|
6
|
-
|
9
|
+
attr_reader :raw_text, :property_name, :format_string
|
7
10
|
|
8
|
-
def initialize(raw_text, property_name)
|
11
|
+
def initialize(raw_text, property_name, format = nil)
|
9
12
|
@raw_text = raw_text
|
10
13
|
@property_name = property_name
|
14
|
+
@format_string = format ? "%#{format}" : nil
|
11
15
|
end
|
12
16
|
|
13
17
|
def render(output, properties)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
output <<
|
19
|
+
if properties.key?(property_name)
|
20
|
+
format_property_value(properties[property_name])
|
21
|
+
else
|
22
|
+
raw_text
|
23
|
+
end
|
24
|
+
rescue StandardError => e
|
25
|
+
SelfLogger.error("Failed to render property token: #{property_name}", e)
|
26
|
+
|
27
|
+
output << raw_text
|
21
28
|
end
|
22
29
|
|
23
30
|
def ==(other)
|
24
31
|
return false unless other
|
32
|
+
return false unless other.respond_to?(:raw_text)
|
25
33
|
return false unless other.respond_to?(:property_name)
|
34
|
+
return false unless other.respond_to?(:format_string)
|
26
35
|
|
27
|
-
|
36
|
+
raw_text == other.raw_text && \
|
37
|
+
property_name == other.property_name && \
|
38
|
+
format_string == other.format_string
|
28
39
|
end
|
29
40
|
|
30
41
|
def eql?(other)
|
@@ -32,7 +43,17 @@ module Semlogr
|
|
32
43
|
end
|
33
44
|
|
34
45
|
def hash
|
35
|
-
|
46
|
+
[raw_text, property_name, format_string].hash
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def format_property_value(property_value)
|
52
|
+
if format_string
|
53
|
+
format(format_string, property_value)
|
54
|
+
else
|
55
|
+
Formatters::PropertyValueFormatter.format(property_value)
|
56
|
+
end
|
36
57
|
end
|
37
58
|
end
|
38
59
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'delegate'
|
4
|
+
|
5
|
+
module Semlogr
|
6
|
+
module Utils
|
7
|
+
class BoundedQueue
|
8
|
+
def initialize(max_size)
|
9
|
+
@max_size = max_size
|
10
|
+
@queue = Queue.new
|
11
|
+
@queue_mutex = Mutex.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def size
|
15
|
+
@queue.size
|
16
|
+
end
|
17
|
+
|
18
|
+
def push(item)
|
19
|
+
@queue_mutex.synchronize do
|
20
|
+
return if size >= @max_size
|
21
|
+
|
22
|
+
@queue << item
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def pop
|
27
|
+
@queue.pop
|
28
|
+
end
|
29
|
+
|
30
|
+
def pop_count(count)
|
31
|
+
items = []
|
32
|
+
|
33
|
+
@queue_mutex.synchronize do
|
34
|
+
items << @queue.pop until @queue.empty? || items.size == count
|
35
|
+
end
|
36
|
+
|
37
|
+
items
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/semlogr/version.rb
CHANGED
data/lib/semlogr.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'semlogr/logger'
|
3
|
-
require 'semlogr/null_logger'
|
4
4
|
require 'semlogr/log_context'
|
5
|
+
require 'semlogr/null_logger'
|
6
|
+
require 'semlogr/self_logger'
|
7
|
+
require 'semlogr/version'
|
5
8
|
|
6
9
|
# Built-in enrichers
|
7
10
|
require 'semlogr/enrichers/event_type'
|
@@ -11,6 +14,7 @@ require 'semlogr/enrichers/property'
|
|
11
14
|
require 'semlogr/enrichers/thread'
|
12
15
|
|
13
16
|
# Built-in sinks
|
17
|
+
require 'semlogr/sinks/batching'
|
14
18
|
require 'semlogr/sinks/console'
|
15
19
|
require 'semlogr/sinks/colored_console'
|
16
20
|
require 'semlogr/sinks/file'
|
data/samples/basic.rb
CHANGED
data/samples/context.rb
CHANGED
data/samples/enrichment.rb
CHANGED
data/samples/filtering.rb
CHANGED
data/samples/log_context.rb
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'semlogr'
|
5
|
+
|
6
|
+
class TestSink
|
7
|
+
def emit(_log_event)
|
8
|
+
raise StandardError, 'emit error'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class TestEnricher
|
13
|
+
def enrich(_log_event)
|
14
|
+
raise StandardError, 'enrich error'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Semlogr::SelfLogger.logger = STDERR
|
19
|
+
Semlogr.logger = Semlogr::Logger.create do |c|
|
20
|
+
c.write_to :console
|
21
|
+
|
22
|
+
c.write_to TestSink.new
|
23
|
+
c.enrich_with TestEnricher.new
|
24
|
+
c.filter ->(_log_event) { raise StandardError, 'filter error' }
|
25
|
+
end
|
26
|
+
|
27
|
+
Semlogr.info('Customer {id} checked out', id: 123)
|
data/samples/sinks.rb
CHANGED
data/semlogr.gemspec
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
lib = File.expand_path('lib', __dir__)
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
5
|
|
@@ -31,4 +33,5 @@ Gem::Specification.new do |spec|
|
|
31
33
|
spec.add_development_dependency 'rspec', '~> 3.7'
|
32
34
|
spec.add_development_dependency 'rubocop', '0.53'
|
33
35
|
spec.add_development_dependency 'simplecov', '~>0.15'
|
36
|
+
spec.add_development_dependency 'timecop', '~>0.9'
|
34
37
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: semlogr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Sedich
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: digest-xxhash
|
@@ -164,6 +164,20 @@ dependencies:
|
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0.15'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: timecop
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0.9'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0.9'
|
167
181
|
description: A modern semantic logger for Ruby inspired by Serilog.
|
168
182
|
email:
|
169
183
|
- stefan.sedich@gmail.com
|
@@ -200,7 +214,9 @@ files:
|
|
200
214
|
- lib/semlogr/logger.rb
|
201
215
|
- lib/semlogr/null_logger.rb
|
202
216
|
- lib/semlogr/properties/output_properties.rb
|
217
|
+
- lib/semlogr/self_logger.rb
|
203
218
|
- lib/semlogr/sinks/aggregate.rb
|
219
|
+
- lib/semlogr/sinks/batching.rb
|
204
220
|
- lib/semlogr/sinks/colored_console.rb
|
205
221
|
- lib/semlogr/sinks/console.rb
|
206
222
|
- lib/semlogr/sinks/enriching.rb
|
@@ -211,12 +227,14 @@ files:
|
|
211
227
|
- lib/semlogr/templates/template.rb
|
212
228
|
- lib/semlogr/templates/template_cache.rb
|
213
229
|
- lib/semlogr/templates/text_token.rb
|
230
|
+
- lib/semlogr/utils/bounded_queue.rb
|
214
231
|
- lib/semlogr/version.rb
|
215
232
|
- samples/basic.rb
|
216
233
|
- samples/context.rb
|
217
234
|
- samples/enrichment.rb
|
218
235
|
- samples/filtering.rb
|
219
236
|
- samples/log_context.rb
|
237
|
+
- samples/self_logger.rb
|
220
238
|
- samples/sinks.rb
|
221
239
|
- semlogr.gemspec
|
222
240
|
homepage: https://github.com/semlogr/semlogr
|