smart_message 0.0.8 → 0.0.10

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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.irbrc +24 -0
  4. data/CHANGELOG.md +119 -0
  5. data/Gemfile.lock +6 -1
  6. data/README.md +389 -17
  7. data/docs/README.md +3 -1
  8. data/docs/addressing.md +119 -13
  9. data/docs/architecture.md +184 -46
  10. data/docs/dead_letter_queue.md +673 -0
  11. data/docs/dispatcher.md +87 -0
  12. data/docs/examples.md +59 -1
  13. data/docs/getting-started.md +8 -1
  14. data/docs/logging.md +382 -326
  15. data/docs/message_deduplication.md +488 -0
  16. data/docs/message_filtering.md +451 -0
  17. data/examples/01_point_to_point_orders.rb +54 -53
  18. data/examples/02_publish_subscribe_events.rb +14 -10
  19. data/examples/03_many_to_many_chat.rb +16 -8
  20. data/examples/04_redis_smart_home_iot.rb +20 -10
  21. data/examples/05_proc_handlers.rb +12 -11
  22. data/examples/06_custom_logger_example.rb +95 -100
  23. data/examples/07_error_handling_scenarios.rb +4 -2
  24. data/examples/08_entity_addressing_basic.rb +18 -6
  25. data/examples/08_entity_addressing_with_filtering.rb +27 -9
  26. data/examples/09_dead_letter_queue_demo.rb +559 -0
  27. data/examples/09_regex_filtering_microservices.rb +407 -0
  28. data/examples/10_header_block_configuration.rb +263 -0
  29. data/examples/10_message_deduplication.rb +209 -0
  30. data/examples/11_global_configuration_example.rb +219 -0
  31. data/examples/README.md +102 -0
  32. data/examples/dead_letters.jsonl +12 -0
  33. data/examples/performance_metrics/benchmark_results_ractor_20250818_205603.json +135 -0
  34. data/examples/performance_metrics/benchmark_results_ractor_20250818_205831.json +135 -0
  35. data/examples/performance_metrics/benchmark_results_test_20250818_204942.json +130 -0
  36. data/examples/performance_metrics/benchmark_results_threadpool_20250818_204942.json +130 -0
  37. data/examples/performance_metrics/benchmark_results_threadpool_20250818_204959.json +130 -0
  38. data/examples/performance_metrics/benchmark_results_threadpool_20250818_205044.json +130 -0
  39. data/examples/performance_metrics/benchmark_results_threadpool_20250818_205109.json +130 -0
  40. data/examples/performance_metrics/benchmark_results_threadpool_20250818_205252.json +130 -0
  41. data/examples/performance_metrics/benchmark_results_unknown_20250819_172852.json +130 -0
  42. data/examples/performance_metrics/compare_benchmarks.rb +519 -0
  43. data/examples/performance_metrics/dead_letters.jsonl +3100 -0
  44. data/examples/performance_metrics/performance_benchmark.rb +344 -0
  45. data/examples/show_logger.rb +367 -0
  46. data/examples/show_me.rb +145 -0
  47. data/examples/temp.txt +94 -0
  48. data/examples/tmux_chat/bot_agent.rb +4 -2
  49. data/examples/tmux_chat/human_agent.rb +4 -2
  50. data/examples/tmux_chat/room_monitor.rb +4 -2
  51. data/examples/tmux_chat/shared_chat_system.rb +6 -3
  52. data/lib/smart_message/addressing.rb +259 -0
  53. data/lib/smart_message/base.rb +123 -599
  54. data/lib/smart_message/circuit_breaker.rb +2 -1
  55. data/lib/smart_message/configuration.rb +199 -0
  56. data/lib/smart_message/ddq/base.rb +71 -0
  57. data/lib/smart_message/ddq/memory.rb +109 -0
  58. data/lib/smart_message/ddq/redis.rb +168 -0
  59. data/lib/smart_message/ddq.rb +31 -0
  60. data/lib/smart_message/dead_letter_queue.rb +27 -10
  61. data/lib/smart_message/deduplication.rb +174 -0
  62. data/lib/smart_message/dispatcher.rb +259 -61
  63. data/lib/smart_message/header.rb +5 -0
  64. data/lib/smart_message/logger/base.rb +21 -1
  65. data/lib/smart_message/logger/default.rb +88 -138
  66. data/lib/smart_message/logger/lumberjack.rb +324 -0
  67. data/lib/smart_message/logger/null.rb +81 -0
  68. data/lib/smart_message/logger.rb +17 -9
  69. data/lib/smart_message/messaging.rb +100 -0
  70. data/lib/smart_message/plugins.rb +132 -0
  71. data/lib/smart_message/serializer/base.rb +25 -8
  72. data/lib/smart_message/serializer/json.rb +5 -4
  73. data/lib/smart_message/subscription.rb +196 -0
  74. data/lib/smart_message/transport/base.rb +72 -41
  75. data/lib/smart_message/transport/memory_transport.rb +7 -5
  76. data/lib/smart_message/transport/redis_transport.rb +15 -45
  77. data/lib/smart_message/transport/stdout_transport.rb +18 -8
  78. data/lib/smart_message/transport.rb +1 -34
  79. data/lib/smart_message/utilities.rb +142 -0
  80. data/lib/smart_message/version.rb +1 -1
  81. data/lib/smart_message/versioning.rb +85 -0
  82. data/lib/smart_message/wrapper.rb.bak +132 -0
  83. data/lib/smart_message.rb +74 -28
  84. data/smart_message.gemspec +3 -0
  85. metadata +83 -3
  86. data/lib/smart_message/serializer.rb +0 -10
  87. data/lib/smart_message/wrapper.rb +0 -43
