hatchet 0.0.1 → 0.0.2

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.
@@ -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