Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions Darling/Darling.Tests/CollectorEngineCapabilityDerivationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -477,12 +477,21 @@ public void TheShippedCatalogSplitsCleanlyOnTheKindAxis()
Assert.All(sqlServer, c => Assert.True(CollectorEngineCapability.IsCollectedOnEngineKind(c, MonitoredEngineKind.SqlServer)));
Assert.All(postgres, c => Assert.False(CollectorEngineCapability.IsCollectedOnEngineKind(c, MonitoredEngineKind.SqlServer)));

/* Aurora is a strict superset of the surfaces the PostgreSQL collectors read, so every one of them
applies there. This is the half that would break if a new collector were written against something
Aurora removes rather than adds. */
Assert.All(postgres, c => Assert.True(
CollectorEngineCapability.IsCollectedOnEngineKind(c, MonitoredEngineKind.AuroraPostgres),
$"{c.Name} is reported as a permanent gap on Aurora PostgreSQL"));
/* Aurora is a strict superset of the surfaces the PostgreSQL collectors read - with ONE exception
since #3604, and it is the case this half was written to catch: pg_wait_sampling is written against
something Aurora REMOVES (the ability to preload the module; Aurora permits a fixed list of
libraries and pg_wait_sampling is not on it), so it is a permanent gap there by design, and
CoveredInsteadBy sends an Aurora caller to pg_wait_stats, which reads the engine's own counters.
Named here rather than filtered generically, so a SECOND collector gated off Aurora has to argue
its case in this comment rather than slip through. */
var auroraGaps = postgres
.Where(c => !CollectorEngineCapability.IsCollectedOnEngineKind(c, MonitoredEngineKind.AuroraPostgres))
.Select(c => c.Name)
.ToArray();
Assert.Equal(new[] { "pg_wait_sampling" }, auroraGaps);
Assert.Contains("pg_wait_stats",
CollectorEngineCapability.NotCollectedMessage("aurora-01", 0, MonitoredEngineKind.AuroraPostgres, "pg_wait_sampling"),
StringComparison.Ordinal);

