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,125 @@
|
|
1
|
+
# Copyright (c) 2009-2011 RightScale, Inc, All Rights Reserved Worldwide.
|
2
|
+
#
|
3
|
+
# THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE
|
4
|
+
# AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use,
|
5
|
+
# reproduction, modification, or disclosure of this program is
|
6
|
+
# strictly prohibited. Any use of this program by an authorized
|
7
|
+
# licensee is strictly subject to the terms and conditions,
|
8
|
+
# including confidentiality obligations, set forth in the applicable
|
9
|
+
# License Agreement between RightScale.com, Inc. and the licensee.
|
10
|
+
|
11
|
+
require 'socket'
|
12
|
+
|
13
|
+
module RightSupport::Net
|
14
|
+
# A helper module that provides some useful methods for querying the local machine about its network
|
15
|
+
# addresses.
|
16
|
+
#
|
17
|
+
# This module is automatically included into the eigenclass of RightSupport::Net for convenience. Any
|
18
|
+
# of the methods available in this module can be called as RightSupport::Net.foo without needing to
|
19
|
+
# include this module.
|
20
|
+
module AddressHelper
|
21
|
+
class NoSuitableInterface < RuntimeError; end
|
22
|
+
|
23
|
+
PRIVATE_IP_REGEX = /^(10\.|192\.168\.|172\.(1[6789]|2[0-9]|3[01]))/
|
24
|
+
LOOPBACK_IP_REGEX = /^(127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})/
|
25
|
+
|
26
|
+
# Determine the network address of some local interface that has a route to the public Internet.
|
27
|
+
#
|
28
|
+
# On some systems, Socket.getaddrinfo(Socket.gethostname, ...) does not return any IP addresses,
|
29
|
+
# for instance because the local hostname cannot be resolved by DNS. This method can be used to
|
30
|
+
# detect "my IP address" in such cases.
|
31
|
+
#
|
32
|
+
# This code does NOT make a connection or send any packets (to 64.233.187.99 which is google).
|
33
|
+
# Since UDP is a stateless protocol, connect() merely makes a system call which figures out how
|
34
|
+
# to route the packets based on the address and what interface (and therefore IP address) it
|
35
|
+
# should bind to. addr() returns an array containing the family (AF_INET), local port, and
|
36
|
+
# local address (which is what we want) of the socket.
|
37
|
+
#
|
38
|
+
# === Parameters
|
39
|
+
# address_family(Integer):: Socket::AF_INET or Socket::AF_INET6
|
40
|
+
#
|
41
|
+
# === Return
|
42
|
+
# address(String):: a single IP address in dotted-quad notation
|
43
|
+
def local_routable_address(address_family)
|
44
|
+
case address_family
|
45
|
+
when Socket::AF_INET
|
46
|
+
remote_address = '64.233.187.99'
|
47
|
+
when Socket::AF_INET6
|
48
|
+
remote_address = '2607:f8b0:4003:c00::68'
|
49
|
+
else
|
50
|
+
raise ArgumentError, "Routable address discovery only works for AF_INET or AF_INET6"
|
51
|
+
end
|
52
|
+
|
53
|
+
# turn off reverse DNS resolution temporarily
|
54
|
+
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
|
55
|
+
UDPSocket.open(address_family) do |s|
|
56
|
+
s.connect remote_address, 1
|
57
|
+
s.addr.last
|
58
|
+
end
|
59
|
+
ensure
|
60
|
+
Socket.do_not_reverse_lookup = orig
|
61
|
+
end
|
62
|
+
|
63
|
+
# Determine all network addresses of the local machine that are resolvable using either the machine's
|
64
|
+
# hostname or "localhost". Typically this allows us to discover the local IP addresses of
|
65
|
+
# "interesting" network interfaces without relying on OS-specific tools such as ifconfig/ipconfig.
|
66
|
+
#
|
67
|
+
# === Parameters
|
68
|
+
# address_family(Integer):: Socket::AF_INET or Socket::AF_INET6
|
69
|
+
#
|
70
|
+
# === Return
|
71
|
+
# addresses(Array):: a list of IP addresses in dotted-quad notation
|
72
|
+
def local_hostname_addresses(address_family)
|
73
|
+
loopback = Socket.getaddrinfo('localhost', 1,
|
74
|
+
address_family, Socket::SOCK_STREAM,
|
75
|
+
nil, nil).collect { |x| x[3] }
|
76
|
+
|
77
|
+
real = Socket.getaddrinfo(Socket.gethostname, 1,
|
78
|
+
address_family, Socket::SOCK_STREAM,
|
79
|
+
nil, nil).collect { |x| x[3] }
|
80
|
+
(loopback + real).uniq
|
81
|
+
end
|
82
|
+
|
83
|
+
# Determine all IPv4 addresses of the local machine that fall into the given range of IP address space
|
84
|
+
# (public, private or loopback).
|
85
|
+
#
|
86
|
+
# === Parameters
|
87
|
+
# flavor(Symbol):: One of :public, :private or :loopback
|
88
|
+
#
|
89
|
+
# === Return
|
90
|
+
# addresses(Array):: a list of IP addresses in dotted-quad notation
|
91
|
+
def my_ipv4_addresses(flavor=:private)
|
92
|
+
all = local_hostname_addresses(Socket::AF_INET)
|
93
|
+
all << local_routable_address(Socket::AF_INET)
|
94
|
+
all.uniq!
|
95
|
+
|
96
|
+
case flavor
|
97
|
+
when :public
|
98
|
+
return all.select { |ip| ip !~ PRIVATE_IP_REGEX && ip !~ LOOPBACK_IP_REGEX }
|
99
|
+
when :private
|
100
|
+
return all.select { |ip| ip =~ PRIVATE_IP_REGEX }
|
101
|
+
when :loopback
|
102
|
+
return all.select { |ip| ip =~ LOOPBACK_IP_REGEX }
|
103
|
+
else
|
104
|
+
raise ArgumentError, "flavor must be :public, :private or :loopback"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Determine an IPv4 address of the local machine that falls into the given range of IP address space
|
109
|
+
# (public, private or loopback). If multiple suitable addresses are found, the same address will be
|
110
|
+
# consistently returned but there is no way to influence _which_ address that will be.
|
111
|
+
#
|
112
|
+
# === Parameters
|
113
|
+
# flavor(Symbol):: One of :public, :private or :loopback
|
114
|
+
#
|
115
|
+
# === Return
|
116
|
+
# addresses(Array):: a list of IP addresses in dotted-quad notation
|
117
|
+
def my_ipv4_address(flavor=:private)
|
118
|
+
candidates = my_ipv4_addresses(flavor)
|
119
|
+
raise NoSuitableInterface, "No interface had a #{flavor} IPv4 address" if candidates.empty?
|
120
|
+
|
121
|
+
#Ensure we consistently the same interface by doing a lexical sort
|
122
|
+
return candidates.sort.first
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -91,12 +91,16 @@ module RightSupport::Net
|
|
91
91
|
|
92
92
|
exceptions = []
|
93
93
|
result = nil
|
94
|
-
|
94
|
+
complete = false
|
95
|
+
n = 0
|
96
|
+
|
97
|
+
while !complete && n < @endpoints.size
|
98
|
+
endpoint = next_endpoint
|
99
|
+
n += 1
|
95
100
|
|
96
|
-
@endpoints.each do |endpoint|
|
97
101
|
begin
|
98
|
-
result
|
99
|
-
|
102
|
+
result = yield(endpoint)
|
103
|
+
complete = true
|
100
104
|
break
|
101
105
|
rescue Exception => e
|
102
106
|
if to_raise = handle_exception(endpoint, e)
|
@@ -107,7 +111,7 @@ module RightSupport::Net
|
|
107
111
|
end
|
108
112
|
end
|
109
113
|
|
110
|
-
return result if
|
114
|
+
return result if complete
|
111
115
|
|
112
116
|
exceptions = exceptions.map { |e| e.class.name }.uniq.join(', ')
|
113
117
|
raise NoResult, "All URLs in the rotation failed! Exceptions: #{exceptions}"
|
@@ -142,6 +146,13 @@ module RightSupport::Net
|
|
142
146
|
end
|
143
147
|
end
|
144
148
|
|
149
|
+
def next_endpoint
|
150
|
+
@round_robin ||= 0
|
151
|
+
result = @endpoints[ @round_robin % @endpoints.size ]
|
152
|
+
@round_robin += 1
|
153
|
+
return result
|
154
|
+
end
|
155
|
+
|
145
156
|
# Test that something is a callable (Proc, Lambda or similar) with the expected arity.
|
146
157
|
# Used mainly by the initializer to test for correct options.
|
147
158
|
def test_callable_arity(callable, arity, optional)
|
data/lib/right_support/net.rb
CHANGED
@@ -22,41 +22,37 @@
|
|
22
22
|
|
23
23
|
require 'logger'
|
24
24
|
|
25
|
-
module RightSupport
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
@app, @level = app, level
|
25
|
+
module RightSupport::Rack
|
26
|
+
# A Rack middleware that allows an arbitrary object to be used as the Rack logger.
|
27
|
+
# This is more flexible than Rack's built-in Logger middleware, which always logs
|
28
|
+
# to a file-based Logger and doesn't allow you to control anything other than the
|
29
|
+
# filename.
|
30
|
+
class CustomLogger
|
31
|
+
# Initialize an instance of the middleware.
|
32
|
+
#
|
33
|
+
# === Parameters
|
34
|
+
# app(Object):: the inner application or middleware layer; must respond to #call
|
35
|
+
# level(Integer):: one of the Logger constants: DEBUG, INFO, WARN, ERROR, FATAL
|
36
|
+
# logger(Logger):: (optional) the Logger object to use, if other than default
|
37
|
+
#
|
38
|
+
def initialize(app, level = ::Logger::INFO, logger = nil)
|
39
|
+
@app, @level = app, level
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
logger ||= ::Logger.new(env['rack.errors'])
|
42
|
+
logger.level = @level
|
43
|
+
@logger = logger
|
44
|
+
end
|
46
45
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
ensure
|
58
|
-
@logger.close
|
59
|
-
end
|
46
|
+
# Add a logger to the Rack environment and call the next middleware.
|
47
|
+
#
|
48
|
+
# === Parameters
|
49
|
+
# env(Hash):: the Rack environment
|
50
|
+
#
|
51
|
+
# === Return
|
52
|
+
# always returns whatever value is returned by the next layer of middleware
|
53
|
+
def call(env)
|
54
|
+
env['rack.logger'] = @logger
|
55
|
+
return @app.call(env)
|
60
56
|
end
|
61
57
|
end
|
62
58
|
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 Rack middleware and other enhancements.
|
26
|
+
#
|
27
|
+
module Rack
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Dir[File.expand_path('../rack/*.rb', __FILE__)].each do |filename|
|
33
|
+
require filename
|
34
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
module RightSupport
|
2
|
-
module
|
1
|
+
module RightSupport::Ruby
|
2
|
+
module ObjectExtensions
|
3
3
|
# Attempt to require one or more source files; if the require succeeds (or
|
4
4
|
# if the files have already been successfully required), yield to the block.
|
5
5
|
#
|
@@ -26,5 +26,5 @@ module RightSupport
|
|
26
26
|
end
|
27
27
|
|
28
28
|
class Object
|
29
|
-
include RightSupport::
|
29
|
+
include RightSupport::Ruby::ObjectExtensions
|
30
30
|
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 extensions to Ruby builtin classes.
|
26
|
+
#
|
27
|
+
module Ruby
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Dir[File.expand_path('../ruby/*.rb', __FILE__)].each do |filename|
|
33
|
+
require filename
|
34
|
+
end
|
@@ -1,176 +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
|
-
|
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
|
2
|
+
SystemLogger = RightSupport::Log::SystemLogger
|
3
|
+
end
|
@@ -1,72 +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
|
-
# 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
|
2
|
+
TagLogger = RightSupport::Log::TagLogger
|
72
3
|
end
|
data/lib/right_support.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
-
|
1
|
+
# Namespaces for RightSupport
|
2
|
+
require 'right_support/ruby'
|
3
|
+
require 'right_support/db'
|
4
|
+
require 'right_support/log'
|
5
|
+
require 'right_support/net'
|
6
|
+
require 'right_support/rack'
|
7
|
+
require 'right_support/validation'
|
8
|
+
|
9
|
+
# Deprecated stubs
|
10
|
+
require 'right_support/cassandra_model'
|
2
11
|
require 'right_support/filter_logger'
|
3
12
|
require 'right_support/system_logger'
|
4
13
|
require 'right_support/tag_logger'
|
5
|
-
require 'right_support/rack/custom_logger'
|
6
|
-
|
7
|
-
require 'right_support/validation'
|
8
|
-
|
9
|
-
require 'right_support/net'
|
data/right_support.gemspec
CHANGED
@@ -7,8 +7,8 @@ spec = Gem::Specification.new do |s|
|
|
7
7
|
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
8
8
|
|
9
9
|
s.name = 'right_support'
|
10
|
-
s.version = '0.9.
|
11
|
-
s.date = '2011-
|
10
|
+
s.version = '0.9.8'
|
11
|
+
s.date = '2011-08-13'
|
12
12
|
|
13
13
|
s.authors = ['Tony Spataro']
|
14
14
|
s.email = 'tony@rightscale.com'
|