forked from 1b-agent/fieldcraft-upstream
App: send usage batches to PostHog Cloud EU from a background thread (#238)
ureq over rustls (ring) with the OS certificate verifier. The project key is the build-time FIELDCRAFT_POSTHOG_KEY; without it nothing is asked or sent. FIELDCRAFT_TELEMETRY=0 turns it off; --control and CI runs only with FIELDCRAFT_TELEMETRY=1. A failed post drops its batch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
1 parent
79d583ea0f
commit
ed9ec7748d
5 files changed
+1586
-34
No files matched your search
@@ -12,6 +12,7 @@
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
mod control_server;
|
||||
mod usage;
|
||||
|
||||
use fieldcraft_engine::autosave::{self, Autosaver};
|
||||
use fieldcraft_engine::{Session, crash, logfile};
|
||||
@@ -49,6 +50,8 @@ struct App {
|
||||
autosaved_at: f64,
|
||||
/// The first frame was drawn (the crash journal says the app is up).
|
||||
running: bool,
|
||||
/// Sends the anonymous usage events, when this run may (docs/privacy.md).
|
||||
usage: Option<usage::Sender>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
@@ -82,6 +85,10 @@ impl eframe::App for App {
|
||||
{
|
||||
log::warn!("autosave: {e}");
|
||||
}
|
||||
self.app.usage_closing();
|
||||
if let Some(u) = self.usage.take() {
|
||||
u.finish();
|
||||
}
|
||||
log::info!("FieldCraft closed");
|
||||
crash::end_session();
|
||||
}
|
||||
@@ -103,7 +110,8 @@ fn services() -> Services {
|
||||
})),
|
||||
// Beside the recovery folder in the per-user data folder.
|
||||
recent_path: fieldcraft_io::recovery::default_dir().and_then(|d| d.parent().map(|p| p.join("recent.json"))),
|
||||
prefs_path: fieldcraft_io::recovery::default_dir().and_then(|d| d.parent().map(|p| p.join("prefs.json"))),
|
||||
prefs: fieldcraft_io::recovery::default_dir()
|
||||
.and_then(|d| d.parent().map(|p| fieldcraft_ui_egui::files::PrefsStore::file(p.join("prefs.json")))),
|
||||
open_url: Some(Box::new(open_url)),
|
||||
}
|
||||
}
|
||||
@@ -236,6 +244,14 @@ fn main() -> eframe::Result {
|
||||
// The window's model: its commands go into the crash journal.
|
||||
session.crash_journal = crash::enabled();
|
||||
let mut app = ModelApp::new(session).with_services(services());
|
||||
// Anonymous usage: asked once, recorded only when the user agreed (docs/privacy.md).
|
||||
let usage = match usage::host(args.control.is_some()) {
|
||||
Some(host) => {
|
||||
app = app.with_usage(host);
|
||||
usage::start()
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
app.custom_titlebar = CUSTOM_TITLEBAR;
|
||||
app.integrated_titlebar = cfg!(target_os = "macos");
|
||||
if let Some(rs) = &cc.wgpu_render_state {
|
||||
@@ -261,7 +277,7 @@ fn main() -> eframe::Result {
|
||||
Autosaver::new(&dir).map_err(|e| log::warn!("autosave unavailable: {e}")).ok()
|
||||
});
|
||||
app.announce_crashes(&crashed);
|
||||
Ok(Box::new(App { app, autosaver, autosaved_at: 0.0, running: false }))
|
||||
Ok(Box::new(App { app, autosaver, autosaved_at: 0.0, running: false, usage }))
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user