Review 1.2: keep SQL Server's error message out of the replication reason
When the distribution database could not be read, SQL Server's message (which names the agent's login) was appended to Unavailable. That text is the rules' "not measurable" reason and is returned unredacted by /rule-states and /replication. It is now UnavailableDetail: shown on the local instance page and [udeladt] in the API unless ApiIncludesSensitiveEvidence. The agent list is also capped (TOP 500). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fcf2466738
commit
a01ec374a4
4 changed files with 9 additions and 3 deletions
|
|
@ -14,7 +14,7 @@ public sealed class ReplicationCollector : Collector<ReplicationSnapshot>
|
||||||
internal const string DistributionDatabaseSql = "SELECT TOP 1 name FROM sys.databases WHERE is_distributor = 1 AND state = 0";
|
internal const string DistributionDatabaseSql = "SELECT TOP 1 name FROM sys.databases WHERE is_distributor = 1 AND state = 0";
|
||||||
|
|
||||||
internal const string AgentsSql = """
|
internal const string AgentsSql = """
|
||||||
SELECT a.name, a.publisher_db, h.runstatus, DATEADD(minute, DATEDIFF(minute, GETDATE(), GETUTCDATE()), h.time), h.delivery_latency,
|
SELECT TOP 500 a.name, a.publisher_db, h.runstatus, DATEADD(minute, DATEDIFF(minute, GETDATE(), GETUTCDATE()), h.time), h.delivery_latency,
|
||||||
CAST(h.comments AS nvarchar(500))
|
CAST(h.comments AS nvarchar(500))
|
||||||
FROM dbo.MSdistribution_agents a
|
FROM dbo.MSdistribution_agents a
|
||||||
OUTER APPLY (SELECT TOP 1 x.runstatus, x.time, x.delivery_latency, x.comments FROM dbo.MSdistribution_history x
|
OUTER APPLY (SELECT TOP 1 x.runstatus, x.time, x.delivery_latency, x.comments FROM dbo.MSdistribution_history x
|
||||||
|
|
@ -58,7 +58,9 @@ public sealed class ReplicationCollector : Collector<ReplicationSnapshot>
|
||||||
return new ReplicationSnapshot
|
return new ReplicationSnapshot
|
||||||
{
|
{
|
||||||
CapturedAt = context.Now, IsDistributor = true, DistributionDatabase = distribution,
|
CapturedAt = context.Now, IsDistributor = true, DistributionDatabase = distribution,
|
||||||
Unavailable = NoRightsText + " (" + ex.Message.Split('\n')[0].Trim() + ")",
|
// The error message names the agent's login: kept apart from the reason, which rules and the API show as is.
|
||||||
|
Unavailable = NoRightsText,
|
||||||
|
UnavailableDetail = ex.Message.Split('\n')[0].Trim(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@ public sealed record ReplicationSnapshot
|
||||||
/// <summary>Why the distribution database could not be read (typically no SELECT rights); null when it could.</summary>
|
/// <summary>Why the distribution database could not be read (typically no SELECT rights); null when it could.</summary>
|
||||||
public string? Unavailable { get; init; }
|
public string? Unavailable { get; init; }
|
||||||
|
|
||||||
|
/// <summary>SQL Server's error message when it could not be read. Names the agent's login: sensitive (local UI only).</summary>
|
||||||
|
public string? UnavailableDetail { get; init; }
|
||||||
|
|
||||||
public IReadOnlyList<DistributionAgent> Agents { get; init; } = [];
|
public IReadOnlyList<DistributionAgent> Agents { get; init; } = [];
|
||||||
|
|
||||||
/// <summary>Rows in MSrepl_errors the last 24 hours.</summary>
|
/// <summary>Rows in MSrepl_errors the last 24 hours.</summary>
|
||||||
|
|
|
||||||
|
|
@ -572,6 +572,7 @@ public static class ApiV1Endpoints
|
||||||
IsDistributor = r?.IsDistributor,
|
IsDistributor = r?.IsDistributor,
|
||||||
r?.DistributionDatabase,
|
r?.DistributionDatabase,
|
||||||
r?.Unavailable,
|
r?.Unavailable,
|
||||||
|
UnavailableDetail = redact.Value(r?.UnavailableDetail),
|
||||||
r?.ErrorsLastDay,
|
r?.ErrorsLastDay,
|
||||||
Agents = (r?.Agents ?? []).Select(a => new { a.Name, a.PublisherDatabase, a.RunStatus, a.StatusText, a.LastRunAt, a.DeliveryLatencyMs, Comment = redact.Value(a.Comment) }),
|
Agents = (r?.Agents ?? []).Select(a => new { a.Name, a.PublisherDatabase, a.RunStatus, a.StatusText, a.LastRunAt, a.DeliveryLatencyMs, Comment = redact.Value(a.Comment) }),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ else
|
||||||
<div class="card-head"><h2>Replikering</h2><span class="muted">distributionsdatabase @repl.DistributionDatabase</span></div>
|
<div class="card-head"><h2>Replikering</h2><span class="muted">distributionsdatabase @repl.DistributionDatabase</span></div>
|
||||||
@if (repl.Unavailable is { } why)
|
@if (repl.Unavailable is { } why)
|
||||||
{
|
{
|
||||||
<p class="muted">@why</p>
|
<p class="muted">@why@(repl.UnavailableDetail is { } detail ? " (" + detail + ")" : "")</p>
|
||||||
}
|
}
|
||||||
else if (repl.Agents.Count == 0)
|
else if (repl.Agents.Count == 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue