superlogger 1.0.1 → 1.1.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: '082cbc716a6f0432e73617a883fd03584bd8f3de5a1f3f32afd6a48882d05f76'
4
- data.tar.gz: c85c50a9e182a78c3c281a427b5fd351c4c01b9181dbeffe81a6831bc51f7b39
3
+ metadata.gz: 31133b660d9663478b8feabfa3bfc2f38431485648ef434230ae56e778b9a65c
4
+ data.tar.gz: 7c2bf630ad96997d64a6ac7224a3635fe3dd6246b79ab289305498bdf68a5ac8
5
5
  SHA512:
6
- metadata.gz: 7f5eb670792f8cb1abf4a4b3830b7b0e415b9f0849d9339bf8ddce091dc71dd7f2cc455813f7c6ca64fafba40ab8de59f32c6fd1a6c5cec74d24968caecc3624
7
- data.tar.gz: bc3c65ddb32e7e5eec96de1028d86a12557fda30643797eb71e863db4dac24fcf82dd5434a8c72639a9eb78b1168e60fc4c2dc3fbbd71fffb6a0dcbf08cc3f13
6
+ metadata.gz: 29ca48eafa2e7e648cb852e6e2142aa4092f95b5e1b86a9cd0eb432ac180616b9af0c2746c6cfa161ec997038fe7e38b3b5552bb8bf01b0a55ae7003211bad0b
7
+ data.tar.gz: b554d0898a26c4b32936754cec07cc557faafa74c719e918c789d20b7f11110e98915ff62476d2de199d2bc0a0a445011c7531f02642b5acbaf4e1caa5382142
data/README.md CHANGED
@@ -72,3 +72,34 @@ Rails.logger.info "Meatball"
72
72
  - `request_id` = 32 characters
73
73
  - `msg` = If values given is not a hash, it is treated as `{"msg":<value>"}`
74
74
  - All duration related fields are in milliseconds
75
+
76
+ To log additional fields that are available on the `ActionDispatch::Request` object, set in `config/application.rb`:
77
+ ```ruby
78
+ Superlogger.include_log_fields = lambda do |request|
79
+ # Return a hash of extra fields to log.
80
+ {
81
+ user_id: request.session[:current_user].id,
82
+ ip: request.ip
83
+ }
84
+ end
85
+ ```
86
+
87
+ ## Testing ##
88
+
89
+ To run the tests for Superlogger:
90
+
91
+ ```sh
92
+ rake test
93
+ ```
94
+
95
+ ## Publishing a New Release ##
96
+
97
+ 1. Bump the version in `lib/superlogger/version.rb`.
98
+ 1. Run `bundle install` to update the version of Superlogger in `Gemfile.lock`.
99
+ 1. Open a pull request with the changes from the above steps.
100
+ 1. After the pull request is merged, publish a new release on GitHub with the same version tag.
101
+ 1. Clear all temporary files to prevent them from being bundled into the gem.
102
+ This is most easily achieved by building from a new clone of the repository.
103
+ 1. Run `gem build superlogger.gemspec` to build the gem.
104
+ 1. Run `gem push superlogger-x.x.x.gem` to publish the gem to RubyGems.
105
+ You will be prompted for credentials if this is your first time publishing the gem on your machine.
@@ -1,7 +1,10 @@
1
1
  module Superlogger
2
2
  class SuperloggerMiddleware
3
- def initialize(app)
3
+ def initialize(app, options = {})
4
4
  @app = app
5
+ @options = {
6
+ include_log_fields: ->(_request) { {} }
7
+ }.merge(options)
5
8
  end
6
9
 
7
10
  def call(env)
@@ -15,7 +18,8 @@ module Superlogger
15
18
  end
16
19
 
17
20
  def process_request(request)
18
- setup_logging(request)
21
+ setup_request_id_for_logging(request)
22
+ setup_session_id_for_logging(request)
19
23
 
20
24
  # Start of request
21
25
  Rails.logger.info method: request.method, path: request.fullpath
@@ -27,20 +31,24 @@ module Superlogger
27
31
 
28
32
  # End of request
29
33
  duration = ((t2 - t1) * 1000).to_f.round(2)
