hatchet 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Hatchet
4
+
5
+ # Public: Class for configuring Hatchet.
6
+ #
7
+ class Configuration
8
+ include LevelManager
9
+
10
+ # Public: The Array of configured appenders.
11
+ #
12
+ attr_reader :appenders
13
+
14
+ # Internal: Creates a new configuration.
15
+ #
16
+ # Creates the levels Hash with a default logging level of info.
17
+ #
18
+ def initialize
19
+ @levels = { nil => :info }
20
+ @appenders = []
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
@@ -0,0 +1,58 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Hatchet
4
+
5
+ # Public: Module for managing the configuration of log levels on a class or
6
+ # module level. Useful when you are creating custom appenders.
7
+ #
8
+ module LevelManager
9
+
10
+ # Private: All the possible levels of log filter in order of severity.
11
+ #
12
+ LEVELS = [:debug, :info, :warn, :error, :fatal, :off]
13
+
14
+ # Public: The Hash containing the log level configuration.
15
+ #
16
+ attr_accessor :levels
17
+
18
+ # Public: Set the lowest level of message to log for the given context.
19
+ #
20
+ # level - The lowest level of message to log for the given context.
21
+ # context - The context that level applies to (default: nil).
22
+ #
23
+ # Setting a level for nil set the default level for all contexts that have
24
+ # not been specified.
25
+ #
26
+ # Returns nothing.
27
+ def level(level, context = nil)
28
+ context = context.to_s unless context.nil?
29
+ self.levels[context] = level
30
+ end
31
+
32
+ # Internal: Returns true if the appender is configured to log messages of
33
+ # the given level within the given context, otherwise returns false.
34
+ #
35
+ # level - The level of the message.
36
+ # context - The context of the message.
37
+ #
38
+ # Returns true if the appender is configured to log messages of the given
39
+ # level within the given context, otherwise returns false.
40
+ #
41
+ def enabled?(level, context)
42
+ unless self.levels.key? context
43
+ lvl = self.levels[nil]
44
+ root = []
45
+ context.to_s.split('::').each do |part|
46
+ root << part
47
+ path = root.join '::'
48
+ lvl = self.levels[path] if self.levels.key? path
49
+ end
50
+ self.levels[context] = lvl
51
+ end
52
+ LEVELS.index(level) >= LEVELS.index(self.levels[context])
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
@@ -0,0 +1,102 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Hatchet
4
+
5
+ # Internal: Class that handles logging calls and distributes them to all its
6
+ # appenders.
7
+ #
8
+ # Each logger has 6 methods. Those are, in decreasing order of severity:
9
+ #
10
+ # * fatal
11
+ # * error
12
+ # * warn
13
+ # * info
14
+ # * debug
15
+ # * trace
16
+ #
17
+ # All the methods have the same signature. You can either provide a message as
18
+ # a direct string, or as a block to the method is lazily evaluated (this is
19
+ # the recommended option).
20
+ #
21
+ # Examples
22
+ #
23
+ # logger.info "Informational message"
24
+ # logger.info { "Informational message #{potentially_expensive}" }
25
+ #
26
+ # Log messages are sent to each appender where they will be filtered and
27
+ # invoked as configured.
28
+ #
29
+ class Logger
30
+
31
+ # Internal: Creates a new logger.
32
+ #
33
+ # host - The object the logger gains its context from.
34
+ # appenders - The appenders the logger delegates its messages to.
35
+ #
36
+ def initialize(host, appenders)
37
+ @context = context host
38
+ @appenders = appenders
39
+ end
40
+
41
+ # Public: Logs a message at the given level.
42
+ #
43
+ # message - An already evaluated message, usually a String (default: nil).
44
+ # block - An optional block which will provide a message when invoked.
45
+ #
46
+ # One of message or block must be provided. If both are provided then the
47
+ # block is preferred as it is assumed to provide more detail.
48
+ #
49
+ # Returns nothing.
50
+ #
51
+ [:trace, :debug, :info, :warn, :error, :fatal].each do |level|
52
+ define_method level do |message = nil, &block|
53
+ return unless message or block
54
+ add level, Message.new(message, &block)
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ # Private: Adds a message to each appender at the specified level.
61
+ #
62
+ # level - The level of the message. One of, in decreasing order of
63
+ # severity:
64
+ #
65
+ # * fatal
66
+ # * error
67
+ # * warn
68
+ # * info
69
+ # * debug
70
+ # * trace
71
+ #
72
+ # message - The message that will be logged by an appender when it is
73
+ # configured to log at the given level or lower.
74
+ #
75
+ # Returns nothing.
76
+ #
77
+ def add(level, message)
78
+ @appenders.each { |appender| appender.add(level, @context, message) }
79
+ end
80
+
81
+ # Private: Determines the contextual name of the host object.
82
+ #
83
+ # host - The object hosting this logger.
84
+ #
85
+ # Returns the String 'main' if this is the initial execution context of
86
+ # Ruby, the host itself when the host is a module, otherwise the object's
87
+ # class.
88
+ #
89
+ def context(host)
90
+ if host.inspect == 'main'
91
+ 'main'
92
+ elsif host.class == Module
93
+ host
94
+ else
95
+ host.class
96
+ end
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+
@@ -0,0 +1,71 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'logger'
4
+
5
+ module Hatchet
6
+
7
+ # Public: Class for wrapping a standard Logger with Hatchet's class/module
8
+ # level log filtering.
9
+ #
10
+ class LoggerAppender
11
+ include LevelManager
12
+
13
+ # Public: The Logger the appender encapsulates.
14
+ #
15
+ attr_accessor :logger
16
+
17
+ # Public: The formatter used to format the message before they are sent to
18
+ # the logger.
19
+ #
20
+ attr_accessor :formatter
21
+
22
+ # Public: Creates a new Logger appender.
23
+ #
24
+ # options - The Hash options used to setup the appender (default: {}).
25
+ # :formatter - The formatter used to format log messages.
26
+ # :levels - The configuration of logging levels to the
27
+ # class/module level.
28
+ # :logger - The Logger messages are sent to. It will have its
29
+ # formatter changed to delegate entirely to the
30
+ # appender's formatter and its level set to debug so
31
+ # that it does not filter out any messages it is
32
+ # sent.
33
+ # block - Optional block that can be used to customize the appender. The
34
+ # appender itself is passed to the block.
35
+ #
36
+ # Once the values from the options Hash have been applied and any
37
+ # modifications are made within the block the appender should have its
38
+ # levels, logger, and formatter set.
39
+ #
40
+ def initialize(options = {})
41
+ @formatter = options[:formatter]
42
+ @logger = options[:logger]
43
+ @levels = options[:levels] || {}
44
+
45
+ yield self if block_given?
46
+
47
+ @logger.level = ::Logger::DEBUG
48
+ @logger.formatter = proc do |severity, datetime, progname, msg|
49
+ "#{msg}\n"
50
+ end
51
+ end
52
+
53
+ # Internal: Adds a message to the appender if the appender is configured to
54
+ # log messages at the given level for the given context.
55
+ #
56
+ # level - The level of the message.
57
+ # context - The context of the message.
58
+ # message - The message to add to the appender if it is configured to log
59
+ # messages at the given level for the given context.
60
+ #
61
+ # Returns nothing.
62
+ #
63
+ def add(level, context, message)
64
+ return unless enabled? level, context
65
+ @logger.send level, @formatter.format(level, context, message)
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
@@ -0,0 +1,39 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Hatchet
4
+
5
+ # Internal: Class for wrapping message strings and blocks in a way that means
6
+ # they can be treated identically.
7
+ #
8
+ # Blocks will be lazily evaluated once for all appenders when required.
9
+ #
10
+ class Message
11
+
12
+ # Internal: Creates a new message.
13
+ #
14
+ # message - An already evaluated message, usually a String (default: nil).
15
+ # block - An optional block which will provide a message when invoked.
16
+ #
17
+ # One of message or block must be provided. If both are provided then the
18
+ # block is preferred as it is assumed to provide more detail.
19
+ #
20
+ # Examples
21
+ #
22
+ # Message.new "Evaluated message"
23
+ # Message.new { "Lazily evaluated message" }
24
+ #
25
+ def initialize(message = nil, &block)
26
+ @block = block
27
+ @message = message unless @block
28
+ end
29
+
30
+ # Internal: Returns the String representation of the message.
31
+ #
32
+ def to_s
33
+ @message ||= @block.call
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
@@ -0,0 +1,43 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Hatchet
4
+
5
+ # Public: Standard formatter class.
6
+ #
7
+ class StandardFormatter
8
+
9
+ # Public: Returns the formatted message.
10
+ #
11
+ # level - The severity of the log message.
12
+ # context - The context of the log message.
13
+ # message - The message provided by the log caller.
14
+ #
15
+ # Returns the context and message separated by a hypen.
16
+ #
17
+ def format(level, context, message)
18
+ "#{timestamp} [#{thread_name}] #{level.to_s.upcase.ljust 5} #{message}"
19
+ end
20
+
21
+ private
22
+
23
+ # Private: Returns the current time as a String.
24
+ #
25
+ def timestamp
26
+ Time.now.strftime('%Y-%m-%d %H:%M:%S.%L')
27
+ end
28
+
29
+ # Private: Returns the name of the current thread from the processes pid and
30
+ # the threads object_id when it is not the main thread for the process.
31
+ #
32
+ def thread_name
33
+ if Thread.current == Thread.main
34
+ Process.pid
35
+ else
36
+ "#{Process.pid}##{Thread.current.object_id}"
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
@@ -1,3 +1,9 @@
1
+ # -*- encoding: utf-8 -*-
2
+
1
3
  module Hatchet
