Beacon .NET SDK
The Beacon .NET SDK provides native integration for desktop (WPF, WinForms, MAUI), server (ASP.NET Core, Windows Services), and console applications.
Installation
Install via NuGet:
dotnet add package SoftAgility.BeaconOr via the Package Manager Console:
Install-Package SoftAgility.BeaconSystem Requirements
- .NET 8.0 or later
- Windows, Linux, or macOS
- No additional dependencies
Configuration
ASP.NET Core / Host Builder
Register Beacon with dependency injection to resolve IBeaconTracker:
services.AddBeacon(options =>
{
options.ApiKey = "your-api-key";
options.ApiBaseUrl = "https://api.beacon.softagility.com";
options.AppName = "MyApp";
options.AppVersion = "1.2.0";
});Manual Initialization
For applications without dependency injection, use the static Configure method. It returns void and creates a singleton BeaconTracker. Retrieve the instance via BeaconTracker.Instance after configuration:
BeaconTracker.Configure(options =>
{
options.ApiKey = "your-api-key";
options.ApiBaseUrl = "https://api.beacon.softagility.com";
options.AppName = "MyApp";
options.AppVersion = "1.2.0";
});
var tracker = BeaconTracker.Instance!;Calling Configure a second time throws InvalidOperationException. If required options (ApiKey, ApiBaseUrl, AppName) are missing, the SDK disables itself silently and logs a warning — it does not throw.
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
ApiKey | string | — | Your Beacon API key (required) |
ApiBaseUrl | string | — | Beacon API base URL (required) |
AppName | string | — | The application name sent as source_app on every event. Must match a product slug registered in the Beacon dashboard, or events are rejected with UNRECOGNIZED_PRODUCT. The SDK truncates values longer than 128 chars before sending. (required) |
AppVersion | string | — | Your application’s version string, sent as source_version. The SDK truncates values longer than 256 chars; note the backend rejects source_version values longer than 128 chars, so practically keep this under 128. (required) |
Enabled | bool | true | Enable or disable tracking globally |
FlushIntervalSeconds | int | 60 | How often to send batched events (1-3600) |
MaxBatchSize | int | 25 | Events per batch. Values above 1000 are clamped to 1000; otherwise the configured value is used. |
MaxQueueSizeMb | int | 10 | Maximum offline queue size in MB (1-1000) |
MaxBreadcrumbs | int | 25 | Breadcrumb ring buffer size (0-200) |
Events | EventDefinitionBuilder | — | Builder for registering known events |
Logger | Microsoft.Extensions.Logging.ILogger? | null | Optional logger for SDK diagnostics |
Known limit mismatch (SDK ≤ 1.0.1): The .NET SDK currently truncates
AppNameat 128 chars andAppVersionat 256 chars. The wire format actually allows the opposite —source_appup to 256 andsource_versionup to 128. To stay safe today, keepAppName≤ 128 andAppVersion≤ 128. A future SDK release will reconcile this with the wire format.
Identifying Users
Before tracking events or sessions, identify the current actor (user or device):
tracker.Identify("user-123");Actor IDs can be up to 512 characters. Once identified, all subsequent Track, StartSession, and TrackException calls use this actor. You can also pass an explicit actor ID to any tracking method.
Tracking Events
Events are organized by category and name, with optional properties.
Basic Event
tracker.Track("ui", "button_clicked", new
{
button_name = "export",
screen = "dashboard"
});With Explicit Actor
tracker.Track("reports", "report_exported", "user-456", new
{
format = "pdf",
row_count = 1500
});Event Limits
- Category: max 128 characters
- Name: max 256 characters
- Actor ID: max 512 characters
Session Management
Sessions group related events and track duration.
// Start a session (uses the identified actor)
tracker.StartSession();
// Or start with an explicit actor ID
tracker.StartSession("user-123");
// End the current session
tracker.EndSession();Exception Tracking
Track handled or unhandled exceptions with full stack traces. The SDK sends the exception type, message, and stack trace to the Beacon API, which assigns a fingerprint and groups similar exceptions together.
try
{
ProcessOrder(order);
}
catch (Exception ex)
{
tracker.TrackException(ex, ExceptionSeverity.NonFatal);
throw;
}Severity options are ExceptionSeverity.Fatal and ExceptionSeverity.NonFatal. Recent tracking calls are automatically attached as breadcrumbs to provide context.
Breadcrumbs
The SDK maintains a circular ring buffer of recent Track calls. When an exception is reported, these breadcrumbs are attached automatically, giving you a timeline of what happened before the error.
Configure the buffer size with MaxBreadcrumbs (default 25, max 200). Set to 0 to disable.
Flushing Events
Events are batched and sent on a timer (FlushIntervalSeconds) or when the batch reaches MaxBatchSize. To flush manually:
await tracker.FlushAsync();Check the last flush result:
FlushStatus status = tracker.LastFlushStatus;Offline Persistence
The SDK queues events in a local SQLite database under the OS-specific Local Application Data directory (e.g., %LOCALAPPDATA%\SoftAgility\Beacon\{SanitizedAppName}\queue.db on Windows; equivalent paths on Linux and macOS). The application name is sanitized for safe filesystem use. Events persist across application restarts and sync automatically when connectivity returns.
- FIFO queue with a configurable maximum size (
MaxQueueSizeMb) - Best-effort durable retry: events are retained on disk through transient network failures, but if the queue reaches the configured size cap, the oldest events are evicted to make room for new ones
- Background timer handles automatic flushing
- Permanent failures (4xx errors other than 401/402/429) are not retried; events are dropped with a logged warning
To guarantee delivery before shutdown, call await tracker.FlushAsync() explicitly. Disposing the tracker persists in-memory events to disk for the next launch but does not perform a network flush.
Event Manifest
Export a JSON manifest of your registered events for import into the Beacon portal’s allowlist page:
tracker.ExportEventManifest("events.json");Thread Safety
BeaconTracker is fully thread-safe. A single instance can be shared across your application and called from any thread.
Disposal
BeaconTracker implements both IDisposable and IAsyncDisposable. Dispose when your application shuts down to release resources and persist in-memory events to disk for the next launch:
// To deliver pending events to the network before shutdown:
await tracker.FlushAsync();
// Then release resources:
tracker.Dispose();
// or
await tracker.DisposeAsync();Disposal alone does not perform a network flush — pending events are written to disk and sent on the next session. For immediate delivery at shutdown, call FlushAsync first.
WPF Example
public partial class App : Application
{
private IBeaconTracker _tracker;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
BeaconTracker.Configure(options =>
{
options.ApiKey = "your-api-key";
options.ApiBaseUrl = "https://api.beacon.softagility.com";
options.AppName = "MyDesktopApp";
options.AppVersion = "2.1.0";
});
_tracker = BeaconTracker.Instance!;
_tracker.Identify("device-" + Environment.MachineName);
_tracker.StartSession();
}
protected override async void OnExit(ExitEventArgs e)
{
_tracker.EndSession();
await _tracker.FlushAsync();
_tracker.Dispose();
base.OnExit(e);
}
}Next Steps
- Getting Started for a general overview
- API Reference for direct HTTP integration
- Verify your first event (User Manual) — confirm ingestion from the Beacon dashboard
- Pricing for plan details