a13g 0.1.0.beta3 → 0.1.0.beta4
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.
- 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
|