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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -0
  3. data/.semaphore/semaphore.yml +132 -2
  4. data/.standard.yml +2 -0
  5. data/Appraisals +31 -0
  6. data/CHANGELOG.md +62 -3
  7. data/README.md +90 -53
  8. data/Rakefile +7 -2
  9. data/app/middlewares/rails_api_logger/middleware.rb +80 -0
  10. data/app/models/rails_api_logger/inbound_request_log.rb +5 -0
  11. data/app/models/rails_api_logger/loggable.rb +27 -0
  12. data/app/models/rails_api_logger/logger.rb +22 -0
  13. data/app/models/rails_api_logger/outbound_request_log.rb +5 -0
  14. data/app/models/rails_api_logger/request_log.rb +85 -0
  15. data/bin/rails +16 -0
  16. data/gemfiles/rails_6.1.gemfile +10 -0
  17. data/gemfiles/rails_6.1.gemfile.lock +240 -0
  18. data/gemfiles/rails_7.0.gemfile +10 -0
  19. data/gemfiles/rails_7.0.gemfile.lock +239 -0
  20. data/gemfiles/rails_7.1.gemfile +9 -0
  21. data/gemfiles/rails_7.1.gemfile.lock +272 -0
  22. data/gemfiles/rails_7.2.gemfile +9 -0
  23. data/gemfiles/rails_7.2.gemfile.lock +272 -0
  24. data/gemfiles/rails_8.0.gemfile +9 -0
  25. data/lib/generators/rails_api_logger/install_generator.rb +1 -1
  26. data/lib/rails_api_logger/engine.rb +25 -0
  27. data/lib/rails_api_logger/version.rb +5 -0
  28. data/lib/rails_api_logger.rb +9 -27
  29. data/rails_api_logger.gemspec +10 -6
  30. metadata +58 -29
  31. data/CODE_OF_CONDUCT.md +0 -74
  32. data/lib/rails_api_logger/inbound_request_log.rb +0 -2
  33. data/lib/rails_api_logger/inbound_requests_logger_middleware.rb +0 -71
  34. data/lib/rails_api_logger/outbound_request_log.rb +0 -2
  35. data/lib/rails_api_logger/request_log.rb +0 -76
  36. /data/{lib/rails_api_logger → app/controllers}/inbound_requests_logger.rb +0 -0
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_api_logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alessandro Rodi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-12 00:00:00.000000000 Z
11
+ date: 2025-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: railties
14
+ name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.1.0
19
+ version: '6.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 4.1.0
26
+ version: '6.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: activerecord
28
+ name: activejob
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 4.1.0
33
+ version: '6.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 4.1.0
40
+ version: '6.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: actionpack
42
+ name: railties
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 4.1.0
47
+ version: '6.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 4.1.0
54
+ version: '6.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: nokogiri
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 1.4.0
89
+ version: 2.1.0
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 1.4.0
96
+ version: 2.1.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: pg
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -109,47 +109,47 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: 1.5.4
111
111
  - !ruby/object:Gem::Dependency
112
- name: standard
112
+ name: mysql2
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '1.31'
117
+ version: 0.5.6
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '1.31'
124
+ version: 0.5.6
125
125
  - !ruby/object:Gem::Dependency
126
- name: rake
126
+ name: standard
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '12.0'
131
+ version: '1.31'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '12.0'
138
+ version: '1.31'
139
139
  - !ruby/object:Gem::Dependency
140
- name: rspec
140
+ name: rake
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '3.0'
145
+ version: '12.0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '3.0'
152
+ version: '12.0'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: rack
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: appraisal
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '2.5'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '2.5'
167
181
  description: Log inbound and outbound API requests in your Rails application
168
182
  email:
169
183
  - alessandro.rodi@renuo.ch
@@ -176,22 +190,37 @@ files:
176
190
  - ".ruby-version"
177
191
  - ".semaphore/main-deploy.yml"
178
192
  - ".semaphore/semaphore.yml"
193
+ - ".standard.yml"
194
+ - Appraisals
179
195
  - CHANGELOG.md
180
- - CODE_OF_CONDUCT.md
181
196
  - Gemfile
182
197
  - LICENSE.txt
183
198
  - README.md
184
199
  - Rakefile
200
+ - app/controllers/inbound_requests_logger.rb
201
+ - app/middlewares/rails_api_logger/middleware.rb
202
+ - app/models/rails_api_logger/inbound_request_log.rb
203
+ - app/models/rails_api_logger/loggable.rb
204
+ - app/models/rails_api_logger/logger.rb
205
+ - app/models/rails_api_logger/outbound_request_log.rb
206
+ - app/models/rails_api_logger/request_log.rb
185
207
  - bin/console
208
+ - bin/rails
186
209
  - bin/setup
