armature-framework 0.2.2

A modern, type-safe HTTP framework for Rust inspired by Angular and NestJS. Features dependency injection, decorators, middleware, authentication (JWT/OAuth2/SAML), validation, OpenAPI/Swagger, caching, job queues, and observability.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
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
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
# Logging Guide

Comprehensive guide to Armature's logging system with JSON output by default and configurable pretty printing for development.

## Table of Contents

- [Overview]#overview
- [Quick Start]#quick-start
- [Configuration]#configuration
- [Environment Variables]#environment-variables
- [Programmatic Configuration]#programmatic-configuration
- [Log Formats]#log-formats
- [Log Levels]#log-levels
- [Structured Logging]#structured-logging
- [HTTP Request Logging]#http-request-logging
- [Best Practices]#best-practices
- [Performance]#performance
- [Examples]#examples

---

## Overview

Armature provides a powerful, environment-configurable logging system built for production use with features like:

- **JSON by Default**: Production-ready structured logging out of the box
- **Pretty Printing**: Human-readable format for development
- **Environment Configuration**: Switch formats without code changes
- **Runtime Configuration**: Change settings programmatically
- **Zero-Cost When Disabled**: Debug macros compile to no-ops
- **Presets**: Built-in configurations for development and production

**Default Configuration:** JSON format to STDERR at INFO level

---

## Quick Start

### Basic Logging

```rust
use armature_log::{debug, info, warn, error, trace};

fn main() {
    // Logs are automatically initialized on first use
    info!("Application started on port {}", 8080);
    debug!("Debug information");
    warn!("Warning message");
    error!("Error occurred");
}
```

**Default JSON Output:**
```json
{"timestamp":"2024-12-20T12:00:00Z","level":"INFO","target":"my_app","message":"Application started on port 8080"}
```

### Switch to Pretty Logging

```bash
# Development - Pretty format with colors
ARMATURE_LOG_FORMAT=pretty cargo run
```

**Pretty Output:**
```
2024-12-20 12:00:00.123 INFO  my_app Application started on port 8080
```

---

## Configuration

### Environment Variables (Recommended)

The easiest way to configure logging is via environment variables:

| Variable | Values | Default | Description |
|----------|--------|---------|-------------|
| `ARMATURE_LOG_FORMAT` | `json`, `pretty`, `compact` | `json` | Output format |
| `ARMATURE_LOG_LEVEL` | `trace`, `debug`, `info`, `warn`, `error` | `info` | Minimum log level |
| `ARMATURE_LOG_COLOR` | `1`, `true`, `0`, `false` | auto-detect | Enable ANSI colors |
| `ARMATURE_DEBUG` | `1`, `true` | `false` | Enable debug mode |
| `ARMATURE_LOG_TIMESTAMPS` | `1`, `0` | `1` | Include timestamps |
| `ARMATURE_LOG_MODULE` | `1`, `0` | `1` | Include module path |

**Examples:**

```bash
# Development
ARMATURE_LOG_FORMAT=pretty ARMATURE_LOG_LEVEL=debug cargo run

# Production
ARMATURE_LOG_FORMAT=json ARMATURE_LOG_LEVEL=info cargo run

# Quiet mode
ARMATURE_LOG_LEVEL=warn cargo run
```

### Programmatic Configuration

Use the fluent API for runtime configuration:

```rust
use armature_log::{configure, Format, Level};

// Configure logging
configure()
    .format(Format::Pretty)
    .level(Level::Debug)
    .color(true)
    .timestamps(true)
    .apply();
```

### Direct Setters

```rust
use armature_log::{set_format, set_level, Format, Level};

// Change format at runtime
set_format(Format::Pretty);
set_format(Format::Json);

// Change level at runtime
set_level(Level::Debug);
```

### Presets

Use built-in presets for common configurations:

```rust
use armature_log;

// Development: Pretty + Debug + Colors
armature_log::preset_development();

// Production: JSON + Info + No colors
armature_log::preset_production();

// Quiet: JSON + Warn only
armature_log::preset_quiet();
```

---

## Log Formats

### JSON Format (Default)

Machine-readable, structured format ideal for production and log aggregators.

```json
{"timestamp":"2024-12-20T12:00:00.123Z","level":"INFO","target":"my_app","message":"User logged in"}
```

