Rust Guide
Installation
bash
cmake -B build -DCMAKE_BUILD_TYPE=Release cmake --build build -j$(nproc) cmake --install build --prefix ~/.local export PKG_CONFIG_PATH="$HOME/.local/lib/pkgconfig:$PKG_CONFIG_PATH" export LD_LIBRARY_PATH="$HOME/.local/lib:$LD_LIBRARY_PATH" cd source/bindings/rust cargo build --release
Config
rust
use ddstream::{Config, DDStream};
use std::time::{SystemTime, UNIX_EPOCH};
let now = SystemTime::now()
.duration_since(UNIX_EPOCH).unwrap().as_secs() as i64;
let cfg = Config {
api_key: "YOUR_DD_API_KEY".into(),
app_key: "YOUR_DD_APP_KEY".into(),
query: "avg:system.cpu.user{*}".into(),
range_start: now - 86400,
range_end: now,
granularity: 60,
chunk_seconds: 14400,
enable_prefetch: true,
..Config::default()
};
// Validate credentials
if let Err(e) = DDStream::validate(&cfg) {
eprintln!("Invalid credentials: {}", e);
return;
}Iterator Trait
DDStream exposes an iter() method returning an iterator of
Result<Batch, String>. Use ? or match to handle errors.
rust
let mut stream = DDStream::new(cfg).expect("failed to create stream");
for result in stream.iter() {
let batch = result.expect("stream error");
println!("Batch: {} points", batch.points.len());
let sum_avg: f64 = batch.points.iter().map(|p| p.avg).sum();
let mean = sum_avg / batch.points.len() as f64;
println!(" mean avg: {:.2}%", mean);
if batch.is_last { break; }
}Explicit pull with full error handling:
rust
stream.reset();
loop {
match stream.next_batch() {
Err(e) => { eprintln!("Error: {}", e); break; }
Ok(None) => break, // exhausted
Ok(Some(b)) => {
process_batch(&b);
if b.is_last { break; }
}
}
}Ownership & Drop
Batch.points is a Box<[DDPoint]> - owned heap memory transferred out of
the C++ layer. It is freed automatically when the Batch is dropped.
DDStream also implements Drop to call ddstream_destroy() on the
underlying handle.
rust
{
let batch = stream.next_batch().unwrap().unwrap();
// batch.points is Box<[DDPoint]>
let first = &batch.points[0];
println!("t={}, avg={}", first.timestamp, first.avg);
// batch dropped here → Box freed
}
// stream dropped at end of scope → ddstream_destroy() calledSend / Sync
DDStream is Send but not Sync
DDStream can be moved to another thread (Send) but cannot be shared
across threads without external locking (not Sync). This mirrors the C++
BatchManager contract: not thread-safe for concurrent callers, but safe
to move between threads.
rust
// OK: move stream to a thread
let handle = std::thread::spawn(move || {
for result in stream.iter() {
// process ...
}
});
// NOT OK: sharing across threads without Mutex
// let arc = Arc::new(stream); // compile error: DDStream is not Sync