# Master Log Rust Client
Rust client for sending structured logs to Master Log. It mirrors the Python client’s core shape: environment configuration, a `configure()` function that takes precedence over env values, simple module-level logging helpers, explicit client instances, automatic host/process metadata, TTL support, background batching, flush/shutdown, backpressure, and a minimum HTTP request interval.
## Environment
Linux/macOS:
```bash
export MASTER_LOG_API_KEY=dev-key
export MASTER_LOG_ENDPOINT=http://127.0.0.1:8000
```
Windows PowerShell:
```powershell
$env:MASTER_LOG_API_KEY = "dev-key"
$env:MASTER_LOG_ENDPOINT = "http://127.0.0.1:8000"
```
`MASTER_LOG_ENDPOINT` may be the backend root, `/api/v1`, `/api/v1/logs`, or `/api/v1/logs/batch`.
Optional controls:
```bash
export MASTER_LOG_TIMEOUT_SECONDS=2.0
export MASTER_LOG_ECHO=false
export MASTER_LOG_ASYNC=true
export MASTER_LOG_BATCH_SIZE=100
export MASTER_LOG_FLUSH_INTERVAL_SECONDS=1.0
export MASTER_LOG_MAX_QUEUE_SIZE=10000
export MASTER_LOG_DROP_WHEN_FULL=true
export MASTER_LOG_QUEUE_TIMEOUT_SECONDS=0.25
export MASTER_LOG_BACKPRESSURE=true
export MASTER_LOG_INITIAL_SEND_SECONDS_PER_LOG=0.005
export MASTER_LOG_MAX_ENQUEUE_SLEEP_SECONDS=0.25
export MASTER_LOG_MIN_REQUEST_INTERVAL_SECONDS=0.25
```
## Add To A Rust Project
From a local checkout:
```toml
[dependencies]
master-log-client = { path = "../master_log_clients/rust" }
serde_json = "1"
```
## Simple Usage
```rust
use std::time::Duration;
use master_log_client::{flush, mlog, mlogf, warn};
fn main() {
mlog("Telescope array online");
warn("Dome slit wind threshold approaching");
mlogf!("Captured frame {} for {}", 42, "M31");
let result = flush(Duration::from_secs(5));
if !result.ok {
eprintln!("Master Log flush failed: {}", result.error.unwrap_or_default());
}
}
```
## Configure In Code
Values passed to `configure()` are used immediately and take precedence over `MASTER_LOG_API_KEY` and `MASTER_LOG_ENDPOINT`.
```rust
use std::time::Duration;
use master_log_client::{configure, flush, mlog, MasterLogConfig};
fn main() {
configure(
MasterLogConfig::from_env()
.api_key("dev-key")
.endpoint("http://127.0.0.1:8000")
.batch_size(100)
.flush_interval(Duration::from_secs(1))
.min_request_interval(Duration::from_millis(250)),
);
mlog("Mirror cover opened");
flush(Duration::from_secs(5));
}
```
## Structured Fields
```rust
use std::time::Duration;
use master_log_client::{flush, log_entry, LogEntry, Severity};
use serde_json::json;
fn main() {
log_entry(
LogEntry::with_title("Camera cooling alert", "CCD cooling loop failed to settle")
.severity(Severity::Error)
.tags(["ccd", "camera"])
.ttl_seconds(120)
.metadata(json!({
"setpoint_celsius": -20,
"actual_celsius": -16.8
})),
);
flush(Duration::from_secs(5));
}
```
## Explicit Client
```rust
use std::time::Duration;
use master_log_client::{LogEntry, MasterLogClient, MasterLogConfig, Severity};
fn main() {
let client = MasterLogClient::new(
MasterLogConfig::from_env()
.api_key("dev-key")
.endpoint("http://127.0.0.1:8000"),
);
client.log_entry(
LogEntry::new("Flat-field calibration completed")
.severity(Severity::Info)
.tags(["calibration", "ccd"]),
);
client.flush(Duration::from_secs(5));
}
```
## Background Batching
The Rust client defaults to a background worker thread. Calls enqueue log events locally and wake the worker. The worker drains the queue, batches events, and sends them to `/api/v1/logs/batch`.
`min_request_interval` or `MASTER_LOG_MIN_REQUEST_INTERVAL_SECONDS` enforces a minimum delay between actual HTTP request starts. This is separate from `flush_interval`: a full batch can wake the worker immediately, but the worker still waits until the minimum request interval has elapsed.
Async enqueue is intentionally not free by default. After each queued log, the caller sleeps for the worker’s moving average send time per accepted log. The first burst uses `initial_send_seconds_per_log`, then successful batch sends tune the value. Use `backpressure(false)` only when the caller already has its own rate limit.
Use `async_mode(false)` when a program must block on every send or when a background thread is not appropriate.
## Automatic Metadata
Every event includes a `rust_client` metadata block with:
- Hostname
- Process id
- Process name
- `argv0`
- Current working directory
- Library name and version
Failures are non-fatal by default. Logging calls return `MasterLogResult` with `ok`, `status_code`, `event_id`, `queued`, `accepted`, `response`, and `error`. Use `try_log()` or `try_log_entry()` on `MasterLogClient` when Rust `Result` errors are preferred.