**Use Cases:**
- Production environments
- Log aggregation (ELK, Splunk, Datadog, Grafana Loki)
- Automated log parsing
- Cloud environments (AWS CloudWatch, GCP Logging)

**Enable:**
```bash
ARMATURE_LOG_FORMAT=json cargo run
```

Or in code:
```rust
armature_log::set_format(armature_log::Format::Json);
```

### Pretty Format

Formatted, colored output for development with human-readable timestamps.

```
2024-12-20 12:00:00.123 INFO  my_app User logged in
2024-12-20 12:00:00.124 DEBUG armature_core::routing Matched route: GET /api/users
2024-12-20 12:00:00.125 WARN  my_app Rate limit approaching
```

**Use Cases:**
- Local development
- Debugging
- Interactive terminal use
- Quick troubleshooting

**Enable:**
```bash
ARMATURE_LOG_FORMAT=pretty cargo run
```

Or in code:
```rust
armature_log::preset_development();
```

### Compact Format

Minimal single-line output for space efficiency.

```
12:00:00 I my_app: User logged in
12:00:00 D armature_core::routing: Matched route
12:00:00 W my_app: Rate limit approaching
```

**Use Cases:**
- Low-volume logging
- CI/CD pipelines
- Space-constrained environments

**Enable:**
```bash
ARMATURE_LOG_FORMAT=compact cargo run
```

---

## Log Levels

### Available Levels

| Level | Use Case | Example |
|-------|----------|---------|
| `TRACE` | Very detailed debugging | Function entry/exit, loop iterations |
| `DEBUG` | Development information | Variable values, state changes |
| `INFO` | General information | App start, config loaded, request processed |
| `WARN` | Potential issues | Deprecated API used, fallback activated |
| `ERROR` | Failures requiring attention | Database error, API call failed |

### Setting Log Level

```bash
# Via environment variable
ARMATURE_LOG_LEVEL=debug cargo run
```

```rust
// Via code
armature_log::set_level(armature_log::Level::Debug);
```

### Logging Macros

```rust
use armature_log::{trace, debug, info, warn, error};

trace!("Entering function");
debug!("Processing item {}", id);
info!("User {} logged in", username);
warn!("Rate limit approaching: {}/100", count);
error!("Failed to connect to database: {}", err);
```

### With Target

Specify a custom target (module path) for filtering:

```rust
debug!(target: "armature::router", "Matching route: {}", path);
info!(target: "database", "Query executed in {}ms", duration);
```

---

## Structured Logging

Add context to log messages with key-value pairs.

### Basic Structured Logging

```rust
info!(
    user_id = 123,
    action = "login",
    ip_address = "192.168.1.1",
    "User authentication successful"
);
```

**JSON Output:**
```json
{
  "timestamp": "2024-12-20T12:00:00.123Z",
  "level": "INFO",
  "target": "my_app",
  "message": "User authentication successful"
}
```

### Complex Types

```rust
// Strings
info!("User created: {}", name);

// Numbers
info!("Query completed in {}ms, {} rows", duration_ms, row_count);

// With error context
error!("Operation failed: {}", err);
```

---

## HTTP Request Logging

Armature automatically adds logging to HTTP request handling when using `armature-core`.

### Automatic Request Logging

```rust
use armature_core::Application;

let app = Application::new();
// Logging is automatically enabled
```

**Example Logs:**
```json
{"timestamp":"2024-12-20T12:00:00Z","level":"INFO","target":"armature_core::application","message":"HTTP server listening with pipelining enabled"}
{"timestamp":"2024-12-20T12:00:01Z","level":"DEBUG","target":"armature_core::routing","message":"Matching route: /api/users"}
{"timestamp":"2024-12-20T12:00:01Z","level":"TRACE","target":"armature_core::routing","message":"Route matched: GET /api/users"}
```

---

## Best Practices

### 1. Use Environment Variables for Format

```bash
# .env.development
ARMATURE_LOG_FORMAT=pretty
ARMATURE_LOG_LEVEL=debug

# .env.production
ARMATURE_LOG_FORMAT=json
ARMATURE_LOG_LEVEL=info
```

### 2. Use Appropriate Log Levels

