ezlog 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 94596a090c0744c6edb767e0bec261a515c5954a853f061984c5b094d9cf7cf2
4
+ data.tar.gz: 303cb838d233797f903d74f6d20a38bcae91b43c23b20c544b64930529df4253
5
+ SHA512:
6
+ metadata.gz: 7317b40e4ab676771a660e1bdd24003ba488e5cb7cfcca4b6ff2c9fd8c3360e98fc2cb3398af344cbabb8304bdf00f42c8fe3a852cb13155ec2f6eaf9f1277d6
7
+ data.tar.gz: 67218232ac200cc27322b83198f9d4bded0d660ada98fffc9f43205a26388a7cd9f47abc9d50d6757b6e9272675283f6213f6d19d1592b0059237cc21924bbfa
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+ .ruby-version
13
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format progress
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.1
7
+ before_install: gem install bundler -v 2.0.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ezlog.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright © 2019 Emarsys
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,101 @@
1
+ # Ezlog
2
+
3
+ Ezlog is intended to be a zero-configuration logging setup for pure Ruby or Rails projects using
4
+ [Sidekiq](https://github.com/mperham/sidekiq), [Rack::Timeout](https://github.com/heroku/rack-timeout),
5
+ [Sequel](https://sequel.jeremyevans.net/), etc. It uses Tim Pease's wonderful [Logging](https://github.com/TwP/logging)
6
+ gem for an all-purpose logging solution.
7
+
8
+ Ezlog's purpose is threefold:
9
+ 1. Make sure that our applications are logging in a sensible manner; emitting no unnecessary "noise" but containing all
10
+ relevant and necessary information (like timing).
11
+ 2. Make sure that all log messages are written to STDOUT in a machine-processable format (JSON) across all of our projects.
12
+ 3. Achieving the above goal should require no configuration in the projects where the library is used.
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'ezlog'
20
+ ```
21
+
22
+ ## What it does
23
+
24
+ * Initializes the [Logging](https://github.com/TwP/logging) library
25
+ * Configures Rails logging
26
+ * Configures Sidekiq logging
27
+ * Configures Rack::Timeout logging
28
+
29
+ #### Initializes the Logging library
30
+
31
+ Ezlog sets up [Logging](https://github.com/TwP/logging)'s root logger to have an appender that writes to STDOUT.
32
+ Any loggers created by the application will inherit this appender and will thus write their logs to STDOUT.
33
+ Ezlog also comes with its own log layout, which it uses to output messages sent to the STDOUT appender. This layout
34
+ does several very useful things to make our lives easier:
35
+
36
+ * It can handle log messages in several formats:
37
+ * String (obviously)
38
+ * Hash
39
+ * Exception
40
+ * any object that can be coerced into a String
41
+ * It automatically adds basic information to all log messages, such as:
42
+ * name of the logger
43
+ * timestamp
44
+ * log level (as string)
45
+ * hostname
46
+ * PID
47
+
48
+ Examples:
49
+ ```ruby
50
+ logger.info 'Log message'
51
+ #=> {"logger":"App","timestamp":"2019-05-11T16:08:38+02:00","level":"INFO","hostname":"MacbookPro.local","pid":71674,"message":"Log message"}
52
+
53
+ logger.info message: 'Job finished', duration: 2
54
+ #=> {"logger":"App","timestamp":"2019-05-11T16:08:38+02:00","level":"INFO","hostname":"MacbookPro.local","pid":71674,"message":"Job finished","duration":2}
55
+
56
+ logger.error ex
57
+ #=> {"logger":"App","timestamp":"2019-05-11T16:08:38+02:00","level":"INFO","hostname":"MacbookPro.local","pid":71674,"message":"Error message","error":{"class":"StandardError","message":"Error message","backtrace":[...]}}
58
+ ```
59
+
60
+ #### Configures Rails logging
61
+
62
+ Ezlog configures the `Rails.logger` to be an instance of a [Logging](https://github.com/TwP/logging) logger by the name
63
+ of `Application`, behaving as described above. The logger uses the log level set in `application.rb` (if present) or
64
+ uses INFO as a default log level. It also adds the environment (`Rails.env`) to the logger's initial context, meaning
65
+ it will automatically be appended to all log messages emitted by the application.
66
+
67
+ #### Configures Sidekiq logging
68
+
69
+ Ezlog comes with its own job logger for [Sidekiq](https://github.com/mperham/sidekiq) which does several things that
70
+ come in very handy when working with background jobs.
71
+
72
+ * It emits two log messages per job run; one when the job is started and another one when the job is finished (successfully or unsuccessfuly).
73
+ * It measures the time it took to execute the job and appends the benchmark information to the final log message.
74
+ * It adds all basic information about the job (worker, queue, JID, created_at, enqueued_at) to the log context so
75
+ all log messages emitted during the execution of the job will contain this information.
76
+ * It also adds all of the job's parameters to the log context, which means that all log messages emitted during the execution
77
+ of the job will contain this information as well.
78
+
79
+ ```ruby
80
+ class TestWorker
81
+ def perform(customer_id, name)
82
+ end
83
+ end
84
+
85
+ #=> {"logger":"Sidekiq","timestamp":"2019-05-12T10:38:10+02:00","level":"INFO","hostname":"MacbookPro.local","pid":75538,"jid":"job id","queue":"job queue","worker":"TestWorker","created_at":"2019-05-12 10:38:10 +0200","enqueued_at":"2019-05-12 10:38:10 +0200","customer_id":1,"name":"name param","message":"TestWorker started"}
86
+ #=> {"logger":"Sidekiq","timestamp":"2019-05-12T10:38:12+02:00","level":"INFO","hostname":"MacbookPro.local","pid":75538,"jid":"job id","queue":"job queue","worker":"TestWorker","created_at":"2019-05-12 10:38:10 +0200","enqueued_at":"2019-05-12 10:38:10 +0200","customer_id":1,"name":"name param","duration_sec":2.667,"message":"TestWorker finished"}
87
+ ```
88
+
89
+ #### Configures Rack::Timeout logging
90
+
91
+ [Rack::Timeout](https://github.com/heroku/rack-timeout) is a very useful tool for people running services on Heroku
92
+ but it is way too verbose by default. What Ezlog does is simply reconfigure its logging to use Ezlog's logging
93
+ mechanism and to only output messages at or above WARN level.
94
+
95
+ ## Disclaimer
96
+
97
+ Ezlog is highly opinionated software and does in no way aim or claim to be useful for everyone. Use at your own discretion.
98
+
99
+ ## License
100
+
101
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ezlog"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,29 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "ezlog/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "ezlog"
7
+ spec.version = Ezlog::VERSION
8
+ spec.authors = ["Zoltan Ormandi"]
9
+ spec.email = ["zoltan.ormandi@emarsys.com"]
10
+
11
+ spec.summary = "A zero-configuration logging solution for projects using Sidekiq, Rails, Sequel, etc."
12
+ spec.homepage = "https://github.com/emartech/ezlog"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
16
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ end
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "logging", "~> 2.0"
23
+ spec.add_dependency "multi_json"
24
+
25
+ spec.add_development_dependency "bundler", "~> 2.0"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "rspec", "~> 3.0"
28
+ spec.add_development_dependency "sidekiq", "~> 5.0"
29
+ end
@@ -0,0 +1,4 @@
1
+ require 'ezlog/version'
2
+ require 'ezlog/logging_layout'
3
+
4
+ require 'ezlog/railtie' if defined? Rails
@@ -0,0 +1,65 @@
1
+ require 'time'
2
+ require 'multi_json'
3
+ require 'logging'
4
+
5
+ module Ezlog
6
+ class LoggingLayout < ::Logging::Layout
7
+ def initialize(context = {})
8
+ @initial_context = context
9
+ end
10
+
11
+ def format(event)
12
+ log_entry = basic_information_for event
13
+ add_initial_context_to log_entry
14
+ add_logging_context_to log_entry
15
+ add_event_information_to log_entry, event
16
+ ::MultiJson.dump(log_entry) + "\n"
17
+ end
18
+
19
+ private
20
+
21
+ def basic_information_for(event)
22
+ {
23
+ 'logger' => event.logger,
24
+ 'timestamp' => event.time.iso8601,
25
+ 'level' => ::Logging::LNAMES[event.level],
26
+ 'hostname' => Socket.gethostname,
27
+ 'pid' => Process.pid
28
+ }
29
+ end
30
+
31
+ def add_initial_context_to(log_entry)
32
+ log_entry.merge! @initial_context
33
+ end
34
+
35
+ def add_logging_context_to(log_entry)
36
+ log_entry.merge! ::Logging.mdc.context
37
+ end
38
+
39
+ def add_event_information_to(log_entry, event)
40
+ log_entry.merge! hash_from(event.data)
41
+ end
42
+
43
+ def hash_from(obj)
44
+ case obj
45
+ when Exception
46
+ exception_message_by(obj)
47
+ when Hash
48
+ obj
49
+ else
50
+ {message: obj}
51
+ end
52
+ end
53
+
54
+ def exception_message_by(exception)
55
+ {
56
+ message: exception.message,
57
+ error: {
58
+ class: exception.class.name,
59
+ message: exception.message,
60
+ backtrace: exception.backtrace.first(20)
61
+ }
62
+ }
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,37 @@
1
+ module Ezlog
2
+ class Railtie < Rails::Railtie
3
+ initializer 'ezlog.configure_logging' do |app|
4
+ ::Logging.logger.root.appenders = ::Logging.appenders.stdout 'stdout',
5
+ layout: Ezlog::LoggingLayout.new(environment: Rails.env),
6
+ level: app.config.log_level || :info
7
+ end
8
+
9
+ initializer 'ezlog.configure_sidekiq_logging' do
10
+ initialize_sidekiq_logging if defined? ::Sidekiq
11
+ end
12
+
13
+ initializer 'ezlog.configure_rack_timeout_logging' do
14
+ initialize_rack_timeout_logging if defined? ::Rack::Timeout
15
+ end
16
+
17
+ config.before_configuration do |app|
18
+ app.config.logger = ::Logging.logger['Application']
19
+ end
20
+
21
+ private
22
+
23
+ def initialize_sidekiq_logging
24
+ ::Sidekiq.logger = Logging.logger['Sidekiq']
25
+ ::Sidekiq.logger.level = :info
26
+ ::Sidekiq.configure_server do |config|
27
+ require 'ezlog/sidekiq/job_logger'
28
+ config.options[:job_logger] = Ezlog::Sidekiq::JobLogger
29
+ end
30
+ end
31
+
32
+ def initialize_rack_timeout_logging
33
+ ::Rack::Timeout::Logger.logger = ::Logging.logger['rack-timeout']
34
+ ::Rack::Timeout::Logger.logger.level = :warn
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspec/logging_helper'
2
+ require_relative 'rspec/helpers'
3
+ require_relative 'rspec/matchers'
4
+
5
+ RSpec.configure do |config|
6
+ config.include Ezlog::RSpec::Helpers
7
+ config.before(:suite) do
8
+ Logging.appenders.string_io('__ezlog_stringio__', layout: Ezlog::LoggingLayout.new)
9
+ config.capture_log_messages to: '__ezlog_stringio__'
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module Ezlog
2
+ module RSpec
3
+ module Helpers
4
+ def log_output_is_expected
5
+ expect(log_output)
6
+ end
7
+
8
+ def log_output
9
+ @log_output.clone.readlines
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,57 @@
1
+ RSpec::Matchers.define :include_log_message do |expected|
2
+ chain :at_level, :log_level
3
+
4
+ match do |actual|
5
+ actual.any? { |log_line| includes? log_line, expected_messages_from(expected) }
6
+ end
7
+
8
+ def includes?(log_line, messages)
9
+ return false unless includes_log_level? log_line
10
+ messages.all? { |message| log_line.include? message }
11
+ end
12
+
13
+ def includes_log_level?(log_line)
14
+ return true if log_level.nil?
15
+ log_line.include? log_level_string(log_level)
16
+ end
17
+
18
+ def log_level_string(log_level)
19
+ return 'WARN' if log_level == :warning
20
+ log_level.to_s.upcase
21
+ end
22
+
23
+ def expected_messages_from(object)
24
+ @expected_messages ||= case object
25
+ when Hash
26
+ object.map { |k, v| MultiJson.dump(k => v)[1...-1] }
27
+ when String
28
+ [object]
29
+ else
30
+ raise NotImplementedError, 'log expectation must be Hash or String'
31
+ end
32
+ end
33
+
34
+ failure_message do |actual|
35
+ error_message = "expected log output\n\t'#{actual.join('')}'\nto include log message\n\t'#{expected}'"
36
+ error_message += " at #{log_level} level" if log_level
37
+ error_message
38
+ end
39
+ end
40
+
41
+ RSpec::Matchers.define :log do
42
+ supports_block_expectations
43
+ chain :at_level, :log_level
44
+
45
+ failure_message do
46
+ error_message = "expected operation to log '#{expected}'"
47
+ error_message += " at #{log_level} level" if log_level
48
+ "#{error_message}\n\nactual log output:\n#{log_output.join('')}"
49
+ end
50
+
51
+ match do |operation|
52
+ raise 'log matcher only supports block expectations' unless operation.is_a? Proc
53
+ log_output_is_expected.not_to include_log_message(expected)
54
+ operation.call
55
+ log_output_is_expected.to include_log_message(expected).at_level(log_level)
56
+ end
57
+ end
@@ -0,0 +1,65 @@
1
+ require 'sidekiq'
2
+
3
+ module Ezlog
4
+ module Sidekiq
5
+ class JobLogger
6
+ def call(item, queue)
7
+ within_log_context_of(item) do
8
+ logger.info "#{item['class']} started"
9
+ benchmark { yield }
10
+ logger.info message: "#{item['class']} finished"
11
+ rescue Exception
12
+ logger.info message: "#{item['class']} failed"
13
+ raise
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def within_log_context_of(item)
20
+ Logging.mdc.push log_context(item)
21
+ yield
22
+ ensure
23
+ Logging.mdc.pop
24
+ end
25
+
26
+ def log_context(job)
27
+ basic_info_for(job).merge arguments_of(job)
28
+ end
29
+
30
+ def basic_info_for(job)
31
+ {
32
+ 'jid' => job['jid'],
33
+ 'queue' => job['queue'],
34
+ 'worker' => job['class'],
35
+ 'created_at' => job['created_at'],
36
+ 'enqueued_at' => job['enqueued_at']
37
+ }
38
+ end
39
+
40
+ def arguments_of(job)
41
+ {}.tap do |arguments|
42
+ method_parameters_of(job).each_with_index do |(_, param_name), index|
43
+ arguments[param_name] = job['args'][index]
44
+ end
45
+ end
46
+ end
47
+
48
+ def method_parameters_of(job)
49
+ Kernel.const_get(job['class'].to_sym).instance_method(:perform).parameters
50
+ end
51
+
52
+ def logger
53
+ ::Sidekiq.logger
54
+ end
55
+
56
+ def benchmark
57
+ start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
58
+ yield
59
+ ensure
60
+ end_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
61
+ Logging.mdc[:duration_sec] = (end_time - start_time).round(3)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,3 @@
1
+ module Ezlog
2
+ VERSION = "0.2.0"
3
+ end
metadata ADDED
@@ -0,0 +1,146 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ezlog
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Zoltan Ormandi
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-05-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logging
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: multi_json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sidekiq
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '5.0'
97
+ description:
98
+ email:
99
+ - zoltan.ormandi@emarsys.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - ".travis.yml"
107
+ - Gemfile
108
+ - LICENSE.txt
109
+ - README.md
110
+ - Rakefile
111
+ - bin/console
112
+ - bin/setup
113
+ - ezlog.gemspec
114
+ - lib/ezlog.rb
115
+ - lib/ezlog/logging_layout.rb
116
+ - lib/ezlog/railtie.rb
117
+ - lib/ezlog/rspec.rb
118
+ - lib/ezlog/rspec/helpers.rb
119
+ - lib/ezlog/rspec/matchers.rb
120
+ - lib/ezlog/sidekiq/job_logger.rb
121
+ - lib/ezlog/version.rb
122
+ homepage: https://github.com/emartech/ezlog
123
+ licenses:
124
+ - MIT
125
+ metadata: {}
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubygems_version: 3.0.1
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: A zero-configuration logging solution for projects using Sidekiq, Rails,
145
+ Sequel, etc.
146
+ test_files: []