feat(ui): gate OperationTiming.Shared behind a kill switch, off by default
Its job (surfacing the DetailsIsland.BindAsync churn) is done; leave the InvokeTimedAsync wrappers and Island Record call sites in place as a chokepoint for next time, but stop writing by default. Shared now only writes when CLAUDEDO_OP_TIMING=1 is set; the constructor keeps enabled=true so both TestSetup redirects and OperationTimingTests are unaffected.
This commit is contained in:
@@ -7,6 +7,7 @@ namespace ClaudeDo.Ui.Services;
|
||||
/// Appends one NDJSON line per timed operation (hub invoke, bulk DB read/write) to a log file, so
|
||||
/// a day of normal usage yields a file that can be sorted by duration to find real outliers.
|
||||
/// Never throws — a failed write is swallowed, because a measurement must never disturb the app.
|
||||
/// <see cref="Shared"/> is off by default; set <c>CLAUDEDO_OP_TIMING=1</c> to turn it back on.
|
||||
/// </summary>
|
||||
public sealed class OperationTiming
|
||||
{
|
||||
@@ -21,29 +22,38 @@ public sealed class OperationTiming
|
||||
public static string DefaultPath =>
|
||||
Path.Combine(Paths.AppDataRoot(), "logs", "operation-timing.ndjson");
|
||||
|
||||
/// <summary>Kill switch for <see cref="Shared"/>: off by default, set
|
||||
/// <c>CLAUDEDO_OP_TIMING=1</c> in the environment to turn the sink back on.</summary>
|
||||
private static readonly bool DefaultEnabled =
|
||||
Environment.GetEnvironmentVariable("CLAUDEDO_OP_TIMING") == "1";
|
||||
|
||||
// Settable, not just get-only: xUnit constructs real ViewModels (DetailsIslandViewModel,
|
||||
// TasksIslandViewModel, ...) that call Shared.Record directly, so without a way to redirect
|
||||
// it every test run appended its churn straight into the live app's NDJSON file at the real
|
||||
// AppData path — see Ui.Tests' TestSetup module initializer, which points this at a temp file
|
||||
// for the whole test process before any test runs.
|
||||
public static OperationTiming Shared { get; set; } = new(DefaultPath);
|
||||
public static OperationTiming Shared { get; set; } = new(DefaultPath, enabled: DefaultEnabled);
|
||||
|
||||
private static readonly int ProcessId = Environment.ProcessId;
|
||||
|
||||
private readonly string _path;
|
||||
private readonly int _minMs;
|
||||
private readonly long _maxBytes;
|
||||
private readonly bool _enabled;
|
||||
private readonly object _writeLock = new();
|
||||
|
||||
public OperationTiming(string filePath, int minMs = DefaultMinMs, long maxBytes = DefaultMaxBytes)
|
||||
public OperationTiming(string filePath, int minMs = DefaultMinMs, long maxBytes = DefaultMaxBytes, bool enabled = true)
|
||||
{
|
||||
_path = filePath;
|
||||
_minMs = minMs;
|
||||
_maxBytes = maxBytes;
|
||||
_enabled = enabled;
|
||||
}
|
||||
|
||||
public void Record(string kind, string operation, TimeSpan elapsed, bool ok)
|
||||
{
|
||||
if (!_enabled) return;
|
||||
|
||||
try
|
||||
{
|
||||
var ms = (long)elapsed.TotalMilliseconds;
|
||||
|
||||
Reference in New Issue
Block a user