feature: add error reporting integration - #16
Open
ivnbogdan wants to merge 3 commits into
Open
Conversation
ivnbogdan
force-pushed
the
feat/error-reporting
branch
from
August 25, 2026 03:58
5d6eac8 to
84f763e
Compare
Integrates the Unity SDK with the error reporting feature added to the server in aptabase/aptabase#183, following the pattern used by the MAUI and React Native SDKs. - Add Aptabase.TrackError(Exception, fatal) posting structured error reports (type, message, stack trace, severity, kind) to /api/v0/error - Add optional automatic crash reporting via EnableCrashReporting: exceptions logged by Unity (unhandled), process-terminating exceptions (crash) and unobserved Task exceptions (taskException) - Dedicated ErrorDispatcher shared by all platforms: flush on enqueue, retry on connection error/408/429/5xx, drop on 403 (quota) and other 4xx - Report only the first occurrence of each unique error per session (max 100), since Unity keeps running after an exception and a throwing Update() would otherwise flood the error quota - Send osName "web" on WebGL error reports (the error endpoint does not infer the OS from the User-Agent like the events endpoint does) - Fix stray $ characters in the User-Agent header - Fix Aptabase.Flush() throwing when the SDK failed to initialize - Bump to 0.3.0 and align Version.cs with package.json Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YWERdp5jK3YRMkkWM4RLcE
ivnbogdan
force-pushed
the
feat/error-reporting
branch
from
August 25, 2026 04:29
3664aad to
de6acc4
Compare
The samples never showed a using directive, so the namespace was only discoverable by reading the source. Closes #8 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YWERdp5jK3YRMkkWM4RLcE
Matches the local backend's HTTPS endpoint and the MAUI/React Native SDKs. HTTPS requests whose parsed host is a loopback address get a CertificateHandler that accepts the self-signed development certificate; production hosts and WebGL (where the browser validates TLS) are unaffected. The rule is matched on the parsed host rather than a string prefix so that e.g. https://localhost.example.com never has verification disabled. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YWERdp5jK3YRMkkWM4RLcE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Integrates the Unity SDK with the error reporting feature added to the server in aptabase/aptabase#183, following the pattern of aptabase/aptabase-maui#15 and the React Native integration (aptabase/aptabase-react-native@94d7cf6). Rebased on top of #14 (per-URL
WebRequestHelper,Task-returningFlush(CancellationToken),SetEnabled/SetResponseListener).Public API
Plus an opt-in
EnableCrashReportingtoggle on theAptabaseSettingsasset (off by default, like the other SDKs).Aptabase.Flush()now flushes error reports too, andSetEnabled(false)drops them.What's included
ErrorReport— thePOST /api/v0/errorbody, built from anExceptionor from a UnityLogType.Exceptionlog entry ("Type: message"parsed, namespaced types shortened to matchGetType().Name). Session/system context is stamped at capture time and every field is truncated to the server's limits so a report is never rejected with 400.ErrorDispatcher— separate from the events dispatcher because the endpoint takes one report per request (so WebGL and the other platforms share it) and has different retry semantics: retry on connection error/408/429/5xx, drop on 403 (monthly quota exhausted, per the server's deliberate 403-not-429 choice) and other 4xx. Flush-on-enqueue since errors are high-value; failures ride along with the regular flushes. Queue capped at 25. Honors theCancellationTokenlike the events dispatcher.CrashReporter—Application.logMessageReceivedThreaded(LogType.Exceptiononly →unhandled/error),AppDomain.UnhandledException(crash/fatalwhen terminating, best-effort delivery),TaskScheduler.UnobservedTaskException(taskException). Re-entrancy guarded, registered once, unregistered onApplication.quittingso domain-reload-off in the Editor doesn't stack handlers.WebRequestHelper.CreateAndSendWebRequestWithResultAsync— same pipeline as the events path but returns the status code/response body so the error dispatcher can decide whether to retry. The events path is now built on it (same logging and response-listener behaviour as before).Version.cswas drifted at 0.2.3 vspackage.json).Unity-specific decisions (where this diverges from MAUI/RN)
unhandled/error, not fatal. OnlyAppDomain.UnhandledExceptionwithIsTerminatingproducescrash/fatal. Native crashes are not captured.Update()fires 60×/s, which would hit the server's 20 req/s per-IP limit immediately and burn the monthly quota. Only the first occurrence of each unique (kind, type, message, stack) is reported per session, max 100 unique errors per session.UnityWebRequestis main-thread only, so the dispatcher queue is locked and off-thread enqueues post their flush to the capturedSynchronizationContext. Session ids now useSystem.Randomfor the same reason.osName. The events endpoint treats an emptyosNameas "web" and parses the browser User-Agent; the error endpoint doesn't, so error reports on WebGL sendosName: "web"(same as React Native) with the browser-reported OS string inosVersion. Events are unchanged.Debug.LogError/ assertions are not reported (no exception type, too noisy). No disk persistence in this version (same as RN; MAUI has it).SetResponseListenerstays events-only.Also fixed along the way
Aptabase.Flush()threw aNullReferenceExceptionwhen the SDK failed to initialize.CancellationTokenfires mid-request, theUnityWebRequestis now aborted and disposed (previously it kept running and the batch was re-sent later, so the server could receive it twice).Also included
using AptabaseSDK;and call out the namespace. Closes Add "using AptabaseSDK;" to documentation. #8.DEVregion host now points tohttps://localhost:3000like RN/MAUI. HTTPS requests whose parsed host is a loopback address (localhost,127.0.0.1,::1) attach aCertificateHandlerthat accepts the self-signed dev certificate (mirrors MAUI'sLocalHttpsClientHandler, but matched on the parsed host sohttps://localhost.example.comcan't disable verification); production hosts and WebGL are unaffected.Verification
Unity 6000.5.9f1 (batch mode, package referenced from disk, against a local mock Aptabase server over plain HTTP and self-signed HTTPS):
UnityWebRequestpipeline: structured report (headers, every body field, timestamp), fatal reports carry the stack trace,Debug.LogExceptionreported once asunhandled(same call site ×3 → 1 request),Debug.LogError/assertions ignored, 403/400 dropped and never retried, 429/500 retried on the nextFlush(), self-signed loopback HTTPS accepted by theCertificateHandler, events still batch to/api/v0/events,SetEnabled(false)drops reports,Flush()on an uninitialized SDK doesn't throw,TrackErrorfrom a worker thread is delivered.[RuntimeInitializeOnLoadMethod(BeforeSceneLoad)]init:SynchronizationContext.Currentis Unity's main-thread context at that point (so off-thread crash hooks can post their flush), a 5×-logged exception is reported once via the runtime log hook, and a report from a rawThreadis delivered.Running in Unity surfaced one real bug that the .NET stub harness had missed (fixed, folded into the error reporting commit): a
Flush()issued while a flush was in flight was silently skipped, so awaiting it didn't guarantee that re-queued reports (after a 429) were retried. Error flushes are now chained like in the React Native SDK, and only the first report of a batch kicks an automatic flush.Also still green: the .NET 10 stub harness (Runtime sources compiled against stub
UnityEnginetypes, payloads validated with the server'sErrorBody.cs), 62 checks including cancellation abort/dispose and the loopback trust-rule bypass cases.Not covered locally: on-device Android/iOS behaviour and IL2CPP stack-trace quality, and the exact
SystemInfo.operatingSystemstring a WebGL build reports (only affects theosVersionshown for WebGL error reports).🤖 Generated with Claude Code
https://claude.ai/code/session_01YWERdp5jK3YRMkkWM4RLcE