cogger 0.13.1 → 0.14.0

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: 590801ee49ce6abe0d7d22d1d66732a10e41e384eb5018394b1f9de0c4ae1b4e
4
- data.tar.gz: 6707a9761a959c480f2ae2aa629b5c826248322880e428f92d3ce9b625e2fd26
3
+ metadata.gz: e943adc7eaeab019242b860b3c66da64e24c52cfe756c242d3b92de480586503
4
+ data.tar.gz: ad0f47de612ca8fde2eff91593e32e5ed7cfaad13f77b62b6c3aebcbe18a9bc6
5
5
  SHA512:
6
- metadata.gz: 3972438237dafd8409de8cc2ae0a9e8eec351cd10f60fced84691b2b13998d3fec29a2403adf495a28a732d65c66ebc825f53d2f76b990966bcfa4d70ef629db
7
- data.tar.gz: 3ab12b7c97dedd47ec5630db725093ba7f15679640ce20afbf6ca396a4655e2e5a837b26021750f54a93ba38b885acd7f0face409cb76e309877b472695b34db
6
+ metadata.gz: 52c552fcb5ae45c4893bb84e427691504d49b987904734e81ce68b3dac889544f30c040e547d7a99d17c18429c732651a63b7628d11c00de6ba506985ea7c493
7
+ data.tar.gz: 4d7d3c410af6800bbcc6c2d35d969d06e5752c9a326010e55c8049ba91e5657aa808a04cb82cbaf294f077630a61c01ff4dcbed156abf54696a017cd59955a00
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -2,10 +2,11 @@
2
2
  :toclevels: 5
3
3
  :figure-caption!:
4
4
 
5
- :tone_link: link:https://alchemists.io/projects/tone[Tone]
5
+ :format_link: link:https://ruby-doc.org/3.2.2/format_specifications_rdoc.html[String Format Specification]
6
6
  :logger_link: link:https://rubyapi.org/o/s?q=Logger[Logger]
7
- :format_link: link:https://ruby-doc.org/3.2.1/format_specifications_rdoc.html[Format Specification]
8
7
  :pattern_matching_link: link:https://alchemists.io/articles/ruby_pattern_matching[pattern matching]
8
+ :rack_link: link:https://github.com/rack/rack[Rack]
9
+ :tone_link: link:https://alchemists.io/projects/tone[Tone]
9
10
 
10
11
  = Cogger
11
12
 
@@ -23,6 +24,7 @@ toc::[]
23
24
  * Provides multiple streams so you can log the same information to several outputs at once.
24
25
  * Provides global and individual log entry tagging.
25
26
  * Provides filtering of sensitive information.
27
+ * Provides {rack_link} middleware for HTTP request logging.
26
28
 
27
29
  == Screenshots
28
30
 
@@ -44,7 +46,7 @@ image::https://alchemists.io/images/projects/cogger/screenshots/detail.png[Detai
44
46
 
45
47
  *JSON*
46
48
 
47
- image::https://alchemists.io/images/projects/cogger/screenshots/json.png[JSON,width=962,height=297]
49
+ image::https://alchemists.io/images/projects/cogger/screenshots/json.png[JSON,width=1002,height=290]
48
50
 
49
51
  *Rack*
50
52
 
@@ -156,51 +158,32 @@ logger = Cogger.new id: :demo,
156
158
  suffix: "%Y"
157
159
  ----
158
160
 
159
- === Inspection
161
+ === Levels
160
162
 
161
- Each instance can be inspected via the `#inspect` message:
163
+ Supported levels can be obtained via `Cogger::LEVELS`. Example:
162
164
 
163
165
  [source,ruby]
164
166
  ----