/* Stock PostgreSQL is where the Aurora-only surfaces become a real gap (#2532), so the two tokens
genuinely differ — counted from the catalog rather than listed, and asserted as a PROPER subset so
Expand Down
15 changes: 9 additions & 6 deletions Darling/Darling.Tests/CollectorStateContractTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,16 @@ public void TheCollectorsDeclaringStateArePinned()
collector is a two-host concern rather than a definition-local one. Pinned on the catalog
surface both hosts iterate.

ONE of them now: default_trace_events' last-seen trace FILE (#1962). pg_index_bloat's
per-database rotation cursor (#3153) was the other and #3234 retired it — the statistics
estimate covers every index in one statement, so there is no position to resume from. It did
not need host CODE, and neither does the survivor: the wiring below is generic. Enumerated in
the same file that pins that wiring, so a collector newly declaring state lands here first. */
TWO of them now. default_trace_events' last-seen trace FILE (#1962); pg_index_bloat's
per-database rotation cursor (#3153) was the other until #3234 retired it — the statistics
estimate covers every index in one statement, so there is no position to resume from. Then
pg_wait_sampling (#3604): the arm that ran (its instrument token, which the reads disclose) and,
on the service-sampler arm, the cumulative tally the next cycle adds to — state a MAX() over the
table cannot recover, since the table holds only the tally's last written value per key. Neither
needed host CODE: the wiring below is generic. Enumerated in the same file that pins that wiring,
so a collector newly declaring state lands here first. */
Assert.Equal(
new[] { "default_trace_events" },
new[] { "default_trace_events", "pg_wait_sampling" },
CollectorCatalog.All
.Where(c => c.StateKeys.Count > 0)
.Select(c => c.Name)
Expand Down
34 changes: 29 additions & 5 deletions Darling/Darling.Tests/DarlingCliCommandsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,16 +145,40 @@ public void FormatProbeLine_PostgresTarget_ReportsPostgresFactsAndNoSqlServerOne
Assert.DoesNotContain("Unknown (0)", line, StringComparison.Ordinal);
}

/// <summary>An Aurora writer clears every gate, so the count says so rather than listing nothing.</summary>
/// <summary>
/// An Aurora writer clears every gate but ONE, and the line names it. Until #3604 Aurora was a strict
/// superset of what the PostgreSQL collectors read and the line said "all N apply"; <c>pg_wait_sampling</c>
/// is now gated off Aurora — the engine cannot preload the module and has <c>pg_wait_stats</c> instead —
/// so the pre-flight is where an operator first sees that one collector, by name, does not run there.
/// Counted from the catalog and the collectors' own gates rather than hard-coded, so a second Aurora
/// gap shows up here as a changed count rather than a silently passing pin.
/// </summary>
[Fact]
public void FormatProbeLine_AuroraWriter_ReportsEveryPostgresCollectorApplies()
public void FormatProbeLine_AuroraWriter_ReportsEveryPostgresCollectorButTheOneAuroraCannotHave()
{
var expected = CollectorCatalog.All.Count(d => d.TargetEngine == CollectorTargetEngine.PostgreSql);
var target = PostgresProbe().ToTargetInfo();
var postgres = CollectorCatalog.All.Where(d => d.TargetEngine == CollectorTargetEngine.PostgreSql).ToList();
var skipped = postgres.Where(d => !CollectorCatalog.AppliesTo(d, target)).Select(d => d.Name).ToList();
Assert.Equal(new[] { PgWaitSamplingCollector.Instance.Name }, skipped);

var line = DarlingCliCommands.FormatProbeLine("aurora-writer", PostgresProbe());

Assert.Contains($"all {expected} PostgreSQL collectors apply", line, StringComparison.Ordinal);
Assert.DoesNotContain("skipped", line, StringComparison.Ordinal);
Assert.Contains($"{postgres.Count - 1} of {postgres.Count} PostgreSQL collectors apply", line, StringComparison.Ordinal);
Assert.Contains("skipped: pg_wait_sampling", line, StringComparison.Ordinal);
}

/// <summary>The line an Aurora writer used to get, every PostgreSQL collector applying, is now the STOCK
/// writer's with the extension present — the shape #3604 made the finest stock tier.</summary>
[Fact]
public void FormatProbeLine_StockWriterWithTheExtension_ReportsEveryPostgresCollectorApplies()
{
var expected = CollectorCatalog.All.Count(d => d.TargetEngine == CollectorTargetEngine.PostgreSql);
var probe = PostgresProbe() with { IsAurora = false, HasPgWaitSamplingExtension = true };

/* pg_wait_stats and pg_cpu_utilization are Aurora-only, so a stock target skips those two instead. */
var line = DarlingCliCommands.FormatProbeLine("stock-writer", probe);
Assert.Contains($"{expected - 2} of {expected} PostgreSQL collectors apply", line, StringComparison.Ordinal);
Assert.DoesNotContain("pg_wait_sampling", line, StringComparison.Ordinal);
}

/// <summary>
Expand Down
20 changes: 20 additions & 0 deletions Darling/Darling.Tests/DarlingComposeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,16 @@ SQL Server target when the engine half is skipped. */
PostgresMajorVersion = 17, PostgresVersionNum = 170_005, IsInRecovery = false,
};

/* #3604: pg_wait_sampling is gated OFF Aurora (the module cannot be preloaded there; pg_wait_stats is
the instrument on that engine), so its measures surface for a stock writer instead. Every other
PostgreSQL measure still clears the Aurora writer, and the two shapes together still cover the
whole PostgreSQL measure set - which is the property this test exists for. */
var stockWriterWithExtension = new CollectorTargetInfo
{
Engine = CollectorTargetEngine.PostgreSql, IsAurora = false, HasPgWaitSamplingExtension = true,
PostgresMajorVersion = 17, PostgresVersionNum = 170_005, IsInRecovery = false,
};

var pg = PostgresMeasures();
Assert.NotEmpty(pg);
foreach (var measure in pg)
Expand All @@ -308,6 +318,16 @@ SQL Server target when the engine half is skipped. */
$"pg measure '{measure.Key}' source '{measure.SourceTable}' engine gate must exclude SQL Server.");
Assert.False(CollectorCatalog.AppliesTo(collector!, sqlServer),
$"pg measure '{measure.Key}' source '{measure.SourceTable}' must not apply to a SQL Server target.");

if (string.Equals(measure.SourceTable, PgWaitSamplingCollector.Instance.TargetTable, StringComparison.Ordinal))
{
Assert.False(CollectorCatalog.AppliesTo(collector!, auroraWriter),
$"pg measure '{measure.Key}' reads pg_wait_sampling, which #3604 gated off Aurora - it must not surface there.");
Assert.True(CollectorCatalog.AppliesTo(collector!, stockWriterWithExtension),
$"pg measure '{measure.Key}' source '{measure.SourceTable}' must apply to a stock writer with the extension.");
continue;
}

Assert.True(CollectorCatalog.AppliesTo(collector!, auroraWriter),
$"pg measure '{measure.Key}' source '{measure.SourceTable}' must apply to a modern Aurora writer.");
}
Expand Down
Loading
Loading