log4ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/log4ruby.rb ADDED
@@ -0,0 +1,36 @@
1
+ #
2
+ # 21 Jul 2012
3
+ #
4
+
5
+ require "options_arg"
6
+
7
+ require "log4ruby/appender"
8
+ require "log4ruby/exceptions"
9
+ require "log4ruby/formatter"
10
+ require "log4ruby/log"
11
+ require "log4ruby/logger"
12
+
13
+ require "log4ruby/level"
14
+
15
+ module Log4Ruby
16
+
17
+ @@loggers = {}
18
+
19
+ # Get a logger with the specified name. The name can be a '.' separated string or a "::" separated string.
20
+ # Loggers are created only if required.
21
+ #
22
+ # @param [String] name the name of the logger to get.
23
+ #
24
+ # @return [Log4Ruby::Logger] the logger.
25
+ def self.get_logger(name)
26
+ # Return a logger if it had been created earlier.
27
+ return @@loggers[name] if @@loggers.has_key?(name)
28
+ # Otherwise, create it.
29
+ parts = name.index("::") ? name.split("::") : name.split(".")
30
+ logger = RootLogger.instance
31
+ parts.each { |part| logger = logger.get_logger(part, true) }
32
+ # The logger.
33
+ @@loggers[name] = logger
34
+ end
35
+
36
+ end
@@ -0,0 +1,42 @@
1
+ #
2
+ # 21 Jul 2012
3
+ #
4
+
5
+ module Log4Ruby
6
+
7
+ # Base class for appenders.
8
+ class Appender
9
+
10
+ # Set the formatter this appender uses.
11
+ attr_writer :formatter
12
+
13
+ # New appender. This class should be treated as an abstract base class and should not be initialised directly.
14
+ #
15
+ # @param [Log4Ruby::Level] level the threshold level for the appender.
16
+ # @param [Log4Ruby::Formatter] formatter the formatter the appender uses.
17
+ def initialize(level, formatter)
18
+ @level = level
19
+ @formatter = formatter
20
+ end
21
+
22
+ # Process the log item.
23
+ #
24
+ # @param [Log4Ruby::Log] log
25
+ def process_log(log)
26
+ return if log[:level] < @level
27
+
28
+ # Format the log item and emit it.
29
+ emit(@formatter.format(log))
30
+ end
31
+
32
+ private
33
+
34
+ # Emits a log message to this appenders target.
35
+ #
36
+ # @param [String] message the message to emit.
37
+ def emit(message)
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,16 @@
1
+ #
2
+ # 21 Jul 2012
3
+ #
4
+
5
+ module Log4Ruby
6
+
7
+ # An appender that does nothing. All logs to it are ignored and just consumed.
8
+ class NilAppender
9
+
10
+ # Don't do anything with the log. Just return.
11
+ def process_log(log)
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,31 @@
1
+ #
2
+ # 21 Jul 2012
3
+ #
4
+
5
+ require "log4ruby/appender"
6
+
7
+ module Log4Ruby
8
+
9
+ # Simple appender that can emit to a stream (file, console, socket, etc i.e. anything that responds to the write method)
10
+ class StreamAppender < Log4Ruby::Appender
11
+
12
+ # New stream appender.
13
+ #
14
+ # @param [IO] stream a IO stream that can respond to the write method.
15
+ def initialize(level, formatter, stream)
16
+ super(level, formatter)
17
+ @stream = stream
18
+ end
19
+
20
+ private
21
+
22
+ # Writes the message to the underlying stream.
23
+ #
24
+ # @param [String] message the message to write.
25
+ def emit(message)
26
+ @stream.write(message)
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,10 @@
1
+ #
2
+ # 22 Jul 2012
3
+ #
4
+
5
+ module Log4Ruby
6
+
7
+ class LoggerNotFoundError < Exception
8
+ end
9
+
10
+ end
@@ -0,0 +1,20 @@
1
+ #
2
+ # 21 Jul 2012
3
+ #
4
+
5
+ module Log4Ruby
6
+
7
+ # Base class for all formatters.
8
+ class Formatter
9
+
10
+ # Format a log item.
11
+ #
12
+ # @param [Log4Ruby::Log] log
13
+ #
14
+ # @return [String] the fully formatted log message.
15
+ def format(log)
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,51 @@
1
+ #
2
+ # 21 Jul 2012
3
+ #
4
+
5
+ require "log4ruby/formatter"
6
+ require "log4ruby/log"
7
+
8
+ module Log4Ruby
9
+
10
+ class PatternFormatter
11
+
12
+ # New pattern formatted.
13
+ #
14
+ # @param [String] format_string the pattern string to use when formatting log messages.
15
+ # @param [Array] subst_array the log parameters to substitute into the format string.
16
+ # @param [Hash] custom_formatters custom formatters for log parameters. Maps parameter names to callable objects
17
+ # that will be invoked with the parameter's value. The values returned will be used when substituting into the
18
+ # format string.
19
+ #
20
+ # e.g.
21
+ # format_string = [%s] %7s - %s : %s
22
+ # subst_array = [:timestamp, :level, :full_logger_name, :message]
23
+ # custom_formatters = {:timestamp => Proc.new { |value| value.strftime("%Y-%m-%d %H:%M:%S.%L") }}
24
+ #
25
+ # The above example will print the timestamp in the format specified.
26
+ # The level will be right aligned padded on the left to use 7 spaces followed by the full logger name and the
27
+ # message.
28
+ def initialize(format_string, subst_array, custom_formatters = {})
29
+ @format_string = get_option(options, :format_string)
30
+ @subst_array = get_option(options, :subst_array)
31
+ @custom_formatters = get_option(options, :custom_formatters)
32
+ end
33
+
34
+ # Format the log item using the pattern string.
35
+ #
36
+ # @param [Log4Ruby::Log] log the log to format.
37
+ #
38
+ # @return [String] the fully formatted log message.
39
+ def format(log)
40
+ # Get the values of the parameters (apply custom formatters too).
41
+ parameters = @subst_array.map do |parameter|
42
+ value = log[parameter]
43
+ @custom_formatters.has_key?(parameter) ? @custom_formatters[parameter].call(value) : value.to_s
44
+ end
45
+ # Substitute into the format string.
46
+ @format_string % parameters
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,94 @@
1
+ #
2
+ # 21 Jul 2012
3
+ #
4
+
5
+ require "log4ruby/logger"
6
+
7
+ module Log4Ruby
8
+
9
+ class Level
10
+
11
+ # Creates a new level with the specified name and weight. Only level's created using this method are
12
+ # automatically made available on the Logger class. Any other level's will have to be handled manually.
13
+ # The method with which it is made available is the same as the level, but with all lowercase characters.
14
+ #
15
+ # @param [String] name the name of the new level. Will overwrite an existing level with the same name, if it exists.
16
+ # The name is converted to all uppercase characters.
17
+ # @param [Float] weight the weight of the level. Higher the weight, higher the priority.
18
+ def self.register(name, weight)
19
+ name = name.upcase
20
+ method_name = name.downcase
21
+ query_method_name = "#{method_name}?"
22
+ level = Level.new(name, weight)
23
+ const_set(name, level)
24
+ # Create the logging method.
25
+ Logger.send(:define_method, method_name) do |message, parameters = {}|
26
+ return if level < self.effective_level
27
+ # Construct the log and dispatch it.
28
+ parameters[:message] = message
29
+ parameters[:level] = level
30
+ parameters[:logger] = self
31
+ self.process_log(Log.new(parameters))
32
+ end
33
+ # Create the query method - for checking the effective level of a logger / appender.
34
+ Logger.send(:define_method, query_method_name) { self.effective_level <= level }
35
+ Appender.send(:define_method, query_method_name) { self.level <= level }
36
+ end
37
+
38
+ # Parses the specified string in an attempt to convert it to a Level object.
39
+ #
40
+ # @param [String] name the name of the level.
41
+ #
42
+ # @return [Log4Ruby::Level] the level object.
43
+ def self.parse(name)
44
+ name = name.upcase
45
+ const_get(name)
46
+ end
47
+
48
+ # The weight of this level. Higher the value, more severe the log.
49
+ attr_reader :weight
50
+ # The name of the level.
51
+ attr_reader :name
52
+
53
+ # Creates a new level.
54
+ #
55
+ # @param [String] name the name of the level.
56
+ # @param [Float] weight the weight for this level. Higher the weight, higher the severity.
57
+ def initialize(name, weight)
58
+ @name = name
59
+ @weight = weight
60
+ end
61
+
62
+ # Check if this level is less than the specified other log level.
63
+ # Comparison is done using the weight attribute
64
+ def <(other)
65
+ self.weight < other.weight
66
+ end
67
+
68
+ # Check if this level is less than or equal to the specified other log level.
69
+ # Comparison is done using the weight attribute
70
+ def <=(other)
71
+ self.weight <= other.weight
72
+ end
73
+
74
+ # Override to return the name of the level.
75
+ #
76
+ # @return [String] the level's name.
77
+ def to_s
78
+ @name
79
+ end
80
+
81
+ register("ALL", Float::MIN)
82
+ register("TRACE", 100.0)
83
+ register("FINE", 200.0)
84
+ register("DEBUG", 300.0)
85
+ register("CONF", 400.0)
86
+ register("INFO", 500.0)
87
+ register("WARN", 600.0)
88
+ register("ERROR", 700.0)
89
+ register("FATAL", 800.0)
90
+ register("OFF", Float::MAX)
91
+
92
+ end
93
+
94
+ end
@@ -0,0 +1,36 @@
1
+ #
2
+ # 21 Jul 2012
3
+ #
4
+
5
+ module Log4Ruby
6
+
7
+ # Represents a log item.
8
+ class Log
9
+
10
+ attr_reader :parameters
11
+
12
+ # A hash containing all the information in this log.
13
+ # A message, level and logger are the only mandatory parameters.
14
+ def initialize(parameters = {})
15
+ @message = get_option(parameters, :message, true)
16
+ @level = get_option(parameters, :level, true)
17
+ @logger = get_option(parameters, :logger, true)
18
+ @timestamp = set_option(parameters, :timestamp, Time.now, true)
19
+
20
+ @parameters = parameters
21
+ @parameters[:logger_name] = @logger.name
22
+ @parameters[:full_logger_name] = @logger.full_name
23
+ end
24
+
25
+ # Get the specified parameter.
26
+ #
27
+ # @param [Symbol] parameter the parameter to get.
28
+ #
29
+ # @return [Object] the parameter's value, or nil if the parameter did not exist.
30
+ def [](parameter)
31
+ @parameters[parameter]
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,127 @@
1
+ #
2
+ # 22 Jul 2012
3
+ #
4
+
5
+ require "singleton"
6
+
7
+ module Log4Ruby
8
+
9
+ # Represents a logger.
10
+ # Loggers are arranged into a tree, where each logger, after having dispatched the log to its appenders,
11
+ # forwards the log to its parents too.
12
+ class Logger
13
+
14
+ # The effective level of this logger. This will be the parent's effective level if a level has not been
15
+ # explicitly set for this logger.
16
+ attr_reader :effective_level
17
+ # The full name of this logger.
18
+ attr_reader :full_name
19
+ # The name of this logger.
20
+ attr_reader :name
21
+ # True to use parent appenders (the default) false to use only this logger's appenders.
22
+ attr_writer :use_parent_appenders
23
+
24
+ # Creates a new logger. Users should not use this method, and should use the Log4Ruby.get_logger method.
25
+ #
26
+ # @param [String] name the name for this logger.
27
+ # @param [Log4Ruby::Logger] parent the parent to this logger. If set to nil, becomes the child of the root logger.
28
+ # @param [Log4Ruby::Level] level the level of this logger. If set to nil, uses the parent's effective level
29
+ # (defaults to DEBUG for the root logger).
30
+ # @param [Array] appenders a list of appenders this logger will use.
31
+ def initialize(name, parent = nil, level = nil, appenders = [])
32
+ @name = name
33
+ @parent = parent.nil? ? RootLogger.instance : parent
34
+ @level = level
35
+ @appenders = appenders
36
+ @children = {}
37
+
38
+ @use_parent_appenders = true
39
+ @full_name = @parent.kind_of?(RootLogger) ? @name : @parent.full_name + "." + @name
40
+ @effective_level = level.nil? ? @parent.effective_level : level
41
+ end
42
+
43
+ # Adds an appender to this logger.
44
+ #
45
+ # @param [Log4Ruby::Appender] appender the appender to add.
46
+ def add_appender(appender)
47
+ @appenders << appender
48
+ end
49
+
50
+ # Gets a child logger with the specified name. If the create flag is true, it will create a new logger
51
+ # with this name.
52
+ #
53
+ # @param [String] name the name of the logger.
54
+ # @param [TrueClass, FalseClass] create if true, create a logger if it does not exist.
55
+ def get_logger(name, create = false)
56
+ if @children.has_key?(name)
57
+ @children[name]
58
+ elsif create
59
+ @children[name] = Logger.new(name, self)
60
+ else
61
+ raise Log4Ruby::LoggerNotFoundError.new("Logger '#{name}' does not exist under '#@full_name'!")
62
+ end
63
+ end
64
+
65
+ # Update this logger's level. This will update the effective level for all child loggers too (except for the ones
66
+ # that have had their level explicitly set.
67
+ #
68
+ # @param [Log4Ruby::Level] new_level the new level.
69
+ def set_level(new_level)
70
+ @level = new_level
71
+ @effective_level = new_level
72
+ @children.each_value { |logger| logger.update_effective_level(new_level) }
73
+ end
74
+
75
+ protected
76
+
77
+ # Updates the effective level for this logger. This method is called internally when a logger's level is updated
78
+ # and should not be invoked directly.
79
+ #
80
+ # @param [Log4Ruby::Level] new_level the new effective level.
81
+ def update_effective_level(new_level)
82
+ if @level.nil?
83
+ @effective_level = new_level
84
+ @children.each_value { |logger| logger.update_effective_level(new_level) }
85
+ end
86
+ end
87
+
88
+ # Process the log message.
89
+ #
90
+ # @param [Log4Ruby::Log] log the log item to process. Does nothing if the log does not meet this logger's
91
+ # threshold level.
92
+ def process_log(log)
93
+ return if log[:level] < @effective_level
94
+ # Forward to each appender. Once done, send to the parent.
95
+ @appenders.each { |appender| appender.process_log(log) }
96
+ @parent.process_log(log) if @use_parent_appenders
97
+ end
98
+
99
+ private
100
+
101
+ end
102
+
103
+ # Represents the root logger. This logger is similar to any other logger, except since it does not have a parent
104
+ # logger, it does not forward logs.
105
+ class RootLogger < Logger
106
+
107
+ include Singleton
108
+
109
+ # New root logger. The root logger is the parent of all loggers in the system.
110
+ def initialize
111
+ @full_name = @name = "Root"
112
+ @parent = nil
113
+ @effective_level = @level = Log4Ruby::Level::DEBUG
114
+ @appenders = []
115
+ @children = {}
116
+ @use_parent_appenders = false
117
+ end
118
+
119
+ # Override to do nothing. Since the root doesn't have a parent.
120
+ #
121
+ # @param [Log4Ruby::Level] new_level ignored, since the root doesn't have a parent.
122
+ def use_parent_appenders=(new_level)
123
+ end
124
+
125
+ end
126
+
127
+ end
@@ -0,0 +1,9 @@
1
+ #
2
+ # 21 Jul 2012
3
+ #
4
+
5
+ module Log4Ruby
6
+
7
+ VERSION = "0.0.1"
8
+
9
+ end
@@ -0,0 +1,66 @@
1
+ #
2
+ # 16 Jul 2012
3
+ #
4
+
5
+ # Provides a few methods to work with hashes.
6
+ module Kernel
7
+
8
+ # Raised if a required option has not been set.
9
+ class OptionNotSetError < Exception
10
+ end
11
+
12
+ private
13
+
14
+ # Get a value from the specified hash.
15
+ #
16
+ # @param [Hash] options the hash.
17
+ # @param [Symbol] key the key whose value is required.
18
+ # @param [TrueClass, FalseClass] required flag to indicate if it is an error if the key does not exist.
19
+ # @param [Object] default the default value if the key does not exist. Only used if 'required' is false.
20
+ #
21
+ # @return [Object] the value from the hash, or the default value.
22
+ def get_option(options, key, required = false, default = nil)
23
+ if options.has_key?(key)
24
+ options[key]
25
+ elsif required
26
+ raise OptionNotSetError.new("Option '#{key}' has not been set!")
27
+ else
28
+ default
29
+ end
30
+ end
31
+
32
+ # Pops (delete) a value from the specified hash.
33
+ #
34
+ # @param [Hash] options the hash.
35
+ # @param [Symbol] key the key whose value is required.
36
+ # @param [TrueClass, FalseClass] required flag to indicate if it is an error if the key does not exist.
37
+ # @param [Object] default the default value if the key does not exist. Only used if 'required' is false.
38
+ #
39
+ # @return [Object] the value from the hash, or the default value.
40
+ def pop_option(options, key, required = false, default = nil)
41
+ if options.has_key?(key)
42
+ options.delete(key)
43
+ elsif required
44
+ raise OptionNotSetError.new("Option '#{key}' has not been set!")
45
+ else
46
+ default
47
+ end
48
+ end
49
+
50
+ # Sets a value in the specified hash.
51
+ #
52
+ # @param [Hash] options the hash.
53
+ # @param [Symbol] key the key whose value is to be set.
54
+ # @param [Object] value the value to set.
55
+ # @param [TrueClass, FalseClass] overwrite flag to indicate if existing values should be overwritten.
56
+ #
57
+ # @return [Object] the value in the hash at the end of the operation.
58
+ def set_option(options, key, value, overwrite)
59
+ if not options.has_key?(key) or overwrite
60
+ options[key] = value
61
+ end
62
+ # Return whatever is in the hash now.
63
+ options[key]
64
+ end
65
+
66
+ end
data/lib/tests.rb ADDED
@@ -0,0 +1,38 @@
1
+ #
2
+ # 22 Jul 2012
3
+ #
4
+
5
+ $LOAD_PATH << "."
6
+
7
+ require "log4ruby"
8
+ require "log4ruby/appenders/stream_appender"
9
+ require "log4ruby/formatters/pattern_formatter"
10
+
11
+ # The pattern formatter, with a custom parameter formatter for the timestamp.
12
+ timestamp_formatter = Proc.new { |timestamp| timestamp.strftime("%Y-%m-%d %H:%M:%S.%L") }
13
+ formatter = Log4Ruby::PatternFormatter.new("[%s] %7s - %s : %s\n", [:timestamp, :level, :full_logger_name, :message],
14
+ {:timestamp => timestamp_formatter})
15
+ # Stream appender for printing to stdout.
16
+ console_appender = Log4Ruby::StreamAppender.new(Log4Ruby::Level::ALL, formatter, $stdout)
17
+
18
+ # Register a custom level FINER, that is between TRACE and FINE
19
+ Log4Ruby::Level.register("FINER", 150.0)
20
+
21
+ # The logger.
22
+ logger = Log4Ruby.get_logger("Log4Ruby::TestLogger")
23
+ logger.set_level(Log4Ruby::Level::FINER)
24
+ logger.add_appender(console_appender)
25
+
26
+ puts "Logger will print TRACE? : #{logger.trace?}"
27
+ puts "Logger will print FINER? : #{logger.finer?}"
28
+ puts "Logger will print FINE? : #{logger.fine?}"
29
+
30
+ logger.trace("Test!")
31
+ logger.finer("Test!")
32
+ logger.fine("Test!")
33
+ logger.debug("Test!")
34
+ logger.conf("Test!")
35
+ logger.info("Test!")
36
+ logger.warn("Test!")
37
+ logger.error("Test!")
38
+ logger.fatal("Test!")
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: log4ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Suraj Vijayakumar
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-22 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A logging system for Ruby applications inspired by Java's logging API.
15
+ email:
16
+ - vijayakumar.suraj@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/log4ruby/appender.rb
22
+ - lib/log4ruby/appenders/nil_appender.rb
23
+ - lib/log4ruby/appenders/stream_appender.rb
24
+ - lib/log4ruby/exceptions.rb
25
+ - lib/log4ruby/formatter.rb
26
+ - lib/log4ruby/formatters/pattern_formatter.rb
27
+ - lib/log4ruby/level.rb
28
+ - lib/log4ruby/log.rb
29
+ - lib/log4ruby/logger.rb
30
+ - lib/log4ruby/version.rb
31
+ - lib/log4ruby.rb
32
+ - lib/options_arg.rb
33
+ - lib/tests.rb
34
+ homepage:
35
+ licenses: []
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project:
54
+ rubygems_version: 1.8.24
55
+ signing_key:
56
+ specification_version: 3
57
+ summary: A simple and customizable logging system inspired by Java logging API.
58
+ test_files: []