using SQLInsight.Core.Servers;
namespace SQLInsight.Servers;
/// Opens read-only sessions to Windows servers, as the agent's own identity.
public interface IWindowsServerSource
{
/// Connects to : WS-Man (WinRM) first, DCOM if that fails, or locally for the agent's own computer.
/// The server could not be reached; the message says why (Danish).
Task ConnectAsync(string host, CancellationToken cancellationToken);
}
///
/// One connection to a Windows server. Every method only reads: no method changes, starts or stops anything. Each
/// throws with the exact reason when its area cannot be read.
///
public interface IWindowsServerSession : IDisposable
{
/// "WS-Man", "DCOM" or "lokal".
string Protocol { get; }
/// Why the preferred protocol was not used (Danish), when it was not.
string? ProtocolNote { get; }
Task GetOperatingSystemAsync(CancellationToken cancellationToken);
Task GetPerformanceAsync(DateTimeOffset now, CancellationToken cancellationToken);
Task> GetDisksAsync(CancellationToken cancellationToken);
Task> GetServicesAsync(CancellationToken cancellationToken);
/// One service, or null when it does not exist (or cannot be seen).
Task GetServiceAsync(string name, CancellationToken cancellationToken);
/// Errors and critical events in the System and Application logs since , oldest first.
Task GetEventsAsync(DateTimeOffset since, int max, CancellationToken cancellationToken);
/// Scheduled tasks; run information only for the ones selects (at most ).
Task GetTasksAsync(Func watch, int maxWatched, CancellationToken cancellationToken);
}
/// How the logs were read: "Event Log (RPC)" or "CIM (Win32_NTLogEvent)".
/// More events than max: the rest is read next time.
public sealed record ServerEventRead(IReadOnlyList Entries, string Method, bool Truncated, string? Note = null);
/// Every task the agent could see.
public sealed record ServerTaskRead(IReadOnlyList Watched, int Visible, string? Note = null);
public enum ServerAccessProblem
{
/// The server does not answer (name, network, firewall, WinRM/RPC not running).
Unreachable,
/// The server answers, but the agent's account may not read this.
AccessDenied,
/// The server does not have it (an older Windows without the class or namespace).
NotAvailable,
/// The server did not answer in time.
Timeout,
/// The agent cannot do it at all (not on Windows).
NotSupported,
Other,
}
/// A Windows server or one of its areas could not be read. The message is Danish and says exactly why and what to do.
public sealed class ServerAccessException : Exception
{
public ServerAccessException()
{
}
public ServerAccessException(string message)
: base(message)
{
}
public ServerAccessException(string message, Exception innerException)
: base(message, innerException)
{
}
public ServerAccessException(ServerAccessProblem problem, string message, Exception? innerException = null)
: base(message, innerException)
{
Problem = problem;
}
public ServerAccessProblem Problem { get; } = ServerAccessProblem.Other;
/// The Windows error code (HRESULT) when there was one, for support.
public uint? Code { get; init; }
}
/// For an agent that does not run on Windows: Windows servers cannot be read from Linux.
public sealed class UnsupportedWindowsServerSource : IWindowsServerSource
{
public const string Reason = "Windows-servere kan kun overvåges, når SQLInsight Agent kører på Windows (CIM/WMI og hændelseslog er Windows-protokoller).";
public Task ConnectAsync(string host, CancellationToken cancellationToken) =>
throw new ServerAccessException(ServerAccessProblem.NotSupported, Reason);
}