event_logger_rails 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +27 -0
- data/app/controllers/concerns/event_logger_rails/loggable_controller.rb +5 -2
- data/app/models/concerns/event_logger_rails/loggable_model.rb +5 -2
- data/lib/event_logger_rails/current_request.rb +13 -1
- data/lib/event_logger_rails/emitter.rb +25 -3
- data/lib/event_logger_rails/engine.rb +17 -2
- data/lib/event_logger_rails/event.rb +79 -2
- data/lib/event_logger_rails/event_logger.rb +16 -0
- data/lib/event_logger_rails/exceptions/invalid_logger_level.rb +8 -1
- data/lib/event_logger_rails/exceptions/unregistered_event.rb +10 -1
- data/lib/event_logger_rails/extensions/loggable.rb +12 -4
- data/lib/event_logger_rails/formatters/json.rb +20 -0
- data/lib/event_logger_rails/message.rb +14 -2
- data/lib/event_logger_rails/middleware/capture_request_details.rb +8 -1
- data/lib/event_logger_rails/output.rb +40 -2
- data/lib/event_logger_rails/version.rb +4 -1
- data/lib/event_logger_rails.rb +46 -6
- metadata +4 -3
- data/lib/event_logger_rails/json_logger.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31f83610ba9d1fbd9edb2f165dd19927cfffce11f39f8fdb17c48743fe76eb27
|
4
|
+
data.tar.gz: 6a59e89dc85c6a82cada24710a84e8b2fb4b0aebac1babfe6ed7e47c54fbc805
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a91d59e2d7b19433d7405beb536b8a911cf17bc61a596ecd040110be5602340e0cc07179ceec627f7e4f0c4e1294015424adff2035b072f79c5e872c650683a
|
7
|
+
data.tar.gz: ec168b78dbcf93a860ecbcc42883a0401c743951a0434b42f22ed988d723b50a89dc3e1d916a50e0e4f5f486cb90dfcd6214b9fa458830ac0d7e136682e0cf1d
|
data/README.md
CHANGED
@@ -327,6 +327,14 @@ Rails.application.configure do |config|
|
|
327
327
|
end
|
328
328
|
```
|
329
329
|
|
330
|
+
You can configure a custom formatter. Reference `EventLoggerRails::Formatters::JSON` for an example.
|
331
|
+
|
332
|
+
```ruby
|
333
|
+
Rails.application.configure do |config|
|
334
|
+
config.event_logger_rails.formatter = 'MyCustomFormatterClass'
|
335
|
+
end
|
336
|
+
```
|
337
|
+
|
330
338
|
By default, `EventLoggerRails` outputs to a separate log file (`log/event_logger_rails.#{Rails.env}.log`) from normal Rails log output, allowing
|
331
339
|
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
340
|
|
@@ -344,6 +352,25 @@ Rails.application.configure do |config|
|
|
344
352
|
end
|
345
353
|
```
|
346
354
|
|
355
|
+
You can configure a custom logger. Reference `EventLoggerRails::EventLogger` for an example.
|
356
|
+
|
357
|
+
```ruby
|
358
|
+
Rails.application.configure do |config|
|
359
|
+
config.event_logger_rails.logger_class = 'MyCustomLoggerClass'
|
360
|
+
end
|
361
|
+
```
|
362
|
+
|
363
|
+
You can also configure the Rails logger to use `EventLoggerRails::EventLogger` to render structured logs in JSON format with the additional app and request data.
|
364
|
+
|
365
|
+
```ruby
|
366
|
+
Rails.application.configure do
|
367
|
+
config.colorize_logging = false
|
368
|
+
config.log_level = ENV.fetch('RAILS_LOG_LEVEL', :info)
|
369
|
+
logger = EventLoggerRails::EventLogger.new($stdout)
|
370
|
+
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
371
|
+
end
|
372
|
+
```
|
373
|
+
|
347
374
|
## Contributing
|
348
375
|
|
349
376
|
Your inputs echo in this realm. Venture forth and materialize your thoughts through a PR.
|
@@ -7,13 +7,16 @@ module EventLoggerRails
|
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
include EventLoggerRails::Extensions::Loggable
|
9
9
|
|
10
|
-
|
10
|
+
# Includes the controller name and action in the log output.
|
11
|
+
#
|
12
|
+
# @return [Hash] The data to include in log output.
|
13
|
+
def optional_event_logger_data
|
11
14
|
{
|
12
15
|
action: action_name,
|
13
16
|
controller: controller_name.camelcase
|
14
17
|
}
|
15
18
|
end
|
16
19
|
|
17
|
-
private :
|
20
|
+
private :optional_event_logger_data
|
18
21
|
end
|
19
22
|
end
|
@@ -7,13 +7,16 @@ module EventLoggerRails
|
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
include EventLoggerRails::Extensions::Loggable
|
9
9
|
|
10
|
-
|
10
|
+
# Includes the model name and instance ID in the log output.
|
11
|
+
#
|
12
|
+
# @return [Hash] The data to include in log output.
|
13
|
+
def optional_event_logger_data
|
11
14
|
{
|
12
15
|
model: self.class.name,
|
13
16
|
instance_id: id
|
14
17
|
}
|
15
18
|
end
|
16
19
|
|
17
|
-
private :
|
20
|
+
private :optional_event_logger_data
|
18
21
|
end
|
19
22
|
end
|
@@ -1,9 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module EventLoggerRails
|
4
|
-
##
|
5
4
|
# Provides global state with request details
|
6
5
|
class CurrentRequest < ActiveSupport::CurrentAttributes
|
6
|
+
# @note Defines the attributes for the current request object.
|
7
|
+
# @!attribute [rw] id
|
8
|
+
# @return [String] The ID of the request.
|
9
|
+
# @!attribute [rw] format
|
10
|
+
# @return [Symbol] The format of the request.
|
11
|
+
# @!attribute [rw] method
|
12
|
+
# @return [String] The HTTP method of the request.
|
13
|
+
# @!attribute [rw] parameters
|
14
|
+
# @return [Hash] The parameters of the request.
|
15
|
+
# @!attribute [rw] path
|
16
|
+
# @return [String] The path of the request.
|
17
|
+
# @!attribute [rw] remote_ip
|
18
|
+
# @return [String] The remote IP of the request.
|
7
19
|
attribute :id, :format, :method, :parameters, :path, :remote_ip
|
8
20
|
end
|
9
21
|
end
|
@@ -1,13 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module EventLoggerRails
|
4
|
-
##
|
5
4
|
# Processes events, sending data to logger.
|
6
5
|
class Emitter
|
7
|
-
|
8
|
-
|
6
|
+
# Initializes the emitter.
|
7
|
+
# It references the configured log device for log output.
|
8
|
+
# It references the configured logger class for logging, falling back to EventLogger.
|
9
|
+
def initialize
|
10
|
+
logdev = EventLoggerRails.logdev
|
11
|
+
@logger = EventLoggerRails.logger_class.constantize.new(logdev) || EventLoggerRails::EventLogger.new(logdev)
|
9
12
|
end
|
10
13
|
|
14
|
+
# Validates and logs an event with the given level and data.
|
15
|
+
# If an error is raised, it recursively calls itself with the error's event.
|
16
|
+
#
|
17
|
+
# @note Prefer to use the public API provided by `EventLoggerRails.log()`.
|
18
|
+
# @param event [EventLoggerRails::Event, String] The event to log. Can be a string or an Event object.
|
19
|
+
# @param level [Symbol] The level of the event.
|
20
|
+
# @param data [Hash] Additional data to log.
|
21
|
+
# @return [Integer] The number of bytes written to the log.
|
22
|
+
# @example
|
23
|
+
# emitter = EventLoggerRails::Emitter.new
|
24
|
+
# emitter.log('foo.bar.baz', level: :info, data: { foo: 'bar' })
|
11
25
|
def log(event, level:, data: {})
|
12
26
|
Event.new(event).validate! do |validated_event|
|
13
27
|
message = Message.new(event: validated_event, data:)
|
@@ -20,8 +34,16 @@ module EventLoggerRails
|
|
20
34
|
|
21
35
|
private
|
22
36
|
|
37
|
+
# @!attribute [r] logger
|
38
|
+
# @return [JsonLogger] The logger instance used for log output.
|
23
39
|
attr_reader :logger
|
24
40
|
|
41
|
+
# Logs a message with the given level.
|
42
|
+
#
|
43
|
+
# @param message [String] The message to log.
|
44
|
+
# @param level [Symbol] The level of the message.
|
45
|
+
# @return [Integer] The number of bytes written to the log.
|
46
|
+
# @raise [EventLoggerRails::Exceptions::InvalidLoggerLevel] If the level is invalid.
|
25
47
|
def log_message(message, level)
|
26
48
|
logger.send(level) { message }
|
27
49
|
rescue NoMethodError
|
@@ -1,28 +1,43 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module EventLoggerRails
|
4
|
-
|
5
|
-
# Engine for plugging into Rails
|
4
|
+
# Engine for plugging into Rails.
|
6
5
|
class Engine < ::Rails::Engine
|
6
|
+
# Use the EventLoggerRails namespace.
|
7
7
|
isolate_namespace EventLoggerRails
|
8
8
|
|
9
|
+
# Use the rspec test framework.
|
9
10
|
config.generators do |generator|
|
10
11
|
generator.test_framework :rspec
|
11
12
|
end
|
12
13
|
|
14
|
+
# Initialize the EventLoggerRails configuration.
|
13
15
|
config.event_logger_rails = ActiveSupport::OrderedOptions.new
|
16
|
+
config.event_logger_rails.formatter = 'EventLoggerRails::Formatters::JSON'
|
14
17
|
config.event_logger_rails.logdev = "log/event_logger_rails.#{Rails.env}.log"
|
18
|
+
config.event_logger_rails.logger_class = 'EventLoggerRails::EventLogger'
|
15
19
|
config.event_logger_rails.default_level = :warn
|
16
20
|
|
21
|
+
# Add the EventLoggerRails middleware.
|
17
22
|
initializer 'event_logger_rails.add_middleware' do |app|
|
23
|
+
# Use middleware to capture the request details.
|
18
24
|
app.middleware.use Middleware::CaptureRequestDetails
|
19
25
|
end
|
20
26
|
|
27
|
+
# Configure EventLoggerRails
|
21
28
|
config.after_initialize do |app|
|
22
29
|
EventLoggerRails.setup do |engine|
|
30
|
+
# Set the default logging level from the registration.
|
23
31
|
engine.default_level = app.config.event_logger_rails.default_level
|
32
|
+
# Set the formatter.
|
33
|
+
engine.formatter = app.config.event_logger_rails.formatter
|
34
|
+
# Set the log device.
|
24
35
|
engine.logdev = app.config.event_logger_rails.logdev
|
36
|
+
# Set the logger class.
|
37
|
+
engine.logger_class = app.config.event_logger_rails.logger_class
|
38
|
+
# Set the registered events from the registration.
|
25
39
|
engine.registered_events = Rails.application.config_for(:event_logger_rails)
|
40
|
+
# Set the sensitive fields.
|
26
41
|
engine.sensitive_fields = app.config.filter_parameters
|
27
42
|
end
|
28
43
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module EventLoggerRails
|
4
|
-
##
|
5
4
|
# Models an event for logging.
|
6
5
|
class Event
|
6
|
+
# Contains the default event registration.
|
7
7
|
DEFAULT_EVENTS = {
|
8
8
|
'event_logger_rails.logger_level.invalid' => {
|
9
9
|
description: 'Indicates provided level was invalid.',
|
@@ -20,32 +20,89 @@ module EventLoggerRails
|
|
20
20
|
}.freeze
|
21
21
|
private_constant :DEFAULT_EVENTS
|
22
22
|
|
23
|
-
|
23
|
+
# @!attribute [r] identifier
|
24
|
+
# @return [String] The identifier of the event.
|
25
|
+
attr_reader :identifier
|
24
26
|
|
27
|
+
# @!attribute [r] description
|
28
|
+
# @return [String] The description of the event.
|
29
|
+
attr_reader :description
|
30
|
+
|
31
|
+
# @!attribute [r] level
|
32
|
+
# @return [Symbol] The configured logging level of the event.
|
33
|
+
attr_reader :level
|
34
|
+
|
35
|
+
# Initializes the event using the provided identifier to determine its properties from
|
36
|
+
# either the default registration (for default events) or the user-defined registry.
|
37
|
+
#
|
38
|
+
# @param provided_identifier [EventLoggerRails::Event, String] The event or its identifier.
|
25
39
|
def initialize(provided_identifier)
|
26
40
|
@provided_identifier = provided_identifier.to_s
|
27
41
|
|
42
|
+
# Attempt to find default registration for event
|
28
43
|
if (default_event = DEFAULT_EVENTS[@provided_identifier])
|
29
44
|
default_registration = [@provided_identifier, *default_event&.values]
|
30
45
|
end
|
31
46
|
|
47
|
+
# Fallback to user-defined registration if default not found.
|
48
|
+
# Deconstruct registration to set identifier, description, and level attributes.
|
32
49
|
@identifier, @description, @level = default_registration || config_registration
|
33
50
|
end
|
34
51
|
|
52
|
+
# Converts the event into a hash and merges the given hash into it.
|
53
|
+
#
|
54
|
+
# @param kwargs [Hash] The hash to merge into the event.
|
55
|
+
# @return [Hash] The merged hash.
|
56
|
+
# @example
|
57
|
+
# event = EventLoggerRails::Event.new('event_logger_rails.event.testing')
|
58
|
+
# event.merge(foo: 'bar')
|
59
|
+
# # {
|
60
|
+
# # event_identifier: 'event_logger_rails.event.testing',
|
61
|
+
# # event_description: 'Event reserved for testing',
|
62
|
+
# # foo: 'bar'
|
63
|
+
# # }
|
35
64
|
def merge(...)
|
36
65
|
to_hash.merge(...)
|
37
66
|
end
|
38
67
|
|
68
|
+
# Determines if the event is valid.
|
69
|
+
#
|
70
|
+
# @return [Boolean] true if the event is valid, false otherwise.
|
71
|
+
# @example
|
72
|
+
# valid_event = EventLoggerRails::Event.new('event_logger_rails.event.testing')
|
73
|
+
# valid_event.valid? # => true
|
74
|
+
# invalid_event = EventLoggerRails::Event.new('foo.bar.baz')
|
75
|
+
# invalid_event.valid? # => false
|
39
76
|
def valid?
|
40
77
|
identifier.present?
|
41
78
|
end
|
42
79
|
|
80
|
+
# Validates the event and yields it to the given block.
|
81
|
+
#
|
82
|
+
# @note This only validates the event registration. Logger level is validated at the time of logging.
|
83
|
+
# @yield [self] Yields the event to the given block.
|
84
|
+
# @raise [EventLoggerRails::Exceptions::UnregisteredEvent] If the event is not registered.
|
85
|
+
# @example
|
86
|
+
# event = EventLoggerRails::Event.new('event_logger_rails.event.testing')
|
87
|
+
# event.validate! do |validated_event|
|
88
|
+
# puts "Event: #{validated_event}"
|
89
|
+
# end
|
43
90
|
def validate!
|
44
91
|
raise Exceptions::UnregisteredEvent.new(unregistered_event: self) unless valid?
|
45
92
|
|
46
93
|
yield(self)
|
47
94
|
end
|
48
95
|
|
96
|
+
# Returns a hash representation of the event.
|
97
|
+
#
|
98
|
+
# @return [Hash] The event as a hash.
|
99
|
+
# @example
|
100
|
+
# event = EventLoggerRails::Event.new('event_logger_rails.event.testing')
|
101
|
+
# event.to_hash
|
102
|
+
# # {
|
103
|
+
# # event_identifier: 'event_logger_rails.event.testing',
|
104
|
+
# # event_description: 'Event reserved for testing'
|
105
|
+
# # }
|
49
106
|
def to_hash
|
50
107
|
{
|
51
108
|
event_identifier: identifier,
|
@@ -53,18 +110,38 @@ module EventLoggerRails
|
|
53
110
|
}
|
54
111
|
end
|
55
112
|
|
113
|
+
# Returns a string representation of the event.
|
114
|
+
# The provided identifier is returned if the event is not registered.
|
115
|
+
#
|
116
|
+
# @return [String] The event as a string.
|
117
|
+
# @example
|
118
|
+
# event = EventLoggerRails::Event.new('event_logger_rails.event.testing')
|
119
|
+
# event.to_s # => 'event_logger_rails.event.testing'
|
56
120
|
def to_s
|
57
121
|
identifier&.to_s || provided_identifier.to_s
|
58
122
|
end
|
59
123
|
|
124
|
+
# Determines if the event is equivalent to the given object through string comparison.
|
125
|
+
#
|
126
|
+
# @param other [EventLoggerRails::Event] The event to compare.
|
127
|
+
# @return [Boolean] true if the event is equal to the given object, false otherwise.
|
128
|
+
# @example
|
129
|
+
# event = EventLoggerRails::Event.new('event_logger_rails.event.testing')
|
130
|
+
# event == 'event_logger_rails.event.testing' # => true
|
60
131
|
def ==(other)
|
61
132
|
to_s == other.to_s
|
62
133
|
end
|
63
134
|
|
64
135
|
private
|
65
136
|
|
137
|
+
# @!attribute [r] provided_identifier
|
138
|
+
# @return [String] The identifier provided when the event was initialized.
|
66
139
|
attr_reader :provided_identifier
|
67
140
|
|
141
|
+
# Parses the event identifier and looks up the details from the user-defined registry.
|
142
|
+
#
|
143
|
+
# @return [Array<String, String, Symbol>] The identifier, description, and level of the event.
|
144
|
+
# If the event is not registered, each array element will be nil.
|
68
145
|
def config_registration
|
69
146
|
parsed_event = provided_identifier.split('.').map(&:to_sym)
|
70
147
|
config = EventLoggerRails.registered_events.dig(*parsed_event)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EventLoggerRails
|
4
|
+
# Writes log entries in configured format.
|
5
|
+
class EventLogger < ::Logger
|
6
|
+
include ActiveSupport::LoggerSilence
|
7
|
+
|
8
|
+
# Initializes the logger with a JSON formatter.
|
9
|
+
#
|
10
|
+
# @param logdev [IO, #write] The log device for log output.
|
11
|
+
def initialize(...)
|
12
|
+
super(...)
|
13
|
+
@formatter = EventLoggerRails.formatter.constantize.new || EventLoggerRails::Formatters::JSON.new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -2,17 +2,22 @@
|
|
2
2
|
|
3
3
|
module EventLoggerRails
|
4
4
|
module Exceptions
|
5
|
-
##
|
6
5
|
# Indicates invalid log level provided.
|
7
6
|
class InvalidLoggerLevel < StandardError
|
7
|
+
# @!attribute [r] event
|
8
|
+
# @return [EventLoggerRails::Event] The default invalid logging level event.
|
8
9
|
attr_reader :event
|
9
10
|
|
11
|
+
# Initializes the exception with the given logger level.
|
10
12
|
def initialize(logger_level:)
|
11
13
|
super
|
12
14
|
@event = Event.new('event_logger_rails.logger_level.invalid')
|
13
15
|
@logger_level = logger_level
|
14
16
|
end
|
15
17
|
|
18
|
+
# Provides an informative error message.
|
19
|
+
#
|
20
|
+
# @return [String] The error message.
|
16
21
|
def message
|
17
22
|
"Invalid logger level provided: '#{logger_level.to_sym}'. " \
|
18
23
|
'Valid levels: :debug, :info, :warn, :error, :unknown.'
|
@@ -20,6 +25,8 @@ module EventLoggerRails
|
|
20
25
|
|
21
26
|
private
|
22
27
|
|
28
|
+
# @!attribute [r] logger_level
|
29
|
+
# @return [Symbol] The invalid logger level.
|
23
30
|
attr_reader :logger_level
|
24
31
|
end
|
25
32
|
end
|
@@ -2,23 +2,32 @@
|
|
2
2
|
|
3
3
|
module EventLoggerRails
|
4
4
|
module Exceptions
|
5
|
-
##
|
6
5
|
# Indicates event provided not registered.
|
7
6
|
class UnregisteredEvent < StandardError
|
7
|
+
# @!attribute [r] event
|
8
|
+
# @return [EventLoggerRails::Event] The default event for unregistered events.
|
8
9
|
attr_reader :event
|
9
10
|
|
11
|
+
# Initializes the exception with the given unregistered event.
|
12
|
+
#
|
13
|
+
# @param unregistered_event [EventLoggerRails::Event] The unregistered event.
|
10
14
|
def initialize(unregistered_event:)
|
11
15
|
super()
|
12
16
|
@event = Event.new('event_logger_rails.event.unregistered')
|
13
17
|
@unregistered_event = unregistered_event
|
14
18
|
end
|
15
19
|
|
20
|
+
# Provides an informative error message.
|
21
|
+
#
|
22
|
+
# @return [String] The error message.
|
16
23
|
def message
|
17
24
|
"Event provided not registered: #{unregistered_event}"
|
18
25
|
end
|
19
26
|
|
20
27
|
private
|
21
28
|
|
29
|
+
# @!attribute [r] unregistered_event
|
30
|
+
# @return [EventLoggerRails::Event] The unregistered event.
|
22
31
|
attr_reader :unregistered_event
|
23
32
|
end
|
24
33
|
end
|
@@ -2,20 +2,28 @@
|
|
2
2
|
|
3
3
|
module EventLoggerRails
|
4
4
|
module Extensions
|
5
|
-
|
6
|
-
# Provides event logging with relevant model data.
|
5
|
+
# Provides event logging with optional data.
|
7
6
|
module Loggable
|
7
|
+
# Logs an event with the given level and data.
|
8
|
+
#
|
9
|
+
# @param event [EventLoggerRails::Event] The event to log.
|
10
|
+
# @option kwargs [Symbol] :level The level of the event.
|
11
|
+
# @option kwargs [Hash] :data The data of the event.
|
8
12
|
def log_event(event, **kwargs)
|
9
13
|
EventLoggerRails.log(
|
10
14
|
event,
|
11
15
|
level: kwargs[:level] || nil,
|
12
|
-
data: (kwargs[:data] || {}).merge(
|
16
|
+
data: (kwargs[:data] || {}).merge(optional_event_logger_data)
|
13
17
|
)
|
14
18
|
end
|
15
19
|
|
16
20
|
private
|
17
21
|
|
18
|
-
|
22
|
+
# Optional data to include in log output.
|
23
|
+
#
|
24
|
+
# @return [Hash] The data to include in log output.
|
25
|
+
# @note This method can be overridden by classes that implement Loggable.
|
26
|
+
def optional_event_logger_data
|
19
27
|
{}
|
20
28
|
end
|
21
29
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EventLoggerRails
|
4
|
+
module Formatters
|
5
|
+
# Writes log entries in JSON format
|
6
|
+
class JSON < ActiveSupport::Logger::SimpleFormatter
|
7
|
+
# Returns the formatted output for logging.
|
8
|
+
#
|
9
|
+
# @param level [Symbol] The level of the event.
|
10
|
+
# @param timestamp [Time] The timestamp of the event.
|
11
|
+
# @param progname [String] The name of the logger.
|
12
|
+
# @param message [EventLoggerRails::Message, Hash, String] The message containing the data for logging.
|
13
|
+
# @return [String] The formatted output for logging.
|
14
|
+
def call(level, timestamp, _progname, message)
|
15
|
+
output = Output.new(level:, timestamp:, message:)
|
16
|
+
"#{output.to_json}\n"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,20 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module EventLoggerRails
|
4
|
-
##
|
5
4
|
# Models a message sent to the logger containing event and optional data
|
6
5
|
class Message
|
6
|
+
# Initializes the message with the given event and data.
|
7
|
+
#
|
8
|
+
# @param event [EventLoggerRails::Event] The event to log.
|
9
|
+
# @param data [Hash] Additional data to log.
|
7
10
|
def initialize(event:, data: {})
|
8
11
|
@event = event
|
9
12
|
@data = data
|
10
13
|
end
|
11
14
|
|
15
|
+
# Converts the message to a hash containing the event and data details.
|
16
|
+
#
|
17
|
+
# @return [Hash] The hash representation of the message.
|
12
18
|
def to_hash
|
13
19
|
event.merge(data)
|
14
20
|
end
|
15
21
|
|
16
22
|
private
|
17
23
|
|
18
|
-
|
24
|
+
# @!attribute [r] event
|
25
|
+
# @return [EventLoggerRails::Event] The event to log.
|
26
|
+
attr_reader :event
|
27
|
+
|
28
|
+
# @!attribute [r] data
|
29
|
+
# @return [Hash] Additional data to log.
|
30
|
+
attr_reader :data
|
19
31
|
end
|
20
32
|
end
|
@@ -4,14 +4,21 @@ require_relative '../current_request'
|
|
4
4
|
|
5
5
|
module EventLoggerRails
|
6
6
|
module Middleware
|
7
|
-
##
|
8
7
|
# Middleware to capture request details and store in global state
|
9
8
|
class CaptureRequestDetails
|
9
|
+
# Initializes the middleware with the given app.
|
10
|
+
#
|
11
|
+
# @param app [Proc] The Rack app.
|
10
12
|
def initialize(app)
|
11
13
|
@app = app
|
12
14
|
end
|
13
15
|
|
14
16
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
17
|
+
|
18
|
+
# Captures request details and stores in global state
|
19
|
+
#
|
20
|
+
# @param env [Hash] The Rack environment.
|
21
|
+
# @note The CurrentRequest is reset at the end of the request.
|
15
22
|
def call(env)
|
16
23
|
begin
|
17
24
|
request = ActionDispatch::Request.new(env)
|
@@ -1,9 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module EventLoggerRails
|
4
|
-
##
|
5
4
|
# Merges data from application, request, and logger message for structured output
|
6
5
|
class Output
|
6
|
+
# Initializes the output with the given level, timestamp, and message.
|
7
|
+
#
|
8
|
+
# @param level [Symbol] The level of the event.
|
9
|
+
# @param timestamp [Time] The timestamp of the event.
|
10
|
+
# @param message [EventLoggerRails::Message] The message of the event.
|
7
11
|
def initialize(level:, timestamp:, message:)
|
8
12
|
@current_request = EventLoggerRails::CurrentRequest
|
9
13
|
@level = level
|
@@ -11,22 +15,48 @@ module EventLoggerRails
|
|
11
15
|
@message = message.respond_to?(:to_hash) ? sanitizer.filter(**message) : { message: }
|
12
16
|
end
|
13
17
|
|
18
|
+
# Converts the output to a JSON string.
|
19
|
+
#
|
20
|
+
# @return [String] The JSON representation of the output.
|
14
21
|
def to_json(*args)
|
15
22
|
JSON.generate(to_hash, *args)
|
16
23
|
end
|
17
24
|
|
25
|
+
# Converts the output to a hash containing the application, request, and logger details.
|
26
|
+
#
|
27
|
+
# @return [Hash] The hash representation of the output.
|
18
28
|
def to_hash
|
19
29
|
application_data.merge(**current_request_data, **logger_data)
|
20
30
|
end
|
21
31
|
|
22
32
|
private
|
23
33
|
|
24
|
-
|
34
|
+
# @!attribute [r] level
|
35
|
+
# @return [Symbol] The level of the event.
|
36
|
+
attr_reader :level
|
25
37
|
|
38
|
+
# @!attribute [r] timestamp
|
39
|
+
# @return [Time] The timestamp of the event.
|
40
|
+
attr_reader :timestamp
|
41
|
+
|
42
|
+
# @!attribute [r] message
|
43
|
+
# @return [EventLoggerRails::Message] The message to log.
|
44
|
+
attr_reader :message
|
45
|
+
|
46
|
+
# @!attribute [r] current_request
|
47
|
+
# @return [EventLoggerRails::CurrentRequest] The object storing the current request data.
|
48
|
+
attr_reader :current_request
|
49
|
+
|
50
|
+
# Finds or initializes a parameter filter for sensitive data.
|
51
|
+
#
|
52
|
+
# @return [ActiveSupport::ParameterFilter] The parameter filter for sensitive data.
|
26
53
|
def sanitizer
|
27
54
|
@sanitizer ||= ActiveSupport::ParameterFilter.new(EventLoggerRails.sensitive_fields)
|
28
55
|
end
|
29
56
|
|
57
|
+
# Structures the application data to include in the output.
|
58
|
+
#
|
59
|
+
# @return [Hash] The application data to include in the output.
|
30
60
|
def application_data
|
31
61
|
{
|
32
62
|
environment: Rails.env,
|
@@ -36,6 +66,10 @@ module EventLoggerRails
|
|
36
66
|
end
|
37
67
|
|
38
68
|
# rubocop:disable Metrics/AbcSize
|
69
|
+
|
70
|
+
# Structures the request data to include in the output.
|
71
|
+
#
|
72
|
+
# @return [Hash] The request data to include in the output.
|
39
73
|
def current_request_data
|
40
74
|
return {} if CurrentRequest.instance.attributes.blank?
|
41
75
|
|
@@ -50,6 +84,10 @@ module EventLoggerRails
|
|
50
84
|
end
|
51
85
|
# rubocop:enable Metrics/AbcSize
|
52
86
|
|
87
|
+
# Structures the logger data to include in the output.
|
88
|
+
#
|
89
|
+
# @return [Hash] The logger data to include in the output.
|
90
|
+
# @note The logger data includes the level, timestamp, and message.
|
53
91
|
def logger_data
|
54
92
|
{
|
55
93
|
level:,
|
data/lib/event_logger_rails.rb
CHANGED
@@ -2,39 +2,79 @@
|
|
2
2
|
|
3
3
|
require 'rails'
|
4
4
|
require 'active_support/dependencies'
|
5
|
-
require 'event_logger_rails/engine'
|
6
5
|
require 'event_logger_rails/current_request'
|
7
|
-
require 'event_logger_rails/
|
6
|
+
require 'event_logger_rails/engine'
|
8
7
|
require 'event_logger_rails/emitter'
|
8
|
+
require 'event_logger_rails/event'
|
9
|
+
require 'event_logger_rails/event_logger'
|
9
10
|
require 'event_logger_rails/exceptions/invalid_logger_level'
|
10
11
|
require 'event_logger_rails/exceptions/unregistered_event'
|
11
12
|
require 'event_logger_rails/extensions/loggable'
|
12
|
-
require 'event_logger_rails/
|
13
|
+
require 'event_logger_rails/formatters/json'
|
13
14
|
require 'event_logger_rails/message'
|
14
15
|
require 'event_logger_rails/middleware/capture_request_details'
|
15
16
|
require 'event_logger_rails/output'
|
16
17
|
require 'event_logger_rails/version'
|
17
18
|
|
18
|
-
|
19
|
-
#
|
19
|
+
# Provides configurable state and public API for EventLoggerRails.
|
20
|
+
# Also serves as the namespace for the gem.
|
20
21
|
module EventLoggerRails
|
22
|
+
# @!attribute [r] default_level
|
23
|
+
# @return [Symbol] The default level of the events logged by EventLoggerRails.
|
21
24
|
mattr_accessor :default_level
|
25
|
+
|
26
|
+
# @!attribute [r] formatter
|
27
|
+
# @return [Class] The formatter to use for logging.
|
28
|
+
mattr_accessor :formatter
|
29
|
+
|
30
|
+
# @!attribute [r] logdev
|
31
|
+
# @return [IO, #write] The log device used by EventLoggerRails.
|
22
32
|
mattr_accessor :logdev
|
33
|
+
|
34
|
+
# @!attribute [r] logger_class
|
35
|
+
# @return [Class] The logger class used by EventLoggerRails.
|
36
|
+
mattr_accessor :logger_class
|
37
|
+
|
38
|
+
# @!attribute [r] registered_events
|
39
|
+
# @return [Array<Hash>] The events registry defined in the config/event_logger_rails.yml file.
|
23
40
|
mattr_accessor :registered_events
|
41
|
+
|
42
|
+
# @!attribute [r] sensitive_fields
|
43
|
+
# @return [Array<Symbol>] The fields which may contain sensitive data that EventLoggerRails should filter.
|
24
44
|
mattr_accessor :sensitive_fields
|
25
45
|
|
46
|
+
# Provides a method for configuring EventLoggerRails.
|
47
|
+
#
|
48
|
+
# @yield [self] Gives the class itself to the block for configuration.
|
49
|
+
# @example
|
50
|
+
# EventLoggerRails.setup do |config|
|
51
|
+
# config.default_level = :info
|
52
|
+
# end
|
53
|
+
# @return [void]
|
26
54
|
def self.setup
|
27
55
|
yield self
|
28
56
|
end
|
29
57
|
|
58
|
+
# Returns or initializes the Emitter instance for EventLoggerRails.
|
59
|
+
#
|
60
|
+
# @return [Emitter] The Emitter instance used for logging events.
|
30
61
|
def self.emitter
|
31
|
-
@emitter ||= Emitter.new
|
62
|
+
@emitter ||= Emitter.new
|
32
63
|
end
|
33
64
|
|
65
|
+
# Forwards the arguments to the Emitter's log method.
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# EventLoggerRails.log('foo.bar.baz', level: :info, data: { foo: 'bar' })
|
69
|
+
# @param (see Emitter#log)
|
70
|
+
# @return (see Emitter#log)
|
34
71
|
def self.log(...)
|
35
72
|
emitter.log(...)
|
36
73
|
end
|
37
74
|
|
75
|
+
# Resets the Emitter instance.
|
76
|
+
#
|
77
|
+
# @return [void]
|
38
78
|
def self.reset
|
39
79
|
@emitter = nil
|
40
80
|
end
|
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.4.0
|
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: 2024-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -43,10 +43,11 @@ files:
|
|
43
43
|
- lib/event_logger_rails/emitter.rb
|
44
44
|
- lib/event_logger_rails/engine.rb
|
45
45
|
- lib/event_logger_rails/event.rb
|
46
|
+
- lib/event_logger_rails/event_logger.rb
|
46
47
|
- lib/event_logger_rails/exceptions/invalid_logger_level.rb
|
47
48
|
- lib/event_logger_rails/exceptions/unregistered_event.rb
|
48
49
|
- lib/event_logger_rails/extensions/loggable.rb
|
49
|
-
- lib/event_logger_rails/
|
50
|
+
- lib/event_logger_rails/formatters/json.rb
|
50
51
|
- lib/event_logger_rails/message.rb
|
51
52
|
- lib/event_logger_rails/middleware/capture_request_details.rb
|
52
53
|
- lib/event_logger_rails/output.rb
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module EventLoggerRails
|
4
|
-
##
|
5
|
-
# Writes log entries in JSON format
|
6
|
-
class JsonLogger < ::Logger
|
7
|
-
def initialize(...)
|
8
|
-
super(...)
|
9
|
-
@formatter = proc do |level, timestamp, _progname, message|
|
10
|
-
output = Output.new(level:, timestamp:, message:)
|
11
|
-
"#{output.to_json}\n"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|