2
- VERSION = "0.0.1"
4
+
5
+ # Public: The version of Hatchet.
6
+ #
7
+ VERSION = "0.0.2"
8
+
3
9
  end
data/lib/hatchet.rb CHANGED
@@ -1,22 +1,119 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require_relative 'hatchet/level_manager'
4
+ require_relative 'hatchet/configuration'
5
+ require_relative 'hatchet/logger'
6
+ require_relative 'hatchet/logger_appender'
7
+ require_relative 'hatchet/message'
8
+ require_relative 'hatchet/standard_formatter'
1
9
  require_relative 'hatchet/version'
2
10
 
11
+ # Public: Hatchet is a library for providing logging facilities whose levels are
12
+ # configurable to the class and module level.
13
+ #
14
+ # It also provides the facility to have several appenders added to from a single
15
+ # log call with each appender capable of being configured to log at different
16
+ # levels.
17
+ #
18
+ # Hatchet provides no logging implementations of its own. Instead it delegates
19
+ # to the standard Logger within the reference LoggerAppender implementation.
20
+ #
3
21
  module Hatchet
4
22
 
23
+ # Public: Returns a Logger for the object.
24
+ #
25
+ # The returned logger has 5 methods. Those are, in decreasing order of
26
+ # severity:
27
+ #
28
+ # * fatal
29
+ # * error
30
+ # * warn
31
+ # * info
32
+ # * debug
33
+ #
34
+ # All the methods have the same signature. You can either provide a message as
35
+ # a direct string, or as a block to the method is lazily evaluated (this is
36
+ # the recommended option).
37
+ #
38
+ # Examples
39
+ #
40
+ # logger.info "Informational message"
41
+ # logger.info { "Informational message #{potentially_expensive}" }
42
+ #
43
+ # Log messages are sent to appender where they will be filtered and invoked as
44
+ # configured.
45
+ #
46
+ # Returns a Logger for the object.
47
+ #
5
48
  def logger