@@ -0,0 +1,209 @@
1
+ #!/usr/bin/env ruby
2
+ # examples/10_message_deduplication.rb
3
+
4
+ require_relative '../lib/smart_message'
5
+
6
+ # Example demonstrating message deduplication with DDQ (Deduplication Queue)
7
+
8
+ # Message class with deduplication enabled
9
+ class OrderMessage < SmartMessage::Base
10
+ version 1
11
+ property :order_id, required: true
12
+ property :amount, required: true
13
+
14
+ from "order-service"
15
+
16
+ # Configure deduplication
17
+ ddq_size 100 # Keep track of last 100 message UUIDs
18
+ ddq_storage :memory # Use memory storage (could be :redis)
19
+ enable_deduplication! # Enable deduplication for this message class
20
+
21
+ def self.process(message)
22
+ puts "✅ Processing order: #{message.order_id} for $#{message.amount}"
23
+ @@processed_orders ||= []
24
+ @@processed_orders << message.order_id
25
+ end
26
+
27
+ def self.processed_orders
28
+ @@processed_orders || []
29
+ end
30
+
31
+ def self.clear_processed
32
+ @@processed_orders = []
33
+ end
34
+ end
35
+
36
+ # Regular message class without deduplication
37
+ class NotificationMessage < SmartMessage::Base
38
+ version 1
39
+ property :message, required: true
40
+ property :recipient, required: true
41
+
42
+ from "notification-service"
43
+
44
+ def self.process(message)
45
+ puts "📧 Sending: '#{message.message}' to #{message.recipient}"
46
+ @@sent_notifications ||= []
47
+ @@sent_notifications << { message: message.message, recipient: message.recipient }
48
+ end
49
+
50
+ def self.sent_notifications
51
+ @@sent_notifications || []
52
+ end
53
+
54
+ def self.clear_processed
55
+ @@sent_notifications = []
56
+ end
57
+ end
58
+
59
+ def demonstrate_deduplication
60
+ puts "=== SmartMessage Deduplication Demo ==="
61
+ puts
62
+
63
+ # Setup transport and subscriptions
64
+ transport = SmartMessage::Transport::MemoryTransport.new
65
+
66
+ OrderMessage.transport(transport)
67
+ OrderMessage.serializer(SmartMessage::Serializer::Json.new)
68
+ OrderMessage.subscribe('OrderMessage.process')
69
+
70
+ NotificationMessage.transport(transport)
71
+ NotificationMessage.serializer(SmartMessage::Serializer::Json.new)
72
+ NotificationMessage.subscribe('NotificationMessage.process')
73
+
74
+ # Clear any previous state
75
+ OrderMessage.clear_processed
76
+ NotificationMessage.clear_processed
77
+ OrderMessage.clear_ddq!
78
+
79
+ puts "📊 DDQ Configuration:"
80
+ config = OrderMessage.ddq_config
81
+ puts " - Enabled: #{config[:enabled]}"
82
+ puts " - Size: #{config[:size]}"
83
+ puts " - Storage: #{config[:storage]}"
84
+ puts
85
+
86
+ # Create a specific UUID for testing duplicates
87
+ uuid = SecureRandom.uuid
88
+ puts "🔍 Testing with UUID: #{uuid}"
89
+ puts
90
+
91
+ # Test 1: OrderMessage with deduplication
92
+ puts "--- Test 1: OrderMessage (with deduplication) ---"
93
+
94
+ # Create header with specific UUID
95
+ header = SmartMessage::Header.new(
96
+ uuid: uuid,
97
+ message_class: "OrderMessage",
98
+ published_at: Time.now,
99
+ publisher_pid: Process.pid,
100
+ version: 1,
101
+ from: "order-service"
102
+ )
103
+
104
+ # First message
105
+ order1 = OrderMessage.new(
106
+ _sm_header: header,
107
+ _sm_payload: { order_id: "ORD-001", amount: 99.99 }
108
+ )
109
+
110
+ puts "Publishing first order message..."
111
+ order1.publish
112
+ sleep 0.1 # Allow processing
113
+
114
+ # Second message with SAME UUID (should be deduplicated)
115
+ order2 = OrderMessage.new(
116
+ _sm_header: header,
117
+ _sm_payload: { order_id: "ORD-002", amount: 149.99 }
118
+ )
119
+
120
+ puts "Publishing duplicate order message (same UUID)..."
121
+ order2.publish
122
+ sleep 0.1 # Allow processing
123
+
124
+ puts "📈 Results:"
125
+ puts " - Processed orders: #{OrderMessage.processed_orders.length}"
126
+ puts " - Orders: #{OrderMessage.processed_orders}"
127
+ puts
128
+
129
+ # Test 2: NotificationMessage without deduplication
130
+ puts "--- Test 2: NotificationMessage (no deduplication) ---"
131
+
132
+ # Create header with same UUID
133
+ notification_header = SmartMessage::Header.new(
134
+ uuid: uuid, # Same UUID as orders!
135
+ message_class: "NotificationMessage",
136
+ published_at: Time.now,
137
+ publisher_pid: Process.pid,
138
+ version: 1,
139
+ from: "notification-service"
140
+ )
141
+
142
+ # First notification
143
+ notif1 = NotificationMessage.new(
144
+ _sm_header: notification_header,
145
+ _sm_payload: { message: "Order confirmed", recipient: "customer@example.com" }
146
+ )
147
+
148
+ puts "Publishing first notification..."
149
+ notif1.publish
150
+ sleep 0.1
151
+
152
+ # Second notification with same UUID (should NOT be deduplicated)
153
+ notif2 = NotificationMessage.new(
154
+ _sm_header: notification_header,
155
+ _sm_payload: { message: "Order shipped", recipient: "customer@example.com" }
156
+ )
157
+
158
+ puts "Publishing duplicate notification (same UUID)..."
159
+ notif2.publish
160
+ sleep 0.1
161
+
162
+ puts "📈 Results:"
163
+ puts " - Sent notifications: #{NotificationMessage.sent_notifications.length}"
164
+ puts " - Notifications: #{NotificationMessage.sent_notifications}"
165
+ puts
166
+
167
+ # Show DDQ statistics
168
+ puts "📊 DDQ Statistics:"
169
+ stats = OrderMessage.ddq_stats
170
+ if stats[:enabled]
171
+ puts " - Current count: #{stats[:current_count]}"
172
+ puts " - Utilization: #{stats[:utilization]}%"
173
+ puts " - Storage type: #{stats[:storage_type]}"
174
+ else
175
+ puts " - DDQ not enabled"
176
+ end
177
+ end
178
+
179
+ def demonstrate_memory_efficiency
180
+ puts
181
+ puts "=== Memory Usage Demonstration ==="
182
+ puts
183
+
184
+ # Show memory usage for different DDQ sizes
185
+ test_sizes = [10, 100, 1000]
186
+
187
+ test_sizes.each do |size|
188
+ memory_usage = size * 48 # Approximate bytes per UUID
189
+ puts "DDQ size #{size}: ~#{memory_usage} bytes (~#{(memory_usage / 1024.0).round(1)} KB)"
190
+ end
191
+
192
+ puts
193
+ puts "💡 Memory is very reasonable - even 1000 entries uses less than 50KB!"
194
+ end
195
+
196
+ if __FILE__ == $0
197
+ demonstrate_deduplication
198
+ demonstrate_memory_efficiency
199
+
200
+ puts
201
+ puts "✨ Key Benefits:"
202
+ puts " - O(1) duplicate detection"
203
+ puts " - Configurable queue size"
204
+ puts " - Memory or Redis storage"
205
+ puts " - Per-message-class configuration"
206
+ puts " - Automatic integration with dispatcher"
207
+ puts
208
+ puts "🚀 Ready for production multi-transport scenarios!"
209
+ end
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env ruby
2
+ # examples/11_global_configuration_example.rb
3
+ #
4
+ # Global Configuration System Example
5
+ #
6
+ # This example demonstrates how to use SmartMessage's global configuration
7
+ # system to set default logger, transport, and serializer for all message
8
+ # classes in your application.
9
+
10
+ require_relative '../lib/smart_message'
11
+
12
+ puts "=== SmartMessage Global Configuration Example ==="
13
+ puts
14
+
15
+ # Example 1: Default behavior (no configuration) - NO LOGGING
16
+ puts "1. Default Framework Behavior (NO LOGGING):"
17
+ puts " Default Logger: #{SmartMessage::Logger.default.class}"
18
+ puts " Default Transport: #{SmartMessage::Transport.default.class}"
19
+ puts " Default Serializer: #{SmartMessage::Serializer.default.class}"
20
+ puts " Note: No logging unless explicitly configured!"
21
+ puts
22
+
23
+ # Example 2: Configure logging with string path
24
+ puts "2. Configuring Logging with String Path:"
25
+ SmartMessage.configure do |config|
26
+ config.logger = "log/my_application.log" # String = Lumberjack logger with this path
27
+ config.transport = SmartMessage::Transport::StdoutTransport.new(loopback: true)
28
+ config.serializer = SmartMessage::Serializer::Json.new
29
+ end
30
+
31
+ puts " Configured Logger: #{SmartMessage::Logger.default.class}"
32
+ puts " Log File: #{SmartMessage::Logger.default.log_file rescue 'N/A'}"
33
+ puts " Configured Transport: #{SmartMessage::Transport.default.class}"
34
+ puts " Configured Serializer: #{SmartMessage::Serializer.default.class}"
35
+ puts
36
+
37
+ # Reset for next example
38
+ SmartMessage.reset_configuration!
39
+
40
+ # Example 3: Configure with :default symbol (framework defaults)
41
+ puts "3. Configuring with :default Symbol:"
42
+ SmartMessage.configure do |config|
43
+ config.logger = :default # Use Lumberjack with default settings
44
+ config.transport = SmartMessage::Transport::StdoutTransport.new(loopback: true)
45
+ config.serializer = SmartMessage::Serializer::Json.new
46
+ end
47
+
48
+ puts " Configured Logger: #{SmartMessage::Logger.default.class}"
49
+ puts " Log File: #{SmartMessage::Logger.default.log_file rescue 'N/A'}"
50
+ puts " Configured Transport: #{SmartMessage::Transport.default.class}"
51
+ puts " Configured Serializer: #{SmartMessage::Serializer.default.class}"
52
+ puts
53
+
54
+ # Example 4: Message classes automatically use global configuration
55
+ puts "4. Message Classes Using Global Configuration:"
56
+
57
+ class NotificationMessage < SmartMessage::Base
58
+ property :recipient
59
+ property :message
60
+ property :priority, default: 'normal'
61
+
62
+ # No config block needed - automatically uses global configuration!
63
+
64
+ def self.process(wrapper)
65
+ message_header, message_payload = wrapper.split
66
+ data = JSON.parse(message_payload)
67
+
68
+ priority_emoji = case data['priority']
69
+ when 'high' then '🔴'
70
+ when 'medium' then '🟡'
71
+ else '🟢'
72
+ end
73
+
74
+ puts "#{priority_emoji} Notification: #{data['message']} (to: #{data['recipient']})"
75
+ end
76
+ end
77
+
78
+ class OrderStatusMessage < SmartMessage::Base
79
+ property :order_id
80
+ property :status
81
+ property :customer_id
82
+
83
+ # Also uses global configuration automatically
84
+
85
+ def self.process(wrapper)
86
+ message_header, message_payload = wrapper.split
87
+ data = JSON.parse(message_payload)
88
+
89
+ status_emoji = case data['status']
90
+ when 'confirmed' then '✅'
91
+ when 'shipped' then '📦'
92
+ when 'delivered' then '🎉'
93
+ when 'cancelled' then '❌'
94
+ else '⏳'
95
+ end
96
+
97
+ puts "#{status_emoji} Order #{data['order_id']}: #{data['status']}"
98
+ end
99
+ end
100
+
101
+ # Subscribe to messages to see them in action
102
+ NotificationMessage.subscribe
103
+ OrderStatusMessage.subscribe
104
+
105
+ puts " Message classes configured automatically!"
106
+ puts
107
+
108
+ # Example 4: Creating and publishing messages
109
+ puts "4. Publishing Messages (using global configuration):"
110
+
111
+ notification = NotificationMessage.new(
112
+ recipient: "admin@example.com",
113
+ message: "System maintenance scheduled for tonight",
114
+ priority: "high",
115
+ from: "SystemService"
116
+ )
117
+
118
+ order_status = OrderStatusMessage.new(
119
+ order_id: "ORD-12345",
120
+ status: "shipped",
121
+ customer_id: "CUST-001",
122
+ from: "OrderService"
123
+ )
124
+
125
+ puts "\n--- Publishing Messages ---"
126
+ notification.publish
127
+ order_status.publish
128
+
129
+ # Give time for async processing
130
+ sleep(0.5)
131
+
132
+ puts
133
+
134
+ # Example 5: Individual classes can still override global configuration
135
+ puts "5. Overriding Global Configuration for Specific Classes:"
136
+
137
+ class SpecialMessage < SmartMessage::Base
138
+ property :content
139
+
140
+ # Override just the logger, keep global transport and serializer
141
+ config do
142
+ logger SmartMessage::Logger::Default.new(log_file: STDERR, level: Logger::WARN)
143
+ # transport and serializer still use global configuration
144
+ end
145
+
146
+ def self.process(wrapper)
147
+ message_header, message_payload = wrapper.split
148
+ data = JSON.parse(message_payload)
149
+ puts "⭐ Special processing: #{data['content']}"
150
+ end
151
+ end
152
+
153
+ SpecialMessage.subscribe
154
+
155
+ special = SpecialMessage.new(
156
+ content: "This uses custom logger but global transport/serializer",
157
+ from: "SpecialService"
158
+ )
159
+
160
+ puts " SpecialMessage logger: #{SpecialMessage.logger.class}"
161
+ puts " (Should be SmartMessage::Logger::Default with STDERR output)"
162
+
163
+ special.publish
164
+ sleep(0.5)
165
+
166
+ puts
167
+
168
+ # Example 6: Resetting configuration
169
+ puts "6. Resetting to Framework Defaults:"
170
+ SmartMessage.reset_configuration!
171
+
172
+ puts " After reset:"
173
+ puts " Logger: #{SmartMessage::Logger.default.class}"
174
+ puts " Transport: #{SmartMessage::Transport.default.class}"
175
+ puts " Serializer: #{SmartMessage::Serializer.default.class}"
176
+
177
+ puts "\n✨ Global Configuration Example Complete!"
178
+ puts
179
+ puts "Key Benefits:"
180
+ puts "• Set defaults once for entire application"
181
+ puts "• All message classes inherit global configuration automatically"
182
+ puts "• Individual classes can still override when needed"
183
+ puts "• Clean, centralized configuration management"
184
+ puts "• No need for repetitive config blocks in every message class"
185
+ puts "• Easy integration with Rails.logger or any other logger"
186
+ puts
187
+ puts "Configuration Options Summary:"
188
+ puts " # No configuration = NO LOGGING (new default behavior)"
189
+ puts " # No SmartMessage.configure block needed"
190
+ puts
191
+ puts " # String path = Lumberjack logger with that file"
192
+ puts " SmartMessage.configure do |config|"
193
+ puts " config.logger = 'log/my_app.log' # String path"
194
+ puts " end"
195
+ puts
196
+ puts " # STDOUT/STDERR = Lumberjack logger to console"
197
+ puts " SmartMessage.configure do |config|"
198
+ puts " config.logger = STDOUT # Log to STDOUT"
199
+ puts " config.logger = STDERR # Log to STDERR"
200
+ puts " end"
201
+ puts
202
+ puts " # :default symbol = Lumberjack with framework defaults"
203
+ puts " SmartMessage.configure do |config|"
204
+ puts " config.logger = :default # Framework default (file)"
205
+ puts " end"
206
+ puts
207
+ puts " # Custom logger object = Use that logger"
208
+ puts " SmartMessage.configure do |config|"
209
+ puts " config.logger = Rails.logger # Rails logger"
210
+ puts " config.logger = MyApp::Logger.new # Custom logger"
211
+ puts " end"
212
+ puts
213
+ puts " # Explicit nil = No logging (same as no configuration)"
214
+ puts " SmartMessage.configure do |config|"
215
+ puts " config.logger = nil # Explicit no logging"
216
+ puts " end"
217
+
218
+ # Clean up test file
219
+ File.delete('test_config.rb') if File.exist?('test_config.rb')
data/examples/README.md CHANGED
@@ -16,6 +16,10 @@ ruby 05_proc_handlers.rb
16
16
  ruby 06_custom_logger_example.rb