165
- logger = Cogger.new
166
- logger.inspect
167
-
168
- # "#<Cogger::Hub @id=console,
169
- # @io=IO,
170
- # @level=1,
171
- # @formatter=Cogger::Formatters::Emoji,
172
- # @tags=[],
173
- # @mode=false,
174
- # @age=0,
175
- # @size=1048576,
176
- # @suffix=\"%Y-%m-%d\",
177
- # @entry=Cogger::Entry,
178
- # @logger=Logger>"
167
+ Cogger::LEVELS
168
+ # ["debug", "info", "warn", "error", "fatal", "unknown"]
179
169
  ----
180
170
 
181
- You can also look at individual attributes:
171
+ === Environment
182
172
 
183
- [source,ruby]
184
- ----
185
- logger = Cogger.new
173
+ You can use your environment to define the desired default log level. The default log level is: `"info"`. Although, you can set the log level to any of the following:
186
174
 
187
- logger.id # "console"
188
- logger.io # #<IO:<STDOUT>>
189
- logger.tags # []
190
- logger.mode # false
191
- logger.age # 0
192
- logger.size # 1048576
193
- logger.suffix # "%Y-%m-%d"
194
-
195
- logger.level # 1
196
- logger.formatter # Cogger::Formatters::Emoji
197
- logger.debug? # false
198
- logger.info? # true
199
- logger.warn? # true
200
- logger.error? # true
201
- logger.fatal? # true
175
+ [source,bash]
176
+ ----
177
+ export LOG_LEVEL=debug
178
+ export LOG_LEVEL=info
179
+ export LOG_LEVEL=warn
180
+ export LOG_LEVEL=error
181
+ export LOG_LEVEL=fatal
182
+ export LOG_LEVEL=unknown
202
183
  ----
203
184
 
185
+ While downcase is preferred for the log level, you can use upcased values as well. If the `LOG_LEVEL` environment variable is not set, `Cogger` will fall back to `"info"` unless overwritten during initialization. Example: `Cogger.new level: :debug`. Otherwise, an invalid log level will result in an `ArgumentError`.
186
+
204
187
  === Mutations
205
188
 
206
189
  Each instance can be mutated using the following messages:
@@ -222,26 +205,9 @@ logger.level = Logger::WARN # 2
222
205
 
223
206
  Please see the {logger_link} documentation for more information.
224
207
 
225
- === Environment
226
-
227
- The default log level is `INFO` but can be customized via your environment. For instance, you could
228
- set the logging level to any of the following:
229
-
230
- [source,bash]
231
- ----
232
- export LOG_LEVEL=DEBUG
233
- export LOG_LEVEL=INFO
234
- export LOG_LEVEL=WARN
235
- export LOG_LEVEL=ERROR
236
- export LOG_LEVEL=FATAL
237
- export LOG_LEVEL=UNKNOWN
238
- ----
239
-
240
- By default, `Cogger` will automatically use whatever is set via the `LOG_LEVEL` environment variable unless overwritten during initialization.
241
-
242
208
  === Templates
243
209
 
244
- Templates are used by all formatters and adhere to {format_link} as used by `Kernel#format`. All specifiers, flags, width, and precision are supported except for the following restrictions:
210
+ Templates are used by all formatters and adhere to the {format_link} as used by `Kernel#format`. All specifiers, flags, width, and precision are supported except for the following restrictions:
245
211
 
246
212
  - Use of _reference by name_ is required which means `%<demo>s` is allowed but `%{demo}` is not. This is because _reference by name_ is required for regular expressions and/or {pattern_matching_link}.
247
213
  - Use of the `n$` flag is prohibited because this isn't compatible with the above.
@@ -539,16 +505,16 @@ logger.warn "Demo"
539
505
 
540
506
  ==== JSON
541
507
 
542
- This formatter is similar in behavior to the _simple_ formatter except the template allows you to _order_ the layout of your keys. All other template information is ignored, only the order of your template keys matters. Example:
508
+ This formatter is similar in behavior to the _simple_ formatter except that date/time defaults to UTC, is formattted according to link:https://datatracker.ietf.org/doc/html/rfc3339[RFC 3339] using millisecond precision, and the template allows you to _order_ the layout of your keys. All other template information is ignored, only the order of your template keys matters. Example:
543
509
 
