Skip to main content

Privacy and breadcrumbs

note

Breadcrumb filtering is new in 7.0.0.

What breadcrumbs are

Breadcrumbs are short structured records of what the app was doing in the lead-up to an issue — navigation, taps, lifecycle changes, network requests, system events. They are aggregated into the report timeline and surface in the Bugsee dashboard.

The SDK ships four built-in breadcrumb sources:

SourceExamples
AppApplication lifecycle (onCreate, foreground/background), low-memory warnings.
UIActivity / Fragment navigation, dialog open/close, gesture events.
NetworkHTTP request lifecycle entries — host, path, method, status, mechanism.
SystemConnectivity, battery, thermal, orientation, configuration changes.

Breadcrumb capture is on by default and is gated by the CaptureBreadcrumbs option — see configuration.

Disabling breadcrumb collection

To turn off breadcrumb capture entirely, set CaptureBreadcrumbs to false in your manifest or programmatically:

<meta-data android:name="com.bugsee.option.capture.breadcrumbs"
android:value="false" />

Most apps should keep capture on and use the filter below to scrub or drop only the entries that matter.

Filtering breadcrumbs

Bugsee.setBreadcrumbFilter(EventFilter<Breadcrumb>) registers a single filter that is invoked for every breadcrumb the SDK is about to record — regardless of source. Pass the (possibly mutated) breadcrumb to the supplied callback to keep it, or pass null to drop it.

The filter shape mirrors setLogEventFilter and setNetworkEventFilter — the same generic EventFilter<T> interface, whose single filter(event, callback) method hands you the event and a Callback1 to invoke with the result.

HTTP-request breadcrumb URLs are emitted verbatim; opt into masking, PII redaction, or drop semantics through this filter (see the URL-masking example below).

The Breadcrumb interface (com.bugsee.library.contracts.exchange.Breadcrumb) exposes:

MethodPurpose
getCategory() / setCategory(String)Source category — typical values: "navigation", "user", "system", "business", "error".
getType() / setType(String)Sub-type within the category (for example http_request, gesture, lifecycle).
getMessage() / setMessage(String)Human-readable description.
getLevel() / setLevel(Breadcrumb.Level)One of DEBUG, INFO, WARNING, ERROR, FATAL.
getData() / setData(Map) / setData(key, value)Free-form key/value context map. HTTP-request breadcrumbs put url, method, status_code, mechanism, etc. here.
setTimestamp(long)Wall-clock milliseconds.

Examples

Mask query-string tokens on HTTP-request breadcrumbs

import com.bugsee.library.Bugsee;
import com.bugsee.library.contracts.exchange.Breadcrumb;

Bugsee.setBreadcrumbFilter((crumb, callback) -> {
Map<String, Object> data = crumb.getData();
if (data != null) {
Object urlObj = data.get("url");
if (urlObj instanceof String) {
String url = (String) urlObj;
if (url.contains("token=")) {
crumb.setData("url",
url.replaceAll("token=[^&\\s]+", "token=[REDACTED]"));
}
}
}
callback.run(crumb); // callback.run(null) to drop the breadcrumb entirely
});

Drop noisy breadcrumb categories

Bugsee.setBreadcrumbFilter((crumb, callback) -> {
if ("system".equals(crumb.getCategory())
&& "battery".equals(crumb.getType())) {
callback.run(null); // drop battery-state pings
return;
}
callback.run(crumb);
});

Downgrade level for known-noisy entries

Bugsee.setBreadcrumbFilter((crumb, callback) -> {
String message = crumb.getMessage();
if (message != null && message.startsWith("[heartbeat]")) {
crumb.setLevel(Breadcrumb.Level.DEBUG);
}
callback.run(crumb);
});

Declaring the filter in the manifest

You can also point Bugsee at a breadcrumb filter from AndroidManifest.xml, with no code. Add a com.bugsee.filter.breadcrumb <meta-data> whose value is a class that implements EventFilter<Breadcrumb> and has a public no-arg constructor. The benefit: the filter is in force from the very first captured event, even under auto-initialization, before any of your own code runs.

<application>
<meta-data android:name="com.bugsee.filter.breadcrumb"
android:value="com.example.MyBreadcrumbFilter" />
</application>
import androidx.annotation.Keep;
import com.bugsee.library.contracts.common.Callback1;
import com.bugsee.library.contracts.exchange.Breadcrumb;
import com.bugsee.library.contracts.exchange.EventFilter;

@Keep // referenced only by name in the manifest — keep it from R8
public class MyBreadcrumbFilter implements EventFilter<Breadcrumb> {
public MyBreadcrumbFilter() { } // required public no-arg constructor

@Override
public void filter(Breadcrumb crumb, Callback1<Breadcrumb> callback) {
if ("system".equals(crumb.getCategory())
&& "battery".equals(crumb.getType())) {
callback.run(null); // drop battery-state pings
return;
}
callback.run(crumb);
}
}

A filter set in code with Bugsee.setBreadcrumbFilter(...) takes precedence over the manifest one. Because the class is referenced only by name, keep it from R8 — annotate it @Keep or add -keep class com.example.MyBreadcrumbFilter { <init>(); }.

The same mechanism is available for network events and logs.

Recording custom breadcrumbs

Beyond the built-in sources, you can record your own breadcrumbs with Bugsee.addBreadcrumb(...) — see Breadcrumbs → Recording custom breadcrumbs. Custom breadcrumbs run through the filter you register here, exactly like the built-in ones.

Notes

  • The filter is synchronous — it runs on the recording thread before the breadcrumb is persisted. Keep it allocation-light and fast; do not perform I/O.
  • Mutate the breadcrumb in place and pass the same instance to callback.run(...). Passing a different Breadcrumb implementation to the callback is not supported.
  • The filter is invoked for all sources. Use getCategory() / getType() to scope your logic per source (for example, only touch HTTP-request entries by checking category == "navigation" and type == "http_request").
  • Network events (the entries surfaced in the network tab of the report) are scrubbed separately via setNetworkEventFilter. The breadcrumb filter only affects the breadcrumb timeline.
Found an issue, typo, or wrong statement on this page? Report it now →