210
+ - gemfiles/rails_6.1.gemfile
211
+ - gemfiles/rails_6.1.gemfile.lock
212
+ - gemfiles/rails_7.0.gemfile
213
+ - gemfiles/rails_7.0.gemfile.lock
214
+ - gemfiles/rails_7.1.gemfile
215
+ - gemfiles/rails_7.1.gemfile.lock
216
+ - gemfiles/rails_7.2.gemfile
217
+ - gemfiles/rails_7.2.gemfile.lock
218
+ - gemfiles/rails_8.0.gemfile
187
219
  - lib/generators/rails_api_logger/install_generator.rb
188
220
  - lib/generators/templates/create_rails_api_logger_table.rb.tt
189
221
  - lib/rails_api_logger.rb
190
- - lib/rails_api_logger/inbound_request_log.rb
191
- - lib/rails_api_logger/inbound_requests_logger.rb
192
- - lib/rails_api_logger/inbound_requests_logger_middleware.rb
193
- - lib/rails_api_logger/outbound_request_log.rb
194
- - lib/rails_api_logger/request_log.rb
222
+ - lib/rails_api_logger/engine.rb
223
+ - lib/rails_api_logger/version.rb
195
224
  - rails_api_logger.gemspec
196
225
  homepage: https://github.com/renuo/rails_api_logger
197
226
  licenses:
@@ -215,7 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
215
244
  - !ruby/object:Gem::Version
216
245
  version: '0'
217
246
  requirements: []
218
- rubygems_version: 3.5.17
247
+ rubygems_version: 3.3.27
219
248
  signing_key:
220
249
  specification_version: 4
221
250
  summary: "Log API requests like a king \U0001F451"
