logbert 0.6.4
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/lib/logbert/formatters.rb +41 -0
- data/lib/logbert/handlers.rb +45 -0
- data/lib/logbert/levels.rb +106 -0
- data/lib/logbert/logger.rb +68 -0
- data/lib/logbert/logger_factory.rb +44 -0
- data/lib/logbert/message.rb +37 -0
- data/lib/logbert/naming.rb +20 -0
- data/lib/logbert.rb +20 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c133267e75a816038c4abdafba21f850d4a0731f
|
4
|
+
data.tar.gz: 6bd905d93430880aa4889e11e4ceb063f1581673
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 26f685bcedaf8d2fbfec4dc5caff3f212d5e9a3c10d547f07c785a95497e9fa0ca7c2d02b4efbd7faaa721c4278def872b34001f829671131f7035a1e3084d83
|
7
|
+
data.tar.gz: be0035b051689de397e889f75a3777bbecd806ad99720ea5201ff937ed39ede1506838e4f23b6e1b9a2c6e2c8d87d90e4fdf61cae53915c973cf635a4abc2cda
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
require 'logbert/message'
|
3
|
+
|
4
|
+
module Logbert
|
5
|
+
|
6
|
+
module Formatters
|
7
|
+
|
8
|
+
class Formatter
|
9
|
+
def format(msg)
|
10
|
+
raise NotImplementedError
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class SimpleFormatter < Formatter
|
15
|
+
def format(msg)
|
16
|
+
level = msg.level.to_s.upcase.ljust(8)
|
17
|
+
"#{level} [time='#{msg.time}' pid='#{msg.pid}' logger='#{msg.logger}'] : #{msg.content}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
class ProcFormatter < Formatter
|
23
|
+
attr_accessor :proc
|
24
|
+
|
25
|
+
def initialize(&block)
|
26
|
+
raise ArgumentError, "ProcFormatter must be initialized with a block" unless block_given?
|
27
|
+
@proc = block
|
28
|
+
end
|
29
|
+
|
30
|
+
def format(msg)
|
31
|
+
@proc.call msg
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.fmt(&block)
|
36
|
+
ProcFormatter.new(&block)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
require 'logbert/formatters'
|
3
|
+
|
4
|
+
module Logbert
|
5
|
+
module Handlers
|
6
|
+
|
7
|
+
|
8
|
+
class BaseHandler
|
9
|
+
|
10
|
+
def formatter
|
11
|
+
@formatter ||= Logbert::Formatters::SimpleFormatter.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def formatter=(value)
|
15
|
+
@formatter = value
|
16
|
+
end
|
17
|
+
|
18
|
+
def publish(message)
|
19
|
+
emit self.formatter.format(message)
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def emit(output)
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
class StreamHandler < BaseHandler
|
31
|
+
attr_accessor :stream
|
32
|
+
|
33
|
+
def initialize(stream = $stderr)
|
34
|
+
@stream = stream
|
35
|
+
end
|
36
|
+
|
37
|
+
def emit(output)
|
38
|
+
@stream.puts output
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
|
2
|
+
module Logbert
|
3
|
+
|
4
|
+
DefaultLevels = {
|
5
|
+
debug: 100,
|
6
|
+
info: 200,
|
7
|
+
warning: 300,
|
8
|
+
error: 400,
|
9
|
+
fatal: 500,
|
10
|
+
}
|
11
|
+
|
12
|
+
|
13
|
+
class Level
|
14
|
+
attr_reader :name, :value
|
15
|
+
|
16
|
+
def initialize(name, value)
|
17
|
+
@name = name
|
18
|
+
@value = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
@name.to_s
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# This class doubles as a mixin. Bazinga!
|
27
|
+
class LevelManager < Module
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@name_to_level = {}
|
31
|
+
@value_to_level = {}
|
32
|
+
|
33
|
+
@quick_lookup = {}
|
34
|
+
|
35
|
+
Logbert::DefaultLevels.each{|name, value| self.define_level(name, value)}
|
36
|
+
end
|
37
|
+
|
38
|
+
def names
|
39
|
+
@name_to_level.keys
|
40
|
+
end
|
41
|
+
|
42
|
+
def values
|
43
|
+
@value_to_level.keys
|
44
|
+
end
|
45
|
+
|
46
|
+
def levels
|
47
|
+
@name_to_level.values
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def define_level(name, value)
|
52
|
+
unless name.instance_of?(Symbol) or name.instance_of?(String)
|
53
|
+
raise ArgumentError, "The Level's name must be a Symbol or a String"
|
54
|
+
end
|
55
|
+
raise ArgumentError, "The Level's value must be an Integer" unless value.is_a? Integer
|
56
|
+
|
57
|
+
# TODO: Verify that the name/value are not already taken
|
58
|
+
raise KeyError, "A Level with that name is already defined: #{name}" if @name_to_level.has_key? name
|
59
|
+
raise KeyError, "A Level with that value is already defined: #{value}" if @value_to_level.has_key? value
|
60
|
+
|
61
|
+
level = Level.new(name, value)
|
62
|
+
|
63
|
+
@name_to_level[name] = level
|
64
|
+
@value_to_level[value] = level
|
65
|
+
@quick_lookup[name] = @quick_lookup[value] = @quick_lookup[level] = level
|
66
|
+
|
67
|
+
self.create_logging_method(name)
|
68
|
+
self.create_predicate_method(name, value)
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
def [](x)
|
73
|
+
@quick_lookup[x] or begin
|
74
|
+
if x.is_a? Integer
|
75
|
+
# Return either the pre-defined level, or produce a virtual level.
|
76
|
+
level = @value_to_level[x] || Logbert::Level.new("LEVEL_#{x}".to_sym, x)
|
77
|
+
return level
|
78
|
+
elsif x.is_a? String
|
79
|
+
level = @name_to_level[x.to_sym]
|
80
|
+
return level if level
|
81
|
+
end
|
82
|
+
|
83
|
+
raise KeyError, "No Level could be found for input: #{x}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
protected
|
89
|
+
|
90
|
+
def create_logging_method(level_name)
|
91
|
+
define_method level_name do |content = nil, &block|
|
92
|
+
self.log(level_name, content, &block)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def create_predicate_method(level_name, level_value)
|
97
|
+
define_method "#{level_name}?" do
|
98
|
+
self.level.value <= level_value
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
|
2
|
+
require 'logbert/message'
|
3
|
+
require 'logbert/handlers'
|
4
|
+
|
5
|
+
module Logbert
|
6
|
+
|
7
|
+
class Logger
|
8
|
+
|
9
|
+
attr_reader :factory, :level_manager, :name, :handlers
|
10
|
+
|
11
|
+
def initialize(factory, level_manager, name)
|
12
|
+
@factory = factory
|
13
|
+
@level_manager = level_manager
|
14
|
+
|
15
|
+
@name = name.dup.freeze
|
16
|
+
@handlers = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def level_inherited?
|
20
|
+
!!@level
|
21
|
+
end
|
22
|
+
|
23
|
+
def level
|
24
|
+
@level || self.parent.level
|
25
|
+
end
|
26
|
+
|
27
|
+
def level=(x)
|
28
|
+
@level = @level_manager[x]
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def parent
|
33
|
+
unless @parent_defined
|
34
|
+
@parent = @factory.parent_for(self)
|
35
|
+
@parent_defined = true
|
36
|
+
end
|
37
|
+
return @parent
|
38
|
+
end
|
39
|
+
|
40
|
+
def root
|
41
|
+
self.factory.root
|
42
|
+
end
|
43
|
+
|
44
|
+
def log(level, content = nil, &block)
|
45
|
+
message = Logbert::Message.create(self, @level_manager[level], content, &block)
|
46
|
+
handle_message(message)
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
@name
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
def handle_message(message)
|
57
|
+
if message.level.value >= self.level.value
|
58
|
+
@handlers.each{|h| h.publish message}
|
59
|
+
end
|
60
|
+
|
61
|
+
p = self.parent
|
62
|
+
p.handle_message(message) if p
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
require 'logbert/naming'
|
3
|
+
require 'logbert/logger'
|
4
|
+
require 'logbert/levels'
|
5
|
+
|
6
|
+
module Logbert
|
7
|
+
|
8
|
+
class LoggerFactory
|
9
|
+
|
10
|
+
attr_reader :level_manager
|
11
|
+
|
12
|
+
def initialize(level_manager = LevelManager.new)
|
13
|
+
@inventory = {}
|
14
|
+
@level_manager = level_manager
|
15
|
+
self.root.level = @level_manager[:warning]
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](name_or_module)
|
19
|
+
name = Logbert.name_for(name_or_module)
|
20
|
+
@inventory[name] ||= begin
|
21
|
+
l = Logger.new(self, @level_manager, name)
|
22
|
+
l.extend @level_manager
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def root
|
27
|
+
@root ||= self['']
|
28
|
+
end
|
29
|
+
|
30
|
+
def parent_for(logger)
|
31
|
+
n = logger.name
|
32
|
+
unless n.empty?
|
33
|
+
components = Logbert.split_name(n)
|
34
|
+
components.pop
|
35
|
+
parent_name = components.join(Logbert::NameSeparator)
|
36
|
+
return self[parent_name]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
module Logbert
|
3
|
+
|
4
|
+
class Message
|
5
|
+
attr_reader :logger, :level, :time, :pid, :content_proc
|
6
|
+
|
7
|
+
def initialize(logger, level, time, pid, content = nil, &content_proc)
|
8
|
+
@logger = logger
|
9
|
+
@level = level
|
10
|
+
@time = time
|
11
|
+
@pid = pid
|
12
|
+
|
13
|
+
@content = content
|
14
|
+
@content_proc = content_proc
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.create(logger, level, content = nil, &content_proc)
|
18
|
+
Message.new logger, level, Time.now, Process.pid, content, &content_proc
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the content. If the content has not been created yet,
|
22
|
+
# then call @content_proc and save the value.
|
23
|
+
def content
|
24
|
+
@content ||= begin
|
25
|
+
if @content_proc
|
26
|
+
@content_proc.call.to_s
|
27
|
+
else
|
28
|
+
""
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
module Logbert
|
3
|
+
|
4
|
+
NameSeparator = "/"
|
5
|
+
|
6
|
+
def self.split_name(name)
|
7
|
+
name.split(Logbert::NameSeparator).reject{|n| n.empty?}
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.name_for(n)
|
11
|
+
if n.is_a? Module
|
12
|
+
n.name.gsub("::", Logbert::NameSeparator)
|
13
|
+
else
|
14
|
+
Logbert.split_name(n.to_s).join(Logbert::NameSeparator)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
|
data/lib/logbert.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
require 'logbert/levels'
|
3
|
+
require 'logbert/logger_factory'
|
4
|
+
|
5
|
+
module Logbert
|
6
|
+
|
7
|
+
def self.factory
|
8
|
+
@factory ||= LoggerFactory.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.[](name)
|
12
|
+
self.factory[name]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.root
|
16
|
+
self.factory.root
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: logbert
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.6.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brian Lauber
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-14 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Change your logging behaviors without mucking with your code!
|
14
|
+
email: constructible.truth@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/logbert/formatters.rb
|
20
|
+
- lib/logbert/handlers.rb
|
21
|
+
- lib/logbert/levels.rb
|
22
|
+
- lib/logbert/logger.rb
|
23
|
+
- lib/logbert/logger_factory.rb
|
24
|
+
- lib/logbert/message.rb
|
25
|
+
- lib/logbert/naming.rb
|
26
|
+
- lib/logbert.rb
|
27
|
+
homepage:
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubyforge_project:
|
47
|
+
rubygems_version: 2.0.3
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: Logging for winners.
|
51
|
+
test_files: []
|