30
- Rails.logger.info method: request.method, path: request.fullpath, response_time: duration, status: status
34
+
35
+ # After the request has been processed, the session ID can change from what it was before the request
36
+ # was processed. As such, we need to setup the session ID again.
37
+ setup_session_id_for_logging(request)
38
+
39
+ Rails.logger.info method: request.method, path: request.fullpath, response_time: duration, status: status, **@options[:include_log_fields].call(request)
31
40
 
32
41
  [status, _headers, _response]
33
42
  end
34
43
 
35
- def setup_logging(request)
36
- if request.env['rack.session']
37
- # Store session id before any actual logging is done
38
- if request.env['rack.session'].id
39
- Superlogger.session_id = request.env['rack.session'].id.to_s
40
- end
41
- end
42
-
44
+ def setup_request_id_for_logging(request)
43
45
  Superlogger.request_id = request.uuid.try(:gsub, '-', '')
44
46
  end
47
+
48
+ def setup_session_id_for_logging(request)
49
+ return unless request.env['rack.session']&.id
50
+
51
+ Superlogger.session_id = request.env['rack.session'].id.to_s
52
+ end
45
53
  end
46
54
  end
@@ -1,3 +1,3 @@
1
1
  module Superlogger
2
- VERSION = '1.0.1'
2
+ VERSION = '1.1.0'
3
3
  end
data/lib/superlogger.rb CHANGED
@@ -3,6 +3,7 @@ require 'superlogger/logger'
3
3
 
4
4
  module Superlogger
5
5
  @@enabled = false
6
+ @@include_log_fields = nil
6
7
 
7
8
  module_function
8
9
 
@@ -18,7 +19,9 @@ module Superlogger
18
19
  require 'superlogger/superlogger_middleware'
19
20
 
20
21
  # important to insert after session middleware so we can get the session id
21
- app.middleware.use Superlogger::SuperloggerMiddleware
22
+ app.middleware.use Superlogger::SuperloggerMiddleware, {
23
+ include_log_fields: @@include_log_fields
24
+ }.compact
22
25
  end
23
26
 
24
27
  def detach_existing_log_subscribers
@@ -74,6 +77,14 @@ module Superlogger
74
77
  def enabled
75
78
  @@enabled
76
79
  end
80
+
81
+ def include_log_fields=(include_log_fields)
82
+ @@include_log_fields=include_log_fields
83
+ end
84
+
85
+ def include_log_fields
86
+ @@include_log_fields
87
+ end
77
88
  end
78
89
 
79
90
  require 'superlogger/railtie' if defined?(Rails)
@@ -2,4 +2,10 @@ class HomeController < ApplicationController
2
2
  def index
3
3
  Something.where(paper: '123', stone: '456').first
4
4
  end
5
+
6
+ def index_with_session
7
+ # Force load session by writing to it.
8
+ session[:current_time] = Time.now
9
+ redirect_to action: :index
10
+ end
5
11
  end
@@ -23,5 +23,13 @@ module Dummy
23
23
 
24
24
  Superlogger.enabled = true
25
25
  config.logger = Superlogger::Logger.new(STDOUT)
26
+
27
+ Superlogger.include_log_fields = lambda do |request|
28
+ session = request.session
29
+ {
30
+ current_time: session[:current_time],
31
+ hello: 'world'
32
+ }
33
+ end
26
34
  end
27
35
  end
@@ -1,3 +1,4 @@
1
1
  Rails.application.routes.draw do
2
2
  get 'home/index'
3
+ get 'home/index_with_session'
3
4
  end
@@ -33,10 +33,30 @@ class SuperloggerTest < ActiveSupport::TestCase
33
33
  assert_not_nil Superlogger::VERSION
34
34
  end
35
35
 
36
- test 'log format' do
36
+ test 'log format when session is not loaded' do
37
37
  request('home/index')
38
38
 
39
- fields = output.first
39
+ fields = output[4]
40
+ assert fields.key?("level")
41
+ assert fields.key?("ts")
42
+ assert fields.key?("caller")
43
+ assert_equal fields.key?("session_id"), false
44
+ assert fields.key?("request_id")
45
+ end
46
+
47
+ test 'log format when session is loaded' do
48
+ request('home/index_with_session')
49
+
50
+ # Session is not loaded before the request is processed.
51
+ fields = output[0]
52
+ assert fields.key?("level")
53
+ assert fields.key?("ts")
54
+ assert fields.key?("caller")
55
+ assert_equal fields.key?("session_id"), false
56
+ assert fields.key?("request_id")
57
+
58
+ # Session is loaded after the request is processed.
59
+ fields = output[4]
40
60
  assert fields.key?("level")
