semlogr 0.3.0 → 0.3.1
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/.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
|