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 audit. We want a typed stream so consumers can filter and emit structured JSON.
Proposed API
namespace Xamarin.Android.Tools;
public partial class AdbRunner
{
/// adb -s <serial> logcat [-v threadtime] [-T 'YYYY-MM-DD HH:mm:ss.SSS' | -d] <filterspec>
public virtual IAsyncEnumerable<LogcatEntry> LogcatAsync(
string serial,
LogcatOptions? options = null,
CancellationToken cancellationToken = default);
/// adb -s <serial> 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<LogcatFilter>? Filters = null,
/// Restrict to a process. When set, runs `adb shell pidof <package>` to resolve PID once.
string? PackageName = null,
int? Pid = null,
/// `-T <epoch|date>`: 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) —
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 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
Summary
Add structured
logcatstreaming toXamarin.Android.Tools.AdbRunnerso the MAUI DevTools CLI can surface device logs to agents and IDEs without consumers parsing rawadb logcatoutput.Context
adb logcatis 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 inlogcat. The MAUI DevTools CLI and DevFlow skills currently advise rawadb logcat …as a fallback — see maui-labs#197 audit. We want a typed stream so consumers can filter and emit structured JSON.Proposed API
Implementation notes:
-v threadtimeformat (well-defined columns) and parse line-by-line. Format spec:MM-DD HH:MM:SS.mmm PID TID L tag: message.LogcatEntryper parsed line. Cancellation kills the underlyingadb logcatprocess.PackageNameis set and PID resolution returns nothing, retry once after a short delay (covers app-not-yet-launched). After two failures, throw.ClearLogcatAsyncis separate so streaming can resume from a known point.Consumer
maui android device logcat [--package …] [--tag …] [--since …] [--json]with sensible MAUI defaults (tagsMauiDevFlow,DOTNET,mono-rt,ART, level Info on the rest). See maui-labs#197 audit.Related
references/android.md"Raw fallbacks not yet inmauiCLI" section