One package for WPF, WinForms, Avalonia, MAUI, console tools and ASP.NET.
Every call appends to a bounded in-memory queue and returns: nothing throws into your code, nothing blocks your thread, and if firstrun is unreachable your application is unaffected. No dependencies on any target framework.
dotnet add package Firstrun
dotnet add package Firstrun.Extensions.Hosting # ASP.NET and IHost onlyusing Firstrun;
Analytics = new FirstrunClient(new FirstrunOptions
{
SourceKey = "fr_xxxxxxxxxxxxxxxx",
Host = "https://app.firstrun.app",
ServiceName = "YourApp", // names the folder the anonymous id lives in
Channel = "stable",
});app_install on the first run ever and app_launch on everyrun are queued by the constructor. ServiceVersion defaults to the entry assembly, and the operating system, architecture and locale to the machine. Set ServiceName so the anonymous id on disk survives a key rotation. For ASP.NET, builder.Services.AddFirstrunServer(sourceKey, host) registers the same client as a singleton and flushes on shutdown.
Analytics.Event("exported_project", new FirstrunAttributes()
.Set("format", "pdf")
.Set("pages", 12));
Analytics.Error(ex);
Analytics.Log(new FirstrunEvent("render_stalled")
{
Severity = Severity.Warn,
Attributes = new FirstrunAttributes().Set("frames_dropped", 41),
});
Analytics.Identify("acct_8812"); // your own id, when they sign in
Analytics.Dispose(); // on exit. Optional: the worker is a background threadEvent writes at INFO and Error at ERROR, both filling in the conventional attributes; Log takes any name, any severity and any attributes. Values go on the wire as JSON and Set converts with the invariant culture, so a German machine does not send 1,5.