rails_api_logger 0.9.0 → 0.10.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 +4 -4
- data/.gitignore +6 -0
- data/.semaphore/semaphore.yml +132 -2
- data/.standard.yml +2 -0
- data/Appraisals +31 -0
- data/CHANGELOG.md +62 -3
- data/README.md +90 -53
- data/Rakefile +7 -2
- data/app/middlewares/rails_api_logger/middleware.rb +80 -0
- data/app/models/rails_api_logger/inbound_request_log.rb +5 -0
- data/app/models/rails_api_logger/loggable.rb +27 -0
- data/app/models/rails_api_logger/logger.rb +22 -0
- data/app/models/rails_api_logger/outbound_request_log.rb +5 -0
- data/app/models/rails_api_logger/request_log.rb +85 -0
- data/bin/rails +16 -0
- data/gemfiles/rails_6.1.gemfile +10 -0
- data/gemfiles/rails_6.1.gemfile.lock +240 -0
- data/gemfiles/rails_7.0.gemfile +10 -0
- data/gemfiles/rails_7.0.gemfile.lock +239 -0
- data/gemfiles/rails_7.1.gemfile +9 -0
- data/gemfiles/rails_7.1.gemfile.lock +272 -0
- data/gemfiles/rails_7.2.gemfile +9 -0
- data/gemfiles/rails_7.2.gemfile.lock +272 -0
- data/gemfiles/rails_8.0.gemfile +9 -0
- data/lib/generators/rails_api_logger/install_generator.rb +1 -1
- data/lib/rails_api_logger/engine.rb +25 -0
- data/lib/rails_api_logger/version.rb +5 -0
- data/lib/rails_api_logger.rb +9 -27
- data/rails_api_logger.gemspec +10 -6
- metadata +58 -29
- data/CODE_OF_CONDUCT.md +0 -74
- data/lib/rails_api_logger/inbound_request_log.rb +0 -2
- data/lib/rails_api_logger/inbound_requests_logger_middleware.rb +0 -71
- data/lib/rails_api_logger/outbound_request_log.rb +0 -2
- data/lib/rails_api_logger/request_log.rb +0 -76
- /data/{lib/rails_api_logger → app/controllers}/inbound_requests_logger.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4959094cde8a80515bac5d15b4bd4f475e7c723b94803a2ecdc00de59aba1995
|
4
|
+
data.tar.gz: 283881fcb6952b5ffab21a816558f8c6ef9c705252d25f183a261e614317db3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d727ed904aff3668f16d2bdfdedee5576b30c53819911303f7df0723608344fbe9c30eb7e313cde7c2ca6d33e832c9ac4073baa065331f2cb9e11276975e3f8
|
7
|
+
data.tar.gz: e76f28822d9646a1973f4fb75612c52a0ed0d18d089ae27e9eccc5ac5f1313ee58e5236564b086246a17d6f158d4616a29ebc1419e25484a7a6cb73021529629
|
data/.gitignore
CHANGED
data/.semaphore/semaphore.yml
CHANGED
@@ -21,12 +21,142 @@ blocks:
|
|
21
21
|
- cache restore
|
22
22
|
- bundle config set path 'vendor/bundle'
|
23
23
|
- bundle install -j 4
|
24
|
-
|
24
|
+
|
25
25
|
- cache store
|
26
|
+
env_vars:
|
27
|
+
- name: BUNDLE_GEMFILE
|
28
|
+
value: /home/semaphore/rails_api_logger/gemfiles/rails_8.0.gemfile
|
26
29
|
jobs:
|
27
|
-
- name:
|
30
|
+
- name: linter
|
28
31
|
commands:
|
29
32
|
- bundle exec standardrb
|
33
|
+
- name: tests postgres separate db and separate target
|
34
|
+
env_vars:
|
35
|
+
- name: SAME_DB
|
36
|
+
value: "false"
|
37
|
+
- name: SAME_TARGET
|
38
|
+
value: "false"
|
39
|
+
- name: TARGET_DB
|
40
|
+
value: postgres
|
41
|
+
- name: RAILS_ENV
|
42
|
+
value: test
|
43
|
+
commands:
|
44
|
+
- sem-service start postgres 14
|
45
|
+
- bin/rails db:create db:migrate
|
46
|
+
- bundle exec rspec
|
47
|
+
- name: tests postgres separate db and same target
|
48
|
+
env_vars:
|
49
|
+
- name: SAME_DB
|
50
|
+
value: "false"
|
51
|
+
- name: SAME_TARGET
|
52
|
+
value: "true"
|
53
|
+
- name: TARGET_DB
|
54
|
+
value: postgres
|
55
|
+
- name: RAILS_ENV
|
56
|
+
value: test
|
57
|
+
commands:
|
58
|
+
- sem-service start postgres 14
|
59
|
+
- bin/rails db:create db:migrate
|
60
|
+
- bundle exec rspec
|
61
|
+
- name: tests postgres same db and separate target
|
62
|
+
env_vars:
|
63
|
+
- name: SAME_DB
|
64
|
+
value: "true"
|
65
|
+
- name: TARGET_DB
|
66
|
+
value: postgres
|
67
|
+
- name: RAILS_ENV
|
68
|
+
value: test
|
69
|
+
commands:
|
70
|
+
- sem-service start postgres 14
|
71
|
+
- bin/rails db:create db:migrate
|
72
|
+
- bundle exec rspec
|
73
|
+
- name: tests postgres separate db and separate target | rails 6.1
|
74
|
+
env_vars:
|
75
|
+
- name: SAME_DB
|
76
|
+
value: "false"
|
77
|
+
- name: SAME_TARGET
|
78
|
+
value: "false"
|
79
|
+
- name: TARGET_DB
|
80
|
+
value: postgres
|
81
|
+
- name: RAILS_ENV
|
82
|
+
value: test
|
83
|
+
- name: BUNDLE_GEMFILE
|
84
|
+
value: /home/semaphore/rails_api_logger/gemfiles/rails_6.1.gemfile
|
85
|
+
commands:
|
86
|
+
- sem-service start postgres 14
|
87
|
+
- bin/rails db:create db:migrate
|
88
|
+
- bundle exec rspec
|
89
|
+
- name: tests postgres separate db and separate target | rails 7.0
|
90
|
+
env_vars:
|
91
|
+
- name: SAME_DB
|
92
|
+
value: "false"
|
93
|
+
- name: SAME_TARGET
|
94
|
+
value: "false"
|
95
|
+
- name: TARGET_DB
|
96
|
+
value: postgres
|
97
|
+
- name: RAILS_ENV
|
98
|
+
value: test
|
99
|
+
- name: BUNDLE_GEMFILE
|
100
|
+
value: /home/semaphore/rails_api_logger/gemfiles/rails_7.0.gemfile
|
101
|
+
commands:
|
102
|
+
- sem-service start postgres 14
|
103
|
+
- bin/rails db:create db:migrate
|
104
|
+
- bundle exec rspec
|
105
|
+
- name: tests postgres separate db and separate target | rails 7.1
|
106
|
+
env_vars:
|
107
|
+
- name: SAME_DB
|
108
|
+
value: "false"
|
109
|
+
- name: SAME_TARGET
|
110
|
+
value: "false"
|
111
|
+
- name: TARGET_DB
|
112
|
+
value: postgres
|
113
|
+
- name: RAILS_ENV
|
114
|
+
value: test
|
115
|
+
- name: BUNDLE_GEMFILE
|
116
|
+
value: /home/semaphore/rails_api_logger/gemfiles/rails_7.1.gemfile
|
117
|
+
commands:
|
118
|
+
- sem-service start postgres 14
|
119
|
+
- bin/rails db:create db:migrate
|
120
|
+
- bundle exec rspec
|
121
|
+
- name: tests postgres separate db and separate target | rails 7.2
|
122
|
+
env_vars:
|
123
|
+
- name: SAME_DB
|
124
|
+
value: "false"
|
125
|
+
- name: SAME_TARGET
|
126
|
+
value: "false"
|
127
|
+
- name: TARGET_DB
|
128
|
+
value: postgres
|
129
|
+
- name: RAILS_ENV
|
130
|
+
value: test
|
131
|
+
- name: BUNDLE_GEMFILE
|
132
|
+
value: /home/semaphore/rails_api_logger/gemfiles/rails_7.2.gemfile
|
133
|
+
commands:
|
134
|
+
- sem-service start postgres 14
|
135
|
+
- bin/rails db:create db:migrate
|
136
|
+
- bundle exec rspec
|
137
|
+
- name: tests sqlite separate db and separate target
|
138
|
+
env_vars:
|
139
|
+
- name: SAME_DB
|
140
|
+
value: "false"
|
141
|
+
- name: SAME_TARGET
|
142
|
+
value: "false"
|
143
|
+
- name: TARGET_DB
|
144
|
+
value: sqlite
|
145
|
+
- name: RAILS_ENV
|
146
|
+
value: test
|
147
|
+
commands:
|
148
|
+
- bin/rails db:create db:migrate
|
149
|
+
- bundle exec rspec
|
150
|
+
- name: tests sqlite same db
|
151
|
+
env_vars:
|
152
|
+
- name: SAME_DB
|
153
|
+
value: "true"
|
154
|
+
- name: TARGET_DB
|
155
|
+
value: sqlite
|
156
|
+
- name: RAILS_ENV
|
157
|
+
value: test
|
158
|
+
commands:
|
159
|
+
- bin/rails db:create db:migrate
|
30
160
|
- bundle exec rspec
|
31
161
|
promotions:
|
32
162
|
- name: main
|
data/.standard.yml
ADDED
data/Appraisals
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
appraise "rails-6.1" do
|
2
|
+
gem "concurrent-ruby", "1.3.4"
|
3
|
+
gem "rails", "~> 6.1.0"
|
4
|
+
gem "rspec-rails", "~> 6.1.0"
|
5
|
+
gem "sqlite3", "~> 1.7.3"
|
6
|
+
end
|
7
|
+
|
8
|
+
appraise "rails-7.0" do
|
9
|
+
gem "concurrent-ruby", "1.3.4"
|
10
|
+
gem "rails", "~> 7.0.0"
|
11
|
+
gem "rspec-rails", "~> 7.1.0"
|
12
|
+
gem "sqlite3", "~> 1.7.3"
|
13
|
+
end
|
14
|
+
|
15
|
+
appraise "rails-7.1" do
|
16
|
+
gem "rails", "~> 7.1.0"
|
17
|
+
gem "rspec-rails", "~> 7.1.0"
|
18
|
+
gem "sqlite3", "~> 1.7.3"
|
19
|
+
end
|
20
|
+
|
21
|
+
appraise "rails-7.2" do
|
22
|
+
gem "rails", "~> 7.2.0"
|
23
|
+
gem "rspec-rails", "~> 7.1.0"
|
24
|
+
gem "sqlite3", "~> 1.7.3"
|
25
|
+
end
|
26
|
+
|
27
|
+
appraise "rails-8.0" do
|
28
|
+
gem "rails", "~> 8.0.0"
|
29
|
+
gem "rspec-rails", "~> 7.1.0"
|
30
|
+
gem "sqlite3", "~> 2.1.0"
|
31
|
+
end
|
data/CHANGELOG.md
CHANGED
@@ -1,41 +1,98 @@
|
|
1
|
+
# 0.10.1
|
2
|
+
|
3
|
+
* Fix a bug introduced in 0.8.1 where we fixed Rails 7.1 warnings. This broke the serialization in Rails < 7.1.
|
4
|
+
We now configure the serializer differently if you are running Rails 7.0 or lower.
|
5
|
+
If you used the gem version 0.8.1 or above in combination with Rails 7.0 or lower this caused the serialization of
|
6
|
+
the request and response body into YML format instead of JSON. This is now fixed and tests run on different rails
|
7
|
+
versions as well.
|
8
|
+
|
9
|
+
# 0.10.0
|
10
|
+
|
11
|
+
**BREAKING CHANGES**
|
12
|
+
|
13
|
+
This version contains many breaking changes. Consider this when upgrading:
|
14
|
+
|
15
|
+
* Replace calls to `RailsApiLogger.new` with `RailsApiLogger::Logger.new`. More in general the logger has been renamed.
|
16
|
+
* `InboundRequestLog` has been renamed to `RailsApiLogger::InboundRequestLog`. Table name did not change.
|
17
|
+
* `OutboundRequestLog` has been renamed to `RailsApiLogger::OutboundRequestLog`. Table name did not change.
|
18
|
+
* If you had `has_many :inbound_request_logs` or `has_many :outbound_request_logs` defined, this will break. There's
|
19
|
+
now [three methods](app/models/rails_api_logger/loggable.rb) you can use on your model.
|
20
|
+
* `InboundRequestsLoggerMiddleware` has been renamed to `RailsApiLogger::Middleware`
|
21
|
+
|
22
|
+
> Do the changes above and then continue with the following steps if you want to connect rails_api_logger to a different
|
23
|
+
> database:
|
24
|
+
|
25
|
+
* Specify a database called `api_logger`. [Check here](spec/dummy/config/database.yml) for an example.
|
26
|
+
* Check that everything still works (also in production!) with the new configuration.
|
27
|
+
* Add the migrations in the right folder to create again the necessary tables. Run the migrations that will generate a
|
28
|
+
new schema file.
|
29
|
+
* Release and do the same in production. Adapt your build/release steps if you need.
|
30
|
+
|
31
|
+
* Add the following line into `production.rb`:
|
32
|
+
`config.rails_api_logger.connects_to = { database: { writing: :api_logger } }` if you want to point to a new database.
|
33
|
+
|
34
|
+
> If you are not on SQLite you can point also `api_logger` database to the current database you have, so you benefit
|
35
|
+
> from isolated transactions but don't need to create a new database or migrate data.
|
36
|
+
|
37
|
+
### List of changes in this version:
|
38
|
+
|
39
|
+
* Namespace correctly. Renamed all classes
|
40
|
+
* Added tests with a dummy app
|
41
|
+
* Use a separate database connection configuration to isolate transactions
|
42
|
+
* I acknowledge that there might be issues on mysql. I don't use it so I won't fix them, but PR are welcome.
|
43
|
+
* Added `host_regexp` option to the middleware.
|
44
|
+
|
1
45
|
# 0.9.0
|
2
|
-
|
46
|
+
|
47
|
+
* Add option skip_request_body to skip the request body. Use this option when you don't want to persist the request
|
48
|
+
body. `[Skipped]` will be persisted instead.
|
3
49
|
* Add option skip_request_body_regexp to skip logging the body of requests matching a regexp.
|
4
50
|
* Renamed the option skip_body into skip_response_body. This is a breaking change!
|
5
51
|
* Renamed the option skip_body_regexp into skip_response_body_regexp. This is a breaking change!
|
6
52
|
|
7
53
|
# 0.8.1
|
54
|
+
|
8
55
|
* Fix Rails 7.1 warnings.
|
9
56
|
|
10
57
|
# 0.8.0
|
11
|
-
|
58
|
+
|
59
|
+
* Add option skip_body to skip the body for request responses. Use this option when you don't want to persist the
|
60
|
+
response body. `[Skipped]` will be persisted instead. This is not a breaking change.
|
12
61
|
|
13
62
|
# 0.7.0
|
63
|
+
|
14
64
|
* Fix an issue in the middleware where the request body was not read correctly if there were encoding issues.
|
15
65
|
* Improved documentation about outboud request logging.
|
16
66
|
* Add option skip_body_regexp to skip logging the body of requests matching a regexp.
|
17
67
|
|
18
68
|
# 0.6.3
|
69
|
+
|
19
70
|
* Fix the CHANGELOG path in gemspec.
|
20
71
|
|
21
72
|
# 0.6.2
|
73
|
+
|
22
74
|
* Fixes Zeitwerk warning.
|
23
75
|
|
24
76
|
# 0.6.1
|
77
|
+
|
25
78
|
* Fixes the loading of concern into controllers.
|
26
79
|
|
27
80
|
# 0.6.0
|
81
|
+
|
28
82
|
* Fixes an important concurrency issue by removing instance variables in the rack middleware.
|
29
83
|
|
30
84
|
# 0.5.0
|
85
|
+
|
31
86
|
* Started using Zeitwerk.
|
32
87
|
* Removed RailsAdmin specific code.
|
33
88
|
* Improved RailsApiLogger class.
|
34
89
|
|
35
90
|
# 0.4.1
|
91
|
+
|
36
92
|
* Fixed the `.failed` scope.
|
37
93
|
|
38
94
|
# 0.4.0
|
95
|
+
|
39
96
|
* Added `started_at`, `ended_at` and `duration` methods.
|
40
97
|
|
41
98
|
Migrate your tables with:
|
@@ -47,12 +104,14 @@ add_column :outbound_request_logs, :started_at, :timestamp
|
|
47
104
|
add_column :outbound_request_logs, :ended_at, :timestamp
|
48
105
|
```
|
49
106
|
|
50
|
-
|
51
107
|
# 0.3.0
|
108
|
+
|
52
109
|
* Added `formatted_request_body` and `formatted_response_body` methods.
|
53
110
|
|
54
111
|
# 0.2.0
|
112
|
+
|
55
113
|
* Switch to a middleware solution.
|
56
114
|
|
57
115
|
# 0.1.0
|
116
|
+
|
58
117
|
* Initial release.
|
data/README.md
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
# Rails API Logger
|
2
2
|
|
3
|
-
The simplest way to log API requests
|
3
|
+
The simplest way to log API requests in your database.
|
4
4
|
|
5
5
|
The Rails API logger gem introduces a set of tools to log and debug API requests.
|
6
|
+
|
6
7
|
It works on two sides:
|
7
8
|
|
8
9
|
* **Inbound requests**: API exposed by your application
|
9
|
-
* **Outbound requests**: API invoked by your application
|
10
|
+
* **Outbound requests**: API invoked by your application
|
10
11
|
|
11
|
-
This gem has been extracted from various Renuo projects
|
12
|
-
technique multiple times successfully.
|
12
|
+
This gem has been extracted from various [Renuo](https://www.renuo.ch) projects.
|
13
13
|
|
14
14
|
This gem creates two database tables to log the following information:
|
15
15
|
|
16
16
|
* **path** the path/url invoked
|
17
17
|
* **method** the method used to invoke the API (get, post, put, etc...)
|
18
18
|
* **request_body** what was included in the request body
|
19
|
-
* **response_body** what was included in the response body
|
20
|
-
* **response_code** the HTTP response code of the request
|
19
|
+
* **response_body** what was included in the response body
|
20
|
+
* **response_code** the HTTP response code of the request
|
21
21
|
* **started_at** when the request started
|
22
22
|
* **ended_at** when the request finished
|
23
23
|
|
@@ -33,14 +33,34 @@ And then execute:
|
|
33
33
|
|
34
34
|
```bash
|
35
35
|
bundle install
|
36
|
-
|
37
|
-
|
38
|
-
bundle exec rails db:migrate
|
36
|
+
bin/rails g rails_api_logger:install
|
37
|
+
bin/rails db:migrate
|
39
38
|
```
|
40
39
|
|
41
40
|
This will generate two tables `inbound_request_logs` and `outbound_request_logs`.
|
42
41
|
These tables will contain the logs.
|
43
42
|
|
43
|
+
## Ensure logging of data
|
44
|
+
|
45
|
+
RailsApiLogger can use a separate database, to ensure that the logs are written in the database even if a
|
46
|
+
surrounding database transaction is rolled back.
|
47
|
+
|
48
|
+
Make sure to add the following in your `config/environments/production.rb`:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
config.rails_api_logger.connects_to = { database: { writing: :api_logger } }
|
52
|
+
```
|
53
|
+
|
54
|
+
and [configure a new database](spec/dummy/config/database.yml) accordingly.
|
55
|
+
|
56
|
+
> ⚠️ If you skip this step, rails_api_logger will use your primary database but a rollback will also rollback the
|
57
|
+
> writing of logs
|
58
|
+
> If you are not on SQLite you can point also `api_logger` to the same database! By doing so you can use a single
|
59
|
+
> database but still guarantee the writing of logs in an isolated transaction:
|
60
|
+
> ```
|
61
|
+
> config.rails_api_logger.connects_to = { database: { writing: :primary } }
|
62
|
+
> ```
|
63
|
+
|
44
64
|
## Log Outbound Requests
|
45
65
|
|
46
66
|
Given an outbound request in the following format:
|
@@ -59,7 +79,7 @@ uri = URI('http://example.com/some_path?query=string')
|
|
59
79
|
http = Net::HTTP.start(uri.host, uri.port)
|
60
80
|
request = Net::HTTP::Get.new(uri)
|
61
81
|
|
62
|
-
log = OutboundRequestLog.from_request(request)
|
82
|
+
log = RailsApiLogger::OutboundRequestLog.from_request(request)
|
63
83
|
|
64
84
|
response = http.request(request)
|
65
85
|
|
@@ -76,7 +96,7 @@ request = Net::HTTP::Post.new(uri)
|
|
76
96
|
request.body = { answer: 42 }.to_json
|
77
97
|
request.content_type = 'application/json'
|
78
98
|
|
79
|
-
response = RailsApiLogger.new.call(nil, request) do
|
99
|
+
response = RailsApiLogger::Logger.new.call(nil, request) do
|
80
100
|
Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
|
81
101
|
end
|
82
102
|
```
|
@@ -86,25 +106,7 @@ This will guarantee that the log is always persisted, even in case of errors.
|
|
86
106
|
### Database Transactions Caveats
|
87
107
|
|
88
108
|
If you log your outbound requests inside of parent app transactions, your logs will not be persisted if
|
89
|
-
the transaction is rolled-back.
|
90
|
-
to the same (or another database if you're into that stuff) when logging.
|
91
|
-
|
92
|
-
```
|
93
|
-
# config/initializers/outbound_request_log_patch.rb
|
94
|
-
|
95
|
-
module OutboundRequestLogTransactionPatch
|
96
|
-
extend ActiveSupport::Concern
|
97
|
-
|
98
|
-
included do
|
99
|
-
connects_to database: { writing: :primary, reading: :primary }
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
OutboundRequestLog.include(OutboundRequestLogTransactionPatch)
|
104
|
-
```
|
105
|
-
|
106
|
-
You can also log the request in a separate thread to provoke the checkout of a separate database connection.
|
107
|
-
Have a look at [this example here](https://github.com/renuo/rails_api_logger/blob/28d4ced88fea5a5f4fd72f5a1db42ad4734eb547/spec/outbound_request_log_spec.rb#L28-L30).
|
109
|
+
the transaction is rolled-back. Use a separate database to prevent this.
|
108
110
|
|
109
111
|
## Log Inbound Requests
|
110
112
|
|
@@ -112,36 +114,41 @@ If you are exposing some API you might be interested in logging the requests you
|
|
112
114
|
You can do so by adding this middleware in `config/application.rb`
|
113
115
|
|
114
116
|
```ruby
|
115
|
-
config.middleware.insert_before Rails::Rack::Logger,
|
117
|
+
config.middleware.insert_before Rails::Rack::Logger, RailsApiLogger::Middleware
|
116
118
|
```
|
117
119
|
|
118
120
|
this will by default only log requests that have an impact in your system (POST, PUT, and PATCH calls).
|
119
121
|
If you want to log all requests (also GET ones) use
|
120
122
|
|
121
123
|
```ruby
|
122
|
-
config.middleware.insert_before Rails::Rack::Logger,
|
124
|
+
config.middleware.insert_before Rails::Rack::Logger, RailsApiLogger::Middleware, only_state_change: false
|
123
125
|
```
|
124
126
|
|
125
127
|
If you want to log only requests on a certain path, you can pass a regular expression:
|
126
128
|
|
127
129
|
```ruby
|
128
|
-
config.middleware.insert_before Rails::Rack::Logger,
|
130
|
+
config.middleware.insert_before Rails::Rack::Logger, RailsApiLogger::Middleware, path_regexp: /api/
|
129
131
|
```
|
130
132
|
|
131
|
-
If you want to
|
133
|
+
If you want to log only requests on a certain host, you can also use a regular expression:
|
132
134
|
|
133
135
|
```ruby
|
134
|
-
config.middleware.insert_before Rails::Rack::Logger,
|
135
|
-
skip_request_body_regexp: /api/books/,
|
136
|
-
skip_response_body_regexp: /api/letters/
|
136
|
+
config.middleware.insert_before Rails::Rack::Logger, RailsApiLogger::Middleware, host_regexp: /api.example.com/
|
137
137
|
```
|
138
138
|
|
139
|
+
If you want to skip logging the response or request body of certain requests, you can pass a regular expression:
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
config.middleware.insert_before Rails::Rack::Logger, RailsApiLogger::Middleware,
|
143
|
+
skip_request_body_regexp: /api\/books/,
|
144
|
+
skip_response_body_regexp: /api\/letters/
|
145
|
+
```
|
139
146
|
|
140
147
|
In the implementation of your API, you can call any time `attach_inbound_request_loggable(model)`
|
141
148
|
to attach an already persisted model to the log record.
|
142
149
|
|
143
|
-
|
144
150
|
For example:
|
151
|
+
|
145
152
|
```ruby
|
146
153
|
|
147
154
|
def create
|
@@ -158,18 +165,21 @@ end
|
|
158
165
|
in the User model you can define:
|
159
166
|
|
160
167
|
```ruby
|
161
|
-
|
168
|
+
has_many_inbound_request_logs
|
162
169
|
```
|
163
170
|
|
164
|
-
to be able to access the logs attached to the model.
|
171
|
+
to be able to access the inbound logs attached to the model.
|
172
|
+
|
173
|
+
You also have `has_many_outbound_request_logs` and `has_many_request_logs` that includes both.
|
165
174
|
|
166
175
|
## RailsAdmin integration
|
167
176
|
|
168
177
|
We provide here some code samples to integrate the models in [RailsAdmin](https://github.com/sferik/rails_admin).
|
169
178
|
|
170
|
-
This configuration will give you some nice views, and searches to work with the logs efficiently.
|
179
|
+
This configuration will give you some nice views, and searches to work with the logs efficiently.
|
180
|
+
|
171
181
|
```ruby
|
172
|
-
%w[InboundRequestLog OutboundRequestLog].each do |logging_model|
|
182
|
+
%w[RailsApiLogger::InboundRequestLog RailsApiLogger::OutboundRequestLog].each do |logging_model|
|
173
183
|
config.model logging_model do
|
174
184
|
list do
|
175
185
|
filters %i[method path response_code request_body response_body created_at]
|
@@ -204,24 +214,51 @@ This configuration will give you some nice views, and searches to work with the
|
|
204
214
|
end
|
205
215
|
```
|
206
216
|
|
207
|
-
|
208
217
|
## Development
|
209
218
|
|
210
|
-
|
219
|
+
We use Appraisals to un on different Rails versions. This is a run example:
|
211
220
|
|
212
|
-
|
221
|
+
```bash
|
222
|
+
export SAME_TARGET=false
|
223
|
+
export SAME_DB=false
|
224
|
+
export TARGET_DB=postgres
|
225
|
+
export BUNDLE_GEMFILE=/Users/alessandrorodi/RenuoWorkspace/rails_api_logger/gemfiles/rails_6.1.gemfile
|
226
|
+
bundle exec rails db:create db:migrate
|
227
|
+
bundle exec rspec
|
228
|
+
```
|
229
|
+
|
230
|
+
These are the possible ENV variables:
|
231
|
+
|
232
|
+
* `SAME_TARGET` if true, the api_logger database is the same as the primary one. It will still use two separate
|
233
|
+
connection pools, but they'll point to the same database. This cannot be set to true if TARGET_DB is sqlite because
|
234
|
+
sqlite does not support multiple connection pools to the same database.
|
235
|
+
* `SAME_DB` if true, the api_logger uses the primary database. In this case SAME_TARGET is ignored.
|
236
|
+
* `TARGET_DB` the database to use. Can be `postgres`, `mysql`, or `sqlite`.
|
237
|
+
* `BUNDLE_GEMFILE` the gemfile to use. This is used to run the tests on different Rails versions.
|
238
|
+
|
239
|
+
Possible combinations:
|
240
|
+
|
241
|
+
| SAME_DB | SAME_TARGET | TARGET_DB | Description |
|
242
|
+
|---------|-------------|-----------|----------------------------------------------------------------------|
|
243
|
+
| false | false | postgres | Separate database, separate connection pool. |
|
244
|
+
| false | true | postgres | Same database, separate connection pool. |
|
245
|
+
| true | - | postgres | Same connection pool so the separate target is ignored. |
|
246
|
+
| false | false | sqlite | Separate database, separate connection pool. |
|
247
|
+
| false | true | sqlite | Not allowed. sqlite cannot have two connection pools to the same db. |
|
248
|
+
| true | - | sqlite | Same connection pool so the separate target is ignored. |
|
249
|
+
|
250
|
+
|
251
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the
|
252
|
+
version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version,
|
253
|
+
push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
213
254
|
|
214
255
|
## Contributing
|
215
256
|
|
216
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/renuo/rails_api_logger.
|
217
|
-
This project is intended to be a safe, welcoming space for collaboration
|
218
|
-
|
257
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/renuo/rails_api_logger.
|
258
|
+
This project is intended to be a safe, welcoming space for collaboration.
|
259
|
+
|
260
|
+
Try to be a decent human being while interacting with other people.
|
219
261
|
|
220
262
|
## License
|
221
263
|
|
222
264
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
223
|
-
|
224
|
-
## Code of Conduct
|
225
|
-
|
226
|
-
Everyone interacting in the RailsApiLogger project's codebases, issue trackers, chat rooms and mailing lists is
|
227
|
-
expected to follow the [code of conduct](https://github.com/renuo/rails_api_logger/blob/main/CODE_OF_CONDUCT.md).
|
data/Rakefile
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/setup"
|
1
4
|
require "bundler/gem_tasks"
|
2
|
-
require "
|
5
|
+
require "rake/testtask"
|
3
6
|
|
4
|
-
|
7
|
+
APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
|
8
|
+
load "rails/tasks/engine.rake"
|
9
|
+
load "rails/tasks/statistics.rake"
|
5
10
|
|
6
11
|
task default: :spec
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module RailsApiLogger
|
2
|
+
class Middleware
|
3
|
+
attr_accessor :only_state_change, :host_regexp, :path_regexp, :skip_request_body_regexp, :skip_response_body_regexp
|
4
|
+
|
5
|
+
def initialize(app, only_state_change: true,
|
6
|
+
host_regexp: /.*/,
|
7
|
+
path_regexp: /.*/,
|
8
|
+
skip_request_body_regexp: nil,
|
9
|
+
skip_response_body_regexp: nil)
|
10
|
+
@app = app
|
11
|
+
self.only_state_change = only_state_change
|
12
|
+
self.host_regexp = host_regexp
|
13
|
+
self.path_regexp = path_regexp
|
14
|
+
self.skip_request_body_regexp = skip_request_body_regexp
|
15
|
+
self.skip_response_body_regexp = skip_response_body_regexp
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(env)
|
19
|
+
request = ActionDispatch::Request.new(env)
|
20
|
+
logging = log?(env, request)
|
21
|
+
if logging
|
22
|
+
env["INBOUND_REQUEST_LOG"] = InboundRequestLog.from_request(request, skip_request_body: skip_request_body?(env))
|
23
|
+
request.body.rewind if request.body.respond_to?(:read)
|
24
|
+
end
|
25
|
+
status, headers, body = @app.call(env)
|
26
|
+
if logging
|
27
|
+
updates = {response_code: status, ended_at: Time.current}
|
28
|
+
updates[:response_body] = if skip_response_body?(env)
|
29
|
+
"[Skipped]"
|
30
|
+
else
|
31
|
+
parsed_body(body)
|
32
|
+
end
|
33
|
+
# this usually works. let's be optimistic.
|
34
|
+
begin
|
35
|
+
env["INBOUND_REQUEST_LOG"].update_columns(updates)
|
36
|
+
rescue JSON::GeneratorError => _e # this can be raised by activerecord if the string is not UTF-8.
|
37
|
+
env["INBOUND_REQUEST_LOG"].update_columns(updates.except(:response_body))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
[status, headers, body]
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def skip_request_body?(env)
|
46
|
+
skip_request_body_regexp && env["PATH_INFO"] =~ skip_request_body_regexp
|
47
|
+
end
|
48
|
+
|
49
|
+
def skip_response_body?(env)
|
50
|
+
skip_response_body_regexp && env["PATH_INFO"] =~ skip_response_body_regexp
|
51
|
+
end
|
52
|
+
|
53
|
+
def log?(env, request)
|
54
|
+
# The HTTP_HOST header is preferred to the SERVER_NAME header per the Rack spec: https://github.com/rack/rack/blob/main/SPEC.rdoc#label-The+Environment
|
55
|
+
host = env["HTTP_HOST"] || env["SERVER_NAME"]
|
56
|
+
path = env["PATH_INFO"]
|
57
|
+
(host =~ host_regexp) &&
|
58
|
+
(path =~ path_regexp) &&
|
59
|
+
(!only_state_change || request_with_state_change?(request))
|
60
|
+
end
|
61
|
+
|
62
|
+
def parsed_body(body)
|
63
|
+
return unless body.present?
|
64
|
+
|
65
|
+
if body.respond_to?(:to_ary)
|
66
|
+
JSON.parse(body.to_ary[0])
|
67
|
+
elsif body.respond_to?(:body)
|
68
|
+
JSON.parse(body.body)
|
69
|
+
else
|
70
|
+
body
|
71
|
+
end
|
72
|
+
rescue JSON::ParserError, ArgumentError
|
73
|
+
body
|
74
|
+
end
|
75
|
+
|
76
|
+
def request_with_state_change?(request)
|
77
|
+
request.post? || request.put? || request.patch? || request.delete?
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|