hatchet 0.1.0 → 0.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/RELEASE.md +15 -0
- data/lib/hatchet.rb +3 -3
- data/lib/hatchet/hatchet_logger.rb +12 -4
- data/lib/hatchet/message.rb +46 -9
- data/lib/hatchet/middleware.rb +34 -0
- data/lib/hatchet/nested_diagnostic_context.rb +160 -0
- data/lib/hatchet/railtie.rb +7 -0
- data/lib/hatchet/simple_formatter.rb +4 -3
- data/lib/hatchet/standard_formatter.rb +8 -2
- data/lib/hatchet/version.rb +1 -1
- data/spec/helpers/storing_appender.rb +1 -0
- data/spec/logger_spec.rb +83 -1
- data/spec/message_spec.rb +45 -3
- data/spec/middleware_spec.rb +115 -0
- data/spec/plain_formatter_spec.rb +2 -2
- data/spec/simple_formatter_spec.rb +16 -3
- data/spec/standard_formatter_spec.rb +6 -4
- metadata +6 -2
data/RELEASE.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Release notes
|
2
2
|
|
3
|
+
## 0.2.0
|
4
|
+
|
5
|
+
* Added nested diagnostic context and Rack middleware to clear it between
|
6
|
+
requests
|
7
|
+
|
8
|
+
### Note
|
9
|
+
|
10
|
+
The `Hatchet::Message` constructor has been altered, going forward it will take
|
11
|
+
a Hash of arguments instead of fixed arguments. It is currently backwards
|
12
|
+
compatible but this will likely be dropped for 1.0.0 so it is advised you update
|
13
|
+
your libraries now.
|
14
|
+
|
15
|
+
This should only affect custom formatters which may want to take advantage of
|
16
|
+
the nested diagnostic context which is now available anyway.
|
17
|
+
|
3
18
|
## 0.1.0
|
4
19
|
|
5
20
|
No changes from 0.0.20, just time for a minor version release.
|
data/lib/hatchet.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
|
-
require 'logger'
|
4
|
-
|
5
3
|
require_relative 'hatchet/level_manager'
|
6
4
|
require_relative 'hatchet/backtrace_formatter'
|
7
5
|
require_relative 'hatchet/thread_name_formatter'
|
@@ -10,6 +8,8 @@ require_relative 'hatchet/delegating_formatter'
|
|
10
8
|
require_relative 'hatchet/hatchet_logger'
|
11
9
|
require_relative 'hatchet/logger_appender'
|
12
10
|
require_relative 'hatchet/message'
|
11
|
+
require_relative 'hatchet/middleware'
|
12
|
+
require_relative 'hatchet/nested_diagnostic_context'
|
13
13
|
require_relative 'hatchet/plain_formatter'
|
14
14
|
require_relative 'hatchet/simple_formatter'
|
15
15
|
require_relative 'hatchet/standard_formatter'
|
@@ -66,7 +66,7 @@ module Hatchet
|
|
66
66
|
# Returns a HatchetLogger for the object.
|
67
67
|
#
|
68
68
|
def logger
|
69
|
-
@_hatchet_logger ||= HatchetLogger.new
|
69
|
+
@_hatchet_logger ||= HatchetLogger.new(self, Hatchet.configuration, Hatchet::NestedDiagnosticContext.current)
|
70
70
|
end
|
71
71
|
|
72
72
|
# Public: Returns a HatchetLogger for the object.
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
|
+
require 'logger'
|
4
|
+
|
3
5
|
module Hatchet
|
4
6
|
|
5
7
|
# Public: Class that handles logging calls and distributes them to all its
|
@@ -60,15 +62,21 @@ module Hatchet
|
|
60
62
|
Logger::FATAL => :fatal
|
61
63
|
}
|
62
64
|
|
65
|
+
# Public: Gets the NestedDiagnosticContext for the logger.
|
66
|
+
#
|
67
|
+
attr_reader :ndc
|
68
|
+
|
63
69
|
# Internal: Creates a new logger.
|
64
70
|
#
|
65
71
|
# host - The object the logger gains its context from.
|
66
72
|
# configuration - The configuration of Hatchet.
|
73
|
+
# ndc - The nested diagnostic context of the logger.
|
67
74
|
#
|
68
|
-
def initialize(host, configuration)
|
69
|
-
@context =
|
75
|
+
def initialize(host, configuration, ndc)
|
76
|
+
@context = host_name(host)
|
70
77
|
@configuration = configuration
|
71
78
|
@appenders = configuration.appenders
|
79
|
+
@ndc = ndc
|
72
80
|
end
|
73
81
|
|
74
82
|
[:debug, :info, :warn, :error, :fatal].each do |level|
|
@@ -103,7 +111,7 @@ module Hatchet
|
|
103
111
|
#
|
104
112
|
define_method level do |message = nil, error = nil, &block|
|
105
113
|
return unless message or block
|
106
|
-
add level, Message.new(message, error, &block)
|
114
|
+
add level, Message.new(ndc: @ndc.context.clone, message: message, error: error, &block)
|
107
115
|
end
|
108
116
|
|
109
117
|
# Public: Returns true if any of the appenders will log messages for the
|
@@ -193,7 +201,7 @@ module Hatchet
|
|
193
201
|
# Ruby, the host itself when the host is a module, otherwise the object's
|
194
202
|
# class.
|
195
203
|
#
|
196
|
-
def
|
204
|
+
def host_name(host)
|
197
205
|
if host.inspect == 'main'
|
198
206
|
'main'
|
199
207
|
elsif [Module, Class].include? host.class
|
data/lib/hatchet/message.rb
CHANGED
@@ -8,6 +8,9 @@ module Hatchet
|
|
8
8
|
# If an error is associated with the message this will be available via the
|
9
9
|
# #error attribute.
|
10
10
|
#
|
11
|
+
# The nested diagnostic context of the message will be availble via the #ndc
|
12
|
+
# attribute.
|
13
|
+
#
|
11
14
|
# Blocks will be lazily evaluated once for all appenders when required.
|
12
15
|
#
|
13
16
|
class Message
|
@@ -16,27 +19,61 @@ module Hatchet
|
|
16
19
|
#
|
17
20
|
attr_reader :error
|
18
21
|
|
19
|
-
#
|
22
|
+
# Public: Gets the nested diagnostic context values.
|
23
|
+
#
|
24
|
+
attr_reader :ndc
|
25
|
+
|
26
|
+
# Public: Creates a new message.
|
27
|
+
#
|
28
|
+
# args - The Hash used to provide context for the message (default: {}):
|
29
|
+
# :ndc - An Array of nested diagnostic context values
|
30
|
+
# (default: []).
|
31
|
+
# :message - An already evaluated message, usually a String
|
32
|
+
# (default: nil).
|
33
|
+
# :error - An error that is associated with the message
|
34
|
+
# (default: nil).
|
35
|
+
# block - An optional block which will provide a message when invoked.
|
36
|
+
#
|
37
|
+
# Examples
|
38
|
+
#
|
39
|
+
# Message.new(ndc: [], message: "Evaluated message", error: e)
|
40
|
+
# Message.new(ndc: %w{Foo Bar}) { "Lazily evaluated message" }
|
41
|
+
#
|
42
|
+
# The signature of the constructor was originally:
|
20
43
|
#
|
21
44
|
# message - An already evaluated message, usually a String (default: nil).
|
22
45
|
# error - An error that is associated with the message (default: nil).
|
23
46
|
# block - An optional block which will provide a message when invoked.
|
24
47
|
#
|
25
|
-
#
|
26
|
-
#
|
48
|
+
# This format is also supported for compatibility to version 0.1.0 and below
|
49
|
+
# and will be deprecated in the future.
|
27
50
|
#
|
28
51
|
# Examples
|
29
52
|
#
|
30
|
-
# Message.new
|
53
|
+
# Message.new("Evaluated message", e)
|
31
54
|
# Message.new { "Lazily evaluated message" }
|
32
55
|
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
56
|
+
# One of message or block must be provided. If both are provided then the
|
57
|
+
# block is preferred as it is assumed to provide more detail.
|
58
|
+
#
|
59
|
+
def initialize(args = {}, error = nil, &block)
|
60
|
+
if args.kind_of? Hash
|
61
|
+
# If args is a Hash then using new constructor format or no parameters
|
62
|
+
# specified. Either way, use the new format.
|
63
|
+
@ndc = args[:ndc] || []
|
64
|
+
@error = args[:error]
|
65
|
+
@message = args[:message] unless block
|
66
|
+
else
|
67
|
+
# Otherwise assume the old format and coerce args accordingly.
|
68
|
+
@ndc = []
|
69
|
+
@error = error
|
70
|
+
@message = args unless block
|
71
|
+
end
|
72
|
+
|
73
|
+
@block = block
|
37
74
|
end
|
38
75
|
|
39
|
-
#
|
76
|
+
# Public: Returns the String representation of the message.
|
40
77
|
#
|
41
78
|
def to_s
|
42
79
|
@message ||= @block.call
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Hatchet
|
2
|
+
|
3
|
+
# Public: Middleware for making sure the nested diagnostic context is cleared
|
4
|
+
# between requests.
|
5
|
+
#
|
6
|
+
class Middleware
|
7
|
+
include Hatchet
|
8
|
+
|
9
|
+
# Public: Creates a new instance of the middleware, wrapping the given
|
10
|
+
# application.
|
11
|
+
#
|
12
|
+
# app - The application to wrap.
|
13
|
+
#
|
14
|
+
def initialize(app)
|
15
|
+
@app = app
|
16
|
+
end
|
17
|
+
|
18
|
+
# Public: Calls the wrapped application with the given environment, ensuring
|
19
|
+
# the nested diagnostic context is cleared afterwards.
|
20
|
+
#
|
21
|
+
# env - The enviroment Hash for the request.
|
22
|
+
#
|
23
|
+
# Returns the status, headers, body Array returned by the wrapped
|
24
|
+
# application.
|
25
|
+
#
|
26
|
+
def call(env)
|
27
|
+
@app.call(env)
|
28
|
+
ensure
|
29
|
+
log.ndc.clear!
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module Hatchet
|
2
|
+
|
3
|
+
# Public: Class that manages the nested diagnostic context for a thread.
|
4
|
+
#
|
5
|
+
# All access to this class is performed through internal classes.
|
6
|
+
#
|
7
|
+
class NestedDiagnosticContext
|
8
|
+
|
9
|
+
# Internal: Gets the current context stack.
|
10
|
+
#
|
11
|
+
attr_reader :context
|
12
|
+
|
13
|
+
# Internal: Gets the NestedDiagnosticContext for the current thread, lazily
|
14
|
+
# initializing it as necessary.
|
15
|
+
#
|
16
|
+
def self.current
|
17
|
+
Thread.current[:hatchet_ndc] ||= NestedDiagnosticContext.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# Internal: Creates a new instance of the class.
|
21
|
+
#
|
22
|
+
def initialize
|
23
|
+
clear!
|
24
|
+
end
|
25
|
+
|
26
|
+
# Public: Adds one or more messages onto the context stack.
|
27
|
+
#
|
28
|
+
# values - One or more messages to add to the context stack.
|
29
|
+
#
|
30
|
+
# Returns nothing.
|
31
|
+
#
|
32
|
+
def push(*values)
|
33
|
+
@context.push(*values)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Public: Removes one or more message from the context stack.
|
37
|
+
#
|
38
|
+
# n - The number of messages to remove from the context stack (default:
|
39
|
+
# nil). If no number is provided then one message will be removed.
|
40
|
+
#
|
41
|
+
# Returns the message or messages removed from the context stack. If n was
|
42
|
+
# not specified it will return a single message, otherwise it will return an
|
43
|
+
# Array of up to n messages.
|
44
|
+
#
|
45
|
+
def pop(n = nil)
|
46
|
+
if n
|
47
|
+
@context.pop(n)
|
48
|
+
else
|
49
|
+
@context.pop
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Public: Adds one more or message onto the context stack for the scope of
|
54
|
+
# the given block.
|
55
|
+
#
|
56
|
+
# values - One or more messages to add to the context stack for the scope of
|
57
|
+
# the given block.
|
58
|
+
# block - The block to execute with the additional messages.
|
59
|
+
#
|
60
|
+
# Returns the result of calling the block.
|
61
|
+
#
|
62
|
+
def scope(*values, &block)
|
63
|
+
before = @context.clone
|
64
|
+
push(*values)
|
65
|
+
block.call
|
66
|
+
ensure
|
67
|
+
@context = before
|
68
|
+
end
|
69
|
+
|
70
|
+
# Public: Clears all messages from the context stack.
|
71
|
+
#
|
72
|
+
# Intend for use when the current thread is, or may, be reused in the future
|
73
|
+
# and the accumlated context is no longer wanted.
|
74
|
+
#
|
75
|
+
# Returns nothing.
|
76
|
+
#
|
77
|
+
def clear!
|
78
|
+
@context = ContextStack.new
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
|
82
|
+
# Public: Class for holding the context stack of a NestedDiagnosticContext.
|
83
|
+
#
|
84
|
+
# Deliberately intended to have a similar API to Array to make testing
|
85
|
+
# easier.
|
86
|
+
#
|
87
|
+
class ContextStack
|
88
|
+
|
89
|
+
# Internal: Gets the internal stack.
|
90
|
+
#
|
91
|
+
attr_reader :stack
|
92
|
+
|
93
|
+
# Internal: Creates a new instance.
|
94
|
+
#
|
95
|
+
# stack - An Array of values to initialize the stack with (default: []).
|
96
|
+
#
|
97
|
+
def initialize(stack = [])
|
98
|
+
@stack = stack
|
99
|
+
end
|
100
|
+
|
101
|
+
# Public: Returns true if the stack contains any messages, otherwise
|
102
|
+
# returns false.
|
103
|
+
#
|
104
|
+
def any?
|
105
|
+
@stack.size != 0
|
106
|
+
end
|
107
|
+
|
108
|
+
# Internal: Returns a clone of the stack.
|
109
|
+
#
|
110
|
+
def clone
|
111
|
+
ContextStack.new(@stack.clone)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Public: Returns a String created by converting each message of the stack
|
115
|
+
# to a String, separated by separator.
|
116
|
+
#
|
117
|
+
# separator - The String to separate the messages of the stack with
|
118
|
+
# (default: $,).
|
119
|
+
#
|
120
|
+
# Returns a String created by converting each message of the stack to a
|
121
|
+
# String, separated by separator.
|
122
|
+
#
|
123
|
+
def join(separator = $,)
|
124
|
+
@stack.join(separator)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Internal: Pushes the given messages onto the stack.
|
128
|
+
#
|
129
|
+
# values - One or more messages to add to the context stack.
|
130
|
+
#
|
131
|
+
# Returns nothing.
|
132
|
+
#
|
133
|
+
def push(*values)
|
134
|
+
@stack.push(*values)
|
135
|
+
nil
|
136
|
+
end
|
137
|
+
|
138
|
+
# Internal: Removes one or more message from the stack.
|
139
|
+
#
|
140
|
+
# n - The number of messages to remove from the cstack (default: nil). If
|
141
|
+
# no number is provided then one message will be removed.
|
142
|
+
#
|
143
|
+
# Returns the message or messages removed from the context stack. If n was
|
144
|
+
# not specified it will return a single message, otherwise it will return
|
145
|
+
# an Array of up to n messages.
|
146
|
+
#
|
147
|
+
def pop(n = nil)
|
148
|
+
if n
|
149
|
+
@stack.pop(n)
|
150
|
+
else
|
151
|
+
@stack.pop
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
data/lib/hatchet/railtie.rb
CHANGED
@@ -15,6 +15,13 @@ module Hatchet
|
|
15
15
|
#
|
16
16
|
self.config.hatchet = Hatchet.configuration
|
17
17
|
|
18
|
+
# Add the Hatchet::Middleware to the middleware stack to enable nested
|
19
|
+
# diagnostic context clearance between requests.
|
20
|
+
#
|
21
|
+
initializer "hatchet_railtie.insert_middleware" do |app|
|
22
|
+
app.config.middleware.use Hatchet::Middleware
|
23
|
+
end
|
24
|
+
|
18
25
|
# Wrap the default Rails.logger, Rails.application.assets.logger, and all
|
19
26
|
# log subscribers found in ActiveSupport::LogSubscriber.log_subscribers
|
20
27
|
# collection on initialization.
|
@@ -31,11 +31,12 @@ module Hatchet
|
|
31
31
|
#
|
32
32
|
def format(level, context, message)
|
33
33
|
msg = message.to_s.strip
|
34
|
+
thread = thread_context ? "[#{thread_name}] - " : nil
|
34
35
|
|
35
|
-
if
|
36
|
-
msg = "
|
36
|
+
if message.ndc.any?
|
37
|
+
msg = "#{thread}#{level.to_s.upcase} - #{context} #{message.ndc.join(' ')} - #{msg}"
|
37
38
|
else
|
38
|
-
msg = "#{level.to_s.upcase} - #{context} - #{msg}"
|
39
|
+
msg = "#{thread}#{level.to_s.upcase} - #{context} - #{msg}"
|
39
40
|
end
|
40
41
|
|
41
42
|
with_backtrace(message, msg)
|
@@ -12,6 +12,7 @@ module Hatchet
|
|
12
12
|
#
|
13
13
|
def initialize
|
14
14
|
@secs = 0
|
15
|
+
@level_cache = {}
|
15
16
|
end
|
16
17
|
|
17
18
|
# Public: Returns the formatted message.
|
@@ -29,7 +30,12 @@ module Hatchet
|
|
29
30
|
#
|
30
31
|
def format(level, context, message)
|
31
32
|
msg = message.to_s.strip
|
32
|
-
|
33
|
+
|
34
|
+
if message.ndc.any?
|
35
|
+
msg = "#{timestamp} [#{thread_name}] #{format_level(level)} #{context} #{message.ndc.join(' ')} - #{msg}"
|
36
|
+
else
|
37
|
+
msg = "#{timestamp} [#{thread_name}] #{format_level(level)} #{context} - #{msg}"
|
38
|
+
end
|
33
39
|
|
34
40
|
with_backtrace(message, msg)
|
35
41
|
end
|
@@ -58,7 +64,7 @@ module Hatchet
|
|
58
64
|
# Private: Returns the level formatted for log output as a String.
|
59
65
|
#
|
60
66
|
def format_level(level)
|
61
|
-
level.to_s.upcase.ljust(5)
|
67
|
+
@level_cache[level] ||= level.to_s.upcase.ljust(5)
|
62
68
|
end
|
63
69
|
|
64
70
|
end
|
data/lib/hatchet/version.rb
CHANGED
data/spec/logger_spec.rb
CHANGED
@@ -8,9 +8,15 @@ describe HatchetLogger do
|
|
8
8
|
let(:appenders) { [appender, disabled_appender] }
|
9
9
|
let(:configuration) { Configuration.new }
|
10
10
|
let(:context) { Context::Class.new }
|
11
|
+
let(:ndc) { NestedDiagnosticContext.new }
|
12
|
+
|
13
|
+
def last_message
|
14
|
+
appender.messages.last.message
|
15
|
+
end
|
16
|
+
|
11
17
|
let(:subject) do
|
12
18
|
configuration.appenders.push(*appenders)
|
13
|
-
HatchetLogger.new context, configuration
|
19
|
+
HatchetLogger.new context, configuration, ndc
|
14
20
|
end
|
15
21
|
|
16
22
|
ALL_LEVELS.each do |level|
|
@@ -139,5 +145,81 @@ describe HatchetLogger do
|
|
139
145
|
end
|
140
146
|
end
|
141
147
|
end
|
148
|
+
|
149
|
+
describe 'nested diagnostic context' do
|
150
|
+
|
151
|
+
describe 'pushing context' do
|
152
|
+
|
153
|
+
it 'passes the context with the message' do
|
154
|
+
subject.ndc.push(:foo)
|
155
|
+
subject.info 'Message'
|
156
|
+
assert_equal [:foo], last_message.ndc.stack
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'stacks contexts with the message' do
|
160
|
+
subject.ndc.push(:foo, :bar, :baz)
|
161
|
+
subject.info 'Message'
|
162
|
+
assert_equal [:foo, :bar, :baz], last_message.ndc.stack
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'pops contexts individually' do
|
166
|
+
subject.ndc.push(:foo, :bar, :baz)
|
167
|
+
|
168
|
+
subject.info 'Message'
|
169
|
+
assert_equal [:foo, :bar, :baz], last_message.ndc.stack
|
170
|
+
|
171
|
+
subject.ndc.pop
|
172
|
+
subject.info 'Message'
|
173
|
+
assert_equal [:foo, :bar], last_message.ndc.stack
|
174
|
+
|
175
|
+
subject.ndc.pop
|
176
|
+
subject.info 'Message'
|
177
|
+
assert_equal [:foo], last_message.ndc.stack
|
178
|
+
|
179
|
+
subject.ndc.pop
|
180
|
+
subject.info 'Message'
|
181
|
+
assert_equal [], last_message.ndc.stack
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'pops a specified number of contexts' do
|
185
|
+
subject.ndc.push(:foo, :bar, :baz)
|
186
|
+
|
187
|
+
subject.info 'Message'
|
188
|
+
assert_equal [:foo, :bar, :baz], last_message.ndc.stack
|
189
|
+
|
190
|
+
subject.ndc.pop(2)
|
191
|
+
subject.info 'Message'
|
192
|
+
assert_equal [:foo], last_message.ndc.stack
|
193
|
+
|
194
|
+
subject.ndc.pop(2)
|
195
|
+
subject.info 'Message'
|
196
|
+
assert_equal [], last_message.ndc.stack
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'scopes contexts when used with blocks' do
|
200
|
+
subject.ndc.scope(:foo) do
|
201
|
+
subject.info 'Message'
|
202
|
+
assert_equal [:foo], last_message.ndc.stack
|
203
|
+
end
|
204
|
+
|
205
|
+
subject.info 'Message'
|
206
|
+
assert_equal [], last_message.ndc.stack
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'can clear all contexts' do
|
210
|
+
subject.ndc.push(:foo, :bar, :baz)
|
211
|
+
|
212
|
+
subject.info 'Message'
|
213
|
+
assert_equal [:foo, :bar, :baz], last_message.ndc.stack
|
214
|
+
|
215
|
+
subject.ndc.clear!
|
216
|
+
|
217
|
+
subject.info 'Message'
|
218
|
+
assert_equal [], last_message.ndc.stack
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
142
224
|
end
|
143
225
|
|
data/spec/message_spec.rb
CHANGED
@@ -4,7 +4,7 @@ require_relative 'spec_helper'
|
|
4
4
|
|
5
5
|
describe Message do
|
6
6
|
describe 'providing an evaluted message' do
|
7
|
-
let(:subject) { Message.new 'Evaluated' }
|
7
|
+
let(:subject) { Message.new(ndc: [], message: 'Evaluated') }
|
8
8
|
|
9
9
|
it 'returns the given message' do
|
10
10
|
assert_equal 'Evaluated', subject.to_s
|
@@ -14,7 +14,7 @@ describe Message do
|
|
14
14
|
describe 'providing a block message' do
|
15
15
|
let(:subject) do
|
16
16
|
@evaluated = 0
|
17
|
-
Message.new do
|
17
|
+
Message.new(ndc: []) do
|
18
18
|
@evaluated += 1
|
19
19
|
'Block'
|
20
20
|
end
|
@@ -33,7 +33,7 @@ describe Message do
|
|
33
33
|
|
34
34
|
describe 'providing both an evaluated and block message' do
|
35
35
|
let(:subject) do
|
36
|
-
Message.new 'Evaluated' do
|
36
|
+
Message.new(ndc: [], message: 'Evaluated') do
|
37
37
|
'Block'
|
38
38
|
end
|
39
39
|
end
|
@@ -42,5 +42,47 @@ describe Message do
|
|
42
42
|
assert_equal 'Block', subject.to_s
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
describe 'supporting the old constructor format' do
|
47
|
+
describe 'providing an evaluted message' do
|
48
|
+
let(:subject) { Message.new('Evaluated') }
|
49
|
+
|
50
|
+
it 'returns the given message' do
|
51
|
+
assert_equal 'Evaluated', subject.to_s
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'providing a block message' do
|
56
|
+
let(:subject) do
|
57
|
+
@evaluated = 0
|
58
|
+
Message.new do
|
59
|
+
@evaluated += 1
|
60
|
+
'Block'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'returns the result of evaluating the block' do
|
65
|
+
assert_equal 'Block', subject.to_s
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'only evaluates the block once for multiple calls' do
|
69
|
+
subject.to_s
|
70
|
+
subject.to_s
|
71
|
+
assert_equal 1, @evaluated
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'providing both an evaluated and block message' do
|
76
|
+
let(:subject) do
|
77
|
+
Message.new('Evaluated') do
|
78
|
+
'Block'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'returns the result of evaluating the block' do
|
83
|
+
assert_equal 'Block', subject.to_s
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
45
87
|
end
|
46
88
|
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Middleware do
|
4
|
+
|
5
|
+
class App
|
6
|
+
include Hatchet
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@request = 1
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
log.ndc.push(@request)
|
14
|
+
|
15
|
+
log.info "Start"
|
16
|
+
|
17
|
+
one = One.new
|
18
|
+
one.run(env)
|
19
|
+
|
20
|
+
log.ndc.push(:end)
|
21
|
+
log.info "Finish"
|
22
|
+
|
23
|
+
@request += 1
|
24
|
+
|
25
|
+
[:status, :headers, :body]
|
26
|
+
end
|
27
|
+
|
28
|
+
class One
|
29
|
+
include Hatchet
|
30
|
+
|
31
|
+
def run(env)
|
32
|
+
log.ndc.push(:one)
|
33
|
+
log.info env[:one]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
let(:storing_appender) { StoringAppender.new :debug }
|
40
|
+
let(:messages) { storing_appender.messages }
|
41
|
+
|
42
|
+
let(:subject) do
|
43
|
+
Hatchet.configure do |config|
|
44
|
+
config.reset!
|
45
|
+
config.appenders << storing_appender
|
46
|
+
end
|
47
|
+
|
48
|
+
app = App.new
|
49
|
+
Middleware.new(app)
|
50
|
+
end
|
51
|
+
|
52
|
+
before do
|
53
|
+
messages.clear
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "maintaining the result" do
|
57
|
+
|
58
|
+
before do
|
59
|
+
@status, @headers, @body = subject.call(one: 'Testing')
|
60
|
+
end
|
61
|
+
|
62
|
+
it "maintains the status" do
|
63
|
+
assert_equal :status, @status
|
64
|
+
end
|
65
|
+
|
66
|
+
it "maintains the headers" do
|
67
|
+
assert_equal :headers, @headers
|
68
|
+
end
|
69
|
+
|
70
|
+
it "maintains the body" do
|
71
|
+
assert_equal :body, @body
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "accumulating context" do
|
77
|
+
|
78
|
+
before do
|
79
|
+
subject.call(one: 'Testing')
|
80
|
+
end
|
81
|
+
|
82
|
+
it "logs accumulating context" do
|
83
|
+
assert_equal "Start", messages[0].message.to_s
|
84
|
+
assert_equal [1], messages[0].message.ndc.stack
|
85
|
+
|
86
|
+
assert_equal 'Testing', messages[1].message.to_s
|
87
|
+
assert_equal [1, :one], messages[1].message.ndc.stack
|
88
|
+
|
89
|
+
assert_equal 'Finish', messages[2].message.to_s
|
90
|
+
assert_equal [1, :one, :end], messages[2].message.ndc.stack
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "clearing context between requests" do
|
96
|
+
|
97
|
+
before do
|
98
|
+
subject.call(one: 'Testing')
|
99
|
+
subject.call(one: 'TestingAgain')
|
100
|
+
end
|
101
|
+
|
102
|
+
it "clears context from previous requests" do
|
103
|
+
assert_equal "Start", messages[3].message.to_s
|
104
|
+
assert_equal [2], messages[3].message.ndc.stack
|
105
|
+
|
106
|
+
assert_equal 'TestingAgain', messages[4].message.to_s
|
107
|
+
assert_equal [2, :one], messages[4].message.ndc.stack
|
108
|
+
|
109
|
+
assert_equal 'Finish', messages[5].message.to_s
|
110
|
+
assert_equal [2, :one, :end], messages[5].message.ndc.stack
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
@@ -10,7 +10,7 @@ describe PlainFormatter do
|
|
10
10
|
describe 'without an error' do
|
11
11
|
|
12
12
|
before do
|
13
|
-
@message = Message.new(' Hello, World ')
|
13
|
+
@message = Message.new(ndc: [], message: ' Hello, World ')
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'outputs the message in the MESSAGE format' do
|
@@ -24,7 +24,7 @@ describe PlainFormatter do
|
|
24
24
|
|
25
25
|
before do
|
26
26
|
error = OpenStruct.new(message: 'Boom!', backtrace: ['foo.rb:1:a', 'foo.rb:20:b'])
|
27
|
-
@message = Message.new(' Hello, World ', error)
|
27
|
+
@message = Message.new(ndc: [], message: ' Hello, World ', error: error)
|
28
28
|
end
|
29
29
|
|
30
30
|
describe 'with backtraces enabled' do
|
@@ -10,7 +10,7 @@ describe SimpleFormatter do
|
|
10
10
|
describe 'without an error' do
|
11
11
|
|
12
12
|
before do
|
13
|
-
@message = Message.new(' Hello, World ')
|
13
|
+
@message = Message.new(ndc: [], message: ' Hello, World ')
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'outputs the message in the LEVEL - CONTEXT - MESSAGE format' do
|
@@ -24,7 +24,7 @@ describe SimpleFormatter do
|
|
24
24
|
|
25
25
|
before do
|
26
26
|
error = OpenStruct.new(message: 'Boom!', backtrace: ['foo.rb:1:a', 'foo.rb:20:b'])
|
27
|
-
@message = Message.new(' Hello, World ', error)
|
27
|
+
@message = Message.new(ndc: [], message: ' Hello, World ', error: error)
|
28
28
|
end
|
29
29
|
|
30
30
|
describe 'with backtraces enabled' do
|
@@ -57,7 +57,7 @@ describe SimpleFormatter do
|
|
57
57
|
|
58
58
|
before do
|
59
59
|
subject.thread_context = true
|
60
|
-
@message = Message.new(' Hello, World ')
|
60
|
+
@message = Message.new(ndc: [], message: ' Hello, World ')
|
61
61
|
end
|
62
62
|
|
63
63
|
it 'outputs the message in the [THREAD] - LEVEL - CONTEXT - MESSAGE format' do
|
@@ -67,6 +67,19 @@ describe SimpleFormatter do
|
|
67
67
|
|
68
68
|
end
|
69
69
|
|
70
|
+
describe 'with ndc' do
|
71
|
+
|
72
|
+
before do
|
73
|
+
@message = Message.new(ndc: [:foo, 123], message: ' Hello, World ')
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'outputs the message in the [THREAD] - LEVEL - CONTEXT NDC - MESSAGE format' do
|
77
|
+
message = subject.format(:info, 'Custom::Context', @message)
|
78
|
+
assert "INFO - Custom::Context foo 123 - Hello, World" == message, "got #{message}"
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
70
83
|
end
|
71
84
|
|
72
85
|
end
|
@@ -10,7 +10,8 @@ describe StandardFormatter do
|
|
10
10
|
|
11
11
|
describe 'when formatting a message' do
|
12
12
|
before do
|
13
|
-
|
13
|
+
ndc = NestedDiagnosticContext::ContextStack.new([:foo, 12])
|
14
|
+
@message = Message.new(ndc: ndc, message: 'Hello, World')
|
14
15
|
@context = 'Custom::Context'
|
15
16
|
@level = :info
|
16
17
|
@formatted_message = subject.format(@level, @context, @message)
|
@@ -37,7 +38,7 @@ describe StandardFormatter do
|
|
37
38
|
end
|
38
39
|
|
39
40
|
it 'formats the message after the time as expected' do
|
40
|
-
expected = "[#{Process.pid}] #{@level.to_s.upcase.ljust 5} #{@context} - #{@message}"
|
41
|
+
expected = "[#{Process.pid}] #{@level.to_s.upcase.ljust 5} #{@context} foo 12 - #{@message}"
|
41
42
|
actual_without_time = @formatted_message[24..-1]
|
42
43
|
|
43
44
|
assert_equal expected, actual_without_time
|
@@ -58,7 +59,7 @@ describe StandardFormatter do
|
|
58
59
|
|
59
60
|
before do
|
60
61
|
error = OpenStruct.new(message: 'Boom!', backtrace: ['foo.rb:1:a', 'foo.rb:20:b'])
|
61
|
-
@message = Message.new(' Hello, World ', error)
|
62
|
+
@message = Message.new(ndc: [], message: ' Hello, World ', error: error)
|
62
63
|
end
|
63
64
|
|
64
65
|
describe 'with backtraces enabled' do
|
@@ -98,7 +99,8 @@ describe StandardFormatter do
|
|
98
99
|
end
|
99
100
|
|
100
101
|
took = Time.now - start
|
101
|
-
limit = 0.
|
102
|
+
limit = 0.6
|
103
|
+
puts "\nMessages took #{took} to generate\n"
|
102
104
|
assert took < limit, "Expected messages to take less than #{limit} but took #{took}"
|
103
105
|
end
|
104
106
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hatchet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.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: 2013-01-10 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Logging library that provides the ability to add class/module specific
|
15
15
|
filters
|
@@ -26,6 +26,8 @@ files:
|
|
26
26
|
- lib/hatchet/level_manager.rb
|
27
27
|
- lib/hatchet/logger_appender.rb
|
28
28
|
- lib/hatchet/message.rb
|
29
|
+
- lib/hatchet/middleware.rb
|
30
|
+
- lib/hatchet/nested_diagnostic_context.rb
|
29
31
|
- lib/hatchet/plain_formatter.rb
|
30
32
|
- lib/hatchet/railtie.rb
|
31
33
|
- lib/hatchet/simple_formatter.rb
|
@@ -44,6 +46,7 @@ files:
|
|
44
46
|
- spec/logger_appender_spec.rb
|
45
47
|
- spec/logger_spec.rb
|
46
48
|
- spec/message_spec.rb
|
49
|
+
- spec/middleware_spec.rb
|
47
50
|
- spec/plain_formatter_spec.rb
|
48
51
|
- spec/simple_formatter_spec.rb
|
49
52
|
- spec/spec_helper.rb
|
@@ -87,6 +90,7 @@ test_files:
|
|
87
90
|
- spec/logger_appender_spec.rb
|
88
91
|
- spec/logger_spec.rb
|
89
92
|
- spec/message_spec.rb
|
93
|
+
- spec/middleware_spec.rb
|
90
94
|
- spec/plain_formatter_spec.rb
|
91
95
|
- spec/simple_formatter_spec.rb
|
92
96
|
- spec/spec_helper.rb
|