batch-kit 0.3
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.
- 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
|
+
|