544
510
  *Default Order*
545
511
 
546
512
  [source,ruby]
547
513
  ----
548
514
  logger = Cogger.new formatter: :json
549
- logger.info verb: "GET", path: "/"
550
515
 
551
- # {"id":"console","severity":"INFO","at":"2023-04-10 09:03:55 -0600","verb":"GET","path":"/"}
516
+ logger.info verb: "GET", path: "/"
517
+ # {"id":"console","severity":"INFO","at":"2023-12-10T18:42:32.844+00:00","verb":"GET","path":"/"}
552
518
  ----
553
519
 
554
520
  *Custom Order*
@@ -556,9 +522,9 @@ logger.info verb: "GET", path: "/"
556
522
  [source,ruby]
557
523
  ----
558
524
  logger = Cogger.new formatter: Cogger::Formatters::JSON.new("%<severity>s %<verb>s")
559
- logger.info verb: "GET", path: "/"
560
525
 
561
- # {"severity":"INFO","verb":"GET","id":"console","at":"2023-04-10 09:05:03 -0600","path":"/"}
526
+ logger.info verb: "GET", path: "/"
527
+ # {"severity":"INFO","verb":"GET","id":"console","at":"2023-12-10T18:43:03.805+00:00","path":"/"}
562
528
  ----
563
529
 
564
530
  Your template can be a full or partial match of keys. If no keys match what is defined in the template, then the original order of the keys will be used instead.
@@ -567,29 +533,29 @@ You can always supply a message as your first argument -- or specify it by using
567
533
 
568
534
  [source,ruby]
569
535
  ----
570
- logger = Cogger.new formatter: json
536
+ logger = Cogger.new formatter: :json
571
537
 
572
538
  logger.info "Demo"
573
- # {"id":"console","severity":"INFO","at":"2023-10-18 19:38:55 -0600","message":"Demo"}
539
+ # {"id":"console","severity":"INFO","at":"2023-12-10T18:43:42.029+00:00","message":"Demo"}
574
540
 
575
- logger.info messsage: "Demo"
576
- {"id":"console","severity":"INFO","at":"2023-10-18 19:39:19 -0600","messsage":"Demo"}
541
+ logger.info message: "Demo"
542
+ # {"id":"console","severity":"INFO","at":"2023-12-10T18:44:14.568+00:00","message":"Demo"}
577
543
  ----
578
544
 
579
- When tags are provided, the `:tags` key will appear in the output depending on whether you are using _single tags_. If hash tags are used, they'll show up as additional attributes in the outout. Here's an example where a mix of single and hash keys are used:
545
+ When tags are provided, the `:tags` key will appear in the output depending on whether you are using _single tags_. If hash tags are used, they'll show up as additional attributes in the output. Here's an example where a mix of single and hash keys are used:
580
546
 
581
547
  [source,ruby]
582
548
  ----
583
549
  logger = Cogger.new formatter: :json
584
550
 
585
551
  logger.info "Demo", tags: ["WEB", "PRIMARY", {service: :api, demo: true}]
586
-
587
552
  # {
588
553
  # "id":"console",
589
554
  # "severity":"INFO",
590
- # "at":"2023-10-18 19:47:11 -0600",
555
+ # "at":"2023-12-10T18:44:32.723+00:00",
591
556
  # "message":"Demo",
592
- # "tags":["WEB","PRIMARY"],
557
+ # "tags":["WEB",
558
+ # "PRIMARY"],
593
559
  # "service":"api",
594
560
  # "demo":true
595
561
  # }
@@ -789,6 +755,89 @@ logger.info "Demo"
789
755
  # Demo
790
756
  ----
791
757
 
