cmdx 1.0.1 → 1.1.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 +4 -4
- data/.cursor/prompts/docs.md +9 -0
- data/.cursor/prompts/rspec.md +21 -0
- data/.cursor/prompts/yardoc.md +13 -0
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +29 -3
- data/README.md +2 -1
- data/docs/ai_prompts.md +269 -195
- data/docs/basics/call.md +126 -60
- data/docs/basics/chain.md +190 -160
- data/docs/basics/context.md +242 -154
- data/docs/basics/setup.md +302 -32
- data/docs/callbacks.md +382 -119
- data/docs/configuration.md +211 -49
- data/docs/deprecation.md +245 -0
- data/docs/getting_started.md +161 -39
- data/docs/internationalization.md +590 -70
- data/docs/interruptions/exceptions.md +135 -118
- data/docs/interruptions/faults.md +152 -127
- data/docs/interruptions/halt.md +134 -80
- data/docs/logging.md +183 -120
- data/docs/middlewares.md +165 -392
- data/docs/outcomes/result.md +140 -112
- data/docs/outcomes/states.md +134 -99
- data/docs/outcomes/statuses.md +204 -146
- data/docs/parameters/coercions.md +251 -289
- data/docs/parameters/defaults.md +224 -169
- data/docs/parameters/definitions.md +289 -141
- data/docs/parameters/namespacing.md +250 -161
- data/docs/parameters/validations.md +247 -159
- data/docs/testing.md +196 -203
- data/docs/workflows.md +146 -101
- data/lib/cmdx/.DS_Store +0 -0
- data/lib/cmdx/callback.rb +39 -55
- data/lib/cmdx/callback_registry.rb +80 -73
- data/lib/cmdx/chain.rb +65 -122
- data/lib/cmdx/chain_inspector.rb +23 -116
- data/lib/cmdx/chain_serializer.rb +34 -146
- data/lib/cmdx/coercion.rb +57 -0
- data/lib/cmdx/coercion_registry.rb +113 -0
- data/lib/cmdx/coercions/array.rb +18 -36
- data/lib/cmdx/coercions/big_decimal.rb +21 -33
- data/lib/cmdx/coercions/boolean.rb +21 -40
- data/lib/cmdx/coercions/complex.rb +18 -31
- data/lib/cmdx/coercions/date.rb +20 -39
- data/lib/cmdx/coercions/date_time.rb +22 -39
- data/lib/cmdx/coercions/float.rb +19 -32
- data/lib/cmdx/coercions/hash.rb +22 -41
- data/lib/cmdx/coercions/integer.rb +20 -33
- data/lib/cmdx/coercions/rational.rb +20 -32
- data/lib/cmdx/coercions/string.rb +23 -31
- data/lib/cmdx/coercions/time.rb +24 -40
- data/lib/cmdx/coercions/virtual.rb +14 -31
- data/lib/cmdx/configuration.rb +101 -162
- data/lib/cmdx/context.rb +34 -166
- data/lib/cmdx/core_ext/hash.rb +42 -67
- data/lib/cmdx/core_ext/module.rb +35 -79
- data/lib/cmdx/core_ext/object.rb +63 -98
- data/lib/cmdx/correlator.rb +59 -154
- data/lib/cmdx/error.rb +37 -202
- data/lib/cmdx/errors.rb +153 -216
- data/lib/cmdx/fault.rb +68 -150
- data/lib/cmdx/faults.rb +26 -137
- data/lib/cmdx/immutator.rb +22 -110
- data/lib/cmdx/lazy_struct.rb +110 -186
- data/lib/cmdx/log_formatters/json.rb +14 -40
- data/lib/cmdx/log_formatters/key_value.rb +14 -40
- data/lib/cmdx/log_formatters/line.rb +14 -48
- data/lib/cmdx/log_formatters/logstash.rb +14 -57
- data/lib/cmdx/log_formatters/pretty_json.rb +14 -50
- data/lib/cmdx/log_formatters/pretty_key_value.rb +13 -46
- data/lib/cmdx/log_formatters/pretty_line.rb +16 -54
- data/lib/cmdx/log_formatters/raw.rb +19 -49
- data/lib/cmdx/logger.rb +22 -79
- data/lib/cmdx/logger_ansi.rb +31 -72
- data/lib/cmdx/logger_serializer.rb +74 -103
- data/lib/cmdx/middleware.rb +56 -60
- data/lib/cmdx/middleware_registry.rb +82 -77
- data/lib/cmdx/middlewares/correlate.rb +41 -226
- data/lib/cmdx/middlewares/timeout.rb +46 -185
- data/lib/cmdx/parameter.rb +167 -183
- data/lib/cmdx/parameter_evaluator.rb +231 -0
- data/lib/cmdx/parameter_inspector.rb +37 -55
- data/lib/cmdx/parameter_registry.rb +65 -84
- data/lib/cmdx/parameter_serializer.rb +32 -76
- data/lib/cmdx/railtie.rb +24 -107
- data/lib/cmdx/result.rb +254 -259
- data/lib/cmdx/result_ansi.rb +28 -80
- data/lib/cmdx/result_inspector.rb +34 -70
- data/lib/cmdx/result_logger.rb +23 -77
- data/lib/cmdx/result_serializer.rb +59 -125
- data/lib/cmdx/rspec/matchers.rb +28 -0
- data/lib/cmdx/rspec/result_matchers/be_executed.rb +42 -0
- data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +94 -0
- data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +94 -0
- data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +59 -0
- data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +57 -0
- data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +87 -0
- data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +51 -0
- data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +58 -0
- data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +59 -0
- data/lib/cmdx/rspec/result_matchers/have_context.rb +86 -0
- data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +54 -0
- data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +52 -0
- data/lib/cmdx/rspec/result_matchers/have_metadata.rb +114 -0
- data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +66 -0
- data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +64 -0
- data/lib/cmdx/rspec/result_matchers/have_runtime.rb +78 -0
- data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +76 -0
- data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +62 -0
- data/lib/cmdx/rspec/task_matchers/have_callback.rb +85 -0
- data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +68 -0
- data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +92 -0
- data/lib/cmdx/rspec/task_matchers/have_middleware.rb +46 -0
- data/lib/cmdx/rspec/task_matchers/have_parameter.rb +181 -0
- data/lib/cmdx/task.rb +336 -427
- data/lib/cmdx/task_deprecator.rb +52 -0
- data/lib/cmdx/task_processor.rb +246 -0
- data/lib/cmdx/task_serializer.rb +34 -69
- data/lib/cmdx/utils/ansi_color.rb +13 -89
- data/lib/cmdx/utils/log_timestamp.rb +13 -42
- data/lib/cmdx/utils/monotonic_runtime.rb +11 -63
- data/lib/cmdx/utils/name_affix.rb +21 -71
- data/lib/cmdx/validator.rb +57 -0
- data/lib/cmdx/validator_registry.rb +108 -0
- data/lib/cmdx/validators/exclusion.rb +55 -94
- data/lib/cmdx/validators/format.rb +31 -85
- data/lib/cmdx/validators/inclusion.rb +65 -110
- data/lib/cmdx/validators/length.rb +117 -133
- data/lib/cmdx/validators/numeric.rb +123 -130
- data/lib/cmdx/validators/presence.rb +38 -79
- data/lib/cmdx/version.rb +1 -7
- data/lib/cmdx/workflow.rb +58 -330
- data/lib/cmdx.rb +1 -1
- data/lib/generators/cmdx/install_generator.rb +14 -31
- data/lib/generators/cmdx/task_generator.rb +39 -55
- data/lib/generators/cmdx/templates/install.rb +24 -6
- data/lib/generators/cmdx/workflow_generator.rb +41 -66
- data/lib/locales/ar.yml +0 -1
- data/lib/locales/cs.yml +0 -1
- data/lib/locales/da.yml +0 -1
- data/lib/locales/de.yml +0 -1
- data/lib/locales/el.yml +0 -1
- data/lib/locales/en.yml +0 -1
- data/lib/locales/es.yml +0 -1
- data/lib/locales/fi.yml +0 -1
- data/lib/locales/fr.yml +0 -1
- data/lib/locales/he.yml +0 -1
- data/lib/locales/hi.yml +0 -1
- data/lib/locales/it.yml +0 -1
- data/lib/locales/ja.yml +0 -1
- data/lib/locales/ko.yml +0 -1
- data/lib/locales/nl.yml +0 -1
- data/lib/locales/no.yml +0 -1
- data/lib/locales/pl.yml +0 -1
- data/lib/locales/pt.yml +0 -1
- data/lib/locales/ru.yml +0 -1
- data/lib/locales/sv.yml +0 -1
- data/lib/locales/th.yml +0 -1
- data/lib/locales/tr.yml +0 -1
- data/lib/locales/vi.yml +0 -1
- data/lib/locales/zh.yml +0 -1
- metadata +36 -8
- data/lib/cmdx/parameter_validator.rb +0 -81
- data/lib/cmdx/parameter_value.rb +0 -244
- data/lib/cmdx/parameters_inspector.rb +0 -72
- data/lib/cmdx/parameters_serializer.rb +0 -115
- data/lib/cmdx/rspec/result_matchers.rb +0 -917
- data/lib/cmdx/rspec/task_matchers.rb +0 -570
- data/lib/cmdx/validators/custom.rb +0 -102
data/docs/logging.md
CHANGED
@@ -6,96 +6,109 @@ CMDx provides comprehensive automatic logging for task execution with structured
|
|
6
6
|
- [TLDR](#tldr)
|
7
7
|
- [Log Formatters](#log-formatters)
|
8
8
|
- [Standard Formatters](#standard-formatters)
|
9
|
-
- [Stylized Formatters
|
9
|
+
- [Stylized Formatters](#stylized-formatters)
|
10
10
|
- [Sample Output](#sample-output)
|
11
|
-
- [Success Result](#success-result)
|
12
|
-
- [Skipped Result](#skipped-result)
|
13
|
-
- [Failed Result](#failed-result)
|
14
|
-
- [Failure Chain (Workflow Workflows)](#failure-chain-workflow-workflows)
|
15
11
|
- [Configuration](#configuration)
|
16
12
|
- [Global Configuration](#global-configuration)
|
17
13
|
- [Task-Specific Configuration](#task-specific-configuration)
|
18
|
-
- [Environment-Specific Configuration](#environment-specific-configuration)
|
19
14
|
- [Severity Mapping](#severity-mapping)
|
20
15
|
- [Manual Logging](#manual-logging)
|
21
|
-
- [
|
22
|
-
|
16
|
+
- [Error Handling](#error-handling)
|
17
|
+
- [Advanced Usage](#advanced-usage)
|
18
|
+
- [Custom Formatters](#custom-formatters)
|
23
19
|
- [Multi-Destination Logging](#multi-destination-logging)
|
24
20
|
- [Log Data Structure](#log-data-structure)
|
25
21
|
|
26
22
|
## TLDR
|
27
23
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
24
|
+
```ruby
|
25
|
+
# Automatic logging - no setup required
|
26
|
+
class ProcessOrderTask < CMDx::Task
|
27
|
+
def call
|
28
|
+
# Task execution automatically logged with metadata
|
29
|
+
end
|
30
|
+
end
|
34
31
|
|
35
|
-
|
32
|
+
# Custom formatter
|
33
|
+
cmd_settings!(log_formatter: CMDx::LogFormatters::Json.new)
|
36
34
|
|
37
|
-
|
35
|
+
# Manual logging within tasks
|
36
|
+
logger.info "Processing order", order_id: context.order_id
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
38
|
+
# Global configuration
|
39
|
+
CMDx.configure do |config|
|
40
|
+
config.logger = Logger.new("log/cmdx.log")
|
41
|
+
config.log_formatter = CMDx::LogFormatters::Json.new
|
42
|
+
end
|
43
|
+
```
|
45
44
|
|
46
|
-
|
45
|
+
## Log Formatters
|
47
46
|
|
48
47
|
> [!NOTE]
|
49
|
-
>
|
48
|
+
> All formatters automatically include execution metadata. Choose based on your environment: stylized for development, standard for production.
|
50
49
|
|
51
|
-
|
52
|
-
- **`PrettyJson`** - Human-readable multi-line JSON with syntax highlighting
|
53
|
-
- **`PrettyKeyValue`** - Colorized key=value pairs for terminal readability
|
50
|
+
### Standard Formatters
|
54
51
|
|
55
|
-
|
52
|
+
| Formatter | Use Case | Output Style |
|
53
|
+
|-----------|----------|--------------|
|
54
|
+
| `Line` | Traditional logging | Single-line format |
|
55
|
+
| `Json` | Structured systems | Compact JSON |
|
56
|
+
| `KeyValue` | Log parsing | `key=value` pairs |
|
57
|
+
| `Logstash` | ELK stack | JSON with @version/@timestamp |
|
58
|
+
| `Raw` | Minimal output | Message content only |
|
56
59
|
|
57
|
-
###
|
58
|
-
```txt
|
59
|
-
I, [2022-07-17T18:43:15.000000 #3784] INFO -- CreateOrderTask: index=0 chain_id=018c2b95-b764-7615-a924-cc5b910ed1e5 type=Task class=CreateOrderTask id=018c2b95-b764-7615-a924-cc5b910ed1e5 tags=[] state=complete status=success outcome=success metadata={order_id: 123, confirmation: "ABC123"} runtime=0.45 origin=CMDx
|
60
|
-
```
|
60
|
+
### Stylized Formatters
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
W, [2022-07-17T18:43:15.000000 #3784] WARN -- ValidatePaymentTask: index=0 chain_id=018c2b95-b764-7615-a924-cc5b910ed1e5 type=Task class=ValidatePaymentTask id=018c2b95-b764-7615-a924-cc5b910ed1e5 tags=[] state=interrupted status=skipped outcome=skipped metadata={reason: "Order already processed"} runtime=0.02 origin=CMDx
|
65
|
-
```
|
62
|
+
> [!TIP]
|
63
|
+
> Stylized formatters include ANSI color codes for better terminal readability in development environments.
|
66
64
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
65
|
+
| Formatter | Description |
|
66
|
+
|-----------|-------------|
|
67
|
+
| `PrettyLine` | Colorized line format (default) |
|
68
|
+
| `PrettyJson` | Multi-line JSON with syntax highlighting |
|
69
|
+
| `PrettyKeyValue` | Colorized key=value pairs |
|
71
70
|
|
72
|
-
|
73
|
-
|
74
|
-
|
71
|
+
## Sample Output
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
# Success (INFO level)
|
75
|
+
I, [2022-07-17T18:43:15.000000 #3784] INFO -- CreateOrderTask:
|
76
|
+
index=0 chain_id=018c2b95-b764-7615-a924-cc5b910ed1e5 type=Task
|
77
|
+
class=CreateOrderTask status=success metadata={order_id: 123} runtime=0.45
|
78
|
+
|
79
|
+
# Skipped (WARN level)
|
80
|
+
W, [2022-07-17T18:43:15.000000 #3784] WARN -- ValidatePaymentTask:
|
81
|
+
index=1 status=skipped metadata={reason: "Order already processed"} runtime=0.02
|
82
|
+
|
83
|
+
# Failed (ERROR level)
|
84
|
+
E, [2022-07-17T18:43:15.000000 #3784] ERROR -- ProcessPaymentTask:
|
85
|
+
index=2 status=failed metadata={error_code: "INSUFFICIENT_FUNDS"} runtime=0.15
|
86
|
+
|
87
|
+
# Workflow failure chain
|
88
|
+
E, [2022-07-17T18:43:15.000000 #3784] ERROR -- OrderWorkflow:
|
89
|
+
caused_failure={index: 2, class: "ProcessPaymentTask", status: "failed"}
|
90
|
+
threw_failure={index: 1, class: "ValidatePaymentTask", status: "failed"}
|
75
91
|
```
|
76
92
|
|
77
93
|
## Configuration
|
78
94
|
|
79
95
|
### Global Configuration
|
80
96
|
|
81
|
-
Configure logging globally in your CMDx initializer:
|
82
|
-
|
83
97
|
```ruby
|
84
98
|
CMDx.configure do |config|
|
85
|
-
config.logger = Logger.new("log/cmdx.log"
|
86
|
-
config.
|
99
|
+
config.logger = Logger.new("log/cmdx.log")
|
100
|
+
config.log_formatter = CMDx::LogFormatters::Json.new
|
101
|
+
config.log_level = Logger::INFO
|
87
102
|
end
|
88
103
|
```
|
89
104
|
|
90
105
|
### Task-Specific Configuration
|
91
106
|
|
92
|
-
Override logging settings for individual tasks:
|
93
|
-
|
94
107
|
```ruby
|
95
108
|
class SendEmailTask < CMDx::Task
|
96
|
-
|
109
|
+
cmd_settings!(
|
97
110
|
logger: Rails.logger,
|
98
|
-
log_formatter: CMDx::LogFormatters::
|
111
|
+
log_formatter: CMDx::LogFormatters::Logstash.new,
|
99
112
|
log_level: Logger::WARN
|
100
113
|
)
|
101
114
|
|
@@ -104,12 +117,11 @@ class SendEmailTask < CMDx::Task
|
|
104
117
|
end
|
105
118
|
end
|
106
119
|
|
107
|
-
# Base class
|
120
|
+
# Base class configuration
|
108
121
|
class ApplicationTask < CMDx::Task
|
109
|
-
|
122
|
+
cmd_settings!(
|
110
123
|
logger: Logger.new("log/tasks.log"),
|
111
|
-
log_formatter: CMDx::LogFormatters::
|
112
|
-
log_level: Logger::INFO
|
124
|
+
log_formatter: CMDx::LogFormatters::Json.new
|
113
125
|
)
|
114
126
|
end
|
115
127
|
```
|
@@ -117,55 +129,99 @@ end
|
|
117
129
|
## Severity Mapping
|
118
130
|
|
119
131
|
> [!IMPORTANT]
|
120
|
-
> CMDx automatically maps result statuses to
|
132
|
+
> CMDx automatically maps result statuses to log severity levels. Manual overrides are not recommended as they break monitoring conventions.
|
121
133
|
|
122
|
-
|
|
123
|
-
|
124
|
-
| `success`
|
125
|
-
| `skipped`
|
126
|
-
| `failed`
|
134
|
+
| Status | Log Level | When Used |
|
135
|
+
|--------|-----------|-----------|
|
136
|
+
| `success` | `INFO` | Normal completion |
|
137
|
+
| `skipped` | `WARN` | Intentional skip via business logic |
|
138
|
+
| `failed` | `ERROR` | Task failure or exception |
|
127
139
|
|
128
140
|
## Manual Logging
|
129
141
|
|
130
|
-
Access the configured logger within tasks for custom log messages:
|
131
|
-
|
132
142
|
```ruby
|
133
143
|
class ProcessOrderTask < CMDx::Task
|
134
144
|
def call
|
145
|
+
# Structured logging with metadata
|
135
146
|
logger.info "Starting order processing", order_id: context.order_id
|
136
147
|
|
137
148
|
# Performance-optimized debug logging
|
138
149
|
logger.debug { "Order details: #{context.order.inspect}" }
|
139
150
|
|
140
|
-
#
|
141
|
-
logger.info "Payment processed", {
|
142
|
-
order_id: context.order_id,
|
143
|
-
amount: context.order.total,
|
144
|
-
payment_method: context.payment_method
|
145
|
-
}
|
146
|
-
|
147
|
-
# Exception handling with logging
|
151
|
+
# Exception context
|
148
152
|
begin
|
149
153
|
validate_inventory
|
150
154
|
rescue StandardError => e
|
151
|
-
logger.error "Inventory validation failed
|
155
|
+
logger.error "Inventory validation failed", {
|
152
156
|
exception: e.class.name,
|
153
|
-
order_id: context.order_id
|
157
|
+
order_id: context.order_id,
|
158
|
+
message: e.message
|
154
159
|
}
|
155
160
|
raise
|
156
161
|
end
|
162
|
+
|
163
|
+
# Success with metadata
|
164
|
+
logger.info "Order processed successfully", {
|
165
|
+
order_id: context.order_id,
|
166
|
+
amount: context.order.total
|
167
|
+
}
|
157
168
|
end
|
158
169
|
end
|
159
170
|
```
|
160
171
|
|
161
|
-
##
|
172
|
+
## Error Handling
|
162
173
|
|
163
|
-
|
174
|
+
> [!WARNING]
|
175
|
+
> Logger configuration errors are handled gracefully, falling back to STDOUT with PrettyLine formatter to ensure execution continuity.
|
164
176
|
|
165
|
-
|
177
|
+
### Configuration Error Recovery
|
166
178
|
|
167
179
|
```ruby
|
168
|
-
|
180
|
+
# Invalid logger configuration
|
181
|
+
CMDx.configure do |config|
|
182
|
+
config.logger = Logger.new("/invalid/path/cmdx.log") # Permission denied
|
183
|
+
end
|
184
|
+
|
185
|
+
# CMDx automatically falls back to:
|
186
|
+
# Logger.new(STDOUT, formatter: CMDx::LogFormatters::PrettyLine.new)
|
187
|
+
```
|
188
|
+
|
189
|
+
### Formatter Error Handling
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
class BrokenFormatter
|
193
|
+
def call(severity, time, task, message)
|
194
|
+
raise StandardError, "Formatter error"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
class TestTask < CMDx::Task
|
199
|
+
cmd_settings!(log_formatter: BrokenFormatter.new)
|
200
|
+
|
201
|
+
def call
|
202
|
+
# Execution continues with fallback formatter
|
203
|
+
# Error logged to STDERR for debugging
|
204
|
+
end
|
205
|
+
end
|
206
|
+
```
|
207
|
+
|
208
|
+
### Log Level Validation
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
# Invalid log levels default to INFO
|
212
|
+
CMDx.configure do |config|
|
213
|
+
config.log_level = "INVALID" # → Logger::INFO
|
214
|
+
end
|
215
|
+
|
216
|
+
# Valid levels: DEBUG, INFO, WARN, ERROR, FATAL
|
217
|
+
```
|
218
|
+
|
219
|
+
## Advanced Usage
|
220
|
+
|
221
|
+
### Custom Formatters
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
class AlertFormatter
|
169
225
|
def call(severity, time, task, message)
|
170
226
|
emoji = case severity
|
171
227
|
when 'INFO' then '✅'
|
@@ -174,21 +230,23 @@ class SlackLogFormatter
|
|
174
230
|
else '📝'
|
175
231
|
end
|
176
232
|
|
177
|
-
"#{emoji} #{task.class.name}: #{message}\n"
|
233
|
+
"[#{time.strftime('%H:%M:%S')}] #{emoji} #{task.class.name}: #{message}\n"
|
178
234
|
end
|
179
235
|
end
|
180
236
|
|
181
|
-
class
|
182
|
-
|
183
|
-
|
184
|
-
|
237
|
+
class NotificationTask < CMDx::Task
|
238
|
+
cmd_settings!(log_formatter: AlertFormatter.new)
|
239
|
+
|
240
|
+
def call
|
241
|
+
# Uses custom emoji-based formatting
|
242
|
+
end
|
185
243
|
end
|
186
244
|
```
|
187
245
|
|
188
246
|
### Multi-Destination Logging
|
189
247
|
|
190
248
|
> [!TIP]
|
191
|
-
>
|
249
|
+
> Combine multiple loggers to output to both console and files simultaneously during development.
|
192
250
|
|
193
251
|
```ruby
|
194
252
|
class MultiLogger
|
@@ -197,21 +255,13 @@ class MultiLogger
|
|
197
255
|
end
|
198
256
|
|
199
257
|
%w[debug info warn error fatal].each do |level|
|
200
|
-
define_method(level) do |message = nil, &block|
|
201
|
-
@loggers.each { |logger| logger.send(level, message, &block) }
|
258
|
+
define_method(level) do |message = nil, **metadata, &block|
|
259
|
+
@loggers.each { |logger| logger.send(level, message, **metadata, &block) }
|
202
260
|
end
|
203
261
|
end
|
204
|
-
|
205
|
-
def formatter=(formatter)
|
206
|
-
@loggers.each { |logger| logger.formatter = formatter }
|
207
|
-
end
|
208
|
-
|
209
|
-
def level=(level)
|
210
|
-
@loggers.each { |logger| logger.level = level }
|
211
|
-
end
|
212
262
|
end
|
213
263
|
|
214
|
-
#
|
264
|
+
# Configuration
|
215
265
|
CMDx.configure do |config|
|
216
266
|
config.logger = MultiLogger.new(
|
217
267
|
Logger.new(STDOUT, formatter: CMDx::LogFormatters::PrettyLine.new),
|
@@ -222,32 +272,45 @@ end
|
|
222
272
|
|
223
273
|
## Log Data Structure
|
224
274
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
275
|
+
> [!NOTE]
|
276
|
+
> All log entries include comprehensive execution metadata for debugging and monitoring. Field availability depends on the execution context.
|
277
|
+
|
278
|
+
### Core Fields
|
279
|
+
|
280
|
+
| Field | Description | Example |
|
281
|
+
|-------|-------------|---------|
|
282
|
+
| `severity` | Log level | `INFO`, `WARN`, `ERROR` |
|
283
|
+
| `timestamp` | ISO 8601 execution time | `2022-07-17T18:43:15.000000` |
|
284
|
+
| `pid` | Process ID | `3784` |
|
285
|
+
| `origin` | Source identifier | `CMDx` |
|
286
|
+
|
287
|
+
### Task Information
|
288
|
+
|
289
|
+
| Field | Description | Example |
|
290
|
+
|-------|-------------|---------|
|
291
|
+
| `index` | Execution sequence position | `0`, `1`, `2` |
|
292
|
+
| `chain_id` | Unique execution chain ID | `018c2b95-b764-7615...` |
|
293
|
+
| `type` | Execution unit type | `Task`, `Workflow` |
|
294
|
+
| `class` | Task class name | `ProcessOrderTask` |
|
295
|
+
| `id` | Unique task instance ID | `018c2b95-b764-7615...` |
|
296
|
+
| `tags` | Custom categorization | `["priority", "payment"]` |
|
297
|
+
|
298
|
+
### Execution Data
|
299
|
+
|
300
|
+
| Field | Description | Example |
|
301
|
+
|-------|-------------|---------|
|
302
|
+
| `state` | Lifecycle state | `complete`, `interrupted` |
|
303
|
+
| `status` | Business outcome | `success`, `skipped`, `failed` |
|
304
|
+
| `outcome` | Final classification | `success`, `interrupted` |
|
305
|
+
| `metadata` | Custom task data | `{order_id: 123, amount: 99.99}` |
|
306
|
+
| `runtime` | Execution time (seconds) | `0.45` |
|
307
|
+
|
308
|
+
### Failure Chain (Workflows)
|
309
|
+
|
310
|
+
| Field | Description |
|
311
|
+
|-------|-------------|
|
312
|
+
| `caused_failure` | Original failing task details |
|
313
|
+
| `threw_failure` | Task that propagated the failure |
|
251
314
|
|
252
315
|
---
|
253
316
|
|