eyes-subscriber 0.6.0

Tracing subscriber for sending traces to Eyes (eyes.coreyja.com)
Documentation

Eyes Subscriber

A tracing subscriber for sending structured trace data to Eyes (eyes.coreyja.com).

Quick Start

use eyes_subscriber::EyesSubscriberBuilder;
use tracing_subscriber::prelude::*;
use uuid::Uuid;

# async fn example() -> Result<(), Box<dyn std::error::Error>> {
let org_id = Uuid::parse_str("your-org-id")?;
let app_id = Uuid::parse_str("your-app-id")?;

// Simplest: auto-configure from environment variables
let (eyes_layer, shutdown_handle) = EyesSubscriberBuilder::build_from_env(org_id, app_id)?;

tracing_subscriber::registry()
    .with(eyes_layer)
    .init();

// Your application code here
tracing::info!("Application started");

// Graceful shutdown
shutdown_handle.shutdown().await?;
# Ok(())
# }

Configuration

The subscriber can be configured in several ways:

  1. Environment variables (recommended):
    • EYES_URL: Override the default URL (defaults to https://eyes.coreyja.com)
    • EYES_TRANSPORT: Set to "websocket" or "ws" for WebSocket, defaults to HTTP
    • EYES_QUEUE_CAPACITY: Capacity of the bounded event queue (defaults to 65536)
    • EYES_TOKEN: Bearer token sent on every request (HTTP, batch, WebSocket upgrade, manifest and heartbeat). Required once the server runs with EYES_API_AUTH=enforce.
    • EYES_EMIT_ENTER_EXIT: Set to "1" or "true" (case-insensitive) to emit span_enter/span_exit events (disabled by default; see [EyesSubscriberBuilder::with_emit_enter_exit])
  2. Default production: Use new_with_default() for https://eyes.coreyja.com
  3. Custom URL: Use new() with any URL for self-hosted instances

Transports

Three transport methods are available:

  • HTTP (default): Reliable, request/response based
  • BatchingHttp: HTTP with client-side batching for high-volume use cases
  • WebSocket: Lower latency, persistent connection

Emitted measurements

A measurement is an ordinary event with event_type = "measurement" and a versioned payload:

{"version": 1, "metric_name": "cpu", "metric_kind": "gauge", "value": 42.5,
 "unit": "percent", "description": "CPU utilisation",
 "fields": {"host": "web-1"}, "level": "INFO", "target": "eyes::measurement"}

Emit one with [emit_gauge], [emit_counter], [emit_sample], or the [measurement!] macro when you have dimensions:

eyes_subscriber::emit_gauge("cpu", 42.5);
eyes_subscriber::emit_counter("requests", 5);
eyes_subscriber::measurement!(
    "gauge", "cpu", 42.5_f64,
    unit = "percent", description = "CPU utilisation", host = "web-1"
);

The v1 instrument matrix

kind meaning accepted values
gauge instantaneous value any finite number
counter cumulative, monotonically non-decreasing total any finite number >= 0
sample one discrete observation any finite number

Int and float are both valid for every kind. Counter rate and reset semantics are deferred: counters are stored and aggregable, but nothing computes a rate or detects a reset.

Required filter directive

Measurements travel as tracing events on the reserved [MEASUREMENT_TARGET], so a global EnvFilter that does not enable INFO for eyes::measurement drops them before this layer ever runs. An app with a target-scoped filter must include eyes::measurement=info.