758
+ === Rack
759
+
760
+ {rack_link} is _implicitly_ supported which means your middleware _must be_ Rack-based and _must require_ the Rack gem since `Cogger::Rack::Logger` doesn't _explicitly_ require Rack by default. If these requirements are met then, to add HTTP request logging, you only need to use it. Example:
761
+
762
+ [source,ruby]
763
+ ----
764
+ use Rails::Rack::Logger
765
+ ----
766
+
767
+ Like any other {rack_link} middleware, `Rails::Rack::Logger` is initialized with your current application along with any custom options. Example:
768
+
769
+ [source,ruby]
770
+ ----
771
+ middleware = Cogger::Rack::Logger.new application
772
+ middleware.call environment
773
+ ----
774
+
775
+ The following defaults are supported:
776
+
777
+ [source,ruby]
778
+ ----
779
+ Cogger::Rack::Logger::DEFAULTS
780
+
781
+ # {
782
+ # logger: Cogger.new(formatter: :json),
783
+ # timer: Cogger::Time::Span.new,
784
+ # :key_map => {
785
+ # :verb => "REQUEST_METHOD",
786
+ # :ip => "REMOTE_ADDR",
787
+ # :path => "PATH_INFO",
788
+ # :params => "QUERY_STRING",
789
+ # :length => "CONTENT_LENGTH"
790
+ # }
791
+ # }
792
+ ----
793
+
794
+ The defaults can be customized. Example:
795
+
796
+ [source,]
797
+ ----
798
+ Cogger::Rack::Logger.new application, {logger: Cogger.new}
799
+ ----
800
+
801
+ In the above example, we see `Cogger.new` overrides the default `Cogger.new(formatter: :json)`. In practice, you'll want to customize the logger and key map. Here's how each default is configured to be used:
802
+
803
+ * `logger`: Defaults to JSON formatted logging but you'll want to pass in the same logger as globally configured for your application in order to reduce duplication and save on memory.
804
+ * `timer`: The timer calculates the total duration of the request and defaults to nanosecond precision but you can swap this out with your own timer if desired. When providing your own timer, the only requirement is that the timer respond to the `#call` message with a block.
805
+ * `key_map`: The key map is used to map the HTTP Headers to keys (i.e. tags) used in the log output. You can use the existing key map, provide your own, or use a hybrid.
806
+
807
+ Once this middleware is configured and used within your application, you'll start seeing the following kinds of log entries (depending on your specific settings and tags used):
808
+
809
+ [source,json]
810
+ ----
811
+ {
812
+ "id":"demo",
813
+ "severity":"INFO",
814
+ "at":"2023-12-10T22:37:06.341+00:00",
815
+ "verb":"GET",
816
+ "ip":"127.0.0.1",
817
+ "path":"/dashboard",
818
+ "status":200,
819
+ "duration":83,
820
+ "unit":"ms"
821
+ }
822
+ ----
823
+
824
+ *Rails*
825
+
826
+ To build upon the above -- and if using the Rails framework -- you could configure your application as follows:
827
+
828
+ [source,ruby]
829
+ ----
830
+ # demo/config/application.rb
831
+ module Demo
832
+ class Application < Rails::Application
833
+ config.logger = Cogger.new id: "demo", formatter: :json,
834
+ config.middleware.swap Rails::Rack::Logger, Cogger::Rack::Logger, {logger: config.logger}
835
+ end
836
+ end
837
+ ----
838
+
839
+ The above defines `Cogger` as the default logger for the entire application, ensures `Cogger::Rack::Logger` is configured to use it and swaps itself with the default `Rails::Rack::Logger` so you don't have two pieces of middleware logging the same HTTP requests.
840
+
792
841
  === Defaults
793
842
 
794
843
  Should you ever need quick access to the defaults, you can use:
@@ -800,6 +849,51 @@ Cogger.defaults
800
849
 
801
850
  This is primarily meant for display/inspection purposes, though.
802
851
 