17
17
  ruby 07_error_handling_scenarios.rb
18
18
  ruby 08_entity_addressing.rb
19
+ ruby 09_regex_filtering_microservices.rb
20
+ ruby 10_header_block_configuration.rb
21
+ ruby 11_global_configuration_example.rb
22
+ ruby show_logger.rb
19
23
  ```
20
24
 
21
25
  ## Examples Overview
@@ -266,6 +270,73 @@ payment.publish
266
270
  - **Runtime Configuration**: Dynamic addressing based on conditions
267
271
  - **Integration Patterns**: Gateway support for external systems
268
272
 
273
+ ---
274
+
275
+ ### 10. Header Block Configuration (Addressing DSL)
276
+ **File:** `10_header_block_configuration.rb`
277
+
278
+ **Scenario:** Comprehensive demonstration of SmartMessage's flexible header configuration options, showing three different methods for setting addressing fields.
279
+
280
+ **Key Features:**
281
+ - Direct class methods for addressing configuration
282
+ - Header block DSL for clean, grouped configuration
283
+ - Mixed approach combining both methods
284
+ - Instance-level addressing overrides with method chaining
285
+ - Setter syntax for addressing fields
286
+ - Automatic header synchronization with instance values
287
+ - Configuration checking and validation methods
288
+
289
+ **Configuration Methods Demonstrated:**
290
+ ```ruby
291
+ # Method 1: Direct class methods
292
+ class DirectMethodMessage < SmartMessage::Base
293
+ from 'service-a'
294
+ to 'service-b'
295
+ reply_to 'service-a-callback'
296
+ end
297
+
298
+ # Method 2: Header block DSL
299
+ class HeaderBlockMessage < SmartMessage::Base
300
+ header do
301
+ from 'service-x'
302
+ to 'service-y'
303
+ reply_to 'service-x-callback'
304
+ end
305
+ end
306
+
307
+ # Method 3: Mixed approach
308
+ class MixedConfigMessage < SmartMessage::Base
309
+ header do
310
+ from 'mixed-service'
311
+ to 'target-service'
312
+ end
313
+ reply_to 'mixed-callback' # Outside block
314
+ end
315
+ ```
316
+
317
+ **Instance-Level Features:**
318
+ - **Method Chaining**: `msg.from('sender').to('recipient').reply_to('callback')`
319
+ - **Setter Syntax**: `msg.from = 'sender'`, `msg.to = 'recipient'`
320
+ - **Shortcut Accessors**: `msg.from`, `msg.to`, `msg.reply_to`
321
+ - **Header Access**: `msg._sm_header.from`, `msg._sm_header.to`
322
+ - **Configuration Checks**: `msg.from_configured?`, `msg.to_missing?`
323
+ - **Reset Methods**: `msg.reset_from`, `msg.reset_to`, `msg.reset_reply_to`
324
+
325
+ **What You'll Learn:**
326
+ - How to choose the best configuration method for your use case
327
+ - Benefits of header block DSL for grouped configuration
328
+ - Dynamic addressing overrides at runtime
329
+ - Three ways to access addressing values
330
+ - How headers automatically sync with instance changes
331
+ - Configuration validation and checking methods
332
+
333
+ **Benefits:**
334
+ - **Clean Syntax**: Header block groups related configuration
335
+ - **Flexibility**: Multiple configuration approaches to suit different styles
336
+ - **Runtime Control**: Instance-level overrides for dynamic routing
337
+ - **Consistency**: Headers stay synchronized with instance values
338
+ - **Validation**: Built-in methods to check configuration state
339
+
269
340
  ## Message Patterns Demonstrated
270
341
 
271
342
  ### Request-Response Pattern
@@ -471,6 +542,37 @@ class MyCustomTransport < SmartMessage::Transport::Base
471
542
  end
472
543
  ```
