Rust SDK
The telemetry-sh crate provides a small blocking client for event ingestion and interactive queries. Each method constructs a blocking reqwest client and sends one HTTP request. The crate does not expose an asynchronous client, configurable timeout, retry policy, batch queue, or flush method.
Install and initialize
[dependencies]
telemetry-sh = "1.0.0"
serde_json = "1.0"
uuid = { version = "1", features = ["v4"] }
use std::env;
use telemetry_sh::Telemetry;
let mut telemetry = Telemetry::new();
telemetry.init(env::var("TELEMETRY_API_KEY")?);
Keep the key in server-side configuration. Use a write-scoped key for ingestion-only services and a read-scoped key for reports or query automation.
Send a structured event
use serde_json::json;
use uuid::Uuid;
let event_id = Uuid::new_v4().to_string();
let event = json!({
"event_id": event_id,
"job_name": "invoice_sync",
"status": "success",
"duration_ms": 912,
"attempt": 1,
"release": env::var("APP_RELEASE").ok(),
});
match telemetry.log("job_completed", &event) {
Ok(response) => println!("telemetry response: {response}"),
Err(error) => eprintln!(
"telemetry delivery failed event_id={} error_type=transport_error: {}",
event_id,
error
),
}
Avoid credentials, headers, cookies, raw request bodies, prompts, exception text, and private customer content. Prefer controlled categories and stable internal identifiers.
The SDK accepts one serde_json::Value. An array value can represent a Log API bulk payload, but test the exact crate and API behavior before making batching part of a production delivery contract.
Run SQL
let query = r#"
SELECT
status,
COUNT(*) AS jobs
FROM job_completed
WHERE timestamp_utc >= now() - INTERVAL '24 hours'
GROUP BY status
ORDER BY jobs DESC
"#;
let result = telemetry.query(query)?;
let rows = result
.get("data")
.and_then(|value| value.as_array())
.cloned()
.unwrap_or_default();
println!("query rows: {}", rows.len());
The result is dynamic JSON. Validate types, nulls, API status, and empty results before using values in automation. Use the asynchronous Query API directly for long-running JSON or Parquet exports.
Blocking and timeout behavior
Both crate methods use reqwest::blocking. Do not call them directly on an asynchronous executor thread or a latency-sensitive request path without isolating the blocking work.
The published crate does not expose its HTTP client or configure a timeout. If the service needs context cancellation, connection reuse, a fixed timeout, status-specific retries, or a durable queue, implement the documented HTTP request with an application-owned reqwest::Client instead.
Keep the transport policy bounded so a telemetry outage cannot exhaust worker threads.
Retry and shutdown policy
Retry only transient connection failures, 429, 502, 503, and 504. Use exponential backoff with jitter, cap total time, and preserve the same event_id. Do not retry an unchanged invalid request.
The SDK has no background queue to flush. A successful log return means the immediate request produced a decodable response; it is not a promise of exactly-once storage. Track required calls or persist durable events in an application-owned outbox before process shutdown.
For ordinary analytics, do not turn a completed customer action into a failure because telemetry is unavailable. Review event delivery and idempotency.
Verify the integration
Send known success and failure fixtures, then query:
SELECT timestamp_utc, event_id, job_name, status, duration_ms, error_type
FROM job_completed
ORDER BY timestamp_utc DESC
LIMIT 20;
Check table naming, field types, units, null behavior, duplicate event IDs, and sensitive-data boundaries. Exercise a connection timeout and graceful shutdown before relying on the event for an alert.
Troubleshooting
- Missing-key error: initialize the client from a non-empty server-side environment value.
- Runtime stalls: move blocking calls off async executor threads or use an application-owned async HTTP client.
- Error response decodes as JSON: inspect the returned status and message; the crate does not call
error_for_status. - Duplicate rows: preserve
event_idacross network attempts and monitor duplicate IDs. - Large export: use the HTTP async-query start, status, and download flow.
Continue with the Log API, ingestion troubleshooting, and production instrumentation checklist.