Skip to Content
Core ConceptsDiagnostics & Bug Reports

Diagnostics, Logs & Bug Reports

Every Tracelet app records what the SDK is doing on the device — permissions, tracking state, sensor availability, and a rolling log. The tracelet_doctor package turns all of that into a one-tap diagnostic screen and a copy-and-paste bug report, so when something looks wrong you (or your users) can capture exactly what happened.

New in 3.3.0: the Doctor’s Copy button now bundles everything (health + configuration + logs + telematics) into a single Markdown report, and a new Share button lets you download/email it as a .md file. There’s also a Copy logs button in the log viewer.


The 30-second version

Add tracelet_doctor as a dev dependency (not a regular one) — it’s a debugging tool, and Flutter excludes dev-dependency packages from release builds:

flutter pub add dev:tracelet_doctor

Then guard usage behind kDebugMode so it’s tree-shaken out of release builds:

import 'package:flutter/foundation.dart' show kDebugMode; import 'package:tracelet_doctor/tracelet_doctor.dart'; // Open the diagnostic screen from a debug menu, button, or shake gesture: if (kDebugMode) { TraceletDoctor.show(context); }

That opens a sheet with:

  • Warnings — anything that could hurt tracking (permission denied, power-save mode, aggressive OEM, no significant-motion sensor, mock locations…).
  • Permissions, tracking state, battery & OEM, configuration, sensors, database.
  • A View Logs button (the last 500 log lines).
  • Copy Bug Report and Share Bug Report buttons in the top-right.

Filing a bug report (for your users)

When a user reports an issue, the fastest way to help them is to get a Tracelet bug report. Tell them to:

  1. Open the Tracelet Doctor screen (wherever you placed it in your app).
  2. Tap the Share icon (↗) — or Copy (⧉) — in the top-right.
  3. Paste / attach it into your support channel or the GitHub issue, along with any of your own app logs.

The report is plain Markdown and looks like this:

# Tracelet Bug Report _Generated by Tracelet Doctor at 2026-06-14T10:22:31Z (UTC)._ ## Health check | Field | Value | |---|---| | Platform | android | | OS version | 14 | | Manufacturer | Xiaomi | | Aggressive OEM | true (rating 5/5) | | Location permission | always | | Power save mode | true | ... **Warnings (2):** - ⚠️ Power Save mode is ON — may throttle background tracking - ⚠️ Device manufacturer may kill background apps ## Active configuration ```json { "geo": { "distanceFilter": 10.0, ... }, "http": { "url": "«redacted»", "headers": "«redacted»", ... } } ``` ## Telematics events (most recent) | Type | Severity | Lat | Lng | Time | Synced | ... ## Logs (last 500) 2026-06-14T10:21:55Z [INFO] Tracking started (mode: location) 2026-06-14T10:22:03Z [WARN] Location accuracy degraded ...

Secrets are redacted automatically. Before the configuration is added to the report, any value whose key looks like a URL, header, parameter, key, token, or certificate is replaced with «redacted». Your sync URL, API keys and auth headers never end up in a pasted report. (Everything else — distance filters, accuracy, feature toggles — is kept, because that’s what helps debugging.)


Working with logs directly

The Doctor reads the same logs you can access from the API. This is handy if you want to build your own diagnostics screen or ship logs to your backend.

// Read the most recent log entries. final logs = await Tracelet.getLogs(500); for (final entry in logs) { print('${entry.timestamp} [${entry.level}] ${entry.message}'); } // Wipe stored logs (e.g. after the user files a report). await Tracelet.clearLogs();

Each LogEntry has id, level (DEBUG/INFO/WARN/ERROR), message, and an ISO-8601 timestamp. Logs are stored in the on-device SQLite database, so they survive app restarts and capture background activity — exactly the events that are otherwise impossible to see in a debugger.

How much is logged is controlled by your LoggerConfig (log level). Lower the level in production to keep the database small; raise it to debug while reproducing an issue.


Building your own report

If you’d rather generate the report yourself (e.g. attach it to your own crash reporter, or add your app version), call the builder directly:

import 'package:tracelet_doctor/tracelet_doctor.dart'; final report = await TraceletBugReport.build( appName: 'My App', appVersion: '2.4.1', // e.g. from package_info_plus logLimit: 500, telematicsLimit: 100, ); // Now copy, share, upload, or attach `report` however you like.

You can also reuse just the secret-redaction helper on any config map — handy if you log your own configuration:

final safe = TraceletBugReport.redactConfig(Tracelet.activeConfig.toMap());

What’s in the report (cheat-sheet)

SectionSourceWhy it helps
Health checkTracelet.getHealth()Permissions, OEM/battery, sensors, device — the usual suspects
WarningscomputedThe likely cause of “tracking stops in the background”
Active configurationTracelet.activeConfig (redacted)Confirms the settings actually in effect — including any applied remote config (3.6.10+)
Telematics eventsTracelet.getTelematicsEvents()Recent driving/impact events (3.3.0)
LogsTracelet.getLogs()A timeline of what the SDK did, including in the background

Good to know

  • Privacy first — the report is generated entirely on the device. Nothing is uploaded unless you send it. Secrets are redacted before they’re included.
  • Works when not initialized — if Tracelet hasn’t been started yet, the Doctor shows a friendly “not initialized” screen instead of crashing, and each report section degrades gracefully.
  • Ship it in debug builds — many teams wire TraceletDoctor.show(context) to a shake gesture or a hidden debug menu so QA and support can grab a report in seconds.
Last updated on