active_model_logger 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rubocop.yml +44 -0
- data/CHANGELOG.md +7 -0
- data/CODE_OF_CONDUCT.md +55 -0
- data/LICENSE.txt +21 -0
- data/README.md +1215 -0
- data/Rakefile +12 -0
- data/examples/basic_usage.rb +142 -0
- data/examples/log_block_demo.rb +487 -0
- data/examples/stdout_logging_demo.rb +35 -0
- data/identifier.sqlite +0 -0
- data/lib/active_model_logger/block_logger.rb +133 -0
- data/lib/active_model_logger/generators/active_model_logger/install_generator.rb +30 -0
- data/lib/active_model_logger/generators/active_model_logger/templates/README +33 -0
- data/lib/active_model_logger/generators/active_model_logger/templates/create_active_model_logs.rb +34 -0
- data/lib/active_model_logger/json_query_helpers.rb +103 -0
- data/lib/active_model_logger/log.rb +86 -0
- data/lib/active_model_logger/loggable.rb +380 -0
- data/lib/active_model_logger/loggable_helpers.rb +78 -0
- data/lib/active_model_logger/railtie.rb +14 -0
- data/lib/active_model_logger/version.rb +5 -0
- data/lib/active_model_logger.rb +17 -0
- data/sig/ActiveModelLogger.rbs +4 -0
- metadata +211 -0
@@ -0,0 +1,380 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
require "active_model_logger/block_logger"
|
5
|
+
require "active_model_logger/loggable_helpers"
|
6
|
+
|
7
|
+
module ActiveModelLogger
|
8
|
+
# The Loggable concern provides comprehensive logging functionality to ActiveRecord models.
|
9
|
+
# It allows models to create, query, and manage log entries with various levels of detail.
|
10
|
+
#
|
11
|
+
# @example Basic usage
|
12
|
+
# class User < ApplicationRecord
|
13
|
+
# include ActiveModelLogger::Loggable
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# user = User.create!(name: "John")
|
17
|
+
# user.log("User created successfully")
|
18
|
+
# user.log("User updated", log_level: "info", metadata: { action: "update" })
|
19
|
+
#
|
20
|
+
# @example Configuration
|
21
|
+
# class User < ApplicationRecord
|
22
|
+
# include ActiveModelLogger::Loggable
|
23
|
+
#
|
24
|
+
# configure_loggable(
|
25
|
+
# default_visible_to: "user",
|
26
|
+
# default_log_level: "debug"
|
27
|
+
# )
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# @example Batch logging
|
31
|
+
# user.log_batch([
|
32
|
+
# { message: "Step 1 completed", status: "success" },
|
33
|
+
# { message: "Step 2 completed", status: "success" },
|
34
|
+
# { message: "Process finished", status: "completed" }
|
35
|
+
# ])
|
36
|
+
#
|
37
|
+
module Loggable
|
38
|
+
extend ActiveSupport::Concern
|
39
|
+
include LoggableHelpers
|
40
|
+
|
41
|
+
included do
|
42
|
+
has_many :active_model_logs, as: :loggable, dependent: :destroy, class_name: "ActiveModelLogger::Log"
|
43
|
+
|
44
|
+
# Configuration options
|
45
|
+
class_attribute :loggable_config, default: {
|
46
|
+
default_visible_to: "admin",
|
47
|
+
default_log_level: "info",
|
48
|
+
auto_log_chain: true,
|
49
|
+
log_chain_method: :log_chain,
|
50
|
+
stdout_logging: true,
|
51
|
+
stdout_logger: nil,
|
52
|
+
}
|
53
|
+
|
54
|
+
# Creates a new log entry for this object.
|
55
|
+
#
|
56
|
+
# @param message [String] The log message (required)
|
57
|
+
# @param visible_to [String] Who can see this log (defaults to configured default)
|
58
|
+
# @param log_level [String] The log level: debug, info, warn, error, fatal (defaults to configured default)
|
59
|
+
# @param log_chain [String] Custom log chain for grouping related logs (optional)
|
60
|
+
# @param metadata [Hash] Additional metadata to store with the log entry
|
61
|
+
# @option metadata [String] :status Status of the logged event
|
62
|
+
# @option metadata [String] :category Category of the logged event
|
63
|
+
# @option metadata [String] :type Type of the logged event
|
64
|
+
# @option metadata [String] :title Title of the logged event
|
65
|
+
# @return [ActiveModelLogger::Log] The created log entry
|
66
|
+
# @raise [ArgumentError] If message is nil or log_level is invalid
|
67
|
+
# @raise [ActiveModelLogger::LogCreationError] If the log entry cannot be created
|
68
|
+
#
|
69
|
+
# @example Basic logging
|
70
|
+
# user.log("User logged in")
|
71
|
+
#
|
72
|
+
# @example Logging with log_chain
|
73
|
+
# user.log("Payment processed", log_chain: "payment_123")
|
74
|
+
#
|
75
|
+
# @example Advanced logging with metadata
|
76
|
+
# user.log("Payment processed",
|
77
|
+
# visible_to: "admin",
|
78
|
+
# log_level: "info",
|
79
|
+
# log_chain: "payment_123",
|
80
|
+
# metadata: {
|
81
|
+
# status: "success",
|
82
|
+
# category: "payment",
|
83
|
+
# amount: 100.00
|
84
|
+
# })
|
85
|
+
#
|
86
|
+
def log(message, visible_to: nil, log_level: nil, log_chain: nil, metadata: {})
|
87
|
+
# Use configuration defaults if not provided
|
88
|
+
visible_to ||= loggable_config[:default_visible_to]
|
89
|
+
log_level ||= loggable_config[:default_log_level]
|
90
|
+
|
91
|
+
# Validate inputs
|
92
|
+
validate_log_inputs(message, visible_to, log_level, metadata)
|
93
|
+
|
94
|
+
# Normalize inputs
|
95
|
+
normalized_log_level = log_level.downcase
|
96
|
+
normalized_metadata = metadata.transform_keys(&:to_s)
|
97
|
+
|
98
|
+
# Generate log chain (use provided log_chain or generate one)
|
99
|
+
log_chain_value = log_chain || generate_log_chain(normalized_metadata)
|
100
|
+
|
101
|
+
# If a new log_chain was provided, update the cached log_chain
|
102
|
+
@log_chain = log_chain if log_chain
|
103
|
+
|
104
|
+
# Create log attributes
|
105
|
+
log_attributes = build_log_attributes(
|
106
|
+
message, visible_to, normalized_log_level, normalized_metadata, log_chain_value
|
107
|
+
)
|
108
|
+
|
109
|
+
# Create log entry
|
110
|
+
log_entry = create_log_entry(log_attributes)
|
111
|
+
|
112
|
+
# Send to stdout if enabled
|
113
|
+
stdout_params = {
|
114
|
+
log_entry: log_entry,
|
115
|
+
message: message,
|
116
|
+
visible_to: visible_to,
|
117
|
+
log_level: normalized_log_level,
|
118
|
+
metadata: normalized_metadata,
|
119
|
+
log_chain_value: log_chain_value,
|
120
|
+
}
|
121
|
+
log_to_stdout(stdout_params)
|
122
|
+
|
123
|
+
log_entry
|
124
|
+
rescue ActiveRecord::RecordInvalid => e
|
125
|
+
raise ActiveModelLogger::LogCreationError, "Failed to create log entry: #{e.message}"
|
126
|
+
end
|
127
|
+
|
128
|
+
# Batch logging for performance
|
129
|
+
def log_batch(entries)
|
130
|
+
return [] if entries.empty?
|
131
|
+
|
132
|
+
log_entries = build_batch_log_entries(entries)
|
133
|
+
|
134
|
+
# Use insert_all for efficient batch insertion
|
135
|
+
ActiveModelLogger::Log.insert_all(log_entries)
|
136
|
+
|
137
|
+
# Send to stdout if enabled
|
138
|
+
log_entries.each do |entry|
|
139
|
+
log_to_stdout_batch(entry)
|
140
|
+
end
|
141
|
+
|
142
|
+
active_model_logs.reload
|
143
|
+
end
|
144
|
+
|
145
|
+
# Block-based logging that collects logs during block execution and saves them when the block exits.
|
146
|
+
# This is useful for grouping related operations and ensuring all logs are saved together.
|
147
|
+
#
|
148
|
+
# @param log_chain [String] Optional log chain to use for all logs in this block
|
149
|
+
# @param visible_to [String] Who can see these logs (defaults to configured default)
|
150
|
+
# @param log_level [String] The log level for all logs in this block (defaults to configured default)
|
151
|
+
# @param metadata [Hash] Base metadata to include with all logs in this block
|
152
|
+
# @yield [logger] The block to execute, yielding a logger object
|
153
|
+
# @yieldparam logger [ActiveModelLogger::BlockLogger] A logger object that collects log entries
|
154
|
+
# @return [Array<ActiveModelLogger::Log>] Array of created log entries
|
155
|
+
# @raise [ArgumentError] If no block is provided
|
156
|
+
#
|
157
|
+
# @example Basic usage
|
158
|
+
# user.log_block do |logger|
|
159
|
+
# logger.log("Process started")
|
160
|
+
# logger.log("Step 1 completed", status: "success")
|
161
|
+
# logger.log("Step 2 completed", status: "success")
|
162
|
+
# logger.log("Process finished", status: "complete")
|
163
|
+
# end
|
164
|
+
#
|
165
|
+
# @example With custom log chain and metadata
|
166
|
+
# user.log_block(log_chain: "order_123", metadata: { category: "order" }) do |logger|
|
167
|
+
# logger.log("Order processing started")
|
168
|
+
# logger.log("Payment processed", status: "success", amount: 99.99)
|
169
|
+
# logger.log("Order completed", status: "complete")
|
170
|
+
# end
|
171
|
+
#
|
172
|
+
# @example With custom visibility and log level
|
173
|
+
# user.log_block(visible_to: "admin", log_level: "debug") do |logger|
|
174
|
+
# logger.log("Admin action started")
|
175
|
+
# logger.log("Sensitive operation performed", type: "admin_action")
|
176
|
+
# logger.log("Admin action completed")
|
177
|
+
# end
|
178
|
+
#
|
179
|
+
def log_block(log_chain: nil, visible_to: nil, log_level: nil, metadata: {}, &block)
|
180
|
+
raise ArgumentError, "Block required for log_block" unless block_given?
|
181
|
+
|
182
|
+
# Use configuration defaults if not provided
|
183
|
+
visible_to ||= loggable_config[:default_visible_to]
|
184
|
+
log_level ||= loggable_config[:default_log_level]
|
185
|
+
|
186
|
+
# Normalize inputs
|
187
|
+
normalized_log_level = log_level.downcase
|
188
|
+
normalized_metadata = metadata.transform_keys(&:to_s)
|
189
|
+
|
190
|
+
# Generate log chain (use provided log_chain or generate one)
|
191
|
+
log_chain_value = log_chain || generate_log_chain(normalized_metadata)
|
192
|
+
|
193
|
+
# Create a block logger that collects entries
|
194
|
+
block_logger = BlockLogger.new(
|
195
|
+
self,
|
196
|
+
log_chain_value,
|
197
|
+
visible_to,
|
198
|
+
normalized_log_level,
|
199
|
+
normalized_metadata
|
200
|
+
)
|
201
|
+
|
202
|
+
# Execute the block with the logger
|
203
|
+
block.call(block_logger)
|
204
|
+
|
205
|
+
# Save all collected logs
|
206
|
+
block_logger.save_logs
|
207
|
+
end
|
208
|
+
|
209
|
+
#
|
210
|
+
# returns the logs attached to this object or the logs associated
|
211
|
+
# with the log_chain passed in
|
212
|
+
#
|
213
|
+
# @param log_chain [String] Optional log chain to filter by
|
214
|
+
# @param limit [Integer] Maximum number of logs to return (default: 10)
|
215
|
+
# @return [ActiveRecord::Relation] Collection of log entries
|
216
|
+
#
|
217
|
+
# @example Get all recent logs
|
218
|
+
# user.logs
|
219
|
+
#
|
220
|
+
# @example Get recent logs with custom limit
|
221
|
+
# user.logs(limit: 5)
|
222
|
+
#
|
223
|
+
# @example Get logs for specific chain
|
224
|
+
# user.logs(log_chain: "process_123")
|
225
|
+
#
|
226
|
+
# @example Get logs for specific chain with limit
|
227
|
+
# user.logs(log_chain: "process_123", limit: 3)
|
228
|
+
#
|
229
|
+
def logs(log_chain: nil, limit: 10)
|
230
|
+
if log_chain
|
231
|
+
active_model_logs.by_log_chain(log_chain).newest.limit(limit)
|
232
|
+
else
|
233
|
+
active_model_logs.newest.limit(limit)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
#
|
238
|
+
# The root log on the object will have a log_chain assigned to it. By
|
239
|
+
# default this is a uuid, but the value can be overridden.
|
240
|
+
#
|
241
|
+
# The purpose of a log chain is to connect a series of logs together.
|
242
|
+
# By default, it will use the log_chain from the most recent log entry.
|
243
|
+
# If this is the first log entry, it will generate a new UUID.
|
244
|
+
#
|
245
|
+
# Defaults to either the most recent log_chain or a new UUID. This can be
|
246
|
+
# set specifically by providing the log_chain with the log.
|
247
|
+
#
|
248
|
+
# The default behavior will preserve the log_chain between any services
|
249
|
+
# that use the same database. This is its primary purpose. For this to
|
250
|
+
# work successfully, you will need to set the log_chain value at the
|
251
|
+
# start of any chain of events you want to track. If you have asyncronous
|
252
|
+
# processes using the same table row, you will need to pass the log_chain
|
253
|
+
# value to the other services so they can set the log_chain value and keep
|
254
|
+
# the logs grouped together.
|
255
|
+
#
|
256
|
+
def log_chain
|
257
|
+
@log_chain ||= most_recent_log_chain || SecureRandom.uuid
|
258
|
+
end
|
259
|
+
|
260
|
+
# Get the log_chain from the most recent log entry for this object
|
261
|
+
def most_recent_log_chain
|
262
|
+
return nil unless persisted?
|
263
|
+
|
264
|
+
recent_log = active_model_logs.newest(1).first
|
265
|
+
return nil unless recent_log&.log_chain
|
266
|
+
|
267
|
+
recent_log.log_chain
|
268
|
+
end
|
269
|
+
|
270
|
+
# Send log entry to stdout
|
271
|
+
def log_to_stdout(params)
|
272
|
+
return unless loggable_config[:stdout_logging]
|
273
|
+
|
274
|
+
logger = loggable_config[:stdout_logger] || default_stdout_logger
|
275
|
+
formatted_message = format_stdout_message(params)
|
276
|
+
|
277
|
+
log_to_stdout_with_level(logger, params[:log_level], formatted_message)
|
278
|
+
end
|
279
|
+
|
280
|
+
# Helper method to log with appropriate level
|
281
|
+
def log_to_stdout_with_level(logger, log_level, formatted_message)
|
282
|
+
case log_level.downcase
|
283
|
+
when "debug"
|
284
|
+
logger.debug(formatted_message)
|
285
|
+
when "warn"
|
286
|
+
logger.warn(formatted_message)
|
287
|
+
when "error"
|
288
|
+
logger.error(formatted_message)
|
289
|
+
when "fatal"
|
290
|
+
logger.fatal(formatted_message)
|
291
|
+
else # "info" and unknown levels default to info
|
292
|
+
logger.info(formatted_message)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# Send batch log entry to stdout
|
297
|
+
def log_to_stdout_batch(entry)
|
298
|
+
return unless loggable_config[:stdout_logging]
|
299
|
+
|
300
|
+
logger = loggable_config[:stdout_logger] || default_stdout_logger
|
301
|
+
formatted_message = format_stdout_message_batch(entry)
|
302
|
+
log_level = entry[:metadata]["log_level"] || "info"
|
303
|
+
|
304
|
+
log_to_stdout_with_level(logger, log_level, formatted_message)
|
305
|
+
end
|
306
|
+
|
307
|
+
# Get default stdout logger
|
308
|
+
def default_stdout_logger
|
309
|
+
@default_stdout_logger ||= begin
|
310
|
+
require "logger"
|
311
|
+
Logger.new($stdout)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
# Format message for stdout output
|
316
|
+
def format_stdout_message(params)
|
317
|
+
log_entry = params[:log_entry]
|
318
|
+
message = params[:message]
|
319
|
+
log_level = params[:log_level]
|
320
|
+
metadata = params[:metadata]
|
321
|
+
log_chain_value = params[:log_chain_value]
|
322
|
+
|
323
|
+
timestamp = log_entry.created_at.strftime("%Y-%m-%d %H:%M:%S")
|
324
|
+
model_info = "#{self.class.name}##{id}"
|
325
|
+
chain_info = log_chain_value ? " [chain:#{log_chain_value}]" : ""
|
326
|
+
metadata_info = format_metadata_for_stdout(metadata)
|
327
|
+
|
328
|
+
"[#{timestamp}] #{log_level.upcase} #{model_info}#{chain_info} - #{message}#{metadata_info}"
|
329
|
+
end
|
330
|
+
|
331
|
+
# Format batch message for stdout output
|
332
|
+
def format_stdout_message_batch(entry)
|
333
|
+
timestamp = entry[:created_at].strftime("%Y-%m-%d %H:%M:%S")
|
334
|
+
model_info = "#{entry[:loggable_type]}##{entry[:loggable_id]}"
|
335
|
+
log_level = entry[:metadata]["log_level"] || "info"
|
336
|
+
chain_info = entry[:metadata]["log_chain"] ? " [chain:#{entry[:metadata]['log_chain']}]" : ""
|
337
|
+
metadata_info = format_metadata_for_stdout(entry[:metadata])
|
338
|
+
|
339
|
+
"[#{timestamp}] #{log_level.upcase} #{model_info}#{chain_info} - #{entry[:message]}#{metadata_info}"
|
340
|
+
end
|
341
|
+
|
342
|
+
# Format metadata for stdout output
|
343
|
+
def format_metadata_for_stdout(metadata)
|
344
|
+
return "" if metadata.nil? || metadata.empty?
|
345
|
+
|
346
|
+
relevant_metadata = metadata.except("log_level", "visible_to", "log_chain")
|
347
|
+
return "" if relevant_metadata.empty?
|
348
|
+
|
349
|
+
formatted = relevant_metadata.map { |k, v| "#{k}=#{v}" }.join(", ")
|
350
|
+
" (#{formatted})"
|
351
|
+
end
|
352
|
+
|
353
|
+
# Configuration methods
|
354
|
+
def self.configure_loggable(options = {})
|
355
|
+
self.loggable_config = loggable_config.merge(options)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
class_methods do
|
360
|
+
# Class-level configuration
|
361
|
+
def configure_loggable(options = {})
|
362
|
+
self.loggable_config = loggable_config.merge(options)
|
363
|
+
end
|
364
|
+
|
365
|
+
# Find models with recent activity
|
366
|
+
def with_recent_logs(since: 1.hour.ago)
|
367
|
+
joins(:active_model_logs)
|
368
|
+
.where(active_model_logs: { created_at: since.. })
|
369
|
+
.distinct
|
370
|
+
end
|
371
|
+
|
372
|
+
# Find models by log level
|
373
|
+
def with_logs_at_level(level)
|
374
|
+
joins(:active_model_logs)
|
375
|
+
.where(active_model_logs: { log_level: level.downcase })
|
376
|
+
.distinct
|
377
|
+
end
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveModelLogger
|
4
|
+
# Helper methods for the Loggable concern
|
5
|
+
module LoggableHelpers
|
6
|
+
def validate_log_inputs(message, visible_to, log_level, metadata)
|
7
|
+
raise ArgumentError, "Message cannot be nil" if message.nil?
|
8
|
+
raise ArgumentError, "Visible_to cannot be nil or empty" if visible_to.nil? || visible_to.empty?
|
9
|
+
raise ArgumentError, "Log level cannot be nil or empty" if log_level.nil? || log_level.empty?
|
10
|
+
raise ArgumentError, "Metadata must be a hash" unless metadata.is_a?(Hash)
|
11
|
+
|
12
|
+
valid_levels = %w[debug info warn error fatal]
|
13
|
+
return if valid_levels.include?(log_level.downcase)
|
14
|
+
|
15
|
+
raise ArgumentError, "Invalid log level '#{log_level}'. Must be one of: #{valid_levels.join(', ')}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate_log_chain(normalized_metadata)
|
19
|
+
if loggable_config[:auto_log_chain] && normalized_metadata["log_chain"].nil?
|
20
|
+
send(loggable_config[:log_chain_method])
|
21
|
+
else
|
22
|
+
normalized_metadata["log_chain"] || send(loggable_config[:log_chain_method])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def build_log_attributes(message, visible_to, log_level, normalized_metadata, log_chain_value)
|
27
|
+
{
|
28
|
+
message: message.to_s,
|
29
|
+
log_chain: log_chain_value,
|
30
|
+
status: normalized_metadata["status"],
|
31
|
+
category: normalized_metadata["category"],
|
32
|
+
type: normalized_metadata["type"],
|
33
|
+
title: normalized_metadata["title"],
|
34
|
+
visible_to: visible_to.to_s,
|
35
|
+
log_level: log_level,
|
36
|
+
data: normalized_metadata["data"],
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_log_entry(log_attributes)
|
41
|
+
if respond_to?(:create_log!)
|
42
|
+
create_log!(log_attributes)
|
43
|
+
else
|
44
|
+
active_model_logs.create!(log_attributes)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def build_batch_log_entries(entries)
|
49
|
+
entries.map do |entry|
|
50
|
+
{
|
51
|
+
loggable_type: self.class.name,
|
52
|
+
loggable_id: id,
|
53
|
+
message: entry[:message].to_s,
|
54
|
+
metadata: {
|
55
|
+
log_chain: entry[:log_chain] || log_chain,
|
56
|
+
status: entry[:status],
|
57
|
+
category: entry[:category],
|
58
|
+
type: entry[:type],
|
59
|
+
title: entry[:title],
|
60
|
+
visible_to: entry[:visible_to] || loggable_config[:default_visible_to],
|
61
|
+
log_level: (entry[:log_level] || loggable_config[:default_log_level]).downcase,
|
62
|
+
data: entry[:data],
|
63
|
+
},
|
64
|
+
created_at: Time.current,
|
65
|
+
updated_at: Time.current,
|
66
|
+
}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def cleanup_logs(older_than: 30.days, keep_recent: 100)
|
71
|
+
old_logs = active_model_logs.where("created_at < ?", older_than.ago)
|
72
|
+
recent_logs = active_model_logs.newest(keep_recent)
|
73
|
+
|
74
|
+
logs_to_delete = old_logs.where.not(id: recent_logs.select(:id))
|
75
|
+
logs_to_delete.delete_all
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveModelLogger
|
4
|
+
if defined?(Rails)
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
initializer "active_model_logger.setup" do
|
7
|
+
# Include the Loggable concern in ApplicationRecord by default
|
8
|
+
ActiveSupport.on_load(:active_record) do
|
9
|
+
ApplicationRecord.include ActiveModelLogger::Loggable if defined?(ApplicationRecord)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model_logger/version"
|
4
|
+
require "active_model_logger/loggable"
|
5
|
+
require "active_model_logger/log"
|
6
|
+
require "active_model_logger/block_logger"
|
7
|
+
require "active_model_logger/loggable_helpers"
|
8
|
+
require "active_model_logger/railtie"
|
9
|
+
|
10
|
+
# Load generators if Rails is available and fully loaded
|
11
|
+
require "active_model_logger/generators/active_model_logger/install_generator" if defined?(Rails::Generators)
|
12
|
+
|
13
|
+
module ActiveModelLogger
|
14
|
+
class Error < StandardError; end
|
15
|
+
class LogCreationError < Error; end
|
16
|
+
class ConfigurationError < Error; end
|
17
|
+
end
|