hanami-utils 2.0.0.beta1 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1c3da2c837516bf458d208681a9183b4ce2255d4015d1ef436344b951f72127
4
- data.tar.gz: 1dd912dfe51da2149599514b70c1d1893651d09e2a2c6f65ffdce4b5142c7132
3
+ metadata.gz: e32b8748a32b673f476ffc41c81608f5e6d372f610e990594488c214e27fdfd1
4
+ data.tar.gz: 0e043561435c85f622bd8a1b1f341a5ad77b1359578fd00923c0ee19c6150b63
5
5
  SHA512:
6
- metadata.gz: d1fb0f77574208374688089528fc4e9479f17fe514d795c0407fd6cb65c3c14cd64aa5956bf90f9e29692042c784845ea3f27c0c6c0fc5fbcf52fb439f6ba557
7
- data.tar.gz: 5e5dd4627115e3d92f8fa5c19a323e645b5bc245e72a6156c40b449af68eed08b42148639f25a5cee98e5d2739504d9cb0bfb6dd7781f54e1ae554b77955bbd9
6
+ metadata.gz: dbedf69794dbd7ee0ae949ef77a2891fe29c5439feb7cb3c6e2e91b87b3fae16f74e6f624357e646cb68c47668120d5be0cc8e8961c198c75106f0636cb4373e
7
+ data.tar.gz: 615330821eadb25847032710fff58adab597281783b09767e92da9ecf3523cb511dff516ed5f6640d06b5d8d5cfaaa8c93ffcb45f1be5db520ec7ccdb058a84d
data/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  Ruby core extensions and class utilities for Hanami
4
4
 
5
+ ## v2.0.0.rc1 - 2022-11-08
6
+
7
+ ### Fixed
8
+
9
+ - [Benjamin Klotz] Ensure `Hanami::Utils::String.underscore` to replace `"."` (dot character) into underscore
10
+
11
+ ### Changed
12
+
13
+ - [Luca Guidi] Removed `Hanami::Logger` in favor of `Dry::Logger`
14
+
5
15
  ## v2.0.0.beta1 - 2022-07-20
6
16
 
7
17
  ### Changed
@@ -231,7 +231,7 @@ module Hanami
231
231
  string.gsub!(NAMESPACE_SEPARATOR, UNDERSCORE_SEPARATOR)
232
232
  string.gsub!(/([A-Z\d]+)([A-Z][a-z])/, UNDERSCORE_DIVISION_TARGET)
233
233
  string.gsub!(/([a-z\d])([A-Z])/, UNDERSCORE_DIVISION_TARGET)
234
- string.gsub!(/[[:space:]]|-/, UNDERSCORE_DIVISION_TARGET)
234
+ string.gsub!(/[[:space:]]|-|\./, UNDERSCORE_DIVISION_TARGET)
235
235
  string.downcase
236
236
  end
237
237
 
@@ -2,9 +2,7 @@
2
2
 
3
3
  module Hanami
4
4
  module Utils
5
- # Defines the version
6
- #
7
- # @since 0.1.0
8
- VERSION = "2.0.0.beta1"
5
+ # @api public
6
+ VERSION = "2.0.0.rc1"
9
7
  end
10
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta1
4
+ version: 2.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-20 00:00:00.000000000 Z
11
+ date: 2022-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-transformer
@@ -112,10 +112,6 @@ files:
112
112
  - README.md
113
113
  - hanami-utils.gemspec
114
114
  - lib/hanami-utils.rb
115
- - lib/hanami/logger.rb
116
- - lib/hanami/logger/colorizer.rb
117
- - lib/hanami/logger/filter.rb
118
- - lib/hanami/logger/formatter.rb
119
115
  - lib/hanami/middleware.rb
120
116
  - lib/hanami/utils.rb
121
117
  - lib/hanami/utils/blank.rb
