Caudal SDK (Rust)
Observability SDK for event-driven distributed systems.
What is Caudal?
Caudal is an observability system for event flows. It is NOT a broker, it DOES NOT participate in the critical path, and it DOES NOT guarantee delivery. It only observes, records, and correlates events describing how a message flows through a distributed system.
Features
- ✅ Append-only: Only records events, never modifies them.
- ✅ Event-only: Does not transport business payloads.
- ✅ Non-blocking: BufferedEmitter for non-blocking emission.
- ✅ Idempotent: Safe for retries.
- ✅ Production-safe: Never breaks the system using it.
- ✅ Transport-agnostic: Decoupled through traits.
- ✅ Kafka/Redpanda: Optional implementation via feature flag.
- ✅ Async support: Support for async/await.
- ✅ Metrics: Internal emission metrics.
Installation
Add this to your Cargo.toml:
[]
= "0.1.0"
# With JSON serialization
= { = "0.1.0", = ["serde_json"] }
# With Kafka support
= { = "0.1.0", = ["kafka"] }
# With async support
= { = "0.1.0", = ["async-runtime"] }
# All features
= { = "0.1.0", = ["serde_json", "kafka", "async-runtime"] }
Basic Usage
Creating and Emitting Events
use ;
// Create an event (flow_id is required and represents the logical unit)
let event = new
.group_flow // Optional: grouping for Realtime/UI
.node
.stage
.status
.ack
.payload_bytes // Optional: Logical size
.input_bytes // Optional: Input bytes
.output_bytes // Optional: Output bytes
.meta
.build?;
// event_id is generated automatically as UUID v4 if not specified
// Emit with custom transport
let emitter = new;
emitter.emit_strict?;
// Or best-effort mode (never fails)
emitter.emit_best_effort;
BufferedEmitter (Non-Blocking)
use BufferedEmitter;
use ;
let config = BufferedConfig ;
let emitter = new;
// Emit without blocking (never fails)
emitter.emit_best_effort;
// Get metrics
let metrics = emitter.metrics;
println!;
Kafka Transport
use ;
let config = KafkaConfig ;
let transport = new?;
let emitter = new;
Features
| Feature | Description | Dependencies |
|---|---|---|
serde_json |
JSON serialization of events | serde_json |
kafka |
Kafka/Redpanda transport | rdkafka, tokio |
async-runtime |
async/await support | async-trait, tokio |
tracing |
Integration with tracing | tracing |
FlowEvent v1 Contract
Each event includes:
Enums
- NodeType:
Producer,Bridge,Consumer,Storage,External - FlowStage:
Ingress,Emit,Bridge,Consume,Process,Persist,Egress,Error - FlowStatus:
Sent,Received,Ack,Nack,Timeout,Skipped - AckType:
None,Implicit,Explicit,Bridge
Canonical Event Pattern
Applications SHOULD:
- Define domain events explicitly: Model your business events clearly before emitting flow events.
- Emit a single "processed" event per flow: Each flow should have one definitive completion event.
- Emit explicit ACK events for external systems: When integrating with external services, emit explicit acknowledgment events.
- Correlate using flow_id: Use the same
flow_idacross all events in a single flow for proper correlation.
Example Flow
let flow_id = "order-processing";
let group = "siscom";
// 1. Ingress event
let ingress = new
.group_flow
.node
.stage
.status
.build?;
// 2. Processing event
let processing = new
.group_flow
.node
.stage
.status
.build?;
// 3. External ACK event
let ack = new
.group_flow
.node
.stage
.status
.ack
.build?;
// 4. Final "processed" event
let processed = new
.group_flow
.node
.stage
.status
.meta
.build?;
Implementing a Transport
use ;
use Result;
Kafka Configuration
let config = KafkaConfig ;
Acks Configuration
"all"or"-1": Maximum durability (waits for all replicas)"1": Waits only for the leader"0": Fire-and-forget (no acknowledgment)
Guarantees and Limitations
✅ Guarantees
- Non-blocking: BufferedEmitter never blocks the production thread.
- Production-safe: Manageable errors, never panics.
- Idempotent: Safe for retries.
- Thread-safe: All components are Send + Sync.
⚠️ Limitations
- Best-effort: Does not guarantee delivery (it is not a broker).
- Non-transactional: Does not participate in distributed transactions.
- Metadata only: Does not send business payloads.
- Append-only: Does not modify or delete events.
Examples
See the examples/ directory for full examples:
# Basic example
# BufferedEmitter
# Kafka producer (requires local Kafka)
Testing
# Unit tests
# Tests with all features
# Clippy
# Format
Roadmap
- FlowEvent v1 Contract
- Ergonomic Builder
- Abstract Transport (traits)
- Non-blocking BufferedEmitter
- Kafka/Redpanda Implementation
- async/await Support
- JSON Serialization
- Unit Tests
- Configurable retry policies
- Circuit breaker
- Prometheus metrics
- Intelligent batching
- Event compression
[!NOTE] Future versions may provide helper builders for common patterns, once enough real-world usage patterns are validated.
License
MIT OR Apache-2.0
Contributing
Contributions are welcome! Please open an issue or PR.
Support
- 📖 Documentación
- 🐛 Issues
- 💬 Discussions