ezlog 0.2.2 → 0.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af49b0170f9c53fe3f0b41ced3fd1afe3a420402bbb64b62318bda81144d8c23
4
- data.tar.gz: 6c85e8f81ee2848bba6ad407aafbf0ce8b567523801cf133ac3fa795fbb6b14c
3
+ metadata.gz: 93492a6b3f140b41d4aad461fcb7bd9017149c3bca1a0d19a9edf5e2ed9fc25d
4
+ data.tar.gz: bddac2fcd0e1ef426f228e97bb537a34704d102d8f480cee872be74e505aefcc
5
5
  SHA512:
6
- metadata.gz: a7917365ade7f63164081e865efbcbac0b3f71e26f77abd0a2f32e0c15f2ca4465aabb55db07c64ab20c05ed089525e31319e89ef946e91394a51d73f8dc98da
7
- data.tar.gz: 631f9ff0ef37d8fb1250e3713f8322e262d2e5366e1e46fa48da522b296cd3cf8445723fdc42f33ef039ad5ccdc2d32bebfaa1dd53749957b663d7f1206e06fd
6
+ metadata.gz: 22f5427eaa445d7189140bb98bf1206f2e5b0dd0b1df8d1f1ec12af01a2472dea1006422b69e50d28bf7c87dd9f2002ee29ba7a8dcdbccceea6cb3c65ff60080
7
+ data.tar.gz: 8c0c3f28b548609c667f7e4b1d610a50a9a44a114b05a66dfaef9901d6f252e564eb6458ae4808c5154c759e685dd44b368b984a076ad1b9b7a53a75a555ae89
@@ -1,3 +1,20 @@
1
+ ### 0.3.1 (2019-06-09)
2
+
3
+ [Full Changelog](https://github.com/emartech/ezlog/compare/v0.2.2...v0.3.1)
4
+
5
+ * Features & enhancements
6
+ * Unified access log for Rails
7
+ * 1 message per request
8
+ * Includes request ID, parameters, response code
9
+ * Non-verbose logging of uncaught exceptions in Rails apps
10
+ * 1 message per error
11
+ * Use ERROR level instead of FATAL
12
+ * [Rack::Timeout](https://github.com/heroku/rack-timeout) logging is now completely turned off, because Timeout errors
13
+ are handled by the application's error logger and we don't want duplicated log messages
14
+
15
+ * Bug fixes
16
+ * Fix bug where the application log level wasn't set to INFO by default but remained on DEBUG
17
+
1
18
  ### 0.2.2 (2019-05-19)
2
19
 
3
20
  [Full Changelog](https://github.com/emartech/ezlog/compare/v0.2.1...v0.2.2)
data/README.md CHANGED
@@ -3,31 +3,41 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/ezlog.svg)](https://badge.fury.io/rb/ezlog)
4
4
  [![Build Status](https://travis-ci.com/emartech/ezlog.svg?branch=master)](https://travis-ci.com/emartech/ezlog)
5
5
 
6
- Ezlog is intended to be a zero-configuration logging setup for pure Ruby or Rails projects using
7
- [Sidekiq](https://github.com/mperham/sidekiq), [Rack::Timeout](https://github.com/heroku/rack-timeout),
8
- [Sequel](https://sequel.jeremyevans.net/), etc. It uses Tim Pease's wonderful [Logging](https://github.com/TwP/logging)
9
- gem for an all-purpose logging solution.
6
+ Ezlog is intended to be a zero-configuration structured logging setup for pure Ruby or [Ruby on Rails](https://rubyonrails.org/)
7
+ projects using any (or all) of the following libraries or frameworks:
8
+
9
+ * [Ruby on Rails](https://rubyonrails.org/)
10
+ * [Sidekiq](https://github.com/mperham/sidekiq)
11
+ * [Sequel](https://sequel.jeremyevans.net/)
12
+ * [Rack::Timeout](https://github.com/heroku/rack-timeout)
13
+
14
+ It uses Tim Pease's wonderful [Logging](https://github.com/TwP/logging) gem for an all-purpose structured logging solution.
10
15
 
11
16
  Ezlog's purpose is threefold:
12
- 1. Make sure that our applications are logging in a sensible manner; emitting no unnecessary "noise" but containing all
13
- relevant and necessary information (like timing).
17
+ 1. Make sure that our applications are logging in a concise and sensible manner; emitting no unnecessary "noise" but
18
+ containing all relevant and necessary information (like timing).
14
19
  2. Make sure that all log messages are written to STDOUT in a machine-processable format (JSON) across all of our projects.
15
- 3. Achieving the above goal should require no configuration in the projects where the library is used.
20
+ 3. Achieving the above goals should require no configuration in the projects where the library is used.
16
21
 
17
22
  ## Installation
18
23
 
24
+ #### Rails
25
+
19
26
  Add this line to your application's Gemfile:
20
27
 
21
28
  ```ruby
22
29
  gem 'ezlog'
23
30
  ```
24
31
 
32
+ That's it. Everything else is automatically configured.
33
+
25
34
  ## What it does
26
35
 
27
36
  * Initializes the [Logging](https://github.com/TwP/logging) library
28
37
  * Configures Rails logging
29
38
  * Configures Sidekiq logging
30
39
  * Configures Rack::Timeout logging
40
+ * Provides testing support for [RSpec](https://rspec.info/)
31
41
 
32
42
  #### Initializes the Logging library
33
43
 
@@ -64,8 +74,39 @@ logger.error ex
64
74
 
65
75
  Ezlog configures the `Rails.logger` to be an instance of a [Logging](https://github.com/TwP/logging) logger by the name
66
76
  of `Application`, behaving as described above. The logger uses the log level set in `application.rb` (if present) or
67
- uses INFO as a default log level. It also adds the environment (`Rails.env`) to the logger's initial context, meaning
68
- it will automatically be appended to all log messages emitted by the application.
77
+ uses INFO as a default log level.
78
+
79
+ In addition to this, Ezlog also does the following:
80
+ * It adds the environment (`Rails.env`) to the logger's initial context, so it will automatically be appended to all log messages
81
+ emitted by the application.
82
+ * It disables Rails's default (verbose) logging of uncaught errors and injects its own error logger into the application, which
83
+ * logs 1 line per error, including the error's name and context (stack trace, etc.),
84
+ * logs every error at ERROR level instead of the default FATAL.
85
+ * It disables Rails's default (verbose) request logging, which logs several lines per event during the processing of an action
86
+ and replaces the default Rack access log with its own access log middleware. The end result is an access log, which
87
+ * contains all relevant information (request ID, method, path, params, client IP, duration and response status code), and
88
+ * has 1 log line per request, logged at the end of the request.
89
+
90
+ Thanks to Mathias Meyer for writing [Lograge](https://github.com/roidrage/lograge), which inspired the solution.
91
+ If Ezlog's not your cup of tea but you're looking for a way to tame Rails's logging then be sure to check out
92
+ [Lograge](https://github.com/roidrage/lograge).
93
+
94
+ ```
95
+ GET /welcome?subsession_id=34ea8596f9764f475f81158667bc2654
96
+
97
+ With default Rails logging:
98
+
99
+ Started GET "/welcome?subsession_id=34ea8596f9764f475f81158667bc2654" for 127.0.0.1 at 2019-06-08 08:49:31 +0200
100
+ Processing by PagesController#welcome as HTML
101
+ Parameters: {"subsession_id"=>"34ea8596f9764f475f81158667bc2654"}
102
+ Rendering pages/welcome.html.haml within layouts/application
103
+ Rendered pages/welcome.html.haml within layouts/application (5.5ms)
104
+ Completed 200 OK in 31ms (Views: 27.3ms | ActiveRecord: 0.0ms)
105
+
106
+ With Ezlog:
107
+
108
+ {"logger":"AccessLog","timestamp":"2019-06-08T08:49:31+02:00","level":"INFO","hostname":"MacbookPro.local","pid":75463,"environment":"development","request_id":"9a43631b-284c-4677-9d08-9c1cc5c7d3a7","duration_sec":0.031,"message":"GET /welcome?subsession_id=34ea8596f9764f475f81158667bc2654 - 200 (OK)","remote_ip":"127.0.0.1","method":"GET","path":"/welcome?subsession_id=34ea8596f9764f475f81158667bc2654","params":{"subsession_id":"34ea8596f9764f475f81158667bc2654","controller":"pages","action":"welcome"},"response_status_code":200}
109
+ ```
69
110
 
70
111
  #### Configures Sidekiq logging
71
112
 
@@ -97,8 +138,38 @@ TestWorker.perform_async 42
97
138
  #### Configures Rack::Timeout logging
98
139
 
99
140
  [Rack::Timeout](https://github.com/heroku/rack-timeout) is a very useful tool for people running services on Heroku
100
- but it is way too verbose by default. What Ezlog does is simply reconfigure its logging to use Ezlog's logging
101
- mechanism and to only output messages at or above WARN level.
141
+ but it is way too verbose by default and all of its important messages (i.e. Timeout errors) are logged by the application
142
+ as well. For this reason, Ezlog turns off [Rack::Timeout](https://github.com/heroku/rack-timeout) logging completely.
143
+
144
+ #### Provides testing support for RSpec
145
+
146
+ Ezlog comes with built-in support for testing your logging activity using [RSpec](https://rspec.info/).
147
+ To enable spec support for Ezlog, put this line in your `spec_helper.rb` or `rails_helper.rb`:
148
+ ```ruby
149
+ require "ezlog/rspec"
150
+ ```
151
+
152
+ What you get:
153
+ * Helpers
154
+ * `log_output` provides access to the complete log output in your specs
155
+ * `log_output_is_expected` shorthand for writing expectations for the log output
156
+ * Matchers
157
+ * `include_log_message` matcher for expecting a certain message in the log output
158
+ * `log` matcher for expecting an operation to log a certain message
159
+
160
+ ```ruby
161
+ # Check that the log contains a certain message
162
+ expect(log_output).to include_log_message message: 'Test message'
163
+ log_output_is_expected.to include_log_message message: 'Test message'
164
+
165
+ # Check that the message is not present in the logs before the operation but is present after it
166
+ expect { operation }.to log message: 'Test message',
167
+ user_id: 123456
168
+
169
+ # Expect a certain log level
170
+ log_output_is_expected.to include_log_message(message: 'Test message').at_level(:info)
171
+ expect { operation }.to log(message: 'Test message').at_level(:info)
172
+ ```
102
173
 
103
174
  ## Disclaimer
104
175
 
@@ -23,10 +23,10 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ["lib"]
24
24
 
25
25
  spec.add_dependency "logging", "~> 2.0"
26
- spec.add_dependency "multi_json"
27
26
 
28
27
  spec.add_development_dependency "bundler", "~> 2.0"
29
28
  spec.add_development_dependency "rake", "~> 10.0"
30
29
  spec.add_development_dependency "rspec", "~> 3.0"
31
30
  spec.add_development_dependency "sidekiq", "~> 5.0"
31
+ spec.add_development_dependency "actionpack", "~> 5.0"
32
32
  end
@@ -6,9 +6,10 @@ require 'ezlog/railtie' if defined? Rails
6
6
  module Ezlog
7
7
  autoload :LogContextHelper, 'ezlog/log_context_helper'
8
8
  autoload :LoggingLayout, 'ezlog/logging_layout'
9
+ autoload :Rails, 'ezlog/rails'
9
10
  autoload :Sidekiq, 'ezlog/sidekiq'
10
11
 
11
12
  def self.logger(name)
12
- Logging::Logger[name]
13
+ ::Logging::Logger[name]
13
14
  end
14
15
  end
@@ -1,5 +1,5 @@
1
1
  require 'time'
2
- require 'multi_json'
2
+ require 'json'
3
3
 
4
4
  module Ezlog
5
5
  class LoggingLayout < ::Logging::Layout
@@ -12,7 +12,7 @@ module Ezlog
12
12
  add_initial_context_to log_entry
13
13
  add_logging_context_to log_entry
14
14
  add_event_information_to log_entry, event
15
- ::MultiJson.dump(log_entry) + "\n"
15
+ ::JSON.dump(log_entry) + "\n"
16
16
  end
17
17
 
18
18
  private
@@ -0,0 +1,12 @@
1
+ require "action_controller"
2
+ require "action_controller/log_subscriber"
3
+
4
+ module Ezlog
5
+ module Rails
6
+ autoload :AccessLog, 'ezlog/rails/access_log'
7
+ autoload :DebugExceptions, 'ezlog/rails/debug_exceptions'
8
+ autoload :LogExceptions, 'ezlog/rails/log_exceptions'
9
+ autoload :RequestLogContext, 'ezlog/rails/request_log_context'
10
+ autoload :LogSubscriber, 'ezlog/rails/log_subscriber'
11
+ end
12
+ end
@@ -0,0 +1,37 @@
1
+ module Ezlog
2
+ module Rails
3
+ class AccessLog
4
+ include LogContextHelper
5
+
6
+ def initialize(app, logger)
7
+ @app = app
8
+ @logger = logger
9
+ end
10
+
11
+ def call(env)
12
+ status, headers, body_lines = benchmark { @app.call(env) }
13
+ log_request ActionDispatch::Request.new(env), status
14
+ [status, headers, body_lines]
15
+ end
16
+
17
+ private
18
+
19
+ def benchmark
20
+ start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
21
+ yield
22
+ ensure
23
+ end_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
24
+ add_to_log_context duration_sec: (end_time - start_time).round(3)
25
+ end
26
+
27
+ def log_request(request, status)
28
+ @logger.info message: '%s %s - %i (%s)' % [request.method, request.filtered_path, status, Rack::Utils::HTTP_STATUS_CODES[status]],
29
+ remote_ip: request.remote_ip,
30
+ method: request.method,
31
+ path: request.filtered_path,
32
+ params: request.filtered_parameters,
33
+ response_status_code: status
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,8 @@
1
+ module Ezlog
2
+ module Rails
3
+ class DebugExceptions < ::ActionDispatch::DebugExceptions
4
+ def log_error(_request, _wrapper)
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ module Ezlog
2
+ module Rails
3
+ class LogExceptions
4
+ def initialize(app, logger)
5
+ @app = app
6
+ @logger = logger
7
+ end
8
+
9
+ def call(env)
10
+ @app.call(env)
11
+ rescue Exception => exception
12
+ @logger.error exception
13
+ raise
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Ezlog
2
+ module Rails
3
+ class LogSubscriber
4
+ def self.detach(subscriber_class)
5
+ subscriber = ::ActiveSupport::LogSubscriber.log_subscribers.find { |subscriber| subscriber.is_a? subscriber_class }
6
+ return unless subscriber
7
+
8
+ subscriber.patterns.each do |pattern|
9
+ ::ActiveSupport::Notifications.notifier.listeners_for(pattern).each do |listener|
10
+ ::ActiveSupport::Notifications.unsubscribe listener if listener.instance_variable_get('@delegate').is_a? subscriber_class
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module Ezlog
2
+ module Rails
3
+ class RequestLogContext
4
+ include LogContextHelper
5
+
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ within_log_context request_id: env['action_dispatch.request_id'] do
12
+ @app.call(env)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -2,8 +2,8 @@ module Ezlog
2
2
  class Railtie < Rails::Railtie
3
3
  initializer 'ezlog.configure_logging' do |app|
4
4
  ::Logging.logger.root.appenders = ::Logging.appenders.stdout 'stdout',
5
- layout: Ezlog::LoggingLayout.new(environment: Rails.env),
6
- level: app.config.log_level || :info
5
+ layout: Ezlog::LoggingLayout.new(environment: ::Rails.env),
6
+ level: app.config.log_level
7
7
  end
8
8
 
9
9
  initializer 'ezlog.configure_sidekiq_logging' do
@@ -11,11 +11,24 @@ module Ezlog
11
11
  end
12
12
 
13
13
  initializer 'ezlog.configure_rack_timeout_logging' do
14
- initialize_rack_timeout_logging if defined? ::Rack::Timeout
14
+ disable_rack_timeout_logging if defined? ::Rack::Timeout
15
+ end
16
+
17
+ initializer 'ezlog.configure_middlewares' do |app|
18
+ app.config.middleware.insert_after ::ActionDispatch::RequestId, Ezlog::Rails::RequestLogContext
19
+ app.config.middleware.swap ::Rails::Rack::Logger, Ezlog::Rails::AccessLog, Ezlog.logger('AccessLog')
20
+ app.config.middleware.swap ::ActionDispatch::DebugExceptions, Ezlog::Rails::DebugExceptions
21
+ app.config.middleware.insert_after Ezlog::Rails::DebugExceptions, Ezlog::Rails::LogExceptions, Ezlog.logger('Application')
22
+ end
23
+
24
+ config.after_initialize do
25
+ Ezlog::Rails::LogSubscriber.detach ::ActionController::LogSubscriber
26
+ Ezlog::Rails::LogSubscriber.detach ::ActionView::LogSubscriber
15
27
  end
16
28
 
17
29
  config.before_configuration do |app|
18
- app.config.logger = ::Logging.logger['Application']
30
+ app.config.logger = Ezlog.logger('Application')
31
+ app.config.log_level = :info
19
32
  end
20
33
 
21
34
  private
@@ -30,9 +43,8 @@ module Ezlog
30
43
  end
31
44
  end
32
45
 
33
- def initialize_rack_timeout_logging
34
- ::Rack::Timeout::Logger.logger = ::Logging.logger['rack-timeout']
35
- ::Rack::Timeout::Logger.logger.level = :warn
46
+ def disable_rack_timeout_logging
47
+ ::Rack::Timeout::Logger.logger = ::Logger.new(nil)
36
48
  end
37
49
  end
38
50
  end
@@ -5,7 +5,7 @@ module Ezlog
5
5
  class JobLogger
6
6
  include LogContextHelper
7
7
 
8
- def call(job_hash, queue)
8
+ def call(job_hash, _queue)
9
9
  within_log_context(JobContext.from_job_hash(job_hash)) do
10
10
  logger.info "#{job_hash['class']} started"
11
11
  benchmark { yield }
@@ -1,3 +1,3 @@
1
1
  module Ezlog
2
- VERSION = "0.2.2"
2
+ VERSION = '0.3.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ezlog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zoltan Ormandi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-19 00:00:00.000000000 Z
11
+ date: 2019-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logging
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
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
27
  - !ruby/object:Gem::Dependency
42
28
  name: bundler
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +80,20 @@ dependencies:
94
80
  - - "~>"
95
81
  - !ruby/object:Gem::Version
96
82
  version: '5.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: actionpack
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
97
  description:
98
98
  email:
99
99
  - zoltan.ormandi@emarsys.com
@@ -115,6 +115,12 @@ files:
115
115
  - lib/ezlog.rb
116
116
  - lib/ezlog/log_context_helper.rb
117
117
  - lib/ezlog/logging_layout.rb
118
+ - lib/ezlog/rails.rb
119
+ - lib/ezlog/rails/access_log.rb
120
+ - lib/ezlog/rails/debug_exceptions.rb
121
+ - lib/ezlog/rails/log_exceptions.rb
122
+ - lib/ezlog/rails/log_subscriber.rb
123
+ - lib/ezlog/rails/request_log_context.rb
118
124
  - lib/ezlog/railtie.rb
119
125
  - lib/ezlog/rspec.rb
120
126
  - lib/ezlog/rspec/helpers.rb