852
+ === Inspection
853
+
854
+ Each instance can be inspected via the `#inspect` message:
855
+
856
+ [source,ruby]
857
+ ----
858
+ logger = Cogger.new
859
+ logger.inspect
860
+
861
+ # "#<Cogger::Hub @id=console,
862
+ # @io=IO,
863
+ # @level=1,
864
+ # @formatter=Cogger::Formatters::Emoji,
865
+ # @tags=[],
866
+ # @mode=false,
867
+ # @age=0,
868
+ # @size=1048576,
869
+ # @suffix=\"%Y-%m-%d\",
870
+ # @entry=Cogger::Entry,
871
+ # @logger=Logger>"
872
+ ----
873
+
874
+ You can also look at individual attributes:
875
+
876
+ [source,ruby]
877
+ ----
878
+ logger = Cogger.new
879
+
880
+ logger.id # "console"
881
+ logger.io # #<IO:<STDOUT>>
882
+ logger.tags # []
883
+ logger.mode # false
884
+ logger.age # 0
885
+ logger.size # 1048576
886
+ logger.suffix # "%Y-%m-%d"
887
+
888
+ logger.level # 1
889
+ logger.formatter # Cogger::Formatters::Emoji
890
+ logger.debug? # false
891
+ logger.info? # true
892
+ logger.warn? # true
893
+ logger.error? # true
894
+ logger.fatal? # true
895
+ ----
896
+
803
897
  === Testing
804
898
 
805
899
  When testing, you might find it convenient to rewind and read from the stream you are writing too (i.e. `IO`, `StringIO`, `File`). For instance, here is an example where I inject the default logger into my `Demo` class and then, for testing purposes, create a new logger to be injected which only logs to `StringIO` so I can buffer and read for test verification:
@@ -852,7 +946,7 @@ You can also use the IRB console for direct access to all objects:
852
946
  bin/console
853
947
  ----
854
948
 
855
- Lastly, there is a `bin/show` script which displays multiple log formats for quick visual reference. This is the same script used to generate the screenshots shown at the top of this document.
949
+ Lastly, there is a `bin/demo` script which displays multiple log formats for quick visual reference. This is the same script used to generate the screenshots shown at the top of this document.
856
950
 
857
951
  == Tests
858
952
 
data/cogger.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "cogger"
5
- spec.version = "0.13.1"
5
+ spec.version = "0.14.0"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://alchemists.io/projects/cogger"
@@ -20,7 +20,7 @@ module Cogger
20
20
  ) do
21
21
  def initialize id: Program.call,
22
22
  io: $stdout,
23
- level: Logger.const_get(ENV.fetch("LOG_LEVEL", "INFO")),
23
+ level: Level.call,
24
24
  formatter: Formatters::Emoji.new,
25
25
  tags: Core::EMPTY_ARRAY,
26
26
  mode: false,
data/lib/cogger/entry.rb CHANGED
@@ -6,8 +6,9 @@ module Cogger
6
6
  # Defines a log entry which can be formatted for output.
7
7
  Entry = Data.define :id, :severity, :at, :message, :tags, :payload do
8
8
  def self.for(message = nil, **payload)
9
- new id: (payload.delete(:id) || Program.call),
9
+ new id: payload.delete(:id) || Program.call,
10
10
  severity: (payload.delete(:severity) || "INFO").upcase,
11
+ at: payload.delete(:at) || ::Time.now,
11
12
  message: (block_given? ? yield : message),
12
13
  tags: Array(payload.delete(:tags)),
13
14
  payload:
@@ -26,7 +27,7 @@ module Cogger
26
27
 
27
28
  def initialize id: Program.call,
28
29
  severity: "INFO",
29
- at: Time.now,
30
+ at: ::Time.now,
30
31
  message: nil,
31
32
  tags: [],
32
33
  payload: Core::EMPTY_HASH
@@ -18,6 +18,7 @@ module Cogger
18
18
 
19
19
  def call(*input)
20
20
  attributes = sanitizer.call(*input).tagged_attributes.tap(&:compact!)
21
+ format_date_time attributes
21
22
 
22
23
  return "#{attributes.to_json}\n" if positions.empty?
23
24
 
@@ -27,6 +28,11 @@ module Cogger
27
28
  private
28
29
 
