hanami-utils 2.0.0.alpha6 → 2.0.0.rc1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +157 -1
- data/README.md +9 -18
- data/hanami-utils.gemspec +0 -1
- data/lib/hanami/utils/string.rb +1 -1
- data/lib/hanami/utils/version.rb +2 -4
- metadata +2 -8
- data/lib/hanami/interactor.rb +0 -619
- data/lib/hanami/logger/colorizer.rb +0 -105
- data/lib/hanami/logger/filter.rb +0 -144
- data/lib/hanami/logger/formatter.rb +0 -183
- data/lib/hanami/logger.rb +0 -362
- data/lib/hanami/utils/basic_object.rb +0 -141
data/lib/hanami/logger.rb
DELETED
@@ -1,362 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "logger"
|
4
|
-
require "hanami/utils/string"
|
5
|
-
require "hanami/utils/files"
|
6
|
-
|
7
|
-
module Hanami
|
8
|
-
# Hanami logger
|
9
|
-
#
|
10
|
-
# Implementation with the same interface of Ruby std lib `Logger`.
|
11
|
-
# It uses `STDOUT`, `STDERR`, file name or open file as output stream.
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# When a Hanami application is initialized, it creates a logger for that specific application.
|
15
|
-
# For instance for a `Bookshelf::Application` a `Bookshelf::Logger` will be available.
|
16
|
-
#
|
17
|
-
# This is useful for auto-tagging the output. Eg (`app=Booshelf`).
|
18
|
-
#
|
19
|
-
# When used standalone (eg. `Hanami::Logger.info`), it tags lines with `app=Shared`.
|
20
|
-
#
|
21
|
-
#
|
22
|
-
# The available severity levels are the same of `Logger`:
|
23
|
-
#
|
24
|
-
# * DEBUG
|
25
|
-
# * INFO
|
26
|
-
# * WARN
|
27
|
-
# * ERROR
|
28
|
-
# * FATAL
|
29
|
-
# * UNKNOWN
|
30
|
-
#
|
31
|
-
# Those levels are available both as class and instance methods.
|
32
|
-
#
|
33
|
-
# Also Hanami::Logger supports different formatters. Now available only two:
|
34
|
-
#
|
35
|
-
# * Formatter (default)
|
36
|
-
# * JSONFormatter
|
37
|
-
#
|
38
|
-
# And if you want to use custom formatter you need create new class inherited from
|
39
|
-
# `Formatter` class and define `_format` private method like this:
|
40
|
-
#
|
41
|
-
# class CustomFormatter < Formatter
|
42
|
-
# private
|
43
|
-
# def _format(hash)
|
44
|
-
# # ...
|
45
|
-
# end
|
46
|
-
# end
|
47
|
-
#
|
48
|
-
# @since 0.5.0
|
49
|
-
#
|
50
|
-
# @see http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger.html
|
51
|
-
# @see http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger/Severity.html
|
52
|
-
#
|
53
|
-
# @example Basic usage
|
54
|
-
# require 'hanami'
|
55
|
-
#
|
56
|
-
# module Bookshelf
|
57
|
-
# class Application < Hanami::Application
|
58
|
-
# end
|
59
|
-
# end
|
60
|
-
#
|
61
|
-
# # Initialize the application with the following code:
|
62
|
-
# Bookshelf::Application.load!
|
63
|
-
# # or
|
64
|
-
# Bookshelf::Application.new
|
65
|
-
#
|
66
|
-
# Bookshelf::Logger.new.info('Hello')
|
67
|
-
# # => app=Bookshelf severity=INFO time=1988-09-01 00:00:00 UTC message=Hello
|
68
|
-
#
|
69
|
-
# @example Standalone usage
|
70
|
-
# require 'hanami/logger'
|
71
|
-
#
|
72
|
-
# Hanami::Logger.new.info('Hello')
|
73
|
-
# # => app=Hanami severity=INFO time=2016-05-27 10:14:42 UTC message=Hello
|
74
|
-
#
|
75
|
-
# @example Custom tagging
|
76
|
-
# require 'hanami/logger'
|
77
|
-
#
|
78
|
-
# Hanami::Logger.new('FOO').info('Hello')
|
79
|
-
# # => app=FOO severity=INFO time=2016-05-27 10:14:42 UTC message=Hello
|
80
|
-
#
|
81
|
-
# @example Write to file
|
82
|
-
# require 'hanami/logger'
|
83
|
-
#
|
84
|
-
# Hanami::Logger.new(stream: 'logfile.log').info('Hello')
|
85
|
-
# # in logfile.log
|
86
|
-
# # => app=FOO severity=INFO time=2016-05-27 10:14:42 UTC message=Hello
|
87
|
-
#
|
88
|
-
# @example Use JSON formatter
|
89
|
-
# require 'hanami/logger'
|
90
|
-
#
|
91
|
-
# Hanami::Logger.new(formatter: Hanami::Logger::JSONFormatter).info('Hello')
|
92
|
-
# # => "{\"app\":\"Hanami\",\"severity\":\"INFO\",\"time\":\"1988-09-01 00:00:00 UTC\",\"message\":\"Hello\"}"
|
93
|
-
#
|
94
|
-
# @example Disable colorization
|
95
|
-
# require 'hanami/logger'
|
96
|
-
#
|
97
|
-
# Hanami::Logger.new(colorizer: false)
|
98
|
-
#
|
99
|
-
# @example Use custom colors
|
100
|
-
# require 'hanami/logger'
|
101
|
-
#
|
102
|
-
# Hanami::Logger.new(colorizer: Hanami::Logger::Colorizer.new(colors: { app: :red }))
|
103
|
-
#
|
104
|
-
# @example Use custom colorizer
|
105
|
-
# require "hanami/logger"
|
106
|
-
# require "paint" # gem install paint
|
107
|
-
#
|
108
|
-
# class LogColorizer < Hanami::Logger::Colorizer
|
109
|
-
# def initialize(colors: { app: [:red, :bright], severity: [:red, :blue], datetime: [:italic, :yellow] })
|
110
|
-
# super
|
111
|
-
# end
|
112
|
-
#
|
113
|
-
# private
|
114
|
-
#
|
115
|
-
# def colorize(message, color:)
|
116
|
-
# Paint[message, *color]
|
117
|
-
# end
|
118
|
-
# end
|
119
|
-
#
|
120
|
-
# Hanami::Logger.new(colorizer: LogColorizer.new)
|
121
|
-
class Logger < ::Logger
|
122
|
-
require "hanami/logger/formatter"
|
123
|
-
require "hanami/logger/colorizer"
|
124
|
-
|
125
|
-
# Default application name.
|
126
|
-
# This is used as a fallback for tagging purposes.
|
127
|
-
#
|
128
|
-
# @since 0.5.0
|
129
|
-
# @api private
|
130
|
-
DEFAULT_APPLICATION_NAME = "hanami"
|
131
|
-
|
132
|
-
# @since 0.8.0
|
133
|
-
# @api private
|
134
|
-
LEVELS = ::Hash[
|
135
|
-
"debug" => DEBUG,
|
136
|
-
"info" => INFO,
|
137
|
-
"warn" => WARN,
|
138
|
-
"error" => ERROR,
|
139
|
-
"fatal" => FATAL,
|
140
|
-
"unknown" => UNKNOWN
|
141
|
-
].freeze
|
142
|
-
|
143
|
-
# @since 1.2.0
|
144
|
-
# @api private
|
145
|
-
def self.level(level)
|
146
|
-
case level
|
147
|
-
when DEBUG..UNKNOWN
|
148
|
-
level
|
149
|
-
else
|
150
|
-
LEVELS.fetch(level.to_s.downcase, DEBUG)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
# @since 0.5.0
|
155
|
-
# @api private
|
156
|
-
attr_writer :application_name
|
157
|
-
|
158
|
-
# Initialize a logger
|
159
|
-
#
|
160
|
-
# @param application_name [String] an optional application name used for
|
161
|
-
# tagging purposes
|
162
|
-
#
|
163
|
-
# @param args [Array<Object>] an optional set of arguments to honor Ruby's
|
164
|
-
# `Logger#initialize` arguments. See Ruby documentation for details.
|
165
|
-
#
|
166
|
-
# @param stream [String, IO, StringIO, Pathname] an optional log stream.
|
167
|
-
# This is a filename (`String`) or `IO` object (typically `$stdout`,
|
168
|
-
# `$stderr`, or an open file). It defaults to `$stderr`.
|
169
|
-
#
|
170
|
-
# @param level [Integer,String] logging level. It can be expressed as an
|
171
|
-
# integer, according to Ruby's `Logger` from standard library or as a
|
172
|
-
# string with the name of the level
|
173
|
-
#
|
174
|
-
# @param formatter [Symbol,#_format] a formatter - We support `:json` as
|
175
|
-
# JSON formatter or an object that respond to `#_format(data)`
|
176
|
-
#
|
177
|
-
# @since 0.5.0
|
178
|
-
#
|
179
|
-
# @see https://ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger.html#class-Logger-label-How+to+create+a+logger
|
180
|
-
#
|
181
|
-
# @example Basic usage
|
182
|
-
# require 'hanami/logger'
|
183
|
-
#
|
184
|
-
# logger = Hanami::Logger.new
|
185
|
-
# logger.info "Hello World"
|
186
|
-
#
|
187
|
-
# # => [Hanami] [DEBUG] [2017-03-30 15:41:01 +0200] Hello World
|
188
|
-
#
|
189
|
-
# @example Custom application name
|
190
|
-
# require 'hanami/logger'
|
191
|
-
#
|
192
|
-
# logger = Hanami::Logger.new('bookshelf')
|
193
|
-
# logger.info "Hello World"
|
194
|
-
#
|
195
|
-
# # => [bookshelf] [DEBUG] [2017-03-30 15:44:23 +0200] Hello World
|
196
|
-
#
|
197
|
-
# @example Logger level (Integer)
|
198
|
-
# require 'hanami/logger'
|
199
|
-
#
|
200
|
-
# logger = Hanami::Logger.new(level: 2) # WARN
|
201
|
-
# logger.info "Hello World"
|
202
|
-
# # => true
|
203
|
-
#
|
204
|
-
# logger.info "Hello World"
|
205
|
-
# # => true
|
206
|
-
#
|
207
|
-
# logger.warn "Hello World"
|
208
|
-
# # => [Hanami] [WARN] [2017-03-30 16:00:48 +0200] Hello World
|
209
|
-
#
|
210
|
-
# @example Logger level (Constant)
|
211
|
-
# require 'hanami/logger'
|
212
|
-
#
|
213
|
-
# logger = Hanami::Logger.new(level: Hanami::Logger::WARN)
|
214
|
-
# logger.info "Hello World"
|
215
|
-
# # => true
|
216
|
-
#
|
217
|
-
# logger.info "Hello World"
|
218
|
-
# # => true
|
219
|
-
#
|
220
|
-
# logger.warn "Hello World"
|
221
|
-
# # => [Hanami] [WARN] [2017-03-30 16:00:48 +0200] Hello World
|
222
|
-
#
|
223
|
-
# @example Logger level (String)
|
224
|
-
# require 'hanami/logger'
|
225
|
-
#
|
226
|
-
# logger = Hanami::Logger.new(level: 'warn')
|
227
|
-
# logger.info "Hello World"
|
228
|
-
# # => true
|
229
|
-
#
|
230
|
-
# logger.info "Hello World"
|
231
|
-
# # => true
|
232
|
-
#
|
233
|
-
# logger.warn "Hello World"
|
234
|
-
# # => [Hanami] [WARN] [2017-03-30 16:00:48 +0200] Hello World
|
235
|
-
#
|
236
|
-
# @example Use a file
|
237
|
-
# require 'hanami/logger'
|
238
|
-
#
|
239
|
-
# logger = Hanami::Logger.new(stream: "development.log")
|
240
|
-
# logger.info "Hello World"
|
241
|
-
#
|
242
|
-
# # => true
|
243
|
-
#
|
244
|
-
# File.read("development.log")
|
245
|
-
# # =>
|
246
|
-
# # # Logfile created on 2017-03-30 15:52:48 +0200 by logger.rb/56815
|
247
|
-
# # [Hanami] [DEBUG] [2017-03-30 15:52:54 +0200] Hello World
|
248
|
-
#
|
249
|
-
# @example Period rotation
|
250
|
-
# require 'hanami/logger'
|
251
|
-
#
|
252
|
-
# # Rotate daily
|
253
|
-
# logger = Hanami::Logger.new('bookshelf', 'daily', stream: 'development.log')
|
254
|
-
#
|
255
|
-
# @example File size rotation
|
256
|
-
# require 'hanami/logger'
|
257
|
-
#
|
258
|
-
# # leave 10 old log files where the size is about 1,024,000 bytes
|
259
|
-
# logger = Hanami::Logger.new('bookshelf', 10, 1024000, stream: 'development.log')
|
260
|
-
#
|
261
|
-
# @example Use a StringIO
|
262
|
-
# require 'hanami/logger'
|
263
|
-
#
|
264
|
-
# stream = StringIO.new
|
265
|
-
# logger = Hanami::Logger.new(stream: stream)
|
266
|
-
# logger.info "Hello World"
|
267
|
-
#
|
268
|
-
# # => true
|
269
|
-
#
|
270
|
-
# stream.rewind
|
271
|
-
# stream.read
|
272
|
-
#
|
273
|
-
# # => "[Hanami] [DEBUG] [2017-03-30 15:55:22 +0200] Hello World\n"
|
274
|
-
#
|
275
|
-
# @example JSON formatter
|
276
|
-
# require 'hanami/logger'
|
277
|
-
#
|
278
|
-
# logger = Hanami::Logger.new(formatter: :json)
|
279
|
-
# logger.info "Hello World"
|
280
|
-
#
|
281
|
-
# # => {"app":"Hanami","severity":"DEBUG","time":"2017-03-30T13:57:59Z","message":"Hello World"}
|
282
|
-
# rubocop:disable Lint/SuppressedException
|
283
|
-
# rubocop:disable Metrics/ParameterLists
|
284
|
-
def initialize(application_name = nil, *args, stream: $stdout, level: DEBUG, formatter: nil, filter: [], colorizer: nil) # rubocop:disable Layout/LineLength
|
285
|
-
begin
|
286
|
-
Utils::Files.mkdir_p(stream)
|
287
|
-
rescue TypeError
|
288
|
-
end
|
289
|
-
|
290
|
-
super(stream, *args)
|
291
|
-
|
292
|
-
@level = _level(level)
|
293
|
-
@stream = stream
|
294
|
-
@application_name = application_name
|
295
|
-
@formatter = Formatter.fabricate(formatter, self.application_name, filter, lookup_colorizer(colorizer))
|
296
|
-
end
|
297
|
-
|
298
|
-
# rubocop:enable Metrics/ParameterLists
|
299
|
-
# rubocop:enable Lint/SuppressedException
|
300
|
-
|
301
|
-
# Returns the current application name, this is used for tagging purposes
|
302
|
-
#
|
303
|
-
# @return [String] the application name
|
304
|
-
#
|
305
|
-
# @since 0.5.0
|
306
|
-
def application_name
|
307
|
-
@application_name || _application_name_from_namespace || _default_application_name
|
308
|
-
end
|
309
|
-
|
310
|
-
# @since 0.8.0
|
311
|
-
# @api private
|
312
|
-
def level=(value)
|
313
|
-
super _level(value)
|
314
|
-
end
|
315
|
-
|
316
|
-
# Closes the logging stream if this stream isn't an STDOUT
|
317
|
-
#
|
318
|
-
# @since 0.8.0
|
319
|
-
def close
|
320
|
-
super unless [STDOUT, $stdout].include?(@stream) # rubocop:disable Style/GlobalStdStream
|
321
|
-
end
|
322
|
-
|
323
|
-
private
|
324
|
-
|
325
|
-
# @since 0.5.0
|
326
|
-
# @api private
|
327
|
-
def _application_name_from_namespace
|
328
|
-
class_name = self.class.name
|
329
|
-
namespace = Utils::String.namespace(class_name)
|
330
|
-
|
331
|
-
class_name != namespace and return namespace
|
332
|
-
end
|
333
|
-
|
334
|
-
# @since 0.5.0
|
335
|
-
# @api private
|
336
|
-
def _default_application_name
|
337
|
-
DEFAULT_APPLICATION_NAME
|
338
|
-
end
|
339
|
-
|
340
|
-
# @since 0.8.0
|
341
|
-
# @api private
|
342
|
-
def _level(level)
|
343
|
-
self.class.level(level)
|
344
|
-
end
|
345
|
-
|
346
|
-
# @since 1.2.0
|
347
|
-
# @api private
|
348
|
-
def lookup_colorizer(colorizer)
|
349
|
-
return NullColorizer.new if colorizer == false
|
350
|
-
|
351
|
-
colorizer || (tty? ? Colorizer : NullColorizer).new
|
352
|
-
end
|
353
|
-
|
354
|
-
# @since 1.2.0
|
355
|
-
# @api private
|
356
|
-
def tty?
|
357
|
-
return false if @logdev.nil?
|
358
|
-
|
359
|
-
@logdev.dev.tty?
|
360
|
-
end
|
361
|
-
end
|
362
|
-
end
|
@@ -1,141 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Hanami
|
4
|
-
module Utils
|
5
|
-
# BasicObject
|
6
|
-
#
|
7
|
-
# @since 0.3.5
|
8
|
-
class BasicObject < ::BasicObject
|
9
|
-
# Lookups constants at the top-level namespace, if they are missing in the
|
10
|
-
# current context.
|
11
|
-
#
|
12
|
-
# @param name [Symbol] the constant name
|
13
|
-
#
|
14
|
-
# @return [Object, Module] the constant
|
15
|
-
#
|
16
|
-
# @raise [NameError] if the constant cannot be found
|
17
|
-
#
|
18
|
-
# @since 1.3.4
|
19
|
-
# @api private
|
20
|
-
#
|
21
|
-
# @see https://ruby-doc.org/core/Module.html#method-i-const_missing
|
22
|
-
def self.const_missing(name)
|
23
|
-
::Object.const_get(name)
|
24
|
-
end
|
25
|
-
|
26
|
-
# Returns the class for debugging purposes.
|
27
|
-
#
|
28
|
-
# @since 0.3.5
|
29
|
-
#
|
30
|
-
# @see http://ruby-doc.org/core/Object.html#method-i-class
|
31
|
-
def class
|
32
|
-
(class << self; self; end).superclass
|
33
|
-
end
|
34
|
-
|
35
|
-
# Bare minimum inspect for debugging purposes.
|
36
|
-
#
|
37
|
-
# @return [String] the inspect string
|
38
|
-
#
|
39
|
-
# @since 0.3.5
|
40
|
-
#
|
41
|
-
# @see http://ruby-doc.org/core/Object.html#method-i-inspect
|
42
|
-
def inspect
|
43
|
-
"#<#{self.class}:#{'0x0000%x' % (__id__ << 1)}#{__inspect}>"
|
44
|
-
end
|
45
|
-
|
46
|
-
# @!macro [attach] instance_of?(class)
|
47
|
-
#
|
48
|
-
# Determines if self is an instance of given class or module
|
49
|
-
#
|
50
|
-
# @param class [Class,Module] the class of module to verify
|
51
|
-
#
|
52
|
-
# @return [TrueClass,FalseClass] the result of the check
|
53
|
-
#
|
54
|
-
# @raise [TypeError] if the given argument is not of the expected types
|
55
|
-
#
|
56
|
-
# @since 1.3.2
|
57
|
-
#
|
58
|
-
# @see http://ruby-doc.org/core/Object.html#method-i-instance_of-3F
|
59
|
-
define_method :instance_of?, ::Object.instance_method(:instance_of?)
|
60
|
-
|
61
|
-
# @!macro [attach] is_a?(class)
|
62
|
-
#
|
63
|
-
# Determines if self is of the type of the object class or module
|
64
|
-
#
|
65
|
-
# @param class [Class,Module] the class of module to verify
|
66
|
-
#
|
67
|
-
# @return [TrueClass,FalseClass] the result of the check
|
68
|
-
#
|
69
|
-
# @raise [TypeError] if the given argument is not of the expected types
|
70
|
-
#
|
71
|
-
# @since 1.3.2
|
72
|
-
#
|
73
|
-
# @see http://ruby-doc.org/core/Object.html#method-i-is_a-3F
|
74
|
-
define_method :is_a?, ::Object.instance_method(:is_a?)
|
75
|
-
|
76
|
-
# @!macro [attach] kind_of?(class)
|
77
|
-
#
|
78
|
-
# Determines if self is of the kind of the object class or module
|
79
|
-
#
|
80
|
-
# @param class [Class,Module] the class of module to verify
|
81
|
-
#
|
82
|
-
# @return [TrueClass,FalseClass] the result of the check
|
83
|
-
#
|
84
|
-
# @raise [TypeError] if the given argument is not of the expected types
|
85
|
-
#
|
86
|
-
# @since 1.3.2
|
87
|
-
#
|
88
|
-
# @see http://ruby-doc.org/core/Object.html#method-i-kind_of-3F
|
89
|
-
define_method :kind_of?, ::Object.instance_method(:kind_of?)
|
90
|
-
|
91
|
-
# Alias for __id__
|
92
|
-
#
|
93
|
-
# @return [Fixnum] the object id
|
94
|
-
#
|
95
|
-
# @since 0.9.0
|
96
|
-
#
|
97
|
-
# @see http://ruby-doc.org/core/Object.html#method-i-object_id
|
98
|
-
def object_id
|
99
|
-
__id__
|
100
|
-
end
|
101
|
-
|
102
|
-
# Interface for pp
|
103
|
-
#
|
104
|
-
# @param printer [PP] the Pretty Printable printer
|
105
|
-
# @return [String] the pretty-printable inspection of the object
|
106
|
-
#
|
107
|
-
# @since 0.9.0
|
108
|
-
#
|
109
|
-
# @see https://ruby-doc.org/stdlib/libdoc/pp/rdoc/PP.html
|
110
|
-
def pretty_print(printer)
|
111
|
-
printer.text(inspect)
|
112
|
-
end
|
113
|
-
|
114
|
-
# Returns true if responds to the given method.
|
115
|
-
#
|
116
|
-
# @return [TrueClass,FalseClass] the result of the check
|
117
|
-
#
|
118
|
-
# @since 0.3.5
|
119
|
-
#
|
120
|
-
# @see http://ruby-doc.org/core-2.2.1/Object.html#method-i-respond_to-3F
|
121
|
-
def respond_to?(method_name, include_all = false)
|
122
|
-
respond_to_missing?(method_name, include_all)
|
123
|
-
end
|
124
|
-
|
125
|
-
private
|
126
|
-
|
127
|
-
# Must be overridden by descendants
|
128
|
-
#
|
129
|
-
# @since 0.3.5
|
130
|
-
# @api private
|
131
|
-
def respond_to_missing?(_method_name, _include_all)
|
132
|
-
::Kernel.raise ::NotImplementedError
|
133
|
-
end
|
134
|
-
|
135
|
-
# @since 0.3.5
|
136
|
-
# @api private
|
137
|
-
def __inspect
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|