41
61
  assert fields.key?("ts")
42
62
  assert fields.key?("caller")
@@ -44,14 +64,49 @@ class SuperloggerTest < ActiveSupport::TestCase
44
64
  assert fields.key?("request_id")
45
65
  end
46
66
 
67
+ # The additional fields to log are defined in `/test/dummy/config/application.rb`.
68
+ # Unfortunately, because `Superlogger::SuperloggerMiddleware` is initialised
69
+ # together with the Rails application, and because we cannot programmatically
70
+ # reinitialise the Rails application or run multiple instances of it, we are
71
+ # only able to test a single Superlogger configuration. Once the Rails
72
+ # application is initialised, the middleware stack cannot be changed.
73
+ #
74
+ # This effectively means that we are unable to change the Superlogger settings
75
+ # in the Rails application configuration on a per-test basis. For the sake of
76
+ # testing, we choose the Superlogger settings that let us test the presence of
77
+ # behaviours and set the additional fields to log.
78
+ test 'log format when logging additional fields' do
79
+ request('home/index_with_session')
80
+
81
+ # Additional fields are not logged before the request is processed.
82
+ fields = output[0]
83
+ assert fields.key?("level")
84
+ assert fields.key?("ts")
85
+ assert fields.key?("caller")
86
+ assert_equal fields.key?("session_id"), false
87
+ assert fields.key?("request_id")
88
+ assert_equal fields.key?("current_time"), false
89
+ assert_equal fields.key?("hello"), false
90
+
91
+ # Additional fields are logged after the request is processed.
92
+ fields = output[4]
93
+ assert fields.key?("level")
94
+ assert fields.key?("ts")
95
+ assert fields.key?("caller")
96
+ assert fields.key?("session_id")
97
+ assert fields.key?("request_id")
98
+ assert fields.key?("current_time")
99
+ assert fields.key?("hello")
100
+ end
101
+
47
102
  test 'timestamp' do
48
103
  request('home/index')
49
104
  assert_equal Time.at(output[0]["ts"]).to_date, Date.today
50
105
  end
51
106
 
52
107
  test 'with session_id' do
53
- env = request('home/index')
54
- assert_match env['rack.session'].id.to_s[0..11], output[0]["session_id"]
108
+ env = request('home/index_with_session')
109
+ assert_match env['rack.session'].id.to_s[0..11], output[4]["session_id"]
55
110
  end
56
111
 
57
112
  test 'without session_id' do
@@ -108,7 +163,7 @@ class SuperloggerTest < ActiveSupport::TestCase
108
163
  test 'action_controller_log_subscriber.process_action' do
109
164
  request('home/index')
110
165
 
111
- fields = output[5]
166
+ fields = output[7]
112
167
  assert_operator fields["view_duration"], :>, 0
113
168
  assert_operator fields["db_duration"], :>, 0
114
169
  end
@@ -116,11 +171,11 @@ class SuperloggerTest < ActiveSupport::TestCase
116
171
  test 'action_view_log_subscriber.render_template.render_partial.render_collection' do
117
172
  request('home/index')
118
173
 
119
- fields = output[3]
174
+ fields = output[4]
120
175
  assert_match 'partial.html.erb', fields["view"]
121
176
  assert fields.key?("duration")
122
177
 
123
- fields = output[4]
178
+ fields = output[5]
124
179
  assert_match 'index.html.erb', fields["view"]
125
180
  assert fields.key?("duration")
126
181
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: superlogger
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soh Yu Ming
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-04 00:00:00.000000000 Z
11
+ date: 2024-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -117,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
117
  - !ruby/object:Gem::Version
118
118
  version: '0'
119
119
  requirements: []
120
- rubygems_version: 3.2.33
120
+ rubygems_version: 3.5.9
121
121
  signing_key:
122
122
  specification_version: 4
123
123
  summary: Machine-readable logging for Rails