Add AdbRunner structured logcat streaming API
- Dominant language
- C#
- Stars
- 2.1k
- Forks
- 579
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 257
Description
## Summary
Add structured `logcat` streaming to `Xamarin.Android.Tools.AdbRunner` so the MAUI DevTools CLI can surface device logs to agents and IDEs without consumers parsing raw `adb logcat` output.
## Context
`adb logcat` is the only way to see app logs from an Android device until the DevFlow agent in the app is up and running. Even after that, system-level logs (ART runtime, app crashes, native binder errors) only appear in `logcat`. The MAUI DevTools CLI and DevFlow skills currently advise raw `adb logcat …` as a fallback — see [maui-labs#197](https://github.com/dotnet/maui-labs/issues/197) audit. We want a typed stream so consumers can filter and emit structured JSON.
## Proposed API
```csharp
namespace Xamarin.Android.Tools;
public partial class AdbRunner
{
/// adb -s logcat [-v threadtime] [-T 'YYYY-MM-DD HH:mm:ss.SSS' | -d]
public virtual IAsyncEnumerable LogcatAsync(
string serial,
LogcatOptions? options = null,
CancellationToken cancellationToken = default);
/// adb -s logcat -c — clear the device log buffer.
public virtual Task ClearLogcatAsync(string serial, CancellationToken cancellationToken = default);
}
public record LogcatOptions(
/// Tag/priority filter pairs. Examples: ("MauiDevFlow","V"), ("DOTNET","I"), ("*","W")
IReadOnlyList? Filters = null,
/// Restrict to a process. When set, runs `adb shell pidof ` to resolve PID once.
string? PackageName = null,
int? Pid = null,
/// `-T `: only entries since this point. Implies `-d` is false.
DateTimeOffset? Since = null,
/// `-d`: dump existing buffer and exit (no streaming).
bool DumpAndExit = false,
/// Buffer to read: main, system, crash, events, all.
LogcatBuffer Buffers = LogcatBuffer.Main | LogcatBuffer.System | LogcatBuffer.Crash);
public record LogcatFilter(string Tag, LogcatLevel Minimum);
public enum LogcatLevel { Verbose, Debug, Info, Warning, Error, Fatal, Silent }
[Flags]
public enum LogcatBuffer { Main = 1, System = 2, Radio = 4, Events = 8, Crash = 16, All = Main | System | Radio | Events | Crash }
public record LogcatEntry(
DateTimeOffset Timestamp,
int Pid,
int Tid,
LogcatLevel Level,
string Tag,
string Message);
```
Implementation notes:
- Use `-v threadtime` format (well-defined columns) and parse line-by-line. Format spec: `MM-DD HH:MM:SS.mmm PID TID L tag: message`.
- The async enumerable yields one `LogcatEntry` per parsed line. Cancellation kills the underlying `adb logcat` process.
- When `PackageName` is set and PID resolution returns nothing, retry once after a short delay (covers app-not-yet-launched). After two failures, throw.
- `ClearLogcatAsync` is separate so streaming can resume from a known point.
## Consumer
- **MAUI DevTools CLI** ([dotnet/maui-labs](https://github.com/dotnet/maui-labs)) — `maui android device logcat [--package …] [--tag …] [--since …] [--json]` with sensible MAUI defaults (tags `MauiDevFlow`, `DOTNET`, `mono-rt`, `ART`, level Info on the rest). See [maui-labs#197](https://github.com/dotnet/maui-labs/issues/197) audit.
- **DevFlow agent debugging** — pre-agent diagnostics (the agent itself emits structured logs via the HTTP API once up; this gap covers the pre-agent window).
- **Integration test fixtures** that need to assert "log line X appeared within Y seconds" without a manual parser.
## Related
- dotnet/android#12071 — Add ADB wrapper (parent issue)
- dotnet/android-tools#305 — pattern reference (ServiceHub-equivalent typed API)
- maui-labs dotnet/android-tools#197 — DevFlow skill audit; current `references/android.md` "Raw fallbacks not yet in `maui` CLI" section
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.