473
544
 
545
+ ---
546
+
547
+ ### Show Logger Demonstration
548
+ **File:** `show_logger.rb`
549
+
550
+ **Scenario:** Comprehensive demonstration of SmartMessage's enhanced logging capabilities, showing how applications can use the SmartMessage logger directly and configure various Lumberjack options.
551
+
552
+ **Key Features:**
553
+ - Colorized console output for different log levels
554
+ - JSON and text log formatting
555
+ - File-based logging with rolling (size and date-based)
556
+ - Application logger patterns and direct logger usage
557
+ - Multiple logger configurations
558
+ - Integration with SmartMessage classes
559
+
560
+ **What You'll Learn:**
561
+ - How to configure SmartMessage's global logger settings
562
+ - Different log output formats (text vs JSON)
563
+ - Colorized logging for console output
564
+ - File rolling strategies for production use
565
+ - How to use the SmartMessage logger directly in applications
566
+ - Best practices for structured logging
567
+ - Integration patterns between application code and SmartMessage classes
568
+
569
+ **Demonstrates:**
570
+ - `SmartMessage.configure` block usage for logger configuration
571
+ - `log_level`, `log_format`, `log_colorize`, and `log_options` settings
572
+ - Direct access to `SmartMessage.configuration.default_logger`
573
+ - Creating multiple logger instances with different configurations
574
+ - Practical application patterns using the logger
575
+
474
576
  ## Production Considerations
