unicorn-cuba-base 1.1.2 → 1.2.0
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/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/VERSION +1 -1
- data/lib/unicorn-cuba-base/default_error_reporter.rb +7 -1
- data/lib/unicorn-cuba-base/rack/common_logger_xid.rb +15 -0
- data/lib/unicorn-cuba-base/rack/error_handling.rb +1 -3
- data/lib/unicorn-cuba-base/rack/xid_logging.rb +24 -0
- data/lib/unicorn-cuba-base/root_logger.rb +144 -31
- data/lib/unicorn-cuba-base/stats_reporter.rb +2 -2
- data/lib/unicorn-cuba-base/uri_ext.rb +20 -0
- data/lib/unicorn-cuba-base.rb +44 -23
- data/spec/root_logger_spec.rb +101 -7
- data/unicorn-cuba-base.gemspec +9 -3
- metadata +23 -4
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.2.0
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
require 'pp'
|
2
|
+
|
3
|
+
class DefaultErrorReporter < Controller
|
2
4
|
self.define do
|
3
5
|
on error Rack::UnhandledRequest::UnhandledRequestError do |error|
|
4
6
|
write_error 404, error
|
@@ -9,6 +11,10 @@ class DefaultErrorReporter < Controler
|
|
9
11
|
raise error
|
10
12
|
end
|
11
13
|
|
14
|
+
on error URI::InvalidURIError do |error|
|
15
|
+
write_error 400, error
|
16
|
+
end
|
17
|
+
|
12
18
|
on error StandardError do |error|
|
13
19
|
log.error "unhandled error while processing request: #{env['REQUEST_METHOD']} #{env['SCRIPT_NAME']}[#{env["PATH_INFO"]}]", error
|
14
20
|
log.debug {
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Rack
|
2
|
+
class CommonLoggerXID < Rack::CommonLogger
|
3
|
+
def log(env, *args)
|
4
|
+
# this is called after body was sent so it won't be in scope of XIDLogging - setting xid again
|
5
|
+
xid = env['xid'] && env['xid'].first.last
|
6
|
+
if xid
|
7
|
+
@logger.with_meta_context(xid: xid) do
|
8
|
+
super(env, *args)
|
9
|
+
end
|
10
|
+
else
|
11
|
+
super(env, *args)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Rack
|
2
|
+
class XIDLogging
|
3
|
+
def initialize(app, root_logger, header_name = 'XID', &block)
|
4
|
+
@root_logger = root_logger
|
5
|
+
@header_name = header_name
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
begin
|
11
|
+
xid = env["HTTP_#{@header_name.upcase.tr('-', '_')}"]
|
12
|
+
if xid
|
13
|
+
env['xid'] = {@header_name => xid}
|
14
|
+
@root_logger.with_meta_context(xid: xid) do
|
15
|
+
return @app.call(env)
|
16
|
+
end
|
17
|
+
else
|
18
|
+
return @app.call(env)
|
19
|
+
end
|
20
|
+
ensure
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -6,10 +6,7 @@ class RootLogger < Logger
|
|
6
6
|
|
7
7
|
def initialize(root_logger, class_obj)
|
8
8
|
@root_logger = root_logger
|
9
|
-
@
|
10
|
-
@root_logger.formatter = proc do |severity, datetime, progname, msg|
|
11
|
-
"[#{datetime.utc.strftime "%Y-%m-%d %H:%M:%S.%6N %Z"}] [#{$$} #{progname}] #{severity}: #{msg}\n"
|
12
|
-
end
|
9
|
+
@class_name = class_obj.name
|
13
10
|
end
|
14
11
|
|
15
12
|
def respond_to?(method)
|
@@ -18,22 +15,24 @@ class RootLogger < Logger
|
|
18
15
|
|
19
16
|
def method_missing(name, *args, &block)
|
20
17
|
if @@levels.include? name
|
21
|
-
|
22
|
-
|
18
|
+
root_logger = @root_logger.with_meta('className' => @class_name)
|
19
|
+
|
20
|
+
if block
|
21
|
+
root_logger.send(name, &block)
|
23
22
|
else
|
24
|
-
args.
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
23
|
+
message = args.first
|
24
|
+
|
25
|
+
if args.last.is_a? Exception
|
26
|
+
error = args.last
|
27
|
+
root_logger = root_logger.with_meta('exceptionClass' => error.class.name)
|
28
|
+
message = "#{message}: #{error.class.name}: #{error.message}\n#{error.backtrace.join("\n")}"
|
29
|
+
end
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
# log with class name
|
32
|
+
root_logger.send(name, message.chomp, &block)
|
33
|
+
end
|
36
34
|
else
|
35
|
+
# forward to root logger
|
37
36
|
@root_logger.send(name, *args, &block)
|
38
37
|
end
|
39
38
|
end
|
@@ -45,6 +44,50 @@ class RootLogger < Logger
|
|
45
44
|
end
|
46
45
|
end
|
47
46
|
|
47
|
+
class MetaData < Hash
|
48
|
+
def initialize(parent = nil)
|
49
|
+
@parent = parent
|
50
|
+
end
|
51
|
+
|
52
|
+
attr_accessor :parent
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
chain = []
|
56
|
+
parent = self
|
57
|
+
while parent
|
58
|
+
chain << parent
|
59
|
+
parent = parent.parent
|
60
|
+
end
|
61
|
+
|
62
|
+
hash = {}
|
63
|
+
|
64
|
+
chain.reverse.each do |child|
|
65
|
+
hash.merge! child
|
66
|
+
end
|
67
|
+
|
68
|
+
"[meta #{hash.map{|k, v| "#{k}=\"#{v.to_s.tr('"', "'")}\""}.join(' ')}]"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialize(logdev = STDERR, &formatter)
|
73
|
+
super(logdev)
|
74
|
+
|
75
|
+
@ext_formatter = proc do |severity, datetime, progname, meta, msg|
|
76
|
+
if formatter
|
77
|
+
formatter.call(severity, datetime, progname, meta, msg)
|
78
|
+
else
|
79
|
+
"#{datetime.utc.strftime "%Y-%m-%d %H:%M:%S.%6N %Z"} #{meta.to_s} #{severity}: #{msg}\n"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
@meta = MetaData.new
|
84
|
+
@meta['pid'] = $$
|
85
|
+
|
86
|
+
self.formatter = proc do |severity, datetime, progname, msg|
|
87
|
+
@ext_formatter.call(severity, datetime, progname, @meta, msg)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
48
91
|
def logger_for(class_obj)
|
49
92
|
ClassLogger.new(self, class_obj)
|
50
93
|
end
|
@@ -53,11 +96,87 @@ class RootLogger < Logger
|
|
53
96
|
self
|
54
97
|
end
|
55
98
|
|
99
|
+
attr_accessor :meta
|
100
|
+
|
101
|
+
def with_meta(hash)
|
102
|
+
n = self.dup
|
103
|
+
n.meta = MetaData.new(@meta)
|
104
|
+
n.meta.merge! hash
|
105
|
+
|
106
|
+
# capture new meta hash with this new formatter proc - needed since old formatter proc will point to old object
|
107
|
+
n.formatter = proc do |severity, datetime, progname, msg|
|
108
|
+
@ext_formatter.call(severity, datetime, progname, n.meta, msg)
|
109
|
+
end
|
110
|
+
n
|
111
|
+
end
|
112
|
+
|
113
|
+
def with_meta_context(hash)
|
114
|
+
old_meta = @meta
|
115
|
+
new_meta = MetaData.new(old_meta)
|
116
|
+
new_meta.merge! hash
|
117
|
+
|
118
|
+
begin
|
119
|
+
@meta = new_meta
|
120
|
+
yield
|
121
|
+
ensure
|
122
|
+
@meta = old_meta
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
56
126
|
def inspect
|
57
127
|
"#<RootLogger #{"0x%X" % object_id}>"
|
58
128
|
end
|
59
129
|
end
|
60
130
|
|
131
|
+
class SyslogLogDev
|
132
|
+
def initialize(program_name, facility = 'daemon', log_to_stderr = false)
|
133
|
+
require 'syslog'
|
134
|
+
|
135
|
+
facility = "LOG_#{facility.upcase}".to_sym
|
136
|
+
Syslog.constants.include? facility or fail "No such syslog facility: #{facility}"
|
137
|
+
facility = Syslog.const_get facility
|
138
|
+
|
139
|
+
@log_level_mapping = Hash[%w{DEBUG INFO WARN ERROR FATAL}.zip(
|
140
|
+
[Syslog::LOG_DEBUG, Syslog::LOG_INFO, Syslog::LOG_WARNING, Syslog::LOG_ERR, Syslog::LOG_CRIT]
|
141
|
+
)]
|
142
|
+
@log_level_mapping.default = Syslog::LOG_NOTICE
|
143
|
+
|
144
|
+
flags = Syslog::LOG_PID | Syslog::LOG_NDELAY
|
145
|
+
|
146
|
+
if log_to_stderr
|
147
|
+
STDERR.sync = true
|
148
|
+
flags |= Syslog::LOG_PERROR
|
149
|
+
end
|
150
|
+
|
151
|
+
@syslog = Syslog.open(program_name, flags, facility)
|
152
|
+
end
|
153
|
+
|
154
|
+
def write(msg)
|
155
|
+
log_level, msg = *msg.match(/([^ ]+) (.*)/m).captures
|
156
|
+
@syslog.log(@log_level_mapping[log_level], "%s", msg.chomp)
|
157
|
+
end
|
158
|
+
|
159
|
+
def close
|
160
|
+
@syslog.close
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
class RootSyslogLogger < RootLogger
|
165
|
+
def initialize(program_name, facility = 'daemon', log_to_stderr = false)
|
166
|
+
super(SyslogLogDev.new(program_name, facility, log_to_stderr)) do |severity, datetime, progname, meta, msg|
|
167
|
+
# provide severity to SyslogLogDev
|
168
|
+
"#{severity} #{meta} #{msg}\n"
|
169
|
+
end
|
170
|
+
|
171
|
+
@meta.delete 'pid' # pid is already within syslog message header
|
172
|
+
end
|
173
|
+
|
174
|
+
# used when obj is used as log device (access logs)
|
175
|
+
def write(msg)
|
176
|
+
info(msg)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
61
180
|
module ClassLogging
|
62
181
|
module ClassMethods
|
63
182
|
def init_logger
|
@@ -69,22 +188,16 @@ module ClassLogging
|
|
69
188
|
end
|
70
189
|
|
71
190
|
def log
|
72
|
-
unless @@logger
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
else
|
79
|
-
new_root_logger = true
|
80
|
-
Logger.new(STDERR)
|
191
|
+
unless @@logger.include? self
|
192
|
+
root_logger = if an = ancestors.find{|an| an != self and an.respond_to? :log and an.log.respond_to? :root_logger}
|
193
|
+
an.log.root_logger
|
194
|
+
else
|
195
|
+
RootLogger.new.tap do |logger|
|
196
|
+
logger.warn 'no root logger found; using default logger'
|
81
197
|
end
|
198
|
+
end
|
82
199
|
|
83
|
-
|
84
|
-
|
85
|
-
logger = RootLogger::ClassLogger.new(root_logger, self)
|
86
|
-
logger.warn "new default logger crated" if new_root_logger
|
87
|
-
@@logger[self] = logger
|
200
|
+
@@logger[self] = RootLogger::ClassLogger.new(root_logger, self)
|
88
201
|
end
|
89
202
|
@@logger[self]
|
90
203
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module URI
|
4
|
+
class << self
|
5
|
+
alias_method :pct_decode, :decode
|
6
|
+
end
|
7
|
+
|
8
|
+
# From http://en.wikipedia.org/wiki/Percent-encoding:
|
9
|
+
# The generic URI syntax mandates that new URI schemes that provide for the representation of character data in a URI must, in effect, represent characters from the unreserved set without translation, and should convert all other characters to bytes according to UTF-8, and then percent-encode those values.
|
10
|
+
def self.utf_decode(str)
|
11
|
+
pct_decode(str).force_encoding('UTF-8').tap do |u|
|
12
|
+
raise URI::InvalidURIError, "invalid UTF-8 encoding in URI: #{u.inspect}" if not u.valid_encoding?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Use it by default
|
17
|
+
def self.decode(str)
|
18
|
+
self.utf_decode(str)
|
19
|
+
end
|
20
|
+
end
|
data/lib/unicorn-cuba-base.rb
CHANGED
@@ -6,6 +6,7 @@ require 'facter'
|
|
6
6
|
require 'pathname'
|
7
7
|
require 'ip'
|
8
8
|
|
9
|
+
require_relative 'unicorn-cuba-base/uri_ext'
|
9
10
|
require_relative 'unicorn-cuba-base/stats'
|
10
11
|
require_relative 'unicorn-cuba-base/root_logger'
|
11
12
|
require_relative 'unicorn-cuba-base/plugin/error_matcher'
|
@@ -15,8 +16,10 @@ require_relative 'unicorn-cuba-base/plugin/memory_limit'
|
|
15
16
|
require_relative 'unicorn-cuba-base/rack/error_handling'
|
16
17
|
require_relative 'unicorn-cuba-base/rack/unhandled_request'
|
17
18
|
require_relative 'unicorn-cuba-base/rack/memory_limit'
|
19
|
+
require_relative 'unicorn-cuba-base/rack/xid_logging'
|
20
|
+
require_relative 'unicorn-cuba-base/rack/common_logger_xid'
|
18
21
|
|
19
|
-
class
|
22
|
+
class Controller < Cuba
|
20
23
|
include ClassLogging
|
21
24
|
end
|
22
25
|
|
@@ -46,12 +49,19 @@ class Application
|
|
46
49
|
@cli = setup_cli(program_name, defaults, @cli_setup) or fail 'no cli defined'
|
47
50
|
@settings = @settings_setup ? setup_settings(@settings_setup) : @cli.parse!
|
48
51
|
|
49
|
-
root_logger =
|
52
|
+
root_logger = if @settings.syslog_facility
|
53
|
+
# open /dev/null as log file if we are using syslog and we are not in foreground
|
54
|
+
@settings.log_file = Pathname.new '/dev/null' unless @settings.foreground
|
55
|
+
RootSyslogLogger.new(program_name, @settings.syslog_facility, @settings.foreground)
|
56
|
+
else
|
57
|
+
RootLogger.new
|
58
|
+
end
|
59
|
+
|
50
60
|
root_logger.level = RootLogger::WARN
|
51
61
|
root_logger.level = RootLogger::INFO if @settings.verbose
|
52
62
|
root_logger.level = RootLogger::DEBUG if @settings.debug
|
53
|
-
|
54
|
-
MemoryLimit.logger =
|
63
|
+
Controller.logger = root_logger
|
64
|
+
MemoryLimit.logger = Controller.logger_for(MemoryLimit)
|
55
65
|
|
56
66
|
unicorn_settings = {}
|
57
67
|
unicorn_settings[:logger] = root_logger.logger_for(Unicorn::HttpServer)
|
@@ -67,7 +77,7 @@ class Application
|
|
67
77
|
unicorn_settings[:stderr_path] = @settings.log_file.to_s
|
68
78
|
unicorn_settings[:stdout_path] = @settings.log_file.to_s
|
69
79
|
|
70
|
-
Unicorn::Launcher.daemonize!(unicorn_settings)
|
80
|
+
Unicorn::Launcher.daemonize!(unicorn_settings)
|
71
81
|
|
72
82
|
# capture startup messages
|
73
83
|
@settings.log_file.open('ab') do |log|
|
@@ -77,25 +87,30 @@ class Application
|
|
77
87
|
end
|
78
88
|
end
|
79
89
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
@main_setup or fail 'no main
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
90
|
+
Controller.settings[:listeners] = @settings.listener
|
91
|
+
#Controller.settings[:access_log_file] = @settings.access_log_file
|
92
|
+
|
93
|
+
Controller.plugin Plugin::ErrorMatcher
|
94
|
+
Controller.plugin Plugin::Logging
|
95
|
+
Controller.plugin Plugin::ResponseHelpers
|
96
|
+
Controller.plugin Plugin::MemoryLimit
|
97
|
+
|
98
|
+
@main_setup or fail 'no main controller provided'
|
99
|
+
main_controller = setup_main(@main_setup) or fail 'no main controller class returned'
|
100
|
+
|
101
|
+
main_controller.use Rack::ErrorHandling
|
102
|
+
main_controller.use Rack::XIDLogging, root_logger, @settings.xid_header if @settings.xid_header
|
103
|
+
if @settings.syslog_facility
|
104
|
+
main_controller.use Rack::CommonLoggerXID, root_logger.with_meta(type: 'http-access')
|
105
|
+
else
|
106
|
+
access_log_file = @settings.access_log_file.open('a+')
|
107
|
+
access_log_file.sync = true
|
108
|
+
main_controller.use Rack::CommonLogger, access_log_file
|
109
|
+
end
|
110
|
+
main_controller.use Rack::MemoryLimit, @settings.limit_memory * 1024 ** 2
|
111
|
+
main_controller.use Rack::UnhandledRequest
|
97
112
|
|
98
|
-
Unicorn::HttpServer.new(
|
113
|
+
Unicorn::HttpServer.new(main_controller, unicorn_settings).start.join
|
99
114
|
end
|
100
115
|
|
101
116
|
private
|
@@ -108,11 +123,17 @@ class Application
|
|
108
123
|
cast: Pathname,
|
109
124
|
description: 'log file location',
|
110
125
|
default: "#{program_name}.log"
|
126
|
+
option :syslog_facility,
|
127
|
+
short: :s,
|
128
|
+
description: 'when set logs will be sent to syslog instead of log files; one of: auth, authpriv, cron, daemon, ftp, kern, lpr, mail, news, syslog, user, uucp, local0, local1, local2, local3, local4, local5, local6, local7'
|
111
129
|
option :access_log_file,
|
112
130
|
short: :a,
|
113
131
|
cast: Pathname,
|
114
132
|
description: 'NCSA access log file location',
|
115
133
|
default: "#{program_name}_access.log"
|
134
|
+
option :xid_header,
|
135
|
+
short: :x,
|
136
|
+
description: 'log value of named request header with request context'
|
116
137
|
option :pid_file,
|
117
138
|
short: :p,
|
118
139
|
cast: Pathname,
|
data/spec/root_logger_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require_relative 'spec_helper'
|
|
3
3
|
require 'unicorn-cuba-base/root_logger'
|
4
4
|
require 'stringio'
|
5
5
|
|
6
|
-
describe
|
6
|
+
describe RootLogger do
|
7
7
|
let! :log_out do
|
8
8
|
StringIO.new
|
9
9
|
end
|
@@ -44,15 +44,109 @@ describe do
|
|
44
44
|
subject.logger_for(String).info 'hello world'
|
45
45
|
log_out.string.should include 'String'
|
46
46
|
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should log exceptions' do
|
50
|
+
begin
|
51
|
+
raise RuntimeError, 'bad luck'
|
52
|
+
rescue => error
|
53
|
+
subject.logger_for(String).error 'hello world', error
|
54
|
+
end
|
55
|
+
log_out.string.should include 'hello world: RuntimeError: bad luck'
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'meta data' do
|
59
|
+
it 'should log with metadata in RFC5424 format' do
|
60
|
+
subject.with_meta(type: 'access-log').info 'GET /asdfas'
|
61
|
+
log_out.string.should include 'type="access-log"'
|
47
62
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
63
|
+
subject.info 'GET /asdfas'
|
64
|
+
log_out.string.lines.to_a.last.should_not include 'type="access-log"'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should work with chaining' do
|
68
|
+
subject.with_meta(type: 'access-log').with_meta(blah: 'xxx').info 'GET /asdfas'
|
69
|
+
log_out.string.should include 'type="access-log" blah="xxx"'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should log with metadata context' do
|
73
|
+
subject.with_meta_context(type: 'app-log') do
|
74
|
+
subject.info 'GET /asdfas'
|
53
75
|
end
|
54
|
-
log_out.string.should include '
|
76
|
+
log_out.string.should include 'type="app-log"'
|
77
|
+
|
78
|
+
subject.info 'GET /asdfas'
|
79
|
+
log_out.string.lines.to_a.last.should_not include 'type="app-log"'
|
55
80
|
end
|
56
81
|
end
|
57
82
|
end
|
58
83
|
|
84
|
+
require 'capture-output'
|
85
|
+
|
86
|
+
describe SyslogLogDev do
|
87
|
+
subject do
|
88
|
+
SyslogLogDev.new('unicorn-cuba-base-test', 'daemon', true)
|
89
|
+
end
|
90
|
+
|
91
|
+
after :each do
|
92
|
+
subject.close
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should write messages to syslog expecting first word to be log level' do
|
96
|
+
Capture.stderr{subject.write 'INFO hello world'}.should include '<Info>'
|
97
|
+
Capture.stderr{subject.write 'WARN hello world'}.should include '<Warning>'
|
98
|
+
Capture.stderr{subject.write 'INFO hello world'}.should include 'hello world'
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should handle multiline log entries' do
|
102
|
+
Capture.stderr{subject.write "INFO hello\nworld"}.should include "<Info>: hello\n\tworld\n"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe RootSyslogLogger do
|
107
|
+
subject do
|
108
|
+
@subject ||= RootSyslogLogger.new('unicorn-cuba-base-test', 'daemon', true).logger_for(RSpec)
|
109
|
+
end
|
110
|
+
|
111
|
+
after :each do
|
112
|
+
subject.close
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should log to syslog' do
|
116
|
+
log_out = Capture.stderr{subject.info 'hello world'}
|
117
|
+
|
118
|
+
log_out.should include 'unicorn-cuba-base-test'
|
119
|
+
log_out.should match /\[[0-9]+\]/
|
120
|
+
log_out.should include '<Info>:'
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should include message' do
|
124
|
+
Capture.stderr{subject.info 'hello world'}.should include 'hello world'
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should include class name' do
|
128
|
+
Capture.stderr{subject.info 'hello world'}.should include 'RSpec'
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should map log levels to syslog severities' do
|
132
|
+
Capture.stderr{subject.debug 'hello world'}.should include '<Debug>'
|
133
|
+
Capture.stderr{subject.info 'hello world'}.should include '<Info>'
|
134
|
+
Capture.stderr{subject.warn 'hello world'}.should include '<Warning>'
|
135
|
+
Capture.stderr{subject.error 'hello world'}.should include '<Error>'
|
136
|
+
Capture.stderr{subject.fatal 'hello world'}.should include '<Critical>'
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should handle multiline logs by appending tab after new line (done by syslog?)' do
|
140
|
+
Capture.stderr{subject.info "hello\nworld\ntest"}.should include "hello\n\tworld\n\ttest\n"
|
141
|
+
end
|
142
|
+
|
143
|
+
describe 'direct wirtes' do
|
144
|
+
it 'should use Info level' do
|
145
|
+
Capture.stderr{subject.write "hello world"}.should include '<Info>'
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should allow use of meta data' do
|
149
|
+
Capture.stderr{subject.with_meta('type' => 'access-log').write "hello world"}.should include 'type="access-log"'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
data/unicorn-cuba-base.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "unicorn-cuba-base"
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jakub Pastuszek"]
|
12
|
-
s.date = "
|
12
|
+
s.date = "2014-07-28"
|
13
13
|
s.description = "web application base powered by Unicorn HTTP server and based on Cuba framework extended with additional Rack middleware and Cuba plugins"
|
14
14
|
s.email = "jpastuszek@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -32,12 +32,15 @@ Gem::Specification.new do |s|
|
|
32
32
|
"lib/unicorn-cuba-base/plugin/logging.rb",
|
33
33
|
"lib/unicorn-cuba-base/plugin/memory_limit.rb",
|
34
34
|
"lib/unicorn-cuba-base/plugin/response_helpers.rb",
|
35
|
+
"lib/unicorn-cuba-base/rack/common_logger_xid.rb",
|
35
36
|
"lib/unicorn-cuba-base/rack/error_handling.rb",
|
36
37
|
"lib/unicorn-cuba-base/rack/memory_limit.rb",
|
37
38
|
"lib/unicorn-cuba-base/rack/unhandled_request.rb",
|
39
|
+
"lib/unicorn-cuba-base/rack/xid_logging.rb",
|
38
40
|
"lib/unicorn-cuba-base/root_logger.rb",
|
39
41
|
"lib/unicorn-cuba-base/stats.rb",
|
40
42
|
"lib/unicorn-cuba-base/stats_reporter.rb",
|
43
|
+
"lib/unicorn-cuba-base/uri_ext.rb",
|
41
44
|
"spec/memory_limit_spec.rb",
|
42
45
|
"spec/root_logger_spec.rb",
|
43
46
|
"spec/spec_helper.rb",
|
@@ -46,7 +49,7 @@ Gem::Specification.new do |s|
|
|
46
49
|
s.homepage = "http://github.com/jpastuszek/unicorn-cuba-base"
|
47
50
|
s.licenses = ["MIT"]
|
48
51
|
s.require_paths = ["lib"]
|
49
|
-
s.rubygems_version = "1.8.
|
52
|
+
s.rubygems_version = "1.8.23"
|
50
53
|
s.summary = "web appliaction base powered by Unicorn and Cuba"
|
51
54
|
|
52
55
|
if s.respond_to? :specification_version then
|
@@ -62,6 +65,7 @@ Gem::Specification.new do |s|
|
|
62
65
|
s.add_development_dependency(%q<rspec>, ["~> 2.13"])
|
63
66
|
s.add_development_dependency(%q<rdoc>, ["~> 3.9"])
|
64
67
|
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
68
|
+
s.add_development_dependency(%q<capture-output>, ["~> 1.0"])
|
65
69
|
else
|
66
70
|
s.add_dependency(%q<cuba>, ["~> 3.0"])
|
67
71
|
s.add_dependency(%q<unicorn>, [">= 4.6.2"])
|
@@ -72,6 +76,7 @@ Gem::Specification.new do |s|
|
|
72
76
|
s.add_dependency(%q<rspec>, ["~> 2.13"])
|
73
77
|
s.add_dependency(%q<rdoc>, ["~> 3.9"])
|
74
78
|
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
79
|
+
s.add_dependency(%q<capture-output>, ["~> 1.0"])
|
75
80
|
end
|
76
81
|
else
|
77
82
|
s.add_dependency(%q<cuba>, ["~> 3.0"])
|
@@ -83,6 +88,7 @@ Gem::Specification.new do |s|
|
|
83
88
|
s.add_dependency(%q<rspec>, ["~> 2.13"])
|
84
89
|
s.add_dependency(%q<rdoc>, ["~> 3.9"])
|
85
90
|
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
91
|
+
s.add_dependency(%q<capture-output>, ["~> 1.0"])
|
86
92
|
end
|
87
93
|
end
|
88
94
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicorn-cuba-base
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-07-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cuba
|
@@ -155,6 +155,22 @@ dependencies:
|
|
155
155
|
- - ~>
|
156
156
|
- !ruby/object:Gem::Version
|
157
157
|
version: 1.8.4
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: capture-output
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ~>
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '1.0'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ~>
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '1.0'
|
158
174
|
description: web application base powered by Unicorn HTTP server and based on Cuba
|
159
175
|
framework extended with additional Rack middleware and Cuba plugins
|
160
176
|
email: jpastuszek@gmail.com
|
@@ -179,12 +195,15 @@ files:
|
|
179
195
|
- lib/unicorn-cuba-base/plugin/logging.rb
|
180
196
|
- lib/unicorn-cuba-base/plugin/memory_limit.rb
|
181
197
|
- lib/unicorn-cuba-base/plugin/response_helpers.rb
|
198
|
+
- lib/unicorn-cuba-base/rack/common_logger_xid.rb
|
182
199
|
- lib/unicorn-cuba-base/rack/error_handling.rb
|
183
200
|
- lib/unicorn-cuba-base/rack/memory_limit.rb
|
184
201
|
- lib/unicorn-cuba-base/rack/unhandled_request.rb
|
202
|
+
- lib/unicorn-cuba-base/rack/xid_logging.rb
|
185
203
|
- lib/unicorn-cuba-base/root_logger.rb
|
186
204
|
- lib/unicorn-cuba-base/stats.rb
|
187
205
|
- lib/unicorn-cuba-base/stats_reporter.rb
|
206
|
+
- lib/unicorn-cuba-base/uri_ext.rb
|
188
207
|
- spec/memory_limit_spec.rb
|
189
208
|
- spec/root_logger_spec.rb
|
190
209
|
- spec/spec_helper.rb
|
@@ -204,7 +223,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
204
223
|
version: '0'
|
205
224
|
segments:
|
206
225
|
- 0
|
207
|
-
hash:
|
226
|
+
hash: 668318932229336882
|
208
227
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
209
228
|
none: false
|
210
229
|
requirements:
|
@@ -213,7 +232,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
213
232
|
version: '0'
|
214
233
|
requirements: []
|
215
234
|
rubyforge_project:
|
216
|
-
rubygems_version: 1.8.
|
235
|
+
rubygems_version: 1.8.23
|
217
236
|
signing_key:
|
218
237
|
specification_version: 3
|
219
238
|
summary: web appliaction base powered by Unicorn and Cuba
|