Skip to content

Commit be2e862

Browse files
author
MJarmo
committed
POC for go auditlog sdk
1 parent 81aeace commit be2e862

File tree

8 files changed

+2412
-173
lines changed

8 files changed

+2412
-173
lines changed

sdk/log/AUDIT_LOG_README.md

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
# Audit Log Storage for OpenTelemetry Go SDK
2+
3+
This package provides audit log storage capabilities for the OpenTelemetry Go SDK, similar to the Java implementation. It includes persistent storage, priority-based processing, and retry mechanisms for reliable audit logging.
4+
5+
## Features
6+
7+
- **Persistent Storage**: File-based storage that survives application restarts
8+
- **Priority Processing**: Higher severity logs are processed first
9+
- **Retry Logic**: Automatic retry with exponential backoff for failed exports
10+
- **Batch Processing**: Configurable batch sizes for efficient export
11+
- **Thread-Safe**: Concurrent access support with proper locking
12+
- **Exception Handling**: Customizable error handling for audit failures
13+
- **Memory Store**: In-memory implementation for testing and development
14+
15+
## Components
16+
17+
### AuditLogStore Interface
18+
19+
The `AuditLogStore` interface provides the core storage functionality:
20+
21+
```go
22+
type AuditLogStore interface {
23+
Save(ctx context.Context, record *Record) error
24+
RemoveAll(ctx context.Context, records []Record) error
25+
GetAll(ctx context.Context) ([]Record, error)
26+
}
27+
```
28+
29+
### Implementations
30+
31+
#### AuditLogFileStore
32+
33+
File-based persistent storage that writes audit logs to disk:
34+
35+
```go
36+
store, err := NewAuditLogFileStore("/path/to/audit/logs")
37+
if err != nil {
38+
log.Fatal(err)
39+
}
40+
```
41+
42+
#### AuditLogInMemoryStore
43+
44+
In-memory storage for testing and development:
45+
46+
```go
47+
store := NewAuditLogInMemoryStore()
48+
```
49+
50+
### AuditLogProcessor
51+
52+
The `AuditLogProcessor` implements the `Processor` interface and provides:
53+
54+
- Priority-based processing (higher severity first)
55+
- Automatic retry with exponential backoff
56+
- Batch processing with configurable sizes
57+
- Background processing with periodic exports
58+
- Graceful shutdown with remaining log export
59+
60+
### Configuration
61+
62+
Use the `AuditLogProcessorBuilder` to configure the processor:
63+
64+
```go
65+
processor, err := NewAuditLogProcessorBuilder(exporter, store).
66+
SetScheduleDelay(100 * time.Millisecond).
67+
SetMaxExportBatchSize(512).
68+
SetExporterTimeout(30 * time.Second).
69+
SetRetryPolicy(RetryPolicy{
70+
MaxAttempts: 3,
71+
InitialBackoff: time.Second,
72+
MaxBackoff: time.Minute,
73+
BackoffMultiplier: 2.0,
74+
}).
75+
SetWaitOnExport(false).
76+
Build()
77+
```
78+
79+
## Usage Examples
80+
81+
### Basic Usage
82+
83+
```go
84+
package main
85+
86+
import (
87+
"context"
88+
"log"
89+
"time"
90+
91+
"go.opentelemetry.io/otel/log"
92+
"go.opentelemetry.io/otel/sdk/log"
93+
)
94+
95+
func main() {
96+
// Create audit log store
97+
store, err := log.NewAuditLogFileStore("/var/log/audit")
98+
if err != nil {
99+
log.Fatal(err)
100+
}
101+
102+
// Create exporter (your actual exporter implementation)
103+
exporter := yourExporter
104+
105+
// Create processor
106+
processor, err := log.NewAuditLogProcessorBuilder(exporter, store).
107+
SetScheduleDelay(time.Second).
108+
SetMaxExportBatchSize(100).
109+
Build()
110+
if err != nil {
111+
log.Fatal(err)
112+
}
113+
defer processor.Shutdown(context.Background())
114+
115+
// Create logger with audit processor
116+
logger := log.NewLogger(processor)
117+
118+
// Log audit events
119+
record := &log.Record{
120+
Timestamp: time.Now(),
121+
Severity: log.SeverityInfo,
122+
Body: log.StringValue("User login attempt"),
123+
}
124+
record.AddAttributes(log.String("user_id", "12345"))
125+
126+
if err := logger.Emit(context.Background(), record); err != nil {
127+
log.Printf("Failed to emit audit log: %v", err)
128+
}
129+
}
130+
```
131+
132+
### Custom Exception Handling
133+
134+
```go
135+
type CustomAuditHandler struct {
136+
alertService AlertService
137+
}
138+
139+
func (h *CustomAuditHandler) Handle(exception *log.AuditException) {
140+
// Send alert for audit failures
141+
h.alertService.SendAlert(fmt.Sprintf(
142+
"Audit log export failed: %s", exception.Message))
143+
144+
// Log the exception
145+
log.Printf("Audit exception: %v", exception)
146+
}
147+
148+
// Use in processor
149+
processor, err := log.NewAuditLogProcessorBuilder(exporter, store).
150+
SetExceptionHandler(&CustomAuditHandler{alertService: alerts}).
151+
Build()
152+
```
153+
154+
### Testing with In-Memory Store
155+
156+
```go
157+
func TestAuditLogging(t *testing.T) {
158+
store := log.NewAuditLogInMemoryStore()
159+
exporter := NewMockExporter()
160+
161+
processor, err := log.NewAuditLogProcessorBuilder(exporter, store).
162+
SetScheduleDelay(10 * time.Millisecond).
163+
Build()
164+
if err != nil {
165+
t.Fatal(err)
166+
}
167+
defer processor.Shutdown(context.Background())
168+
169+
// Test audit logging
170+
record := createTestAuditRecord("test event", log.SeverityInfo)
171+
if err := processor.OnEmit(context.Background(), &record); err != nil {
172+
t.Fatalf("Failed to emit record: %v", err)
173+
}
174+
175+
// Wait for processing
176+
time.Sleep(50 * time.Millisecond)
177+
178+
// Verify export
179+
if exporter.GetExportCount() == 0 {
180+
t.Error("Expected record to be exported")
181+
}
182+
}
183+
```
184+
185+
## Configuration Options
186+
187+
### AuditLogProcessorConfig
188+
189+
| Option | Type | Default | Description |
190+
|--------|------|---------|-------------|
191+
| `ScheduleDelay` | `time.Duration` | `1s` | Delay between periodic exports |
192+
| `MaxExportBatchSize` | `int` | `512` | Maximum records per export batch |
193+
| `ExporterTimeout` | `time.Duration` | `30s` | Timeout for export operations |
194+
| `WaitOnExport` | `bool` | `false` | Whether to wait for exports to complete |
195+
| `RetryPolicy` | `RetryPolicy` | See below | Retry configuration |
196+
197+
### RetryPolicy
198+
199+
| Option | Type | Default | Description |
200+
|--------|------|---------|-------------|
201+
| `MaxAttempts` | `int` | `3` | Maximum retry attempts |
202+
| `InitialBackoff` | `time.Duration` | `1s` | Initial backoff duration |
203+
| `MaxBackoff` | `time.Duration` | `1m` | Maximum backoff duration |
204+
| `BackoffMultiplier` | `float64` | `2.0` | Backoff multiplier |
205+
206+
## Priority Processing
207+
208+
Logs are processed in priority order based on severity:
209+
210+
1. **Fatal** (Priority 6) - Highest priority
211+
2. **Error** (Priority 5)
212+
3. **Warn** (Priority 4)
213+
4. **Info** (Priority 3)
214+
5. **Debug** (Priority 2)
215+
6. **Trace** (Priority 1) - Lowest priority
216+
217+
## File Storage Format
218+
219+
Audit logs are stored as JSON lines, one record per line:
220+
221+
```json
222+
{"timestamp":"2023-12-07T10:30:00Z","severity":"INFO","body":"User login","attributes":[{"key":"user_id","value":"12345"}]}
223+
{"timestamp":"2023-12-07T10:31:00Z","severity":"ERROR","body":"Authentication failed","attributes":[{"key":"user_id","value":"67890"}]}
224+
```
225+
226+
## Error Handling
227+
228+
The audit log processor includes comprehensive error handling:
229+
230+
- **Storage Errors**: Automatically handled with retry logic
231+
- **Export Errors**: Retry with exponential backoff
232+
- **Configuration Errors**: Validation with clear error messages
233+
- **Shutdown Errors**: Graceful handling of shutdown scenarios
234+
235+
## Performance Considerations
236+
237+
- **Batch Processing**: Reduces overhead by processing multiple records together
238+
- **Priority Queue**: Efficient processing of high-priority logs first
239+
- **Async Processing**: Non-blocking log emission with background export
240+
- **File I/O**: Optimized for append-only operations
241+
- **Memory Usage**: Configurable batch sizes to control memory consumption
242+
243+
## Security Considerations
244+
245+
- **File Permissions**: Ensure audit log files have appropriate permissions
246+
- **Disk Space**: Monitor disk usage for audit log files
247+
- **Retention**: Implement log rotation and cleanup policies
248+
- **Encryption**: Consider encrypting audit log files at rest
249+
- **Access Control**: Restrict access to audit log files and directories
250+
251+
## Migration from Java Implementation
252+
253+
This Go implementation provides equivalent functionality to the Java audit log implementation:
254+
255+
| Java Component | Go Equivalent |
256+
|----------------|---------------|
257+
| `AuditLogStore` | `AuditLogStore` interface |
258+
| `AuditLogFileStore` | `AuditLogFileStore` |
259+
| `AuditLogRecordProcessor` | `AuditLogProcessor` |
260+
| `AuditException` | `AuditException` |
261+
| `AuditExceptionHandler` | `AuditExceptionHandler` |
262+
| `RetryPolicy` | `RetryPolicy` |
263+
264+
## Contributing
265+
266+
When contributing to the audit log functionality:
267+
268+
1. Add tests for new features
269+
2. Update documentation
270+
3. Ensure thread safety
271+
4. Follow Go best practices
272+
5. Consider performance implications
273+
6. Test with both file and in-memory stores
274+
275+
## License
276+
277+
This code is licensed under the Apache License 2.0, same as the OpenTelemetry project.

0 commit comments

Comments
 (0)