Skip to content
Telemetry
Browse docs

SDKsUpdated October 1, 20263 min read

Use this doc with your coding agent

Copy an instrumentation prompt into your coding agent and adapt it to your application.

On this page
  1. Install and initialize
  2. Send a structured event
  3. Run SQL
  4. Blocking and timeout behavior
  5. Retry and shutdown policy
  6. Verify the integration
  7. Troubleshooting

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.

These examples send fictional values to check delivery. Keep them in the reserved telemetry_quickstart sample table; they do not instrument a running application. For real use, record observed values after an actual operation in its own workflow table, and measure duration around that operation rather than the telemetry call.

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 an ingest-only key for services that only send events 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("telemetry_quickstart", &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 telemetry_quickstart
    WHERE timestamp_utc >= now() - INTERVAL '24 hours'
    AND job_name IS NOT NULL
    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
FROM telemetry_quickstart
WHERE job_name IS NOT NULL
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_id across 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.

Related feature

Use consistent event names and field types. Check for private data before sending events.

Page authors and references

The Telemetry editorial team maintains this page. The product team checks the examples and confirms how the product behaves.

How we review our docs