event_logger_rails 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +18 -2
- 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 -17
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,13 +352,21 @@ Rails.application.configure do |config|
|
|
344
352
|
end
|
345
353
|
```
|
346
354
|
|
347
|
-
You can
|
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.
|
348
364
|
|
349
365
|
```ruby
|
350
366
|
Rails.application.configure do
|
351
367
|
config.colorize_logging = false
|
352
368
|
config.log_level = ENV.fetch('RAILS_LOG_LEVEL', :info)
|
353
|
-
logger = EventLoggerRails::
|
369
|
+
logger = EventLoggerRails::EventLogger.new($stdout)
|
354
370
|
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
355
371
|
end
|
356
372
|
```
|
@@ -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,17 +0,0 @@
|
|
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
|