Reporting
Surface the browser's own health reports - deprecations, interventions, CSP violations and crashes - to your C# code through the Reporting API's ReportingObserver, so they can travel to your monitoring stack alongside ordinary errors.
@inject Bit.Butil.Reporting reportingMDN reference
Returns true when the runtime exposes ReportingObserver. Check it before subscribing on browsers you do not control.
if (await reporting.IsSupported())
{
// safe to subscribe
}Registers a handler that receives each batch of browser-generated reports. With buffered set to true (the default) reports queued before the observer registered are delivered too.
var subscription = await reporting.Subscribe(reports =>
{
foreach (var report in reports)
{
// report.Type → "deprecation", "intervention", ...
// report.Url → the page the report applies to
// report.Body → type-specific payload as a JsonElement
}
});
// later, when no longer needed:
await subscription.DisposeAsync();Pass a whitelist of report types to receive only what you care about - for example just deprecations, so you learn early when the app relies on an API scheduled for removal.
var subscription = await reporting.Subscribe(
reports =>
{
foreach (var report in reports)
{
// only deprecation reports arrive here
}
},
types: ["deprecation"],
buffered: true);The body shape varies per report type, so it is surfaced as a JsonElement. For a deprecation report, for instance, the body carries the offending API id and a human-readable message.
foreach (var report in reports)
{
if (report.Type is "deprecation")
{
var id = report.Body.GetProperty("id").GetString();
var message = report.Body.GetProperty("message").GetString();
// e.g. log it, or forward it to your telemetry backend
}
}API reference
ValueTask<bool> IsSupported()Task<ButilSubscription> Subscribe(Action<BrowserReport[]> handler, string[]? types = null, bool buffered = true)void InvokeBrowserReport(Guid id, BrowserReport[] reports)ValueTask DisposeAsync()