bevy_fleet 0.1.0

bevy swarm diagnostic, event, metric, and telemetry client
Documentation
use bevy::diagnostic::DiagnosticsStore;
use serde::{Deserialize, Serialize};

/// Diagnostic information extracted from Bevy diagnostics
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FleetDiagnostic {
    pub name: String,
    pub value: String,
}

/// Extracts diagnostics from Bevy's DiagnosticsStore
pub fn extract_diagnostics(diagnostics: &DiagnosticsStore) -> Vec<FleetDiagnostic> {
    let mut results = Vec::new();

    // Collect uptime
    let uptime = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap_or_default()
        .as_secs();
    results.push(FleetDiagnostic {
        name: "uptime_seconds".to_string(),
        value: uptime.to_string(),
    });

    // Extract diagnostic metadata
    for diagnostic in diagnostics.iter() {
        let path = diagnostic.path();
        let current = diagnostic.value();
        let average = diagnostic.average();

        // Only include smoothed values when they provide extra signal compared to the metrics we
        // already export (`value` and `average`). This keeps diagnostics focused on information
        // that isn't duplicated under the `metrics` field.
        if let Some(smoothed) = diagnostic.smoothed() {
            let matches_current = current
                .map(|value| (value - smoothed).abs() <= f64::EPSILON)
                .unwrap_or(false);
            let matches_average = average
                .map(|value| (value - smoothed).abs() <= f64::EPSILON)
                .unwrap_or(false);

            if !matches_current && !matches_average {
                results.push(FleetDiagnostic {
                    name: format!("{}.smoothed", path),
                    value: smoothed.to_string(),
                });
            }
        }

        let history_len = diagnostic.history_len();
        if history_len > 0 {
            results.push(FleetDiagnostic {
                name: format!("{}.history_len", path),
                value: history_len.to_string(),
            });
        }

        if let Some(duration) = diagnostic.duration() {
            results.push(FleetDiagnostic {
                name: format!("{}.history_duration_seconds", path),
                value: duration.as_secs_f64().to_string(),
            });
        }
    }

    results
}