batch-kit 0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +165 -0
- data/lib/batch-kit.rb +9 -0
- data/lib/batch-kit/arguments.rb +57 -0
- data/lib/batch-kit/config.rb +517 -0
- data/lib/batch-kit/configurable.rb +68 -0
- data/lib/batch-kit/core_ext/enumerable.rb +97 -0
- data/lib/batch-kit/core_ext/file.rb +69 -0
- data/lib/batch-kit/core_ext/file_utils.rb +103 -0
- data/lib/batch-kit/core_ext/hash.rb +17 -0
- data/lib/batch-kit/core_ext/numeric.rb +17 -0
- data/lib/batch-kit/core_ext/string.rb +88 -0
- data/lib/batch-kit/database.rb +133 -0
- data/lib/batch-kit/database/java_util_log_handler.rb +65 -0
- data/lib/batch-kit/database/log4r_outputter.rb +57 -0
- data/lib/batch-kit/database/models.rb +548 -0
- data/lib/batch-kit/database/schema.rb +229 -0
- data/lib/batch-kit/encryption.rb +7 -0
- data/lib/batch-kit/encryption/java_encryption.rb +178 -0
- data/lib/batch-kit/encryption/ruby_encryption.rb +175 -0
- data/lib/batch-kit/events.rb +157 -0
- data/lib/batch-kit/framework/acts_as_job.rb +197 -0
- data/lib/batch-kit/framework/acts_as_sequence.rb +123 -0
- data/lib/batch-kit/framework/definable.rb +169 -0
- data/lib/batch-kit/framework/job.rb +121 -0
- data/lib/batch-kit/framework/job_definition.rb +105 -0
- data/lib/batch-kit/framework/job_run.rb +145 -0
- data/lib/batch-kit/framework/runnable.rb +235 -0
- data/lib/batch-kit/framework/sequence.rb +87 -0
- data/lib/batch-kit/framework/sequence_definition.rb +38 -0
- data/lib/batch-kit/framework/sequence_run.rb +48 -0
- data/lib/batch-kit/framework/task_definition.rb +89 -0
- data/lib/batch-kit/framework/task_run.rb +53 -0
- data/lib/batch-kit/helpers/date_time.rb +54 -0
- data/lib/batch-kit/helpers/email.rb +198 -0
- data/lib/batch-kit/helpers/html.rb +175 -0
- data/lib/batch-kit/helpers/process.rb +101 -0
- data/lib/batch-kit/helpers/zip.rb +30 -0
- data/lib/batch-kit/job.rb +11 -0
- data/lib/batch-kit/lockable.rb +138 -0
- data/lib/batch-kit/loggable.rb +78 -0
- data/lib/batch-kit/logging.rb +169 -0
- data/lib/batch-kit/logging/java_util_logger.rb +87 -0
- data/lib/batch-kit/logging/log4r_logger.rb +71 -0
- data/lib/batch-kit/logging/null_logger.rb +35 -0
- data/lib/batch-kit/logging/stdout_logger.rb +96 -0
- data/lib/batch-kit/resources.rb +191 -0
- data/lib/batch-kit/sequence.rb +7 -0
- metadata +122 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
require_relative '../logging'
|
5
|
+
|
6
|
+
|
7
|
+
class BatchKit
|
8
|
+
|
9
|
+
module Helpers
|
10
|
+
|
11
|
+
# Provides support for running an external process.
|
12
|
+
# This support consists of support for:
|
13
|
+
# - launching the process as a child
|
14
|
+
# - capturing the output of the process and logging it
|
15
|
+
# - handling the return code of the process, and raising an exception for
|
16
|
+
# failures.
|
17
|
+
module Process
|
18
|
+
|
19
|
+
# Provides a means for executing a command-line.
|
20
|
+
#
|
21
|
+
# @param cmd_line [String] The command-line that is to be launched.
|
22
|
+
# @param options [Hash] An options hash.
|
23
|
+
# @option options [Proc] :callback If specified, the supplied Proc will
|
24
|
+
# be invoked for each line of output produced by the process.
|
25
|
+
# @option options [Proc] :input If specified, the supplied Proc will
|
26
|
+
# be invoked for each line of output produced by the process. It will
|
27
|
+
# be passed the pipe on which input for the process can be written,
|
28
|
+
# plus the last line of output produced. This is useful in cases where
|
29
|
+
# it is necessary to communicate with the child process via its STDIN.
|
30
|
+
# @return [Fixnum] The exit status code from the external process.
|
31
|
+
def popen(cmd_line, options = {}, &block)
|
32
|
+
callback = options[:callback]
|
33
|
+
input = options[:input]
|
34
|
+
IO.popen(cmd_line, input ? 'r+' : 'r') do |pipe|
|
35
|
+
while !pipe.eof?
|
36
|
+
line = pipe.gets.chomp
|
37
|
+
input.call(pipe, line) if input
|
38
|
+
callback.call(line) if callback
|
39
|
+
block.call(line) if block_given?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
$?.exitstatus
|
43
|
+
end
|
44
|
+
module_function :popen
|
45
|
+
|
46
|
+
|
47
|
+
# Launch an external process with logging etc. By default, an exception
|
48
|
+
# will be raised if the process returns a non-zero exit code.
|
49
|
+
#
|
50
|
+
# @param cmd_line [String, Array<String>] The command-line to be run,
|
51
|
+
# in the form of either a single String, or an Array of Strings.
|
52
|
+
# @param options [Hash] An options hash.
|
53
|
+
# @option options [Boolean] :raise_on_error If true (default), an
|
54
|
+
# exception is raised if the return code is not a success code.
|
55
|
+
# @option options [Fixnum, Array<Fixnum>] The return code(s) that the
|
56
|
+
# process can return if successful (default 0).
|
57
|
+
# @option options [Boolean] :show_duration If true (default), logs the
|
58
|
+
# duration taken by the process.
|
59
|
+
# @option options [Logger] :logger The logger to use; defaults to using
|
60
|
+
# a logger named after the process being executed.
|
61
|
+
def launch(cmd_line, options = {}, &block)
|
62
|
+
exe = cmd_line.is_a?(String) ?
|
63
|
+
File.basename(Shellwords.shellwords(cmd_line.gsub(/\\/, '/')).first) :
|
64
|
+
File.basename(cmd_line.first)
|
65
|
+
|
66
|
+
raise_on_error = options.fetch(:raise_on_error, true)
|
67
|
+
show_duration = options.fetch(:show_duration, true)
|
68
|
+
success_code = options.fetch(:success_code, 0)
|
69
|
+
log = options.fetch(:logger, BatchKit::LogManager.logger(exe))
|
70
|
+
log_level = options.fetch(:log_level, :detail)
|
71
|
+
unless block_given? || options[:callback]
|
72
|
+
options = options.dup
|
73
|
+
options[:callback] = lambda{ |line| log.send(log_level, line) }
|
74
|
+
end
|
75
|
+
|
76
|
+
log.trace("Executing command line: #{cmd_line}") if log
|
77
|
+
begin
|
78
|
+
start = Time.now
|
79
|
+
rc = popen(cmd_line, options, &block)
|
80
|
+
ensure
|
81
|
+
if log && show_duration
|
82
|
+
log.detail "#{exe} completed in #{Time.now - start} seconds with exit code #{rc}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
if raise_on_error
|
87
|
+
ok = case success_code
|
88
|
+
when Fixnum then success_code == rc
|
89
|
+
when Array then success_code.include?(rc)
|
90
|
+
end
|
91
|
+
raise "#{exe} returned failure exit code #{rc}" unless ok
|
92
|
+
end
|
93
|
+
rc
|
94
|
+
end
|
95
|
+
module_function :launch
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'zip/zip'
|
3
|
+
|
4
|
+
|
5
|
+
class BatchKit
|
6
|
+
|
7
|
+
module Helpers
|
8
|
+
|
9
|
+
module Zip
|
10
|
+
|
11
|
+
# Creates a new +zip_file+, adding +files+ to it.
|
12
|
+
#
|
13
|
+
# @param zip_file [String] A path to the zip file to be created
|
14
|
+
# @param files [String] One or more paths to files to be added to
|
15
|
+
# the zip.
|
16
|
+
def create_zip(zip_file, *files)
|
17
|
+
FileUtils.rm_f(zip_file)
|
18
|
+
Zip::ZipFile.open(zip_file, Zip::ZipFile::CREATE) do |zip|
|
19
|
+
files.each do |file|
|
20
|
+
zip.add(File.basename(file), file)
|
21
|
+
end
|
22
|
+
yield zip if block_given?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative 'events'
|
2
|
+
require_relative 'lockable'
|
3
|
+
require_relative 'framework/definable'
|
4
|
+
require_relative 'framework/job_definition'
|
5
|
+
require_relative 'framework/task_definition'
|
6
|
+
require_relative 'framework/runnable'
|
7
|
+
require_relative 'framework/job_run'
|
8
|
+
require_relative 'framework/task_run'
|
9
|
+
require_relative 'framework/acts_as_job'
|
10
|
+
require_relative 'framework/job'
|
11
|
+
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require_relative 'events'
|
3
|
+
|
4
|
+
|
5
|
+
class BatchKit
|
6
|
+
|
7
|
+
# Defines lockable behaviour, which can be added to any batch process.
|
8
|
+
# This behavior allows a process to define a named lock that it needs
|
9
|
+
# exclusively during execution.
|
10
|
+
# When the process is about to be executed, it will first attempt to obtain
|
11
|
+
# the named lock. If it is successful, execution will proceed as normal, and
|
12
|
+
# on completion of processing (whether succesful or otherwise), the lock
|
13
|
+
# will be released.
|
14
|
+
# If the lock is already held by another process, the requesting process
|
15
|
+
# will block and wait for the lock to become available. The process will
|
16
|
+
# only wait as long as lock_wait_timeout; if the lock has not become
|
17
|
+
# availabe in that time period, a LockTimeout exception will be thrown,
|
18
|
+
# and processing will not take place.
|
19
|
+
module Lockable
|
20
|
+
|
21
|
+
# Attempts to obtain the named lock +lock_name+. If the lock is already
|
22
|
+
# held by another process, this method blocks until one of the following
|
23
|
+
# occurs:
|
24
|
+
# - the lock is released by the process that currently holds it
|
25
|
+
# - the lock expires, by reaching it's timeout period
|
26
|
+
# - the +lock_wait_timeout+ period is reached.
|
27
|
+
#
|
28
|
+
# Lock management is managed via the event publishing system; subscribers
|
29
|
+
# to the 'lock?' event indicate whether a lock is available by their
|
30
|
+
# response to the event. A value of false indicates the lock is
|
31
|
+
# currently held; a response of true indicates the lock has been granted.
|
32
|
+
#
|
33
|
+
# @param lock_name [String] The name of the lock that is needed.
|
34
|
+
# @param lock_timeout [Fixnum] The maximum number of seconds that this
|
35
|
+
# process can hold the requested lock before it times out (allowing
|
36
|
+
# any other processes waiting on the lock to proceed). This value
|
37
|
+
# should be set high enough that the lock does not timeout while
|
38
|
+
# processing that relies on the lock is not still running.
|
39
|
+
# @param lock_wait_timeout [Fixnum] The maximum time this process is
|
40
|
+
# prepared to wait for the lock to become available. If not specified,
|
41
|
+
# the wait will timeout after the same amount of time as +lock_timeout+.
|
42
|
+
# @raise Timeout::Error If the lock is not obtained within
|
43
|
+
# +lock_wait_timeout+ seconds.
|
44
|
+
def lock(lock_name, lock_timeout, lock_wait_timeout = nil)
|
45
|
+
unless lock_timeout && lock_timeout.is_a?(Fixnum) && lock_timeout > 0
|
46
|
+
raise ArgumentError, "Invalid lock_timeout; must be > 0"
|
47
|
+
end
|
48
|
+
unless lock_wait_timeout.nil? || (lock_wait_timeout.is_a?(Fixnum) && lock_wait_timeout >= 0)
|
49
|
+
raise ArgumentError, "Invalid lock_wait_timeout; must be nil or >= 0"
|
50
|
+
end
|
51
|
+
unless Events.has_subscribers?(self, 'lock?')
|
52
|
+
if self.respond_to?(:log)
|
53
|
+
log.warn "No lock manager available; proceeding without locking"
|
54
|
+
end
|
55
|
+
return
|
56
|
+
end
|
57
|
+
lock_wait_timeout ||= lock_timeout
|
58
|
+
lock_expire_time = nil
|
59
|
+
wait_expire_time = Time.now + lock_wait_timeout
|
60
|
+
if lock_wait_timeout > 0
|
61
|
+
# Loop waiting for lock if not available
|
62
|
+
begin
|
63
|
+
Timeout.timeout(lock_wait_timeout) do
|
64
|
+
i = 0
|
65
|
+
loop do
|
66
|
+
lock_holder = {}
|
67
|
+
lock_expire_time = Events.publish(self, 'lock?', lock_name,
|
68
|
+
lock_timeout, lock_holder)
|
69
|
+
break if lock_expire_time
|
70
|
+
if i == 0
|
71
|
+
Events.publish(self, 'lock_held', lock_name,
|
72
|
+
lock_holder[:lock_holder],
|
73
|
+
lock_holder[:lock_expires_at])
|
74
|
+
Events.publish(self, 'lock_wait', lock_name, wait_expire_time)
|
75
|
+
end
|
76
|
+
sleep 1
|
77
|
+
i += 1
|
78
|
+
end
|
79
|
+
Events.publish(self, 'locked', lock_name, lock_expire_time)
|
80
|
+
end
|
81
|
+
rescue Timeout::Error
|
82
|
+
Events.publish(self, 'lock_wait_timeout', lock_name, wait_expire_time)
|
83
|
+
raise Timeout::Error, "Timed out waiting for lock '#{lock_name}' to become available"
|
84
|
+
end
|
85
|
+
else
|
86
|
+
# No waiting for lock to become free
|
87
|
+
lock_holder = {}
|
88
|
+
if lock_expire_time = Events.publish(self, 'lock?', lock_name, lock_timeout, lock_holder)
|
89
|
+
Events.publish(self, 'locked', lock_name, lock_expire_time)
|
90
|
+
else
|
91
|
+
Events.publish(self, 'lock_held', lock_name,
|
92
|
+
lock_holder[:lock_holder], lock_holder[:lock_expires_at])
|
93
|
+
Events.publish(self, 'lock_wait_timeout', lock_name, wait_expire_time)
|
94
|
+
raise Timeout::Error, "Lock '#{lock_name}' is already in use"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
# Release a lock held by this object.
|
101
|
+
#
|
102
|
+
# @param lock_name [String] The name of the lock to be released.
|
103
|
+
def unlock(lock_name)
|
104
|
+
unless Events.has_subscribers?(self, 'unlock?')
|
105
|
+
return
|
106
|
+
end
|
107
|
+
if Events.publish(self, 'unlock?', lock_name)
|
108
|
+
Events.publish(self, 'unlocked', lock_name)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# Obtains the requested +lock_name+, then yields to the supplied block.
|
114
|
+
# Ensures the lock is released when the block ends or raises an error.
|
115
|
+
#
|
116
|
+
# @param lock_name [String] The name of the lock to obtain.
|
117
|
+
# @param lock_timeout [Fixnum] The maximum number of seconds that this
|
118
|
+
# process can hold the requested lock before it times out (allowing
|
119
|
+
# any other processes waiting on the lock to proceed). This value
|
120
|
+
# should be set high enough that the lock does not timeout while
|
121
|
+
# processing that relies on the lock is not still running.
|
122
|
+
# @param lock_wait_timeout [Fixnum] The maximum time this process is
|
123
|
+
# prepared to wait for the lock to become available. If not specified,
|
124
|
+
# the wait will timeout after the same amount of time as +lock_timeout+.
|
125
|
+
# @raise Timeout::Error If the lock is not obtained within
|
126
|
+
# +lock_wait_timeout+ seconds.
|
127
|
+
def with_lock(lock_name, lock_timeout, lock_wait_timeout = nil)
|
128
|
+
self.lock(lock_name, lock_timeout, lock_wait_timeout)
|
129
|
+
begin
|
130
|
+
yield
|
131
|
+
ensure
|
132
|
+
self.unlock(lock_name)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require_relative 'logging'
|
2
|
+
|
3
|
+
|
4
|
+
class BatchKit
|
5
|
+
|
6
|
+
# Adds logging behaviour to a batch-kit process, causing its lifecycle to be
|
7
|
+
# logged.
|
8
|
+
module Loggable
|
9
|
+
|
10
|
+
# Returns a logger instance named after the class
|
11
|
+
def log
|
12
|
+
@log ||= LogManager.logger(self.class.name)
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
if defined?(BatchKit::Events)
|
17
|
+
|
18
|
+
# Subscribe to batch-kit lifecycle events that should be logged
|
19
|
+
Events.subscribe(Configurable, 'config.post-load') do |job_cls, cfg|
|
20
|
+
if cfg.has_key?(:log_level) || cfg.has_key?(:log_file)
|
21
|
+
log = LogManager.logger(job_cls.name)
|
22
|
+
if cfg[:log_level]
|
23
|
+
log.level = cfg[:log_level]
|
24
|
+
log.config "Log level set to #{cfg[:log_level].upcase}"
|
25
|
+
end
|
26
|
+
if cfg.has_key?(:log_file)
|
27
|
+
log.config "Logging output to: #{cfg[:log_file]}" if cfg[:log_file]
|
28
|
+
FileUtils.mkdir_p(File.dirname(cfg[:log_file]))
|
29
|
+
log.log_file = cfg[:log_file]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
Events.subscribe(Loggable, 'sequence_run.execute') do |job_obj, run, *args|
|
34
|
+
job_obj.log.info "Sequence '#{run.label}' started"
|
35
|
+
end
|
36
|
+
Events.subscribe(Loggable, 'job_run.execute') do |job_obj, run, *args|
|
37
|
+
id = run.job_run_id ? " as job run #{run.job_run_id}" : ''
|
38
|
+
job_obj.log.info "Job '#{run.label}' started on #{run.computer} by #{run.run_by}#{id}"
|
39
|
+
end
|
40
|
+
Events.subscribe(Loggable, 'task_run.execute') do |job_obj, run, *args|
|
41
|
+
id = run.task_run_id ? " as task run #{run.task_run_id}" : ''
|
42
|
+
job_obj.log.info "Task '#{run.label}' started#{id}"
|
43
|
+
end
|
44
|
+
%w{sequence_run job_run task_run}.each do |runnable|
|
45
|
+
Events.subscribe(Loggable, "#{runnable}.post-execute") do |job_obj, run, ok|
|
46
|
+
job_obj.log.info "#{run.class.name.split('::')[-2]} '#{run.label}' completed #{
|
47
|
+
ok ? 'successfully' : 'with errors'} in #{'%.3f' % run.elapsed} seconds"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
Events.subscribe(Lockable, 'lock_wait') do |job_run, lock_name|
|
52
|
+
if (job_obj = job_run.object).is_a?(Loggable)
|
53
|
+
job_obj.log.detail "Waiting for lock '#{lock_name}' to become avaialable"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
Events.subscribe(Lockable, 'lock_held') do |job_run, lock_name, lock_holder, lock_expire_time|
|
57
|
+
if (job_obj = job_run.object).is_a?(Loggable)
|
58
|
+
job_obj.log.warn "Lock '#{lock_name}' is currently held by #{lock_holder}; expires at #{
|
59
|
+
lock_expire_time.strftime('%H:%M:%S')}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
Events.subscribe(Lockable, 'locked') do |job_run, lock_name, lock_expire_time|
|
63
|
+
if (job_obj = job_run.object).is_a?(Loggable)
|
64
|
+
job_obj.log.detail "Obtained lock '#{lock_name}'; expires at #{
|
65
|
+
lock_expire_time.strftime('%H:%M:%S')}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
Events.subscribe(Lockable, 'unlocked') do |job_run, lock_name|
|
69
|
+
if (job_obj = job_run.object).is_a?(Loggable)
|
70
|
+
job_obj.log.detail "Released lock '#{lock_name}'"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
|
4
|
+
class BatchKit
|
5
|
+
|
6
|
+
module Logging
|
7
|
+
|
8
|
+
# Log levels available
|
9
|
+
LEVELS = [:error, :warning, :info, :config, :detail, :trace, :debug]
|
10
|
+
|
11
|
+
# Supported logging frameworks
|
12
|
+
FRAMEWORKS = [
|
13
|
+
:null,
|
14
|
+
:stdout,
|
15
|
+
:log4r,
|
16
|
+
:java_util_logging
|
17
|
+
]
|
18
|
+
|
19
|
+
# Method aliasing needed to provide log methods corresponding to levels
|
20
|
+
FRAMEWORK_INIT = {
|
21
|
+
null: lambda{
|
22
|
+
require_relative 'logging/null_logger'
|
23
|
+
},
|
24
|
+
stdout: lambda{
|
25
|
+
require_relative 'logging/stdout_logger'
|
26
|
+
},
|
27
|
+
java_util_logging: lambda{
|
28
|
+
require_relative 'logging/java_util_logger'
|
29
|
+
},
|
30
|
+
log4r: lambda{
|
31
|
+
require_relative 'logging/log4r_logger'
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# Used for setting the log framework to use, and retrieving a logger
|
39
|
+
# from the current framework.
|
40
|
+
class LogManager
|
41
|
+
|
42
|
+
class << self
|
43
|
+
|
44
|
+
def configure(options = {})
|
45
|
+
self.log_framework = options[:log_framework] if options[:log_framework]
|
46
|
+
if options.fetch(:log_color, true)
|
47
|
+
case self.log_framework
|
48
|
+
when :log4r
|
49
|
+
require 'color_console/log4r_logger'
|
50
|
+
Console.replace_console_logger(logger: 'batch')
|
51
|
+
when :java_util_logging
|
52
|
+
require 'color_console/java_util_logger'
|
53
|
+
Console.replace_console_logger(
|
54
|
+
level: Java::JavaUtilLogging::Level::FINE,
|
55
|
+
level_labels: {
|
56
|
+
Java::JavaUtilLogging::Level::FINE => 'DETAIL',
|
57
|
+
Java::JavaUtilLogging::Level::FINER => 'TRACE'
|
58
|
+
})
|
59
|
+
else
|
60
|
+
require 'color_console'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
# Returns a symbol identifying which logging framework is being used.
|
67
|
+
def log_framework
|
68
|
+
unless @log_framework
|
69
|
+
if RUBY_PLATFORM == 'java'
|
70
|
+
LogManager.log_framework = :java_util_logging
|
71
|
+
else
|
72
|
+
begin
|
73
|
+
require 'log4r'
|
74
|
+
LogManager.log_framework = :log4r
|
75
|
+
rescue LoadError
|
76
|
+
LogManager.log_framework = :stdout
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
@log_framework
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# Sets the logging framework
|
85
|
+
def log_framework=(framework)
|
86
|
+
unless Logging::FRAMEWORKS.include?(framework)
|
87
|
+
raise ArgumentError, "Unknown logging framework #{framework.inspect}"
|
88
|
+
end
|
89
|
+
if @log_framework
|
90
|
+
lvl = self.level
|
91
|
+
end
|
92
|
+
@log_framework = framework
|
93
|
+
if init_proc = Logging::FRAMEWORK_INIT[@log_framework]
|
94
|
+
init_proc.call
|
95
|
+
end
|
96
|
+
self.level = lvl if lvl
|
97
|
+
logger.trace "Log framework is #{@log_framework}"
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
# Returns the current root log level
|
102
|
+
def level
|
103
|
+
logger.level
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
# Sets the log level
|
108
|
+
def level=(level)
|
109
|
+
case log_framework
|
110
|
+
when :log4r
|
111
|
+
lvl = Log4r::LNAMES.index(level.to_s.upcase)
|
112
|
+
Log4r::Logger.each_logger{ |l| l.level = lvl }
|
113
|
+
else
|
114
|
+
logger.level = level
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
# Returns a logger with a given name, which must be under the 'batch'
|
120
|
+
# namespace. If name is omitted, the logger is named 'batch'. If a
|
121
|
+
# name is specified that is not under 'batch', then it is prepended
|
122
|
+
# with 'batch'.
|
123
|
+
#
|
124
|
+
# @return [Logger] a logger object that can be used for generating
|
125
|
+
# log messages. The type of logger returned will depend on the
|
126
|
+
# log framework being used, but the logger is guaranteed to
|
127
|
+
# implement the following log methods:
|
128
|
+
# - error
|
129
|
+
# - warning
|
130
|
+
# - info
|
131
|
+
# - config
|
132
|
+
# - detail
|
133
|
+
# - trace
|
134
|
+
# - debug
|
135
|
+
def logger(name = nil)
|
136
|
+
case name
|
137
|
+
when NilClass, ''
|
138
|
+
name = 'batch'
|
139
|
+
when /^batch/
|
140
|
+
when /\./
|
141
|
+
when String
|
142
|
+
name = "batch.#{name}"
|
143
|
+
end
|
144
|
+
case log_framework
|
145
|
+
when :stdout
|
146
|
+
BatchKit::Logging::StdOutLogger.logger(name)
|
147
|
+
when :java_util_logging
|
148
|
+
BatchKit::Logging::JavaLogFacade.new(Java::JavaUtilLogging::Logger.getLogger(name))
|
149
|
+
when :log4r
|
150
|
+
log4r_name = name.gsub('.', '::')
|
151
|
+
BatchKit::Logging::Log4rFacade.new(Log4r::Logger[log4r_name] ||
|
152
|
+
Log4r::Logger.new(log4r_name))
|
153
|
+
else BatchKit::Logging::NullLogger.instance
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
if defined?(Events) && defined?(Configurable)
|
161
|
+
Events.subscribe(Configurable, 'post-configure') do |src, cfg|
|
162
|
+
LogManager.configure(cfg)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|