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.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[test rubocop]
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Basic usage example for ActiveModelLogger
4
+ # This file demonstrates how to use the gem in a Rails application
5
+
6
+ # 1. Include the Loggable concern in your models
7
+ # This will add the active_model_logs association and logging methods
8
+ # The logs are stored as Log records and sent to stdout by default
9
+ class User < ActiveRecord::Base
10
+ include ActiveModelLogger::Loggable
11
+ end
12
+
13
+ class Order < ActiveRecord::Base
14
+ include ActiveModelLogger::Loggable
15
+ end
16
+
17
+ # 2. Basic logging with automatic stdout output
18
+ user = User.find(1)
19
+ user.log("User logged in") # Will appear in both database and stdout
20
+ user.log("Payment processed", log_level: "info")
21
+
22
+ # 3. Logging with log_chain parameter
23
+ user.log("Process started", log_chain: "order_processing_123")
24
+ user.log("Step 1 completed") # Uses cached log_chain
25
+ user.log("Step 2 completed") # Uses cached log_chain
26
+
27
+ # 4. Logging with metadata
28
+ user.log("Order created",
29
+ log_level: "info",
30
+ log_chain: "order_123",
31
+ metadata: {
32
+ status: "success",
33
+ category: "order",
34
+ order_id: 123,
35
+ })
36
+
37
+ # 5. Logging with custom data field
38
+ user.log("Payment processed",
39
+ log_level: "info",
40
+ metadata: {
41
+ status: "success",
42
+ category: "payment",
43
+ data: {
44
+ amount: 99.99,
45
+ currency: "USD",
46
+ payment_method: "credit_card",
47
+ transaction_id: "txn_123456",
48
+ },
49
+ })
50
+
51
+ # 6. Logging with custom visibility
52
+ user.log("Admin action performed",
53
+ visible_to: "admin",
54
+ metadata: { action: "user_suspended" })
55
+
56
+ # 7. Working with log chains (automatic caching)
57
+ # First log generates and caches a UUID
58
+ user.log("Process started") # Uses: "abc-123-def"
59
+
60
+ # Subsequent logs use the cached chain
61
+ user.log("Step 1 completed") # Uses: "abc-123-def" (cached)
62
+ user.log("Step 2 completed") # Uses: "abc-123-def" (cached)
63
+
64
+ # Explicit log_chain breaks the cache
65
+ user.log("New process", log_chain: "process_456") # Uses: "process_456"
66
+
67
+ # Next logs use the new cached chain
68
+ user.log("Step A") # Uses: "process_456" (cached)
69
+ user.log("Step B") # Uses: "process_456" (cached)
70
+
71
+ # 8. Batch logging for efficiency
72
+ user.log_batch([
73
+ { message: "Batch step 1", status: "success", log_chain: "batch_123" },
74
+ { message: "Batch step 2", status: "success" }, # Uses cached log_chain
75
+ { message: "Batch completed", status: "complete" }, # Uses cached log_chain
76
+ ])
77
+
78
+ # 8.1. Block-based logging for grouping related operations
79
+ user.log_block do |logger|
80
+ logger.log("Process started")
81
+ logger.log("Step 1 completed", status: "success")
82
+ logger.log("Step 2 completed", status: "success")
83
+ logger.log("Process finished", status: "complete")
84
+ end
85
+
86
+ # 8.2. Block logging with custom log chain and metadata
87
+ user.log_block(log_chain: "order_processing_456", metadata: { category: "order" }) do |logger|
88
+ logger.log("Order processing started")
89
+ logger.log("Payment processed", status: "success", amount: 99.99)
90
+ logger.log("Inventory updated", status: "success", items: 3)
91
+ logger.log("Order completed", status: "complete")
92
+ end
93
+
94
+ # 8.3. Block logging with custom visibility and log level
95
+ user.log_block(visible_to: "admin", log_level: "debug") do |logger|
96
+ logger.log("Admin action started")
97
+ logger.log("Sensitive operation performed", type: "admin_action")
98
+ logger.log("Admin action completed")
99
+ end
100
+
101
+ # 9. Accessing logs
102
+ user.active_model_logs.newest(1).first # Most recent log
103
+ user.active_model_logs.by_log_chain("process_456").order(:created_at).first # First log in specific chain
104
+ user.logs # All logs for this user (default limit: 10)
105
+ user.logs(limit: 5) # Recent logs limited to 5
106
+ user.logs(log_chain: "process_456") # Logs in specific chain
107
+ user.logs(log_chain: "process_456", limit: 3) # Logs in specific chain, limited to 3
108
+
109
+ # 10. Configuration options
110
+ class User < ActiveRecord::Base
111
+ include ActiveModelLogger::Loggable
112
+
113
+ # Configure default values
114
+ configure_loggable(
115
+ default_visible_to: "user",
116
+ default_log_level: "debug",
117
+ stdout_logging: true, # Enable stdout logging (default: true)
118
+ stdout_logger: Logger.new($stdout) # Custom logger (optional)
119
+ )
120
+ end
121
+
122
+ # 11. Disabling stdout logging
123
+ class Order < ActiveRecord::Base
124
+ include ActiveModelLogger::Loggable
125
+
126
+ configure_loggable(stdout_logging: false) # Only store in database
127
+ end
128
+
129
+ # 12. Using scopes for querying
130
+ ActiveModelLogger::Log.by_level("error")
131
+ ActiveModelLogger::Log.by_visibility("admin")
132
+ ActiveModelLogger::Log.by_log_chain("process_456")
133
+ ActiveModelLogger::Log.by_status("success")
134
+ ActiveModelLogger::Log.by_category("payment")
135
+ ActiveModelLogger::Log.with_data
136
+ ActiveModelLogger::Log.newest(10) # Last 10 logs
137
+ ActiveModelLogger::Log.in_range(1.hour.ago, Time.current)
138
+
139
+ # 13. Example output format in stdout:
140
+ # [2025-09-05 20:58:15] INFO User#123 [chain:abc-123-def] - User logged in (status=success, category=authentication)
141
+ # [2025-09-05 20:58:16] WARN Order#456 [chain:order-789] - Payment processing started (amount=99.99)
142
+ # [2025-09-05 20:58:17] ERROR User#123 [chain:abc-123-def] - Payment failed (error=insufficient_funds)
@@ -0,0 +1,487 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # This example demonstrates the log_block functionality of ActiveModelLogger
5
+ # Run this script to see logs being collected during block execution and saved when the block exits
6
+
7
+ require "bundler/setup"
8
+ require "active_record"
9
+ require "active_support"
10
+ require "active_support/core_ext"
11
+ require "logger"
12
+
13
+ # Load the gem
14
+ require_relative "../lib/active_model_logger"
15
+
16
+ puts "=== ActiveModelLogger Comprehensive Demo ==="
17
+ puts "This demo showcases all the latest functionality including log_block, scopes, and advanced features."
18
+ puts ""
19
+
20
+ # Set up a simple in-memory SQLite database for demonstration
21
+ ActiveRecord::Base.establish_connection(
22
+ adapter: "sqlite3",
23
+ database: ":memory:"
24
+ )
25
+
26
+ # Create the logs table
27
+ ActiveRecord::Base.connection.create_table :active_model_logs do |t|
28
+ t.references :loggable, polymorphic: true, null: false
29
+ t.string :message, null: false
30
+ t.string :log_level, default: "info"
31
+ t.string :visible_to, default: "user"
32
+ t.string :log_chain
33
+ t.json :metadata
34
+ t.timestamps
35
+ end
36
+
37
+ # Create a simple demo_models table
38
+ ActiveRecord::Base.connection.create_table :demo_models, &:timestamps
39
+
40
+ # Create a custom_demo_models table
41
+ ActiveRecord::Base.connection.create_table :custom_demo_models, &:timestamps
42
+
43
+ # Create a simple model for demonstration
44
+ class DemoModel < ActiveRecord::Base
45
+ include ActiveModelLogger::Loggable
46
+
47
+ # Configure with stdout logging for demonstration
48
+ configure_loggable(
49
+ stdout_logging: true,
50
+ stdout_logger: Logger.new($stdout)
51
+ )
52
+ end
53
+
54
+ # Create a test instance
55
+ demo = DemoModel.create!(id: 1)
56
+
57
+ puts "šŸš€ Starting Log Block Demonstrations"
58
+ puts "=" * 50
59
+ puts ""
60
+
61
+ # Demo 1: Basic log_block usage
62
+ puts "šŸ“ Demo 1: Basic Log Block"
63
+ puts "-" * 30
64
+ puts "Creating a basic log block with multiple log entries..."
65
+
66
+ logs = demo.log_block do |logger|
67
+ logger.log("Process started")
68
+ sleep(0.1) # Simulate some work
69
+ logger.log("Step 1 completed", status: "success")
70
+ sleep(0.1) # Simulate some work
71
+ logger.log("Step 2 completed", status: "success")
72
+ sleep(0.1) # Simulate some work
73
+ logger.log("Process finished", status: "complete")
74
+ end
75
+
76
+ puts "āœ… Log block completed! Created #{logs.count} log entries"
77
+ if logs.any?
78
+ puts "šŸ“Š Log chain: #{logs.first.metadata['log_chain']}"
79
+ else
80
+ puts "āš ļø No logs returned - checking all logs for this model..."
81
+ all_logs = demo.logs
82
+ puts "šŸ“Š Total logs in database: #{all_logs.count}"
83
+ puts "šŸ“Š First log metadata: #{all_logs.first.metadata}" if all_logs.any?
84
+ end
85
+ puts ""
86
+
87
+ # Demo 2: Custom log_chain and metadata
88
+ puts "šŸ“ Demo 2: Custom Log Chain and Metadata"
89
+ puts "-" * 40
90
+ puts "Creating a log block with custom parameters..."
91
+
92
+ order_logs = demo.log_block(
93
+ log_chain: "order_processing_123",
94
+ metadata: { category: "order", order_id: 123 }
95
+ ) do |logger|
96
+ logger.log("Order processing started")
97
+ sleep(0.1)
98
+ logger.log("Payment processed", status: "success", amount: 99.99)
99
+ sleep(0.1)
100
+ logger.log("Inventory updated", status: "success", items: 3)
101
+ sleep(0.1)
102
+ logger.log("Order completed", status: "complete")
103
+ end
104
+
105
+ puts "āœ… Order processing completed! Created #{order_logs.count} log entries"
106
+ puts "šŸ“Š Log chain: #{order_logs.first.log_chain}"
107
+ puts "šŸ“Š Category: #{order_logs.first.metadata['category']}"
108
+ puts ""
109
+
110
+ # Demo 3: Custom visibility and log level
111
+ puts "šŸ“ Demo 3: Admin Actions with Custom Visibility"
112
+ puts "-" * 45
113
+ puts "Creating an admin log block with debug level..."
114
+
115
+ admin_logs = demo.log_block(
116
+ visible_to: "admin",
117
+ log_level: "debug"
118
+ ) do |logger|
119
+ logger.log("Admin action started")
120
+ sleep(0.1)
121
+ logger.log("Sensitive operation performed", type: "admin_action", user_id: 456)
122
+ sleep(0.1)
123
+ logger.log("Admin action completed")
124
+ end
125
+
126
+ puts "āœ… Admin action completed! Created #{admin_logs.count} log entries"
127
+ puts "šŸ“Š Visibility: #{admin_logs.first.visible_to}"
128
+ puts "šŸ“Š Log level: #{admin_logs.first.log_level}"
129
+ puts ""
130
+
131
+ # Demo 4: Error handling in log blocks
132
+ puts "šŸ“ Demo 4: Error Handling in Log Blocks"
133
+ puts "-" * 40
134
+ puts "Demonstrating error handling within log blocks..."
135
+
136
+ begin
137
+ demo.log_block(log_chain: "error_demo") do |logger|
138
+ logger.log("Process started")
139
+ sleep(0.1)
140
+ logger.log("Step 1 completed", status: "success")
141
+ sleep(0.1)
142
+ logger.log("Step 2 failed", status: "error", error: "simulated_error")
143
+ sleep(0.1)
144
+ # Simulate an error
145
+ raise StandardError, "Something went wrong!"
146
+ end
147
+ rescue StandardError => e
148
+ puts "āš ļø Error caught: #{e.message}"
149
+ puts "āœ… Logs were still saved before the error occurred"
150
+ end
151
+
152
+ puts ""
153
+
154
+ # Demo 5: Nested log blocks
155
+ puts "šŸ“ Demo 5: Nested Log Blocks"
156
+ puts "-" * 30
157
+ puts "Demonstrating nested log blocks..."
158
+
159
+ # Track inner logs separately
160
+ inner_logs = nil
161
+
162
+ outer_logs = demo.log_block(log_chain: "outer_process") do |logger|
163
+ logger.log("Outer process started")
164
+ sleep(0.1)
165
+
166
+ # Nested log block
167
+ inner_logs = demo.log_block(log_chain: "inner_process") do |inner_logger|
168
+ inner_logger.log("Inner process started")
169
+ sleep(0.1)
170
+ inner_logger.log("Inner process completed")
171
+ end
172
+
173
+ logger.log("Outer process completed")
174
+ end
175
+
176
+ puts "āœ… Nested log blocks completed!"
177
+ puts "šŸ“Š Outer logs: #{outer_logs.count}"
178
+ puts "šŸ“Š Inner logs: #{inner_logs.count}"
179
+ puts ""
180
+
181
+ # Demo 6: Querying logs from blocks
182
+ puts "šŸ“ Demo 6: Querying Logs from Blocks"
183
+ puts "-" * 35
184
+ puts "Demonstrating how to query logs created in blocks..."
185
+
186
+ # Get all logs for our demo model
187
+ all_logs = demo.logs(limit: 20)
188
+ puts "šŸ“Š Total logs created: #{all_logs.count}"
189
+
190
+ # Get logs by log_chain
191
+ order_logs_query = demo.logs(log_chain: "order_processing_123")
192
+ puts "šŸ“Š Order processing logs: #{order_logs_query.count}"
193
+
194
+ # Get logs by visibility
195
+ admin_logs_query = demo.logs.select { |log| log.visible_to == "admin" }
196
+ puts "šŸ“Š Admin logs: #{admin_logs_query.count}"
197
+
198
+ # Get logs by status
199
+ success_logs = demo.logs.select { |log| log.metadata&.dig("status") == "success" }
200
+ puts "šŸ“Š Success logs: #{success_logs.count}"
201
+
202
+ puts ""
203
+
204
+ # Demo 7: Performance comparison
205
+ puts "šŸ“ Demo 7: Performance Comparison"
206
+ puts "-" * 35
207
+ puts "Comparing individual logs vs log_block performance..."
208
+
209
+ # Individual logs
210
+ start_time = Time.current
211
+ 10.times do |i|
212
+ demo.log("Individual log #{i}", metadata: { status: "test" })
213
+ end
214
+ individual_time = Time.current - start_time
215
+
216
+ # Log block
217
+ start_time = Time.current
218
+ demo.log_block(log_chain: "performance_test") do |logger|
219
+ 10.times do |i|
220
+ logger.log("Block log #{i}", status: "test")
221
+ end
222
+ end
223
+ block_time = Time.current - start_time
224
+
225
+ puts "ā±ļø Individual logs time: #{(individual_time * 1000).round(2)}ms"
226
+ puts "ā±ļø Log block time: #{(block_time * 1000).round(2)}ms"
227
+ puts "šŸ“ˆ Performance improvement: #{((individual_time - block_time) / individual_time * 100).round(1)}%"
228
+ puts ""
229
+
230
+ # Demo 8: Advanced Scopes and Querying
231
+ puts "šŸ“ Demo 8: Advanced Scopes and Querying"
232
+ puts "-" * 40
233
+ puts "Demonstrating the powerful scopes available for querying logs..."
234
+
235
+ # Create some diverse logs for querying
236
+ demo.log("User authentication started", log_level: "info", metadata: { category: "auth", status: "started" })
237
+ demo.log("Database connection established", log_level: "debug", metadata: { category: "database", status: "success" })
238
+ demo.log("Payment processing failed", log_level: "error",
239
+ metadata: { category: "payment", status: "failed", error_code: "INSUFFICIENT_FUNDS" })
240
+ demo.log("Email sent successfully", log_level: "info",
241
+ metadata: { category: "notification", status: "sent", recipient: "user@example.com" })
242
+ demo.log("Cache cleared", log_level: "debug", metadata: { category: "cache", status: "cleared" })
243
+ demo.log("Security alert triggered", log_level: "warn",
244
+ metadata: { category: "security", status: "alert", severity: "high" })
245
+
246
+ # Add some logs with data for demonstration
247
+ demo.log("User profile updated", log_level: "info",
248
+ metadata: { category: "user", status: "success",
249
+ data: { user_id: 123, changes: %w[email name] } })
250
+ demo.log("Order created", log_level: "info",
251
+ metadata: { category: "order", status: "created",
252
+ data: { order_id: 456, amount: 99.99, currency: "USD" } })
253
+ demo.log("Admin action", log_level: "info",
254
+ metadata: { category: "admin", status: "success",
255
+ data: { user_id: 123, action: "user_created", target_user: 789 } })
256
+
257
+ # Add some logs with keys at root level for with_keys demonstration
258
+ demo.log("User login", log_level: "info",
259
+ metadata: { user_id: 456, session_id: "abc123", ip_address: "192.168.1.1" })
260
+ demo.log("Payment processed", log_level: "info",
261
+ metadata: { order_id: 789, amount: 149.99, status: "completed" })
262
+ demo.log("System event", log_level: "info",
263
+ metadata: { event_type: "backup", status: "completed", category: "system" })
264
+
265
+ puts "šŸ“Š Total logs created: #{ActiveModelLogger::Log.count}"
266
+
267
+ # Demonstrate various scopes
268
+ puts "\nšŸ” Querying by log level:"
269
+ puts " Info logs: #{ActiveModelLogger::Log.info_logs.count}"
270
+ puts " Debug logs: #{ActiveModelLogger::Log.debug_logs.count}"
271
+ puts " Error logs: #{ActiveModelLogger::Log.error_logs.count}"
272
+ puts " Warning logs: #{ActiveModelLogger::Log.warning_logs.count}"
273
+
274
+ puts "\nšŸ” Querying by category:"
275
+ puts " Auth logs: #{ActiveModelLogger::Log.by_category('auth').count}"
276
+ puts " Payment logs: #{ActiveModelLogger::Log.by_category('payment').count}"
277
+ puts " Database logs: #{ActiveModelLogger::Log.by_category('database').count}"
278
+
279
+ puts "\nšŸ” Querying by status:"
280
+ puts " Success logs: #{ActiveModelLogger::Log.by_status('success').count}"
281
+ puts " Failed logs: #{ActiveModelLogger::Log.by_status('failed').count}"
282
+
283
+ puts "\nšŸ” Querying with data:"
284
+ puts " Logs with data: #{ActiveModelLogger::Log.with_data.count}"
285
+
286
+ puts "\nšŸ” Recent logs:"
287
+ recent_logs = ActiveModelLogger::Log.newest(3)
288
+ recent_logs.each_with_index do |log, index|
289
+ puts " #{index + 1}. [#{log.log_level.upcase}] #{log.message} (#{log.metadata['category']})"
290
+ end
291
+
292
+ puts ""
293
+
294
+ # Demo 9: Log Chain Management
295
+ puts "šŸ“ Demo 9: Log Chain Management"
296
+ puts "-" * 35
297
+ puts "Demonstrating automatic log chain management..."
298
+
299
+ # Create logs with automatic chain management
300
+ demo.log("Process A started")
301
+ demo.log("Process A step 1 completed", metadata: { status: "success" })
302
+ demo.log("Process A step 2 completed", metadata: { status: "success" })
303
+
304
+ # Start a new process (new chain)
305
+ demo.log("Process B started", log_chain: "process_b_123")
306
+ demo.log("Process B step 1 completed", metadata: { status: "success" })
307
+ demo.log("Process B step 2 completed", metadata: { status: "success" })
308
+
309
+ # Continue with Process A (should use cached chain)
310
+ demo.log("Process A step 3 completed", metadata: { status: "success" })
311
+ demo.log("Process A finished", metadata: { status: "complete" })
312
+
313
+ puts "šŸ“Š Current log chain: #{demo.log_chain}"
314
+ puts "šŸ“Š Most recent log chain: #{demo.most_recent_log_chain}"
315
+
316
+ # Query by log chain
317
+ process_a_logs = demo.logs(log_chain: demo.most_recent_log_chain)
318
+ puts "šŸ“Š Process A logs: #{process_a_logs.count}"
319
+
320
+ process_b_logs = demo.logs(log_chain: "process_b_123")
321
+ puts "šŸ“Š Process B logs: #{process_b_logs.count}"
322
+
323
+ puts ""
324
+
325
+ # Demo 10: Batch Logging
326
+ puts "šŸ“ Demo 10: Batch Logging"
327
+ puts "-" * 30
328
+ puts "Demonstrating efficient batch logging..."
329
+
330
+ batch_entries = [
331
+ { message: "Batch step 1", metadata: { status: "success", category: "batch" } },
332
+ { message: "Batch step 2", metadata: { status: "success", category: "batch" } },
333
+ { message: "Batch step 3", metadata: { status: "success", category: "batch" } },
334
+ { message: "Batch completed", metadata: { status: "complete", category: "batch" } },
335
+ ]
336
+
337
+ batch_logs = demo.log_batch(batch_entries)
338
+ puts "āœ… Batch logging completed! Created #{batch_logs.count} log entries"
339
+ puts "šŸ“Š Batch log chain: #{batch_logs.first.metadata['log_chain']}"
340
+
341
+ puts ""
342
+
343
+ # Demo 11: Log Cleanup
344
+ puts "šŸ“ Demo 11: Log Cleanup"
345
+ puts "-" * 25
346
+ puts "Demonstrating log cleanup functionality..."
347
+
348
+ # Create some old logs (simulate by setting created_at in the past)
349
+ old_log = ActiveModelLogger::Log.create!(
350
+ loggable: demo,
351
+ message: "Old log entry",
352
+ metadata: { log_chain: "old_chain", status: "old", category: "cleanup" },
353
+ created_at: 35.days.ago,
354
+ updated_at: 35.days.ago
355
+ )
356
+
357
+ puts "šŸ“Š Logs before cleanup: #{ActiveModelLogger::Log.count}"
358
+
359
+ # Cleanup logs older than 30 days, keeping 100 recent
360
+ demo.cleanup_logs(older_than: 30.days, keep_recent: 100)
361
+
362
+ puts "šŸ“Š Logs after cleanup: #{ActiveModelLogger::Log.count}"
363
+ puts "āœ… Old log cleaned up: #{ActiveModelLogger::Log.find_by(id: old_log.id).nil?}"
364
+
365
+ puts ""
366
+
367
+ # Demo 12: Model-Level Querying
368
+ puts "šŸ“ Demo 12: Model-Level Querying"
369
+ puts "-" * 35
370
+ puts "Demonstrating model-level querying methods..."
371
+
372
+ # Get current log
373
+ current = demo.active_model_logs.newest(1).first
374
+ puts "šŸ“Š Current log: #{current&.message} (#{current&.metadata&.dig('category')})"
375
+
376
+ # Get root log for a specific chain (using oldest scope)
377
+ root_log = demo.logs(log_chain: "process_b_123").oldest(1).first
378
+ puts "šŸ“Š Root log for process_b_123: #{root_log&.message}"
379
+
380
+ # Get logs with custom limit
381
+ recent_five = demo.logs(limit: 5)
382
+ puts "šŸ“Š Recent 5 logs: #{recent_five.count}"
383
+
384
+ # Get logs for specific chain
385
+ chain_logs = demo.logs(log_chain: "process_b_123")
386
+ puts "šŸ“Š Process B chain logs: #{chain_logs.count}"
387
+
388
+ # Demonstrate ordering scopes
389
+ puts "šŸ“Š Oldest 3 logs: #{demo.active_model_logs.oldest(3).pluck(:message).join(', ')}"
390
+ puts "šŸ“Š Newest 3 logs: #{demo.active_model_logs.newest(3).pluck(:message).join(', ')}"
391
+
392
+ # Demonstrate with_data scope with hash parameter
393
+ puts "\nšŸ” Data Querying Examples:"
394
+ puts "šŸ“Š Logs with data: #{demo.active_model_logs.with_data.count}"
395
+ puts "šŸ“Š Logs with user_id 123: #{demo.active_model_logs.with_data({ user_id: 123 }).count}"
396
+ puts "šŸ“Š Logs with order_id 456: #{demo.active_model_logs.with_data({ order_id: 456 }).count}"
397
+
398
+ # Demonstrate with_keys scope
399
+ puts "\nšŸ” Key Querying Examples:"
400
+ puts "šŸ“Š Logs with user_id key: #{demo.active_model_logs.with_keys('user_id').count}"
401
+ puts "šŸ“Š Logs with category key: #{demo.active_model_logs.with_keys('category').count}"
402
+ puts "šŸ“Š Logs with both user_id and category: #{demo.active_model_logs.with_keys('user_id', 'category').count}"
403
+
404
+ puts ""
405
+
406
+ # Demo 13: Configuration Options
407
+ puts "šŸ“ Demo 13: Configuration Options"
408
+ puts "-" * 35
409
+ puts "Demonstrating different configuration options..."
410
+
411
+ # Create a model with custom configuration
412
+ class CustomDemoModel < ActiveRecord::Base
413
+ include ActiveModelLogger::Loggable
414
+
415
+ # Custom configuration
416
+ configure_loggable(
417
+ default_visible_to: "system",
418
+ default_log_level: "debug",
419
+ stdout_logging: false # Disable stdout for this demo
420
+ )
421
+ end
422
+
423
+ custom_demo = CustomDemoModel.create!(id: 2)
424
+
425
+ # Test custom configuration
426
+ custom_demo.log("System process started")
427
+ custom_demo.log("System process completed", metadata: { status: "success" })
428
+
429
+ puts "šŸ“Š Custom model logs: #{custom_demo.logs.count}"
430
+ puts "šŸ“Š Custom model visibility: #{custom_demo.logs.first.metadata['visible_to']}"
431
+ puts "šŸ“Š Custom model log level: #{custom_demo.logs.first.metadata['log_level']}"
432
+
433
+ puts ""
434
+
435
+ # Summary
436
+ puts "šŸŽ‰ Comprehensive Demo Complete!"
437
+ puts "=" * 30
438
+ puts ""
439
+ puts "šŸš€ ActiveModelLogger Features Demonstrated:"
440
+ puts ""
441
+ puts "šŸ“¦ Core Logging:"
442
+ puts "• āœ… Individual logging with metadata"
443
+ puts "• āœ… Batch logging for performance"
444
+ puts "• āœ… Log block for atomic operations"
445
+ puts "• āœ… Automatic log chain management"
446
+ puts "• āœ… Custom configuration per model"
447
+ puts ""
448
+ puts "šŸ” Advanced Querying:"
449
+ puts "• āœ… Query by log level (debug, info, warn, error, fatal)"
450
+ puts "• āœ… Query by category, status, type"
451
+ puts "• āœ… Query by log chain for related operations"
452
+ puts "• āœ… Query logs with data/metadata"
453
+ puts "• āœ… Recent logs with custom limits"
454
+ puts "• āœ… Time-based range queries"
455
+ puts ""
456
+ puts "⚔ Performance Features:"
457
+ puts "• āœ… Batch insertion with insert_all (ActiveRecord 6.0+)"
458
+ puts "• āœ… Automatic log cleanup"
459
+ puts "• āœ… Efficient scopes for large datasets"
460
+ puts "• āœ… Database-agnostic JSON queries"
461
+ puts ""
462
+ puts "šŸ› ļø Developer Experience:"
463
+ puts "• āœ… Stdout logging with formatted output"
464
+ puts "• āœ… Error handling and validation"
465
+ puts "• āœ… Nested log blocks support"
466
+ puts "• āœ… Flexible metadata system"
467
+ puts "• āœ… Model-level querying methods"
468
+ puts ""
469
+ puts "šŸŽÆ Perfect for:"
470
+ puts "• šŸ›’ E-commerce order processing"
471
+ puts "• šŸ” User authentication and authorization"
472
+ puts "• šŸ“Š Data processing pipelines"
473
+ puts "• šŸš€ Background job execution"
474
+ puts "• šŸ”§ Admin operations and maintenance"
475
+ puts "• šŸ“ Comprehensive audit trails"
476
+ puts "• šŸ› Application debugging and monitoring"
477
+ puts "• šŸ“ˆ Performance tracking and analytics"
478
+ puts ""
479
+ puts "šŸš€ Getting Started:"
480
+ puts "1. Include ActiveModelLogger::Loggable in your models"
481
+ puts "2. Configure logging options per model"
482
+ puts "3. Use log_block for grouping related operations"
483
+ puts "4. Query logs using powerful scopes and methods"
484
+ puts "5. Set up log cleanup for production environments"
485
+ puts ""
486
+ puts "šŸ“š For more information, see the gem documentation and examples!"
487
+ puts ""
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # This example demonstrates the stdout logging functionality of ActiveModelLogger
5
+ # Run this script to see logs being output to both database and standard output
6
+ #
7
+ # Note: This example requires a Rails application with the gem installed.
8
+ # For a working demo, see the active_model_logger_demo project.
9
+
10
+ puts "=== ActiveModelLogger Stdout Logging Demo ==="
11
+ puts "This demo shows logs being sent to both database and standard output."
12
+ puts ""
13
+ puts "To see this in action, run the demo project:"
14
+ puts " cd active_model_logger_demo"
15
+ puts " bundle install"
16
+ puts " rails db:migrate"
17
+ puts " rails server"
18
+ puts " # Then visit http://localhost:3000 and click 'Create Demo Data'"
19
+ puts ""
20
+ puts "Or run the test script:"
21
+ puts " ruby test_logging.rb"
22
+ puts ""
23
+ puts "The stdout logging feature provides:"
24
+ puts "• Formatted log messages sent to standard output"
25
+ puts "• Configurable logging levels (debug, info, warn, error, fatal)"
26
+ puts "• Log chain information in the output"
27
+ puts "• Metadata display in the logs"
28
+ puts "• Custom logger support"
29
+ puts "• Ability to disable stdout logging per model"
30
+ puts ""
31
+ puts "Example output format:"
32
+ puts "[2025-09-05 20:58:15] INFO User#123 [chain:abc-123-def] - User logged in " \
33
+ "(status=success, category=authentication)"
34
+ puts "[2025-09-05 20:58:16] WARN Order#456 [chain:order-789] - Payment processing started (amount=99.99)"
35
+ puts "[2025-09-05 20:58:17] ERROR User#123 [chain:abc-123-def] - Payment failed (error=insufficient_funds)"
data/identifier.sqlite ADDED
File without changes