6
49
  @_hatchet_logger ||= Logger.new self, Hatchet.appenders
7
50
  end
8
51
 
52
+ # Public: Returns a logger for the object.
53
+ #
54
+ # The returned logger has 5 methods. Those are, in decreasing order of
55
+ # severity:
56
+ #
57
+ # * fatal
58
+ # * error
59
+ # * warn
60
+ # * info
61
+ # * debug
62
+ #
63
+ # All the methods have the same signature. You can either provide a message as
64
+ # a direct string, or as a block to the method is lazily evaluated (this is
65
+ # the recommended option).
66
+ #
67
+ # Examples
68
+ #
69
+ # log.info "Informational message"
70
+ # log.info { "Informational message #{potentially_expensive}" }
71
+ #
72
+ # Log messages are sent to appender where they will be filtered and invoked as
73
+ # configured.
74
+ #
75
+ # Returns a Logger for the object.
76
+ #
9
77
  alias_method :log, :logger
10
78
 
79
+ # Public: Method for configuring Hatchet.
80
+ #
81
+ # block - Mandatory block which receives a Configuration object that can be
82
+ # used to setup Hatchet.
83
+ #
84
+ # Once the block returns each of the configured appenders has its formatter
85
+ # set as a StandardFormatter if one is not already set, and its levels Hash is
86
+ # set to the shared levels Hash if an explicit one has not been provided.
87
+ #
88
+ # Example
89
+ #
90
+ # Hatchet.configure do |config|
91
+ # # Set the level to use unless overridden (defaults to :info)
92
+ # config.level :info
93
+ # # Set the level for a specific class/module and its children (can be a
94
+ # # string)
95
+ # config.level :debug, Namespace::Something::Nested
96
+ #
97
+ # # Add as many appenders as you like, Hatchet comes with one that formats
98
+ # # the standard logger in the TTCC style of log4j.
99
+ # config.appenders << Hatchet::LoggerAppender.new do |appender|
100
+ # # Set the logger that this is wrapping (required)
101
+ # appender.logger = Logger.new('log/test.log')
102
+ # end
103
+ # end
104
+ #
105
+ # Returns nothing.
11
106
  def self.configure
12
107
  @@config = Configuration.new
13
108
  yield @@config
14
109
  @@config.appenders.each do |appender|
