right_support 0.9.4 → 0.9.8
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/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'
|