using System.Text.Json; namespace SQLInsight.Core.Configuration; /// /// What SQLInsight Web asks the agent to do (insight.AgentRequests). Connection tests and discovery run in the agent, /// as the agent's identity, because that is what connects to the instances in production; the web UI only queues the /// request and shows the result. /// public static class AgentRequestKind { /// Connect to a configured instance and check the agent's rights there. public const string ConnectionTest = "ConnectionTest"; /// List the databases on a configured instance (state, size, recovery model, Dynamics AX …). public const string DatabaseDiscovery = "DatabaseDiscovery"; /// Find SQL Server instances on a computer (SQL Server Browser, and the registry on the agent's own computer). public const string InstanceDiscovery = "InstanceDiscovery"; public static readonly IReadOnlyList All = [ConnectionTest, DatabaseDiscovery, InstanceDiscovery]; } public static class AgentRequestStatus { public const string Pending = "Pending"; public const string Running = "Running"; public const string Done = "Done"; public const string Failed = "Failed"; } /// JSON of request parameters and results, shared by the agent (writes) and the web UI and API (reads). public static class AgentRequestJson { public static readonly JsonSerializerOptions Options = new(JsonSerializerDefaults.Web); public static string Serialize(T value) => JsonSerializer.Serialize(value, Options); public static T? Deserialize(string? json) where T : class { if (string.IsNullOrWhiteSpace(json)) { return null; } try { return JsonSerializer.Deserialize(json, Options); } catch (JsonException) { return null; } } } /// Parameters of an . /// The computer to ask; empty for the agent's own computer. public sealed record InstanceDiscoveryParameters(string? Host); /// One right the agent needs (or may have) on an instance, and whether it has it. /// The permission as written in GRANT, e.g. VIEW SERVER STATE, or SELECT ON msdb.dbo.backupset. /// False for optional rights (ALTER TRACE): missing them limits a feature, not the monitoring. /// What SQLInsight uses it for (Danish). public sealed record PermissionStatus(string Name, bool Granted, bool Required, string Purpose); /// The outcome of a connection test, as the agent saw it. public sealed record ConnectionTestResult { public bool Connected { get; init; } public string? Error { get; init; } /// What to do about (Danish). public string? Hint { get; init; } public string? Provider { get; init; } public bool UsedLegacyFallback { get; init; } public string? ProductVersion { get; init; } public string? Release { get; init; } public string? Edition { get; init; } public string? ServerName { get; init; } /// The login the agent arrived as (SUSER_SNAME()): the one the GRANT script is for. public string? Login { get; init; } /// The agent is sysadmin on the instance. It works, but it is more than it needs. public bool IsSysadmin { get; init; } /// False on SQL Server 2000, which cannot report effective permissions (no HAS_PERMS_BY_NAME). public bool PermissionsChecked { get; init; } public IReadOnlyList Permissions { get; init; } = []; /// Notes about the result, e.g. why permissions were not checked (Danish). public IReadOnlyList Notes { get; init; } = []; public IEnumerable MissingRequired => Permissions.Where(p => p.Required && !p.Granted); } /// A database as the agent found it on an instance. public sealed record DiscoveredDatabase { public required string Name { get; init; } public int DatabaseId { get; init; } public string State { get; init; } = "ONLINE"; public long? SizeMb { get; init; } public string? RecoveryModel { get; init; } public int? CompatibilityLevel { get; init; } public bool IsReadOnly { get; init; } public bool IsSystem { get; init; } /// A database snapshot (not monitored on its own). public bool IsSnapshot { get; init; } /// The agent can enter the database (HAS_DBACCESS); without it, database-specific checks cannot run there. public bool HasAccess { get; init; } /// Recognised as Dynamics AX by the central detection (Core/DynamicsAx/AxDetection.cs). public bool IsDynamicsAx { get; init; } /// The AX version as ("3.0", "2009", "2012 R2/R3" …), when . public string? DynamicsAxVersion { get; init; } } /// Summary of a database discovery; the databases themselves are in insight.ConfiguredDatabases. public sealed record DatabaseDiscoveryResult { public int Databases { get; init; } public IReadOnlyList New { get; init; } = []; public IReadOnlyList Gone { get; init; } = []; /// New databases were monitored at once (the instance monitors new databases automatically). public bool NewMonitored { get; init; } public string? Error { get; init; } public string? Hint { get; init; } } /// A SQL Server instance found on a computer. /// What to type as the server: HOST or HOST\INSTANCE. /// Where it was found (Danish): "SQL Server Browser" or "registreringsdatabasen". public sealed record DiscoveredInstance(string Server, string InstanceName, string? Version, int? TcpPort, bool IsClustered, string Source); public sealed record InstanceDiscoveryResult { public string Host { get; init; } = string.Empty; public IReadOnlyList Instances { get; init; } = []; public IReadOnlyList Notes { get; init; } = []; }