a13g 0.1.0.beta3 → 0.1.0.beta4
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/Rakefile +53 -0
- data/a13g-0.1.0.beta3.gem +0 -0
- data/a13g.gemspec +100 -0
- data/examples/consumer.rb +16 -0
- data/examples/multiple_connections.rb +26 -0
- data/examples/producer.rb +11 -0
- data/examples/simple_project/README +3 -0
- data/examples/simple_project/Rakefile +6 -0
- data/examples/simple_project/config/broker.yml +10 -0
- data/examples/simple_project/lib/consumers/first_consumer.rb +7 -0
- data/examples/simple_project/lib/consumers/second_consumer.rb +9 -0
- data/examples/simple_project/lib/simple_project.rb +20 -0
- data/lib/a13g.rb +68 -0
- data/lib/a13g/adapters.rb +45 -0
- data/lib/a13g/adapters/abstract_adapter.rb +330 -0
- data/lib/a13g/adapters/stomp_adapter.rb +163 -0
- data/lib/a13g/adapters/test_adapter.rb +102 -0
- data/lib/a13g/base.rb +448 -0
- data/lib/a13g/command.rb +69 -0
- data/lib/a13g/consumer.rb +129 -0
- data/lib/a13g/destination.rb +22 -0
- data/lib/a13g/errors.rb +60 -0
- data/lib/a13g/listener.rb +190 -0
- data/lib/a13g/message.rb +68 -0
- data/lib/a13g/producer.rb +107 -0
- data/lib/a13g/railtie.rb +4 -0
- data/lib/a13g/recipes.rb +31 -0
- data/lib/a13g/subscription.rb +123 -0
- data/lib/a13g/support/logger.rb +194 -0
- data/lib/a13g/support/utils.rb +25 -0
- data/lib/a13g/utils.rb +25 -0
- data/lib/a13g/version.rb +10 -0
- data/spec/a13g_spec.rb +74 -0
- data/spec/config/broker.yml +4 -0
- data/spec/dconfig/broker.yml +4 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +14 -0
- metadata +50 -4
data/lib/a13g/message.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
module A13g
|
2
|
+
# This message class is based on stomp message. Should be used by all
|
3
|
+
# adapter to representating of received messages.
|
4
|
+
class Message
|
5
|
+
attr_accessor :headers
|
6
|
+
attr_reader :body, :command, :destination
|
7
|
+
attr_reader :original
|
8
|
+
attr_reader :id
|
9
|
+
attr_accessor :ack
|
10
|
+
|
11
|
+
# Constructor.
|
12
|
+
#
|
13
|
+
# @param [Object] original
|
14
|
+
# original object of received message
|
15
|
+
# @param [String] id
|
16
|
+
# message id
|
17
|
+
# @param [String] body
|
18
|
+
# message content
|
19
|
+
# @param [String] command
|
20
|
+
# type of received message, eg. MESSAGE, ERROR, etc...
|
21
|
+
# @param [A13g::Adapters::AbstractAdapter] connection
|
22
|
+
# connection related with message
|
23
|
+
#
|
24
|
+
# @api public
|
25
|
+
def initialize(original, id, headers, body, command='MESSAGE', connection=Base.connection)
|
26
|
+
@original = original
|
27
|
+
@headers, @body, @command = headers, body, command
|
28
|
+
@destination = Destination.new(@headers['destination'])
|
29
|
+
@id = id
|
30
|
+
@connection = connection
|
31
|
+
@ack = false
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_s # :nodoc:
|
35
|
+
"<A13g::Message @id='#{id} @body='#{body}' @headers='#{headers.inspect}' @command='#{command}'>"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Shortcut to acknowledge message.
|
39
|
+
#
|
40
|
+
# @api public
|
41
|
+
def ack!
|
42
|
+
@connection.ack(@original)
|
43
|
+
@ack = true
|
44
|
+
@connection.logger.info(">> (#{@connection.url}#{@destination.name}): ACK #{@id}")
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns true when message has been acknowledged
|
48
|
+
#
|
49
|
+
# @return [Boolean]
|
50
|
+
#
|
51
|
+
# @api public
|
52
|
+
def ack?
|
53
|
+
!!@ack
|
54
|
+
end
|
55
|
+
|
56
|
+
# It says to processor, that message processing should be aborded.
|
57
|
+
#
|
58
|
+
# @api public
|
59
|
+
def abort!
|
60
|
+
raise AbortMessage
|
61
|
+
end
|
62
|
+
|
63
|
+
# It says to processor, that message should be ignored.
|
64
|
+
def ignore!
|
65
|
+
raise IgnoreMessage
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module A13g
|
2
|
+
# Mixin for publishing messages.
|
3
|
+
#
|
4
|
+
# === Simple publishing:
|
5
|
+
#
|
6
|
+
# include A13g::Producer
|
7
|
+
# publish("/queue/Example", "This is test...")
|
8
|
+
#
|
9
|
+
# === Publishing to different hosts:
|
10
|
+
#
|
11
|
+
# A13g.setup(:first, :adapter => 'stomp', {}, :host => 'first.host.com')
|
12
|
+
# A13g.setup(:second, :adapter => 'stomp', {}, :host => 'second.host.com')
|
13
|
+
#
|
14
|
+
# publish("/queue/Example", "My first message", {}, :first) # will be sent to first.host.com
|
15
|
+
# publish("/queue/Example", "My second message", {}, :first) # will be sent to second.host.com
|
16
|
+
#
|
17
|
+
# === Access directly from A13g:
|
18
|
+
#
|
19
|
+
# A13g.publish("/queue/Example", "Message from A13g..."
|
20
|
+
#
|
21
|
+
# === Transactions:
|
22
|
+
#
|
23
|
+
# begin("trans")
|
24
|
+
# publish("/queue/Example", "First message...", { :transaction => "trans" })
|
25
|
+
# publish("/queue/Example", "Second message...", { :transaction => "trans" })
|
26
|
+
# publish("/queue/Example", "Third message...", { :transaction => "trans" })
|
27
|
+
# commit("trans")
|
28
|
+
module Producer
|
29
|
+
# Publishes message to specified destination.
|
30
|
+
#
|
31
|
+
# @param [String] destination
|
32
|
+
# where message should be sent
|
33
|
+
# @param [String] message
|
34
|
+
# text to send
|
35
|
+
# @param [Hash] headers
|
36
|
+
# message headers
|
37
|
+
# @param [Symbol] context
|
38
|
+
# connection name, which should be used
|
39
|
+
# @param [Array] args
|
40
|
+
# additional arguments
|
41
|
+
#
|
42
|
+
# @api public
|
43
|
+
def publish(destination, message, headers={}, context=nil, *args)
|
44
|
+
context ||= a13g_context
|
45
|
+
conn = Base.connection(context)
|
46
|
+
conn.logger.info(">> " + Utils.format_message("#{conn.url}#{destination}", message, headers))
|
47
|
+
conn.publish(destination, message, headers, *args)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Begins transaction.
|
51
|
+
#
|
52
|
+
# @param [String, Symbol] name
|
53
|
+
# transaction id
|
54
|
+
# @param [Hash] headers
|
55
|
+
# transaction additional headers
|
56
|
+
# @param [Symbol] context
|
57
|
+
# connection name, which should be used
|
58
|
+
# @param [Array] args
|
59
|
+
# additional arguments
|
60
|
+
#
|
61
|
+
# @api public
|
62
|
+
def begin(name, headers={}, context=nil, *args)
|
63
|
+
context ||= a13g_context
|
64
|
+
conn = Base.connection(context)
|
65
|
+
conn.logger.info("Begin transaction at #{conn.url}#{destination}")
|
66
|
+
conn.begin(name, headers, *args)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Commit specified transaction. Params the same as #begin method.
|
70
|
+
#
|
71
|
+
# @see A13g::Producer#begin
|
72
|
+
#
|
73
|
+
# @api public
|
74
|
+
def commit(name, headers={}, context=nil, *args)
|
75
|
+
context ||= a13g_context
|
76
|
+
conn = Base.connection(context)
|
77
|
+
conn.logger.info("Commit transaction to #{conn.url}#{destination}")
|
78
|
+
conn.commit(name, headers, *args)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Abort specified transaction. Params the same as #begin method.
|
82
|
+
#
|
83
|
+
# @see A13g::Producer#begin
|
84
|
+
#
|
85
|
+
# @api public
|
86
|
+
def abort(name, headers={}, context=nil, *args)
|
87
|
+
context ||= a13g_context
|
88
|
+
conn = Base.connection(context)
|
89
|
+
conn.logger.info("Abort transaction at #{conn.url}#{destination}")
|
90
|
+
conn.abort(name, headers, *args)
|
91
|
+
end
|
92
|
+
|
93
|
+
protected
|
94
|
+
|
95
|
+
# Current context for publishing.
|
96
|
+
#
|
97
|
+
# @api semipublic
|
98
|
+
def a13g_context
|
99
|
+
if respond_to?(:context)
|
100
|
+
context
|
101
|
+
else
|
102
|
+
:default
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
data/lib/a13g/railtie.rb
ADDED
data/lib/a13g/recipes.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Capistrano Recipes for managing active_messaging
|
2
|
+
#
|
3
|
+
# Add these callbacks to have the active_messaging process restart when the server
|
4
|
+
# is restarted:
|
5
|
+
#
|
6
|
+
# after "deploy:stop", "active_messaging:stop"
|
7
|
+
# after "deploy:start", "active_messaging:start"
|
8
|
+
# after "deploy:restart", "active_messaging:restart"
|
9
|
+
|
10
|
+
Capistrano::Configuration.instance.load do
|
11
|
+
namespace :delayed_job do
|
12
|
+
def rails_env
|
13
|
+
fetch(:rails_env, false) ? "RAILS_ENV=#{fetch(:rails_env)}" : ''
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Stop the active_messaging process"
|
17
|
+
task :stop, :roles => :app do
|
18
|
+
run "cd #{current_path};#{rails_env} script/messaging stop"
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Start the active_messaging process"
|
22
|
+
task :start, :roles => :app do
|
23
|
+
run "cd #{current_path};#{rails_env} script/messaging start"
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Restart the active_messaging process"
|
27
|
+
task :restart, :roles => :app do
|
28
|
+
run "cd #{current_path};#{rails_env} script/messaging restart"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module A13g
|
2
|
+
class Subscription
|
3
|
+
# Special class for list of subscribed destinations.
|
4
|
+
class DestinationsList < Hash; end
|
5
|
+
|
6
|
+
attr_reader :consumer, :destination, :headers, :connection, :args
|
7
|
+
|
8
|
+
# List of all defined destinations.
|
9
|
+
#
|
10
|
+
# @api public
|
11
|
+
cattr_accessor :all
|
12
|
+
@@all = DestinationsList.new
|
13
|
+
|
14
|
+
# Constructor.
|
15
|
+
#
|
16
|
+
# @param [A13g::Consumer] consumer
|
17
|
+
# consumer class
|
18
|
+
# @param [String] destination
|
19
|
+
# subscribed destination
|
20
|
+
# @param [Hash] headers
|
21
|
+
# additional connection headers
|
22
|
+
# @param [A13g::Adapters::AbstractAdapter] connection
|
23
|
+
# connection object related with subscription
|
24
|
+
# @param [Array] args
|
25
|
+
# additional subscription arguments
|
26
|
+
#
|
27
|
+
# @api public
|
28
|
+
def initialize(consumer, destination, connection=nil, headers={}, *args)
|
29
|
+
@consumer = consumer
|
30
|
+
@args = args
|
31
|
+
@connection = connection
|
32
|
+
@destination, @headers = destination, headers
|
33
|
+
@headers['persistent'] = true
|
34
|
+
@headers['id'] = @consumer.class.to_s if has_consumer?
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns `true` if consumer is assigned to this subscription.
|
38
|
+
#
|
39
|
+
# @return [Boolean]
|
40
|
+
# is there related consumer?
|
41
|
+
#
|
42
|
+
# @api public
|
43
|
+
def has_consumer?
|
44
|
+
!!consumer
|
45
|
+
end
|
46
|
+
|
47
|
+
# Subscribes current destination.
|
48
|
+
#
|
49
|
+
# @api public
|
50
|
+
def subscribe
|
51
|
+
if has_consumer?
|
52
|
+
connection.logger.debug("Destination #{connection.url}#{destination} subscribed by #{consumer.class.to_s}")
|
53
|
+
connection.subscribe(destination, headers, *args)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Unsubscribes destination.
|
58
|
+
#
|
59
|
+
# @api public
|
60
|
+
def unsubscribe
|
61
|
+
connection.unsubscribe(destination, headers, *args)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Port to publishing in current destination.
|
65
|
+
#
|
66
|
+
# @param [String] message
|
67
|
+
# text to send
|
68
|
+
# @param [Hash] headers
|
69
|
+
# additional connection headers
|
70
|
+
# @param [Array] args
|
71
|
+
# additional arguments
|
72
|
+
#
|
73
|
+
# @api public
|
74
|
+
def publish(message, headers={}, *args) # :nodoc:
|
75
|
+
headers = self.headers.merge(headers)
|
76
|
+
connection.publish(destination, message, headers, *args)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Find destination using specified conditions.
|
80
|
+
#
|
81
|
+
# @param [Array] conditions
|
82
|
+
# key only, or name of destination with connection object
|
83
|
+
#
|
84
|
+
# @return [A13g::Subscription]
|
85
|
+
# matching subscription
|
86
|
+
#
|
87
|
+
# @api public
|
88
|
+
def self.find(*conditions)
|
89
|
+
if conditions.size == 1
|
90
|
+
klass = conditions[0]
|
91
|
+
if all.key?(klass.to_s)
|
92
|
+
return all[klass.to_s]
|
93
|
+
else
|
94
|
+
raise DestinationNotDefinedError, "#{klass.to_s} don't subscribes any destination"
|
95
|
+
end
|
96
|
+
elsif conditions.size < 3
|
97
|
+
destination, connection = conditions[0], conditions[1]
|
98
|
+
return all.values.find {|x| x.destination == destination.to_s && x.connection === connection}
|
99
|
+
else
|
100
|
+
raise ArgumentError, 'To many actual parameters'
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
# Creates new subscription. Parameters the same as #initialize method.
|
106
|
+
#
|
107
|
+
# @see A13g::Subscription#initialize
|
108
|
+
#
|
109
|
+
# @return [A13g::Subscription]
|
110
|
+
# created subscription
|
111
|
+
#
|
112
|
+
# @api public
|
113
|
+
def self.create(consumer, destination, headers={}, connection=Base.connection, *args)
|
114
|
+
unless subscription = find(destination, connection)
|
115
|
+
return all[consumer.class.name] = new(consumer, destination, connection, headers, *args)
|
116
|
+
else
|
117
|
+
raise DestinationAlreadySubscribedError,
|
118
|
+
"Destination #{conneciton.url}#{destination} has been already subscribed by `#{consumer.class.name}`"
|
119
|
+
end
|
120
|
+
return subscription
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
require "time" # httpdate
|
2
|
+
# ==== Public Extlib Logger API
|
3
|
+
#
|
4
|
+
# To replace an existing logger with a new one:
|
5
|
+
# Extlib::Logger.set_log(log{String, IO},level{Symbol, String})
|
6
|
+
#
|
7
|
+
# Available logging levels are
|
8
|
+
# Extlib::Logger::{ Fatal, Error, Warn, Info, Debug }
|
9
|
+
#
|
10
|
+
# Logging via:
|
11
|
+
# Extlib.logger.fatal(message<String>,&block)
|
12
|
+
# Extlib.logger.error(message<String>,&block)
|
13
|
+
# Extlib.logger.warn(message<String>,&block)
|
14
|
+
# Extlib.logger.info(message<String>,&block)
|
15
|
+
# Extlib.logger.debug(message<String>,&block)
|
16
|
+
#
|
17
|
+
# Logging with autoflush:
|
18
|
+
# Extlib.logger.fatal!(message<String>,&block)
|
19
|
+
# Extlib.logger.error!(message<String>,&block)
|
20
|
+
# Extlib.logger.warn!(message<String>,&block)
|
21
|
+
# Extlib.logger.info!(message<String>,&block)
|
22
|
+
# Extlib.logger.debug!(message<String>,&block)
|
23
|
+
#
|
24
|
+
# Flush the buffer to
|
25
|
+
# Extlib.logger.flush
|
26
|
+
#
|
27
|
+
# Remove the current log object
|
28
|
+
# Extlib.logger.close
|
29
|
+
#
|
30
|
+
# ==== Private Extlib Logger API
|
31
|
+
#
|
32
|
+
# To initialize the logger you create a new object, proxies to set_log.
|
33
|
+
# Extlib::Logger.new(log{String, IO},level{Symbol, String})
|
34
|
+
module A13g
|
35
|
+
class Logger
|
36
|
+
|
37
|
+
attr_accessor :level
|
38
|
+
attr_accessor :delimiter
|
39
|
+
attr_accessor :auto_flush
|
40
|
+
attr_reader :buffer
|
41
|
+
attr_reader :log
|
42
|
+
attr_reader :init_args
|
43
|
+
|
44
|
+
# ==== Notes
|
45
|
+
# Ruby (standard) logger levels:
|
46
|
+
# :fatal:: An unhandleable error that results in a program crash
|
47
|
+
# :error:: A handleable error condition
|
48
|
+
# :warn:: A warning
|
49
|
+
# :info:: generic (useful) information about system operation
|
50
|
+
# :debug:: low-level information for developers
|
51
|
+
Levels =
|
52
|
+
{
|
53
|
+
:fatal => 7,
|
54
|
+
:error => 6,
|
55
|
+
:warn => 4,
|
56
|
+
:info => 3,
|
57
|
+
:debug => 0
|
58
|
+
}
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# Readies a log for writing.
|
63
|
+
#
|
64
|
+
# ==== Parameters
|
65
|
+
# log<IO, String>:: Either an IO object or a name of a logfile.
|
66
|
+
def initialize_log(log)
|
67
|
+
close if @log # be sure that we don't leave open files laying around.
|
68
|
+
|
69
|
+
if log.respond_to?(:write)
|
70
|
+
@log = log
|
71
|
+
elsif File.exist?(log)
|
72
|
+
@log = open(log, (File::WRONLY | File::APPEND))
|
73
|
+
@log.sync = true
|
74
|
+
else
|
75
|
+
FileUtils.mkdir_p(File.dirname(log)) unless File.directory?(File.dirname(log))
|
76
|
+
@log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
|
77
|
+
@log.sync = true
|
78
|
+
@log.write("#{Time.now.httpdate} #{delimiter} info #{delimiter} Logfile created\n")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
public
|
83
|
+
|
84
|
+
# To initialize the logger you create a new object, proxies to set_log.
|
85
|
+
#
|
86
|
+
# ==== Parameters
|
87
|
+
# *args:: Arguments to create the log from. See set_logs for specifics.
|
88
|
+
def initialize(*args)
|
89
|
+
@init_args = args
|
90
|
+
set_log(*args)
|
91
|
+
self.auto_flush = true
|
92
|
+
A13g.logger = self
|
93
|
+
end
|
94
|
+
|
95
|
+
# Replaces an existing logger with a new one.
|
96
|
+
#
|
97
|
+
# ==== Parameters
|
98
|
+
# log<IO, String>:: Either an IO object or a name of a logfile.
|
99
|
+
# log_level<~to_sym>::
|
100
|
+
# The log level from, e.g. :fatal or :info. Defaults to :error in the
|
101
|
+
# production environment and :debug otherwise.
|
102
|
+
# delimiter<String>::
|
103
|
+
# Delimiter to use between message sections. Defaults to " ~ ".
|
104
|
+
# auto_flush<Boolean>::
|
105
|
+
# Whether the log should automatically flush after new messages are
|
106
|
+
# added. Defaults to false.
|
107
|
+
def set_log(log, log_level = nil, delimiter = " ~ ", auto_flush = false)
|
108
|
+
if log_level && Levels[log_level.to_sym]
|
109
|
+
@level = Levels[log_level.to_sym]
|
110
|
+
else
|
111
|
+
@level = Levels[:debug]
|
112
|
+
end
|
113
|
+
@buffer = []
|
114
|
+
@delimiter = delimiter
|
115
|
+
@auto_flush = auto_flush
|
116
|
+
|
117
|
+
initialize_log(log)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Flush the entire buffer to the log object.
|
121
|
+
def flush
|
122
|
+
return unless @buffer.size > 0
|
123
|
+
@log.write(@buffer.slice!(0..-1).join)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Close and remove the current log object.
|
127
|
+
def close
|
128
|
+
flush
|
129
|
+
@log.close if @log.respond_to?(:close) && !@log.tty?
|
130
|
+
@log = nil
|
131
|
+
end
|
132
|
+
|
133
|
+
# Appends a message to the log. The methods yield to an optional block and
|
134
|
+
# the output of this block will be appended to the message.
|
135
|
+
#
|
136
|
+
# ==== Parameters
|
137
|
+
# string<String>:: The message to be logged. Defaults to nil.
|
138
|
+
#
|
139
|
+
# ==== Returns
|
140
|
+
# String:: The resulting message added to the log file.
|
141
|
+
def <<(string = nil)
|
142
|
+
message = ""
|
143
|
+
message << delimiter
|
144
|
+
message << string if string
|
145
|
+
message << "\n" unless message[-1] == ?\n
|
146
|
+
@buffer << message
|
147
|
+
flush if @auto_flush
|
148
|
+
|
149
|
+
message
|
150
|
+
end
|
151
|
+
alias :push :<<
|
152
|
+
|
153
|
+
# Generate the logging methods for Extlib.logger for each log level.
|
154
|
+
Levels.each_pair do |name, number|
|
155
|
+
class_eval <<-LEVELMETHODS, __FILE__, __LINE__
|
156
|
+
|
157
|
+
# Appends a message to the log if the log level is at least as high as
|
158
|
+
# the log level of the logger.
|
159
|
+
#
|
160
|
+
# ==== Parameters
|
161
|
+
# string<String>:: The message to be logged. Defaults to nil.
|
162
|
+
#
|
163
|
+
# ==== Returns
|
164
|
+
# self:: The logger object for chaining.
|
165
|
+
def #{name}(message = nil)
|
166
|
+
self << message if #{number} >= level
|
167
|
+
self
|
168
|
+
end
|
169
|
+
|
170
|
+
# Appends a message to the log if the log level is at least as high as
|
171
|
+
# the log level of the logger. The bang! version of the method also auto
|
172
|
+
# flushes the log buffer to disk.
|
173
|
+
#
|
174
|
+
# ==== Parameters
|
175
|
+
# string<String>:: The message to be logged. Defaults to nil.
|
176
|
+
#
|
177
|
+
# ==== Returns
|
178
|
+
# self:: The logger object for chaining.
|
179
|
+
def #{name}!(message = nil)
|
180
|
+
self << message if #{number} >= level
|
181
|
+
flush if #{number} >= level
|
182
|
+
self
|
183
|
+
end
|
184
|
+
|
185
|
+
# ==== Returns
|
186
|
+
# Boolean:: True if this level will be logged by this logger.
|
187
|
+
def #{name}?
|
188
|
+
#{number} >= level
|
189
|
+
end
|
190
|
+
LEVELMETHODS
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
end
|