smart_message 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.irbrc +24 -0
- data/CHANGELOG.md +96 -0
- data/Gemfile.lock +6 -1
- data/README.md +289 -15
- data/docs/README.md +3 -1
- data/docs/addressing.md +119 -13
- data/docs/architecture.md +68 -0
- data/docs/dead_letter_queue.md +673 -0
- data/docs/dispatcher.md +87 -0
- data/docs/examples.md +59 -1
- data/docs/getting-started.md +8 -1
- data/docs/logging.md +382 -326
- data/docs/message_filtering.md +451 -0
- data/examples/01_point_to_point_orders.rb +54 -53
- data/examples/02_publish_subscribe_events.rb +14 -10
- data/examples/03_many_to_many_chat.rb +16 -8
- data/examples/04_redis_smart_home_iot.rb +20 -10
- data/examples/05_proc_handlers.rb +12 -11
- data/examples/06_custom_logger_example.rb +95 -100
- data/examples/07_error_handling_scenarios.rb +4 -2
- data/examples/08_entity_addressing_basic.rb +18 -6
- data/examples/08_entity_addressing_with_filtering.rb +27 -9
- data/examples/09_dead_letter_queue_demo.rb +559 -0
- data/examples/09_regex_filtering_microservices.rb +407 -0
- data/examples/10_header_block_configuration.rb +263 -0
- data/examples/11_global_configuration_example.rb +219 -0
- data/examples/README.md +102 -0
- data/examples/dead_letters.jsonl +12 -0
- data/examples/performance_metrics/benchmark_results_ractor_20250818_205603.json +135 -0
- data/examples/performance_metrics/benchmark_results_ractor_20250818_205831.json +135 -0
- data/examples/performance_metrics/benchmark_results_test_20250818_204942.json +130 -0
- data/examples/performance_metrics/benchmark_results_threadpool_20250818_204942.json +130 -0
- data/examples/performance_metrics/benchmark_results_threadpool_20250818_204959.json +130 -0
- data/examples/performance_metrics/benchmark_results_threadpool_20250818_205044.json +130 -0
- data/examples/performance_metrics/benchmark_results_threadpool_20250818_205109.json +130 -0
- data/examples/performance_metrics/benchmark_results_threadpool_20250818_205252.json +130 -0
- data/examples/performance_metrics/benchmark_results_unknown_20250819_172852.json +130 -0
- data/examples/performance_metrics/compare_benchmarks.rb +519 -0
- data/examples/performance_metrics/dead_letters.jsonl +3100 -0
- data/examples/performance_metrics/performance_benchmark.rb +344 -0
- data/examples/show_logger.rb +367 -0
- data/examples/show_me.rb +145 -0
- data/examples/temp.txt +94 -0
- data/examples/tmux_chat/bot_agent.rb +4 -2
- data/examples/tmux_chat/human_agent.rb +4 -2
- data/examples/tmux_chat/room_monitor.rb +4 -2
- data/examples/tmux_chat/shared_chat_system.rb +6 -3
- data/lib/smart_message/addressing.rb +259 -0
- data/lib/smart_message/base.rb +121 -599
- data/lib/smart_message/circuit_breaker.rb +2 -1
- data/lib/smart_message/configuration.rb +199 -0
- data/lib/smart_message/dead_letter_queue.rb +27 -10
- data/lib/smart_message/dispatcher.rb +90 -49
- data/lib/smart_message/header.rb +5 -0
- data/lib/smart_message/logger/base.rb +21 -1
- data/lib/smart_message/logger/default.rb +88 -138
- data/lib/smart_message/logger/lumberjack.rb +324 -0
- data/lib/smart_message/logger/null.rb +81 -0
- data/lib/smart_message/logger.rb +17 -9
- data/lib/smart_message/messaging.rb +100 -0
- data/lib/smart_message/plugins.rb +132 -0
- data/lib/smart_message/serializer/base.rb +25 -8
- data/lib/smart_message/serializer/json.rb +5 -4
- data/lib/smart_message/subscription.rb +193 -0
- data/lib/smart_message/transport/base.rb +72 -41
- data/lib/smart_message/transport/memory_transport.rb +7 -5
- data/lib/smart_message/transport/redis_transport.rb +15 -45
- data/lib/smart_message/transport/stdout_transport.rb +18 -8
- data/lib/smart_message/transport.rb +1 -34
- data/lib/smart_message/utilities.rb +142 -0
- data/lib/smart_message/version.rb +1 -1
- data/lib/smart_message/versioning.rb +85 -0
- data/lib/smart_message/wrapper.rb.bak +132 -0
- data/lib/smart_message.rb +74 -28
- data/smart_message.gemspec +3 -0
- metadata +76 -3
- data/lib/smart_message/serializer.rb +0 -10
- data/lib/smart_message/wrapper.rb +0 -43
data/docs/logging.md
CHANGED
@@ -1,452 +1,508 @@
|
|
1
1
|
# Logging in SmartMessage
|
2
2
|
|
3
|
-
SmartMessage provides
|
3
|
+
SmartMessage provides comprehensive logging capabilities with support for multiple output formats, colorization, structured logging, and file rolling. Built on the Lumberjack logging framework, it offers production-ready features with flexible configuration options.
|
4
4
|
|
5
5
|
## Table of Contents
|
6
6
|
|
7
|
-
- [
|
7
|
+
- [Quick Start](#quick-start)
|
8
8
|
- [Configuration Options](#configuration-options)
|
9
|
-
- [Output
|
10
|
-
- [
|
11
|
-
- [
|
12
|
-
- [
|
13
|
-
- [
|
9
|
+
- [Output Formats](#output-formats)
|
10
|
+
- [Colorized Console Output](#colorized-console-output)
|
11
|
+
- [File Rolling](#file-rolling)
|
12
|
+
- [Structured Logging](#structured-logging)
|
13
|
+
- [Application Integration](#application-integration)
|
14
|
+
- [SmartMessage Integration](#smartmessage-integration)
|
14
15
|
- [Examples](#examples)
|
16
|
+
- [Best Practices](#best-practices)
|
15
17
|
|
16
|
-
##
|
18
|
+
## Quick Start
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
- **Rails Applications**: Uses `Rails.logger` with tagged logging
|
21
|
-
- **Standalone Ruby**: Uses Ruby's standard `Logger` class with file output
|
22
|
-
|
23
|
-
### Quick Start
|
20
|
+
Configure SmartMessage logging through the global configuration block:
|
24
21
|
|
25
22
|
```ruby
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
config
|
30
|
-
|
31
|
-
serializer SmartMessage::Serializer::JSON.new
|
32
|
-
logger SmartMessage::Logger::Default.new # Zero configuration!
|
33
|
-
end
|
23
|
+
SmartMessage.configure do |config|
|
24
|
+
config.logger = STDOUT # Output destination
|
25
|
+
config.log_level = :info # Log level
|
26
|
+
config.log_format = :text # Format
|
27
|
+
config.log_colorize = true # Enable colors
|
34
28
|
end
|
29
|
+
|
30
|
+
# Access the logger in your application
|
31
|
+
logger = SmartMessage.configuration.default_logger
|
32
|
+
logger.info("Application started", component: "main")
|
35
33
|
```
|
36
34
|
|
37
35
|
## Configuration Options
|
38
36
|
|
39
|
-
|
37
|
+
### Global Configuration
|
40
38
|
|
41
|
-
|
39
|
+
All logging configuration is done through the `SmartMessage.configure` block:
|
42
40
|
|
43
41
|
```ruby
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
42
|
+
SmartMessage.configure do |config|
|
43
|
+
# Required: Output destination
|
44
|
+
config.logger = STDOUT # or file path, STDERR
|
45
|
+
|
46
|
+
# Optional: Logging behavior
|
47
|
+
config.log_level = :info # :debug, :info, :warn, :error, :fatal
|
48
|
+
config.log_format = :text # :text, :json
|
49
|
+
config.log_colorize = true # Enable colorized console output
|
50
|
+
config.log_include_source = false # Include file/line information
|
51
|
+
config.log_structured_data = false # Enable structured metadata
|
52
|
+
|
53
|
+
# Optional: File rolling options
|
54
|
+
config.log_options = {
|
55
|
+
roll_by_size: true,
|
56
|
+
max_file_size: 10 * 1024 * 1024, # 10 MB
|
57
|
+
keep_files: 5, # Keep 5 old files
|
58
|
+
roll_by_date: false, # Alternative: date-based rolling
|
59
|
+
date_pattern: '%Y-%m-%d' # Daily pattern
|
60
|
+
}
|
61
|
+
end
|
62
|
+
```
|
51
63
|
|
52
|
-
|
53
|
-
logger SmartMessage::Logger::Default.new(
|
54
|
-
level: Logger::DEBUG
|
55
|
-
)
|
64
|
+
### Configuration Details
|
56
65
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
)
|
62
|
-
|
66
|
+
| Option | Type | Default | Description |
|
67
|
+
|--------|------|---------|-------------|
|
68
|
+
| `logger` | String/IO | Required | Output destination (file path, STDOUT, STDERR) |
|
69
|
+
| `log_level` | Symbol | `:info` | Log level (`:debug`, `:info`, `:warn`, `:error`, `:fatal`) |
|
70
|
+
| `log_format` | Symbol | `:text` | Output format (`:text`, `:json`) |
|
71
|
+
| `log_colorize` | Boolean | `false` | Enable colorized console output |
|
72
|
+
| `log_include_source` | Boolean | `false` | Include source file and line information |
|
73
|
+
| `log_structured_data` | Boolean | `false` | Enable structured data logging |
|
74
|
+
| `log_options` | Hash | `{}` | Additional Lumberjack options |
|
63
75
|
|
64
|
-
## Output
|
76
|
+
## Output Formats
|
65
77
|
|
66
|
-
|
78
|
+
### Text Format (Default)
|
67
79
|
|
68
|
-
|
80
|
+
Human-readable text output with optional colorization:
|
69
81
|
|
70
82
|
```ruby
|
71
|
-
|
72
|
-
logger
|
73
|
-
|
83
|
+
SmartMessage.configure do |config|
|
84
|
+
config.logger = STDOUT
|
85
|
+
config.log_format = :text
|
86
|
+
config.log_colorize = true
|
87
|
+
end
|
74
88
|
|
75
|
-
|
76
|
-
logger
|
77
|
-
|
78
|
-
)
|
89
|
+
logger = SmartMessage.configuration.default_logger
|
90
|
+
logger.info("User login successful", user_id: 12345)
|
91
|
+
# Output: 2025-01-15 10:30:45 [INFO] User login successful user_id=12345
|
79
92
|
```
|
80
93
|
|
81
|
-
|
82
|
-
- Automatic log rotation (10 files, 10MB each)
|
83
|
-
- Directory creation if needed
|
84
|
-
- Timestamped entries with clean formatting
|
85
|
-
|
86
|
-
### STDOUT Logging
|
94
|
+
### JSON Format
|
87
95
|
|
88
|
-
|
96
|
+
Machine-readable structured JSON output:
|
89
97
|
|
90
98
|
```ruby
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
### STDERR Logging
|
98
|
-
|
99
|
-
For error-focused logging:
|
99
|
+
SmartMessage.configure do |config|
|
100
|
+
config.logger = "log/application.log"
|
101
|
+
config.log_format = :json
|
102
|
+
config.log_structured_data = true
|
103
|
+
config.log_include_source = true
|
104
|
+
end
|
100
105
|
|
101
|
-
|
102
|
-
logger
|
103
|
-
|
104
|
-
level: Logger::WARN
|
105
|
-
)
|
106
|
+
logger = SmartMessage.configuration.default_logger
|
107
|
+
logger.info("User action", user_id: 12345, action: "login")
|
108
|
+
# Output: {"timestamp":"2025-01-15T10:30:45.123Z","level":"INFO","message":"User action","user_id":12345,"action":"login","source":"app.rb:42:in `authenticate`"}
|
106
109
|
```
|
107
110
|
|
108
|
-
|
111
|
+
## Colorized Console Output
|
112
|
+
|
113
|
+
SmartMessage provides colorized console output for improved readability during development:
|
109
114
|
|
110
115
|
```ruby
|
111
|
-
|
116
|
+
SmartMessage.configure do |config|
|
117
|
+
config.logger = STDOUT
|
118
|
+
config.log_format = :text
|
119
|
+
config.log_colorize = true
|
120
|
+
end
|
112
121
|
|
113
|
-
logger SmartMessage
|
114
|
-
|
115
|
-
|
116
|
-
)
|
122
|
+
logger = SmartMessage.configuration.default_logger
|
123
|
+
logger.debug("Debug message") # Green background, black text, bold
|
124
|
+
logger.info("Info message") # Bright white text
|
125
|
+
logger.warn("Warning message") # Yellow background, white bold text
|
126
|
+
logger.error("Error message") # Light red background, white bold text
|
127
|
+
logger.fatal("Fatal message") # Light red background, yellow bold text
|
117
128
|
```
|
118
129
|
|
119
|
-
|
130
|
+
### Color Scheme
|
120
131
|
|
121
|
-
|
132
|
+
| Level | Foreground | Background | Style |
|
133
|
+
|-------|------------|------------|-------|
|
134
|
+
| DEBUG | Black | Green | Bold |
|
135
|
+
| INFO | Bright White | None | None |
|
136
|
+
| WARN | White | Yellow | Bold |
|
137
|
+
| ERROR | White | Light Red | Bold |
|
138
|
+
| FATAL | Yellow | Light Red | Bold |
|
122
139
|
|
123
|
-
|
124
|
-
|-------|--------------|-------------|
|
125
|
-
| `Logger::DEBUG` | 0 | Detailed debugging information |
|
126
|
-
| `Logger::INFO` | 1 | General information messages |
|
127
|
-
| `Logger::WARN` | 2 | Warning messages |
|
128
|
-
| `Logger::ERROR` | 3 | Error messages |
|
129
|
-
| `Logger::FATAL` | 4 | Fatal error messages |
|
140
|
+
**Note:** Colorization is automatically disabled for file output to keep log files clean.
|
130
141
|
|
131
|
-
|
142
|
+
## File Rolling
|
132
143
|
|
133
|
-
|
144
|
+
SmartMessage supports both size-based and date-based log file rolling:
|
134
145
|
|
135
|
-
-
|
136
|
-
- **Rails Test**: `Logger::ERROR`
|
137
|
-
- **Rails Development**: `Logger::DEBUG`
|
138
|
-
- **Non-Rails**: `Logger::INFO`
|
146
|
+
### Size-Based Rolling
|
139
147
|
|
140
|
-
|
148
|
+
```ruby
|
149
|
+
SmartMessage.configure do |config|
|
150
|
+
config.logger = "log/application.log"
|
151
|
+
config.log_options = {
|
152
|
+
roll_by_size: true,
|
153
|
+
max_file_size: 10 * 1024 * 1024, # 10 MB
|
154
|
+
keep_files: 5 # Keep 5 old files
|
155
|
+
}
|
156
|
+
end
|
157
|
+
```
|
141
158
|
|
142
|
-
|
159
|
+
Files are named: `application.log`, `application.log.1`, `application.log.2`, etc.
|
143
160
|
|
144
|
-
###
|
161
|
+
### Date-Based Rolling
|
145
162
|
|
146
163
|
```ruby
|
147
|
-
|
148
|
-
|
149
|
-
|
164
|
+
SmartMessage.configure do |config|
|
165
|
+
config.logger = "log/application.log"
|
166
|
+
config.log_options = {
|
167
|
+
roll_by_date: true,
|
168
|
+
date_pattern: '%Y-%m-%d' # Daily rolling
|
169
|
+
}
|
170
|
+
end
|
150
171
|
```
|
151
172
|
|
152
|
-
|
173
|
+
Files are named: `application.log.2025-01-15`, `application.log.2025-01-14`, etc.
|
153
174
|
|
154
|
-
|
155
|
-
# Logged at INFO level
|
156
|
-
message.publish
|
157
|
-
# → [INFO] [SmartMessage] Published: MyMessage via StdoutTransport
|
158
|
-
```
|
175
|
+
### Rolling Options
|
159
176
|
|
160
|
-
|
177
|
+
| Option | Type | Description |
|
178
|
+
|--------|------|-------------|
|
179
|
+
| `roll_by_size` | Boolean | Enable size-based rolling |
|
180
|
+
| `max_file_size` | Integer | Maximum file size in bytes |
|
181
|
+
| `keep_files` | Integer | Number of old files to keep |
|
182
|
+
| `roll_by_date` | Boolean | Enable date-based rolling |
|
183
|
+
| `date_pattern` | String | Date format pattern |
|
161
184
|
|
162
|
-
|
163
|
-
# Logged at INFO level when message is received
|
164
|
-
# → [INFO] [SmartMessage] Received: MyMessage (45 bytes)
|
165
|
-
```
|
185
|
+
## Structured Logging
|
166
186
|
|
167
|
-
|
187
|
+
Enable structured data logging to include metadata with your log entries:
|
168
188
|
|
169
189
|
```ruby
|
170
|
-
|
171
|
-
|
190
|
+
SmartMessage.configure do |config|
|
191
|
+
config.logger = "log/application.log"
|
192
|
+
config.log_format = :json
|
193
|
+
config.log_structured_data = true
|
194
|
+
config.log_include_source = true
|
195
|
+
end
|
196
|
+
|
197
|
+
logger = SmartMessage.configuration.default_logger
|
198
|
+
|
199
|
+
# Log with structured data
|
200
|
+
logger.info("User registration",
|
201
|
+
user_id: "user123",
|
202
|
+
email: "user@example.com",
|
203
|
+
registration_source: "web",
|
204
|
+
timestamp: Time.now.iso8601)
|
205
|
+
|
206
|
+
# Log with block for conditional data
|
207
|
+
logger.warn("Database slow query") do
|
208
|
+
{
|
209
|
+
query: "SELECT * FROM users WHERE status = ?",
|
210
|
+
duration_ms: 1500,
|
211
|
+
table: "users",
|
212
|
+
slow_query: true
|
213
|
+
}
|
214
|
+
end
|
172
215
|
```
|
173
216
|
|
174
|
-
|
217
|
+
## Application Integration
|
218
|
+
|
219
|
+
### Accessing the Logger
|
220
|
+
|
221
|
+
The configured logger is available globally:
|
175
222
|
|
176
223
|
```ruby
|
177
|
-
#
|
178
|
-
|
179
|
-
# → [INFO] [SmartMessage] Subscribed: MyMessage
|
224
|
+
# Get the globally configured logger
|
225
|
+
logger = SmartMessage.configuration.default_logger
|
180
226
|
|
181
|
-
|
182
|
-
|
227
|
+
# Use in your application
|
228
|
+
logger.info("Application starting", version: "1.0.0")
|
229
|
+
logger.warn("Configuration missing", config_key: "database_url")
|
230
|
+
logger.error("Service unavailable", service: "payment_gateway")
|
183
231
|
```
|
184
232
|
|
185
|
-
###
|
233
|
+
### Class-Level Integration
|
186
234
|
|
187
235
|
```ruby
|
188
|
-
|
189
|
-
|
190
|
-
|
236
|
+
class OrderService
|
237
|
+
def initialize
|
238
|
+
@logger = SmartMessage.configuration.default_logger
|
239
|
+
end
|
240
|
+
|
241
|
+
def process_order(order)
|
242
|
+
@logger.info("Processing order",
|
243
|
+
order_id: order.id,
|
244
|
+
customer_id: order.customer_id,
|
245
|
+
amount: order.amount)
|
246
|
+
|
247
|
+
begin
|
248
|
+
# Process order logic
|
249
|
+
result = perform_processing(order)
|
250
|
+
|
251
|
+
@logger.info("Order completed",
|
252
|
+
order_id: order.id,
|
253
|
+
status: "success",
|
254
|
+
processing_time_ms: result[:duration])
|
255
|
+
|
256
|
+
rescue StandardError => e
|
257
|
+
@logger.error("Order processing failed",
|
258
|
+
order_id: order.id,
|
259
|
+
error: e.message,
|
260
|
+
error_class: e.class.name)
|
261
|
+
raise
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
191
265
|
```
|
192
266
|
|
193
|
-
##
|
267
|
+
## SmartMessage Integration
|
194
268
|
|
195
|
-
|
196
|
-
|
197
|
-
### Automatic Detection
|
269
|
+
SmartMessage classes automatically use the configured logger:
|
198
270
|
|
199
271
|
```ruby
|
200
|
-
|
201
|
-
|
272
|
+
class OrderMessage < SmartMessage::Base
|
273
|
+
property :order_id, required: true
|
274
|
+
property :customer_id, required: true
|
275
|
+
property :amount, required: true
|
276
|
+
|
277
|
+
config do
|
278
|
+
transport SmartMessage::Transport::StdoutTransport.new
|
279
|
+
serializer SmartMessage::Serializer::Json.new
|
280
|
+
from 'order-service'
|
281
|
+
end
|
282
|
+
|
283
|
+
def process
|
284
|
+
# Logger is automatically available
|
285
|
+
logger.info("Processing order message",
|
286
|
+
message_id: _sm_header.uuid,
|
287
|
+
order_id: order_id,
|
288
|
+
customer_id: customer_id,
|
289
|
+
amount: amount)
|
290
|
+
|
291
|
+
# Log the complete message structure
|
292
|
+
logger.debug("Message details",
|
293
|
+
header: _sm_header.to_h,
|
294
|
+
payload: _sm_payload,
|
295
|
+
full_message: to_h)
|
296
|
+
|
297
|
+
# Process the order
|
298
|
+
case amount
|
299
|
+
when 0..100
|
300
|
+
logger.info("Small order processed", order_id: order_id)
|
301
|
+
when 101..1000
|
302
|
+
logger.warn("Medium order requires review", order_id: order_id)
|
303
|
+
else
|
304
|
+
logger.error("Large order requires manual approval",
|
305
|
+
order_id: order_id,
|
306
|
+
amount: amount)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
202
310
|
```
|
203
311
|
|
204
|
-
|
312
|
+
## Examples
|
205
313
|
|
206
|
-
|
207
|
-
# In Rails, all SmartMessage logs are tagged
|
208
|
-
Rails.logger.tagged('SmartMessage') do
|
209
|
-
# All SmartMessage logging happens here
|
210
|
-
end
|
211
|
-
```
|
314
|
+
### Development Configuration
|
212
315
|
|
213
|
-
|
316
|
+
Perfect for local development with colorized console output:
|
214
317
|
|
215
318
|
```ruby
|
216
|
-
|
217
|
-
logger
|
218
|
-
|
319
|
+
SmartMessage.configure do |config|
|
320
|
+
config.logger = STDOUT
|
321
|
+
config.log_level = :debug
|
322
|
+
config.log_format = :text
|
323
|
+
config.log_colorize = true
|
324
|
+
config.log_include_source = true
|
325
|
+
end
|
219
326
|
```
|
220
327
|
|
221
|
-
###
|
328
|
+
### Production Configuration
|
222
329
|
|
223
|
-
|
330
|
+
Production setup with JSON logging and file rolling:
|
224
331
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
332
|
+
```ruby
|
333
|
+
SmartMessage.configure do |config|
|
334
|
+
config.logger = "/var/log/app/smartmessage.log"
|
335
|
+
config.log_level = :info
|
336
|
+
config.log_format = :json
|
337
|
+
config.log_colorize = false
|
338
|
+
config.log_structured_data = true
|
339
|
+
config.log_include_source = false
|
340
|
+
config.log_options = {
|
341
|
+
roll_by_size: true,
|
342
|
+
max_file_size: 50 * 1024 * 1024, # 50 MB
|
343
|
+
keep_files: 10
|
344
|
+
}
|
345
|
+
end
|
346
|
+
```
|
230
347
|
|
231
|
-
|
348
|
+
### Docker/Container Configuration
|
232
349
|
|
233
|
-
|
350
|
+
Container-friendly setup with structured STDOUT logging:
|
234
351
|
|
235
352
|
```ruby
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
end
|
244
|
-
|
245
|
-
def log_message_published(message, transport)
|
246
|
-
@logger.info "Published #{message.class.name} via #{transport.class.name}"
|
247
|
-
end
|
248
|
-
|
249
|
-
# Implement other lifecycle methods as needed...
|
353
|
+
SmartMessage.configure do |config|
|
354
|
+
config.logger = STDOUT
|
355
|
+
config.log_level = ENV['LOG_LEVEL']&.downcase&.to_sym || :info
|
356
|
+
config.log_format = :json
|
357
|
+
config.log_colorize = false
|
358
|
+
config.log_structured_data = true
|
359
|
+
config.log_include_source = true
|
250
360
|
end
|
251
361
|
```
|
252
362
|
|
253
|
-
###
|
363
|
+
### Testing Configuration
|
364
|
+
|
365
|
+
Minimal logging for test environments:
|
254
366
|
|
255
367
|
```ruby
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
def log_message_created(message)
|
263
|
-
@logger.debug "Message created", message_class: message.class.name
|
264
|
-
end
|
265
|
-
|
266
|
-
def log_error(context, error)
|
267
|
-
@logger.error "Error in #{context}", exception: error
|
268
|
-
end
|
368
|
+
SmartMessage.configure do |config|
|
369
|
+
config.logger = STDERR
|
370
|
+
config.log_level = :error
|
371
|
+
config.log_format = :text
|
372
|
+
config.log_colorize = false
|
269
373
|
end
|
270
374
|
```
|
271
375
|
|
272
|
-
###
|
376
|
+
### Multiple Logger Configurations
|
377
|
+
|
378
|
+
You can create multiple logger instances for different purposes:
|
273
379
|
|
274
380
|
```ruby
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
def log_message_created(message)
|
281
|
-
@loggers.each { |logger| logger.log_message_created(message) }
|
282
|
-
end
|
283
|
-
|
284
|
-
# Other methods follow same pattern...
|
381
|
+
# Configure global logger
|
382
|
+
SmartMessage.configure do |config|
|
383
|
+
config.logger = "log/application.log"
|
384
|
+
config.log_level = :info
|
385
|
+
config.log_format = :json
|
285
386
|
end
|
286
387
|
|
287
|
-
#
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
388
|
+
# Create additional loggers for specific needs
|
389
|
+
console_logger = SmartMessage::Logger::Lumberjack.new(
|
390
|
+
log_file: STDERR,
|
391
|
+
level: :warn,
|
392
|
+
format: :text,
|
393
|
+
colorize: true
|
394
|
+
)
|
395
|
+
|
396
|
+
debug_logger = SmartMessage::Logger::Lumberjack.new(
|
397
|
+
log_file: "log/debug.log",
|
398
|
+
level: :debug,
|
399
|
+
format: :text,
|
400
|
+
include_source: true
|
292
401
|
)
|
402
|
+
|
403
|
+
# Use in application
|
404
|
+
console_logger.warn("Service degraded")
|
405
|
+
debug_logger.debug("Detailed debugging info", state: app_state)
|
293
406
|
```
|
294
407
|
|
295
|
-
##
|
408
|
+
## Best Practices
|
409
|
+
|
410
|
+
### 1. Environment-Based Configuration
|
296
411
|
|
297
|
-
|
412
|
+
Configure logging based on your environment:
|
298
413
|
|
299
414
|
```ruby
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
# Verbose logging for development
|
310
|
-
logger SmartMessage::Logger::Default.new(
|
311
|
-
log_file: STDOUT,
|
312
|
-
level: Logger::DEBUG
|
313
|
-
)
|
415
|
+
case ENV['RAILS_ENV'] || ENV['ENVIRONMENT']
|
416
|
+
when 'production'
|
417
|
+
SmartMessage.configure do |config|
|
418
|
+
config.logger = "/var/log/app/smartmessage.log"
|
419
|
+
config.log_level = :info
|
420
|
+
config.log_format = :json
|
421
|
+
config.log_structured_data = true
|
422
|
+
config.log_options = { roll_by_size: true, max_file_size: 50.megabytes, keep_files: 10 }
|
314
423
|
end
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
logger
|
326
|
-
|
424
|
+
when 'development'
|
425
|
+
SmartMessage.configure do |config|
|
426
|
+
config.logger = STDOUT
|
427
|
+
config.log_level = :debug
|
428
|
+
config.log_format = :text
|
429
|
+
config.log_colorize = true
|
430
|
+
config.log_include_source = true
|
431
|
+
end
|
432
|
+
when 'test'
|
433
|
+
SmartMessage.configure do |config|
|
434
|
+
config.logger = STDERR
|
435
|
+
config.log_level = :error
|
436
|
+
config.log_format = :text
|
327
437
|
end
|
328
438
|
end
|
329
439
|
```
|
330
440
|
|
331
|
-
###
|
441
|
+
### 2. Structured Data
|
442
|
+
|
443
|
+
Use structured data for better log analysis:
|
332
444
|
|
333
445
|
```ruby
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
# Production logging with file rotation
|
344
|
-
logger SmartMessage::Logger::Default.new(
|
345
|
-
log_file: '/var/log/app/notifications.log',
|
346
|
-
level: Logger::INFO
|
347
|
-
)
|
348
|
-
end
|
349
|
-
end
|
446
|
+
# Good: Structured data
|
447
|
+
logger.info("User action",
|
448
|
+
user_id: user.id,
|
449
|
+
action: "login",
|
450
|
+
ip_address: request.ip,
|
451
|
+
user_agent: request.user_agent)
|
452
|
+
|
453
|
+
# Avoid: String interpolation
|
454
|
+
logger.info("User #{user.id} logged in from #{request.ip}")
|
350
455
|
```
|
351
456
|
|
352
|
-
###
|
457
|
+
### 3. Appropriate Log Levels
|
353
458
|
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
level: ENV['LOG_LEVEL']&.upcase&.to_sym || Logger::INFO
|
369
|
-
)
|
370
|
-
end
|
371
|
-
end
|
372
|
-
```
|
459
|
+
Use log levels appropriately:
|
460
|
+
|
461
|
+
- **DEBUG**: Detailed information for diagnosing problems
|
462
|
+
- **INFO**: General information about program execution
|
463
|
+
- **WARN**: Something unexpected happened, but the application is still working
|
464
|
+
- **ERROR**: A serious problem occurred, but the application can continue
|
465
|
+
- **FATAL**: A very serious error occurred, application may not be able to continue
|
466
|
+
|
467
|
+
### 4. Performance Considerations
|
468
|
+
|
469
|
+
- Use appropriate log levels in production (avoid DEBUG)
|
470
|
+
- Consider async logging for high-volume applications
|
471
|
+
- Use structured data instead of string concatenation
|
472
|
+
- Be mindful of log volume and storage costs
|
373
473
|
|
374
|
-
###
|
474
|
+
### 5. Security
|
475
|
+
|
476
|
+
- Never log sensitive data (passwords, tokens, credit card numbers)
|
477
|
+
- Sanitize user input before logging
|
478
|
+
- Use structured data to avoid log injection attacks
|
375
479
|
|
376
480
|
```ruby
|
377
|
-
#
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
transport SmartMessage::Transport::MemoryTransport.new
|
383
|
-
serializer SmartMessage::Serializer::JSON.new
|
384
|
-
|
385
|
-
# Minimal logging for tests
|
386
|
-
logger SmartMessage::Logger::Default.new(
|
387
|
-
log_file: StringIO.new,
|
388
|
-
level: Logger::FATAL # Only fatal errors in tests
|
389
|
-
)
|
390
|
-
end
|
391
|
-
end
|
481
|
+
# Good: Structured data prevents injection
|
482
|
+
logger.info("User input received", user_input: params[:query])
|
483
|
+
|
484
|
+
# Avoid: Direct string interpolation
|
485
|
+
logger.info("User searched for: #{params[:query]}")
|
392
486
|
```
|
393
487
|
|
394
|
-
###
|
488
|
+
### 6. Testing
|
489
|
+
|
490
|
+
Test your logging configuration:
|
395
491
|
|
396
492
|
```ruby
|
397
|
-
#
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
config
|
403
|
-
|
404
|
-
serializer SmartMessage::Serializer::JSON.new
|
405
|
-
logger SmartMessage::Logger::Default.new # Default logger
|
406
|
-
end
|
493
|
+
# Test that logs are being generated
|
494
|
+
require 'stringio'
|
495
|
+
|
496
|
+
log_output = StringIO.new
|
497
|
+
SmartMessage.configure do |config|
|
498
|
+
config.logger = log_output
|
499
|
+
config.log_level = :debug
|
407
500
|
end
|
408
501
|
|
409
|
-
|
410
|
-
|
411
|
-
log_file: '/var/log/priority.log',
|
412
|
-
level: Logger::DEBUG
|
413
|
-
)
|
502
|
+
logger = SmartMessage.configuration.default_logger
|
503
|
+
logger.info("Test message")
|
414
504
|
|
415
|
-
|
416
|
-
urgent_message.logger(priority_logger) # Override for this instance
|
417
|
-
urgent_message.publish
|
505
|
+
assert_includes log_output.string, "Test message"
|
418
506
|
```
|
419
507
|
|
420
|
-
|
421
|
-
|
422
|
-
1. **Use the default logger** unless you have specific requirements
|
423
|
-
2. **Log to STDOUT** in containerized environments
|
424
|
-
3. **Use appropriate log levels** - avoid DEBUG in production
|
425
|
-
4. **Tag your logs** for better searchability
|
426
|
-
5. **Consider structured logging** for production systems
|
427
|
-
6. **Test your logging** - ensure logs are helpful for debugging
|
428
|
-
7. **Monitor log volume** - excessive logging can impact performance
|
429
|
-
8. **Rotate log files** to prevent disk space issues (default logger handles this)
|
430
|
-
|
431
|
-
## Troubleshooting
|
432
|
-
|
433
|
-
### No logs appearing
|
434
|
-
- Check log level settings
|
435
|
-
- Verify file permissions
|
436
|
-
- Ensure logger is configured
|
437
|
-
|
438
|
-
### Too much logging
|
439
|
-
- Increase log level (DEBUG → INFO → WARN → ERROR)
|
440
|
-
- Consider filtering in production
|
441
|
-
|
442
|
-
### Performance issues
|
443
|
-
- Lower log level in production
|
444
|
-
- Use asynchronous logging for high-volume systems
|
445
|
-
- Consider structured logging formats
|
446
|
-
|
447
|
-
### Rails integration not working
|
448
|
-
- Ensure Rails is loaded before SmartMessage
|
449
|
-
- Check that `Rails.logger` is available
|
450
|
-
- Verify Rails environment is set correctly
|
451
|
-
|
452
|
-
For more troubleshooting tips, see the [Troubleshooting Guide](troubleshooting.md).
|
508
|
+
For more information, see the comprehensive logging example at `examples/show_logger.rb`.
|