@@ -1,105 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "logger"
4
- require "hanami/utils/shell_color"
5
-
6
- module Hanami
7
- class Logger < ::Logger
8
- # Null colorizer for logger streams that aren't a TTY (eg. files)
9
- #
10
- # @since 1.2.0
11
- # @api private
12
- class NullColorizer
13
- # @since 1.2.0
14
- # @api private
15
- def call(app, severity, datetime, _progname)
16
- ::Hash[
17
- app: app,
18
- severity: severity,
19
- time: datetime,
20
- ]
21
- end
22
- end
23
-
24
- # Hanami::Logger Default Colorizer
25
- #
26
- # This colorizer takes in parts of the log message and returns them with
27
- # proper shellcode to colorize when displayed to a tty.
28
- #
29
- # @since 1.2.0
30
- # @api private
31
- class Colorizer < NullColorizer
32
- def initialize(colors: COLORS)
33
- @colors = colors
34
- end
35
-
36
- # Colorize the inputs
37
- #
38
- # @param app [#to_s] the app name
39
- # @param severity [#to_s] log severity
40
- # @param datetime [#to_s] timestamp
41
- # @param _progname [#to_s] program name - ignored, accepted for
42
- # compatibility with Ruby's Logger
43
- #
44
- # @return [::Hash] an Hash containing the keys `:app`, `:severity`, and `:time`
45
- def call(app, severity, datetime, _progname)
46
- ::Hash[
47
- app: app(app),
48
- severity: severity(severity),
49
- time: datetime(datetime),
50
- ]
51
- end
52
-
53
- private
54
-
55
- # The colors defined for the three parts of the log message
56
- #
57
- # @since 1.2.0
58
- # @api private
59
- COLORS = ::Hash[
60
- app: :blue,
61
- datetime: :cyan,
62
- ].freeze
63
-
64
- # @since 1.2.0
65
- # @api private
66
- LEVELS = ::Hash[
67
- Hanami::Logger::DEBUG => :cyan,
68
- Hanami::Logger::INFO => :magenta,
69
- Hanami::Logger::WARN => :yellow,
70
- Hanami::Logger::ERROR => :red,
71
- Hanami::Logger::FATAL => :red,
72
- Hanami::Logger::UNKNOWN => :blue,
73
- ].freeze
74
-
75
- attr_reader :colors
76
-
77
- # @since 1.2.0
78
- # @api private
79
- def app(input)
80
- colorize(input, color: colors.fetch(:app, nil))
81
- end
82
-
83
- # @since 1.2.0
84
- # @api private
85
- def severity(input)
86
- color = LEVELS.fetch(Hanami::Logger.level(input), :gray)
87
- colorize(input, color: color)
88
- end
89
-
90
- # @since 1.2.0
91
- # @api private
92
- def datetime(input)
93
- colorize(input, color: colors.fetch(:datetime, nil))
94
- end
95
-
96
- # @since 1.2.0
97
- # @api private
98
- def colorize(message, color:)
99
- return message if color.nil?
100
-
101
- Hanami::Utils::ShellColor.call(message, color: color)
102
- end
103
- end
104
- end
105
- end
@@ -1,144 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "logger"
4
-
5
- module Hanami
6
- class Logger < ::Logger
7
- # Filtering logic
8
- #
9
- # @since 1.1.0
10
- # @api private
11
- class Filter
12
- # @since 1.3.7
13
- # @api private
14
- FILTERED_VALUE = "[FILTERED]"
15
-
16
- def initialize(filters = [], mask: FILTERED_VALUE)
17
- @filters = filters
18
- @mask = mask
19
- end
20
-
21
- # @since 1.1.0
22
- # @api private
23
- def call(params)
24
- _filter(_copy_params(params))
25
- end
26
-
27
- private
28
-
29
- # @since 1.1.0
30
- # @api private
31
- attr_reader :filters
32
-
33
- # @since 1.3.7
34
- # @api private
35
- attr_reader :mask
36
-
37
- # This is a simple deep merge to merge the original input
38
- # with the filtered hash which contains '[FILTERED]' string.
39
- #
40
- # It only deep-merges if the conflict values are both hashes.
41
- #
42
- # @since 1.3.7
43
- # @api private
44
- def _deep_merge(original_hash, filtered_hash)
45
- original_hash.merge(filtered_hash) do |_key, original_item, filtered_item|
46
- if original_item.is_a?(Hash) && filtered_item.is_a?(Hash)
47
- _deep_merge(original_item, filtered_item)
48
- elsif filtered_item == FILTERED_VALUE
49
- filtered_item
50
- else
51
- original_item
52
- end
53
- end
54
- end
55
-
56
- # @since 1.1.0
57
- # @api private
58
- def _filtered_keys(hash)
59
- _key_paths(hash).select { |key| filters.any? { |filter| key =~ %r{(\.|\A)#{filter}(\.|\z)} } }
60
- end
61
-
62
- # @since 1.1.0
63
- # @api private
64
- def _key_paths(hash, base = nil)
65
- hash.inject([]) do |results, (k, v)|
66
- results + (_key_paths?(v) ? _key_paths(v, _build_path(base, k)) : [_build_path(base, k)])
67
- end
68
- end
69
-
70
- # @since 1.1.0
71
- # @api private
72
- def _build_path(base, key)
73
- [base, key.to_s].compact.join(".")
74
- end
75
-
76
- # @since 1.1.0
77
- # @api private
78
- def _actual_keys(hash, keys)
79
- search_in = hash
80
-
81
- keys.inject([]) do |res, key|
82
- correct_key = search_in.key?(key.to_sym) ? key.to_sym : key
83
- search_in = search_in[correct_key]
84
- res + [correct_key]
85
- end
86
- end
87
-
88
- # Check if the given value can be iterated (`Enumerable`) and that isn't a `File`.
89
- # This is useful to detect closed `Tempfiles`.
90
- #
91
- # @since 1.3.5
92
- # @api private
93
- #
94
- # @see https://github.com/hanami/utils/pull/342
95
- def _key_paths?(value)
96
- value.is_a?(Enumerable) && !value.is_a?(File)
97
- end
98
-
99
- # @since 1.3.7
100
- # @api private
101
- def _deep_dup(hash)
102
- hash.transform_values do |value|
103
- if value.is_a?(Hash)
104
- _deep_dup(value)
105
- else
106
- _key_paths?(value) ? value.dup : value
107
- end
108
- end
109
- end
110
-
111
- # @since 1.3.7
112
- # @api private
113
- def _copy_params(params)
114
- case params
115
- when Hash
116
- _deep_dup(params)
117
- when Array
118
- params.map { |hash| _deep_dup(hash) }
119
- end
120
- end
121
-
122
- # @since 1.3.7
123
- # @api private
124
- def _filter_hash(hash)
125
- _filtered_keys(hash).each do |key|
126
- *keys, last = _actual_keys(hash, key.split("."))
127
- keys.inject(hash, :fetch)[last] = mask
128
- end
129
- hash
130
- end
131
-
132
- # @since 1.3.7
133
- # @api private
134
- def _filter(params)
135
- case params
136
- when Hash
137
- _filter_hash(params)
138
- when Array
139
- params.map { |hash| _filter_hash(hash) }
140
- end
141
- end
142
- end
143
- end
144
- end
@@ -1,183 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "set"
4
- require "json"
5
- require "logger"
6
- require "hanami/utils/json"
7
- require "hanami/utils/class_attribute"
8
- require "hanami/utils/query_string"
9
-
10
- module Hanami
11
- class Logger < ::Logger
12
- # Hanami::Logger default formatter.
13
- # This formatter returns string in key=value format.
14
- #
15
- # @since 0.5.0
16
- # @api private
17
- #
18
- # @see http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger/Formatter.html
19
- class Formatter < ::Logger::Formatter
20
- require "hanami/logger/filter"
21
- require "hanami/logger/colorizer"
22
-
23
- # @since 0.8.0
24
- # @api private
25
- SEPARATOR = " "
26
-
27
- # @since 0.8.0
28
- # @api private
29
- NEW_LINE = $/
30
-
31
- # @since 1.0.0
32
- # @api private
33
- RESERVED_KEYS = %i[app severity time].freeze
34
-
35
- include Utils::ClassAttribute
36
-
37
- class_attribute :subclasses
38
- self.subclasses = Set.new
39
-
40
- def self.fabricate(formatter, application_name, filters, colorizer)
41
- fabricated_formatter = _formatter_instance(formatter)
42
-
43
- fabricated_formatter.application_name = application_name
44
- fabricated_formatter.filter = Filter.new(filters)
45
- fabricated_formatter.colorizer = colorizer
46
-
47
- fabricated_formatter
48
- end
49
-
50
- # @api private
51
- def self.inherited(subclass)
52
- super
53
- subclasses << subclass
54
- end
55
-
56
- # @api private
57
- def self.eligible?(name)
58
- name == :default
59
- end
60
-
61
- # @api private
62
- # @since 1.1.0
63
- def self._formatter_instance(formatter)
64
- case formatter
65
- when Symbol
66
- (subclasses.find { |s| s.eligible?(formatter) } || self).new
67
- when nil
68
- new
69
- else
70
- formatter
71
- end
72
- end
73
- private_class_method :_formatter_instance
74
-
75
- # @since 0.5.0
76
- # @api private
77
- attr_writer :application_name
78
-
79
- # @since 1.0.0
80
- # @api private
81
- attr_reader :application_name
82
-
83
- # @since 1.2.0
84
- # @api private
85
- attr_writer :filter
86
-
87
- # @since 1.2.0
88
- # @api private
89
- attr_writer :colorizer
90
-
91
- # @since 0.5.0
92
- # @api private
93
- #
94
- # @see http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger/Formatter.html#method-i-call
95
- def call(severity, time, progname, msg)
96
- colorized = @colorizer.call(application_name, severity, time, progname)
97
- colorized.merge!(_message_hash(msg))
98
-
99
- _format(colorized)
100
- end
101
-
102
- private
103
-
104
- # @since 0.8.0
105
- # @api private
106
- def _message_hash(message)
107
- case message
108
- when ::Hash
109
- @filter.call(message)
110
- when Exception
111
- ::Hash[
112
- message: message.message,
113
- backtrace: message.backtrace || [],
114
- error: message.class
115
- ]
116
- else
117
- ::Hash[message: message]
118
- end
119
- end
120
-
121
- # @since 0.8.0
122
- # @api private
123
- def _format(hash)
124
- "#{_line_front_matter(hash.delete(:app), hash.delete(:severity), hash.delete(:time))}#{SEPARATOR}#{_format_message(hash)}" # rubocop:disable Layout/LineLength
125
- end
126
-
127
- # @since 1.2.0
128
- # @api private
129
- def _line_front_matter(*args)
130
- args.map { |string| "[#{string}]" }.join(SEPARATOR)
131
- end
132
-
133
- # @since 1.2.0
134
- # @api private
135
- def _format_message(hash)
136
- if hash.key?(:error)
137
- _format_error(hash)
138
- elsif hash.key?(:params)
139
- "#{hash.values.join(SEPARATOR)}#{NEW_LINE}"
140
- else
141
- "#{Utils::QueryString.call(hash[:message] || hash)}#{NEW_LINE}"
142
- end
143
- end
144
-
145
- # @since 1.2.0
146
- # @api private
147
- def _format_error(hash)
148
- result = [hash[:error], hash[:message]].compact.join(": ").concat(NEW_LINE)
149
- hash[:backtrace].each do |line|
150
- result << "from #{line}#{NEW_LINE}"
151
- end
152
-
153
- result
154
- end
155
- end
156
-
157
- # Hanami::Logger JSON formatter.
158
- # This formatter returns string in JSON format.
159
- #
160
- # @since 0.5.0
161
- # @api private
162
- class JSONFormatter < Formatter
163
- # @api private
164
- def self.eligible?(name)
165
- name == :json
166
- end
167
-
168
- # @api private
169
- def colorizer=(*)
170
- @colorizer = NullColorizer.new
171
- end
172
-
173
- private
174
-
175
- # @since 0.8.0
176
- # @api private
177
- def _format(hash)
178
- hash[:time] = hash[:time].utc.iso8601
179
- Hanami::Utils::Json.generate(hash) + NEW_LINE
180
- end
181
- end
182
- end
183
- end
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