475
577
 
476
578
  When adapting these examples for production:
@@ -0,0 +1,12 @@
1
+ {"timestamp":"2025-08-19T16:03:52-05:00","header":{"uuid":"ecb4c4f9-e9a7-47fd-918a-8dc5087218d6","message_class":"OrderMessage","published_at":"2025-08-19T16:03:52.374-05:00","publisher_pid":16266,"version":1,"from":"OrderService","serializer":"SmartMessage::Serializer::JSON"},"payload":"{\"order_id\":\"ORD-1001\",\"customer_id\":\"CUST-001\",\"amount\":99.99,\"currency\":\"USD\",\"payment_method\":\"credit_card\",\"items\":[\"Widget A\",\"Widget B\"]}","payload_format":"json","error":"wrong number of arguments (given 1, expected 2)","retry_count":0,"transport":"circuit_breaker","stack_trace":null}
2
+ {"timestamp":"2025-08-19T16:03:52-05:00","header":{"uuid":"40dce8a2-1723-48f5-ad01-fe49814991a2","message_class":"OrderMessage","published_at":"2025-08-19T16:03:52.889-05:00","publisher_pid":16266,"version":1,"from":"OrderService","serializer":"SmartMessage::Serializer::JSON"},"payload":"{\"order_id\":\"ORD-1002\",\"customer_id\":\"CUST-002\",\"amount\":1299.99,\"currency\":\"USD\",\"payment_method\":\"debit_card\",\"items\":[\"Premium Widget\",\"Extended Warranty\"]}","payload_format":"json","error":"wrong number of arguments (given 1, expected 2)","retry_count":0,"transport":"circuit_breaker","stack_trace":null}
3
+ {"timestamp":"2025-08-19T16:03:53-05:00","header":{"uuid":"0e1a228b-4069-4c05-b1ed-18193174d773","message_class":"OrderMessage","published_at":"2025-08-19T16:03:53.397-05:00","publisher_pid":16266,"version":1,"from":"OrderService","serializer":"SmartMessage::Serializer::JSON"},"payload":"{\"order_id\":\"ORD-1003\",\"customer_id\":\"CUST-003\",\"amount\":45.5,\"currency\":\"USD\",\"payment_method\":\"paypal\",\"items\":[\"Small Widget\"]}","payload_format":"json","error":"wrong number of arguments (given 1, expected 2)","retry_count":0,"transport":"circuit_breaker","stack_trace":null}
4
+ {"timestamp":"2025-08-19T16:04:01-05:00","header":{"uuid":"60ca2ca3-8185-4946-ae20-85269073ce3e","message_class":"UserEventMessage","published_at":"2025-08-19T16:04:01.582-05:00","publisher_pid":16396,"version":1,"from":"UserManager","serializer":"SmartMessage::Serializer::JSON"},"payload":"{\"event_id\":\"EVT-1001\",\"event_type\":\"user_registered\",\"user_id\":\"USER-101\",\"user_email\":\"alice@example.com\",\"user_name\":\"Alice Johnson\",\"timestamp\":\"2025-08-19T16:04:01-05:00\",\"metadata\":{\"source\":\"web_registration\"}}","payload_format":"json","error":"wrong number of arguments (given 1, expected 2)","retry_count":0,"transport":"circuit_breaker","stack_trace":null}
5
+ {"timestamp":"2025-08-19T16:23:07-05:00","header":{"uuid":"ebd1f61b-e5d9-48f4-a787-e1f9f4e09578","message_class":"SystemNotificationMessage","published_at":"2025-08-19T16:23:07.222-05:00","publisher_pid":24163,"version":1,"from":"user-001","serializer":"SmartMessage::Serializer::JSON"},"payload":"{\"notification_id\":\"NOTIF-1755638587-564\",\"room_id\":\"general\",\"notification_type\":\"user_joined\",\"content\":\"Alice joined the room\",\"timestamp\":\"2025-08-19T16:23:07-05:00\",\"metadata\":{\"triggered_by\":\"user-001\"}}","payload_format":"json","error":"undefined method 'handle_system_notification_user-001' for class 'HumanChatAgent'","retry_count":0,"transport":"circuit_breaker","stack_trace":null}
6
+ {"timestamp":"2025-08-19T16:25:50-05:00","header":{"uuid":"e722ef85-7168-42e2-94c2-cc55c1ca6784","message_class":"PaymentMessage","published_at":"2025-08-19T16:25:50.310-05:00","publisher_pid":25696,"version":1,"from":"payment-service","to":"dev-payment-processor","serializer":"SmartMessage::Serializer::JSON"},"payload":"{\"service_id\":\"payment-core\",\"message_type\":\"transaction_complete\",\"data\":{\"merchant\":\"Online Store\"},\"environment\":\"dev\",\"timestamp\":\"2025-08-19T16:25:50-05:00\",\"transaction_id\":\"TXN-001\",\"amount\":99.99,\"currency\":\"USD\"}","payload_format":"json","error":"undefined method 'process_dev' for class 'PaymentMessage'","retry_count":0,"transport":"circuit_breaker","stack_trace":null}
7
+ {"timestamp":"2025-08-19T16:25:50-05:00","header":{"uuid":"d36c3c66-bccc-49af-b919-b62bc6c9e1b2","message_class":"PaymentMessage","published_at":"2025-08-19T16:25:50.831-05:00","publisher_pid":25696,"version":1,"from":"payment-service","to":"prod-payment-processor","serializer":"SmartMessage::Serializer::JSON"},"payload":"{\"service_id\":\"payment-core\",\"message_type\":\"transaction_complete\",\"data\":{\"merchant\":\"Enterprise Store\"},\"environment\":\"prod\",\"timestamp\":\"2025-08-19T16:25:50-05:00\",\"transaction_id\":\"TXN-002\",\"amount\":299.99,\"currency\":\"USD\"}","payload_format":"json","error":"undefined method 'process_prod' for class 'PaymentMessage'","retry_count":0,"transport":"circuit_breaker","stack_trace":null}
8
+ {"timestamp":"2025-08-19T16:25:52-05:00","header":{"uuid":"d3371fb3-ed6e-403c-8f3b-3b130958a013","message_class":"AlertMessage","published_at":"2025-08-19T16:25:52.351-05:00","publisher_pid":25696,"version":1,"from":"admin","to":"security-dashboard","serializer":"SmartMessage::Serializer::JSON"},"payload":"{\"service_id\":\"security-scanner\",\"message_type\":\"security_alert\",\"data\":{\"attempts\":50,\"ip\":\"192.168.1.100\"},\"environment\":\"prod\",\"timestamp\":\"2025-08-19T16:25:52-05:00\",\"alert_level\":\"critical\",\"component\":\"authentication\",\"description\":\"Multiple failed login attempts detected\"}","payload_format":"json","error":"undefined method 'process_admin' for class 'AlertMessage'","retry_count":0,"transport":"circuit_breaker","stack_trace":null}
9
+ {"timestamp":"2025-08-19T16:25:52-05:00","header":{"uuid":"46a5b557-540c-4d50-a1f9-030907ba6275","message_class":"AlertMessage","published_at":"2025-08-19T16:25:52.860-05:00","publisher_pid":25696,"version":1,"from":"system-metrics","to":"ops-dashboard","serializer":"SmartMessage::Serializer::JSON"},"payload":"{\"service_id\":\"system-monitor\",\"message_type\":\"resource_alert\",\"data\":{\"usage_percent\":85,\"threshold\":80},\"environment\":\"staging\",\"timestamp\":\"2025-08-19T16:25:52-05:00\",\"alert_level\":\"warning\",\"component\":\"memory\",\"description\":\"Memory usage above threshold\"}","payload_format":"json","error":"Circuit 'message_processor' is open","retry_count":0,"transport":"circuit_breaker","stack_trace":null}
10
+ {"timestamp":"2025-08-19T16:25:52-05:00","header":{"uuid":"46a5b557-540c-4d50-a1f9-030907ba6275","message_class":"AlertMessage","published_at":"2025-08-19T16:25:52.860-05:00","publisher_pid":25696,"version":1,"from":"system-metrics","to":"ops-dashboard","serializer":"SmartMessage::Serializer::JSON"},"payload":"{\"service_id\":\"system-monitor\",\"message_type\":\"resource_alert\",\"data\":{\"usage_percent\":85,\"threshold\":80},\"environment\":\"staging\",\"timestamp\":\"2025-08-19T16:25:52-05:00\",\"alert_level\":\"warning\",\"component\":\"memory\",\"description\":\"Memory usage above threshold\"}","payload_format":"json","error":"Circuit 'message_processor' is open","retry_count":0,"transport":"circuit_breaker","stack_trace":null}
11
+ {"timestamp":"2025-08-19T16:25:53-05:00","header":{"uuid":"8ebceac3-8c5d-4253-b2a2-ce754084c3c2","message_class":"OrderMessage","published_at":"2025-08-19T16:25:53.365-05:00","publisher_pid":25696,"version":1,"from":"admin-dashboard","to":"prod-fulfillment","serializer":"SmartMessage::Serializer::JSON"},"payload":"{\"service_id\":\"admin-portal\",\"message_type\":\"admin_order_override\",\"data\":{\"priority\":\"high\",\"reason\":\"VIP customer\"},\"environment\":\"prod\",\"timestamp\":\"2025-08-19T16:25:53-05:00\",\"order_id\":\"ORD-999\",\"customer_id\":\"ADMIN\",\"status\":\"expedited\"}","payload_format":"json","error":"Circuit 'message_processor' is open","retry_count":0,"transport":"circuit_breaker","stack_trace":null}
12
+ {"timestamp":"2025-08-19T16:25:53-05:00","header":{"uuid":"8dfa4fed-f2df-4f66-81c2-963a97489a31","message_class":"PaymentMessage","published_at":"2025-08-19T16:25:53.873-05:00","publisher_pid":25696,"version":1,"from":"admin","serializer":"SmartMessage::Serializer::JSON"},"payload":"{\"service_id\":\"payment-system\",\"message_type\":\"system_maintenance\",\"data\":{\"message\":\"Scheduled maintenance in 30 minutes\",\"duration\":\"2 hours\",\"affected_services\":[\"payment\",\"billing\"]},\"environment\":\"prod\",\"timestamp\":\"2025-08-19T16:25:53-05:00\",\"transaction_id\":\"MAINT-001\",\"amount\":0,\"currency\":\"USD\"}","payload_format":"json","error":"Circuit 'message_processor' is open","retry_count":0,"transport":"circuit_breaker","stack_trace":null}