globalog 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,110 @@
1
+ # This gem aims to provide a global cascading logging system, command line arguments aware,
2
+ # to centralize the settings of your individual loggers.
3
+ #
4
+ # It is thought to be compatible with other gems using OptionParser to collect command line arguments, by hijacking the ARGV at require time before others grabs it. (So, it must be required before say, 'Test/Unit' to hijack the ARGV).
5
+ #
6
+ # Each individual logger can follow the setting's cascade, or not. If it does, the command line arguments or the first globalog to setup its parameters have precedence over the local settings. And in case no other globalog is setup is present, the local parameters are used for logging.
7
+ #
8
+ # It is essentially compatible with existing Logger, because it uses logger as it base lib. So all logging is done the same way, with all of logger instance methods also working on globalog instances. You can then transition code logged with logger easily, by either replacing the Logger initialisation in your code by a GlobaLog initialisation, or by leaving logger where it is and only deriving its output and level settings from globalog class methods of the same names, still allowing you to tap into globalog cascading settings.
9
+ #
10
+ # The logging in Globalog is done with Logger so please refer to its documentation for the logging methodologies: http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/
11
+ #
12
+ # ///////////////////////////////////////////////////////////////////////////////////////
13
+ # Example:
14
+ #
15
+ # # script1.rb
16
+ # require 'globalog'
17
+ # $log = GlobaLog.logger(STDERR,:warn)
18
+ #
19
+ # module Script1
20
+ # def example
21
+ # $log.warn("Example") {"Printing Warning!!"}
22
+ # $log.info("Example") {"Printing Info!!"}
23
+ # $log.debug("Example") {"Printing Debug!!"}
24
+ # end
25
+ # end
26
+ #
27
+ # calling the example method will result in:
28
+ #
29
+ # Script1.example # => Printing Warning!!
30
+ #
31
+ # But if you require script1, inside an other script, setting different GlobaLog init parameters, they will have precedence and cascade down as in the example below.
32
+ #
33
+ # # script2.rb
34
+ # require 'globalog'
35
+ # require 'script1'
36
+ #
37
+ # $log = GlobaLog.logger(STDERR,:info)
38
+ # Script1.example
39
+ #
40
+ # running script2 will output:
41
+ #
42
+ # > ruby script2.rb
43
+ # => Printing Warning!!
44
+ # => Printing Info!!
45
+ #
46
+ # And you can also run script2 with arguments to get different log level or output:
47
+ #
48
+ # > ruby script2.rb -L debug
49
+ # => Printing Warning!!
50
+ # => Printing Info!!
51
+ # => Printing Debug!!
52
+ #
53
+ # So this allow you to set a default Logger setting in your libraries, override them with an other default setting in client scripts and still get the flexibility to override both defaults at runtime by providing command line arguments. Ideal for testing purposes where you want a default log level for test overriding the Local log level of your tested libraries, while allowing you to choose the test log level at runtime.
54
+ #
55
+ #
56
+ # Author:: lp (mailto:lp@spiralix.org)
57
+ # Copyright:: 2009 Louis-Philippe Perron - Released under the terms of the MIT license
58
+ #
59
+ # :title:GlobaLog
60
+
61
+ require 'logger'
62
+ class GlobaLog < Logger
63
+ require 'globalog_args'
64
+ require 'globalog_hijack'
65
+
66
+ # The +GlobaLog.logger+ acts as a constructor method for the logger.
67
+ # === Parameters
68
+ # * _def_out_ = the output io or logfile path
69
+ # * _def_level_ = the log level, as a symbol (i.e. :warn, :info, etc)
70
+ # * _master_ = (optional) the logger presence in the cascading settings chain
71
+ # _master_ can be any of the following:
72
+ # * _true_ = Impose its settings on the loggers down the chain
73
+ # * _false_ = Use the chain settings if present (default)
74
+ # * _nil_ = Is out of the chain
75
+ # === Example
76
+ # @log = GlobaLog.logger('logfile.txt',:error,true)
77
+
78
+ def GlobaLog.logger(def_out,def_level,master=false)
79
+ Args.are({:log_output => def_out, :log_level => def_level},master)
80
+ if master.nil?
81
+ log = self.new(def_out)
82
+ log.level = Args.sym_to_level(def_level)
83
+ else
84
+ log = self.new(Args::log_output)
85
+ log.level = Args::log_level
86
+ end
87
+ return log
88
+ end
89
+
90
+ # The +GlobaLog::output+ method return the current log output.
91
+ # Can be used to chain existing Logger instances to GlobaLog cascade,
92
+ # when you don't want to replace them with GlobaLog instances.
93
+ # (and you can only replace the constructor, the logging will still work)
94
+ # === Example
95
+ # $logger = Logger.new(GlobaLog::output)
96
+ def GlobaLog::output
97
+ Args::log_output
98
+ end
99
+
100
+ # The +Globalog::level+ method returns the current log level.
101
+ # Can be used to chain existing Logger instances to GlobaLog cascade,
102
+ # when you don't want to replace them with GlobaLog instances.
103
+ # (and you can only replace the constructor, the logging will still work)
104
+ # === Example
105
+ # $logger.level = GlobaLog::level
106
+ def GlobaLog::level
107
+ Args::log_level
108
+ end
109
+
110
+ end
@@ -0,0 +1,50 @@
1
+ class GlobaLog
2
+ # The Args module manages the GlobaLog arguments in the background.
3
+ # Author:: lp (mailto:lp@spiralix.org)
4
+ # Copyright:: 2009 Louis-Philippe Perron - Released under the terms of the MIT license
5
+ #
6
+ # :title:GlobaLog/Args
7
+ module Args
8
+
9
+ def Args.are(args,override=false)
10
+ $logger_args ||= Hash.new
11
+ if override == true
12
+ $logger_args[:log_level] = args[:log_level].to_sym unless args[:log_level].nil?
13
+ $logger_args[:log_output] = args[:log_output] unless args[:log_output].nil?
14
+ else
15
+ $logger_args[:log_level] ||= args[:log_level].to_sym unless args[:log_level].nil?
16
+ $logger_args[:log_output] ||= args[:log_output] unless args[:log_output].nil?
17
+ end
18
+ end
19
+
20
+ def Args::log_output
21
+ $logger_args[:log_output]
22
+ end
23
+
24
+ def Args::log_level
25
+ if $logger_args[:log_level].is_a?(Symbol)
26
+ $logger_args[:log_level] = self.sym_to_level($logger_args[:log_level])
27
+ end
28
+ $logger_args[:log_level]
29
+ end
30
+
31
+ def Args.sym_to_level(sym)
32
+ case sym
33
+ when :debug
34
+ return Logger::DEBUG
35
+ when :info
36
+ return Logger::INFO
37
+ when :warn
38
+ return Logger::WARN
39
+ when :error
40
+ return Logger::ERROR
41
+ when :fatal
42
+ return Logger::FATAL
43
+ else
44
+ return Logger::UNKNOWN
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,51 @@
1
+ class GlobaLog
2
+ # The Hijack class manages the acquisition of command line arguments,
3
+ # playing nicely with other command line aware libs.
4
+ # Author:: lp (mailto:lp@spiralix.org)
5
+ # Copyright:: 2009 Louis-Philippe Perron - Released under the terms of the MIT license
6
+ #
7
+ # :title:GlobaLog/Hijack
8
+ class Hijack < Hash
9
+ require 'optparse'
10
+
11
+ def initialize
12
+ super()
13
+ self[:log_level] = nil
14
+ self[:log_output] = nil
15
+ opts = OptionParser.new do |opts|
16
+ opts.on('-L','--log-level [STRING]','sets the Test Log Level') do |string|
17
+ self[:log_level] = string.to_sym
18
+ end
19
+ opts.on('-O','--log-output [I/O]','sets the Test Log output') do |io|
20
+ self[:log_output] = io
21
+ end
22
+ end
23
+ opts.parse!($keep_argv)
24
+ end
25
+
26
+ def self.keep_wanted_argv
27
+ args = Array.new(ARGV); ARGV.clear; keep = []
28
+ wanted = ['-L', '--log-level', '-O', '--log-output']
29
+ catch :finished do
30
+ loop do
31
+ throw :finished if args.empty?
32
+ catch :found do
33
+ wanted.each do |arg|
34
+ if args[0] == arg
35
+ 2.times { keep << args.shift }
36
+ throw :found
37
+ end
38
+ end
39
+ ARGV << args.shift
40
+ end
41
+ end
42
+ end
43
+ $keep_argv ||= keep
44
+ end
45
+
46
+ self.keep_wanted_argv
47
+ Args.are(self.new)
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,25 @@
1
+ module LogMessage
2
+
3
+ def log_all_level(identifier)
4
+ @log.debug('test') {"#{identifier} -- debug"}
5
+ @log.info('test') {"#{identifier} -- info"}
6
+ @log.warn('test') {"#{identifier} -- warn"}
7
+ @log.error('test') {"#{identifier} -- error"}
8
+ @log.fatal('test') {"#{identifier} -- fatal"}
9
+ @log.unknown('test') {"#{identifier} -- unknown"}
10
+ end
11
+
12
+ end
13
+
14
+ class External
15
+ include LogMessage
16
+
17
+ def initialize
18
+ @log = GlobaLog.logger(STDERR,:warn)
19
+ end
20
+
21
+ def log
22
+ log_all_level('external')
23
+ end
24
+
25
+ end
@@ -0,0 +1,126 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'globalog'
3
+ require 'test/unit'
4
+
5
+ require 'test/external_helper'
6
+
7
+ class TestGlobaLogMain < Test::Unit::TestCase
8
+ include LogMessage
9
+ $test_file = 'test_log'
10
+
11
+ def setup
12
+ File.new($test_file,'w').close
13
+ end
14
+
15
+ def test_globalog
16
+ output = STDERR
17
+ level = :error
18
+ @log = GlobaLog.logger(output,level,true)
19
+ assert_equal(output,GlobaLog::output)
20
+ assert_equal(3,GlobaLog::level)
21
+ end
22
+
23
+ def test_globalog_debug
24
+ prepare_test(:debug)
25
+ check_test(:debug)
26
+ end
27
+
28
+ def test_globalog_info
29
+ prepare_test(:info)
30
+ check_test(:info)
31
+ end
32
+
33
+ def test_globalog_warn
34
+ prepare_test(:warn)
35
+ check_test(:warn)
36
+ end
37
+
38
+ def test_globalog_error
39
+ prepare_test(:error)
40
+ check_test(:error)
41
+ end
42
+
43
+ def test_globalog_fatal
44
+ prepare_test(:fatal)
45
+ check_test(:fatal)
46
+ end
47
+
48
+ def test_globalog_unknown
49
+ prepare_test(:unknown)
50
+ check_test(:unknown)
51
+ end
52
+
53
+ def teardown
54
+ @log.close
55
+ File.delete($test_file)
56
+ end
57
+
58
+ private
59
+
60
+ def prepare_test(level)
61
+ @log = GlobaLog.logger($test_file,level,true)
62
+ log_all_level('base test')
63
+ pid1 = fork {log_all_level('fork 1'); exit}
64
+ pid2 = fork {log_all_level('fork 2'); exit}
65
+ Process.waitpid(pid2,0)
66
+ External.new().log
67
+ end
68
+
69
+ def check_test(level)
70
+ f = File.open($test_file,'r'); content = f.read; f.close
71
+ check_players(content)
72
+ check_level(level,content)
73
+ end
74
+
75
+ def check_players(content)
76
+ assert_match(/base/,content)
77
+ assert_match(/fork 1/,content)
78
+ assert_match(/fork 2/,content)
79
+ assert_match(/external/,content)
80
+ end
81
+
82
+ def check_level(level,content)
83
+ level_match = match_assertions(content)
84
+ level_no_match = no_match_assertions(content)
85
+ case level
86
+ when :debug
87
+ 0.upto(5) { |num| level_match[num].call }
88
+ when :info
89
+ 0.upto(4) { |num| level_match[num].call }
90
+ 5.downto(5) { |num| level_no_match[num].call }
91
+ when :warn
92
+ 0.upto(3) { |num| level_match[num].call }
93
+ 5.downto(4) { |num| level_no_match[num].call }
94
+ when :error
95
+ 0.upto(2) { |num| level_match[num].call }
96
+ 5.downto(3) { |num| level_no_match[num].call }
97
+ when :fatal
98
+ 0.upto(1) { |num| level_match[num].call }
99
+ 5.downto(2) { |num| level_no_match[num].call }
100
+ when :unknown
101
+ 0.upto(0) { |num| level_match[num].call }
102
+ 5.downto(1) { |num| level_no_match[num].call }
103
+ end
104
+ end
105
+
106
+ def match_assertions(content)
107
+ [ lambda { assert_match(/unknown/,content) },
108
+ lambda { assert_match(/fatal/,content) },
109
+ lambda { assert_match(/error/,content) },
110
+ lambda { assert_match(/warn/,content) },
111
+ lambda { assert_match(/info/,content) },
112
+ lambda { assert_match(/debug/,content) } ]
113
+ end
114
+
115
+ def no_match_assertions(content)
116
+ [ lambda { assert_no_match(/unknown/,content) },
117
+ lambda { assert_no_match(/fatal/,content) },
118
+ lambda { assert_no_match(/error/,content) },
119
+ lambda { assert_no_match(/warn/,content) },
120
+ lambda { assert_no_match(/info/,content) },
121
+ lambda { assert_no_match(/debug/,content) } ]
122
+ end
123
+
124
+
125
+
126
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: globalog
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Louis-Philippe Perron
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-12 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: lp@spiralix.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/globalog.rb
26
+ - lib/globalog_args.rb
27
+ - lib/globalog_hijack.rb
28
+ - test/external_helper.rb
29
+ - test/tc_globalog_main.rb
30
+ has_rdoc: true
31
+ homepage: http://globalog.rubyforge.org/
32
+ post_install_message:
33
+ rdoc_options: []
34
+
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements: []
50
+
51
+ rubyforge_project: GlobaLog
52
+ rubygems_version: 1.2.0
53
+ signing_key:
54
+ specification_version: 2
55
+ summary: Cascading Global Log
56
+ test_files:
57
+ - test/tc_globalog_main.rb