Arnis Telemetry Service: How It Sends Generation Logs and Events
The telemetry service in arnis is an opt-in, privacy-focused subsystem that asynchronously reports generation clicks, structured log entries, and crash diagnostics to a remote endpoint while strictly enforcing user consent and isolating all network activity in background threads to prevent UI blocking.
The arnis repository by louis-e implements a lightweight telemetry module designed to gather diagnostic insights without compromising user privacy or application stability. This service handles three distinct event types—generation clicks, log entries, and crash reports—transmitting them to https://arnismc.com/telemetry/report_telemetry.php only when explicit user consent is granted via an atomic boolean flag.
Architecture and Event Types
The telemetry implementation resides in src/telemetry.rs and operates as a non-intrusive bridge between the application and analytics infrastructure. All transmissions share common architectural principles: strict consent validation, platform detection, compile-time version injection, and thread-isolated execution.
Telemetry Event Categories
The service categorizes data into three JSON payloads:
- Generation clicks: Simple markers indicating user interaction with the world generation feature, sent via
send_generation_click(lines 90‑123) - Log entries: Structured diagnostic messages with severity levels, truncated to 1000 characters, transmitted through
send_log(lines 45‑92) - Crash reports: Panic information captured via custom hooks, truncated to 500 characters, handled by
send_crash_report(lines 66‑88)
Core Implementation Details
Consent Management
At the heart of the privacy controls sits a static atomic boolean initialized to false:
static TELEMETRY_CONSENT: AtomicBool = AtomicBool::new(false);
The public API set_telemetry_consent (lines 14‑16) allows the GUI to toggle this flag based on user preferences, while get_telemetry_consent (lines 18‑21) provides internal access for all telemetry paths. No data transmits unless this function returns true.
Platform Detection and Versioning
Two helper functions enrich every payload with environmental context. The get_platform function (lines 23‑31) maps std::env::consts::OS to standardized strings (windows, linux, macos), while get_app_version (lines 33‑36) injects the crate version at compile time via env!("CARGO_PKG_VERSION").
JSON Payload Definitions
Serde-annotated structs in src/telemetry.rs define the wire format. The LogEntry struct (lines 54‑63) includes optional platform and version fields:
#[derive(Serialize)]
struct LogEntry<'a> {
r#type: &'a str,
log_level: &'a str,
log_message: &'a str,
#[serde(skip_serializing_if = "Option::is_none")]
platform: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
app_version: Option<&'a str>,
}
The CrashReport struct (lines 38‑45) and GenerationClick struct (lines 47‑52) provide specialized schemas for their respective event types.
Transmitting Telemetry Events
Tracking Generation Clicks
The send_generation_click function executes when users initiate world generation in the GUI. It validates consent and release build status, then spawns a background thread wrapped in catch_unwind:
pub fn send_generation_click() {
if !get_telemetry_consent() { return; }
if cfg!(debug_assertions) { return; } // Disable in debug builds
std::thread::spawn(|| {
let _ = std::panic::catch_unwind(AssertUnwindSafe(|| {
let client = Client::new();
let payload = GenerationClick { r#type: "generation_click" };
let _ = client.post(TELEMETRY_URL)
.header("Content-Type", "application/json")
.json(&payload)
.send();
}));
});
}
Sending Log Entries
The send_log function constructs a LogEntry containing the severity level, truncated message (limited to 1000 characters), platform, and version. It dispatches via the same background thread pattern, using std::thread::spawn and AssertUnwindSafe to guarantee that network failures cannot panic the main application.
Crash Reporting via Panic Hooks
The install_panic_hook function (lines 94‑149) registers a custom handler that captures thread panics. After logging locally via the error! macro, it extracts error details and invokes send_crash_report only when telemetry consent is granted and running in release mode. The implementation uses catch_unwind to ensure that the crash reporting itself cannot trigger secondary panics.
GUI Integration Points
The telemetry system connects to the user interface in src/gui.rs at three critical junctions:
- Startup:
install_panic_hook()initializes at line 76 to capture unexpected crashes throughout the application lifecycle - Settings: Line 716 calls
set_telemetry_consentto persist user preferences from the settings checkbox - Generation trigger: Line 719 invokes
send_generation_click()immediately after the user requests world generation
Additional modules like src/world_editor/ and src/progress.rs emit log telemetry throughout the processing pipeline via send_log calls.
Summary
- The telemetry service requires explicit opt-in via an
AtomicBoolconsent flag that defaults to disabled insrc/telemetry.rs(lines 10‑12) - Three event types—generation clicks, logs, and crashes—transmit to
https://arnismc.com/telemetry/report_telemetry.phponly in release builds - All network operations execute in isolated background threads with
std::panic::catch_unwindprotection to prevent UI freezing - Payloads include platform information from
std::env::consts::OSand compile-time version strings for environmental context - Debug builds automatically disable transmission via
cfg!(debug_assertions)checks to prevent analytics pollution during development
Frequently Asked Questions
How does arnis ensure telemetry respects user privacy?
The implementation uses a global AtomicBool initialized to false (lines 10‑12) with no public setter except set_telemetry_consent (lines 14‑16), which the GUI calls only when users explicitly enable telemetry in settings. Every transmission function checks get_telemetry_consent() (lines 18‑21) before executing any network code, ensuring silent operation when consent is withheld.
Why do debug builds not send telemetry?
The code explicitly checks cfg!(debug_assertions) at the entry points of send_generation_click, send_log, and the panic hook. This compile-time configuration prevents debug builds from transmitting data, ensuring that development testing does not pollute production analytics or expose unstable features.
What prevents telemetry from crashing the application if the network fails?
All transmission logic runs inside std::thread::spawn with std::panic::catch_unwind wrappers using AssertUnwindSafe. This design isolates network failures and potential panics within background threads, guaranteeing that telemetry code cannot block the main UI thread or propagate errors back to the user workflow.
How are long error messages handled in crash reports?
The panic hook implementation (lines 94‑149) truncates error messages to 500 characters before JSON serialization, while standard log entries truncate at 1000 characters in send_log. This prevents oversized payloads while preserving essential diagnostic information for debugging.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →