intake 0.1.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +20 -0
- data/lib/intake/async_sink.rb +52 -0
- data/lib/intake/event_drain.rb +26 -0
- data/lib/intake/filter.rb +13 -0
- data/lib/intake/filters/level_filter.rb +25 -0
- data/lib/intake/filters/logger_name_prefix_filter.rb +21 -0
- data/lib/intake/formatter.rb +16 -0
- data/lib/intake/io_sink.rb +22 -0
- data/lib/intake/level.rb +52 -0
- data/lib/intake/log_event.rb +20 -0
- data/lib/intake/logger.rb +80 -0
- data/lib/intake/mdc.rb +42 -0
- data/lib/intake/repository.rb +51 -0
- data/lib/intake/ruby_logger_adapter.rb +68 -0
- data/lib/intake/sink.rb +42 -0
- data/lib/intake/version.rb +5 -0
- data/lib/intake.rb +23 -0
- metadata +188 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: febaaa600f3b7a5c8ed974a8e059a4d5ea12e61b0e5edf6fb0bf3c707f56027b
|
4
|
+
data.tar.gz: 9bc82ce4ad485486a397e63c84c7a54445df78b2e3f285b1d0ec26d1cfddfdc8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bf360302e2ece8d18034a1b34587d3fa6c8a267f8d13ec64535b7de212e7307235b58b76a28c5f429fed832ee1ef4a1aa05c57391ba5cd74f98d207aa2c71033
|
7
|
+
data.tar.gz: d140b351c1171e9a5bce2e5e4d01926900300f60a8e18ce0c0c591cadcf54ac6ced6fa22b584cf3d8ad4dff754dfc31399613ba39a1b2a8a750869026c430ab1
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2022 Andrey Maraev
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# intake
|
2
|
+
|
3
|
+
## Description
|
4
|
+
|
5
|
+
**intake** is a powerful and easy to use logging library.
|
6
|
+
The library is designed with multiple base principles:
|
7
|
+
|
8
|
+
* Be a drop-in replacement for Ruby `Logger`
|
9
|
+
* Advanced API to support structured logging
|
10
|
+
* Highly efficient non-blocking logger API
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
```shell
|
15
|
+
gem install intake
|
16
|
+
```
|
17
|
+
|
18
|
+
## License
|
19
|
+
|
20
|
+
The MIT License. See the [LICENSE](/LICENSE) file for the full text.
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'concurrent'
|
4
|
+
require 'immutable/deque'
|
5
|
+
|
6
|
+
module Intake
|
7
|
+
# Received events and asynchronously forward events to downstream sink
|
8
|
+
class AsyncSink
|
9
|
+
def initialize(forward_sink)
|
10
|
+
@forward_sink = forward_sink
|
11
|
+
@drain_buffer = Concurrent::AtomicReference.new
|
12
|
+
@drain_buffer.set(Immutable::Deque.empty)
|
13
|
+
@has_events_flag = Concurrent::Event.new
|
14
|
+
@drain_thread = Thread.new { drain_thread_func }
|
15
|
+
end
|
16
|
+
|
17
|
+
def receive(event)
|
18
|
+
@drain_buffer.update { |buffer| buffer.push(event) }
|
19
|
+
@has_events_flag.set
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def drain_thread_func
|
25
|
+
@has_events_flag.reset
|
26
|
+
|
27
|
+
loop do
|
28
|
+
@has_events_flag.wait(0.1)
|
29
|
+
@has_events_flag.reset
|
30
|
+
|
31
|
+
drain_backlog(snapshot_backlog)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def snapshot_backlog
|
36
|
+
backlog = nil
|
37
|
+
loop do
|
38
|
+
backlog = @drain_buffer.get
|
39
|
+
break if @drain_buffer.compare_and_set(backlog, Immutable::Deque.empty)
|
40
|
+
end
|
41
|
+
backlog
|
42
|
+
end
|
43
|
+
|
44
|
+
def drain_backlog(backlog)
|
45
|
+
until backlog.empty?
|
46
|
+
e = backlog.first
|
47
|
+
backlog = backlog.shift
|
48
|
+
@forward_sink.receive(e)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
module Intake
|
6
|
+
# EventDrain is a single receiver of messages from loggers. EventDrain forward events to registered sinks
|
7
|
+
class EventDrain
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@sinks = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_sink(sink)
|
15
|
+
@sinks << sink
|
16
|
+
end
|
17
|
+
|
18
|
+
def drain(event)
|
19
|
+
@sinks.each { |s| s.receive(event) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def clear_sinks
|
23
|
+
@sinks.clear
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Intake
|
4
|
+
# Filter is a proc-like object that filters events to be accepted by [Intake::Sink]
|
5
|
+
class Filter
|
6
|
+
# Applies filter to the event
|
7
|
+
# @param event [Intake::Event] event to filter
|
8
|
+
# @return [Boolean] true if [Intake::Sink] should accept the event; false otherwise
|
9
|
+
def call(_event)
|
10
|
+
true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../level'
|
4
|
+
require_relative '../filter'
|
5
|
+
|
6
|
+
module Intake
|
7
|
+
module Filters
|
8
|
+
# Filter by event level. Pass if event level is greater or equal to filter level.
|
9
|
+
class LevelFilter < Filter
|
10
|
+
# Initializes new instance of [Intake::Filters::LevelFilter]
|
11
|
+
# @param limit_level [Intake::Level|Symbol] filter level
|
12
|
+
def initialize(limit_level)
|
13
|
+
super()
|
14
|
+
@limit_level = Intake::Level[limit_level]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Applies filter to the event
|
18
|
+
# @argument event [Intake::Event] event to test
|
19
|
+
# @return [Boolean] true if event pass the filter; false otherwise
|
20
|
+
def call(event)
|
21
|
+
event.level >= @limit_level
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../filter'
|
4
|
+
|
5
|
+
module Intake
|
6
|
+
module Filters
|
7
|
+
# Filter event by logger name. Pass if logger name starts with logger prefix.
|
8
|
+
class LoggerNamePrefixFilter < Intake::Filter
|
9
|
+
def initialize(prefix, include_root: true)
|
10
|
+
super()
|
11
|
+
@prefix = prefix
|
12
|
+
@include_root = include_root
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(event)
|
16
|
+
name = event.logger_name
|
17
|
+
(@include_root && name == :root) || name.start_with?(@prefix)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Intake
|
4
|
+
# Base class that serializes event to data format acceptable by sink (usually it's [String])
|
5
|
+
class Formatter
|
6
|
+
def initialize
|
7
|
+
@timestamp_format = '%Y-%m-%dT%H:%M:%S.%6N'
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(event)
|
11
|
+
# rubocop:disable Layout/LineLength
|
12
|
+
"#{event.level.to_s[0]}, [#{event.timestamp.strftime(@timestamp_format)} ##{Process.pid}] #{event.level} -- #{event[:progname]}: #{event.message}\n"
|
13
|
+
# rubocop:enable Layout/LineLength
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'formatter'
|
4
|
+
require_relative 'sink'
|
5
|
+
|
6
|
+
module Intake
|
7
|
+
# Sink that writes log events to IO stream, e.g., STDOUT or file stream
|
8
|
+
class IOSink < Sink
|
9
|
+
def initialize(io)
|
10
|
+
super()
|
11
|
+
@io = io
|
12
|
+
@formatter = ::Intake::Formatter.new
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_writer :formatter
|
16
|
+
|
17
|
+
def drain(event)
|
18
|
+
txt = @formatter.call(event)
|
19
|
+
@io.write(txt)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/intake/level.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Intake
|
4
|
+
# Log event level.
|
5
|
+
class Level
|
6
|
+
class << self
|
7
|
+
def []=(name, level)
|
8
|
+
(@s ||= {})[name] = level
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](name)
|
12
|
+
(@s ||= {})[name]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :name, :val
|
17
|
+
|
18
|
+
def initialize(name, val)
|
19
|
+
@val = val
|
20
|
+
@name = name
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
@name.to_s.upcase
|
25
|
+
end
|
26
|
+
|
27
|
+
def <(other)
|
28
|
+
@val < other.val
|
29
|
+
end
|
30
|
+
|
31
|
+
def <=(other)
|
32
|
+
@val <= other.val
|
33
|
+
end
|
34
|
+
|
35
|
+
def >(other)
|
36
|
+
@val > other.val
|
37
|
+
end
|
38
|
+
|
39
|
+
def >=(other)
|
40
|
+
@val >= other.val
|
41
|
+
end
|
42
|
+
|
43
|
+
def ==(other)
|
44
|
+
@val == other.val
|
45
|
+
end
|
46
|
+
|
47
|
+
# Define Intake levels
|
48
|
+
[[:debug, 1000], [:info, 2000], [:warn, 3000], [:error, 4000], [:fatal, 5000]].each do |(n, v)|
|
49
|
+
::Intake::Level[n] = ::Intake::Level.new(n, v).freeze
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Intake
|
4
|
+
# Represents a log event.
|
5
|
+
class LogEvent
|
6
|
+
attr_reader :timestamp, :level, :logger_name, :message, :data
|
7
|
+
|
8
|
+
def initialize(timestamp, level, logger_name, msg, meta: nil)
|
9
|
+
@data = (meta || {}).freeze
|
10
|
+
@timestamp = timestamp
|
11
|
+
@level = level
|
12
|
+
@logger_name = logger_name
|
13
|
+
@message = msg
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](key)
|
17
|
+
@data[key]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
require_relative 'event_drain'
|
6
|
+
require_relative 'level'
|
7
|
+
require_relative 'log_event'
|
8
|
+
require_relative 'mdc'
|
9
|
+
require_relative 'repository'
|
10
|
+
|
11
|
+
module Intake
|
12
|
+
# Logger is a object that captures log event and forward that to event sinks.
|
13
|
+
class Logger
|
14
|
+
class << self
|
15
|
+
def [](name)
|
16
|
+
::Intake::Repository.instance.get_or_add(name) do |logger_name|
|
17
|
+
Logger.new(logger_name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :name
|
23
|
+
|
24
|
+
def initialize(name)
|
25
|
+
validate_name(name)
|
26
|
+
|
27
|
+
@name = name
|
28
|
+
@level = ::Intake::Level[:info]
|
29
|
+
end
|
30
|
+
|
31
|
+
def level?(level)
|
32
|
+
@level.val <= level.val
|
33
|
+
end
|
34
|
+
|
35
|
+
def level=(level)
|
36
|
+
@level = case level
|
37
|
+
when String, Symbol then ::Intake::Level[level.to_sym]
|
38
|
+
when ::Intake::Level then level
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
%i[debug info warn error fatal].each do |level|
|
43
|
+
code = <<-CODE
|
44
|
+
undef :#{level} if method_defined? :#{level}
|
45
|
+
LEVEL_#{level} = ::Intake::Level[:#{level}]
|
46
|
+
|
47
|
+
def #{level}(msg = nil, meta: nil, error: nil, &block)
|
48
|
+
log_event(LEVEL_#{level}, msg, meta: meta, error: error, &block)
|
49
|
+
end
|
50
|
+
CODE
|
51
|
+
class_eval(code)
|
52
|
+
end
|
53
|
+
|
54
|
+
def log_event(level, msg = nil, meta: nil, error: nil)
|
55
|
+
return false unless level?(level)
|
56
|
+
|
57
|
+
msg = yield if msg.nil? && block_given?
|
58
|
+
meta ||= {}
|
59
|
+
meta[:error] = error unless error.nil?
|
60
|
+
meta.merge!(MDC.items) if MDC.any?
|
61
|
+
event = ::Intake::LogEvent.new(Time.now, level, @name, msg, meta: meta)
|
62
|
+
dispatch_event event
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def validate_name(name)
|
68
|
+
case name
|
69
|
+
when String
|
70
|
+
raise ArgumentError, 'logger name must not be empty' if name.empty?
|
71
|
+
else
|
72
|
+
raise ArgumentError, 'logger name must be a string'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def dispatch_event(event)
|
77
|
+
EventDrain.instance.drain(event)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/intake/mdc.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Intake
|
4
|
+
# Mapped Diagnostic Context (MDC) is thread-aware Hash-like storage to add extra context details to logged events.
|
5
|
+
module MDC
|
6
|
+
SYNC_MUTEX = Mutex.new
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def []=(key, value)
|
10
|
+
context[key] = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def clear(key)
|
14
|
+
context.delete(key)
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def store(key, value)
|
19
|
+
MDC[key] = value
|
20
|
+
end
|
21
|
+
|
22
|
+
def any?
|
23
|
+
context.any?
|
24
|
+
end
|
25
|
+
|
26
|
+
def items
|
27
|
+
context.dup.freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def context
|
33
|
+
if Thread.current[:intake_mdc].nil?
|
34
|
+
SYNC_MUTEX.synchronize do
|
35
|
+
Thread.current[:intake_mdc] = {} if Thread.current[:intake_mdc].nil?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
Thread.current[:intake_mdc]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
module Intake
|
6
|
+
# Repository stores references to loggers by logger name.
|
7
|
+
class Repository
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
# Initializes new instance of [Intake] class.
|
11
|
+
def initialize
|
12
|
+
@store = {}
|
13
|
+
@mutex = Mutex.new
|
14
|
+
end
|
15
|
+
|
16
|
+
# Tests if logger with given name exists
|
17
|
+
# @return [Boolean] true if logger exists; false otherwise.
|
18
|
+
def key?(name)
|
19
|
+
@store.key? canonize_name(name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_or_add(name)
|
23
|
+
name = canonize_name(name)
|
24
|
+
logger = @store[name]
|
25
|
+
|
26
|
+
if logger.nil?
|
27
|
+
logger = @mutex.synchronize do
|
28
|
+
@store[name] = yield(name) unless @store.key?(name)
|
29
|
+
@store[name]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
logger
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def canonize_name(name)
|
38
|
+
case name
|
39
|
+
when :root, 'root' then 'root'
|
40
|
+
when String then name
|
41
|
+
when Symbol then name.to_s
|
42
|
+
when Module then module_name(name)
|
43
|
+
when Object then module_name(name.class)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def module_name(mod)
|
48
|
+
mod.name
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
require_relative 'level'
|
6
|
+
require_relative 'logger'
|
7
|
+
|
8
|
+
module Intake
|
9
|
+
# Logger is a object that captures log event and forward that to event sinks.
|
10
|
+
class Logger
|
11
|
+
def as_ruby_logger(progname: nil)
|
12
|
+
RubyLoggerAdapter.new(self, progname)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Adapter for [Intake::Logger] to match [::Logger] interface.
|
17
|
+
class RubyLoggerAdapter
|
18
|
+
[
|
19
|
+
[::Logger::DEBUG, ::Intake::Level[:debug]],
|
20
|
+
[::Logger::INFO, ::Intake::Level[:info]],
|
21
|
+
[::Logger::WARN, ::Intake::Level[:warn]],
|
22
|
+
[::Logger::ERROR, ::Intake::Level[:error]],
|
23
|
+
[::Logger::FATAL, ::Intake::Level[:fatal]],
|
24
|
+
[::Logger::UNKNOWN, ::Intake::Level[:fatal]]
|
25
|
+
].each do |(n, v)|
|
26
|
+
::Intake::Level[n] = v
|
27
|
+
end
|
28
|
+
|
29
|
+
%i[DEBUG INFO WARN ERROR FATAL UNKNOWN].each do |l|
|
30
|
+
code = <<-CODE
|
31
|
+
LEVEL_#{l} = ::Intake::Level[::Logger::Severity::#{l}]
|
32
|
+
|
33
|
+
def #{l.downcase}(progname = nil, &block)
|
34
|
+
log_event(LEVEL_#{l}, nil, progname, &block)
|
35
|
+
end
|
36
|
+
CODE
|
37
|
+
class_eval(code)
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(logger, progname)
|
41
|
+
@progname = progname
|
42
|
+
@logger = logger
|
43
|
+
@meta = { progname: @progname }
|
44
|
+
end
|
45
|
+
|
46
|
+
def add(severity, message = nil, progname = nil, &block)
|
47
|
+
severity = ::Intake::Level[severity] unless severity.is_a? ::Intake::Level
|
48
|
+
log_event(severity, message, progname, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def log_event(severity, message, progname, &block)
|
54
|
+
return true unless @logger.level?(severity)
|
55
|
+
|
56
|
+
progname = @progname if progname.nil?
|
57
|
+
|
58
|
+
if message.nil? && block.nil?
|
59
|
+
message = progname
|
60
|
+
progname = @progname
|
61
|
+
end
|
62
|
+
|
63
|
+
meta = progname == @progname ? @meta : { progname: progname }
|
64
|
+
@logger.log_event(severity, message, meta: meta, &block)
|
65
|
+
true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/intake/sink.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'filter'
|
4
|
+
|
5
|
+
module Intake
|
6
|
+
# Sink receives log event and writes to a permanent storage.
|
7
|
+
class Sink
|
8
|
+
def initialize
|
9
|
+
@filters = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def flush
|
13
|
+
@has_events_flag.set if @thread_model == :dedicated_thread
|
14
|
+
end
|
15
|
+
|
16
|
+
def receive(event)
|
17
|
+
return unless accept_event?(event)
|
18
|
+
|
19
|
+
drain event
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_filter(filter)
|
23
|
+
@filters << filter
|
24
|
+
end
|
25
|
+
|
26
|
+
# Receives a message and write to a permanent storage
|
27
|
+
def drain(_event)
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def accept_event?(event)
|
34
|
+
proceed = true
|
35
|
+
@filters.each do |f|
|
36
|
+
proceed &&= f.call(event)
|
37
|
+
break unless proceed
|
38
|
+
end
|
39
|
+
proceed
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/intake.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'intake/async_sink'
|
4
|
+
require_relative 'intake/io_sink'
|
5
|
+
require_relative 'intake/logger'
|
6
|
+
require_relative 'intake/version'
|
7
|
+
require_relative 'intake/filters/level_filter'
|
8
|
+
require_relative 'intake/filters/logger_name_prefix_filter'
|
9
|
+
|
10
|
+
# Public API module of intake logger
|
11
|
+
module Intake
|
12
|
+
def self.[](logger_name)
|
13
|
+
Intake::Logger[logger_name]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.add_sink(sink)
|
17
|
+
Intake::EventDrain.instance.add_sink sink
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.clear_sinks
|
21
|
+
Intake::EventDrain.instance.clear_sinks
|
22
|
+
end
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: intake
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrey Maraev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-10-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: concurrent-ruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.1.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.1.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: concurrent-ruby-ext
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.1.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.1.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: immutable-ruby
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.1.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.1.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: code-scanning-rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.6.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.6.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: debug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.6.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.6.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 13.0.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 13.0.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.11.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 3.11.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.36.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.36.0
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: simplecov
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.21.2
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 0.21.2
|
139
|
+
description:
|
140
|
+
email:
|
141
|
+
- the_vk@thevk.net
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- LICENSE
|
147
|
+
- README.md
|
148
|
+
- lib/intake.rb
|
149
|
+
- lib/intake/async_sink.rb
|
150
|
+
- lib/intake/event_drain.rb
|
151
|
+
- lib/intake/filter.rb
|
152
|
+
- lib/intake/filters/level_filter.rb
|
153
|
+
- lib/intake/filters/logger_name_prefix_filter.rb
|
154
|
+
- lib/intake/formatter.rb
|
155
|
+
- lib/intake/io_sink.rb
|
156
|
+
- lib/intake/level.rb
|
157
|
+
- lib/intake/log_event.rb
|
158
|
+
- lib/intake/logger.rb
|
159
|
+
- lib/intake/mdc.rb
|
160
|
+
- lib/intake/repository.rb
|
161
|
+
- lib/intake/ruby_logger_adapter.rb
|
162
|
+
- lib/intake/sink.rb
|
163
|
+
- lib/intake/version.rb
|
164
|
+
homepage: https://github.com/the-vk/intake
|
165
|
+
licenses:
|
166
|
+
- MIT
|
167
|
+
metadata:
|
168
|
+
rubygems_mfa_required: 'true'
|
169
|
+
post_install_message:
|
170
|
+
rdoc_options: []
|
171
|
+
require_paths:
|
172
|
+
- lib
|
173
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
174
|
+
requirements:
|
175
|
+
- - "~>"
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
version: '3.0'
|
178
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
|
+
requirements:
|
180
|
+
- - ">="
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: '0'
|
183
|
+
requirements: []
|
184
|
+
rubygems_version: 3.3.3
|
185
|
+
signing_key:
|
186
|
+
specification_version: 4
|
187
|
+
summary: Powerful and extensible logging library
|
188
|
+
test_files: []
|