thin 1.5.1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +11 -0
- data/ext/thin_parser/common.rl +8 -4
- data/ext/thin_parser/parser.c +531 -328
- data/ext/thin_parser/parser.rl +9 -9
- data/ext/thin_parser/thin.c +3 -4
- data/lib/thin/backends/base.rb +13 -3
- data/lib/thin/command.rb +2 -2
- data/lib/thin/connection.rb +19 -15
- data/lib/thin/controllers/cluster.rb +4 -4
- data/lib/thin/controllers/controller.rb +5 -4
- data/lib/thin/controllers/service.rb +16 -16
- data/lib/thin/daemonizing.rb +10 -12
- data/lib/thin/logging.rb +144 -33
- data/lib/thin/request.rb +7 -1
- data/lib/thin/runner.rb +23 -6
- data/lib/thin/server.rb +47 -33
- data/lib/thin/stats.rb +1 -1
- data/lib/thin/version.rb +3 -3
- metadata +17 -26
data/ext/thin_parser/parser.rl
CHANGED
@@ -109,7 +109,7 @@ size_t thin_http_parser_execute(http_parser *parser, const char *buffer, size_t
|
|
109
109
|
pe = buffer+len;
|
110
110
|
|
111
111
|
assert(*pe == '\0' && "pointer does not end on NUL");
|
112
|
-
assert(pe - p == len - off && "pointers aren't same distance");
|
112
|
+
assert(pe - p == (long)(len - off) && "pointers aren't same distance");
|
113
113
|
|
114
114
|
|
115
115
|
%% write exec;
|
@@ -132,6 +132,14 @@ size_t thin_http_parser_execute(http_parser *parser, const char *buffer, size_t
|
|
132
132
|
return(parser->nread);
|
133
133
|
}
|
134
134
|
|
135
|
+
int thin_http_parser_has_error(http_parser *parser) {
|
136
|
+
return parser->cs == http_parser_error;
|
137
|
+
}
|
138
|
+
|
139
|
+
int thin_http_parser_is_finished(http_parser *parser) {
|
140
|
+
return parser->cs == http_parser_first_final;
|
141
|
+
}
|
142
|
+
|
135
143
|
int thin_http_parser_finish(http_parser *parser)
|
136
144
|
{
|
137
145
|
int cs = parser->cs;
|
@@ -147,11 +155,3 @@ int thin_http_parser_finish(http_parser *parser)
|
|
147
155
|
return 0;
|
148
156
|
}
|
149
157
|
}
|
150
|
-
|
151
|
-
int thin_http_parser_has_error(http_parser *parser) {
|
152
|
-
return parser->cs == http_parser_error;
|
153
|
-
}
|
154
|
-
|
155
|
-
int thin_http_parser_is_finished(http_parser *parser) {
|
156
|
-
return parser->cs == http_parser_first_final;
|
157
|
-
}
|
data/ext/thin_parser/thin.c
CHANGED
@@ -71,7 +71,6 @@ DEF_MAX_LENGTH(REQUEST_PATH, 1024);
|
|
71
71
|
DEF_MAX_LENGTH(QUERY_STRING, (1024 * 10));
|
72
72
|
DEF_MAX_LENGTH(HEADER, (1024 * (80 + 32)));
|
73
73
|
|
74
|
-
|
75
74
|
static void http_field(void *data, const char *field, size_t flen, const char *value, size_t vlen)
|
76
75
|
{
|
77
76
|
char *ch, *end;
|
@@ -87,10 +86,10 @@ static void http_field(void *data, const char *field, size_t flen, const char *v
|
|
87
86
|
f = rb_str_buf_cat(f, field, flen);
|
88
87
|
|
89
88
|
for(ch = RSTRING_PTR(f) + RSTRING_LEN(global_http_prefix), end = RSTRING_PTR(f) + RSTRING_LEN(f); ch < end; ch++) {
|
90
|
-
if(*ch
|
89
|
+
if (*ch >= 'a' && *ch <= 'z') {
|
90
|
+
*ch &= ~0x20; // upcase
|
91
|
+
} else if (*ch == '-') {
|
91
92
|
*ch = '_';
|
92
|
-
} else {
|
93
|
-
*ch = toupper(*ch);
|
94
93
|
}
|
95
94
|
}
|
96
95
|
|
data/lib/thin/backends/base.rb
CHANGED
@@ -22,11 +22,18 @@ module Thin
|
|
22
22
|
|
23
23
|
# Maximum number of connections that can be persistent
|
24
24
|
attr_accessor :maximum_persistent_connections
|
25
|
-
|
25
|
+
|
26
|
+
#allows setting of the eventmachine threadpool size
|
27
|
+
attr_reader :threadpool_size
|
28
|
+
def threadpool_size=(size)
|
29
|
+
@threadpool_size = size
|
30
|
+
EventMachine.threadpool_size = size
|
31
|
+
end
|
32
|
+
|
26
33
|
# Allow using threads in the backend.
|
27
34
|
attr_writer :threaded
|
28
35
|
def threaded?; @threaded end
|
29
|
-
|
36
|
+
|
30
37
|
# Allow using SSL in the backend.
|
31
38
|
attr_writer :ssl, :ssl_options
|
32
39
|
def ssl?; @ssl end
|
@@ -46,6 +53,7 @@ module Thin
|
|
46
53
|
@no_epoll = false
|
47
54
|
@ssl = nil
|
48
55
|
@threaded = nil
|
56
|
+
@started_reactor = false
|
49
57
|
end
|
50
58
|
|
51
59
|
# Start the backend and connect it.
|
@@ -53,6 +61,7 @@ module Thin
|
|
53
61
|
@stopping = false
|
54
62
|
starter = proc do
|
55
63
|
connect
|
64
|
+
yield if block_given?
|
56
65
|
@running = true
|
57
66
|
end
|
58
67
|
|
@@ -60,6 +69,7 @@ module Thin
|
|
60
69
|
if EventMachine.reactor_running?
|
61
70
|
starter.call
|
62
71
|
else
|
72
|
+
@started_reactor = true
|
63
73
|
EventMachine.run(&starter)
|
64
74
|
end
|
65
75
|
end
|
@@ -81,7 +91,7 @@ module Thin
|
|
81
91
|
@running = false
|
82
92
|
@stopping = false
|
83
93
|
|
84
|
-
EventMachine.stop if EventMachine.reactor_running?
|
94
|
+
EventMachine.stop if @started_reactor && EventMachine.reactor_running?
|
85
95
|
@connections.each_value { |connection| connection.close_connection }
|
86
96
|
close
|
87
97
|
end
|
data/lib/thin/command.rb
CHANGED
@@ -26,8 +26,8 @@ module Thin
|
|
26
26
|
trace shell_cmd
|
27
27
|
trap('INT') {} # Ignore INT signal to pass CTRL+C to subprocess
|
28
28
|
Open3.popen3(shell_cmd) do |stdin, stdout, stderr|
|
29
|
-
|
30
|
-
|
29
|
+
log_info stdout.gets until stdout.eof?
|
30
|
+
log_info stderr.gets until stderr.eof?
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
data/lib/thin/connection.rb
CHANGED
@@ -10,6 +10,8 @@ module Thin
|
|
10
10
|
# This is a template async response. N.B. Can't use string for body on 1.9
|
11
11
|
AsyncResponse = [-1, {}, []].freeze
|
12
12
|
|
13
|
+
EMPTY_BODY = [].freeze
|
14
|
+
|
13
15
|
# Rack application (adapter) served by this connection.
|
14
16
|
attr_accessor :app
|
15
17
|
|
@@ -35,11 +37,10 @@ module Thin
|
|
35
37
|
# Called when data is received from the client.
|
36
38
|
def receive_data(data)
|
37
39
|
@idle = false
|
38
|
-
trace
|
40
|
+
trace data
|
39
41
|
process if @request.parse(data)
|
40
42
|
rescue InvalidRequest => e
|
41
|
-
|
42
|
-
log_error e
|
43
|
+
log_error("Invalid request", e)
|
43
44
|
post_process Response::BAD_REQUEST
|
44
45
|
end
|
45
46
|
|
@@ -81,8 +82,8 @@ module Thin
|
|
81
82
|
response = @app.call(@request.env)
|
82
83
|
end
|
83
84
|
response
|
84
|
-
rescue Exception
|
85
|
-
|
85
|
+
rescue Exception => e
|
86
|
+
unexpected_error(e)
|
86
87
|
# Pass through error response
|
87
88
|
can_persist? && @request.persistent? ? Response::PERSISTENT_ERROR : Response::ERROR
|
88
89
|
end
|
@@ -96,19 +97,23 @@ module Thin
|
|
96
97
|
|
97
98
|
@response.status, @response.headers, @response.body = *result
|
98
99
|
|
99
|
-
|
100
|
+
log_error("Rack application returned nil body. " \
|
101
|
+
"Probably you wanted it to be an empty string?") if @response.body.nil?
|
102
|
+
|
103
|
+
# HEAD requests should not return a body.
|
104
|
+
@response.body = EMPTY_BODY if @request.head?
|
100
105
|
|
101
106
|
# Make the response persistent if requested by the client
|
102
107
|
@response.persistent! if @request.persistent?
|
103
108
|
|
104
109
|
# Send the response
|
105
110
|
@response.each do |chunk|
|
106
|
-
trace
|
111
|
+
trace chunk
|
107
112
|
send_data chunk
|
108
113
|
end
|
109
114
|
|
110
|
-
rescue Exception
|
111
|
-
|
115
|
+
rescue Exception => e
|
116
|
+
unexpected_error(e)
|
112
117
|
# Close connection since we can't handle response gracefully
|
113
118
|
close_connection
|
114
119
|
ensure
|
@@ -122,10 +127,9 @@ module Thin
|
|
122
127
|
end
|
123
128
|
end
|
124
129
|
|
125
|
-
# Logs
|
126
|
-
def
|
127
|
-
|
128
|
-
log_error
|
130
|
+
# Logs information about an unexpected exceptional condition
|
131
|
+
def unexpected_error(e)
|
132
|
+
log_error("Unexpected error while processing request", e)
|
129
133
|
end
|
130
134
|
|
131
135
|
def close_request_response
|
@@ -192,8 +196,8 @@ module Thin
|
|
192
196
|
# IP Address of the remote client.
|
193
197
|
def remote_address
|
194
198
|
socket_address
|
195
|
-
rescue Exception
|
196
|
-
log_error
|
199
|
+
rescue Exception => e
|
200
|
+
log_error('Could not infer remote address', e)
|
197
201
|
nil
|
198
202
|
end
|
199
203
|
|
@@ -45,7 +45,7 @@ module Thin
|
|
45
45
|
|
46
46
|
# Start a single server
|
47
47
|
def start_server(number)
|
48
|
-
|
48
|
+
log_info "Starting server on #{server_id(number)} ... "
|
49
49
|
|
50
50
|
run :start, number
|
51
51
|
end
|
@@ -57,7 +57,7 @@ module Thin
|
|
57
57
|
|
58
58
|
# Stop a single server
|
59
59
|
def stop_server(number)
|
60
|
-
|
60
|
+
log_info "Stopping server on #{server_id(number)} ... "
|
61
61
|
|
62
62
|
run :stop, number
|
63
63
|
end
|
@@ -91,7 +91,7 @@ module Thin
|
|
91
91
|
|
92
92
|
# Make sure the server is running before moving on to the next one.
|
93
93
|
def wait_until_server_started(number)
|
94
|
-
|
94
|
+
log_info "Waiting for server to start ..."
|
95
95
|
STDOUT.flush # Need this to make sure user got the message
|
96
96
|
|
97
97
|
tries = 0
|
@@ -175,4 +175,4 @@ module Thin
|
|
175
175
|
end
|
176
176
|
end
|
177
177
|
end
|
178
|
-
end
|
178
|
+
end
|
@@ -37,7 +37,7 @@ module Thin
|
|
37
37
|
def start
|
38
38
|
# Constantize backend class
|
39
39
|
@options[:backend] = eval(@options[:backend], TOPLEVEL_BINDING) if @options[:backend]
|
40
|
-
|
40
|
+
|
41
41
|
server = Server.new(@options[:socket] || @options[:address], # Server detects kind of socket
|
42
42
|
@options[:port], # Port ignored on UNIX socket
|
43
43
|
@options)
|
@@ -50,6 +50,7 @@ module Thin
|
|
50
50
|
server.maximum_persistent_connections = @options[:max_persistent_conns]
|
51
51
|
server.threaded = @options[:threaded]
|
52
52
|
server.no_epoll = @options[:no_epoll] if server.backend.respond_to?(:no_epoll=)
|
53
|
+
server.threadpool_size = @options[:threadpool_size] if server.threaded?
|
53
54
|
|
54
55
|
# ssl support
|
55
56
|
if @options[:ssl]
|
@@ -113,7 +114,7 @@ module Thin
|
|
113
114
|
@options.keys.each { |o| @options[o.to_s] = @options.delete(o) }
|
114
115
|
|
115
116
|
File.open(config_file, 'w') { |f| f << @options.to_yaml }
|
116
|
-
|
117
|
+
log_info "Wrote configuration to #{config_file}"
|
117
118
|
end
|
118
119
|
|
119
120
|
protected
|
@@ -165,7 +166,7 @@ module Thin
|
|
165
166
|
private
|
166
167
|
def load_adapter
|
167
168
|
adapter = @options[:adapter] || Rack::Adapter.guess(@options[:chdir])
|
168
|
-
|
169
|
+
log_info "Using #{adapter} adapter"
|
169
170
|
Rack::Adapter.for(adapter, @options)
|
170
171
|
rescue Rack::AdapterNotFound => e
|
171
172
|
raise InvalidOption, e.message
|
@@ -185,4 +186,4 @@ module Thin
|
|
185
186
|
end
|
186
187
|
end
|
187
188
|
end
|
188
|
-
end
|
189
|
+
end
|
@@ -33,11 +33,11 @@ module Thin
|
|
33
33
|
|
34
34
|
def install(config_files_path=DEFAULT_CONFIG_PATH)
|
35
35
|
if File.exist?(INITD_PATH)
|
36
|
-
|
36
|
+
log_info "Thin service already installed at #{INITD_PATH}"
|
37
37
|
else
|
38
|
-
|
38
|
+
log_info "Installing thin service at #{INITD_PATH} ..."
|
39
39
|
sh "mkdir -p #{File.dirname(INITD_PATH)}"
|
40
|
-
|
40
|
+
log_info "writing #{INITD_PATH}"
|
41
41
|
File.open(INITD_PATH, 'w') do |f|
|
42
42
|
f << ERB.new(File.read(TEMPLATE)).result(binding)
|
43
43
|
end
|
@@ -46,30 +46,30 @@ module Thin
|
|
46
46
|
|
47
47
|
sh "mkdir -p #{config_files_path}"
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
49
|
+
log_info ''
|
50
|
+
log_info "To configure thin to start at system boot:"
|
51
|
+
log_info "on RedHat like systems:"
|
52
|
+
log_info " sudo /sbin/chkconfig --level 345 #{NAME} on"
|
53
|
+
log_info "on Debian-like systems (Ubuntu):"
|
54
|
+
log_info " sudo /usr/sbin/update-rc.d -f #{NAME} defaults"
|
55
|
+
log_info "on Gentoo:"
|
56
|
+
log_info " sudo rc-update add #{NAME} default"
|
57
|
+
log_info ''
|
58
|
+
log_info "Then put your config files in #{config_files_path}"
|
59
59
|
end
|
60
60
|
|
61
61
|
private
|
62
62
|
def run(command)
|
63
63
|
Dir[config_path + '/*'].each do |config|
|
64
|
-
|
64
|
+
log_info "[#{command}] #{config} ..."
|
65
65
|
Command.run(command, :config => config, :daemonize => true)
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
69
|
def sh(cmd)
|
70
|
-
|
70
|
+
log_info cmd
|
71
71
|
system(cmd)
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
75
|
-
end
|
75
|
+
end
|
data/lib/thin/daemonizing.rb
CHANGED
@@ -55,10 +55,8 @@ module Thin
|
|
55
55
|
|
56
56
|
write_pid_file
|
57
57
|
|
58
|
-
self.after_daemonize if self.respond_to? :after_daemonize
|
59
|
-
|
60
58
|
at_exit do
|
61
|
-
|
59
|
+
log_info "Exiting!"
|
62
60
|
remove_pid_file
|
63
61
|
end
|
64
62
|
end
|
@@ -66,7 +64,7 @@ module Thin
|
|
66
64
|
# Change privileges of the process
|
67
65
|
# to the specified user and group.
|
68
66
|
def change_privilege(user, group=user)
|
69
|
-
|
67
|
+
log_info "Changing process privilege to #{user}:#{group}"
|
70
68
|
|
71
69
|
uid, gid = Process.euid, Process.egid
|
72
70
|
target_uid = Etc.getpwnam(user).uid
|
@@ -82,7 +80,7 @@ module Thin
|
|
82
80
|
Process::UID.change_privilege(target_uid)
|
83
81
|
end
|
84
82
|
rescue Errno::EPERM => e
|
85
|
-
|
83
|
+
log_info "Couldn't change user and group to #{user}:#{group}: #{e}"
|
86
84
|
end
|
87
85
|
|
88
86
|
# Register a proc to be called to restart the server.
|
@@ -93,7 +91,7 @@ module Thin
|
|
93
91
|
# Restart the server.
|
94
92
|
def restart
|
95
93
|
if @on_restart
|
96
|
-
|
94
|
+
log_info 'Restarting ...'
|
97
95
|
stop
|
98
96
|
remove_pid_file
|
99
97
|
@on_restart.call
|
@@ -122,7 +120,7 @@ module Thin
|
|
122
120
|
# Send a +signal+ to the process which PID is stored in +pid_file+.
|
123
121
|
def send_signal(signal, pid_file, timeout=60)
|
124
122
|
if pid = read_pid_file(pid_file)
|
125
|
-
Logging.
|
123
|
+
Logging.log_info "Sending #{signal} signal to process #{pid} ... "
|
126
124
|
Process.kill(signal, pid)
|
127
125
|
Timeout.timeout(timeout) do
|
128
126
|
sleep 0.1 while Process.running?(pid)
|
@@ -131,17 +129,17 @@ module Thin
|
|
131
129
|
raise PidFileNotFound, "Can't stop process, no PID found in #{pid_file}"
|
132
130
|
end
|
133
131
|
rescue Timeout::Error
|
134
|
-
Logging.
|
132
|
+
Logging.log_info "Timeout!"
|
135
133
|
force_kill(pid, pid_file)
|
136
134
|
rescue Interrupt
|
137
135
|
force_kill(pid, pid_file)
|
138
136
|
rescue Errno::ESRCH # No such process
|
139
|
-
Logging.
|
137
|
+
Logging.log_info "process not found!"
|
140
138
|
force_kill(pid, pid_file)
|
141
139
|
end
|
142
140
|
|
143
141
|
def force_kill(pid, pid_file)
|
144
|
-
Logging.
|
142
|
+
Logging.log_info "Sending KILL signal to process #{pid} ... "
|
145
143
|
Process.kill("KILL", pid)
|
146
144
|
File.delete(pid_file) if File.exist?(pid_file)
|
147
145
|
end
|
@@ -161,7 +159,7 @@ module Thin
|
|
161
159
|
end
|
162
160
|
|
163
161
|
def write_pid_file
|
164
|
-
|
162
|
+
log_info "Writing PID to #{@pid_file}"
|
165
163
|
open(@pid_file,"w") { |f| f.write(Process.pid) }
|
166
164
|
File.chmod(0644, @pid_file)
|
167
165
|
end
|
@@ -173,7 +171,7 @@ module Thin
|
|
173
171
|
raise PidFileExist, "#{@pid_file} already exists, seems like it's already running (process ID: #{pid}). " +
|
174
172
|
"Stop the process or delete #{@pid_file}."
|
175
173
|
else
|
176
|
-
|
174
|
+
log_info "Deleting stale PID file #{@pid_file}"
|
177
175
|
remove_pid_file
|
178
176
|
end
|
179
177
|
end
|
data/lib/thin/logging.rb
CHANGED
@@ -1,54 +1,165 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
1
3
|
module Thin
|
2
4
|
# To be included in classes to allow some basic logging
|
3
5
|
# that can be silenced (<tt>Logging.silent=</tt>) or made
|
4
6
|
# more verbose.
|
5
|
-
# <tt>Logging.
|
6
|
-
#
|
7
|
-
# <tt>Logging.
|
8
|
-
#
|
7
|
+
# <tt>Logging.trace=</tt>: log all raw request and response and
|
8
|
+
# messages logged with +trace+.
|
9
|
+
# <tt>Logging.silent=</tt>: silence all log all log messages
|
10
|
+
# altogether.
|
9
11
|
module Logging
|
12
|
+
# Simple formatter which only displays the message.
|
13
|
+
# Taken from ActiveSupport
|
14
|
+
class SimpleFormatter < Logger::Formatter
|
15
|
+
def call(severity, timestamp, progname, msg)
|
16
|
+
"#{String === msg ? msg : msg.inspect}\n"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
10
20
|
class << self
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
21
|
+
|
22
|
+
attr_reader :logger
|
23
|
+
attr_reader :trace_logger
|
24
|
+
|
25
|
+
def trace=(enabled)
|
26
|
+
if enabled
|
27
|
+
@trace_logger ||= Logger.new(STDOUT)
|
28
|
+
else
|
29
|
+
@trace_logger = nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def trace?
|
34
|
+
!@trace_logger.nil?
|
35
|
+
end
|
36
|
+
|
37
|
+
def silent=(shh)
|
38
|
+
if shh
|
39
|
+
@logger = nil
|
40
|
+
else
|
41
|
+
@logger ||= Logger.new(STDOUT)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def silent?
|
46
|
+
!@logger.nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
def level
|
50
|
+
@logger ? @logger.level : nil # or 'silent'
|
51
|
+
end
|
52
|
+
|
53
|
+
def level=(value)
|
54
|
+
# If logging has been silenced, then re-enable logging
|
55
|
+
@logger = Logger.new(STDOUT) if @logger.nil?
|
56
|
+
@logger.level = value
|
57
|
+
end
|
58
|
+
|
59
|
+
# Allow user to specify a custom logger to use.
|
60
|
+
# This object must respond to:
|
61
|
+
# +level+, +level=+ and +debug+, +info+, +warn+, +error+, +fatal+
|
62
|
+
def logger=(custom_logger)
|
63
|
+
[ :level ,
|
64
|
+
:level= ,
|
65
|
+
:debug ,
|
66
|
+
:info ,
|
67
|
+
:warn ,
|
68
|
+
:error ,
|
69
|
+
:fatal ,
|
70
|
+
:unknown ,
|
71
|
+
].each do |method|
|
72
|
+
if not custom_logger.respond_to?(method)
|
73
|
+
raise ArgumentError, "logger must respond to #{method}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
@logger = custom_logger
|
78
|
+
end
|
79
|
+
|
80
|
+
def trace_logger=(custom_tracer)
|
81
|
+
[ :level ,
|
82
|
+
:level= ,
|
83
|
+
:debug ,
|
84
|
+
:info ,
|
85
|
+
:warn ,
|
86
|
+
:error ,
|
87
|
+
:fatal ,
|
88
|
+
:unknown ,
|
89
|
+
].each do |method|
|
90
|
+
if not custom_tracer.respond_to?(method)
|
91
|
+
raise ArgumentError, "trace logger must respond to #{method}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
@trace_logger = custom_tracer
|
96
|
+
end
|
97
|
+
|
98
|
+
def log_msg(msg, level=Logger::INFO)
|
99
|
+
return unless @logger
|
100
|
+
@logger.add(level, msg)
|
101
|
+
end
|
102
|
+
|
103
|
+
def trace_msg(msg)
|
104
|
+
return unless @trace_logger
|
105
|
+
@trace_logger.info(msg)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Provided for backwards compatibility.
|
109
|
+
# Callers should be using the +level+ (on the +Logging+ module
|
110
|
+
# or on the instance) to figure out what the log level is.
|
111
|
+
def debug?
|
112
|
+
self.level == Logger::DEBUG
|
113
|
+
end
|
114
|
+
def debug=(val)
|
115
|
+
self.level = (val ? Logger::DEBUG : Logger::INFO)
|
116
|
+
end
|
117
|
+
|
118
|
+
end # module methods
|
119
|
+
|
19
120
|
def silent
|
20
121
|
Logging.silent?
|
21
122
|
end
|
123
|
+
|
22
124
|
def silent=(value)
|
23
125
|
Logging.silent = value
|
24
126
|
end
|
25
|
-
|
26
|
-
# Log a message
|
27
|
-
def log(msg)
|
28
|
-
puts msg unless Logging.silent?
|
29
|
-
end
|
30
|
-
module_function :log
|
31
|
-
public :log
|
32
|
-
|
33
|
-
# Log a message to the console if tracing is activated
|
127
|
+
|
128
|
+
# Log a message if tracing is activated
|
34
129
|
def trace(msg=nil)
|
35
|
-
|
130
|
+
Logging.trace_msg(msg) if msg
|
36
131
|
end
|
37
132
|
module_function :trace
|
38
133
|
public :trace
|
39
|
-
|
40
|
-
# Log a message
|
41
|
-
def
|
42
|
-
|
43
|
-
end
|
44
|
-
module_function :
|
45
|
-
public :
|
46
|
-
|
47
|
-
# Log
|
48
|
-
def
|
49
|
-
|
134
|
+
|
135
|
+
# Log a message at DEBUG level
|
136
|
+
def log_debug(msg=nil)
|
137
|
+
Logging.log_msg(msg || yield, Logger::DEBUG)
|
138
|
+
end
|
139
|
+
module_function :log_debug
|
140
|
+
public :log_debug
|
141
|
+
|
142
|
+
# Log a message at INFO level
|
143
|
+
def log_info(msg)
|
144
|
+
Logging.log_msg(msg || yield, Logger::INFO)
|
145
|
+
end
|
146
|
+
module_function :log_info
|
147
|
+
public :log_info
|
148
|
+
|
149
|
+
# Log a message at ERROR level (and maybe a backtrace)
|
150
|
+
def log_error(msg, e=nil)
|
151
|
+
log_msg = msg + ": #{e}\n\t" + e.backtrace.join("\n\t") + "\n" if e
|
152
|
+
Logging.log_msg(log_msg, Logger::ERROR)
|
50
153
|
end
|
51
154
|
module_function :log_error
|
52
155
|
public :log_error
|
156
|
+
|
157
|
+
# For backwards compatibility
|
158
|
+
def log msg
|
159
|
+
STDERR.puts('#log has been deprecated, please use the ' \
|
160
|
+
'log_level function instead (e.g. - log_info).')
|
161
|
+
log_info(msg)
|
162
|
+
end
|
163
|
+
|
53
164
|
end
|
54
165
|
end
|