using SQLInsight.Core.Data; namespace SQLInsight.Collectors.Instance; public sealed class ServerCollector : Collector { public override string Name => "server"; public override TimeSpan DefaultInterval => TimeSpan.FromMinutes(15); protected override async Task CollectAsync(CollectorContext context, ServerSnapshot? previous) { var version = context.Instance.Version; var ct = context.CancellationToken; if (version.Major < 9) { return await CollectSql2000Async(context).ConfigureAwait(false); } var memory = version.Major >= 11 ? "physical_memory_kb / 1024" : "physical_memory_in_bytes / 1048576"; var vmType = version >= new Core.Instances.SqlServerVersion(10, 50, 2500, 0) ? "virtual_machine_type_desc" : "CAST(NULL AS nvarchar(60))"; var sql = $""" SELECT {Db.StartTimeExpression(version)}, cpu_count, (SELECT COUNT(*) FROM sys.dm_os_schedulers WHERE status = N'VISIBLE ONLINE'), (SELECT COUNT(DISTINCT parent_node_id) FROM sys.dm_os_schedulers WHERE status = N'VISIBLE ONLINE'), {memory}, {vmType} FROM sys.dm_os_sys_info """; var snapshot = await Db.QuerySingleAsync(context.Connection, sql, r => new ServerSnapshot { CapturedAt = context.Now, SqlServerStartTime = r.DateTime(0), LogicalCpuCount = r.Int(1), VisibleOnlineSchedulers = r.Int(2), NumaNodeCount = version.Major >= 10 ? r.Int(3) : null, PhysicalMemoryMb = r.Long(4), VirtualMachineType = r.NullableString(5), }, ct).ConfigureAwait(false); return snapshot ?? throw new InvalidOperationException("sys.dm_os_sys_info returned no rows."); } private static async Task CollectSql2000Async(CollectorContext context) { var ct = context.CancellationToken; var startTime = await Db.StartTimeAsync(context.Connection, context.Instance.Version, ct).ConfigureAwait(false); // xp_msver: Index, Name, Internal_Value, Character_Value. var msver = await Db.QueryAsync(context.Connection, "EXEC master.dbo.xp_msver", r => (Name: r.String(1), Value: r.NullableLong(2)), ct) .ConfigureAwait(false); long? Get(string name) => msver.FirstOrDefault(m => string.Equals(m.Name, name, StringComparison.OrdinalIgnoreCase)).Value; return new ServerSnapshot { CapturedAt = context.Now, SqlServerStartTime = startTime, LogicalCpuCount = (int)(Get("ProcessorCount") ?? 0), PhysicalMemoryMb = Get("PhysicalMemory"), }; } }