29
30
  attr_reader :positions, :sanitizer
31
+
32
+ # :reek:UtilityFunction
33
+ def format_date_time attributes
34
+ attributes[:at] = attributes[:at].utc.strftime "%Y-%m-%dT%H:%M:%S.%L%:z"
35
+ end
30
36
  end
31
37
  end
32
38
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+ require "refinements/arrays"
5
+
6
+ # Loads log level from environment.
7
+ module Cogger
8
+ using Refinements::Arrays
9
+
10
+ Level = lambda do |logger = Logger, environment: ENV, allowed: LEVELS|
11
+ value = String environment.fetch("LOG_LEVEL", "INFO")
12
+
13
+ return logger.const_get value.upcase if allowed.include? value.downcase
14
+
15
+ fail ArgumentError, %(Invalid log level: #{value.inspect}. Use: #{allowed.to_usage "or"}.)
16
+ end
17
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "core"
4
+
5
+ module Cogger
6
+ module Rack
7
+ # Middlware for enriched logging based on the incoming request.
8
+ class Logger
9
+ DEFAULTS = {
10
+ logger: Cogger.new(formatter: :json),
11
+ timer: Cogger::Time::Span.new,
12
+ key_map: {
13
+ verb: "REQUEST_METHOD",
14
+ ip: "REMOTE_ADDR",
15
+ path: "PATH_INFO",
16
+ params: "QUERY_STRING",
17
+ length: "CONTENT_LENGTH"
18
+ }
19
+ }.freeze
20
+
21
+ def initialize application, options = Core::EMPTY_HASH, defaults: DEFAULTS
22
+ configuration = defaults.merge options
23
+
24
+ @application = application
25
+ @logger = configuration.fetch :logger
26
+ @timer = configuration.fetch :timer
27
+ @key_map = configuration.fetch :key_map
28
+ end
29
+
30
+ def call environment
31
+ request = ::Rack::Request.new environment
32
+ (status, headers, body), duration, unit = timer.call { application.call environment }
33
+
34
+ logger.info tags: [tags_for(request), {status:, duration:, unit:}]
35
+
36
+ [status, headers, body]
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :application, :logger, :timer, :key_map
42
+
43
+ def tags_for request
44
+ key_map.each_key.with_object({}) do |tag, collection|
45
+ key = key_map.fetch tag, tag
46
+ collection[String(tag).downcase] = request.get_header key
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cogger
4
+ module Time
5
+ # An adapter for acquiring current time.
6
+ Clock = -> id = Process::CLOCK_MONOTONIC, unit: :nanosecond { Process.clock_gettime id, unit }
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cogger
4
+ module Time
5
+ RANGE = {
6
+ nanoseconds: ...1_000,
7
+ microseconds: 1_000...1_000_000,
8
+ milliseconds: 1_000_000...1_000_000_000,
9
+ seconds: 1_000_000_000...60_000_000_000,
10
+ minutes: 60_000_000_000...
11
+ }.freeze
12
+ end
13
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cogger
4
+ module Time
5
+ # Measures duration of a process with nanosecond precision.
6
+ class Span
7
+ def initialize clock = Clock, unit: Unit, range: RANGE
8
+ @clock = clock
9
+ @unit = unit
10
+ @range = range
11
+ end
12
+
13
+ def call
14
+ start = current
15
+ result = yield
16
+ span = current - start
17
+
18
+ [result, duration(span), unit.call(span)]
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :clock, :unit, :range
24
+
25
+ def duration value
26
+ case value
27
+ when nanoseconds then value
28
+ when microseconds then value / microseconds.min
29
+ when milliseconds then value / milliseconds.min
30
+ when seconds then value / seconds.min
31
+ else value / minutes.min
32
+ end
33
+ end
34
+
35
+ def current = clock.call
36
+
37
+ def nanoseconds
38
+ @nanoseconds ||= range.fetch __method__
39
+ end
40
+
41
+ def microseconds
42
+ @microseconds ||= range.fetch __method__
43
+ end
44
+
45
+ def milliseconds
46
+ @milliseconds ||= range.fetch __method__
47
+ end
48
+
49
+ def seconds
50
+ @seconds ||= range.fetch __method__
51
+ end
52
+
53
+ def minutes
54
+ @minutes ||= range.fetch __method__
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cogger
4
+ module Time
5
+ # Provides unit of measure for duration.
6
+ # rubocop:disable Style/MethodCallWithArgsParentheses
7
+ Unit = lambda do |duration, range: RANGE|
8
+ case duration
9
+ when range.fetch(:nanoseconds) then "ns"
10
+ when range.fetch(:microseconds) then "µs"
11
+ when range.fetch(:milliseconds) then "ms"
12
+ when range.fetch(:seconds) then "s"
13
+ else "m"
14
+ end
15
+ end
16
+ # rubocop:enable Style/MethodCallWithArgsParentheses
17
+ end
18
+ end
data/lib/cogger.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require "zeitwerk"
4
4
 
5
5
  Zeitwerk::Loader.new.then do |loader|
6
- loader.inflector.inflect "json" => "JSON"
6
+ loader.inflector.inflect "json" => "JSON", "range" => "RANGE"
7
7
  loader.tag = File.basename __FILE__, ".rb"
8
8
  loader.push_dir __dir__
9
9
  loader.setup
@@ -13,6 +13,8 @@ end
13
13
  module Cogger
14
14
  extend Registry
15
15
 
16
+ LEVELS = %w[debug info warn error fatal unknown].freeze
17
+
16
18
  def self.loader registry = Zeitwerk::Registry
17
19
  @loader ||= registry.loaders.find { |loader| loader.tag == File.basename(__FILE__, ".rb") }
18
20
  end
data.tar.gz.sig CHANGED
@@ -1,4 +1,2 @@
1
- 1a̫�6i�=6JrS��W ��.�Y0�� _ 4��_������gk"N��� Z���KV���$cէ�����H~�qv|��P(k�8��r�9�
2
- ����պ�T%����a�UK�:�ח��M��B��٨捼��x9ʉc�*�z���x�ޑ�
3
- 0�ê�\�aFp��VO�R���;��$�2�ǚ��D��^6�Eh����O�/Gjx�B+enS`ڟ톦�,�K�a��IR�=<-����'\�f_�n��W^꓉EL�H�
4
- �qj��$Z%�
1
+ )_��S����q�¦�=��r��B}u��<k8���Y]גq��hnA��IY1�^ebC4%�����-���ϣ�*
2
+ ���
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cogger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.1
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -35,7 +35,7 @@ cert_chain:
35
35
  3n5C8/6Zh9DYTkpcwPSuIfAga6wf4nXc9m6JAw8AuMLaiWN/r/2s4zJsUHYERJEu
36
36
  gZGm4JqtuSg8pYjPeIJxS960owq+SfuC+jxqmRA54BisFCv/0VOJi7tiJVY=
37
37
  -----END CERTIFICATE-----
38
- date: 2023-11-16 00:00:00.000000000 Z
38
+ date: 2023-12-10 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: core
@@ -120,9 +120,15 @@ files:
120
120
  - lib/cogger/formatters/processors/color.rb
121
121
  - lib/cogger/formatters/simple.rb
122
122
  - lib/cogger/hub.rb
123
+ - lib/cogger/level.rb
123
124
  - lib/cogger/program.rb
125
+ - lib/cogger/rack/logger.rb
124
126
  - lib/cogger/registry.rb
125
127
  - lib/cogger/tag.rb
128
+ - lib/cogger/time/clock.rb
129
+ - lib/cogger/time/range.rb
130
+ - lib/cogger/time/span.rb
131
+ - lib/cogger/time/unit.rb
126
132
  homepage: https://alchemists.io/projects/cogger
127
133
  licenses:
128
134
  - Hippocratic-2.1
metadata.gz.sig CHANGED
Binary file