data/CODE_OF_CONDUCT.md DELETED
@@ -1,74 +0,0 @@
1
- # Contributor Covenant Code of Conduct
2
-
3
- ## Our Pledge
4
-
5
- In the interest of fostering an open and welcoming environment, we as
6
- contributors and maintainers pledge to making participation in our project and
7
- our community a harassment-free experience for everyone, regardless of age, body
8
- size, disability, ethnicity, gender identity and expression, level of experience,
9
- nationality, personal appearance, race, religion, or sexual identity and
10
- orientation.
11
-
12
- ## Our Standards
13
-
14
- Examples of behavior that contributes to creating a positive environment
15
- include:
16
-
17
- * Using welcoming and inclusive language
18
- * Being respectful of differing viewpoints and experiences
19
- * Gracefully accepting constructive criticism
20
- * Focusing on what is best for the community
21
- * Showing empathy towards other community members
22
-
23
- Examples of unacceptable behavior by participants include:
24
-
25
- * The use of sexualized language or imagery and unwelcome sexual attention or
26
- advances
27
- * Trolling, insulting/derogatory comments, and personal or political attacks
28
- * Public or private harassment
29
- * Publishing others' private information, such as a physical or electronic
30
- address, without explicit permission
31
- * Other conduct which could reasonably be considered inappropriate in a
32
- professional setting
33
-
34
- ## Our Responsibilities
35
-
36
- Project maintainers are responsible for clarifying the standards of acceptable
37
- behavior and are expected to take appropriate and fair corrective action in
38
- response to any instances of unacceptable behavior.
39
-
40
- Project maintainers have the right and responsibility to remove, edit, or
41
- reject comments, commits, code, wiki edits, issues, and other contributions
42
- that are not aligned to this Code of Conduct, or to ban temporarily or
43
- permanently any contributor for other behaviors that they deem inappropriate,
44
- threatening, offensive, or harmful.
45
-
46
- ## Scope
47
-
48
- This Code of Conduct applies both within project spaces and in public spaces
49
- when an individual is representing the project or its community. Examples of
50
- representing a project or community include using an official project e-mail
51
- address, posting via an official social media account, or acting as an appointed
52
- representative at an online or offline event. Representation of a project may be
53
- further defined and clarified by project maintainers.
54
-
55
- ## Enforcement
56
-
57
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at alessandro.rodi@renuo.ch. All
59
- complaints will be reviewed and investigated and will result in a response that
60
- is deemed necessary and appropriate to the circumstances. The project team is
61
- obligated to maintain confidentiality with regard to the reporter of an incident.
62
- Further details of specific enforcement policies may be posted separately.
63
-
64
- Project maintainers who do not follow or enforce the Code of Conduct in good
65
- faith may face temporary or permanent repercussions as determined by other
66
- members of the project's leadership.
67
-
68
- ## Attribution
69
-
70
- This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at [https://contributor-covenant.org/version/1/4][version]
72
-
73
- [homepage]: https://contributor-covenant.org
74
- [version]: https://contributor-covenant.org/version/1/4/
@@ -1,2 +0,0 @@
1
- class InboundRequestLog < RequestLog
2
- end
@@ -1,71 +0,0 @@
1
- class InboundRequestsLoggerMiddleware
2
- attr_accessor :only_state_change, :path_regexp, :skip_request_body_regexp, :skip_response_body_regexp
3
-
4
- def initialize(app, only_state_change: true,
5
- path_regexp: /.*/,
6
- skip_request_body_regexp: nil,
7
- skip_response_body_regexp: nil)
8
- @app = app
9
- self.only_state_change = only_state_change
10
- self.path_regexp = path_regexp
11
- self.skip_request_body_regexp = skip_request_body_regexp
12
- self.skip_response_body_regexp = skip_response_body_regexp
13
- end
14
-
15
- def call(env)
16
- request = ActionDispatch::Request.new(env)
17
- logging = log?(env, request)
18
- if logging
19
- env["INBOUND_REQUEST_LOG"] = InboundRequestLog.from_request(request, skip_request_body: skip_request_body?(env))
20
- request.body.rewind
21
- end
22
- status, headers, body = @app.call(env)
23
- if logging
24
- updates = {response_code: status, ended_at: Time.current}
25
- updates[:response_body] = if skip_response_body?(env)
26
- "[Skipped]"
27
- else
28
- parsed_body(body)
29
- end
30
- # this usually works. let's be optimistic.
31
- begin
32
- env["INBOUND_REQUEST_LOG"].update_columns(updates)
33
- rescue JSON::GeneratorError => _e # this can be raised by activerecord if the string is not UTF-8.
34
- env["INBOUND_REQUEST_LOG"].update_columns(updates.except(:response_body))
35
- end
36
- end
37
- [status, headers, body]
38
- end
39
-
40
- private
41
-
42
- def skip_request_body?(env)
43
- skip_request_body_regexp && env["PATH_INFO"] =~ skip_request_body_regexp
44
- end
45
-
46
- def skip_response_body?(env)
47
- skip_response_body_regexp && env["PATH_INFO"] =~ skip_response_body_regexp
48
- end
49
-
50
- def log?(env, request)
51
- env["PATH_INFO"] =~ path_regexp && (!only_state_change || request_with_state_change?(request))
52
- end
53
-
54
- def parsed_body(body)
55
- return unless body.present?
56
-
57
- if body.respond_to?(:to_ary)
58
- JSON.parse(body.to_ary[0])
59
- elsif body.respond_to?(:body)
60
- JSON.parse(body.body)
61
- else
62
- body
63
- end
64
- rescue JSON::ParserError, ArgumentError
65
- body
66
- end
67
-
68
- def request_with_state_change?(request)
69
- request.post? || request.put? || request.patch? || request.delete?
70
- end
71
- end
@@ -1,2 +0,0 @@
1
- class OutboundRequestLog < RequestLog
2
- end
@@ -1,76 +0,0 @@
1
- class RequestLog < ActiveRecord::Base
2
- self.abstract_class = true
3
-
4
- serialize :request_body, coder: JSON
5
- serialize :response_body, coder: JSON
6
-
7
- belongs_to :loggable, optional: true, polymorphic: true
8
-
9
- scope :failed, -> { where(response_code: 400..599).or(where.not(ended_at: nil).where(response_code: nil)) }
10
-
11
- validates :method, presence: true
12
- validates :path, presence: true
13
-
14
- def self.from_request(request, loggable: nil, skip_request_body: false)
15
- if skip_request_body
16
- body = "[Skipped]"
17
- else
18
- request_body = (request.body.respond_to?(:read) ? request.body.read : request.body)
19
- body = request_body&.dup&.force_encoding("UTF-8")
20
- begin
21
- body = JSON.parse(body) if body.present?
22
- rescue JSON::ParserError
23
- body
24
- end
25
- end
26
- create(path: request.path, request_body: body, method: request.method, started_at: Time.current, loggable: loggable)
27
- end
28
-
29
- def from_response(response, skip_response_body: false)
30
- self.response_code = response.code
31
- self.response_body = skip_response_body ? "[Skipped]" : manipulate_body(response.body)
32
- self
33
- end
34
-
35
- def formatted_request_body
36
- formatted_body(request_body)
37
- end
38
-
39
- def formatted_response_body
40
- formatted_body(response_body)
41
- end
42
-
43
- def formatted_body(body)
44
- if body.is_a?(String) && body.blank?
45
- ""
46
- elsif body.is_a?(Hash)
47
- JSON.pretty_generate(body)
48
- else
49
- xml = Nokogiri::XML(body)
50
- if xml.errors.any?
51
- body
52
- else
53
- xml.to_xml(indent: 2)
54
- end
55
- end
56
- rescue
57
- body
58
- end
59
-
60
- def duration
61
- return if started_at.nil? || ended_at.nil?
62
- ended_at - started_at
63
- end
64
-
65
- private
66
-
67
- def manipulate_body(body)
68
- body_duplicate = body&.dup&.force_encoding("UTF-8")
69
- begin
70
- body_duplicate = JSON.parse(body_duplicate) if body_duplicate.present?
71
- rescue JSON::ParserError
72
- body_duplicate
73
- end
74
- body_duplicate
75
- end
76
- end