sqlinsight-pro/src/SQLInsight.Contracts/HubInsights.cs
Claude 4269f6f9e8
Some checks are pending
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
Fase 4: experience across customers
The hub records when an instance changes build and works out which
findings went away within three days of an update and which were still
there a week later (version rules excluded). Staff see every effect in
the portal; effects seen at three or more customers, resolved more
often than not, are served to licensed agents as anonymous counts
(rule, major version, build, CU, customers, instances). The agent
fetches them every six hours and the web UI shows them on matching
findings: 'at 3 customers this went away after updating to CU21'.
Data processing documentation covers the aggregation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 10:33:37 +00:00

37 lines
1.8 KiB
C#

namespace SQLInsight.Contracts;
/// <summary>
/// Aggregated experience across SQLInsight Hub customers, sent back to agents. Contains no customer, instance or
/// server names: only counts, and only when at least <see cref="MinCustomers"/> different customers are behind them.
/// </summary>
public sealed record HubInsights(DateTimeOffset GeneratedAt, int MinCustomers, IReadOnlyList<UpgradeInsight> Upgrades);
/// <summary>
/// After instances of SQL Server major version <see cref="Major"/> were updated to <see cref="ToBuild"/> or newer, findings
/// of <see cref="RuleId"/> they had went away within a few days on <see cref="Resolved"/> instances and stayed on
/// <see cref="Persisted"/>. Correlation, not proof of cause.
/// </summary>
public sealed record UpgradeInsight(string RuleId, int Major, string ToBuild, string? ToLevel, int Customers, int Resolved, int Persisted)
{
public double ResolvedShare => Resolved + Persisted == 0 ? 0 : (double)Resolved / (Resolved + Persisted);
}
public static class HubInsightMatcher
{
/// <summary>
/// Insights relevant to a finding: the same rule, the same major version, and a build newer than the instance's.
/// The one backed by most customers first.
/// </summary>
public static IReadOnlyList<UpgradeInsight> For(HubInsights? insights, string ruleId, string? productVersion)
{
if (insights is null || productVersion is null || !Version.TryParse(productVersion, out var current))
{
return [];
}
return insights.Upgrades
.Where(i => i.RuleId == ruleId && i.Major == current.Major && Version.TryParse(i.ToBuild, out var build) && build > current)
.OrderByDescending(i => i.Customers).ThenBy(i => Version.Parse(i.ToBuild))
.ToList();
}
}