15
110
  appender.formatter ||= StandardFormatter.new
16
- appender.levels ||= @@config.levels
111
+ appender.levels = @@config.levels if appender.levels.empty?
17
112
  end
18
113
  end
19
114
 
115
+ # Internal: Returns the Array of configured appenders.
116
+ #
20
117
  def self.appenders
21
118
  if @@config and @@config.appenders
22
119
  @@config.appenders
@@ -25,121 +122,5 @@ module Hatchet
25
122
  end
26
123
  end
27
124
 
28
- class LoggerAppender
29
-
30
- LEVELS = [:trace, :debug, :info, :warn, :error, :fatal, :off]
31
-
32
- attr_accessor :levels
33
-
34
- attr_accessor :logger
35
-
36
- attr_accessor :formatter
37
-
38
- def initialize(args = {})
39
- @logger = args[:logger]
40
- @formatter = args[:formatter]
41
- yield self
42
- @logger.formatter = proc do |severity, datetime, progname, msg|
43
- "#{timestamp} [#{thread_name}] #{severity.ljust 5} #{msg}\n"
44
- end
45
- end
46
-
47
- def add(level, context, msg)
48
- return unless enabled? context, level
49
- @logger.send level, @formatter.format(context, msg)
50
- end
51
-
52
- def enabled?(context, level)
53
- unless self.levels.key? context
54
- lvl = self.levels[nil]
55
- root = []
56
- context.to_s.split('::').each do |part|
57
- root << part
58
- path = root.join '::'
59
- lvl = self.levels[path] if self.levels.key? path
60
- end
61
- self.levels[context] = lvl
62
- end
63
- LEVELS.index(level) >= LEVELS.index(self.levels[context])
64
- end
65
-
66
- private
67
-
68
- def timestamp
69
- Time.now.strftime('%Y-%m-%d %H:%M:%S.%L')
70
- end
71
-
72
- def thread_name
73
- if Thread.current == Thread.main
74
- Process.pid
75
- else
76
- "#{Process.pid}##{Thread.current.object_id}"
77
- end
78
- end
79
-
80
- end
81
-
82
- class StandardFormatter
83
-
84
- def format(context, msg)
85
- "#{context} - #{msg.call}"
86
- end
87
-
88
- end
89
-
90
- class Configuration
91
-
92
- attr_reader :levels
93
-
94
- attr_reader :appenders
95
-
96
- def initialize
97
- @levels = {}
98
- @levels[nil] = :info
99
- @appenders = []
100
- yield self if block_given?
101
- end
102
-
103
- def level(level, context = nil)
104
- context = context.to_s unless context.nil?
105
- @levels[context] = level
106
- end
107
-
108
- end
109
-
110
- class Logger
111
-
112
- def initialize(host, appenders)
113
- @context = context host
114
- @appenders = appenders
115
- end
116
-
117
- [:trace, :debug, :info, :warn, :error, :fatal].reverse.each do |level|
118
- define_method level do |*args, &block|
119
- msg = args[0]
120
- block = Proc.new { msg } unless msg.nil? or block
121
- return if block.nil?
122
- add level, block
123
- end
124
- end
125
-
126
- private
127
-
128
- def add(level, msg)
129
- @appenders.each { |appender| appender.add(level, @context, msg) }
130
- end
131
-
132
- def context(host)
133
- if host.inspect == 'main'
134
- 'main'
135
- elsif host.class == Module
136
- host
137
- else
138
- host.class
139
- end
140
- end
141
-
142
- end
143
-
144
125
  end
145
126
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hatchet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -19,6 +19,12 @@ executables: []
19
19
  extensions: []
20
20
  extra_rdoc_files: []
21
21
  files:
22
+ - lib/hatchet/configuration.rb
23
+ - lib/hatchet/level_manager.rb
24
+ - lib/hatchet/logger.rb
25
+ - lib/hatchet/logger_appender.rb
26
+ - lib/hatchet/message.rb
27
+ - lib/hatchet/standard_formatter.rb
22
28
  - lib/hatchet/version.rb
23
29
  - lib/hatchet.rb
24
30
  - test/experiment.rb
@@ -37,7 +43,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
37
43
  version: '0'
38
44
  segments:
39
45
  - 0
40
- hash: 2996924827001664983
46
+ hash: -2622354468754209643
41
47
  required_rubygems_version: !ruby/object:Gem::Requirement
42
48
  none: false
43
49
  requirements:
@@ -46,7 +52,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
46
52
  version: '0'
47
53
  segments:
48
54
  - 0
49
- hash: 2996924827001664983
55
+ hash: -2622354468754209643
50
56
  requirements: []
51
57
  rubyforge_project:
52
58
  rubygems_version: 1.8.24