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. Bugsee installs it itself as part of launch, so it does not depend on when your code runs. With auto-initialization, capture can start before your Application.onCreate(), and a filter set there in code misses what was captured before the call.

<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; use one or the other, not both. 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 →