event_logger_rails 0.2.1 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +291 -26
- data/app/controllers/concerns/event_logger_rails/loggable_controller.rb +19 -0
- data/app/models/concerns/event_logger_rails/loggable_model.rb +19 -0
- data/lib/event_logger_rails/current_request.rb +9 -0
- data/lib/event_logger_rails/emitter.rb +31 -0
- data/lib/event_logger_rails/engine.rb +23 -0
- data/lib/event_logger_rails/event.rb +81 -0
- data/lib/event_logger_rails/exceptions/invalid_logger_level.rb +13 -2
- data/lib/event_logger_rails/exceptions/unregistered_event.rb +12 -2
- data/lib/event_logger_rails/extensions/loggable.rb +23 -0
- data/lib/event_logger_rails/json_logger.rb +17 -0
- data/lib/event_logger_rails/message.rb +20 -0
- data/lib/event_logger_rails/middleware/capture_request_details.rb +36 -0
- data/lib/event_logger_rails/output.rb +61 -0
- data/lib/event_logger_rails/version.rb +1 -1
- data/lib/event_logger_rails.rb +26 -10
- data/lib/generators/event_logger_rails/install_generator.rb +6 -2
- data/lib/generators/event_logger_rails/templates/event_logger_rails.yml +17 -15
- metadata +23 -12
- data/app/controllers/concerns/event_logger_rails/loggable.rb +0 -29
- data/lib/event_logger_rails/event_logger.rb +0 -97
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13e98d21b691d869d533906e17ff9cd6b7cc4dc9fe53c3956233659c7b8f2f5b
|
4
|
+
data.tar.gz: e8320f015f1e3840304c532b7bd951676a36e5cedca3d7b2967d3a40119a36a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c892160afbb1b52c6875605bb9c578db3cb03b28b074bdd08d611753b62593edf7cafbf5dbe7928022f4dae22b55a4889ef20711aac6a460bfda2618f383527
|
7
|
+
data.tar.gz: af73afed340dcdd9a296fd86fec42574c05f4bb47171c3a0c43d9f0247faba8aebf86d2004d50447074bb89ca956b5bbbc7f1fd8ef2613944ec04e453a7ed842
|
data/README.md
CHANGED
@@ -1,67 +1,294 @@
|
|
1
|
-
|
1
|
+
## 🔌 EventLoggerRails 💾
|
2
2
|
|
3
|
-
|
3
|
+
![Elara](elara.png?raw=true)
|
4
|
+
*Elara, the mascot for `EventLoggerRails`*
|
5
|
+
|
6
|
+
Are you tired of navigating through logs as if you're lost in the labyrinth of the Wired, searching for that elusive piece of data? Say "Hello, World!" to `EventLoggerRails`, the Rails engine transmuting your logs into enlightened gems of understanding. 💎
|
7
|
+
|
8
|
+
### Visualize This
|
9
|
+
|
10
|
+
In a single, centralized config file, decipher the events that pulse through the veins of your business. Once set, let `EventLoggerRails` weave them into intricate patterns of JSON logs that shimmer like a digital mirage. 🎇
|
11
|
+
|
12
|
+
### Yet, The Nexus Expands
|
13
|
+
|
14
|
+
Channel these JSON enigmas directly into analytic realms like OpenSearch. There, witness the alchemy of data taking form through real-time visualizations and analysis. 📊✨
|
15
|
+
|
16
|
+
### Why Choose `EventLoggerRails`?
|
17
|
+
|
18
|
+
- 🚀 **Fast Setup**: Get your logging up and running in minutes, not hours!
|
19
|
+
- 🌐 **Team-Friendly Event Registry**: Simplify how your team defines and logs business-critical events.
|
20
|
+
- 📚 **Readable**: Logs in a clean, JSON-formatted structure for easy parsing and analysis.
|
21
|
+
- 🔍 **In-Depth Insight**: Elevate your business process analysis with granular, structured logging.
|
22
|
+
|
23
|
+
Don't let crucial events get lost in the digital void. Make your app's logging as unforgettable as your first journey into the Wired with `EventLoggerRails`!
|
24
|
+
|
25
|
+
### Huh?
|
26
|
+
|
27
|
+
Ok, so Elara might be a little zealous about our project, and she seems to be stuck in a 90's anime. Don't let that dissuade you from using this engine, though.
|
28
|
+
|
29
|
+
Our no-nonsense project description: **`EventLoggerRails` is a Rails engine for emitting structured events in logs during the execution of business processes for analysis and visualization.
|
30
|
+
It allows teams to define events in a simple, centralized configuration file, and then log those events in JSON format for further processing.**
|
4
31
|
|
5
32
|
## Usage
|
6
33
|
|
7
|
-
You can define a registry of events
|
8
|
-
The events
|
34
|
+
You can define a registry of events your application emits via the config file (`config/event_logger_rails.yml`).
|
35
|
+
The events you define are placed in the config file under the corresponding environment. Most events belong in `shared`, though you may want to define different
|
36
|
+
events or event characteristics per environment.
|
9
37
|
|
10
|
-
For example, to register a user signup event, first define the event as a registered event
|
38
|
+
For example, to register a user signup event, first define the event as a registered event. You must include a `description` for the event, and you may
|
39
|
+
optionally include a `level` to use for that specific event.
|
11
40
|
|
12
41
|
```yaml
|
13
|
-
|
42
|
+
shared:
|
14
43
|
user:
|
15
44
|
signup:
|
16
|
-
success:
|
17
|
-
|
45
|
+
success:
|
46
|
+
description: 'Indicates a successful user signup.'
|
47
|
+
failure:
|
48
|
+
description: 'Indicates a user signup was not successful.'
|
49
|
+
level: 'error'
|
18
50
|
```
|
19
51
|
|
20
|
-
|
52
|
+
### Logging in Controllers
|
53
|
+
|
54
|
+
Continuing this example, we'll want to log the events we registered. To do so, include the `EventLoggerRails::LoggableController` concern in the controller that
|
55
|
+
processes user signup's and call the `log_event` method to log details about the event:
|
21
56
|
|
22
57
|
```ruby
|
23
58
|
class UsersController < ApplicationController
|
24
|
-
include EventLoggerRails::
|
59
|
+
include EventLoggerRails::LoggableController
|
25
60
|
|
26
61
|
def create
|
27
62
|
user = User.new(user_params)
|
28
63
|
if user.save
|
29
|
-
log_event
|
64
|
+
log_event 'user.signup.success'
|
30
65
|
redirect_to dashboard_path
|
31
66
|
else
|
32
|
-
log_event
|
67
|
+
log_event 'user.signup.failure', data: { errors: user.errors.full_messages }
|
33
68
|
render :new
|
34
|
-
|
69
|
+
end
|
35
70
|
end
|
36
71
|
end
|
37
72
|
```
|
38
73
|
|
39
74
|
In this example, a possible successful signup could be structured like this:
|
40
75
|
|
41
|
-
```
|
42
|
-
|
76
|
+
```json
|
77
|
+
{
|
78
|
+
"environment": "development",
|
79
|
+
"format": "application/x-www-form-urlencoded;charset=UTF-8",
|
80
|
+
"host": "d6aeb6b0516c",
|
81
|
+
"id": "2b8f44c1-0e42-4a5f-84b8-52659990d138",
|
82
|
+
"service_name": "DummyApp",
|
83
|
+
"level": "WARN",
|
84
|
+
"method": "POST",
|
85
|
+
"parameters": {
|
86
|
+
"authenticity_token": "[FILTERED]",
|
87
|
+
"user": {
|
88
|
+
"email": "princess@leia.com",
|
89
|
+
"password": "[FILTERED]"
|
90
|
+
}
|
91
|
+
},
|
92
|
+
"path": "/users",
|
93
|
+
"remote_ip": "172.20.0.1",
|
94
|
+
"timestamp": "2023-09-30T06:47:16.938+00:00",
|
95
|
+
"event_identifier": "user.signup.success",
|
96
|
+
"event_description": "Indicates a user signup was successful.",
|
97
|
+
"email": "princess@leia.com",
|
98
|
+
"action": "create",
|
99
|
+
"controller": "Registrations"
|
100
|
+
}
|
43
101
|
```
|
44
102
|
|
45
103
|
...while a failed signup might look like this:
|
46
104
|
|
105
|
+
```json
|
106
|
+
{
|
107
|
+
"environment": "development",
|
108
|
+
"format": "application/x-www-form-urlencoded;charset=UTF-8",
|
109
|
+
"host": "d6aeb6b0516c",
|
110
|
+
"id": "2b8f44c1-0e42-4a5f-84b8-52656690d138",
|
111
|
+
"service_name": "DummyApp",
|
112
|
+
"level": "ERROR",
|
113
|
+
"method": "POST",
|
114
|
+
"parameters": {
|
115
|
+
"authenticity_token": "[FILTERED]",
|
116
|
+
"user": {
|
117
|
+
"email": "",
|
118
|
+
"password": "[FILTERED]"
|
119
|
+
},
|
120
|
+
},
|
121
|
+
"path": "/users",
|
122
|
+
"remote_ip": "172.20.0.1",
|
123
|
+
"timestamp": "2023-09-30T06:47:16.928+00:00",
|
124
|
+
"event_identifier": "user.signup.failure",
|
125
|
+
"event_description": "Indicates a user signup was not successful.",
|
126
|
+
"errors": [
|
127
|
+
"Email can't be blank",
|
128
|
+
"Password can't be blank"
|
129
|
+
],
|
130
|
+
"email": "princess@leia.com",
|
131
|
+
"action": "create",
|
132
|
+
"controller": "Registrations"
|
133
|
+
}
|
47
134
|
```
|
48
|
-
|
135
|
+
|
136
|
+
Note how the log entry from the previous example contains the data passed in via the optional `data` argument.
|
137
|
+
|
138
|
+
You can also provide a logger level as an optional argument if you need to specify a logger level other than the default. If you provide a logger level, it
|
139
|
+
will override the configured event level and the default logger level.
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
log_event 'user.signup.failure', level: :info, data: { errors: user.errors }
|
49
143
|
```
|
50
144
|
|
51
|
-
|
145
|
+
This will output an event with the corresponding severity level. You must provide a valid logger level (`:debug, :info, :warn, :error, or :unknown`).
|
52
146
|
|
147
|
+
```json
|
148
|
+
{
|
149
|
+
"environment": "development",
|
150
|
+
"format": "application/x-www-form-urlencoded;charset=UTF-8",
|
151
|
+
"host": "d6aeb6b0516c",
|
152
|
+
"id": "2b8f44c1-0e42-4a5f-84b8-52656690d138",
|
153
|
+
"service_name": "DummyApp",
|
154
|
+
"level": "INFO",
|
155
|
+
"method": "POST",
|
156
|
+
"parameters": {
|
157
|
+
"authenticity_token": "[FILTERED]",
|
158
|
+
"user": {
|
159
|
+
"email": "",
|
160
|
+
"password": "[FILTERED]"
|
161
|
+
},
|
162
|
+
},
|
163
|
+
"path": "/users",
|
164
|
+
"remote_ip": "172.20.0.1",
|
165
|
+
"timestamp": "2023-09-30T06:47:16.928+00:00",
|
166
|
+
"event_identifier": "user.signup.failure",
|
167
|
+
"event_description": "Indicates a user signup was not successful.",
|
168
|
+
"errors": [
|
169
|
+
"Email can't be blank",
|
170
|
+
"Password can't be blank"
|
171
|
+
],
|
172
|
+
"email": "princess@leia.com",
|
173
|
+
"action": "create",
|
174
|
+
"controller": "Registrations"
|
175
|
+
}
|
53
176
|
```
|
54
|
-
|
177
|
+
|
178
|
+
### Logging in Models
|
179
|
+
|
180
|
+
You can also log events from within models by including the `EventLoggerRails::LoggableModel` concern and calling `log_event`.
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
class User < ApplicationRecord
|
184
|
+
include EventLoggerRails::LoggableModel
|
185
|
+
|
186
|
+
after_create :log_signup
|
187
|
+
|
188
|
+
private
|
189
|
+
|
190
|
+
def log_signup
|
191
|
+
log_event 'user.signup.success', data: { email: }
|
192
|
+
end
|
193
|
+
end
|
55
194
|
```
|
56
195
|
|
57
|
-
|
196
|
+
By default, `EventLoggerRails` will include the model name, instance ID, and whatever data is passed.
|
197
|
+
|
198
|
+
```json
|
199
|
+
{
|
200
|
+
"environment": "development",
|
201
|
+
"format": "application/x-www-form-urlencoded;charset=UTF-8",
|
202
|
+
"host": "d6aeb6b0516c",
|
203
|
+
"id": "2b8f44c1-0e42-4a5f-84b8-52652332d138",
|
204
|
+
"service_name": "DummyApp",
|
205
|
+
"level": "WARN",
|
206
|
+
"method": "POST",
|
207
|
+
"parameters": {
|
208
|
+
"authenticity_token": "[FILTERED]",
|
209
|
+
"user": {
|
210
|
+
"email": "princess@leia.com",
|
211
|
+
"password": "[FILTERED]"
|
212
|
+
}
|
213
|
+
},
|
214
|
+
"path": "/users",
|
215
|
+
"remote_ip": "172.20.0.1",
|
216
|
+
"timestamp": "2023-09-30T06:47:16.817+00:00",
|
217
|
+
"event_identifier": "user.signup.success",
|
218
|
+
"event_description": "Indicates a user signup was successful.",
|
219
|
+
"email": "princess@leia.com",
|
220
|
+
"model": "User",
|
221
|
+
"instance_id": 41
|
222
|
+
}
|
223
|
+
```
|
224
|
+
|
225
|
+
### Logging Everywhere Else
|
58
226
|
|
227
|
+
You can log events from anywhere inside of your application by calling `EventLoggerRails.log` directly, though you won't get the additional context
|
228
|
+
from the controller or model.
|
229
|
+
|
230
|
+
```ruby
|
231
|
+
EventLoggerRails.log 'user.signup.success', level: :info, data: { user_id: @user.id }
|
59
232
|
```
|
60
|
-
|
233
|
+
|
234
|
+
### Errors
|
235
|
+
|
236
|
+
There are two expected errors which are handled by `EventLoggerRails`: an unregistered event and an invalid logger level. Both will result
|
237
|
+
in a log entry with an event corresponding to the error, and the severity level will be set to `ERROR`.
|
238
|
+
|
239
|
+
If you fail to register an event, the logger will emit an `event_logger_rails.event.unregistered` event:
|
240
|
+
|
241
|
+
```json
|
242
|
+
{
|
243
|
+
"environment": "development",
|
244
|
+
"format": "application/x-www-form-urlencoded;charset=UTF-8",
|
245
|
+
"host": "d6aeb6b0516c",
|
246
|
+
"id": "94c5ffe9-1bd8-4e04-88a3-478958e242b0",
|
247
|
+
"service_name": "DummyApp",
|
248
|
+
"level": "ERROR",
|
249
|
+
"method": "POST",
|
250
|
+
"parameters": {
|
251
|
+
"authenticity_token": "[FILTERED]",
|
252
|
+
"user": {
|
253
|
+
"email": "",
|
254
|
+
"password": "[FILTERED]"
|
255
|
+
}
|
256
|
+
},
|
257
|
+
"path": "/users",
|
258
|
+
"remote_ip": "172.20.0.1",
|
259
|
+
"timestamp": "2023-09-30T07:03:34.993+00:00",
|
260
|
+
"event_identifier": "event_logger_rails.event.unregistered",
|
261
|
+
"event_description": "Indicates provided event was unregistered.",
|
262
|
+
"message": "Event provided not registered: foo.bar"
|
263
|
+
}
|
61
264
|
```
|
62
265
|
|
63
|
-
|
64
|
-
|
266
|
+
If you provide an invalid log level, the logger will emit an `event_logger_rails.logger_level.invalid` event:
|
267
|
+
|
268
|
+
```json
|
269
|
+
{
|
270
|
+
"environment": "development",
|
271
|
+
"format": "application/x-www-form-urlencoded;charset=UTF-8",
|
272
|
+
"host": "d6aeb6b0516c",
|
273
|
+
"id": "11541423-0008-4cc7-aef7-1e4af9a801d7",
|
274
|
+
"service_name": "DummyApp",
|
275
|
+
"level": "ERROR",
|
276
|
+
"method": "POST",
|
277
|
+
"parameters": {
|
278
|
+
"authenticity_token": "[FILTERED]",
|
279
|
+
"user": {
|
280
|
+
"email": "",
|
281
|
+
"password": "[FILTERED]"
|
282
|
+
}
|
283
|
+
},
|
284
|
+
"path": "/users",
|
285
|
+
"remote_ip": "172.20.0.1",
|
286
|
+
"timestamp": "2023-09-30T07:04:52.623+00:00",
|
287
|
+
"event_identifier": "event_logger_rails.logger_level.invalid",
|
288
|
+
"event_description": "Indicates provided level was invalid.",
|
289
|
+
"message": "Invalid logger level provided: 'foobar'. Valid levels: :debug, :info, :warn, :error, :unknown."
|
290
|
+
}
|
291
|
+
```
|
65
292
|
|
66
293
|
## Installation
|
67
294
|
|
@@ -74,27 +301,65 @@ gem 'event_logger_rails'
|
|
74
301
|
And then execute:
|
75
302
|
|
76
303
|
```bash
|
77
|
-
|
304
|
+
bundle
|
78
305
|
```
|
79
306
|
|
80
307
|
Or install it yourself as:
|
81
308
|
|
82
309
|
```bash
|
83
|
-
|
310
|
+
gem install event_logger_rails
|
84
311
|
```
|
85
312
|
|
86
313
|
Run the install generator to create a config file (`config/event_logger_rails.yml`):
|
87
314
|
|
88
315
|
```bash
|
89
|
-
|
316
|
+
bin/rails generate event_logger_rails:install
|
90
317
|
```
|
91
318
|
|
92
319
|
Add your events to the generated config file following the structure of the examples.
|
93
320
|
|
321
|
+
You can specify a default level `EventLoggerRails` will use if a level is not included in the call to the logger or configured as a default for the provided event.
|
322
|
+
This default level is set to `:warn` unless otherwise specified.
|
323
|
+
|
324
|
+
```ruby
|
325
|
+
Rails.application.configure do |config|
|
326
|
+
config.event_logger_rails.default_level = :info
|
327
|
+
end
|
328
|
+
```
|
329
|
+
|
330
|
+
By default, `EventLoggerRails` outputs to a separate log file (`log/event_logger_rails.#{Rails.env}.log`) from normal Rails log output, allowing
|
331
|
+
you to ingest these logs independently. If you wish to set an alternative log device to capture output, you can configure it in `config/application.rb`:
|
332
|
+
|
333
|
+
```ruby
|
334
|
+
Rails.application.configure do |config|
|
335
|
+
config.event_logger_rails.logdev = 'path/to/log.file'
|
336
|
+
end
|
337
|
+
```
|
338
|
+
|
339
|
+
Some platforms require logging output to be sent to $STDOUT. You can configure this as an output device easily enough.
|
340
|
+
|
341
|
+
```ruby
|
342
|
+
Rails.application.configure do |config|
|
343
|
+
config.event_logger_rails.logdev = $stdout
|
344
|
+
end
|
345
|
+
```
|
346
|
+
|
347
|
+
You can also configure the Rails logger to use `EventLoggerRails::JsonLogger` to render structured logs in JSON format with the additional app and request data.
|
348
|
+
|
349
|
+
```ruby
|
350
|
+
Rails.application.configure do
|
351
|
+
config.colorize_logging = false
|
352
|
+
config.log_level = ENV.fetch('RAILS_LOG_LEVEL', :info)
|
353
|
+
logger = EventLoggerRails::JsonLogger.new($stdout)
|
354
|
+
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
355
|
+
end
|
356
|
+
```
|
357
|
+
|
94
358
|
## Contributing
|
95
359
|
|
96
|
-
|
360
|
+
Your inputs echo in this realm. Venture forth and materialize your thoughts through a PR.
|
97
361
|
|
98
362
|
## License
|
99
363
|
|
100
364
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
365
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EventLoggerRails
|
4
|
+
##
|
5
|
+
# Provides event logging with relevant controller/request data.
|
6
|
+
module LoggableController
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
include EventLoggerRails::Extensions::Loggable
|
9
|
+
|
10
|
+
def optional_data
|
11
|
+
{
|
12
|
+
action: action_name,
|
13
|
+
controller: controller_name.camelcase
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
private :optional_data
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EventLoggerRails
|
4
|
+
##
|
5
|
+
# Provides event logging with relevant model data.
|
6
|
+
module LoggableModel
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
include EventLoggerRails::Extensions::Loggable
|
9
|
+
|
10
|
+
def optional_data
|
11
|
+
{
|
12
|
+
model: self.class.name,
|
13
|
+
instance_id: id
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
private :optional_data
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EventLoggerRails
|
4
|
+
##
|
5
|
+
# Processes events, sending data to logger.
|
6
|
+
class Emitter
|
7
|
+
def initialize(logdev:)
|
8
|
+
@logger = JsonLogger.new(logdev)
|
9
|
+
end
|
10
|
+
|
11
|
+
def log(event, level:, data: {})
|
12
|
+
Event.new(event).validate! do |validated_event|
|
13
|
+
message = Message.new(event: validated_event, data:)
|
14
|
+
level = level || validated_event.level || EventLoggerRails.default_level
|
15
|
+
log_message(message, level.to_sym)
|
16
|
+
end
|
17
|
+
rescue Exceptions::UnregisteredEvent, Exceptions::InvalidLoggerLevel => error
|
18
|
+
log(error.event, level: :error, data: { message: error.message })
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :logger
|
24
|
+
|
25
|
+
def log_message(message, level)
|
26
|
+
logger.send(level) { message }
|
27
|
+
rescue NoMethodError
|
28
|
+
raise Exceptions::InvalidLoggerLevel.new(logger_level: level)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,7 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module EventLoggerRails
|
4
|
+
##
|
5
|
+
# Engine for plugging into Rails
|
4
6
|
class Engine < ::Rails::Engine
|
5
7
|
isolate_namespace EventLoggerRails
|
8
|
+
|
9
|
+
config.generators do |generator|
|
10
|
+
generator.test_framework :rspec
|
11
|
+
end
|
12
|
+
|
13
|
+
config.event_logger_rails = ActiveSupport::OrderedOptions.new
|
14
|
+
config.event_logger_rails.logdev = "log/event_logger_rails.#{Rails.env}.log"
|
15
|
+
config.event_logger_rails.default_level = :warn
|
16
|
+
|
17
|
+
initializer 'event_logger_rails.add_middleware' do |app|
|
18
|
+
app.middleware.use Middleware::CaptureRequestDetails
|
19
|
+
end
|
20
|
+
|
21
|
+
config.after_initialize do |app|
|
22
|
+
EventLoggerRails.setup do |engine|
|
23
|
+
engine.default_level = app.config.event_logger_rails.default_level
|
24
|
+
engine.logdev = app.config.event_logger_rails.logdev
|
25
|
+
engine.registered_events = Rails.application.config_for(:event_logger_rails)
|
26
|
+
engine.sensitive_fields = app.config.filter_parameters
|
27
|
+
end
|
28
|
+
end
|
6
29
|
end
|
7
30
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EventLoggerRails
|
4
|
+
##
|
5
|
+
# Models an event for logging.
|
6
|
+
class Event
|
7
|
+
DEFAULT_EVENTS = {
|
8
|
+
'event_logger_rails.logger_level.invalid' => {
|
9
|
+
description: 'Indicates provided level was invalid.',
|
10
|
+
level: :error
|
11
|
+
},
|
12
|
+
'event_logger_rails.event.unregistered' => {
|
13
|
+
description: 'Indicates provided event was unregistered.',
|
14
|
+
level: :error
|
15
|
+
},
|
16
|
+
'event_logger_rails.event.testing' => {
|
17
|
+
description: 'Event reserved for testing.',
|
18
|
+
level: :warn
|
19
|
+
}
|
20
|
+
}.freeze
|
21
|
+
private_constant :DEFAULT_EVENTS
|
22
|
+
|
23
|
+
attr_reader :identifier, :description, :level
|
24
|
+
|
25
|
+
def initialize(provided_identifier)
|
26
|
+
@provided_identifier = provided_identifier.to_s
|
27
|
+
|
28
|
+
if (default_event = DEFAULT_EVENTS[@provided_identifier])
|
29
|
+
default_registration = [@provided_identifier, *default_event&.values]
|
30
|
+
end
|
31
|
+
|
32
|
+
@identifier, @description, @level = default_registration || config_registration
|
33
|
+
end
|
34
|
+
|
35
|
+
def merge(...)
|
36
|
+
to_hash.merge(...)
|
37
|
+
end
|
38
|
+
|
39
|
+
def valid?
|
40
|
+
identifier.present?
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate!
|
44
|
+
raise Exceptions::UnregisteredEvent.new(unregistered_event: self) unless valid?
|
45
|
+
|
46
|
+
yield(self)
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_hash
|
50
|
+
{
|
51
|
+
event_identifier: identifier,
|
52
|
+
event_description: description
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
identifier&.to_s || provided_identifier.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
def ==(other)
|
61
|
+
to_s == other.to_s
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
attr_reader :provided_identifier
|
67
|
+
|
68
|
+
def config_registration
|
69
|
+
parsed_event = provided_identifier.split('.').map(&:to_sym)
|
70
|
+
config = EventLoggerRails.registered_events.dig(*parsed_event)
|
71
|
+
case config
|
72
|
+
in { description:, level: }
|
73
|
+
[provided_identifier, description, level]
|
74
|
+
in { description: }
|
75
|
+
[provided_identifier, description, nil]
|
76
|
+
else
|
77
|
+
[nil, nil, nil]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -5,11 +5,22 @@ module EventLoggerRails
|
|
5
5
|
##
|
6
6
|
# Indicates invalid log level provided.
|
7
7
|
class InvalidLoggerLevel < StandardError
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :event
|
9
9
|
|
10
10
|
def initialize(logger_level:)
|
11
|
-
super
|
11
|
+
super
|
12
|
+
@event = Event.new('event_logger_rails.logger_level.invalid')
|
13
|
+
@logger_level = logger_level
|
14
|
+
end
|
15
|
+
|
16
|
+
def message
|
17
|
+
"Invalid logger level provided: '#{logger_level.to_sym}'. " \
|
18
|
+
'Valid levels: :debug, :info, :warn, :error, :unknown.'
|
12
19
|
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :logger_level
|
13
24
|
end
|
14
25
|
end
|
15
26
|
end
|
@@ -5,11 +5,21 @@ module EventLoggerRails
|
|
5
5
|
##
|
6
6
|
# Indicates event provided not registered.
|
7
7
|
class UnregisteredEvent < StandardError
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :event
|
9
9
|
|
10
10
|
def initialize(unregistered_event:)
|
11
|
-
super(
|
11
|
+
super()
|
12
|
+
@event = Event.new('event_logger_rails.event.unregistered')
|
13
|
+
@unregistered_event = unregistered_event
|
14
|
+
end
|
15
|
+
|
16
|
+
def message
|
17
|
+
"Event provided not registered: #{unregistered_event}"
|
12
18
|
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :unregistered_event
|
13
23
|
end
|
14
24
|
end
|
15
25
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EventLoggerRails
|
4
|
+
module Extensions
|
5
|
+
##
|
6
|
+
# Provides event logging with relevant model data.
|
7
|
+
module Loggable
|
8
|
+
def log_event(event, **kwargs)
|
9
|
+
EventLoggerRails.log(
|
10
|
+
event,
|
11
|
+
level: kwargs[:level] || nil,
|
12
|
+
data: (kwargs[:data] || {}).merge(optional_data)
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def optional_data
|
19
|
+
{}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EventLoggerRails
|
4
|
+
##
|
5
|
+
# Writes log entries in JSON format
|
6
|
+
class JsonLogger < ::Logger
|
7
|
+
include ActiveSupport::LoggerSilence
|
8
|
+
|
9
|
+
def initialize(...)
|
10
|
+
super(...)
|
11
|
+
@formatter = proc do |level, timestamp, _progname, message|
|
12
|
+
output = Output.new(level:, timestamp:, message:)
|
13
|
+
"#{output.to_json}\n"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EventLoggerRails
|
4
|
+
##
|
5
|
+
# Models a message sent to the logger containing event and optional data
|
6
|
+
class Message
|
7
|
+
def initialize(event:, data: {})
|
8
|
+
@event = event
|
9
|
+
@data = data
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_hash
|
13
|
+
event.merge(data)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :event, :data
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../current_request'
|
4
|
+
|
5
|
+
module EventLoggerRails
|
6
|
+
module Middleware
|
7
|
+
##
|
8
|
+
# Middleware to capture request details and store in global state
|
9
|
+
class CaptureRequestDetails
|
10
|
+
def initialize(app)
|
11
|
+
@app = app
|
12
|
+
end
|
13
|
+
|
14
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
15
|
+
def call(env)
|
16
|
+
begin
|
17
|
+
request = ActionDispatch::Request.new(env)
|
18
|
+
|
19
|
+
CurrentRequest.id = env['action_dispatch.request_id']
|
20
|
+
CurrentRequest.format = request.headers['Content-Type']
|
21
|
+
CurrentRequest.method = request.method
|
22
|
+
CurrentRequest.parameters = request.parameters.except(:controller, :action, :format)
|
23
|
+
CurrentRequest.path = request.path
|
24
|
+
CurrentRequest.remote_ip = request.remote_ip
|
25
|
+
|
26
|
+
status, headers, body = @app.call(env)
|
27
|
+
ensure
|
28
|
+
CurrentRequest.reset
|
29
|
+
end
|
30
|
+
|
31
|
+
[status, headers, body]
|
32
|
+
end
|
33
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EventLoggerRails
|
4
|
+
##
|
5
|
+
# Merges data from application, request, and logger message for structured output
|
6
|
+
class Output
|
7
|
+
def initialize(level:, timestamp:, message:)
|
8
|
+
@current_request = EventLoggerRails::CurrentRequest
|
9
|
+
@level = level
|
10
|
+
@timestamp = timestamp.iso8601(3)
|
11
|
+
@message = message.respond_to?(:to_hash) ? sanitizer.filter(**message) : { message: }
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_json(*args)
|
15
|
+
JSON.generate(to_hash, *args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_hash
|
19
|
+
application_data.merge(**current_request_data, **logger_data)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :level, :timestamp, :message, :current_request
|
25
|
+
|
26
|
+
def sanitizer
|
27
|
+
@sanitizer ||= ActiveSupport::ParameterFilter.new(EventLoggerRails.sensitive_fields)
|
28
|
+
end
|
29
|
+
|
30
|
+
def application_data
|
31
|
+
{
|
32
|
+
environment: Rails.env,
|
33
|
+
host: Socket.gethostname,
|
34
|
+
service_name: Rails.application.class.module_parent_name
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
# rubocop:disable Metrics/AbcSize
|
39
|
+
def current_request_data
|
40
|
+
return {} if CurrentRequest.instance.attributes.blank?
|
41
|
+
|
42
|
+
{
|
43
|
+
format: current_request.format,
|
44
|
+
id: current_request.id,
|
45
|
+
method: current_request.method,
|
46
|
+
parameters: sanitizer.filter(current_request.parameters),
|
47
|
+
path: current_request.path,
|
48
|
+
remote_ip: current_request.remote_ip
|
49
|
+
}
|
50
|
+
end
|
51
|
+
# rubocop:enable Metrics/AbcSize
|
52
|
+
|
53
|
+
def logger_data
|
54
|
+
{
|
55
|
+
level:,
|
56
|
+
timestamp:,
|
57
|
+
**message
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/event_logger_rails.rb
CHANGED
@@ -2,24 +2,40 @@
|
|
2
2
|
|
3
3
|
require 'rails'
|
4
4
|
require 'active_support/dependencies'
|
5
|
-
require 'event_logger_rails/version'
|
6
5
|
require 'event_logger_rails/engine'
|
7
|
-
require 'event_logger_rails/
|
6
|
+
require 'event_logger_rails/current_request'
|
7
|
+
require 'event_logger_rails/event'
|
8
|
+
require 'event_logger_rails/emitter'
|
8
9
|
require 'event_logger_rails/exceptions/invalid_logger_level'
|
9
10
|
require 'event_logger_rails/exceptions/unregistered_event'
|
11
|
+
require 'event_logger_rails/extensions/loggable'
|
12
|
+
require 'event_logger_rails/json_logger'
|
13
|
+
require 'event_logger_rails/message'
|
14
|
+
require 'event_logger_rails/middleware/capture_request_details'
|
15
|
+
require 'event_logger_rails/output'
|
16
|
+
require 'event_logger_rails/version'
|
10
17
|
|
11
18
|
##
|
12
|
-
# Namespace for
|
19
|
+
# Namespace for EventLoggerRails gem
|
13
20
|
module EventLoggerRails
|
14
|
-
|
15
|
-
|
16
|
-
|
21
|
+
mattr_accessor :default_level
|
22
|
+
mattr_accessor :logdev
|
23
|
+
mattr_accessor :registered_events
|
24
|
+
mattr_accessor :sensitive_fields
|
25
|
+
|
26
|
+
def self.setup
|
27
|
+
yield self
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.emitter
|
31
|
+
@emitter ||= Emitter.new(logdev:)
|
32
|
+
end
|
17
33
|
|
18
|
-
def self.
|
19
|
-
|
34
|
+
def self.log(...)
|
35
|
+
emitter.log(...)
|
20
36
|
end
|
21
37
|
|
22
|
-
def self.
|
23
|
-
|
38
|
+
def self.reset
|
39
|
+
@emitter = nil
|
24
40
|
end
|
25
41
|
end
|
@@ -1,14 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'rails/generators'
|
4
|
+
|
3
5
|
module EventLoggerRails
|
4
6
|
module Generators
|
5
7
|
##
|
6
|
-
# Creates basic config file for EventLoggerRails
|
8
|
+
# Creates basic config file and initializer for EventLoggerRails
|
7
9
|
class InstallGenerator < Rails::Generators::Base
|
8
|
-
desc 'Create
|
10
|
+
desc 'Create event registry file'
|
9
11
|
source_root File.expand_path('templates', __dir__)
|
10
12
|
|
11
13
|
def copy_config_file
|
14
|
+
return if File.exist?(File.join(destination_root, 'config/event_logger_rails.yml'))
|
15
|
+
|
12
16
|
copy_file 'event_logger_rails.yml', 'config/event_logger_rails.yml'
|
13
17
|
end
|
14
18
|
end
|
@@ -1,15 +1,3 @@
|
|
1
|
-
##
|
2
|
-
# Allowed logger levels for use with EventLoggerRails
|
3
|
-
# You can add/remove levels, if desired; however, an exception will occur
|
4
|
-
# when using a logger level that is not enumerated here.
|
5
|
-
#
|
6
|
-
logger_levels:
|
7
|
-
- 'debug'
|
8
|
-
- 'info'
|
9
|
-
- 'warn'
|
10
|
-
- 'error'
|
11
|
-
- 'fatal'
|
12
|
-
|
13
1
|
##
|
14
2
|
# Registered events for use with EventLoggerRails
|
15
3
|
# Add your custom event definitions to this section; attempting to log events
|
@@ -17,9 +5,23 @@ logger_levels:
|
|
17
5
|
#
|
18
6
|
# Example event:
|
19
7
|
#
|
20
|
-
#
|
8
|
+
# shared:
|
21
9
|
# user:
|
22
10
|
# signup:
|
23
|
-
# success:
|
11
|
+
# success:
|
12
|
+
# description: 'Indicates a successful user signup.'
|
13
|
+
# failure:
|
14
|
+
# description: 'Indicates a user signup was not successful.'
|
15
|
+
# level: 'error'
|
16
|
+
#
|
17
|
+
shared:
|
18
|
+
|
19
|
+
##
|
20
|
+
# Add events that are unique to specific environments by uncommenting the appropriate
|
21
|
+
# environment and adding the event.
|
22
|
+
#
|
23
|
+
# development:
|
24
|
+
#
|
25
|
+
# test:
|
24
26
|
#
|
25
|
-
|
27
|
+
# production:
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: event_logger_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dick Davis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -24,7 +24,9 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 7.0.0
|
27
|
-
description:
|
27
|
+
description: |
|
28
|
+
EventLoggerRails is a Rails engine for emitting structured events in logs during the execution of business processes for analysis and visualization.
|
29
|
+
It allows teams to define events in a simple, centralized configuration file, and then log those events in JSON format for further processing.
|
28
30
|
email:
|
29
31
|
- dick@hey.com
|
30
32
|
executables: []
|
@@ -33,25 +35,33 @@ extra_rdoc_files: []
|
|
33
35
|
files:
|
34
36
|
- README.md
|
35
37
|
- Rakefile
|
36
|
-
- app/controllers/concerns/event_logger_rails/
|
38
|
+
- app/controllers/concerns/event_logger_rails/loggable_controller.rb
|
39
|
+
- app/models/concerns/event_logger_rails/loggable_model.rb
|
37
40
|
- config/routes.rb
|
38
41
|
- lib/event_logger_rails.rb
|
42
|
+
- lib/event_logger_rails/current_request.rb
|
43
|
+
- lib/event_logger_rails/emitter.rb
|
39
44
|
- lib/event_logger_rails/engine.rb
|
40
|
-
- lib/event_logger_rails/
|
45
|
+
- lib/event_logger_rails/event.rb
|
41
46
|
- lib/event_logger_rails/exceptions/invalid_logger_level.rb
|
42
47
|
- lib/event_logger_rails/exceptions/unregistered_event.rb
|
48
|
+
- lib/event_logger_rails/extensions/loggable.rb
|
49
|
+
- lib/event_logger_rails/json_logger.rb
|
50
|
+
- lib/event_logger_rails/message.rb
|
51
|
+
- lib/event_logger_rails/middleware/capture_request_details.rb
|
52
|
+
- lib/event_logger_rails/output.rb
|
43
53
|
- lib/event_logger_rails/version.rb
|
44
54
|
- lib/generators/event_logger_rails/install_generator.rb
|
45
55
|
- lib/generators/event_logger_rails/templates/event_logger_rails.yml
|
46
56
|
- lib/tasks/event_logger_rails_tasks.rake
|
47
|
-
homepage: https://github.com/
|
57
|
+
homepage: https://github.com/dickdavis/event_logger_rails
|
48
58
|
licenses:
|
49
59
|
- MIT
|
50
60
|
metadata:
|
51
61
|
rubygems_mfa_required: 'true'
|
52
|
-
homepage_uri: https://github.com/
|
53
|
-
source_code_uri: https://github.com/
|
54
|
-
changelog_uri: https://github.com/
|
62
|
+
homepage_uri: https://github.com/dickdavis/event_logger_rails
|
63
|
+
source_code_uri: https://github.com/dickdavis/event_logger_rails/tree/0.3.0
|
64
|
+
changelog_uri: https://github.com/dickdavis/event_logger_rails/blob/0.3.0/CHANGELOG.md
|
55
65
|
post_install_message:
|
56
66
|
rdoc_options: []
|
57
67
|
require_paths:
|
@@ -60,15 +70,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
60
70
|
requirements:
|
61
71
|
- - ">="
|
62
72
|
- !ruby/object:Gem::Version
|
63
|
-
version:
|
73
|
+
version: 3.1.4
|
64
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
75
|
requirements:
|
66
76
|
- - ">="
|
67
77
|
- !ruby/object:Gem::Version
|
68
78
|
version: '0'
|
69
79
|
requirements: []
|
70
|
-
rubygems_version: 3.
|
80
|
+
rubygems_version: 3.3.26
|
71
81
|
signing_key:
|
72
82
|
specification_version: 4
|
73
|
-
summary: Rails gem
|
83
|
+
summary: Rails gem weaving the fabric of logged events into tapestries for analytic
|
84
|
+
reverie.
|
74
85
|
test_files: []
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module EventLoggerRails
|
4
|
-
##
|
5
|
-
# Provides event logging with relevant controller/request data.
|
6
|
-
module Loggable
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
|
9
|
-
def log_event(level, event, **data)
|
10
|
-
data_to_log = data_from_request.merge(data)
|
11
|
-
EventLoggerRails.log(level, event, **data_to_log)
|
12
|
-
rescue EventLoggerRails::Exceptions::UnregisteredEvent => e
|
13
|
-
log_event :error, 'event_logger_rails.event.unregistered', message: e.message
|
14
|
-
rescue EventLoggerRails::Exceptions::InvalidLoggerLevel => e
|
15
|
-
log_event :error, 'event_logger_rails.logger_level.invalid', message: e.message
|
16
|
-
end
|
17
|
-
|
18
|
-
def data_from_request
|
19
|
-
{
|
20
|
-
controller: controller_name.camelcase,
|
21
|
-
action: action_name,
|
22
|
-
method: request.method,
|
23
|
-
path: request.path,
|
24
|
-
remote_ip: request.remote_ip,
|
25
|
-
parameters: request.query_parameters.to_json
|
26
|
-
}
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,97 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'yaml'
|
4
|
-
|
5
|
-
require_relative 'exceptions/invalid_logger_level'
|
6
|
-
require_relative 'exceptions/unregistered_event'
|
7
|
-
|
8
|
-
module EventLoggerRails
|
9
|
-
##
|
10
|
-
# Outputs event and related data logs.
|
11
|
-
class EventLogger
|
12
|
-
DEFAULT_EVENTS = [
|
13
|
-
'event_logger_rails.logger_level.invalid',
|
14
|
-
'event_logger_rails.event.unregistered',
|
15
|
-
'event_logger_rails.event.testing'
|
16
|
-
].freeze
|
17
|
-
private_constant :DEFAULT_EVENTS
|
18
|
-
|
19
|
-
def initialize
|
20
|
-
@logger_levels = logger_levels_from_config
|
21
|
-
@registered_events = registered_events_from_config
|
22
|
-
@last_updated = File.ctime(config_file)
|
23
|
-
end
|
24
|
-
|
25
|
-
def log(*tags, **params)
|
26
|
-
reload_config if config_changed?
|
27
|
-
|
28
|
-
level, event = *tags
|
29
|
-
validate_tags(level, event)
|
30
|
-
logger = ActiveSupport::TaggedLogging.new(Logger.new(output_device))
|
31
|
-
logger.tagged("#{level.to_s.upcase} | #{DateTime.current} | #{event}") { logger.send(level, **params.as_json) }
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
attr_reader :logger_levels, :registered_events, :last_updated
|
37
|
-
|
38
|
-
def logger_levels_from_config
|
39
|
-
data_from_config[:logger_levels].map(&:to_sym)
|
40
|
-
end
|
41
|
-
|
42
|
-
def registered_events_from_config
|
43
|
-
data_from_config[:registered_events]
|
44
|
-
end
|
45
|
-
|
46
|
-
def data_from_config
|
47
|
-
YAML.safe_load(File.read(config_file)).deep_symbolize_keys
|
48
|
-
end
|
49
|
-
|
50
|
-
def config_file
|
51
|
-
Rails.root.join('config/event_logger_rails.yml')
|
52
|
-
end
|
53
|
-
|
54
|
-
def reload_config
|
55
|
-
@logger_levels = logger_levels_from_config
|
56
|
-
@registered_events = registered_events_from_config
|
57
|
-
@last_updated = File.ctime(config_file)
|
58
|
-
end
|
59
|
-
|
60
|
-
def config_changed?
|
61
|
-
return false unless Rails.env.development?
|
62
|
-
|
63
|
-
last_updated != File.ctime(config_file)
|
64
|
-
end
|
65
|
-
|
66
|
-
def validate_tags(level, event)
|
67
|
-
validate_logger_level(level) && validate_event(event)
|
68
|
-
end
|
69
|
-
|
70
|
-
def validate_logger_level(level)
|
71
|
-
return true if logger_levels.include?(level)
|
72
|
-
|
73
|
-
raise EventLoggerRails::Exceptions::InvalidLoggerLevel.new(logger_level: level)
|
74
|
-
end
|
75
|
-
|
76
|
-
def validate_event(event)
|
77
|
-
return true if event_registered?(event) || default_event?(event)
|
78
|
-
|
79
|
-
raise EventLoggerRails::Exceptions::UnregisteredEvent.new(unregistered_event: event)
|
80
|
-
end
|
81
|
-
|
82
|
-
def event_registered?(event)
|
83
|
-
parsed_event = event.split('.').map(&:to_sym)
|
84
|
-
registered_events.dig(*parsed_event)
|
85
|
-
end
|
86
|
-
|
87
|
-
def default_event?(event)
|
88
|
-
DEFAULT_EVENTS.include?(event)
|
89
|
-
end
|
90
|
-
|
91
|
-
def output_device
|
92
|
-
return $stdout unless Rails.env.test?
|
93
|
-
|
94
|
-
File.open(File::NULL, 'w')
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|