Skip to main content

rustauth_telemetry/
types.rs

1//! Telemetry types shared with the Better Auth telemetry payload shape.
2
3use serde::Serialize;
4use std::future::Future;
5use std::pin::Pin;
6use std::sync::Arc;
7
8/// Provider / framework detection row (mirrors upstream `DetectionInfo`).
9#[derive(Clone, Debug, Serialize, PartialEq, Eq)]
10pub struct DetectionInfo {
11    pub name: String,
12    pub version: Option<String>,
13}
14
15/// Runtime identification for Rust hosts (replaces Node/Bun/Deno detection).
16#[derive(Clone, Debug, Serialize, PartialEq, Eq)]
17pub struct RuntimeInfo {
18    pub name: String,
19    pub version: Option<String>,
20}
21
22/// Event sent to the telemetry collector or `custom_track`.
23#[derive(Clone, Debug, Serialize)]
24pub struct TelemetryEvent {
25    #[serde(rename = "type")]
26    pub event_type: String,
27    #[serde(rename = "anonymousId", skip_serializing_if = "Option::is_none")]
28    pub anonymous_id: Option<String>,
29    pub payload: serde_json::Value,
30}
31
32impl TelemetryEvent {
33    pub fn to_json_value(&self) -> serde_json::Result<serde_json::Value> {
34        serde_json::to_value(self)
35    }
36}
37
38pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
39
40pub type CustomTrackFn = Arc<dyn Fn(TelemetryEvent) -> BoxFuture<'static, ()> + Send + Sync>;
41
42/// Overrides used by integration tests (Vitest mocks replacement).
43#[doc(hidden)]
44#[derive(Clone, Default)]
45pub struct TelemetryTestHooks {
46    pub anonymous_id: Option<String>,
47    pub runtime: Option<RuntimeInfo>,
48    pub database: Option<Option<DetectionInfo>>,
49    pub framework: Option<Option<DetectionInfo>>,
50    pub environment: Option<String>,
51    pub system_info: Option<serde_json::Value>,
52    pub package_manager: Option<Option<DetectionInfo>>,
53}
54
55/// Optional hints and hooks for telemetry collection.
56#[derive(Clone, Default)]
57pub struct TelemetryContext {
58    pub database: Option<String>,
59    pub adapter: Option<String>,
60    pub skip_test_check: bool,
61    pub custom_track: Option<CustomTrackFn>,
62    pub http_transport: Option<Arc<dyn TelemetryHttpTransport>>,
63    pub test_hooks: Option<TelemetryTestHooks>,
64}
65
66/// Async HTTP sink for telemetry JSON payloads.
67pub trait TelemetryHttpTransport: Send + Sync {
68    fn post_json<'a>(
69        &'a self,
70        url: &'a str,
71        body: &'a serde_json::Value,
72    ) -> BoxFuture<'a, Result<(), TelemetryHttpError>>;
73}
74
75/// Transport failures are intentionally opaque (upstream logs and continues).
76#[derive(Clone, Debug)]
77pub struct TelemetryHttpError(pub String);
78
79impl std::fmt::Display for TelemetryHttpError {
80    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81        self.0.fmt(f)
82    }
83}
84
85impl std::error::Error for TelemetryHttpError {}