grape_rails_logger 1.1.3
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 +7 -0
- data/CHANGELOG.md +32 -0
- data/LICENSE.md +23 -0
- data/README.md +108 -0
- data/lib/grape_rails_logger/debug_tracer.rb +87 -0
- data/lib/grape_rails_logger/endpoint_patch.rb +15 -0
- data/lib/grape_rails_logger/endpoint_wrapper.rb +99 -0
- data/lib/grape_rails_logger/railtie.rb +58 -0
- data/lib/grape_rails_logger/status_extractor.rb +56 -0
- data/lib/grape_rails_logger/subscriber.rb +790 -0
- data/lib/grape_rails_logger/timings.rb +36 -0
- data/lib/grape_rails_logger/version.rb +3 -0
- data/lib/grape_rails_logger.rb +78 -0
- data/sig/grape_rails_logger.rbs +47 -0
- metadata +257 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module GrapeRailsLogger
|
|
2
|
+
# Thread-safe storage for DB timing metrics per request
|
|
3
|
+
module Timings
|
|
4
|
+
# Use IsolatedExecutionState for Rails 7.1+ thread/Fiber safety
|
|
5
|
+
# Falls back to Thread.current for Rails 6-7.0
|
|
6
|
+
if defined?(ActiveSupport::IsolatedExecutionState)
|
|
7
|
+
def self.execution_state
|
|
8
|
+
ActiveSupport::IsolatedExecutionState
|
|
9
|
+
end
|
|
10
|
+
else
|
|
11
|
+
def self.execution_state
|
|
12
|
+
Thread.current
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.reset_db_runtime
|
|
17
|
+
state = execution_state
|
|
18
|
+
state[:grape_db_runtime] = 0
|
|
19
|
+
state[:grape_db_calls] = 0
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.db_runtime
|
|
23
|
+
execution_state[:grape_db_runtime] ||= 0
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.db_calls
|
|
27
|
+
execution_state[:grape_db_calls] ||= 0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.append_db_runtime(event)
|
|
31
|
+
state = execution_state
|
|
32
|
+
state[:grape_db_runtime] = (state[:grape_db_runtime] || 0) + event.duration
|
|
33
|
+
state[:grape_db_calls] = (state[:grape_db_calls] || 0) + 1
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require "active_support"
|
|
2
|
+
require "active_support/notifications"
|
|
3
|
+
require "grape"
|
|
4
|
+
|
|
5
|
+
# Load all required files first to ensure constants are available
|
|
6
|
+
# This must happen before the module definition (like other gems do)
|
|
7
|
+
require "grape_rails_logger/version"
|
|
8
|
+
require "grape_rails_logger/timings"
|
|
9
|
+
require "grape_rails_logger/status_extractor"
|
|
10
|
+
require "grape_rails_logger/subscriber"
|
|
11
|
+
require "grape_rails_logger/endpoint_patch"
|
|
12
|
+
require "grape_rails_logger/endpoint_wrapper"
|
|
13
|
+
require "grape_rails_logger/debug_tracer"
|
|
14
|
+
|
|
15
|
+
module GrapeRailsLogger
|
|
16
|
+
# Configuration for GrapeRailsLogger
|
|
17
|
+
#
|
|
18
|
+
# When running in Rails, use Rails.application.config.grape_rails_logger instead:
|
|
19
|
+
#
|
|
20
|
+
# @example Configure in Rails initializer
|
|
21
|
+
# # config/initializers/grape_rails_logger.rb
|
|
22
|
+
# Rails.application.config.grape_rails_logger.enabled = true
|
|
23
|
+
# Rails.application.config.grape_rails_logger.subscriber_class = CustomSubscriber
|
|
24
|
+
#
|
|
25
|
+
# @example Standalone usage (non-Rails)
|
|
26
|
+
# GrapeRailsLogger.config.enabled = false
|
|
27
|
+
class Config
|
|
28
|
+
attr_accessor :enabled, :subscriber_class, :logger, :tag
|
|
29
|
+
|
|
30
|
+
def initialize
|
|
31
|
+
@enabled = true
|
|
32
|
+
@subscriber_class = GrapeRequestLogSubscriber
|
|
33
|
+
@logger = nil # Default to nil, will use Rails.logger if available
|
|
34
|
+
@tag = "Grape" # Default tag for TaggedLogging
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Global configuration instance (for non-Rails usage)
|
|
39
|
+
#
|
|
40
|
+
# @return [Config] The configuration object
|
|
41
|
+
def self.config
|
|
42
|
+
@config ||= Config.new
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Configure the logger (for non-Rails usage)
|
|
46
|
+
#
|
|
47
|
+
# @yield [config] Yields the configuration object
|
|
48
|
+
# @example
|
|
49
|
+
# GrapeRailsLogger.configure do |config|
|
|
50
|
+
# config.enabled = false
|
|
51
|
+
# end
|
|
52
|
+
def self.configure
|
|
53
|
+
yield config
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Get the effective configuration (Rails-aware)
|
|
57
|
+
#
|
|
58
|
+
# @return [Config] The active configuration object
|
|
59
|
+
def self.effective_config
|
|
60
|
+
if defined?(Rails) && Rails.application && Rails.application.config.respond_to?(:grape_rails_logger)
|
|
61
|
+
# Use Rails config if available
|
|
62
|
+
rails_config = Rails.application.config.grape_rails_logger
|
|
63
|
+
config_obj = Config.new
|
|
64
|
+
config_obj.enabled = rails_config.enabled if rails_config.respond_to?(:enabled)
|
|
65
|
+
config_obj.subscriber_class = rails_config.subscriber_class if rails_config.respond_to?(:subscriber_class)
|
|
66
|
+
config_obj.logger = rails_config.logger if rails_config.respond_to?(:logger)
|
|
67
|
+
config_obj.tag = rails_config.tag if rails_config.respond_to?(:tag)
|
|
68
|
+
config_obj
|
|
69
|
+
else
|
|
70
|
+
# Fall back to module-level config for non-Rails usage
|
|
71
|
+
config
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Load Railtie for Rails integration
|
|
77
|
+
# Rails will automatically discover and initialize this Railtie
|
|
78
|
+
require "grape_rails_logger/railtie"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module GrapeRailsLogger
|
|
2
|
+
VERSION: String
|
|
3
|
+
|
|
4
|
+
class Config
|
|
5
|
+
attr_accessor enabled: bool
|
|
6
|
+
attr_accessor subscriber_class: Class
|
|
7
|
+
attr_accessor logger: Logger?
|
|
8
|
+
attr_accessor tag: String
|
|
9
|
+
|
|
10
|
+
def initialize: () -> void
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.config: () -> Config
|
|
14
|
+
def self.configure: () { (Config) -> void } -> void
|
|
15
|
+
def self.effective_config: () -> Config
|
|
16
|
+
|
|
17
|
+
module Timings
|
|
18
|
+
def self.execution_state: () -> untyped
|
|
19
|
+
def self.reset_db_runtime: () -> void
|
|
20
|
+
def self.db_runtime: () -> Float
|
|
21
|
+
def self.db_calls: () -> Integer
|
|
22
|
+
def self.append_db_runtime: (ActiveSupport::Notifications::Event event) -> void
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module StatusExtractor
|
|
26
|
+
def self.extract_status_from_exception: (Exception exception) -> Integer
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
module EndpointPatch
|
|
30
|
+
def build_stack: (*untyped args) -> untyped
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class GrapeRequestLogSubscriber
|
|
34
|
+
def initialize: () -> void
|
|
35
|
+
def grape_request: (ActiveSupport::Notifications::Event event) -> void
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class EndpointWrapper
|
|
39
|
+
def initialize: (untyped app, untyped endpoint) -> void
|
|
40
|
+
def call: (Hash[String, untyped] env) -> Array[Integer, Hash[String, String], Array[String]]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class DebugTracer < Grape::Middleware::Base
|
|
44
|
+
def call!: (Hash[String, untyped] env) -> Array[Integer, Hash[String, String], Array[String]]
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
metadata
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: grape_rails_logger
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.1.3
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- amkisko
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: activesupport
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '6.0'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '9.0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '6.0'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '9.0'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: railties
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - ">="
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '6.0'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '9.0'
|
|
42
|
+
type: :runtime
|
|
43
|
+
prerelease: false
|
|
44
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '6.0'
|
|
49
|
+
- - "<"
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '9.0'
|
|
52
|
+
- !ruby/object:Gem::Dependency
|
|
53
|
+
name: grape
|
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ">="
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '1.6'
|
|
59
|
+
- - "<"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3.0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '1.6'
|
|
69
|
+
- - "<"
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '3.0'
|
|
72
|
+
- !ruby/object:Gem::Dependency
|
|
73
|
+
name: rspec
|
|
74
|
+
requirement: !ruby/object:Gem::Requirement
|
|
75
|
+
requirements:
|
|
76
|
+
- - "~>"
|
|
77
|
+
- !ruby/object:Gem::Version
|
|
78
|
+
version: '3.12'
|
|
79
|
+
type: :development
|
|
80
|
+
prerelease: false
|
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
82
|
+
requirements:
|
|
83
|
+
- - "~>"
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: '3.12'
|
|
86
|
+
- !ruby/object:Gem::Dependency
|
|
87
|
+
name: webmock
|
|
88
|
+
requirement: !ruby/object:Gem::Requirement
|
|
89
|
+
requirements:
|
|
90
|
+
- - "~>"
|
|
91
|
+
- !ruby/object:Gem::Version
|
|
92
|
+
version: '3'
|
|
93
|
+
type: :development
|
|
94
|
+
prerelease: false
|
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
96
|
+
requirements:
|
|
97
|
+
- - "~>"
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '3'
|
|
100
|
+
- !ruby/object:Gem::Dependency
|
|
101
|
+
name: rake
|
|
102
|
+
requirement: !ruby/object:Gem::Requirement
|
|
103
|
+
requirements:
|
|
104
|
+
- - "~>"
|
|
105
|
+
- !ruby/object:Gem::Version
|
|
106
|
+
version: '13.0'
|
|
107
|
+
type: :development
|
|
108
|
+
prerelease: false
|
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
110
|
+
requirements:
|
|
111
|
+
- - "~>"
|
|
112
|
+
- !ruby/object:Gem::Version
|
|
113
|
+
version: '13.0'
|
|
114
|
+
- !ruby/object:Gem::Dependency
|
|
115
|
+
name: simplecov
|
|
116
|
+
requirement: !ruby/object:Gem::Requirement
|
|
117
|
+
requirements:
|
|
118
|
+
- - "~>"
|
|
119
|
+
- !ruby/object:Gem::Version
|
|
120
|
+
version: '0.21'
|
|
121
|
+
type: :development
|
|
122
|
+
prerelease: false
|
|
123
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
124
|
+
requirements:
|
|
125
|
+
- - "~>"
|
|
126
|
+
- !ruby/object:Gem::Version
|
|
127
|
+
version: '0.21'
|
|
128
|
+
- !ruby/object:Gem::Dependency
|
|
129
|
+
name: rspec_junit_formatter
|
|
130
|
+
requirement: !ruby/object:Gem::Requirement
|
|
131
|
+
requirements:
|
|
132
|
+
- - "~>"
|
|
133
|
+
- !ruby/object:Gem::Version
|
|
134
|
+
version: '0.6'
|
|
135
|
+
type: :development
|
|
136
|
+
prerelease: false
|
|
137
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
138
|
+
requirements:
|
|
139
|
+
- - "~>"
|
|
140
|
+
- !ruby/object:Gem::Version
|
|
141
|
+
version: '0.6'
|
|
142
|
+
- !ruby/object:Gem::Dependency
|
|
143
|
+
name: simplecov-cobertura
|
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
|
145
|
+
requirements:
|
|
146
|
+
- - "~>"
|
|
147
|
+
- !ruby/object:Gem::Version
|
|
148
|
+
version: '3'
|
|
149
|
+
type: :development
|
|
150
|
+
prerelease: false
|
|
151
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
152
|
+
requirements:
|
|
153
|
+
- - "~>"
|
|
154
|
+
- !ruby/object:Gem::Version
|
|
155
|
+
version: '3'
|
|
156
|
+
- !ruby/object:Gem::Dependency
|
|
157
|
+
name: standard
|
|
158
|
+
requirement: !ruby/object:Gem::Requirement
|
|
159
|
+
requirements:
|
|
160
|
+
- - "~>"
|
|
161
|
+
- !ruby/object:Gem::Version
|
|
162
|
+
version: '1.0'
|
|
163
|
+
type: :development
|
|
164
|
+
prerelease: false
|
|
165
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
166
|
+
requirements:
|
|
167
|
+
- - "~>"
|
|
168
|
+
- !ruby/object:Gem::Version
|
|
169
|
+
version: '1.0'
|
|
170
|
+
- !ruby/object:Gem::Dependency
|
|
171
|
+
name: appraisal
|
|
172
|
+
requirement: !ruby/object:Gem::Requirement
|
|
173
|
+
requirements:
|
|
174
|
+
- - "~>"
|
|
175
|
+
- !ruby/object:Gem::Version
|
|
176
|
+
version: '2.4'
|
|
177
|
+
type: :development
|
|
178
|
+
prerelease: false
|
|
179
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
180
|
+
requirements:
|
|
181
|
+
- - "~>"
|
|
182
|
+
- !ruby/object:Gem::Version
|
|
183
|
+
version: '2.4'
|
|
184
|
+
- !ruby/object:Gem::Dependency
|
|
185
|
+
name: memory_profiler
|
|
186
|
+
requirement: !ruby/object:Gem::Requirement
|
|
187
|
+
requirements:
|
|
188
|
+
- - "~>"
|
|
189
|
+
- !ruby/object:Gem::Version
|
|
190
|
+
version: '1.0'
|
|
191
|
+
type: :development
|
|
192
|
+
prerelease: false
|
|
193
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
194
|
+
requirements:
|
|
195
|
+
- - "~>"
|
|
196
|
+
- !ruby/object:Gem::Version
|
|
197
|
+
version: '1.0'
|
|
198
|
+
- !ruby/object:Gem::Dependency
|
|
199
|
+
name: rbs
|
|
200
|
+
requirement: !ruby/object:Gem::Requirement
|
|
201
|
+
requirements:
|
|
202
|
+
- - "~>"
|
|
203
|
+
- !ruby/object:Gem::Version
|
|
204
|
+
version: '3.0'
|
|
205
|
+
type: :development
|
|
206
|
+
prerelease: false
|
|
207
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
208
|
+
requirements:
|
|
209
|
+
- - "~>"
|
|
210
|
+
- !ruby/object:Gem::Version
|
|
211
|
+
version: '3.0'
|
|
212
|
+
description: Rails-compatible, ActiveSupport-integrated logging for Grape APIs, including
|
|
213
|
+
request context and ActiveRecord timings.
|
|
214
|
+
email:
|
|
215
|
+
- contact@kiskolabs.com
|
|
216
|
+
executables: []
|
|
217
|
+
extensions: []
|
|
218
|
+
extra_rdoc_files: []
|
|
219
|
+
files:
|
|
220
|
+
- CHANGELOG.md
|
|
221
|
+
- LICENSE.md
|
|
222
|
+
- README.md
|
|
223
|
+
- lib/grape_rails_logger.rb
|
|
224
|
+
- lib/grape_rails_logger/debug_tracer.rb
|
|
225
|
+
- lib/grape_rails_logger/endpoint_patch.rb
|
|
226
|
+
- lib/grape_rails_logger/endpoint_wrapper.rb
|
|
227
|
+
- lib/grape_rails_logger/railtie.rb
|
|
228
|
+
- lib/grape_rails_logger/status_extractor.rb
|
|
229
|
+
- lib/grape_rails_logger/subscriber.rb
|
|
230
|
+
- lib/grape_rails_logger/timings.rb
|
|
231
|
+
- lib/grape_rails_logger/version.rb
|
|
232
|
+
- sig/grape_rails_logger.rbs
|
|
233
|
+
homepage: https://github.com/amkisko/grape_rails_logger.rb
|
|
234
|
+
licenses:
|
|
235
|
+
- MIT
|
|
236
|
+
metadata:
|
|
237
|
+
source_code_uri: https://github.com/amkisko/grape_rails_logger.rb
|
|
238
|
+
changelog_uri: https://github.com/amkisko/grape_rails_logger.rb/blob/main/CHANGELOG.md
|
|
239
|
+
bug_tracker_uri: https://github.com/amkisko/grape_rails_logger.rb/issues
|
|
240
|
+
rdoc_options: []
|
|
241
|
+
require_paths:
|
|
242
|
+
- lib
|
|
243
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
244
|
+
requirements:
|
|
245
|
+
- - ">="
|
|
246
|
+
- !ruby/object:Gem::Version
|
|
247
|
+
version: '2.7'
|
|
248
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
249
|
+
requirements:
|
|
250
|
+
- - ">="
|
|
251
|
+
- !ruby/object:Gem::Version
|
|
252
|
+
version: '0'
|
|
253
|
+
requirements: []
|
|
254
|
+
rubygems_version: 3.6.9
|
|
255
|
+
specification_version: 4
|
|
256
|
+
summary: Unified JSON request logging for Grape on Rails with DB timing.
|
|
257
|
+
test_files: []
|