logbert 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|