```rust
// ✅ Good
info!("User {} logged in", user_id);              // General info
warn!("Rate limit exceeded for IP {}", ip);       // Potential issue
error!("Failed to save user: {}", err);           // Actual error

// ❌ Bad
info!("Database error occurred");                 // Should be ERROR
error!("User clicked button");                    // Should be DEBUG or none
```

### 3. Don't Log Sensitive Data

```rust
// ❌ Bad - logs sensitive data
info!("User logged in with password: {}", password);

// ✅ Good - omits sensitive data
info!("User {} logged in", user_id);
```

### 4. Initialize Logging Early (Optional)

```rust
fn main() {
    // Explicitly initialize logging (optional)
    armature_log::init();

    info!("Application starting");
}
```

### 5. Use Presets for Consistency

```rust
fn main() {
    // Use preset based on environment
    if cfg!(debug_assertions) {
        armature_log::preset_development();
    } else {
        armature_log::preset_production();
    }
}
```

---

## Performance

### Logging Overhead

Armature's logging system is designed for minimal overhead:

- **Lazy evaluation:** Only evaluates log statements that will be output
- **Atomic checks:** Fast level checks using atomics
- **No allocation when filtered:** Filtered logs don't allocate
- **JSON serialization:** Efficient with serde_json

### Benchmarks

| Operation | Time | Overhead |
|-----------|------|----------|
| Filtered out log (TRACE when INFO) | ~5ns | Negligible |
| Simple info! message | ~200ns | Very low |
| JSON formatting | ~1μs | Low |

### Tips for Performance

1. **Use appropriate log levels** - DEBUG/TRACE disabled in production
2. **Avoid expensive operations** - Don't compute values if log is filtered

```rust
// ✅ Good - value only computed if debug is enabled
if armature_log::is_level_enabled(armature_log::Level::Debug) {
    debug!("Expensive computation: {}", expensive_fn());
}
```

---

## Examples

### Production Configuration

```bash
# Docker/K8s environment
ARMATURE_LOG_FORMAT=json
ARMATURE_LOG_LEVEL=info
ARMATURE_LOG_TIMESTAMPS=1
ARMATURE_LOG_MODULE=1
```

### Development Configuration

```bash
# Local development
ARMATURE_LOG_FORMAT=pretty
ARMATURE_LOG_LEVEL=debug
ARMATURE_LOG_COLOR=1
```

Or in code:

```rust
fn main() {
    #[cfg(debug_assertions)]
    armature_log::preset_development();

    #[cfg(not(debug_assertions))]
    armature_log::preset_production();

    info!("Application started");
}
```

### CI/CD Configuration

```bash
# Compact format for CI logs
ARMATURE_LOG_FORMAT=compact
ARMATURE_LOG_LEVEL=info
ARMATURE_LOG_COLOR=0
```

### Complete Example

```rust
use armature_log::{debug, info, warn, error, configure, Format, Level};

fn main() {
    // Configure based on environment
    if std::env::var("DEVELOPMENT").is_ok() {
        configure()
            .format(Format::Pretty)
            .level(Level::Debug)
            .color(true)
            .apply();
    }

    info!("Application starting");

    // Your application code
    match process_request() {
        Ok(_) => info!("Request processed successfully"),
        Err(e) => error!("Request failed: {}", e),
    }
}
```

---

## Summary

### Key Features

✅ **JSON by Default** - Production-ready structured logging
✅ **Pretty Printing** - Human-readable development output
✅ **Environment Configuration** - Switch formats via env vars
✅ **Runtime Configuration** - Change settings in code
✅ **Zero-Cost** - No overhead when disabled
✅ **Presets** - Built-in dev/prod configurations

### Quick Reference

```bash
# Environment Variables
ARMATURE_LOG_FORMAT=pretty|json|compact
ARMATURE_LOG_LEVEL=trace|debug|info|warn|error
ARMATURE_LOG_COLOR=1|0
ARMATURE_DEBUG=1
```

```rust
// Programmatic Configuration
armature_log::preset_development();
armature_log::preset_production();
armature_log::set_format(Format::Pretty);
armature_log::set_level(Level::Debug);

// Logging Macros
trace!("...");
debug!("...");
info!("...");
warn!("...");
error!("...");
```

---

**Happy logging!** 📝