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.
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