right_support 0.9.4 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/right_support/cassandra_model.rb +3 -0
- data/lib/right_support/db/cassandra_model.rb +129 -0
- data/lib/right_support/db.rb +34 -0
- data/lib/right_support/filter_logger.rb +1 -120
- data/lib/right_support/log/filter_logger.rb +122 -0
- data/lib/right_support/log/system_logger.rb +176 -0
- data/lib/right_support/log/tag_logger.rb +72 -0
- data/lib/right_support/log.rb +34 -0
- data/lib/right_support/net/address_helper.rb +125 -0
- data/lib/right_support/net/request_balancer/policy.rb +14 -0
- data/lib/right_support/net/request_balancer/round_robin.rb +7 -0
- data/lib/right_support/net/request_balancer.rb +16 -5
- data/lib/right_support/net.rb +2 -0
- data/lib/right_support/rack/custom_logger.rb +29 -33
- data/lib/right_support/rack.rb +34 -0
- data/lib/right_support/{kernel_extensions.rb → ruby/object_extensions.rb} +3 -3
- data/lib/right_support/ruby.rb +34 -0
- data/lib/right_support/system_logger.rb +2 -175
- data/lib/right_support/tag_logger.rb +1 -70
- data/lib/right_support.rb +10 -6
- data/right_support.gemspec +2 -2
- metadata +17 -5
@@ -0,0 +1,129 @@
|
|
1
|
+
module RightSupport::DB
|
2
|
+
class CassandraModel
|
3
|
+
DEFAULT_TIMEOUT = 10
|
4
|
+
class << self
|
5
|
+
@@logger=nil
|
6
|
+
@@conn = nil
|
7
|
+
|
8
|
+
attr_accessor :column_family
|
9
|
+
attr_writer :keyspace
|
10
|
+
|
11
|
+
def config
|
12
|
+
@@config
|
13
|
+
end
|
14
|
+
|
15
|
+
def config=(value)
|
16
|
+
@@config = value
|
17
|
+
end
|
18
|
+
|
19
|
+
def logger=(l)
|
20
|
+
@@logger=l
|
21
|
+
end
|
22
|
+
|
23
|
+
def logger
|
24
|
+
@@logger
|
25
|
+
end
|
26
|
+
|
27
|
+
def keyspace
|
28
|
+
@keyspace + "_" + (ENV['RACK_ENV'] || 'development')
|
29
|
+
end
|
30
|
+
|
31
|
+
def conn
|
32
|
+
return @@conn if @@conn
|
33
|
+
|
34
|
+
config = @@config[ENV["RACK_ENV"]]
|
35
|
+
@@conn = Cassandra.new(keyspace, config["server"],{:timeout => RightSupport::CassandraModel::DEFAULT_TIMEOUT})
|
36
|
+
@@conn.disable_node_auto_discovery!
|
37
|
+
@@conn
|
38
|
+
end
|
39
|
+
|
40
|
+
def all(k,opt={})
|
41
|
+
list = real_get(k,opt)
|
42
|
+
end
|
43
|
+
|
44
|
+
def get(key)
|
45
|
+
if (hash = real_get(key)).empty?
|
46
|
+
nil
|
47
|
+
else
|
48
|
+
new(key, hash)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def real_get(k,opt={})
|
53
|
+
if k.is_a?(Array)
|
54
|
+
do_op(:multi_get, column_family, k, opt)
|
55
|
+
else
|
56
|
+
do_op(:get, column_family, k, opt)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def insert(key, values,opt={})
|
61
|
+
do_op(:insert, column_family, key, values,opt)
|
62
|
+
end
|
63
|
+
|
64
|
+
def remove(*args)
|
65
|
+
do_op(:remove, column_family, *args)
|
66
|
+
end
|
67
|
+
|
68
|
+
def batch(*args,&block)
|
69
|
+
raise "Block required!" unless block_given?
|
70
|
+
do_op(:batch,*args, &block)
|
71
|
+
end
|
72
|
+
|
73
|
+
def do_op(meth, *args, &block)
|
74
|
+
conn.send(meth, *args, &block)
|
75
|
+
rescue IOError
|
76
|
+
reconnect
|
77
|
+
retry
|
78
|
+
end
|
79
|
+
|
80
|
+
def reconnect
|
81
|
+
config = @@config[ENV["RACK_ENV"]]
|
82
|
+
@@conn = Cassandra.new(keyspace, config["server"],{:timeout => RightSupport::CassandraModel::DEFAULT_TIMEOUT})
|
83
|
+
@@conn.disable_node_auto_discovery!
|
84
|
+
end
|
85
|
+
|
86
|
+
def ring
|
87
|
+
conn.ring
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
attr_accessor :key, :attributes
|
92
|
+
|
93
|
+
def initialize(key, attrs={})
|
94
|
+
self.key = key
|
95
|
+
self.attributes = attrs
|
96
|
+
end
|
97
|
+
|
98
|
+
def save
|
99
|
+
self.class.insert(key, attributes)
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
def reload
|
104
|
+
self.class.get(key)
|
105
|
+
end
|
106
|
+
|
107
|
+
def reload!
|
108
|
+
self.attributes = self.class.real_get(key)
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
112
|
+
def [](key)
|
113
|
+
ret = attributes[key]
|
114
|
+
return ret if ret
|
115
|
+
if key.kind_of? Integer
|
116
|
+
return attributes[Cassandra::Long.new(key)]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def []=(key, value)
|
121
|
+
attributes[key] = value
|
122
|
+
end
|
123
|
+
|
124
|
+
def destroy
|
125
|
+
self.class.remove(key)
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
module RightSupport
|
24
|
+
#
|
25
|
+
# A namespace for database classes and helper modules.
|
26
|
+
#
|
27
|
+
module DB
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Dir[File.expand_path('../db/*.rb', __FILE__)].each do |filename|
|
33
|
+
require filename
|
34
|
+
end
|
@@ -1,122 +1,3 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (c) 2011 RightScale Inc
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
-
# a copy of this software and associated documentation files (the
|
6
|
-
# "Software"), to deal in the Software without restriction, including
|
7
|
-
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
-
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
-
# the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be
|
13
|
-
# included in all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
-
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
-
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
-
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
|
23
|
-
require 'logger'
|
24
|
-
|
25
1
|
module RightSupport
|
26
|
-
|
27
|
-
# before they are passed to the underlying Logger. Can be used to for various log-
|
28
|
-
# processing tasks such as filtering sensitive data or tagging log lines with a
|
29
|
-
# context marker.
|
30
|
-
class FilterLogger < Logger
|
31
|
-
# Initialize a new instance of this class.
|
32
|
-
#
|
33
|
-
# === Parameters
|
34
|
-
# actual_logger(Logger):: The actual, underlying Logger object
|
35
|
-
#
|
36
|
-
def initialize(actual_logger)
|
37
|
-
@actual_logger = actual_logger
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
# Add a log line, filtering the severity and message before calling through
|
42
|
-
# to the underlying logger's #add method.
|
43
|
-
#
|
44
|
-
# === Parameters
|
45
|
-
# severity(Integer):: one of the Logger severity constants
|
46
|
-
# message(String):: the message to log, or nil
|
47
|
-
# progname(String):: the program name, or nil
|
48
|
-
#
|
49
|
-
# === Block
|
50
|
-
# If message == nil and a block is given, yields to the block in order to
|
51
|
-
# capture the log message. This matches the behavior of Logger, but ensures
|
52
|
-
# the severity and message are still filtered.
|
53
|
-
#
|
54
|
-
# === Return
|
55
|
-
# the result of the underlying logger's #add
|
56
|
-
def add(severity, message = nil, progname = nil, &block)
|
57
|
-
severity ||= UNKNOWN
|
58
|
-
return true if severity < level
|
59
|
-
|
60
|
-
if message.nil?
|
61
|
-
if block_given?
|
62
|
-
message = yield
|
63
|
-
else
|
64
|
-
message = progname
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
severity, message = filter(severity, message)
|
69
|
-
return @actual_logger.add(severity, message) if message
|
70
|
-
end
|
71
|
-
|
72
|
-
# Proxies to the encapsulated Logger object. See Logger#<< for info.
|
73
|
-
def <<(msg)
|
74
|
-
@actual_logger << msg
|
75
|
-
end
|
76
|
-
|
77
|
-
# Proxies to the encapsulated Logger object. See Logger#close for info.
|
78
|
-
def close
|
79
|
-
@actual_logger.close
|
80
|
-
end
|
81
|
-
|
82
|
-
# Proxies to the encapsulated Logger object. See Logger#level for info.
|
83
|
-
def level
|
84
|
-
@actual_logger.level
|
85
|
-
end
|
86
|
-
|
87
|
-
# Proxies to the encapsulated Logger object. See Logger#level= for info.
|
88
|
-
def level=(new_level)
|
89
|
-
@actual_logger.level = new_level
|
90
|
-
end
|
91
|
-
|
92
|
-
# Proxies to the encapsulated Logger object. See Logger#debug? for info.
|
93
|
-
def debug?; @actual_logger.debug?; end
|
94
|
-
|
95
|
-
# Proxies to the encapsulated Logger object. See Logger#info? for info.
|
96
|
-
def info?; @actual_logger.info?; end
|
97
|
-
|
98
|
-
# Proxies to the encapsulated Logger object. See Logger#warn? for info.
|
99
|
-
def warn?; @actual_logger.warn?; end
|
100
|
-
|
101
|
-
# Proxies to the encapsulated Logger object. See Logger#error? for info.
|
102
|
-
def error?; @actual_logger.error?; end
|
103
|
-
|
104
|
-
# Proxies to the encapsulated Logger object. See Logger#fatal? for info.
|
105
|
-
def fatal?; @actual_logger.fatal?; end
|
106
|
-
|
107
|
-
protected
|
108
|
-
|
109
|
-
# Filter a log line, transforming its severity and/or message before it is
|
110
|
-
# passed to the underlying logger.
|
111
|
-
#
|
112
|
-
# === Parameters
|
113
|
-
# severity(Integer):: one of the severity constants defined by Logger
|
114
|
-
# messgae(String):: the log message
|
115
|
-
#
|
116
|
-
# === Return
|
117
|
-
# Returns a pair consisting of the filtered [severity, message].
|
118
|
-
def filter(severity, message)
|
119
|
-
return [severity, message]
|
120
|
-
end
|
121
|
-
end
|
2
|
+
FilterLogger = RightSupport::Log::FilterLogger
|
122
3
|
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'logger'
|
24
|
+
|
25
|
+
module RightSupport::Log
|
26
|
+
# A logger than encapsulates an underlying Logger object and filters log entries
|
27
|
+
# before they are passed to the underlying Logger. Can be used to for various log-
|
28
|
+
# processing tasks such as filtering sensitive data or tagging log lines with a
|
29
|
+
# context marker.
|
30
|
+
class FilterLogger < Logger
|
31
|
+
# Initialize a new instance of this class.
|
32
|
+
#
|
33
|
+
# === Parameters
|
34
|
+
# actual_logger(Logger):: The actual, underlying Logger object
|
35
|
+
#
|
36
|
+
def initialize(actual_logger)
|
37
|
+
@actual_logger = actual_logger
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
# Add a log line, filtering the severity and message before calling through
|
42
|
+
# to the underlying logger's #add method.
|
43
|
+
#
|
44
|
+
# === Parameters
|
45
|
+
# severity(Integer):: one of the Logger severity constants
|
46
|
+
# message(String):: the message to log, or nil
|
47
|
+
# progname(String):: the program name, or nil
|
48
|
+
#
|
49
|
+
# === Block
|
50
|
+
# If message == nil and a block is given, yields to the block in order to
|
51
|
+
# capture the log message. This matches the behavior of Logger, but ensures
|
52
|
+
# the severity and message are still filtered.
|
53
|
+
#
|
54
|
+
# === Return
|
55
|
+
# the result of the underlying logger's #add
|
56
|
+
def add(severity, message = nil, progname = nil, &block)
|
57
|
+
severity ||= UNKNOWN
|
58
|
+
return true if severity < level
|
59
|
+
|
60
|
+
if message.nil?
|
61
|
+
if block_given?
|
62
|
+
message = yield
|
63
|
+
else
|
64
|
+
message = progname
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
severity, message = filter(severity, message)
|
69
|
+
return @actual_logger.add(severity, message) if message
|
70
|
+
end
|
71
|
+
|
72
|
+
# Proxies to the encapsulated Logger object. See Logger#<< for info.
|
73
|
+
def <<(msg)
|
74
|
+
@actual_logger << msg
|
75
|
+
end
|
76
|
+
|
77
|
+
# Proxies to the encapsulated Logger object. See Logger#close for info.
|
78
|
+
def close
|
79
|
+
@actual_logger.close
|
80
|
+
end
|
81
|
+
|
82
|
+
# Proxies to the encapsulated Logger object. See Logger#level for info.
|
83
|
+
def level
|
84
|
+
@actual_logger.level
|
85
|
+
end
|
86
|
+
|
87
|
+
# Proxies to the encapsulated Logger object. See Logger#level= for info.
|
88
|
+
def level=(new_level)
|
89
|
+
@actual_logger.level = new_level
|
90
|
+
end
|
91
|
+
|
92
|
+
# Proxies to the encapsulated Logger object. See Logger#debug? for info.
|
93
|
+
def debug?; @actual_logger.debug?; end
|
94
|
+
|
95
|
+
# Proxies to the encapsulated Logger object. See Logger#info? for info.
|
96
|
+
def info?; @actual_logger.info?; end
|
97
|
+
|
98
|
+
# Proxies to the encapsulated Logger object. See Logger#warn? for info.
|
99
|
+
def warn?; @actual_logger.warn?; end
|
100
|
+
|
101
|
+
# Proxies to the encapsulated Logger object. See Logger#error? for info.
|
102
|
+
def error?; @actual_logger.error?; end
|
103
|
+
|
104
|
+
# Proxies to the encapsulated Logger object. See Logger#fatal? for info.
|
105
|
+
def fatal?; @actual_logger.fatal?; end
|
106
|
+
|
107
|
+
protected
|
108
|
+
|
109
|
+
# Filter a log line, transforming its severity and/or message before it is
|
110
|
+
# passed to the underlying logger.
|
111
|
+
#
|
112
|
+
# === Parameters
|
113
|
+
# severity(Integer):: one of the severity constants defined by Logger
|
114
|
+
# messgae(String):: the log message
|
115
|
+
#
|
116
|
+
# === Return
|
117
|
+
# Returns a pair consisting of the filtered [severity, message].
|
118
|
+
def filter(severity, message)
|
119
|
+
return [severity, message]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'logger'
|
24
|
+
|
25
|
+
module RightSupport::Log
|
26
|
+
if_require_succeeds('syslog') do
|
27
|
+
# A logger that forwards log entries to the Unix syslog facility, but complies
|
28
|
+
# with the interface of the Ruby Logger object and faithfully translates log
|
29
|
+
# severities and other concepts. Provides optional cleanup/filtering in order
|
30
|
+
# to keep the syslog from having weird characters or being susceptible to log
|
31
|
+
# forgery.
|
32
|
+
class SystemLogger < Logger
|
33
|
+
LOGGER_LEVELS = {
|
34
|
+
UNKNOWN => :alert,
|
35
|
+
FATAL => :err,
|
36
|
+
ERROR => :warning,
|
37
|
+
WARN => :notice,
|
38
|
+
INFO => :info,
|
39
|
+
DEBUG => :debug
|
40
|
+
}
|
41
|
+
|
42
|
+
SYSLOG_LEVELS = LOGGER_LEVELS.invert
|
43
|
+
DEFAULT_SYSLOG_LEVEL = :alert
|
44
|
+
|
45
|
+
DEFAULT_OPTIONS = {:split=>false, :color=>false}
|
46
|
+
|
47
|
+
@@syslog = nil
|
48
|
+
|
49
|
+
# Initialize this process's syslog facilities and construct a new syslog
|
50
|
+
# logger object.
|
51
|
+
#
|
52
|
+
# === Parameters
|
53
|
+
# program_name(String):: the syslog program name, 'ruby' by default
|
54
|
+
# options(Hash):: (optional) configuration options to use, see below
|
55
|
+
#
|
56
|
+
# === Options
|
57
|
+
# facility:: the syslog facility to use for messages, 'local0' by default
|
58
|
+
# split(true|false):: if true, splits multi-line messages into separate syslog entries
|
59
|
+
# color(true|false):: if true, passes ANSI escape sequences through to syslog
|
60
|
+
#
|
61
|
+
def initialize(program_name='ruby', options={})
|
62
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
63
|
+
@level = Logger::DEBUG
|
64
|
+
|
65
|
+
facility = options[:facility] || 'local0'
|
66
|
+
fac_map = {'user'=>8}
|
67
|
+
(0..7).each { |i| fac_map['local'+i.to_s] = 128+8*i }
|
68
|
+
|
69
|
+
@@syslog ||= Syslog.open(program_name, nil, fac_map[facility.to_s])
|
70
|
+
end
|
71
|
+
|
72
|
+
# Log a message if the given severity is high enough. This is the generic
|
73
|
+
# logging method. Users will be more inclined to use #debug, #info, #warn,
|
74
|
+
# #error, and #fatal.
|
75
|
+
#
|
76
|
+
# === Parameters
|
77
|
+
# severity(Integer):: one of the severity constants defined by Logger
|
78
|
+
# message(Object):: the message to be logged
|
79
|
+
# progname(String):: ignored, the program name is fixed at initialization
|
80
|
+
#
|
81
|
+
# === Block
|
82
|
+
# If message is nil and a block is supplied, this method will yield to
|
83
|
+
# obtain the log message.
|
84
|
+
#
|
85
|
+
# === Return
|
86
|
+
# true:: always returns true
|
87
|
+
#
|
88
|
+
def add(severity, message = nil, progname = nil, &block)
|
89
|
+
severity ||= UNKNOWN
|
90
|
+
if @@syslog.nil? or severity < @level
|
91
|
+
return true
|
92
|
+
end
|
93
|
+
|
94
|
+
progname ||= @progname
|
95
|
+
|
96
|
+
if message.nil?
|
97
|
+
if block_given?
|
98
|
+
message = yield
|
99
|
+
else
|
100
|
+
message = progname
|
101
|
+
progname = @progname
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
parts = clean(message)
|
106
|
+
parts.each { |part| emit_syslog(severity, part) }
|
107
|
+
return true
|
108
|
+
end
|
109
|
+
|
110
|
+
# Emit a log entry at INFO severity.
|
111
|
+
#
|
112
|
+
# === Parameters
|
113
|
+
# msg(Object):: the message to log
|
114
|
+
#
|
115
|
+
# === Return
|
116
|
+
# true:: always returns true
|
117
|
+
#
|
118
|
+
def <<(msg)
|
119
|
+
info(msg)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Do nothing. This method is provided for Logger interface compatibility.
|
123
|
+
#
|
124
|
+
# === Return
|
125
|
+
# true:: always returns true
|
126
|
+
#
|
127
|
+
def close
|
128
|
+
return true
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
# Call the syslog function to emit a syslog entry.
|
134
|
+
#
|
135
|
+
# === Parameters
|
136
|
+
# severity(Integer):: one of the Logger severity constants
|
137
|
+
# message(String):: the log message
|
138
|
+
#
|
139
|
+
# === Return
|
140
|
+
# true:: always returns true
|
141
|
+
def emit_syslog(severity, message)
|
142
|
+
level = SYSLOG_LEVELS[severity] || DEFAULT_SYSLOG_LEVEL
|
143
|
+
@@syslog.send(level, message)
|
144
|
+
return true
|
145
|
+
end
|
146
|
+
|
147
|
+
# Perform cleanup, output escaping and splitting on message.
|
148
|
+
# The operations that it performs can vary, depending on the
|
149
|
+
# options that were passed to this logger at initialization
|
150
|
+
# time.
|
151
|
+
#
|
152
|
+
# === Parameters
|
153
|
+
# message(String):: raw log message
|
154
|
+
#
|
155
|
+
# === Return
|
156
|
+
# log_lines([String]):: an array of String messages that should be logged separately to syslog
|
157
|
+
def clean(message)
|
158
|
+
message = message.to_s.dup
|
159
|
+
message.strip!
|
160
|
+
message.gsub!(/%/, '%%') # syslog(3) freaks on % (printf)
|
161
|
+
|
162
|
+
unless @options[:color]
|
163
|
+
message.gsub!(/\e\[[^m]*m/, '') # remove useless ansi color codes
|
164
|
+
end
|
165
|
+
|
166
|
+
if @options[:split]
|
167
|
+
bits = message.split(/[\n\r]+/)
|
168
|
+
else
|
169
|
+
bits = [message]
|
170
|
+
end
|
171
|
+
|
172
|
+
return bits
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'logger'
|
24
|
+
|
25
|
+
module RightSupport::Log
|
26
|
+
# A logger that prepends a tag to every message that is emitted. Can be used to
|
27
|
+
# correlate logs with a Web session ID, transaction ID or other context.
|
28
|
+
#
|
29
|
+
# The user of this logger is responsible for calling #tag= to set the tag as
|
30
|
+
# appropriate, e.g. in a Web request around-filter.
|
31
|
+
#
|
32
|
+
# This logger uses thread-local storage (TLS) to provide tagging on a per-thread
|
33
|
+
# basis; however, it does not account for EventMachine, neverblock, the use of
|
34
|
+
# Ruby fibers, or any other phenomenon that can "hijack" a thread's call stack.
|
35
|
+
#
|
36
|
+
class TagLogger < FilterLogger
|
37
|
+
# Prepend the current tag to the log message; return the same severity and
|
38
|
+
# the modified message.
|
39
|
+
#
|
40
|
+
# === Parameters
|
41
|
+
# severity(Integer):: one of the severity constants defined by Logger
|
42
|
+
# messgae(String):: the log message
|
43
|
+
#
|
44
|
+
# === Return
|
45
|
+
# Returns a pair consisting of the filtered [severity, message].
|
46
|
+
#
|
47
|
+
def filter(severity, message)
|
48
|
+
@tls_id ||= "tag_logger_#{self.object_id}"
|
49
|
+
tag = Thread.current[@tls_id] || ''
|
50
|
+
if tag
|
51
|
+
return [severity, tag + message]
|
52
|
+
else
|
53
|
+
return [severity, message]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :tag
|
58
|
+
|
59
|
+
# Set the tag for this logger.
|
60
|
+
#
|
61
|
+
# === Parameters
|
62
|
+
# tag(String|nil):: the new tag, or nil to remove the tag
|
63
|
+
#
|
64
|
+
# === Return
|
65
|
+
# String:: returns the new tag
|
66
|
+
def tag=(tag)
|
67
|
+
@tag = tag
|
68
|
+
@tls_id ||= "tag_logger_#{self.object_id}"
|
69
|
+
Thread.current[@tls_id] = @tag
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
module RightSupport
|
24
|
+
#
|
25
|
+
# A namespace for logging functionality.
|
26
|
+
#
|
27
|
+
module Log
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'right_support/log/system_logger'
|
33
|
+
require 'right_support/log/filter_logger'
|
34
|
+
require 'right_support/log/tag_logger'
|