rails_api_logger 0.11.1 → 1.0.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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.semaphore/semaphore.yml +15 -22
- data/Appraisals +7 -32
- data/CHANGELOG.md +37 -1
- data/README.md +34 -3
- data/app/controllers/inbound_requests_logger.rb +7 -1
- data/app/middlewares/rails_api_logger/middleware.rb +18 -17
- data/app/models/rails_api_logger/logger.rb +13 -5
- data/app/models/rails_api_logger/request_log.rb +21 -22
- data/gemfiles/rails_8.0.gemfile.lock +6 -6
- data/gemfiles/{rails_7.1.gemfile → rails_8.1.gemfile} +4 -3
- data/gemfiles/rails_8.1.gemfile.lock +460 -0
- data/gemfiles/rails_webrick_8.0.gemfile.lock +5 -5
- data/lib/generators/rails_api_logger/upgrade_client_reference_generator.rb +25 -0
- data/lib/generators/templates/add_client_reference_to_rails_api_logger_tables.rb.tt +9 -0
- data/lib/generators/templates/create_rails_api_logger_table.rb.tt +6 -4
- data/lib/rails_api_logger/version.rb +1 -1
- data/lib/rails_api_logger.rb +16 -0
- data/rails_api_logger.gemspec +2 -2
- metadata +14 -21
- data/gemfiles/rails_6.1.gemfile +0 -12
- data/gemfiles/rails_6.1.gemfile.lock +0 -261
- data/gemfiles/rails_7.0.gemfile +0 -12
- data/gemfiles/rails_7.0.gemfile.lock +0 -260
- data/gemfiles/rails_7.1.gemfile.lock +0 -292
- data/gemfiles/rails_7.2.gemfile +0 -11
- data/gemfiles/rails_7.2.gemfile.lock +0 -292
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 94143c1b37ced487b63c0f994a1ce48077f2e2dbd65b525430f7015670b6faf0
|
|
4
|
+
data.tar.gz: d387bed67f8534081603c3ac48d26afcf2ae2f19be190088146389e97958cefd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: af01668c07dd98ff8a959a858241a3a910c0fbec4a181795b231cd00bf99f791629060f81e528e79ce664b81780c33b64f7f5216a60c2c47d3963a9e5b9c3453
|
|
7
|
+
data.tar.gz: 99a2c9c802084adca6687b91fb76c21c0708883443913619528e132630723c6db8353f45b5cd46f99a490b57ad0cca5a6db53acb1c722ea86a8c24301b3c29a8
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.2.
|
|
1
|
+
3.2.11
|
data/.semaphore/semaphore.yml
CHANGED
|
@@ -20,6 +20,7 @@ blocks:
|
|
|
20
20
|
- checkout --use-cache
|
|
21
21
|
- cache restore
|
|
22
22
|
- bundle config set path 'vendor/bundle'
|
|
23
|
+
- bundle config set clean 'true'
|
|
23
24
|
- bundle install -j 4
|
|
24
25
|
|
|
25
26
|
- cache store
|
|
@@ -58,7 +59,7 @@ blocks:
|
|
|
58
59
|
- sem-service start postgres 14
|
|
59
60
|
- bin/rails db:create db:migrate
|
|
60
61
|
- bundle exec rspec
|
|
61
|
-
- name: tests postgres same db
|
|
62
|
+
- name: tests postgres same db | rails 8.0
|
|
62
63
|
env_vars:
|
|
63
64
|
- name: SAME_DB
|
|
64
65
|
value: "true"
|
|
@@ -70,7 +71,7 @@ blocks:
|
|
|
70
71
|
- sem-service start postgres 14
|
|
71
72
|
- bin/rails db:create db:migrate
|
|
72
73
|
- bundle exec rspec
|
|
73
|
-
- name: tests postgres separate db and separate target | rails
|
|
74
|
+
- name: tests postgres separate db and separate target | rails 8.1
|
|
74
75
|
env_vars:
|
|
75
76
|
- name: SAME_DB
|
|
76
77
|
value: "false"
|
|
@@ -81,57 +82,49 @@ blocks:
|
|
|
81
82
|
- name: RAILS_ENV
|
|
82
83
|
value: test
|
|
83
84
|
- name: BUNDLE_GEMFILE
|
|
84
|
-
value: /home/semaphore/rails_api_logger/gemfiles/
|
|
85
|
+
value: /home/semaphore/rails_api_logger/gemfiles/rails_8.1.gemfile
|
|
85
86
|
commands:
|
|
86
87
|
- sem-service start postgres 14
|
|
87
88
|
- bin/rails db:create db:migrate
|
|
88
89
|
- bundle exec rspec
|
|
89
|
-
- name: tests
|
|
90
|
+
- name: tests mysql separate db and separate target | rails 8.0
|
|
90
91
|
env_vars:
|
|
91
92
|
- name: SAME_DB
|
|
92
93
|
value: "false"
|
|
93
94
|
- name: SAME_TARGET
|
|
94
95
|
value: "false"
|
|
95
96
|
- name: TARGET_DB
|
|
96
|
-
value:
|
|
97
|
+
value: mysql
|
|
97
98
|
- name: RAILS_ENV
|
|
98
99
|
value: test
|
|
99
|
-
- name: BUNDLE_GEMFILE
|
|
100
|
-
value: /home/semaphore/rails_api_logger/gemfiles/rails_7.0.gemfile
|
|
101
100
|
commands:
|
|
102
|
-
- sem-service start
|
|
101
|
+
- sem-service start mysql 8.0
|
|
103
102
|
- bin/rails db:create db:migrate
|
|
104
103
|
- bundle exec rspec
|
|
105
|
-
- name: tests
|
|
104
|
+
- name: tests mysql separate db and same target | rails 8.0
|
|
106
105
|
env_vars:
|
|
107
106
|
- name: SAME_DB
|
|
108
107
|
value: "false"
|
|
109
108
|
- name: SAME_TARGET
|
|
110
|
-
value: "
|
|
109
|
+
value: "true"
|
|
111
110
|
- name: TARGET_DB
|
|
112
|
-
value:
|
|
111
|
+
value: mysql
|
|
113
112
|
- name: RAILS_ENV
|
|
114
113
|
value: test
|
|
115
|
-
- name: BUNDLE_GEMFILE
|
|
116
|
-
value: /home/semaphore/rails_api_logger/gemfiles/rails_7.1.gemfile
|
|
117
114
|
commands:
|
|
118
|
-
- sem-service start
|
|
115
|
+
- sem-service start mysql 8.0
|
|
119
116
|
- bin/rails db:create db:migrate
|
|
120
117
|
- bundle exec rspec
|
|
121
|
-
- name: tests
|
|
118
|
+
- name: tests mysql same db | rails 8.0
|
|
122
119
|
env_vars:
|
|
123
120
|
- name: SAME_DB
|
|
124
|
-
value: "
|
|
125
|
-
- name: SAME_TARGET
|
|
126
|
-
value: "false"
|
|
121
|
+
value: "true"
|
|
127
122
|
- name: TARGET_DB
|
|
128
|
-
value:
|
|
123
|
+
value: mysql
|
|
129
124
|
- name: RAILS_ENV
|
|
130
125
|
value: test
|
|
131
|
-
- name: BUNDLE_GEMFILE
|
|
132
|
-
value: /home/semaphore/rails_api_logger/gemfiles/rails_7.2.gemfile
|
|
133
126
|
commands:
|
|
134
|
-
- sem-service start
|
|
127
|
+
- sem-service start mysql 8.0
|
|
135
128
|
- bin/rails db:create db:migrate
|
|
136
129
|
- bundle exec rspec
|
|
137
130
|
- name: tests sqlite separate db and separate target | rails 8.0
|
data/Appraisals
CHANGED
|
@@ -1,40 +1,15 @@
|
|
|
1
|
-
appraise "rails-
|
|
2
|
-
gem "
|
|
3
|
-
gem "rails", "~> 6.1.0"
|
|
4
|
-
gem "rspec-rails", "~> 6.1.0"
|
|
5
|
-
gem "sqlite3", "~> 1.7.3"
|
|
6
|
-
gem "ammeter", "~> 1.1"
|
|
7
|
-
gem "webmock", "~> 3.25.0"
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
appraise "rails-7.0" do
|
|
11
|
-
gem "concurrent-ruby", "1.3.4"
|
|
12
|
-
gem "rails", "~> 7.0.0"
|
|
13
|
-
gem "rspec-rails", "~> 7.1.0"
|
|
14
|
-
gem "sqlite3", "~> 1.7.3"
|
|
15
|
-
gem "ammeter", "~> 1.1"
|
|
16
|
-
gem "webmock", "~> 3.25.0"
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
appraise "rails-7.1" do
|
|
20
|
-
gem "rails", "~> 7.1.0"
|
|
21
|
-
gem "rspec-rails", "~> 7.1.0"
|
|
22
|
-
gem "sqlite3", "~> 1.7.3"
|
|
23
|
-
gem "ammeter", "~> 1.1"
|
|
24
|
-
gem "webmock", "~> 3.25.0"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
appraise "rails-7.2" do
|
|
28
|
-
gem "rails", "~> 7.2.0"
|
|
1
|
+
appraise "rails-8.0" do
|
|
2
|
+
gem "rails", "~> 8.0.0"
|
|
29
3
|
gem "rspec-rails", "~> 7.1.0"
|
|
30
|
-
gem "sqlite3", "~> 1.
|
|
4
|
+
gem "sqlite3", "~> 2.1.0"
|
|
31
5
|
gem "ammeter", "~> 1.1"
|
|
6
|
+
gem "puma"
|
|
32
7
|
gem "webmock", "~> 3.25.0"
|
|
33
8
|
end
|
|
34
9
|
|
|
35
|
-
appraise "rails-8.
|
|
36
|
-
gem "rails", "~> 8.
|
|
37
|
-
gem "rspec-rails", "~>
|
|
10
|
+
appraise "rails-8.1" do
|
|
11
|
+
gem "rails", "~> 8.1.0"
|
|
12
|
+
gem "rspec-rails", "~> 8.0"
|
|
38
13
|
gem "sqlite3", "~> 2.1.0"
|
|
39
14
|
gem "ammeter", "~> 1.1"
|
|
40
15
|
gem "puma"
|
data/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,46 @@
|
|
|
1
|
+
# 1.0.0
|
|
2
|
+
|
|
3
|
+
* **Breaking:** Drop support for Rails < 8.0 and Ruby < 3.2.
|
|
4
|
+
* Logging never breaks the host app anymore. When the log can't be written (the logging database is down, a
|
|
5
|
+
validation fails, a column is too small...), the error is reported to `Rails.error` with source
|
|
6
|
+
`rails_api_logger` and the request goes on without a log. Before, the app answered 500, an outbound request was
|
|
7
|
+
not sent, or a successful outbound request raised. The errors of your own requests are still raised as before.
|
|
8
|
+
* Fix a crash (500 in the host app) when a request body is not valid UTF-8, for example a file upload
|
|
9
|
+
([#6](https://github.com/renuo/rails_api_logger/issues/6)). Request and response bodies that are not valid UTF-8
|
|
10
|
+
are now stored as `"[Binary: <size> bytes]"`. Before, such a response body was stored as `nil`.
|
|
11
|
+
* The install migration creates `started_at` and `ended_at` as `datetime` instead of `timestamp`. On MySQL 8,
|
|
12
|
+
`timestamp` columns have no fractional seconds, so the duration of a request was rounded to whole seconds.
|
|
13
|
+
Existing MySQL apps can migrate their columns with:
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
%i[inbound_request_logs outbound_request_logs].each do |table|
|
|
17
|
+
change_column table, :started_at, :datetime, precision: 6
|
|
18
|
+
change_column table, :ended_at, :datetime, precision: 6
|
|
19
|
+
end
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
# 0.12.0
|
|
23
|
+
|
|
24
|
+
* Add `client_reference` column to both `inbound_request_logs` and `outbound_request_logs`. This is a free-form
|
|
25
|
+
indexed string you can set on a log entry to correlate it with any external identifier (similar in spirit to
|
|
26
|
+
`loggable`, but without a polymorphic association).
|
|
27
|
+
* For outbound requests, pass it to the logger: `RailsApiLogger::Logger.new(client_reference: "abc-123")`.
|
|
28
|
+
* For inbound requests, call `attach_inbound_request_client_reference("abc-123")` from your controller.
|
|
29
|
+
|
|
30
|
+
To upgrade an existing app, run:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
bin/rails g rails_api_logger:upgrade_client_reference
|
|
34
|
+
bin/rails db:migrate
|
|
35
|
+
```
|
|
36
|
+
|
|
1
37
|
# 0.11.1
|
|
2
38
|
|
|
3
39
|
* Remove deprecated "require_dependency"
|
|
4
40
|
|
|
5
41
|
# 0.11.0
|
|
6
42
|
|
|
7
|
-
* Fix stack trace
|
|
43
|
+
* Fix stack trace too deep in webrick
|
|
8
44
|
* Fixes for Rails < 7.1
|
|
9
45
|
* Support custom primary key types in migration template
|
|
10
46
|
|
data/README.md
CHANGED
|
@@ -23,7 +23,7 @@ This gem creates two database tables to log the following information:
|
|
|
23
23
|
|
|
24
24
|
## Installation
|
|
25
25
|
|
|
26
|
-
Add this line to your application's Gemfile:
|
|
26
|
+
Requires Rails 8.0 or newer. Add this line to your application's Gemfile:
|
|
27
27
|
|
|
28
28
|
```ruby
|
|
29
29
|
gem 'rails_api_logger'
|
|
@@ -105,6 +105,11 @@ end
|
|
|
105
105
|
|
|
106
106
|
This will guarantee that the log is always persisted, even in case of errors.
|
|
107
107
|
|
|
108
|
+
### Errors while logging
|
|
109
|
+
|
|
110
|
+
Logging never breaks your app. If a log can't be written, for example because the logging database is down,
|
|
111
|
+
the error is reported to `Rails.error` with source `rails_api_logger` and the request goes on without a log.
|
|
112
|
+
|
|
108
113
|
### Database Transactions Caveats
|
|
109
114
|
|
|
110
115
|
If you log your outbound requests inside of parent app transactions, your logs will not be persisted if
|
|
@@ -146,6 +151,9 @@ config.middleware.insert_before Rails::Rack::Logger, RailsApiLogger::Middleware,
|
|
|
146
151
|
skip_response_body_regexp: /api\/letters/
|
|
147
152
|
```
|
|
148
153
|
|
|
154
|
+
Bodies that are not valid UTF-8, such as file uploads, images or PDFs, are not stored.
|
|
155
|
+
The log keeps only their size, for example `"[Binary: 2048 bytes]"`.
|
|
156
|
+
|
|
149
157
|
In the implementation of your API, you can call any time `attach_inbound_request_loggable(model)`
|
|
150
158
|
to attach an already persisted model to the log record.
|
|
151
159
|
|
|
@@ -174,6 +182,29 @@ to be able to access the inbound logs attached to the model.
|
|
|
174
182
|
|
|
175
183
|
You also have `has_many_outbound_request_logs` and `has_many_request_logs` that includes both.
|
|
176
184
|
|
|
185
|
+
### Client reference
|
|
186
|
+
|
|
187
|
+
Both `inbound_request_logs` and `outbound_request_logs` have a `client_reference` column: a free-form indexed
|
|
188
|
+
string you can set on a log entry to correlate it with any external identifier (e.g. a request id coming from an
|
|
189
|
+
upstream system, an idempotency key, a tenant slug). It is independent from the `loggable` polymorphic association.
|
|
190
|
+
|
|
191
|
+
For inbound requests, attach it from your controller:
|
|
192
|
+
|
|
193
|
+
```ruby
|
|
194
|
+
def create
|
|
195
|
+
attach_inbound_request_client_reference(request.headers["X-Request-Id"])
|
|
196
|
+
# ...
|
|
197
|
+
end
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
For outbound requests, pass it when instantiating the logger:
|
|
201
|
+
|
|
202
|
+
```ruby
|
|
203
|
+
RailsApiLogger::Logger.new(client_reference: "ref-abc").call(uri, request) do
|
|
204
|
+
http.request(request)
|
|
205
|
+
end
|
|
206
|
+
```
|
|
207
|
+
|
|
177
208
|
## RailsAdmin integration
|
|
178
209
|
|
|
179
210
|
We provide here some code samples to integrate the models in [RailsAdmin](https://github.com/sferik/rails_admin).
|
|
@@ -227,13 +258,13 @@ end
|
|
|
227
258
|
|
|
228
259
|
## Development
|
|
229
260
|
|
|
230
|
-
We use Appraisals to
|
|
261
|
+
We use Appraisals to run on different Rails versions. This is a run example:
|
|
231
262
|
|
|
232
263
|
```bash
|
|
233
264
|
export SAME_TARGET=false
|
|
234
265
|
export SAME_DB=false
|
|
235
266
|
export TARGET_DB=postgres
|
|
236
|
-
export BUNDLE_GEMFILE=/Users/alessandrorodi/RenuoWorkspace/rails_api_logger/gemfiles/
|
|
267
|
+
export BUNDLE_GEMFILE=/Users/alessandrorodi/RenuoWorkspace/rails_api_logger/gemfiles/rails_8.0.gemfile
|
|
237
268
|
bundle exec rails db:create db:migrate
|
|
238
269
|
bundle exec rspec
|
|
239
270
|
```
|
|
@@ -5,6 +5,12 @@ module InboundRequestsLogger
|
|
|
5
5
|
|
|
6
6
|
def attach_inbound_request_loggable(loggable)
|
|
7
7
|
return unless request.env["INBOUND_REQUEST_LOG"].present?
|
|
8
|
-
|
|
8
|
+
return unless loggable&.persisted?
|
|
9
|
+
RailsApiLogger.safely { request.env["INBOUND_REQUEST_LOG"].update(loggable: loggable) }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def attach_inbound_request_client_reference(client_reference)
|
|
13
|
+
return unless request.env["INBOUND_REQUEST_LOG"].present?
|
|
14
|
+
RailsApiLogger.safely { request.env["INBOUND_REQUEST_LOG"].update(client_reference: client_reference) }
|
|
9
15
|
end
|
|
10
16
|
end
|
|
@@ -19,22 +19,26 @@ module RailsApiLogger
|
|
|
19
19
|
request = ActionDispatch::Request.new(env)
|
|
20
20
|
logging = log?(env, request)
|
|
21
21
|
if logging
|
|
22
|
-
env["INBOUND_REQUEST_LOG"] =
|
|
22
|
+
env["INBOUND_REQUEST_LOG"] = RailsApiLogger.safely do
|
|
23
|
+
InboundRequestLog.from_request(request, skip_request_body: skip_request_body?(env))
|
|
24
|
+
end
|
|
23
25
|
request.body.rewind if request.body.respond_to?(:rewind)
|
|
24
26
|
end
|
|
25
27
|
status, headers, body = @app.call(env)
|
|
26
|
-
if logging
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
if logging && env["INBOUND_REQUEST_LOG"]
|
|
29
|
+
RailsApiLogger.safely do
|
|
30
|
+
updates = {response_code: status, ended_at: Time.current}
|
|
31
|
+
updates[:response_body] = if skip_response_body?(env)
|
|
32
|
+
"[Skipped]"
|
|
33
|
+
else
|
|
34
|
+
parsed_body(body)
|
|
35
|
+
end
|
|
36
|
+
# this usually works. let's be optimistic.
|
|
37
|
+
begin
|
|
38
|
+
env["INBOUND_REQUEST_LOG"].update_columns(updates)
|
|
39
|
+
rescue JSON::GeneratorError => _e # this can be raised by activerecord if the string is not UTF-8.
|
|
40
|
+
env["INBOUND_REQUEST_LOG"].update_columns(updates.except(:response_body))
|
|
41
|
+
end
|
|
38
42
|
end
|
|
39
43
|
end
|
|
40
44
|
[status, headers, body]
|
|
@@ -60,7 +64,6 @@ module RailsApiLogger
|
|
|
60
64
|
end
|
|
61
65
|
|
|
62
66
|
def parsed_body(body)
|
|
63
|
-
return unless body.present?
|
|
64
67
|
parsable_body = if body.respond_to?(:to_ary)
|
|
65
68
|
body.to_ary[0]
|
|
66
69
|
elsif body.respond_to?(:body)
|
|
@@ -69,9 +72,7 @@ module RailsApiLogger
|
|
|
69
72
|
body
|
|
70
73
|
end
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
rescue JSON::ParserError, ArgumentError
|
|
74
|
-
parsable_body
|
|
75
|
+
RequestLog.parse_body(parsable_body).presence
|
|
75
76
|
end
|
|
76
77
|
|
|
77
78
|
def request_with_state_change?(request)
|
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
module RailsApiLogger
|
|
2
2
|
class Logger
|
|
3
|
-
def initialize(loggable = nil, skip_request_body: false, skip_response_body: false)
|
|
3
|
+
def initialize(loggable = nil, client_reference: nil, skip_request_body: false, skip_response_body: false)
|
|
4
4
|
@loggable = loggable
|
|
5
|
+
@client_reference = client_reference
|
|
5
6
|
@skip_request_body = skip_request_body
|
|
6
7
|
@skip_response_body = skip_response_body
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
def call(url, request)
|
|
10
|
-
log =
|
|
11
|
+
log = RailsApiLogger.safely do
|
|
12
|
+
OutboundRequestLog.from_request(request, loggable: @loggable, client_reference: @client_reference,
|
|
13
|
+
skip_request_body: @skip_request_body)
|
|
14
|
+
end
|
|
11
15
|
yield.tap do |response|
|
|
12
|
-
log
|
|
16
|
+
RailsApiLogger.safely { log&.from_response(response, skip_response_body: @skip_response_body) }
|
|
13
17
|
end
|
|
14
18
|
rescue => e
|
|
15
19
|
log.response_body = {error: e.message} if log
|
|
16
20
|
raise
|
|
17
21
|
ensure
|
|
18
|
-
log
|
|
19
|
-
|
|
22
|
+
if log
|
|
23
|
+
RailsApiLogger.safely do
|
|
24
|
+
log.ended_at = Time.current
|
|
25
|
+
log.save!
|
|
26
|
+
end
|
|
27
|
+
end
|
|
20
28
|
end
|
|
21
29
|
end
|
|
22
30
|
end
|
|
@@ -4,13 +4,8 @@ module RailsApiLogger
|
|
|
4
4
|
|
|
5
5
|
connects_to(**RailsApiLogger.connects_to) if RailsApiLogger.connects_to
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
serialize :response_body, coder: JSON
|
|
10
|
-
else
|
|
11
|
-
serialize :request_body, JSON
|
|
12
|
-
serialize :response_body, JSON
|
|
13
|
-
end
|
|
7
|
+
serialize :request_body, coder: JSON
|
|
8
|
+
serialize :response_body, coder: JSON
|
|
14
9
|
|
|
15
10
|
belongs_to :loggable, optional: true, polymorphic: true
|
|
16
11
|
|
|
@@ -19,19 +14,29 @@ module RailsApiLogger
|
|
|
19
14
|
validates :method, presence: true
|
|
20
15
|
validates :path, presence: true
|
|
21
16
|
|
|
22
|
-
def self.from_request(request, loggable: nil, skip_request_body: false)
|
|
17
|
+
def self.from_request(request, loggable: nil, client_reference: nil, skip_request_body: false)
|
|
23
18
|
if skip_request_body
|
|
24
19
|
body = "[Skipped]"
|
|
25
20
|
else
|
|
26
21
|
request_body = (request.body.respond_to?(:read) ? request.body.read : request.body)
|
|
27
|
-
body = request_body
|
|
28
|
-
begin
|
|
29
|
-
body = JSON.parse(body) if body.present?
|
|
30
|
-
rescue JSON::ParserError
|
|
31
|
-
body
|
|
32
|
-
end
|
|
22
|
+
body = parse_body(request_body)
|
|
33
23
|
end
|
|
34
|
-
create(path: request.path, request_body: body, method: request.method, started_at: Time.current,
|
|
24
|
+
create(path: request.path, request_body: body, method: request.method, started_at: Time.current,
|
|
25
|
+
loggable: loggable, client_reference: client_reference)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Bodies that are not valid UTF-8 (file uploads, images, PDFs...) can't be stored as text,
|
|
29
|
+
# so only their size is logged.
|
|
30
|
+
def self.parse_body(body)
|
|
31
|
+
return body unless body.is_a?(String)
|
|
32
|
+
|
|
33
|
+
body = body.dup.force_encoding("UTF-8")
|
|
34
|
+
return "[Binary: #{body.bytesize} bytes]" unless body.valid_encoding?
|
|
35
|
+
return body if body.blank?
|
|
36
|
+
|
|
37
|
+
JSON.parse(body)
|
|
38
|
+
rescue JSON::ParserError
|
|
39
|
+
body
|
|
35
40
|
end
|
|
36
41
|
|
|
37
42
|
def from_response(response, skip_response_body: false)
|
|
@@ -73,13 +78,7 @@ module RailsApiLogger
|
|
|
73
78
|
private
|
|
74
79
|
|
|
75
80
|
def manipulate_body(body)
|
|
76
|
-
|
|
77
|
-
begin
|
|
78
|
-
body_duplicate = JSON.parse(body_duplicate) if body_duplicate.present?
|
|
79
|
-
rescue JSON::ParserError
|
|
80
|
-
body_duplicate
|
|
81
|
-
end
|
|
82
|
-
body_duplicate
|
|
81
|
+
self.class.parse_body(body)
|
|
83
82
|
end
|
|
84
83
|
end
|
|
85
84
|
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: ..
|
|
3
3
|
specs:
|
|
4
|
-
rails_api_logger (0.
|
|
5
|
-
activejob (>=
|
|
6
|
-
activerecord (>=
|
|
4
|
+
rails_api_logger (1.0.0)
|
|
5
|
+
activejob (>= 8.0)
|
|
6
|
+
activerecord (>= 8.0)
|
|
7
7
|
nokogiri
|
|
8
|
-
railties (>=
|
|
8
|
+
railties (>= 8.0)
|
|
9
9
|
zeitwerk (>= 2.0.0)
|
|
10
10
|
|
|
11
11
|
GEM
|
|
@@ -263,7 +263,7 @@ GEM
|
|
|
263
263
|
unicode-display_width (3.1.4)
|
|
264
264
|
unicode-emoji (~> 4.0, >= 4.0.4)
|
|
265
265
|
unicode-emoji (4.0.4)
|
|
266
|
-
uri (1.
|
|
266
|
+
uri (1.1.2)
|
|
267
267
|
useragent (0.16.11)
|
|
268
268
|
webmock (3.25.1)
|
|
269
269
|
addressable (>= 2.8.0)
|
|
@@ -295,4 +295,4 @@ DEPENDENCIES
|
|
|
295
295
|
webmock (~> 3.25.0)
|
|
296
296
|
|
|
297
297
|
BUNDLED WITH
|
|
298
|
-
|
|
298
|
+
4.0.20
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
gem "rails", "~>
|
|
6
|
-
gem "rspec-rails", "~>
|
|
7
|
-
gem "sqlite3", "~> 1.
|
|
5
|
+
gem "rails", "~> 8.1.0"
|
|
6
|
+
gem "rspec-rails", "~> 8.0"
|
|
7
|
+
gem "sqlite3", "~> 2.1.0"
|
|
8
8
|
gem "ammeter", "~> 1.1"
|
|
9
|
+
gem "puma"
|
|
9
10
|
gem "webmock", "~> 3.25.0"
|
|
10
11
|
|
|
11
12
|
gemspec path: "../"
|