diff --git a/.editorconfig b/.editorconfig index e579e4cff..c35e65cd1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -103,23 +103,12 @@ dotnet_naming_symbols.constant_fields.required_modifiers = const dotnet_naming_style.prefix_underscore.capitalization = camel_case dotnet_naming_style.prefix_underscore.required_prefix = _ -# CA1027: Mark enums with FlagsAttribute -dotnet_diagnostic.CA1027.severity = none - -# CA1031: Do not catch general exception types -dotnet_diagnostic.CA1031.severity = none - -# CA1034: Nested types should not be visible -dotnet_diagnostic.CA1034.severity = none - -# CA1063: Implement IDisposable Correctly -dotnet_diagnostic.CA1063.severity = none - -# CA1810: Initialize reference type static fields inline -dotnet_diagnostic.CA1810.severity = none - -# CA1819: Properties should not return arrays -dotnet_diagnostic.CA1819.severity = none - -# CA1822: Mark members as static -dotnet_diagnostic.CA1822.severity = none \ No newline at end of file +dotnet_diagnostic.CA1027.severity = none # CA1027: Mark enums with FlagsAttribute +dotnet_diagnostic.CA1031.severity = none # CA1031: Do not catch general exception types +dotnet_diagnostic.CA1034.severity = none # CA1034: Nested types should not be visible +dotnet_diagnostic.CA1063.severity = none # CA1063: Implement IDisposable Correctly +dotnet_diagnostic.CA1810.severity = none # CA1810: Initialize reference type static fields inline +dotnet_diagnostic.CA1819.severity = none # CA1819: Properties should not return arrays +dotnet_diagnostic.CA1822.severity = none # CA1822: Mark members as static + +dotnet_diagnostic.IDE0130.severity = none # IDE0130: Namespace does not match folder structure diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 000000000..18eaa2c34 --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,40 @@ + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Opserver.sln b/Opserver.sln index b59c3045f..a5f37a41c 100644 --- a/Opserver.sln +++ b/Opserver.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29021.104 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35521.163 d17.12 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Opserver.Core", "src\Opserver.Core\Opserver.Core.csproj", "{C58AFF99-F4D9-4A83-866E-18DA0A633F6B}" EndProject @@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution appveyor.yml = appveyor.yml azure-pipelines.yml = azure-pipelines.yml Build.bat = Build.bat + Directory.Packages.props = Directory.Packages.props global.json = global.json nuget.config = nuget.config readme.md = readme.md diff --git a/nuget.config b/nuget.config index 15932f7c9..b004e5cc7 100644 --- a/nuget.config +++ b/nuget.config @@ -2,7 +2,6 @@ - \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 21c82dae4..f33f9c5d8 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,6 @@ - 8.0 + 11.0 true $(MSBuildThisFileDirectory)Opserver.ruleset @@ -16,15 +16,10 @@ en-US false true - - - - - diff --git a/src/Opserver.Core/Data/Cache.cs b/src/Opserver.Core/Data/Cache.cs index 05d25900b..639a9835d 100644 --- a/src/Opserver.Core/Data/Cache.cs +++ b/src/Opserver.Core/Data/Cache.cs @@ -20,7 +20,7 @@ public class Cache : Cache where T : class private int _hasData; internal override object InnerCache => Data; public override Type Type => typeof (T); - private readonly SemaphoreSlim _pollSemaphoreSlim = new SemaphoreSlim(1); + private readonly SemaphoreSlim _pollSemaphoreSlim = new(1); public override string InventoryDescription { @@ -116,7 +116,7 @@ private async Task UpdateAsync(bool force) private string MiniProfilerDescription { get; } // ReSharper disable once StaticMemberInGenericType - private static readonly MiniProfilerBaseOptions _profilerOptions = new MiniProfilerBaseOptions + private static readonly MiniProfilerBaseOptions _profilerOptions = new() { Storage = new NullStorage(), ProfilerProvider = new DefaultProfilerProvider() diff --git a/src/Opserver.Core/Data/CloudFlare/CloudFlareAPI.Zones.cs b/src/Opserver.Core/Data/CloudFlare/CloudFlareAPI.Zones.cs index b3a53138c..ca89fc4da 100644 --- a/src/Opserver.Core/Data/CloudFlare/CloudFlareAPI.Zones.cs +++ b/src/Opserver.Core/Data/CloudFlare/CloudFlareAPI.Zones.cs @@ -12,7 +12,7 @@ public partial class CloudflareAPI public Cache> Zones => _zones ??= GetCloudflareCache(5.Minutes(), () => Get>("zones")); - private static readonly NameValueCollection _dnsRecordFetchParams = new NameValueCollection + private static readonly NameValueCollection _dnsRecordFetchParams = new() { ["per_page"] = "100" }; @@ -45,19 +45,12 @@ public CloudflareZone GetZoneFromUrl(string url) => /// /// The DNS record to get an IP for /// Root IP Addresses for this record. - public List GetIPs(CloudflareDNSRecord record) + public List GetIPs(CloudflareDNSRecord record) => record.Type switch { - switch (record.Type) - { - case DNSRecordType.A: - case DNSRecordType.AAAA: - return new List { record.IPAddress }; - case DNSRecordType.CNAME: - return GetIPs(record.Content); - default: - return null; - } - } + DNSRecordType.A or DNSRecordType.AAAA => new List { record.IPAddress }, + DNSRecordType.CNAME => GetIPs(record.Content), + _ => null, + }; /// /// Get the IP Addresses for a given fully qualified host (star records not supported), even through CNAME chains. diff --git a/src/Opserver.Core/Data/CloudFlare/CloudFlareModule.cs b/src/Opserver.Core/Data/CloudFlare/CloudFlareModule.cs index caf5f2f64..60de698ad 100644 --- a/src/Opserver.Core/Data/CloudFlare/CloudFlareModule.cs +++ b/src/Opserver.Core/Data/CloudFlare/CloudFlareModule.cs @@ -36,7 +36,7 @@ public CloudflareModule(IConfiguration config, PollingService poller) : base(con public List GetDNSRecords(CloudflareZone zone) => API.DNSRecords.Data?.Where(r => r.ZoneId == zone.Id).ToList() ?? new List(); - private static readonly NameValueCollection _purgeAllParams = new NameValueCollection + private static readonly NameValueCollection _purgeAllParams = new() { ["purge_everything"] = "true" }; @@ -69,7 +69,7 @@ public IEnumerable GetMaskedIPs(List addresses) } } - private readonly ConcurrentDictionary _cached = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _cached = new(); private string GetMaskedIP(IPAddress address) { diff --git a/src/Opserver.Core/Data/CloudFlare/CloudFlareResponse.cs b/src/Opserver.Core/Data/CloudFlare/CloudFlareResponse.cs index f7744d5ce..a1950d240 100644 --- a/src/Opserver.Core/Data/CloudFlare/CloudFlareResponse.cs +++ b/src/Opserver.Core/Data/CloudFlare/CloudFlareResponse.cs @@ -94,27 +94,14 @@ public class CloudflareZone : IMonitorStatus [DataMember(Name = "permissions")] public List Permissons { get; set; } - public MonitorStatus MonitorStatus + public MonitorStatus MonitorStatus => Status switch { - get - { - switch (Status) - { - case ZoneStatus.Active: - return MonitorStatus.Good; - case ZoneStatus.Pending: - case ZoneStatus.Initializing: - case ZoneStatus.Moved: - return MonitorStatus.Warning; - case ZoneStatus.Deleted: - return MonitorStatus.Critical; - case ZoneStatus.Deactivated: - return MonitorStatus.Maintenance; - default: - return MonitorStatus.Unknown; - } - } - } + ZoneStatus.Active => MonitorStatus.Good, + ZoneStatus.Pending or ZoneStatus.Initializing or ZoneStatus.Moved => MonitorStatus.Warning, + ZoneStatus.Deleted => MonitorStatus.Critical, + ZoneStatus.Deactivated => MonitorStatus.Maintenance, + _ => MonitorStatus.Unknown, + }; public string MonitorStatusReason => "Current status: " + Status; } diff --git a/src/Opserver.Core/Data/Dashboard/HardwareSummary.cs b/src/Opserver.Core/Data/Dashboard/HardwareSummary.cs index 7ffbf8c9e..8e4aa85c2 100644 --- a/src/Opserver.Core/Data/Dashboard/HardwareSummary.cs +++ b/src/Opserver.Core/Data/Dashboard/HardwareSummary.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System; namespace Opserver.Data.Dashboard { @@ -48,7 +49,7 @@ public int? Label if (Bank == null) return null; if (Name.Length > Bank.Length) { - if (int.TryParse(Name.Substring(Bank.Length), out int position)) + if (int.TryParse(Name.AsSpan(Bank.Length), out int position)) { _label = position; } diff --git a/src/Opserver.Core/Data/Dashboard/Interface.cs b/src/Opserver.Core/Data/Dashboard/Interface.cs index e4a2d9cf6..67542b8f5 100644 --- a/src/Opserver.Core/Data/Dashboard/Interface.cs +++ b/src/Opserver.Core/Data/Dashboard/Interface.cs @@ -19,7 +19,7 @@ public partial class Interface : IMonitorStatus public string Alias { get; internal set; } public string TypeDescription { get; internal set; } public string PhysicalAddress { get; internal set; } - public bool IsTeam => TeamMembers?.Any() ?? false; + public bool IsTeam => TeamMembers?.Count > 0; public bool IsUnwatched { get; internal set; } public NodeStatus Status { get; internal set; } @@ -40,7 +40,7 @@ public partial class Interface : IMonitorStatus // TODO: Implement public string MonitorStatusReason => null; - private static readonly Dictionary _prettyNameReplacements = new Dictionary + private static readonly Dictionary _prettyNameReplacements = new() { ["Microsoft Network Adapter Multiplexor Driver"] = "Microsoft Team", ["Quad Port Server Adapter"] = "Quad Port SA", @@ -72,7 +72,7 @@ public string PrettySpeed get { if (!Speed.HasValue) { - if (!(TeamMembers?.Any() ?? false)) + if (!(TeamMembers?.Count > 0)) { return "n/a"; } @@ -91,7 +91,7 @@ public string PrettySpeed public string PrettyMAC => PhysicalAddress?.Length == 12 - ? $"{PhysicalAddress.Substring(0, 2)}-{PhysicalAddress.Substring(2, 2)}-{PhysicalAddress.Substring(4, 2)}-{PhysicalAddress.Substring(6, 2)}-{PhysicalAddress.Substring(8, 2)}-{PhysicalAddress.Substring(10, 2)}" + ? $"{PhysicalAddress[..2]}-{PhysicalAddress.Substring(2, 2)}-{PhysicalAddress.Substring(4, 2)}-{PhysicalAddress.Substring(6, 2)}-{PhysicalAddress.Substring(8, 2)}-{PhysicalAddress.Substring(10, 2)}" : PhysicalAddress; internal bool IsLikelyPrimary(Regex pattern) => pattern != null diff --git a/src/Opserver.Core/Data/Dashboard/Node.cs b/src/Opserver.Core/Data/Dashboard/Node.cs index 2c1408cf9..95350c533 100644 --- a/src/Opserver.Core/Data/Dashboard/Node.cs +++ b/src/Opserver.Core/Data/Dashboard/Node.cs @@ -269,7 +269,7 @@ public NodeService GetService(string id) return null; } - private static readonly List EmptyIPs = new List(); + private static readonly List EmptyIPs = new(); public List IPs => Interfaces?.SelectMany(i => i.IPs).ToList() ?? EmptyIPs; diff --git a/src/Opserver.Core/Data/Dashboard/NodeStatus.cs b/src/Opserver.Core/Data/Dashboard/NodeStatus.cs index 6ed204048..7a4d6f85a 100644 --- a/src/Opserver.Core/Data/Dashboard/NodeStatus.cs +++ b/src/Opserver.Core/Data/Dashboard/NodeStatus.cs @@ -27,30 +27,15 @@ public enum NodeStatus public static class ServerStatusExtensions { - public static MonitorStatus ToMonitorStatus(this NodeStatus status) + public static MonitorStatus ToMonitorStatus(this NodeStatus status) => status switch { - switch (status) - { - case NodeStatus.Unmanaged: - return MonitorStatus.Maintenance; - case NodeStatus.Active: - case NodeStatus.External: - case NodeStatus.Up: - case NodeStatus.Shutdown: - return MonitorStatus.Good; - case NodeStatus.Down: - case NodeStatus.Critical: - return MonitorStatus.Critical; - case NodeStatus.Unreachable: - case NodeStatus.Warning: - case NodeStatus.PartlyAvailable: - case NodeStatus.Unconfirmed: - return MonitorStatus.Warning; - //case NodeStatus.Inactive: - //case NodeStatus.Unplugged: - default: - return MonitorStatus.Unknown; - } - } + NodeStatus.Unmanaged => MonitorStatus.Maintenance, + NodeStatus.Active or NodeStatus.External or NodeStatus.Up or NodeStatus.Shutdown => MonitorStatus.Good, + NodeStatus.Down or NodeStatus.Critical => MonitorStatus.Critical, + NodeStatus.Unreachable or NodeStatus.Warning or NodeStatus.PartlyAvailable or NodeStatus.Unconfirmed => MonitorStatus.Warning, + //case NodeStatus.Inactive: + //case NodeStatus.Unplugged: + _ => MonitorStatus.Unknown, + }; } -} \ No newline at end of file +} diff --git a/src/Opserver.Core/Data/Dashboard/Providers/BosunDataProvider.Metrics.cs b/src/Opserver.Core/Data/Dashboard/Providers/BosunDataProvider.Metrics.cs index 56a314eae..90bb25387 100644 --- a/src/Opserver.Core/Data/Dashboard/Providers/BosunDataProvider.Metrics.cs +++ b/src/Opserver.Core/Data/Dashboard/Providers/BosunDataProvider.Metrics.cs @@ -87,7 +87,7 @@ async Task addMetric(string metricName, string[] tags) var tagDict = tags?.ToDictionary(t => t, _ => "*"); var apiResult = await GetMetric(metricName, result.StartTime, tags: tagDict); if (apiResult == null) return; - if (tags?.Any() ?? false) + if (tags?.Length > 0) { result.MultiSeries[metricName] = apiResult.Series .GroupBy(s => s.Host) @@ -171,15 +171,14 @@ public static class TagValues public static class TagCombos { public static readonly Dictionary - AllNetDirections = new Dictionary {[Tags.Direction] = "*" }, - AllDisks = new Dictionary {[Tags.Disk] = "*" }; + AllNetDirections = new() { [Tags.Direction] = "*" }, + AllDisks = new() { [Tags.Disk] = "*" }; - public static Dictionary AllDirectionsForInterface(string ifaceId) - => new Dictionary - { - [Tags.Direction] = "*", - [Tags.IFace] = ifaceId - }; + public static Dictionary AllDirectionsForInterface(string ifaceId) => new() + { + [Tags.Direction] = "*", + [Tags.IFace] = ifaceId + }; } public static bool IsCounter(string metric, string host) @@ -189,18 +188,11 @@ public static bool IsCounter(string metric, string host) { metric = metric.Replace($"__{host}.", ""); } - switch (metric) + return metric switch { - case Globals.CPU: - case Globals.NetBytes: - case Globals.NetBondBytes: - case Globals.NetOtherBytes: - case Globals.NetTunnelBytes: - case Globals.NetVirtualBytes: - return true; - default: - return false; - } + Globals.CPU or Globals.NetBytes or Globals.NetBondBytes or Globals.NetOtherBytes or Globals.NetTunnelBytes or Globals.NetVirtualBytes => true, + _ => false, + }; } public static string InterfaceMetricName(Interface i) => @@ -215,7 +207,7 @@ public static string InterfaceMetricName(Interface i) => public static string GetDenormalized(string metric, string host, Dictionary> metricCache) { - if (host == null || host.Contains("*") || host.Contains("|")) + if (host == null || host.Contains('*') || host.Contains('|')) { return metric; } @@ -264,7 +256,7 @@ public class BosunMetricResponse /// public class PointSeries { - private static readonly Regex HostRegex = new Regex(@"\{host=(.*)[,|\}]", RegexOptions.Compiled); + private static readonly Regex HostRegex = new(@"\{host=(.*)[,|\}]", RegexOptions.Compiled); private string _host; public string Host { @@ -272,9 +264,9 @@ public string Host { if (_host == null) { - if (Tags.ContainsKey("host")) + if (Tags.TryGetValue("host", out string value)) { - Host = Tags["host"]; + Host = value; } else { diff --git a/src/Opserver.Core/Data/Dashboard/Providers/BosunDataProvider.Nodes.cs b/src/Opserver.Core/Data/Dashboard/Providers/BosunDataProvider.Nodes.cs index 1ca8b5df7..ddc17ccf9 100644 --- a/src/Opserver.Core/Data/Dashboard/Providers/BosunDataProvider.Nodes.cs +++ b/src/Opserver.Core/Data/Dashboard/Providers/BosunDataProvider.Nodes.cs @@ -265,16 +265,14 @@ public async Task> GetAllNodesAsync() AppName = key, NiceName = key }; - BosunHost.ProcessInfo process = null; - if (h.Processes?.TryGetValue(key, out process) == true) + if (h.Processes?.TryGetValue(key, out var process) == true) { app.PercentCPU = (decimal)process.CPUPercentUsed; app.CurrentPercentCPU = process.CPUPercentUsed; app.MemoryUsed = process.UsedRealBytes; app.VirtualMemoryUsed = process.UsedVirtualBytes; } - BosunHost.ServiceInfo service = null; - if (h.Services?.TryGetValue(key, out service) == true) + if (h.Services?.TryGetValue(key, out var service) == true) { app.IsRunning = service.Running; } diff --git a/src/Opserver.Core/Data/Dashboard/Providers/BosunDataProvider.cs b/src/Opserver.Core/Data/Dashboard/Providers/BosunDataProvider.cs index 42cc86369..d6c0b043e 100644 --- a/src/Opserver.Core/Data/Dashboard/Providers/BosunDataProvider.cs +++ b/src/Opserver.Core/Data/Dashboard/Providers/BosunDataProvider.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Net; using System.Threading.Tasks; using Jil; using StackExchange.Profiling; diff --git a/src/Opserver.Core/Data/Dashboard/Providers/DashboardDataProvider.cs b/src/Opserver.Core/Data/Dashboard/Providers/DashboardDataProvider.cs index 466afe424..3b78d44f0 100644 --- a/src/Opserver.Core/Data/Dashboard/Providers/DashboardDataProvider.cs +++ b/src/Opserver.Core/Data/Dashboard/Providers/DashboardDataProvider.cs @@ -64,7 +64,7 @@ public virtual IEnumerable GetExceptions() public Node GetNodeByHostname(string hostName) { if (!Module.Settings.Enabled || hostName.IsNullOrEmpty()) return null; - return AllNodes.Find(s => s.Name.IndexOf(hostName, StringComparison.InvariantCultureIgnoreCase) >= 0); + return AllNodes.Find(s => s.Name.Contains(hostName, StringComparison.InvariantCultureIgnoreCase)); } public virtual IEnumerable GetNodesByIP(IPAddress ip) => diff --git a/src/Opserver.Core/Data/Dashboard/Providers/EmptyDataProvider.cs b/src/Opserver.Core/Data/Dashboard/Providers/EmptyDataProvider.cs index 720f55ced..06be9f9db 100644 --- a/src/Opserver.Core/Data/Dashboard/Providers/EmptyDataProvider.cs +++ b/src/Opserver.Core/Data/Dashboard/Providers/EmptyDataProvider.cs @@ -17,7 +17,7 @@ public EmptyDataProvider(DashboardModule module, string uniqueKey) : base(module protected override IEnumerable GetMonitorStatus() => Enumerable.Empty(); protected override string GetMonitorStatusReason() => null; - private static readonly List EmptyAllNodes = new List(); + private static readonly List EmptyAllNodes = new(); public override IEnumerable GetExceptions() => Enumerable.Empty(); diff --git a/src/Opserver.Core/Data/Dashboard/Providers/OrionDataProvider.cs b/src/Opserver.Core/Data/Dashboard/Providers/OrionDataProvider.cs index 24f20adca..de6d283bd 100644 --- a/src/Opserver.Core/Data/Dashboard/Providers/OrionDataProvider.cs +++ b/src/Opserver.Core/Data/Dashboard/Providers/OrionDataProvider.cs @@ -168,7 +168,7 @@ Inner Join APM_ProcessEvidence pe { n.Issues = new List> { - new Issue(n, "Orion", n.PrettyName) + new(n, "Orion", n.PrettyName) { Date = n.LastSync ?? DateTime.UtcNow, Description = n.StatusDescription, diff --git a/src/Opserver.Core/Data/Dashboard/Providers/SignalFxDataProvider.HostProperties.cs b/src/Opserver.Core/Data/Dashboard/Providers/SignalFxDataProvider.HostProperties.cs index ed55ed8d8..d8701ceda 100644 --- a/src/Opserver.Core/Data/Dashboard/Providers/SignalFxDataProvider.HostProperties.cs +++ b/src/Opserver.Core/Data/Dashboard/Providers/SignalFxDataProvider.HostProperties.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Net; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; using StackExchange.Exceptional; diff --git a/src/Opserver.Core/Data/Dashboard/Providers/SignalFxDataProvider.SignalFlow.cs b/src/Opserver.Core/Data/Dashboard/Providers/SignalFxDataProvider.SignalFlow.cs index 06d8f8a09..ac277cdc0 100644 --- a/src/Opserver.Core/Data/Dashboard/Providers/SignalFxDataProvider.SignalFlow.cs +++ b/src/Opserver.Core/Data/Dashboard/Providers/SignalFxDataProvider.SignalFlow.cs @@ -24,14 +24,14 @@ public partial class SignalFxDataProvider "dsname", "computationId", "plugin", "fs_type", "mountpoint" ); - private static readonly SignalFlowStatement Cpu = new SignalFlowStatement("cpu.utilization"); - private static readonly SignalFlowStatement Memory = new SignalFlowStatement("memory.used"); - private static readonly SignalFlowStatement DiskUsage = new SignalFlowStatement("disk.utilization"); - private static readonly SignalFlowStatement DiskUsageByHost = new SignalFlowStatement("disk.utilization", "sum(by=['host'])"); - private static readonly SignalFlowStatement InterfaceRx = new SignalFlowStatement("if_octets.rx", rollup: "rate"); - private static readonly SignalFlowStatement InterfaceRxByHost = new SignalFlowStatement("if_octets.rx", aggregation: "sum(by=['host'])", rollup: "rate"); - private static readonly SignalFlowStatement InterfaceTx = new SignalFlowStatement("if_octets.tx", rollup: "rate"); - private static readonly SignalFlowStatement InterfaceTxByHost = new SignalFlowStatement("if_octets.tx", aggregation: "sum(by=['host'])", rollup: "rate"); + private static readonly SignalFlowStatement Cpu = new("cpu.utilization"); + private static readonly SignalFlowStatement Memory = new("memory.used"); + private static readonly SignalFlowStatement DiskUsage = new("disk.utilization"); + private static readonly SignalFlowStatement DiskUsageByHost = new("disk.utilization", "sum(by=['host'])"); + private static readonly SignalFlowStatement InterfaceRx = new("if_octets.rx", rollup: "rate"); + private static readonly SignalFlowStatement InterfaceRxByHost = new("if_octets.rx", aggregation: "sum(by=['host'])", rollup: "rate"); + private static readonly SignalFlowStatement InterfaceTx = new("if_octets.tx", rollup: "rate"); + private static readonly SignalFlowStatement InterfaceTxByHost = new("if_octets.tx", aggregation: "sum(by=['host'])", rollup: "rate"); private static readonly SignalFlowStatement[] _signalFlowStatements = new[] { Cpu, @@ -92,15 +92,7 @@ public bool Equals(TimeSeriesKey other) return result; } - public override bool Equals(object obj) - { - if (!(obj is TimeSeriesKey other)) - { - return false; - } - - return Equals(other); - } + public override bool Equals(object obj) => obj is TimeSeriesKey other && Equals(other); public override int GetHashCode() { @@ -167,16 +159,14 @@ private Task> GetMetricsAsync(Node node, DateTime? sta private async Task> GetMetricsAsync(IEnumerable metrics, DateTime start, DateTime end, string host = "*", TimeSpan? resolution = null, CancellationToken cancellationToken = default) { - await using (var signalFlowClient = new SignalFlowClient(Settings.Realm, Settings.AccessToken, _logger, cancellationToken)) - { - await signalFlowClient.ConnectAsync(); + await using var signalFlowClient = new SignalFlowClient(Settings.Realm, Settings.AccessToken, _logger, cancellationToken); + await signalFlowClient.ConnectAsync(); - var results = await Task.WhenAll( - metrics.Select(m => ExecuteStatementAsync(signalFlowClient, m, host, start, end, resolution)) - ); + var results = await Task.WhenAll( + metrics.Select(m => ExecuteStatementAsync(signalFlowClient, m, host, start, end, resolution)) + ); - return results.SelectMany(x => x).ToImmutableList(); - } + return results.SelectMany(x => x).ToImmutableList(); static async Task> ExecuteStatementAsync(SignalFlowClient client, SignalFlowStatement statement, string host, DateTime startDate, DateTime endDate, TimeSpan? resolution = null) { @@ -591,7 +581,7 @@ private class SignalFlowClient : IAsyncDisposable { private long _channelId; - private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions + private static readonly JsonSerializerOptions _serializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, @@ -601,7 +591,7 @@ private class SignalFlowClient : IAsyncDisposable } }; - private static readonly JsonSerializerOptions _deserializerOptions = new JsonSerializerOptions + private static readonly JsonSerializerOptions _deserializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, Converters = @@ -617,7 +607,7 @@ private class SignalFlowClient : IAsyncDisposable private readonly string _accessToken; private readonly ClientWebSocket _socket; private readonly Channel _requestChannel; - private readonly ConcurrentDictionary> _responseChannels = new ConcurrentDictionary>(); + private readonly ConcurrentDictionary> _responseChannels = new(); private readonly CancellationToken _cancellationToken; private Task _sendTask; @@ -679,11 +669,8 @@ public async ValueTask ConnectAsync() }); // wait for the "authenticated" message - var response = await WaitOneAsync(); - if (response == null) - { - throw new SignalFlowException("Unable to authenticate to SignalFlow endpoint."); - } + var response = await WaitOneAsync() + ?? throw new SignalFlowException("Unable to authenticate to SignalFlow endpoint."); } public async IAsyncEnumerable ExecuteAsync(string program, DateTime startDate, DateTime endDate, TimeSpan? resolution = null, bool includeMetadata = false) diff --git a/src/Opserver.Core/Data/Dashboard/Providers/SignalFxDataProvider.cs b/src/Opserver.Core/Data/Dashboard/Providers/SignalFxDataProvider.cs index 306939311..f416325ac 100644 --- a/src/Opserver.Core/Data/Dashboard/Providers/SignalFxDataProvider.cs +++ b/src/Opserver.Core/Data/Dashboard/Providers/SignalFxDataProvider.cs @@ -11,8 +11,8 @@ namespace Opserver.Data.Dashboard.Providers { public partial class SignalFxDataProvider : DashboardDataProvider { - private readonly List _emptyPoints = new List(0); - private readonly List _emptyDoublePoints = new List(0); + private readonly List _emptyPoints = new(0); + private readonly List _emptyDoublePoints = new(0); private readonly ILogger _logger; public SignalFxDataProvider(DashboardModule module, SignalFxSettings settings, ILogger logger) : base(module, settings) diff --git a/src/Opserver.Core/Data/Dashboard/Providers/WmiDataProvider.Data.cs b/src/Opserver.Core/Data/Dashboard/Providers/WmiDataProvider.Data.cs index 14aeae25a..ebd908b37 100644 --- a/src/Opserver.Core/Data/Dashboard/Providers/WmiDataProvider.Data.cs +++ b/src/Opserver.Core/Data/Dashboard/Providers/WmiDataProvider.Data.cs @@ -25,7 +25,7 @@ private partial class WmiNode : Node private readonly ConcurrentDictionary> VolumeHistory; private readonly ConcurrentDictionary> VolumePerformanceHistory; - internal readonly ConcurrentDictionary previousPerfDataCache = new ConcurrentDictionary(); + internal readonly ConcurrentDictionary previousPerfDataCache = new(); /// /// Defines if we can use "Win32_PerfFormattedData_Tcpip_NetworkAdapter" to query adapter utilization or not. @@ -78,9 +78,9 @@ public WmiNode(WmiDataProvider provider, string endpoint) { if (iface != null && Interfaces.Find(x => x == iface) != null - && NetHistory.ContainsKey(iface.Name)) + && NetHistory.TryGetValue(iface.Name, out var value)) { - return NetHistory[iface.Name]; + return value; } else { @@ -92,9 +92,9 @@ public WmiNode(WmiDataProvider provider, string endpoint) { if (iface != null && Volumes.Find(x => x == iface) != null - && VolumePerformanceHistory.ContainsKey(iface.Name)) + && VolumePerformanceHistory.TryGetValue(iface.Name, out var value)) { - return VolumePerformanceHistory[iface.Name]; + return value; } else { diff --git a/src/Opserver.Core/Data/Dashboard/Providers/WmiDataProvider.Polling.cs b/src/Opserver.Core/Data/Dashboard/Providers/WmiDataProvider.Polling.cs index 32ae9d2f0..6b70d5886 100644 --- a/src/Opserver.Core/Data/Dashboard/Providers/WmiDataProvider.Polling.cs +++ b/src/Opserver.Core/Data/Dashboard/Providers/WmiDataProvider.Polling.cs @@ -29,7 +29,7 @@ static WmiNode() } private Wmi.WmiQuery Query(string query, string wmiNamespace = Wmi.DefaultWmiNamespace) => - new Wmi.WmiQuery(Config, Endpoint, query, wmiNamespace); + new(Config, Endpoint, query, wmiNamespace); private async Task ClassExists(string className, string wmiNamespace = Wmi.DefaultWmiNamespace) { @@ -440,7 +440,7 @@ private async Task PollMemoryUtilizationAsync() UpdateHistoryStorage(MemoryHistory, utilization); } - private static readonly ConcurrentDictionary CounterLookup = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary CounterLookup = new(); private static string GetCounterName(string original) { @@ -617,7 +617,8 @@ private async Task GetCanQueryAdapterUtilization() /// Possible return codes from service actions /// https://msdn.microsoft.com/en-us/library/aa393660(v=vs.85).aspx /// - private static readonly Dictionary Win32ServiceReturnCodes = new Dictionary { + private static readonly Dictionary Win32ServiceReturnCodes = new() + { [0] = "The request was accepted.", [1] = "The request is not supported.", [2] = "The user did not have the necessary access.", diff --git a/src/Opserver.Core/Data/Dashboard/Providers/WmiDataProvider.cs b/src/Opserver.Core/Data/Dashboard/Providers/WmiDataProvider.cs index a4595806d..9393c4c3f 100644 --- a/src/Opserver.Core/Data/Dashboard/Providers/WmiDataProvider.cs +++ b/src/Opserver.Core/Data/Dashboard/Providers/WmiDataProvider.cs @@ -8,7 +8,7 @@ namespace Opserver.Data.Dashboard.Providers internal partial class WmiDataProvider : DashboardDataProvider, IServiceControlProvider { private readonly WMISettings _config; - private readonly List _wmiNodes = new List(); + private readonly List _wmiNodes = new(); private readonly Dictionary _wmiNodeLookup; public WmiDataProvider(DashboardModule module, WMISettings settings) : base(module, settings) @@ -31,7 +31,7 @@ public WmiDataProvider(DashboardModule module, WMISettings settings) : base(modu /// When adding, a node's IP address is resolved via DNS. /// /// The names of the server nodes to monitor. - private IEnumerable InitNodeList(IList nodeNames) + private List InitNodeList(List nodeNames) { var nodesList = new List(nodeNames.Count); var exclude = Module.Settings.ExcludePatternRegex; diff --git a/src/Opserver.Core/Data/DataApi.cs b/src/Opserver.Core/Data/DataApi.cs index f1ab2d0ba..99fc40c3e 100644 --- a/src/Opserver.Core/Data/DataApi.cs +++ b/src/Opserver.Core/Data/DataApi.cs @@ -9,9 +9,9 @@ public static class DataApi public static IEnumerable GetType(PollingService poller, string type, bool includeData = false) => poller.GetNodes(type).Select(n => new NodeData(n, includeData)); - public static NodeData GetNode(PollNode node, bool includeData = false) => new NodeData(node, includeData); + public static NodeData GetNode(PollNode node, bool includeData = false) => new(node, includeData); - public static CacheData GetCache(Cache cache, bool includeData = false) => new CacheData(cache, includeData); + public static CacheData GetCache(Cache cache, bool includeData = false) => new(cache, includeData); public class NodeData { diff --git a/src/Opserver.Core/Data/Elastic/ElasticCluster.HealthStatus.cs b/src/Opserver.Core/Data/Elastic/ElasticCluster.HealthStatus.cs index ebe916704..025a7d6df 100644 --- a/src/Opserver.Core/Data/Elastic/ElasticCluster.HealthStatus.cs +++ b/src/Opserver.Core/Data/Elastic/ElasticCluster.HealthStatus.cs @@ -17,7 +17,7 @@ public partial class ElasticCluster /// The Index info API changes in ElasticSearch 0.9, it's not really reasonable to support /// data before that given that it's going away /// - public static readonly Version MinIndexInfoVersion = new Version(0, 90); + public static readonly Version MinIndexInfoVersion = new(0, 90); public IEnumerable TroubledIndexes { diff --git a/src/Opserver.Core/Data/Elastic/ElasticCluster.Nodes.cs b/src/Opserver.Core/Data/Elastic/ElasticCluster.Nodes.cs index ed34f2a9d..b6beb0b07 100644 --- a/src/Opserver.Core/Data/Elastic/ElasticCluster.Nodes.cs +++ b/src/Opserver.Core/Data/Elastic/ElasticCluster.Nodes.cs @@ -200,7 +200,7 @@ public class TransportInfo public class HTTPInfo { - private static readonly Regex _inetStrip = new Regex(@"inet\[/(.*)\]", RegexOptions.Compiled); + private static readonly Regex _inetStrip = new(@"inet\[/(.*)\]", RegexOptions.Compiled); [DataMember(Name = "bound_address")] public dynamic BoundAddress { get; internal set; } [DataMember(Name = "publish_address")] public string PublishAddress { get; internal set; } diff --git a/src/Opserver.Core/Data/Elastic/ElasticCluster.State.cs b/src/Opserver.Core/Data/Elastic/ElasticCluster.State.cs index 4f2bc1ab1..97ec1f0cb 100644 --- a/src/Opserver.Core/Data/Elastic/ElasticCluster.State.cs +++ b/src/Opserver.Core/Data/Elastic/ElasticCluster.State.cs @@ -28,13 +28,11 @@ public class ClusterStateInfo : IMonitorStatus public string MonitorStatusReason => null; private List _allShards; - public List AllShards => - _allShards ?? - (_allShards = RoutingNodes?.Nodes.Values + public List AllShards => _allShards ??= RoutingNodes?.Nodes.Values .SelectMany(i => i) .Union(RoutingNodes.Unassigned) .ToList() - ?? new List()); + ?? new List(); [DataMember(Name = "cluster_name")] public string Name { get; internal set; } diff --git a/src/Opserver.Core/Data/Exceptions/Application.cs b/src/Opserver.Core/Data/Exceptions/Application.cs index af54d39df..fe661c11b 100644 --- a/src/Opserver.Core/Data/Exceptions/Application.cs +++ b/src/Opserver.Core/Data/Exceptions/Application.cs @@ -18,7 +18,7 @@ public class Application public int RecentExceptionCount { get; internal set; } public DateTime? MostRecent { get; internal set; } - private static readonly Regex _shortLogStripRegex = new Regex(@"[^A-Za-z_0-9_\-_\.\/]", RegexOptions.Compiled); + private static readonly Regex _shortLogStripRegex = new(@"[^A-Za-z_0-9_\-_\.\/]", RegexOptions.Compiled); private string _shortName; public string ShortName => _shortName ??= _shortLogStripRegex.Replace(Name, ""); diff --git a/src/Opserver.Core/Data/Exceptions/ExceptionStore.cs b/src/Opserver.Core/Data/Exceptions/ExceptionStore.cs index b28ba4024..5ef3e177d 100644 --- a/src/Opserver.Core/Data/Exceptions/ExceptionStore.cs +++ b/src/Opserver.Core/Data/Exceptions/ExceptionStore.cs @@ -54,7 +54,7 @@ private List GetConfiguredApplicationGroups() { var groups = Settings.Groups ?? Module.Settings.Groups; var applications = Settings.Applications ?? Module.Settings.Applications; - if (groups?.Any() ?? false) + if (groups?.Count > 0) { var configured = groups .Select(g => new ApplicationGroup @@ -72,7 +72,7 @@ private List GetConfiguredApplicationGroups() } // One big bucket if nothing is configured CatchAll = new ApplicationGroup { Name = "All" }; - if (applications?.Any() ?? false) + if (applications?.Count > 0) { CatchAll.Applications = applications.OrderBy(a => a).Select(a => new Application { Name = a }).ToList(); } diff --git a/src/Opserver.Core/Data/Exceptions/ExceptionsModule.cs b/src/Opserver.Core/Data/Exceptions/ExceptionsModule.cs index 01b679080..a7f6cf8b2 100644 --- a/src/Opserver.Core/Data/Exceptions/ExceptionsModule.cs +++ b/src/Opserver.Core/Data/Exceptions/ExceptionsModule.cs @@ -22,9 +22,9 @@ public ExceptionsModule(IConfiguration config, PollingService poller) : base(con public override bool IsMember(string node) => false; public int TotalExceptionCount => - Stores.Sum(s => s.Settings.IncludeInTotal ? s.Applications.Data?.Sum(a => a.ExceptionCount) ?? 0 : 0); + Stores.Sum(s => s.Settings.IncludeInTotal ? s.Applications.Data?.Sum(static a => a.ExceptionCount) ?? 0 : 0); public int TotalRecentExceptionCount => - Stores.Sum(s => s.Settings.IncludeInTotal ? s.Applications.Data?.Sum(a => a.RecentExceptionCount) ?? 0 : 0); + Stores.Sum(s => s.Settings.IncludeInTotal ? s.Applications.Data?.Sum(static a => a.RecentExceptionCount) ?? 0 : 0); public override MonitorStatus MonitorStatus { diff --git a/src/Opserver.Core/Data/HAProxy/HAProxyGroup.cs b/src/Opserver.Core/Data/HAProxy/HAProxyGroup.cs index 719a81d9c..7cfce0400 100644 --- a/src/Opserver.Core/Data/HAProxy/HAProxyGroup.cs +++ b/src/Opserver.Core/Data/HAProxy/HAProxyGroup.cs @@ -43,7 +43,7 @@ public HAProxyGroup(HAProxyModule module, HAProxySettings.Instance instance) }; Instances = new List { - new HAProxyInstance(module, instance) + new(module, instance) { Group = this } diff --git a/src/Opserver.Core/Data/HAProxy/HAProxyInstance.cs b/src/Opserver.Core/Data/HAProxy/HAProxyInstance.cs index 4d21347ce..ba4072805 100644 --- a/src/Opserver.Core/Data/HAProxy/HAProxyInstance.cs +++ b/src/Opserver.Core/Data/HAProxy/HAProxyInstance.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Net; -using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; using Microsoft.Net.Http.Headers; @@ -105,7 +103,7 @@ private async Task> ParseHAProxyStatsAsync(string csv) while ((line = await sr.ReadLineAsync()) != null) { //Skip the header - if (line.IsNullOrEmpty() || line.StartsWith("#")) continue; + if (line.IsNullOrEmpty() || line.StartsWith('#')) continue; //Collect each stat line as we go, group later stats.Add(Item.FromLine(line)); } diff --git a/src/Opserver.Core/Data/HAProxy/Item.cs b/src/Opserver.Core/Data/HAProxy/Item.cs index 0a642a283..e5db65b14 100644 --- a/src/Opserver.Core/Data/HAProxy/Item.cs +++ b/src/Opserver.Core/Data/HAProxy/Item.cs @@ -19,7 +19,7 @@ public class Item : IMonitorStatus public string ServerName { get; internal set; } // TODO: Settings - private static readonly Regex _compactReplacer = new Regex(@"-\d+$", RegexOptions.Compiled); + private static readonly Regex _compactReplacer = new(@"-\d+$", RegexOptions.Compiled); private string _compactServerName; public string CompactServerName => _compactServerName ??= _compactReplacer.Replace(ServerName, ""); @@ -409,8 +409,8 @@ private static Item GetStatOfType(string typeNum) => public override string ToString() => RawData; - private static readonly Regex _upGoingDown = new Regex(@"UP \d+/\d+", RegexOptions.Compiled); - private static readonly Regex _downGoingUp = new Regex(@"DOWN \d+/\d+", RegexOptions.Compiled); + private static readonly Regex _upGoingDown = new(@"UP \d+/\d+", RegexOptions.Compiled); + private static readonly Regex _downGoingUp = new(@"DOWN \d+/\d+", RegexOptions.Compiled); public virtual string Description => Type == StatusType.Server ? ServerName : Type.ToString(); @@ -418,34 +418,13 @@ private static Item GetStatOfType(string typeNum) => public bool InDrain => ProxyServerStatus == ProxyServerStatus.Drain; public bool OutOfRotation => InMaintenance || InDrain; - public virtual MonitorStatus MonitorStatus + public virtual MonitorStatus MonitorStatus => ProxyServerStatus switch { - get - { - switch (ProxyServerStatus) - { - case ProxyServerStatus.ActiveUp: - case ProxyServerStatus.BackupUp: - case ProxyServerStatus.NotChecked: - case ProxyServerStatus.Open: - return MonitorStatus.Good; - - case ProxyServerStatus.ActiveUpGoingDown: - case ProxyServerStatus.BackupUpGoingDown: - case ProxyServerStatus.Maintenance: - case ProxyServerStatus.Drain: - return MonitorStatus.Warning; - - case ProxyServerStatus.Down: - case ProxyServerStatus.ActiveDownGoingUp: - case ProxyServerStatus.BackupDownGoingUp: - return MonitorStatus.Critical; - - default: - return MonitorStatus.Unknown; - } - } - } + ProxyServerStatus.ActiveUp or ProxyServerStatus.BackupUp or ProxyServerStatus.NotChecked or ProxyServerStatus.Open => MonitorStatus.Good, + ProxyServerStatus.ActiveUpGoingDown or ProxyServerStatus.BackupUpGoingDown or ProxyServerStatus.Maintenance or ProxyServerStatus.Drain => MonitorStatus.Warning, + ProxyServerStatus.Down or ProxyServerStatus.ActiveDownGoingUp or ProxyServerStatus.BackupDownGoingUp => MonitorStatus.Critical, + _ => MonitorStatus.Unknown, + }; public string MonitorStatusReason => MonitorStatus == MonitorStatus.Good diff --git a/src/Opserver.Core/Data/HAProxy/ServerStatus.cs b/src/Opserver.Core/Data/HAProxy/ServerStatus.cs index cf410be52..4501bb0e1 100644 --- a/src/Opserver.Core/Data/HAProxy/ServerStatus.cs +++ b/src/Opserver.Core/Data/HAProxy/ServerStatus.cs @@ -55,18 +55,10 @@ public static string ShortDescription(this ProxyServerStatus status) => _ => "Unknown", }; - public static bool IsBad(this ProxyServerStatus status) + public static bool IsBad(this ProxyServerStatus status) => status switch { - switch (status) - { - case ProxyServerStatus.ActiveUpGoingDown: - case ProxyServerStatus.BackupUpGoingDown: - case ProxyServerStatus.Drain: - case ProxyServerStatus.Down: - return true; - default: - return false; - } - } + ProxyServerStatus.ActiveUpGoingDown or ProxyServerStatus.BackupUpGoingDown or ProxyServerStatus.Drain or ProxyServerStatus.Down => true, + _ => false, + }; } } diff --git a/src/Opserver.Core/Data/IPNet.cs b/src/Opserver.Core/Data/IPNet.cs index c7b6635c3..b27144da4 100644 --- a/src/Opserver.Core/Data/IPNet.cs +++ b/src/Opserver.Core/Data/IPNet.cs @@ -264,8 +264,8 @@ private static IPAddress IPAddressFromCIDR(AddressFamily family, int cidr) /// Private IP Ranges reserved for internal use by ARIN /// These networks should not route on the global Internet /// - private static readonly List ReservedPrivateRanges = new List - { + private static readonly List ReservedPrivateRanges = new() + { Parse("10.0.0.0/8"), Parse("127.0.0.0/8"), Parse("100.64.0.0/10"), @@ -280,8 +280,8 @@ private static IPAddress IPAddressFromCIDR(AddressFamily family, int cidr) /// /// Multicast IP Ranges reserved for use by ARIN /// - private static readonly List ReservedMulticastRanges = new List - { + private static readonly List ReservedMulticastRanges = new() + { Parse("224.0.0.0/4"), Parse("ff00::/8"), }; @@ -289,8 +289,8 @@ private static IPAddress IPAddressFromCIDR(AddressFamily family, int cidr) /// /// Link-local IP Ranges reserved for use by ARIN /// - private static readonly List ReservedLinkLocalRanges = new List - { + private static readonly List ReservedLinkLocalRanges = new() + { Parse("169.254.0.0/16"), Parse("fe80::/10"), }; @@ -299,8 +299,8 @@ private static IPAddress IPAddressFromCIDR(AddressFamily family, int cidr) /// /// Documentation IP Ranges reserved for use by ARIN /// - private static readonly List ReservedDocumentationRanges = new List - { + private static readonly List ReservedDocumentationRanges = new() + { Parse("192.0.2.0/24"), // TEST-NET-1 Parse("198.51.100.0/24"), // TEST-NET-2 Parse("203.0.113.0/24"), // TEST-NET-3 @@ -316,7 +316,7 @@ public IPNetParseException(string message, Exception innerException) : base(mess } [DataContract] - public struct TinyIPAddress : IEquatable, IComparable + public readonly struct TinyIPAddress : IEquatable, IComparable { [DataMember(Order = 1)] private readonly bool IsV4; @@ -329,9 +329,9 @@ public struct TinyIPAddress : IEquatable, IComparable IsV4 ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6; + public readonly AddressFamily AddressFamily => IsV4 ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6; - public string BitString + public readonly string BitString { get { @@ -360,7 +360,7 @@ public string BitString } } - public IPAddress ToIPAddress() + public readonly IPAddress ToIPAddress() { if (IsV4) { @@ -462,7 +462,7 @@ private static ulong FromBytes(byte[] source, int start) | ((ulong)source[start]); } - public int NumberOfSetBits + public readonly int NumberOfSetBits { get { @@ -502,7 +502,7 @@ private static int NumberOfSetBitsImpl(ulong i) return (int)(unchecked(((i + (i >> 4)) & 0xF0F0F0F0F0F0F0FUL) * 0x101010101010101UL) >> 56); } - public bool IsValidSubnet + public readonly bool IsValidSubnet { get { @@ -586,7 +586,7 @@ private static bool IsValidSubnetImpl(ulong l) public static bool operator <=(TinyIPAddress a, TinyIPAddress b) => Compare(a, b) <= 0; public static bool operator >=(TinyIPAddress a, TinyIPAddress b) => Compare(a, b) >= 0; - public override int GetHashCode() + public override readonly int GetHashCode() { if (IsV4) { @@ -598,12 +598,12 @@ public override int GetHashCode() return hash; } - public bool Equals(TinyIPAddress other) => + public readonly bool Equals(TinyIPAddress other) => IPv4Address == other.IPv4Address && FirstV6Leg == other.FirstV6Leg && LastV6Leg == other.LastV6Leg; - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { if (obj is null) { @@ -612,7 +612,7 @@ public override bool Equals(object obj) return obj is TinyIPAddress tinyIPAddress && Equals(tinyIPAddress); } - public int CompareTo(TinyIPAddress other) => Compare(this, other); + public readonly int CompareTo(TinyIPAddress other) => Compare(this, other); private static int Compare(TinyIPAddress a, TinyIPAddress b) { diff --git a/src/Opserver.Core/Data/Jira/JiraClient.cs b/src/Opserver.Core/Data/Jira/JiraClient.cs index f85d98b25..10519b945 100644 --- a/src/Opserver.Core/Data/Jira/JiraClient.cs +++ b/src/Opserver.Core/Data/Jira/JiraClient.cs @@ -4,11 +4,9 @@ using System.Collections.Specialized; using System.Globalization; using System.Linq; -using System.Net; using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; -using Jil; using StackExchange.Utils; using Microsoft.Net.Http.Headers; @@ -17,8 +15,8 @@ namespace Opserver.Data.Jira public class JiraClient { private readonly JiraSettings _jiraSettings; - private static readonly HashSet HiddenHttpKeys = new HashSet - { + private static readonly HashSet HiddenHttpKeys = new() + { "ALL_HTTP", "ALL_RAW", "HTTP_CONTENT_LENGTH", @@ -27,7 +25,7 @@ public class JiraClient "QUERY_STRING" }; - private static readonly HashSet DefaultHttpKeys = new HashSet + private static readonly HashSet DefaultHttpKeys = new() { "APPL_MD_PATH", "APPL_PHYSICAL_PATH", @@ -84,7 +82,7 @@ public async Task CreateIssueAsync(JiraAction action, E var labels = action.Labels.IsNullOrEmpty() ? null - : action.Labels.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + : action.Labels.Split(StringSplits.Comma, StringSplitOptions.RemoveEmptyEntries); if (labels?.Length > 0) fields.Add("labels", labels); diff --git a/src/Opserver.Core/Data/PagerDuty/PagerDutyAPI.Actions.cs b/src/Opserver.Core/Data/PagerDuty/PagerDutyAPI.Actions.cs index fab2b2c38..2a31cfb8c 100644 --- a/src/Opserver.Core/Data/PagerDuty/PagerDutyAPI.Actions.cs +++ b/src/Opserver.Core/Data/PagerDuty/PagerDutyAPI.Actions.cs @@ -11,7 +11,7 @@ public partial class PagerDutyAPI { public async Task UpdateIncidentStatusAsync(string incidentId, PagerDutyPerson person, IncidentStatus newStatus) { - if (person == null) throw new ArgumentNullException(nameof(person)); + ArgumentNullException.ThrowIfNull(person); var data = new { incident = new diff --git a/src/Opserver.Core/Data/PagerDuty/PagerDutyAPI.OnCall.cs b/src/Opserver.Core/Data/PagerDuty/PagerDutyAPI.OnCall.cs index 99264d25d..99e04ae5a 100644 --- a/src/Opserver.Core/Data/PagerDuty/PagerDutyAPI.OnCall.cs +++ b/src/Opserver.Core/Data/PagerDuty/PagerDutyAPI.OnCall.cs @@ -148,7 +148,7 @@ public string FormattedAddress var sb = StringBuilderCache.Get(); if (CountryCode.HasValue) { - sb.Append("+").Append(CountryCode).Append(" "); + sb.Append('+').Append(CountryCode).Append(' '); } switch (Type) { diff --git a/src/Opserver.Core/Data/PagerDuty/PagerDutyAPI.cs b/src/Opserver.Core/Data/PagerDuty/PagerDutyAPI.cs index c3f020079..daaebfb10 100644 --- a/src/Opserver.Core/Data/PagerDuty/PagerDutyAPI.cs +++ b/src/Opserver.Core/Data/PagerDuty/PagerDutyAPI.cs @@ -13,7 +13,7 @@ namespace Opserver.Data.PagerDuty { public partial class PagerDutyAPI : PollNode { - internal static readonly Options JilOptions = new Options( + internal static readonly Options JilOptions = new( dateFormat: DateTimeFormat.ISO8601, unspecifiedDateTimeKindBehavior: UnspecifiedDateTimeKindBehavior.IsUTC, excludeNulls: true diff --git a/src/Opserver.Core/Data/PollNode.cs b/src/Opserver.Core/Data/PollNode.cs index debfd512d..04a5029c0 100644 --- a/src/Opserver.Core/Data/PollNode.cs +++ b/src/Opserver.Core/Data/PollNode.cs @@ -70,7 +70,7 @@ public bool TryAddToGlobalPollers() return AddedToGlobalPollers = GetParentModule().Poller.TryAdd(this); } - private readonly object _monitorStatusLock = new object(); + private readonly object _monitorStatusLock = new(); protected MonitorStatus? PreviousMonitorStatus; protected MonitorStatus? CachedMonitorStatus; public virtual MonitorStatus MonitorStatus diff --git a/src/Opserver.Core/Data/PollingService.Polling.cs b/src/Opserver.Core/Data/PollingService.Polling.cs index 5d1ebe33a..8fe45d4dd 100644 --- a/src/Opserver.Core/Data/PollingService.Polling.cs +++ b/src/Opserver.Core/Data/PollingService.Polling.cs @@ -9,9 +9,9 @@ namespace Opserver.Data public partial class PollingService { private Thread _globalPollingThread; - private readonly object _addLock = new object(); - private readonly object _pollAllLock = new object(); - public readonly HashSet AllPollNodes = new HashSet(); + private readonly object _addLock = new(); + private readonly object _pollAllLock = new(); + public readonly HashSet AllPollNodes = new(); private readonly Action> _taskRunner = t => Task.Run(t); private long _totalPollIntervals; diff --git a/src/Opserver.Core/Data/PollingService.Stats.cs b/src/Opserver.Core/Data/PollingService.Stats.cs index d3c588073..c039dcfe8 100644 --- a/src/Opserver.Core/Data/PollingService.Stats.cs +++ b/src/Opserver.Core/Data/PollingService.Stats.cs @@ -6,7 +6,7 @@ namespace Opserver.Data { public partial class PollingService { - public GlobalPollingStatus GetPollingStatus() => new GlobalPollingStatus + public GlobalPollingStatus GetPollingStatus() => new() { MonitorStatus = _globalPollingThread.IsAlive ? (AllPollNodes.Count > 0 ? MonitorStatus.Good : MonitorStatus.Unknown) : MonitorStatus.Critical, MonitorStatusReason = _globalPollingThread.IsAlive ? (AllPollNodes.Count > 0 ? null : "No Poll Nodes") : "Global Polling Thread Dead", @@ -21,6 +21,6 @@ public partial class PollingService Nodes = AllPollNodes.ToList() }; - public ThreadStats GetThreadStats() => new ThreadStats(); + public ThreadStats GetThreadStats() => new(); } } diff --git a/src/Opserver.Core/Data/Redis/RedisAnalyzer.Memory.cs b/src/Opserver.Core/Data/Redis/RedisAnalyzer.Memory.cs index 0b4094830..e3f380b71 100644 --- a/src/Opserver.Core/Data/Redis/RedisAnalyzer.Memory.cs +++ b/src/Opserver.Core/Data/Redis/RedisAnalyzer.Memory.cs @@ -198,7 +198,7 @@ public RedisMemoryAnalysis(RedisAnalyzer analyzer, RedisConnectionInfo connectio } } - private static readonly Regex _debugObjectSize = new Regex(@"\bserializedlength:([0-9]+)\b", RegexOptions.Compiled); + private static readonly Regex _debugObjectSize = new(@"\bserializedlength:([0-9]+)\b", RegexOptions.Compiled); internal void TallyDebugLine(string key, string debugLine) { @@ -250,7 +250,7 @@ public class KeyMatcher public class KeyStats { - private readonly object _lock = new object(); + private readonly object _lock = new(); internal long _count; internal long _keyByteSize; @@ -261,7 +261,7 @@ public class KeyStats public long ValueByteSize => _valueByteSize; public long TotalByteSize => _keyByteSize + _valueByteSize; - public readonly SortedList TopKeys = new SortedList(50, new DescLongCompare()); + public readonly SortedList TopKeys = new(50, new DescLongCompare()); public void Tally(string key, long keySize, long valueSize) { diff --git a/src/Opserver.Core/Data/Redis/RedisInfo.Parsing.cs b/src/Opserver.Core/Data/Redis/RedisInfo.Parsing.cs index d6195c8da..0b8d13225 100644 --- a/src/Opserver.Core/Data/Redis/RedisInfo.Parsing.cs +++ b/src/Opserver.Core/Data/Redis/RedisInfo.Parsing.cs @@ -12,6 +12,7 @@ public partial class RedisInfo { private static readonly ConcurrentDictionary _sectionMappings; private static readonly ConcurrentDictionary> _propertyMappings; + private static readonly string[] _infoSplit = new[] { "\r\n" }; static RedisInfo() { @@ -40,10 +41,10 @@ public static RedisInfo FromInfoString(string infoStr) RedisInfoSection currentSection = null; - var lines = infoStr.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); + var lines = infoStr.Split(_infoSplit, StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { - if (line.StartsWith("#")) + if (line.StartsWith('#')) { var sectionName = line.Replace("# ", ""); if (_sectionMappings.TryGetValue(sectionName, out var currentSectionProp)) @@ -150,13 +151,13 @@ public RedisInfoLine(string key, string value) ParsedValue = GetInfoValue(key, value); } - private static readonly List _dontFormatList = new List - { - "redis_git", - "process_id", - "tcp_port", - "master_port" - }; + private static readonly List _dontFormatList = new() + { + "redis_git", + "process_id", + "tcp_port", + "master_port" + }; private static string GetInfoValue(string label, string value) { diff --git a/src/Opserver.Core/Data/Redis/RedisInfo.cs b/src/Opserver.Core/Data/Redis/RedisInfo.cs index 5aae85626..87661fc94 100644 --- a/src/Opserver.Core/Data/Redis/RedisInfo.cs +++ b/src/Opserver.Core/Data/Redis/RedisInfo.cs @@ -88,8 +88,8 @@ public class ReplicationInfo : RedisInfoSection [RedisInfoProperty("repl_backlog_histlen")] public long BacklogHistoryLength { get; internal set; } - public readonly List ReplicaConnections = new List(); - private static readonly Regex _replicaRegex = new Regex(@"slave\d+", RegexOptions.Compiled); + public readonly List ReplicaConnections = new(); + private static readonly Regex _replicaRegex = new(@"slave\d+", RegexOptions.Compiled); public override void MapUnrecognizedLine(string key, string value) { @@ -320,10 +320,10 @@ public class CPUInfo : RedisInfoSection public KeyspaceInfo Keyspace { get; internal set; } = new KeyspaceInfo(); public class KeyspaceInfo : RedisInfoSection { - public readonly Dictionary KeyData = new Dictionary(); + public readonly Dictionary KeyData = new(); - private static readonly Regex _dbNameMatch = new Regex("db([0-9]+)", RegexOptions.Compiled); - private static readonly Regex _keysMatch = new Regex("keys=([0-9]+),expires=([0-9]+)", RegexOptions.Compiled); + private static readonly Regex _dbNameMatch = new("db([0-9]+)", RegexOptions.Compiled); + private static readonly Regex _keysMatch = new("keys=([0-9]+),expires=([0-9]+)", RegexOptions.Compiled); internal override void AddLine(string key, string value) { var dbMatch = _dbNameMatch.Match(key); diff --git a/src/Opserver.Core/Data/Redis/RedisInstance.Actions.cs b/src/Opserver.Core/Data/Redis/RedisInstance.Actions.cs index 45565bf23..6474b8571 100644 --- a/src/Opserver.Core/Data/Redis/RedisInstance.Actions.cs +++ b/src/Opserver.Core/Data/Redis/RedisInstance.Actions.cs @@ -76,7 +76,7 @@ public async Task SetSERedisTiebreakerAsync() /// public Task GetSERedisTiebreakerAsync() => GetSERedisTiebreakerAsync(_connection); - private static async Task GetSERedisTiebreakerAsync(IConnectionMultiplexer conn) + private static async Task GetSERedisTiebreakerAsync(ConnectionMultiplexer conn) { RedisKey tieBreakerKey = ConfigurationOptions.Parse(conn.Configuration).TieBreaker; return await conn.GetDatabase() diff --git a/src/Opserver.Core/Data/Redis/RedisInstance.cs b/src/Opserver.Core/Data/Redis/RedisInstance.cs index bd832e2b1..e02a383bd 100644 --- a/src/Opserver.Core/Data/Redis/RedisInstance.cs +++ b/src/Opserver.Core/Data/Redis/RedisInstance.cs @@ -104,7 +104,7 @@ public RedisInstance(RedisModule module, RedisConnectionInfo connectionInfo) : b } // We're not doing a lot of redis access, so tone down the thread count to 1 socket queue handler - public static readonly SocketManager SharedSocketManager = new SocketManager("Opserver Shared"); + public static readonly SocketManager SharedSocketManager = new("Opserver Shared"); private ConnectionMultiplexer GetConnection(bool allowAdmin = false, int syncTimeout = 60000) { diff --git a/src/Opserver.Core/Data/Redis/RedisInstanceOperation.cs b/src/Opserver.Core/Data/Redis/RedisInstanceOperation.cs index 4013de9e2..f67b49262 100644 --- a/src/Opserver.Core/Data/Redis/RedisInstanceOperation.cs +++ b/src/Opserver.Core/Data/Redis/RedisInstanceOperation.cs @@ -30,7 +30,7 @@ public static RedisInstanceOperation FromString(RedisModule module, string s) var newMaster = module.Instances.Find(i => i.UniqueKey == parts[2]); return ReplicateFrom(opee, newMaster); default: - throw new ArgumentOutOfRangeException(nameof(InstanceCommandType)); + throw new ArgumentOutOfRangeException(nameof(s), nameof(InstanceCommandType)); } } throw new ArgumentOutOfRangeException(nameof(s), $"Invalid op string provided: '{s}'"); @@ -44,20 +44,18 @@ public override string ToString() => _ => throw new ArgumentOutOfRangeException(nameof(InstanceCommandType)), }; - public static RedisInstanceOperation MakeMaster(RedisInstance instance) => - new RedisInstanceOperation - { - Command = InstanceCommandType.MakeMaster, - Instance = instance - }; + public static RedisInstanceOperation MakeMaster(RedisInstance instance) => new() + { + Command = InstanceCommandType.MakeMaster, + Instance = instance + }; - public static RedisInstanceOperation ReplicateFrom(RedisInstance instance, RedisInstance newMaster) => - new RedisInstanceOperation - { - Command = InstanceCommandType.ReplicateFrom, - Instance = instance, - NewMaster = newMaster - }; + public static RedisInstanceOperation ReplicateFrom(RedisInstance instance, RedisInstance newMaster) => new() + { + Command = InstanceCommandType.ReplicateFrom, + Instance = instance, + NewMaster = newMaster + }; } public enum InstanceCommandType diff --git a/src/Opserver.Core/Data/Redis/RedisModule.cs b/src/Opserver.Core/Data/Redis/RedisModule.cs index 83b55dea5..82694e4ea 100644 --- a/src/Opserver.Core/Data/Redis/RedisModule.cs +++ b/src/Opserver.Core/Data/Redis/RedisModule.cs @@ -79,7 +79,7 @@ private List LoadRedisConnections(RedisSettings settings, A public RedisHost GetHost(string hostName) { - if (hostName.IsNullOrEmpty() || hostName.Contains(":")) return null; + if (hostName.IsNullOrEmpty() || hostName.Contains(':')) return null; return Hosts.Find(h => string.Equals(h.HostName, hostName, StringComparison.InvariantCultureIgnoreCase)); } @@ -96,7 +96,7 @@ public RedisInstance GetInstance(RedisConnectionInfo info) public RedisInstance GetInstance(string connectionString) { if (connectionString.IsNullOrEmpty()) return null; - if (connectionString.Contains(":")) + if (connectionString.Contains(':')) { var parts = connectionString.Split(StringSplits.Colon); if (parts.Length != 2) return null; diff --git a/src/Opserver.Core/Data/SQL/QueryPlans/ShowPlanXML.cs b/src/Opserver.Core/Data/SQL/QueryPlans/ShowPlanXML.cs index b96a798a0..c38249823 100644 --- a/src/Opserver.Core/Data/SQL/QueryPlans/ShowPlanXML.cs +++ b/src/Opserver.Core/Data/SQL/QueryPlans/ShowPlanXML.cs @@ -27,24 +27,17 @@ public virtual IEnumerable Statements get { yield return this; } } - public bool IsMinor + public bool IsMinor => StatementType switch { - get { - switch (StatementType) - { - case "COND": - case "RETURN NONE": - return true; - } - return false; - } - } + "COND" or "RETURN NONE" => true, + _ => false, + }; private const string declareFormat = "Declare {0} {1} = {2};"; - private static readonly Regex emptyLineRegex = new Regex(@"^\s+$[\r\n]*", RegexOptions.Compiled | RegexOptions.Multiline); - private static readonly Regex initParamsTrimRegex = new Regex(@"^\s*(begin|end)\s*", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex paramRegex = new Regex(@"^\(( [^\(\)]* ( ( (?\() [^\(\)]* )+ ( (?\)) [^\(\)]* )+ )* (?(Open)(?!)) )\)", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); - private static readonly Regex paramSplitRegex = new Regex(",(?=[@])", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); + private static readonly Regex emptyLineRegex = new(@"^\s+$[\r\n]*", RegexOptions.Compiled | RegexOptions.Multiline); + private static readonly Regex initParamsTrimRegex = new(@"^\s*(begin|end)\s*", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex paramRegex = new(@"^\(( [^\(\)]* ( ( (?\() [^\(\)]* )+ ( (?\)) [^\(\)]* )+ )* (?(Open)(?!)) )\)", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); + private static readonly Regex paramSplitRegex = new(",(?=[@])", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); private static readonly char[] startTrimChars = new[] { '\n', '\r', ';' }; public string ParameterDeclareStatement diff --git a/src/Opserver.Core/Data/SQL/SQLAzureServer.cs b/src/Opserver.Core/Data/SQL/SQLAzureServer.cs index a29403190..8ce3be762 100644 --- a/src/Opserver.Core/Data/SQL/SQLAzureServer.cs +++ b/src/Opserver.Core/Data/SQL/SQLAzureServer.cs @@ -1,12 +1,12 @@ using System.Collections.Concurrent; using System.Collections.Generic; -using System.Data.SqlClient; +using Microsoft.Data.SqlClient; namespace Opserver.Data.SQL { public class SQLAzureServer : SQLInstance { - private readonly ConcurrentDictionary _instancesByKey = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _instancesByKey = new(); private Cache> _instanceCache; public Cache> Instances => diff --git a/src/Opserver.Core/Data/SQL/SQLInstance.ActiveOperations.cs b/src/Opserver.Core/Data/SQL/SQLInstance.ActiveOperations.cs index 842ff7529..d54e3d9a5 100644 --- a/src/Opserver.Core/Data/SQL/SQLInstance.ActiveOperations.cs +++ b/src/Opserver.Core/Data/SQL/SQLInstance.ActiveOperations.cs @@ -83,7 +83,7 @@ public string SqlText public string LoginName { get { return _loginName; } - set { _loginName = _loginLookups.ContainsKey(value) ? _loginLookups[value] : value.Split(StringSplits.BackSlash).Last(); } + set { _loginName = _loginLookups.TryGetValue(value, out string stringVal) ? stringVal : value.Split(StringSplits.BackSlash).Last(); } } public string WaitInfo { get; internal set; } @@ -165,7 +165,7 @@ public ActiveOperation(WhoIsActiveRow row) Exec sp_WhoIsActive @format_output = 0; "; - private static readonly Dictionary _loginLookups = new Dictionary + private static readonly Dictionary _loginLookups = new() { ["NT AUTHORITY\\SYSTEM"] = "(Local System)" }; diff --git a/src/Opserver.Core/Data/SQL/SQLInstance.Databases.cs b/src/Opserver.Core/Data/SQL/SQLInstance.Databases.cs index 59b8f1505..5dfb0f1d0 100644 --- a/src/Opserver.Core/Data/SQL/SQLInstance.Databases.cs +++ b/src/Opserver.Core/Data/SQL/SQLInstance.Databases.cs @@ -102,13 +102,13 @@ public LightweightCache> GetIndexInfoDetiled(string database staleDuration: 5.Minutes()); } - public static readonly HashSet SystemDatabaseNames = new HashSet - { - "master", - "model", - "msdb", - "tempdb" - }; + public static readonly HashSet SystemDatabaseNames = new() + { + "master", + "model", + "msdb", + "tempdb" + }; public class Database : ISQLVersioned, IMonitorStatus { @@ -132,22 +132,14 @@ public MonitorStatus MonitorStatus if (IsReadOnly) return MonitorStatus.Warning; - switch (State) + return State switch { - case DatabaseStates.Restoring: - case DatabaseStates.Recovering: - case DatabaseStates.RecoveryPending: - return MonitorStatus.Unknown; - case DatabaseStates.Copying: - return MonitorStatus.Warning; - case DatabaseStates.Suspect: - case DatabaseStates.Emergency: - case DatabaseStates.Offline: - return MonitorStatus.Critical; + DatabaseStates.Restoring or DatabaseStates.Recovering or DatabaseStates.RecoveryPending => MonitorStatus.Unknown, + DatabaseStates.Copying => MonitorStatus.Warning, + DatabaseStates.Suspect or DatabaseStates.Emergency or DatabaseStates.Offline => MonitorStatus.Critical, //case DatabaseStates.Online: - default: - return MonitorStatus.Good; - } + _ => MonitorStatus.Good, + }; } } @@ -661,7 +653,7 @@ public class DatabaseFile : ISQLVersioned public double AvgReadStallMs => NumReads == 0 ? 0 : StallReadMs / (double)NumReads; public double AvgWriteStallMs => NumWrites == 0 ? 0 : StallWriteMs / (double)NumWrites; - private static readonly Regex _shortPathRegex = new Regex(@"C:\\Program Files\\Microsoft SQL Server\\MSSQL\d+.MSSQLSERVER\\MSSQL\\DATA", RegexOptions.Compiled); + private static readonly Regex _shortPathRegex = new(@"C:\\Program Files\\Microsoft SQL Server\\MSSQL\d+.MSSQLSERVER\\MSSQL\\DATA", RegexOptions.Compiled); private string _shortPhysicalName; public string ShortPhysicalName => _shortPhysicalName ??= _shortPathRegex.Replace(PhysicalName ?? "", @"C:\Program...MSSQLSERVER\MSSQL\DATA"); diff --git a/src/Opserver.Core/Data/SQL/SQLInstance.Features.cs b/src/Opserver.Core/Data/SQL/SQLInstance.Features.cs index ddf01a426..94731538a 100644 --- a/src/Opserver.Core/Data/SQL/SQLInstance.Features.cs +++ b/src/Opserver.Core/Data/SQL/SQLInstance.Features.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; namespace Opserver.Data.SQL { diff --git a/src/Opserver.Core/Data/SQL/SQLInstance.Jobs.cs b/src/Opserver.Core/Data/SQL/SQLInstance.Jobs.cs index 158b21ce3..7b2a9df4f 100644 --- a/src/Opserver.Core/Data/SQL/SQLInstance.Jobs.cs +++ b/src/Opserver.Core/Data/SQL/SQLInstance.Jobs.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Data; using System.Data.Common; using System.Threading.Tasks; @@ -85,18 +84,13 @@ public MonitorStatus LastRunMonitorStatus get { if (!LastRunStatus.HasValue) return MonitorStatus.Unknown; - switch (LastRunStatus.Value) + return LastRunStatus.Value switch { - case JobStatuses.Succeeded: - return MonitorStatus.Good; - case JobStatuses.Retry: - case JobStatuses.Canceled: - return MonitorStatus.Warning; - case JobStatuses.Failed: - return MonitorStatus.Critical; - default: - throw new ArgumentOutOfRangeException("", "LastRunStatus was not recognized"); - } + JobStatuses.Succeeded => MonitorStatus.Good, + JobStatuses.Retry or JobStatuses.Canceled => MonitorStatus.Warning, + JobStatuses.Failed => MonitorStatus.Critical, + _ => throw new ArgumentOutOfRangeException("", "LastRunStatus was not recognized"), + }; } } diff --git a/src/Opserver.Core/Data/SQL/SQLInstance.Services.cs b/src/Opserver.Core/Data/SQL/SQLInstance.Services.cs index e69eca1a4..5f4a2b9f6 100644 --- a/src/Opserver.Core/Data/SQL/SQLInstance.Services.cs +++ b/src/Opserver.Core/Data/SQL/SQLInstance.Services.cs @@ -19,21 +19,13 @@ public MonitorStatus MonitorStatus get { if (!Status.HasValue) return MonitorStatus.Unknown; - switch (Status.Value) + return Status.Value switch { - case ServiceStatuses.Stopped: - return MonitorStatus.Critical; - case ServiceStatuses.StartPending: - case ServiceStatuses.StopPending: - case ServiceStatuses.Paused: - return MonitorStatus.Warning; - case ServiceStatuses.Running: - case ServiceStatuses.ContinuePending: - case ServiceStatuses.PausePending: - return MonitorStatus.Good; - default: - throw new ArgumentOutOfRangeException(); - } + ServiceStatuses.Stopped => MonitorStatus.Critical, + ServiceStatuses.StartPending or ServiceStatuses.StopPending or ServiceStatuses.Paused => MonitorStatus.Warning, + ServiceStatuses.Running or ServiceStatuses.ContinuePending or ServiceStatuses.PausePending => MonitorStatus.Good, + _ => throw new ArgumentOutOfRangeException(), + }; } } @@ -42,15 +34,11 @@ public string MonitorStatusReason get { if (!Status.HasValue) return ServiceName + " - Status unknown"; - switch (Status.Value) + return Status.Value switch { - case ServiceStatuses.Running: - case ServiceStatuses.ContinuePending: - case ServiceStatuses.PausePending: - return null; - default: - return ServiceName + " - " + (Status.HasValue ? Status.Value.AsString(EnumFormat.Description) : ""); - } + ServiceStatuses.Running or ServiceStatuses.ContinuePending or ServiceStatuses.PausePending => null, + _ => ServiceName + " - " + (Status.HasValue ? Status.Value.AsString(EnumFormat.Description) : ""), + }; } } diff --git a/src/Opserver.Core/Data/SQL/SQLInstance.cs b/src/Opserver.Core/Data/SQL/SQLInstance.cs index 7a3e7f0d7..e1e06c886 100644 --- a/src/Opserver.Core/Data/SQL/SQLInstance.cs +++ b/src/Opserver.Core/Data/SQL/SQLInstance.cs @@ -2,9 +2,9 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Data.Common; -using System.Data.SqlClient; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using Microsoft.Data.SqlClient; using Opserver.Helpers; namespace Opserver.Data.SQL @@ -24,8 +24,7 @@ public partial class SQLInstance : PollNode, ISearchableNode public SQLServerEngine Engine { get; internal set; } = new SQLServerEngine(new Version(), SQLServerEditions.Standard); // default to 0.0 protected SQLSettings.Instance Settings { get; } - protected static readonly ConcurrentDictionary, string> QueryLookup = - new ConcurrentDictionary, string>(); + protected static readonly ConcurrentDictionary, string> QueryLookup = new(); public string GetFetchSQL() where T : ISQLVersioned, new() => GetFetchSQL(Engine); public static string GetFetchSQL(in SQLServerEngine e) where T : ISQLVersioned, new() => Singleton.Instance.GetFetchSQL(e); diff --git a/src/Opserver.Core/Data/SQL/SQLNode.AvailabilityGroups.AGDatabaseReplica.cs b/src/Opserver.Core/Data/SQL/SQLNode.AvailabilityGroups.AGDatabaseReplica.cs index 120111d96..cc08d4f80 100644 --- a/src/Opserver.Core/Data/SQL/SQLNode.AvailabilityGroups.AGDatabaseReplica.cs +++ b/src/Opserver.Core/Data/SQL/SQLNode.AvailabilityGroups.AGDatabaseReplica.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using EnumsNET; namespace Opserver.Data.SQL diff --git a/src/Opserver.Core/Data/SQL/SQLNode.AvailabilityGroups.AGListenerIPAddress.cs b/src/Opserver.Core/Data/SQL/SQLNode.AvailabilityGroups.AGListenerIPAddress.cs index 3251b1741..39403ebc8 100644 --- a/src/Opserver.Core/Data/SQL/SQLNode.AvailabilityGroups.AGListenerIPAddress.cs +++ b/src/Opserver.Core/Data/SQL/SQLNode.AvailabilityGroups.AGListenerIPAddress.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; namespace Opserver.Data.SQL { diff --git a/src/Opserver.Core/Data/SQL/SQLServerEngine.cs b/src/Opserver.Core/Data/SQL/SQLServerEngine.cs index 230786ce4..46c7a866f 100644 --- a/src/Opserver.Core/Data/SQL/SQLServerEngine.cs +++ b/src/Opserver.Core/Data/SQL/SQLServerEngine.cs @@ -35,90 +35,90 @@ public static class SQLServerVersions /// public static class SQL7 { - public static readonly Version RTM = new Version(7, 0, 623); - public static readonly Version SP1 = new Version(7, 0, 699); - public static readonly Version SP2 = new Version(7, 0, 842); - public static readonly Version SP3 = new Version(7, 0, 961); - public static readonly Version SP4 = new Version(7, 0, 1063); + public static readonly Version RTM = new(7, 0, 623); + public static readonly Version SP1 = new(7, 0, 699); + public static readonly Version SP2 = new(7, 0, 842); + public static readonly Version SP3 = new(7, 0, 961); + public static readonly Version SP4 = new(7, 0, 1063); } /// /// Shiloh /// public static class SQL2000 { - public static readonly Version RTM = new Version(8, 0, 194); - public static readonly Version SP1 = new Version(8, 0, 384); - public static readonly Version SP2 = new Version(8, 0, 532); - public static readonly Version SP3 = new Version(8, 0, 760); - public static readonly Version SP4 = new Version(8, 0, 2039); + public static readonly Version RTM = new(8, 0, 194); + public static readonly Version SP1 = new(8, 0, 384); + public static readonly Version SP2 = new(8, 0, 532); + public static readonly Version SP3 = new(8, 0, 760); + public static readonly Version SP4 = new(8, 0, 2039); } /// /// Yukon /// public static class SQL2005 { - public static readonly Version RTM = new Version(9, 0, 1399); //.06 technicaly, meh - public static readonly Version SP1 = new Version(9, 0, 2047); - public static readonly Version SP2 = new Version(9, 0, 3042); - public static readonly Version SP3 = new Version(9, 0, 4035); - public static readonly Version SP4 = new Version(9, 0, 5000); + public static readonly Version RTM = new(9, 0, 1399); //.06 technicaly, meh + public static readonly Version SP1 = new(9, 0, 2047); + public static readonly Version SP2 = new(9, 0, 3042); + public static readonly Version SP3 = new(9, 0, 4035); + public static readonly Version SP4 = new(9, 0, 5000); } /// /// Katmai /// public static class SQL2008 { - public static readonly Version RTM = new Version(10, 0, 1600); //.22 - public static readonly Version SP1 = new Version(10, 0, 2531); - public static readonly Version SP2 = new Version(10, 0, 4000); - public static readonly Version SP3 = new Version(10, 0, 5500); + public static readonly Version RTM = new(10, 0, 1600); //.22 + public static readonly Version SP1 = new(10, 0, 2531); + public static readonly Version SP2 = new(10, 0, 4000); + public static readonly Version SP3 = new(10, 0, 5500); } /// /// Kilimanjaro /// public static class SQL2008R2 { - public static readonly Version RTM = new Version(10, 50, 1600); - public static readonly Version SP1 = new Version(10, 50, 2500); - public static readonly Version SP2 = new Version(10, 50, 4000); + public static readonly Version RTM = new(10, 50, 1600); + public static readonly Version SP1 = new(10, 50, 2500); + public static readonly Version SP2 = new(10, 50, 4000); } /// /// Denali /// public static class SQL2012 { - public static readonly Version RTM = new Version(11, 0, 2100); - public static readonly Version SP1 = new Version(11, 0, 3000); - public static readonly Version SP2 = new Version(11, 0, 5058); + public static readonly Version RTM = new(11, 0, 2100); + public static readonly Version SP1 = new(11, 0, 3000); + public static readonly Version SP2 = new(11, 0, 5058); } /// /// Hekaton /// public static class SQL2014 { - public static readonly Version RTM = new Version(12, 0); - public static readonly Version SP1 = new Version(12, 0, 4100); + public static readonly Version RTM = new(12, 0); + public static readonly Version SP1 = new(12, 0, 4100); } public static class SQL2016 { - public static readonly Version RTM = new Version(13, 0); - public static readonly Version SP1 = new Version(13, 0, 4001); + public static readonly Version RTM = new(13, 0); + public static readonly Version SP1 = new(13, 0, 4001); } public static class SQL2017 { - public static readonly Version RTM = new Version(14, 0); + public static readonly Version RTM = new(14, 0); } public static class SQL2019 { - public static readonly Version RTM = new Version(15, 0); + public static readonly Version RTM = new(15, 0); } public static class SQL2022 { - public static readonly Version RTM = new Version(16, 0); + public static readonly Version RTM = new(16, 0); } } } diff --git a/src/Opserver.Core/ExtensionMethods.GetSet.cs b/src/Opserver.Core/ExtensionMethods.GetSet.cs index 008a0a4e8..325eeede6 100644 --- a/src/Opserver.Core/ExtensionMethods.GetSet.cs +++ b/src/Opserver.Core/ExtensionMethods.GetSet.cs @@ -8,9 +8,9 @@ namespace Opserver { public static partial class ExtensionMethods { - private static readonly object _syncLock = new object(); - private static readonly ConcurrentDictionary _getSetNullLocks = new ConcurrentDictionary(); - private static readonly ConcurrentDictionary _getSetSemaphores = new ConcurrentDictionary(); + private static readonly object _syncLock = new(); + private static readonly ConcurrentDictionary _getSetNullLocks = new(); + private static readonly ConcurrentDictionary _getSetSemaphores = new(); internal class GetSetWrapper { @@ -78,11 +78,7 @@ private static bool GotCompeteLock(IMemoryCache cache, string key) private static SemaphoreSlim GetNullSemaphore(ref SemaphoreSlim semaphore, string key) { - if (semaphore == null) - { - semaphore = _getSetSemaphores.AddOrUpdate(key, _ => new SemaphoreSlim(1), (_, old) => old); - } - return semaphore; + return semaphore ??= _getSetSemaphores.AddOrUpdate(key, _ => new SemaphoreSlim(1), (_, old) => old); } private static int _totalGetSetSync, _totalGetSetAsyncSuccess, _totalGetSetAsyncError; diff --git a/src/Opserver.Core/ExtensionMethods.Sequences.cs b/src/Opserver.Core/ExtensionMethods.Sequences.cs index 24c073c93..410316d86 100644 --- a/src/Opserver.Core/ExtensionMethods.Sequences.cs +++ b/src/Opserver.Core/ExtensionMethods.Sequences.cs @@ -8,14 +8,14 @@ public static partial class ExtensionMethods { internal static string GetString(this ref SequenceReader reader, int length) { - var value = Encoding.UTF8.GetString(reader.UnreadSpan.Slice(0, length).Trim((byte)0)); + var value = Encoding.UTF8.GetString(reader.UnreadSpan[..length].Trim((byte)0)); reader.Advance(length); return value; } internal static string GetBase64EncodedString(this ref SequenceReader reader, int length) { - var value = Convert.ToBase64String(reader.UnreadSpan.Slice(0, length)); + var value = Convert.ToBase64String(reader.UnreadSpan[..length]); reader.Advance(length); return value; } diff --git a/src/Opserver.Core/ExtensionMethods.Sql.cs b/src/Opserver.Core/ExtensionMethods.Sql.cs index 42a87b046..54b0ed100 100644 --- a/src/Opserver.Core/ExtensionMethods.Sql.cs +++ b/src/Opserver.Core/ExtensionMethods.Sql.cs @@ -15,7 +15,7 @@ public static partial class ExtensionMethods public static async Task> AsList(this Task> source) { var result = await source; - return result != null && !(result is List) ? result.ToList() : (List) result; + return result != null && result is List resultList ? resultList : result.ToList(); } public static async Task ExecuteAsync(this DbConnection conn, string sql, dynamic param = null, IDbTransaction transaction = null, [CallerFilePath]string fromFile = null, [CallerLineNumber]int onLine = 0, string comment = null, int? commandTimeout = null) @@ -84,7 +84,7 @@ public static async Task> QueryAsync EnsureOpenAsync(this DbConnection connection) { - if (connection == null) throw new ArgumentNullException(nameof(connection)); + ArgumentNullException.ThrowIfNull(connection); switch (connection.State) { case ConnectionState.Open: @@ -108,7 +108,7 @@ public static async Task EnsureOpenAsync(this DbConnection connecti } } - private static readonly ConcurrentDictionary _markedSql = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary _markedSql = new(); /// /// Takes a SQL query, and inserts the path and line in as a comment. Ripped right out of Stack Overflow proper. @@ -155,7 +155,7 @@ private static string MarkSqlString(string sql, string path, int lineNumber, str if (split < 0) return sql; split++; // just for Craver - var ret = sql.Substring(0, i) + " /* " + path.Substring(split) + "@" + lineNumber.ToString() + (comment.HasValue() ? " - " + comment : "") + " */" + commentWrap + sql.Substring(i); + var ret = sql[..i] + " /* " + path[split..] + "@" + lineNumber.ToString() + (comment.HasValue() ? " - " + comment : "") + " */" + commentWrap + sql[i..]; // Cache, don't allocate all this pass again _markedSql[key] = ret; return ret; @@ -163,12 +163,10 @@ private static string MarkSqlString(string sql, string path, int lineNumber, str public static async Task SetReadUncommittedAsync(this DbConnection connection) { - if (connection == null) throw new ArgumentNullException(nameof(connection)); - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"; - await cmd.ExecuteNonQueryAsync(); - } + ArgumentNullException.ThrowIfNull(connection); + using var cmd = connection.CreateCommand(); + cmd.CommandText = "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"; + await cmd.ExecuteNonQueryAsync(); return 1; } diff --git a/src/Opserver.Core/ExtensionMethods.cs b/src/Opserver.Core/ExtensionMethods.cs index 2ec8dd41f..9201f8fec 100644 --- a/src/Opserver.Core/ExtensionMethods.cs +++ b/src/Opserver.Core/ExtensionMethods.cs @@ -100,8 +100,8 @@ public static string Pluralize(this long count, string name, bool includeNumber { var numString = includeNumber ? count.ToComma() + " " : null; if (count == 1) return numString + name; - if (name.EndsWith("y")) return numString + name.Remove(name.Length - 1) + "ies"; - if (name.EndsWith("s")) return numString + name.Remove(name.Length - 1) + "es"; + if (name.EndsWith('y')) return numString + name.Remove(name.Length - 1) + "ies"; + if (name.EndsWith('s')) return numString + name.Remove(name.Length - 1) + "es"; if (name.EndsWith("ex")) return numString + name + "es"; return numString + name + "s"; } @@ -163,7 +163,7 @@ public static string NormalizeHostOrFQDN(this string s, bool defaultToHttps = fa { if (!s.HasValue()) return s; if (!s.StartsWith("http://") && !s.StartsWith("https://")) return $"{(defaultToHttps ? "https" : "http")}://{s}/"; - return s.EndsWith("/") ? s : s + "/"; + return s.EndsWith('/') ? s : s + "/"; } public static T SafeData(this Cache cache, bool emptyIfMissing = false) where T : class, new() => @@ -190,9 +190,9 @@ public static MonitorStatus GetWorstStatus(this IEnumerable ims) public static IOrderedEnumerable ThenByWorst(this IOrderedEnumerable ims, Func getter) => ims.ThenByDescending(getter); - public static HashSet ToHashSet(this IEnumerable source) => new HashSet(source); + public static HashSet ToHashSet(this IEnumerable source) => new(source); - private static readonly DateTime _epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + private static readonly DateTime _epoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); /// /// Returns a Date given a unix Epoch time @@ -365,7 +365,7 @@ public static T AddLoggedData(this T ex, string key, string value) where T : public static class ThirdPartyExtensionMethods { - private static readonly Regex _traceRegex = new Regex(@"(.*).... \((\d+) more bytes\)$", RegexOptions.Compiled); + private static readonly Regex _traceRegex = new(@"(.*).... \((\d+) more bytes\)$", RegexOptions.Compiled); public static string TraceDescription(this CommandTrace trace, int? truncateTo = null) { if (truncateTo != null) @@ -387,7 +387,7 @@ public static string TraceDescription(this CommandTrace trace, int? truncateTo = public static class IntToBytesExtension { private const int DefaultPrecision = 2; - private static readonly IList Units = new List { "", "K", "M", "G", "T" }; + private static readonly List Units = new() { "", "K", "M", "G", "T" }; /// /// Formats the value as a filesize in bytes (KB, MB, etc.) diff --git a/src/Opserver.Core/GlobalSuppressions.cs b/src/Opserver.Core/GlobalSuppressions.cs index 4af121346..0cd44f42e 100644 --- a/src/Opserver.Core/GlobalSuppressions.cs +++ b/src/Opserver.Core/GlobalSuppressions.cs @@ -5,13 +5,9 @@ // a specific target and scoped to a namespace, type, member, etc. [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "RCS1194:Implement exception constructors.", Justification = "Meh", Scope = "type", Target = "~T:Opserver.Data.IPNet.IPNetParseException")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "RCS1194:Implement exception constructors.", Justification = "Meh", Scope = "type", Target = "~T:Opserver.Data.JsonApiException")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Matching SQL fields", Scope = "type", Target = "~T:Opserver.Data.SQL.SQLInstance.WhoIsActiveRow")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "RCS1221:Use pattern matching instead of combination of 'as' operator and null check.", Justification = "", Scope = "member", Target = "~M:Opserver.SettingsProviders.SettingsProvider.GetCurrentProvider~Opserver.SettingsProviders.SettingsProvider")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "", Scope = "member", Target = "~M:Opserver.Data.Dashboard.Providers.WmiDataProvider.WmiNode.GetAllInterfacesAsync~System.Threading.Tasks.Task")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "", Scope = "member", Target = "~M:Opserver.SettingsProviders.SettingsProvider.GetCurrentProvider~Opserver.SettingsProviders.SettingsProvider")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1154:Sort enum members.", Justification = "", Scope = "type", Target = "~T:Opserver.Data.HAProxy.ProxyServerStatus")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "RCS1146:Use conditional access.", Justification = "", Scope = "member", Target = "~M:Opserver.Data.Dashboard.DashboardModule.#cctor")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "RCS1146:Use conditional access.", Justification = "", Scope = "member", Target = "~M:Opserver.Data.Redis.RedisHost.GetDownstreamHosts(System.Collections.Generic.List{Opserver.Data.Redis.RedisInstance})~System.Collections.Generic.List{Opserver.Data.Redis.RedisHost.ReplicaSummary}")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "RCS1146:Use conditional access.", Justification = "", Scope = "member", Target = "~M:Opserver.Helpers.FileSizeFormatProvider.Format(System.String,System.Object,System.IFormatProvider)~System.String")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "RCS1146:Use conditional access.", Justification = "", Scope = "member", Target = "~M:Opserver.Data.Dashboard.Providers.BosunMetric.GetDenormalized(System.String,System.String,System.Collections.Generic.Dictionary{System.String,System.Collections.Generic.List{System.String}})~System.String")] diff --git a/src/Opserver.Core/Helpers/Connection.cs b/src/Opserver.Core/Helpers/Connection.cs index 452724c93..2514ae4d3 100644 --- a/src/Opserver.Core/Helpers/Connection.cs +++ b/src/Opserver.Core/Helpers/Connection.cs @@ -1,9 +1,9 @@ using System; using System.Data; using System.Data.Common; -using System.Data.SqlClient; using System.Threading; using System.Threading.Tasks; +using Microsoft.Data.SqlClient; using StackExchange.Profiling; using StackExchange.Profiling.Data; diff --git a/src/Opserver.Core/Helpers/CryptoRandom.cs b/src/Opserver.Core/Helpers/CryptoRandom.cs index 17b62eb2f..1ddfd7227 100644 --- a/src/Opserver.Core/Helpers/CryptoRandom.cs +++ b/src/Opserver.Core/Helpers/CryptoRandom.cs @@ -57,7 +57,7 @@ public int Next(int exclusiveMax) { if (exclusiveMax < 0) { - throw new ArgumentOutOfRangeException($"Must be >= 0, was {exclusiveMax}", nameof(exclusiveMax)); + throw new ArgumentOutOfRangeException(nameof(exclusiveMax), $"Must be >= 0, was {exclusiveMax}"); } var randomZeroToOneExclusiveDouble = NextDouble(); @@ -70,9 +70,7 @@ public int Next(int inclusiveMin, int exclusiveMax) { if (inclusiveMin > exclusiveMax) { - throw new ArgumentOutOfRangeException( - $"Must be <= {nameof(exclusiveMax)}, was {inclusiveMin} ({nameof(exclusiveMax)} = {exclusiveMax})", - nameof(inclusiveMin)); + throw new ArgumentOutOfRangeException(nameof(inclusiveMin), $"Must be <= {nameof(exclusiveMax)}, was {inclusiveMin} ({nameof(exclusiveMax)} = {exclusiveMax})"); } // based on actual Random: diff --git a/src/Opserver.Core/Helpers/FileSizeFormatProvider.cs b/src/Opserver.Core/Helpers/FileSizeFormatProvider.cs index cff7c0fb2..ff1892035 100644 --- a/src/Opserver.Core/Helpers/FileSizeFormatProvider.cs +++ b/src/Opserver.Core/Helpers/FileSizeFormatProvider.cs @@ -57,9 +57,9 @@ public string Format(string format, object arg, IFormatProvider formatProvider) suffix = " B"; } - string precision = format.Substring(2); + string precision = format[2..]; if (precision.IsNullOrEmpty()) precision = "2"; return string.Format("{0:N" + precision + "}{1}", size, suffix); } } -} \ No newline at end of file +} diff --git a/src/Opserver.Core/Helpers/Singleton.cs b/src/Opserver.Core/Helpers/Singleton.cs index 5325a66d4..4412256a0 100644 --- a/src/Opserver.Core/Helpers/Singleton.cs +++ b/src/Opserver.Core/Helpers/Singleton.cs @@ -2,6 +2,6 @@ { public static class Singleton where T : new() { - public static readonly T Instance = new T(); + public static readonly T Instance = new(); } } diff --git a/src/Opserver.Core/Helpers/WindowsKernelVersions.cs b/src/Opserver.Core/Helpers/WindowsKernelVersions.cs index 0de26adb1..a67c69ea2 100644 --- a/src/Opserver.Core/Helpers/WindowsKernelVersions.cs +++ b/src/Opserver.Core/Helpers/WindowsKernelVersions.cs @@ -4,17 +4,17 @@ namespace Opserver.Helpers { public static class WindowsKernelVersions { - public static readonly Version WindowsNT31 = new Version(3, 1); - public static readonly Version WindowsNT35 = new Version(3, 5); - public static readonly Version WindowsNT351 = new Version(3, 51); - public static readonly Version WindowsNT4 = new Version(4, 0); - public static readonly Version Windows2000 = new Version(5, 0); - public static readonly Version WindowsXP = new Version(5, 1); - public static readonly Version Windows2003AndXP64 = new Version(5, 2); - public static readonly Version Windows2008AndVista = new Version(6, 0); - public static readonly Version Windows2008R2And7 = new Version(6, 1); - public static readonly Version Windows2012And8 = new Version(6, 2); - public static readonly Version Windows2012R2And81 = new Version(6, 3); - public static readonly Version Windows2016And10 = new Version(10, 0); + public static readonly Version WindowsNT31 = new(3, 1); + public static readonly Version WindowsNT35 = new(3, 5); + public static readonly Version WindowsNT351 = new(3, 51); + public static readonly Version WindowsNT4 = new(4, 0); + public static readonly Version Windows2000 = new(5, 0); + public static readonly Version WindowsXP = new(5, 1); + public static readonly Version Windows2003AndXP64 = new(5, 2); + public static readonly Version Windows2008AndVista = new(6, 0); + public static readonly Version Windows2008R2And7 = new(6, 1); + public static readonly Version Windows2012And8 = new(6, 2); + public static readonly Version Windows2012R2And81 = new(6, 3); + public static readonly Version Windows2016And10 = new(10, 0); } } diff --git a/src/Opserver.Core/Helpers/Wmi.cs b/src/Opserver.Core/Helpers/Wmi.cs index d57ca53cc..53082c602 100644 --- a/src/Opserver.Core/Helpers/Wmi.cs +++ b/src/Opserver.Core/Helpers/Wmi.cs @@ -17,13 +17,13 @@ internal static class Wmi internal class WmiQuery : IDisposable { - private static readonly ConnectionOptions _localOptions = new ConnectionOptions + private static readonly ConnectionOptions _localOptions = new() { EnablePrivileges = true }; - private static readonly ConcurrentDictionary<(string Username, string Password), ConnectionOptions> _optionsCache = new ConcurrentDictionary<(string Username, string Password), ConnectionOptions>(); - private static readonly ConcurrentDictionary _scopeCache = new ConcurrentDictionary(); - private static readonly ConcurrentDictionary _searcherCache = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary<(string Username, string Password), ConnectionOptions> _optionsCache = new(); + private static readonly ConcurrentDictionary _scopeCache = new(); + private static readonly ConcurrentDictionary _searcherCache = new(); private ManagementObjectCollection _data; private readonly ManagementObjectSearcher _searcher; @@ -54,29 +54,25 @@ private static ConnectionOptions GetConnectOptions((string Username, string Pass if (machineName == Environment.MachineName) return _localOptions; - switch (machineName) + return machineName switch { - case "localhost": - case "127.0.0.1": - case "::1": - return _localOptions; - default: - return _optionsCache.GetOrAdd(credentials, tuple => - { - var options = new ConnectionOptions - { - EnablePrivileges = true, - Authentication = AuthenticationLevel.Packet, - Timeout = TimeSpan.FromSeconds(30) - }; - if (tuple.Username.HasValue() && tuple.Password.HasValue()) - { - options.Username = tuple.Username; - options.Password = tuple.Password; - } - return options; - }); - } + "localhost" or "127.0.0.1" or "::1" => _localOptions, + _ => _optionsCache.GetOrAdd(credentials, tuple => + { + var options = new ConnectionOptions + { + EnablePrivileges = true, + Authentication = AuthenticationLevel.Packet, + Timeout = TimeSpan.FromSeconds(30) + }; + if (tuple.Username.HasValue() && tuple.Password.HasValue()) + { + options.Username = tuple.Username; + options.Password = tuple.Password; + } + return options; + }), + }; } public Task Result diff --git a/src/Opserver.Core/Opserver.Core.csproj b/src/Opserver.Core/Opserver.Core.csproj index b16a9181c..9e53af342 100644 --- a/src/Opserver.Core/Opserver.Core.csproj +++ b/src/Opserver.Core/Opserver.Core.csproj @@ -7,30 +7,26 @@ embedded - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - \ No newline at end of file diff --git a/src/Opserver.Core/Settings/ElasticSettings.cs b/src/Opserver.Core/Settings/ElasticSettings.cs index e6773577e..def282294 100644 --- a/src/Opserver.Core/Settings/ElasticSettings.cs +++ b/src/Opserver.Core/Settings/ElasticSettings.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; -using System.Linq; using Opserver.Data.Elastic; namespace Opserver { public class ElasticSettings : ModuleSettings { - public override bool Enabled => Clusters?.Any() ?? false; + public override bool Enabled => Clusters?.Count > 0; public override string AdminRole => ElasticRoles.Admin; public override string ViewRole => ElasticRoles.Viewer; diff --git a/src/Opserver.Web/Controllers/AdminController.cs b/src/Opserver.Web/Controllers/AdminController.cs index 8b570d0a3..b2aef756a 100644 --- a/src/Opserver.Web/Controllers/AdminController.cs +++ b/src/Opserver.Web/Controllers/AdminController.cs @@ -23,6 +23,7 @@ public ActionResult Dashboard() /// Access our error log. /// [Route("admin/errors/{resource?}/{subResource?}"), AlsoAllow(Roles.LocalRequest)] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "ASP0018:Unused route parameter", Justification = "Known unused, matching handler patterns")] public Task InvokeErrorHandler() => ExceptionalMiddleware.HandleRequestAsync(HttpContext); } } diff --git a/src/Opserver.Web/Controllers/AuthController.OIDC.cs b/src/Opserver.Web/Controllers/AuthController.OIDC.cs index e9087d48e..4354bfcf3 100644 --- a/src/Opserver.Web/Controllers/AuthController.OIDC.cs +++ b/src/Opserver.Web/Controllers/AuthController.OIDC.cs @@ -194,7 +194,7 @@ static IEnumerable ConvertToClaims(string name, JsonElement jsonElement) return Redirect(returnUrl); } - private IActionResult RedirectToProvider(string returnUrl) + private RedirectResult RedirectToProvider(string returnUrl) { // first write a cookie representing some unique identifier // we'll use this to validate that the OIDC flow is for the specific diff --git a/src/Opserver.Web/Controllers/DataController.cs b/src/Opserver.Web/Controllers/DataController.cs index 03c750e5f..a94afc455 100644 --- a/src/Opserver.Web/Controllers/DataController.cs +++ b/src/Opserver.Web/Controllers/DataController.cs @@ -12,7 +12,7 @@ public class DataController : StatusController { private PollingService Poller { get; } - private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions() + private static readonly JsonSerializerOptions _serializerOptions = new() { DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull, WriteIndented = true diff --git a/src/Opserver.Web/Controllers/DefaultRoute.cs b/src/Opserver.Web/Controllers/DefaultRoute.cs index 2dc16ac32..63109dd0e 100644 --- a/src/Opserver.Web/Controllers/DefaultRoute.cs +++ b/src/Opserver.Web/Controllers/DefaultRoute.cs @@ -7,7 +7,7 @@ namespace Opserver.Controllers [AttributeUsage(AttributeTargets.Method)] public sealed class DefaultRoute : RouteAttribute { - private static Dictionary AllRoutes => new Dictionary(); + private static Dictionary AllRoutes => new(); public DefaultRoute(string template) : base(template) { } diff --git a/src/Opserver.Web/Controllers/ExceptionsController.cs b/src/Opserver.Web/Controllers/ExceptionsController.cs index 52feff040..444d6c770 100644 --- a/src/Opserver.Web/Controllers/ExceptionsController.cs +++ b/src/Opserver.Web/Controllers/ExceptionsController.cs @@ -42,7 +42,7 @@ public override void OnActionExecuting(ActionExecutingContext context) CurrentLog = GetParam("log") ?? GetParam("app"); // old link compat CurrentId = GetParam("id").HasValue() && Guid.TryParse(GetParam("id"), out var guid) ? guid : (Guid?)null; CurrentSimilarId = GetParam("similar").HasValue() && Guid.TryParse(GetParam("similar"), out var similarGuid) ? similarGuid : (Guid?)null; - Enum.TryParse(GetParam("sort"), out CurrentSort); + _ = Enum.TryParse(GetParam("sort"), out CurrentSort); CurrentUrl = GetParam("url")?.Trim(); CurrentHost = GetParam("host")?.Trim(); if (GetDate("startDate") is DateTime startDate) diff --git a/src/Opserver.Web/Controllers/GraphController.Spark.cs b/src/Opserver.Web/Controllers/GraphController.Spark.cs index 76297d3fe..3e1b307c2 100644 --- a/src/Opserver.Web/Controllers/GraphController.Spark.cs +++ b/src/Opserver.Web/Controllers/GraphController.Spark.cs @@ -249,16 +249,16 @@ public async Task SparkSvgAll(string key, Func\n") .Append("\t\n"); @@ -273,7 +273,7 @@ public async Task SparkSvgAll(string key, Func(IEnumerable points, long max, Func getVal, DateTime? start = null) where T : IGraphPoint + private static FileContentResult SparkSVG(IEnumerable points, long max, Func getVal, DateTime? start = null) where T : IGraphPoint { const int height = SparkHeight, width = SparkPoints; @@ -293,16 +293,16 @@ private static FileResult SparkSVG(IEnumerable points, long max, Func "); @@ -316,6 +316,6 @@ private static FileResult SparkSVG(IEnumerable points, long max, Func ", SparkHeight.ToString(), SparkPoints.ToString())); - private static FileResult EmptySparkSVG() => new FileContentResult(EmptySvgBytes, "image/svg+xml"); + private static FileContentResult EmptySparkSVG() => new(EmptySvgBytes, "image/svg+xml"); } } diff --git a/src/Opserver.Web/Controllers/HomeController.cs b/src/Opserver.Web/Controllers/HomeController.cs index c456aacd3..8a5ce6156 100644 --- a/src/Opserver.Web/Controllers/HomeController.cs +++ b/src/Opserver.Web/Controllers/HomeController.cs @@ -148,9 +148,7 @@ public ActionResult ErrorTestPage() { Current.LogException(new Exception("Test Exception via GlobalApplication.LogException()")); -#pragma warning disable RCS1079 // Throwing of new NotImplementedException. throw new NotImplementedException("I AM IMPLEMENTED, I WAS BORN TO THROW ERRORS!"); -#pragma warning restore RCS1079 // Throwing of new NotImplementedException. } } } diff --git a/src/Opserver.Web/Controllers/StatusController.cs b/src/Opserver.Web/Controllers/StatusController.cs index eac8f2355..11350772c 100644 --- a/src/Opserver.Web/Controllers/StatusController.cs +++ b/src/Opserver.Web/Controllers/StatusController.cs @@ -53,7 +53,7 @@ public void SetTitle(string title) /// /// The text content to render protected ContentResult TextPlain(string content) => - new ContentResult { Content = content, ContentType = "text/plain" }; + new() { Content = content, ContentType = "text/plain" }; protected ContentResult ContentNotFound(string message = null) { diff --git a/src/Opserver.Web/Current.cs b/src/Opserver.Web/Current.cs index d7daa4b7d..35852ef7c 100644 --- a/src/Opserver.Web/Current.cs +++ b/src/Opserver.Web/Current.cs @@ -12,7 +12,7 @@ namespace Opserver { public static class Current { - private static readonly AsyncLocal _context = new AsyncLocal(); + private static readonly AsyncLocal _context = new(); public static CurrentContext Context => _context.Value; public static void SetContext(CurrentContext context) => _context.Value = context; diff --git a/src/Opserver.Web/ExtensionMethods.cs b/src/Opserver.Web/ExtensionMethods.cs index 5fbed2d7a..c7dcebf5f 100644 --- a/src/Opserver.Web/ExtensionMethods.cs +++ b/src/Opserver.Web/ExtensionMethods.cs @@ -27,7 +27,7 @@ public static class WebExtensionMethods /// This string is already correctly encoded HTML and can be sent to the client "as is" without additional encoding. /// /// The already-encoded HTML string. - public static HtmlString AsHtml(this string html) => new HtmlString(html); + public static HtmlString AsHtml(this string html) => new(html); /// /// Title cases a string given the current culture. @@ -73,21 +73,13 @@ public static HtmlString ColorCode(this string s) => /// Returns an icon span representation of this MonitorStatus. /// /// The status to get an icon for. - public static HtmlString IconSpan(this MonitorStatus status) + public static HtmlString IconSpan(this MonitorStatus status) => status switch { - switch (status) - { - case MonitorStatus.Good: - return StatusIndicator.IconSpanGood; - case MonitorStatus.Warning: - case MonitorStatus.Maintenance: - return StatusIndicator.IconSpanWarning; - case MonitorStatus.Critical: - return StatusIndicator.IconSpanCritical; - default: - return StatusIndicator.IconSpanUnknown; - } - } + MonitorStatus.Good => StatusIndicator.IconSpanGood, + MonitorStatus.Warning or MonitorStatus.Maintenance => StatusIndicator.IconSpanWarning, + MonitorStatus.Critical => StatusIndicator.IconSpanCritical, + _ => StatusIndicator.IconSpanUnknown, + }; /// /// Gets an icon representing the current status of a . @@ -182,22 +174,13 @@ public static string BackgroundClass(this MonitorStatus status, bool showGood = _ => "bg-muted", }; - public static string ProgressBarClass(this MonitorStatus status) + public static string ProgressBarClass(this MonitorStatus status) => status switch { - switch (status) - { - case MonitorStatus.Good: - return "progress-bar-success"; - case MonitorStatus.Unknown: - case MonitorStatus.Maintenance: - case MonitorStatus.Warning: - return "progress-bar-warning"; - case MonitorStatus.Critical: - return "progress-bar-danger"; - default: - return ""; - } - } + MonitorStatus.Good => "progress-bar-success", + MonitorStatus.Unknown or MonitorStatus.Maintenance or MonitorStatus.Warning => "progress-bar-warning", + MonitorStatus.Critical => "progress-bar-danger", + _ => "", + }; public static HtmlString ToPollSpan(this Cache cache, bool mini = true, bool lastSuccess = false) { @@ -383,18 +366,18 @@ public static HtmlString ToTimeString(this int seconds) var ts = new TimeSpan(0, 0, seconds); var sb = StringBuilderCache.Get(); if (ts.Days > 0) - sb.Append("").Append(ts.Days.ToString()).Append("d "); + sb.Append("").Append(ts.Days).Append("d "); if (ts.Hours > 0) - sb.Append("").Append(ts.Hours.ToString()).Append("hr "); + sb.Append("").Append(ts.Hours).Append("hr "); if (ts.Minutes > 0) - sb.Append("").Append(ts.Minutes.ToString()).Append("min "); + sb.Append("").Append(ts.Minutes).Append("min "); if (ts.Seconds > 0 && ts.Days == 0) - sb.Append("").Append(ts.Seconds.ToString()).Append("sec "); + sb.Append("").Append(ts.Seconds).Append("sec "); return sb.ToStringRecycle().AsHtml(); } - private static readonly HtmlString YesHtml = new HtmlString("Yes"); - private static readonly HtmlString NoHtml = new HtmlString("No"); + private static readonly HtmlString YesHtml = new("Yes"); + private static readonly HtmlString NoHtml = new("No"); public static HtmlString ToYesNo(this bool value) => value ? YesHtml : NoHtml; @@ -438,14 +421,14 @@ public static HtmlString ToMutedIfNA(this string data) public static string ToQueryString(this NameValueCollection nvc) { var sb = StringBuilderCache.Get(); - sb.Append("?"); + sb.Append('?'); foreach (string key in nvc) { foreach (var value in nvc.GetValues(key)) { - if (sb.Length > 1) sb.Append("&"); + if (sb.Length > 1) sb.Append('&'); sb.Append(key.UrlEncode()) - .Append("=") + .Append('=') .Append(value.UrlEncode()); } } @@ -464,7 +447,7 @@ public static RouteValueDictionary ToRouteValues(this IQueryCollection queryStri } public static bool IsAjax(this HttpRequest request) => - request != null && request.Headers["X-Requested-With"] == "XMLHttpRequest"; + request != null && request.Headers.XRequestedWith == "XMLHttpRequest"; public static bool IsAjaxRequest(this RazorPageBase page) => page.ViewContext.HttpContext.Request.IsAjax(); @@ -527,26 +510,17 @@ public static void SetTopNodes(this RazorPage page, public static class EnumExtensions { - public static HtmlString ToSpan(this SynchronizationStates? state, string tooltip = null) + public static HtmlString ToSpan(this SynchronizationStates? state, string tooltip = null) => state switch { - switch (state) - { - case SynchronizationStates.Synchronizing: - case SynchronizationStates.Synchronized: - return StatusIndicator.UpCustomSpan(state.Value.AsString(EnumFormat.Description), tooltip); - case SynchronizationStates.NotSynchronizing: - case SynchronizationStates.Reverting: - case SynchronizationStates.Initializing: - return StatusIndicator.DownCustomSpan(state.Value.AsString(EnumFormat.Description), tooltip); - default: - return StatusIndicator.UnknownCustomSpan(state.Value.AsString(EnumFormat.Description), tooltip); - } - } + SynchronizationStates.Synchronizing or SynchronizationStates.Synchronized => StatusIndicator.UpCustomSpan(state.Value.AsString(EnumFormat.Description), tooltip), + SynchronizationStates.NotSynchronizing or SynchronizationStates.Reverting or SynchronizationStates.Initializing => StatusIndicator.DownCustomSpan(state.Value.AsString(EnumFormat.Description), tooltip), + _ => StatusIndicator.UnknownCustomSpan(state.Value.AsString(EnumFormat.Description), tooltip), + }; public static HtmlString ToSpan(this ReplicaRoles? state, string tooltip = null, bool abbreviate = false) { var desc = state.HasValue ? state.Value.AsString(EnumFormat.Description) : ""; - if (abbreviate) desc = desc.Substring(0, 1); + if (abbreviate) desc = desc[..1]; return state switch { ReplicaRoles.Primary => StatusIndicator.UpCustomSpan(desc, tooltip), diff --git a/src/Opserver.Web/Helpers/Health.cs b/src/Opserver.Web/Helpers/Health.cs index c2fe8c3b8..5a8b38357 100644 --- a/src/Opserver.Web/Helpers/Health.cs +++ b/src/Opserver.Web/Helpers/Health.cs @@ -26,10 +26,10 @@ void Append(MonitorStatus status, int count) { if (addSpace) { - sb.Append(" "); + sb.Append(' '); addSpace = false; } - sb.Append(status.IconSpan()).Append(" ").Append(count.ToComma()); + sb.Append(status.IconSpan()).Append(' ').Append(count.ToComma()); addSpace = true; } } @@ -56,7 +56,7 @@ public static IHtmlContent OfAGs(IEnumerable ims, bool minimal = { sb.Append(MonitorStatus.Good.Span(good.Count.ToComma(), good.Count.Pluralize("Healthy Database"))); } - sb.Append(" "); + sb.Append(' '); if (bad.Count > 0) { if (good.Count > 0) @@ -70,12 +70,12 @@ public static IHtmlContent OfAGs(IEnumerable ims, bool minimal = { if (bad.Count > 0) { - sb.Append(MonitorStatus.Critical.IconSpan()).Append(" ").Append(bad.Count.ToComma()).Append(" Unhealthy"); + sb.Append(MonitorStatus.Critical.IconSpan()).Append(' ').Append(bad.Count.ToComma()).Append(" Unhealthy"); } - sb.Append(" "); + sb.Append(' '); if (good.Count > 0) { - sb.Append(MonitorStatus.Good.IconSpan()).Append(" ").Append(good.Count.ToComma()).Append(" Healthy"); + sb.Append(MonitorStatus.Good.IconSpan()).Append(' ').Append(good.Count.ToComma()).Append(" Healthy"); } } return sb.ToStringRecycle().AsHtml(); diff --git a/src/Opserver.Web/Helpers/MiniProfilerCacheStorage.cs b/src/Opserver.Web/Helpers/MiniProfilerCacheStorage.cs index 388e38684..31e2e20ba 100644 --- a/src/Opserver.Web/Helpers/MiniProfilerCacheStorage.cs +++ b/src/Opserver.Web/Helpers/MiniProfilerCacheStorage.cs @@ -32,10 +32,7 @@ public MiniProfilerCacheStorageDefaults(IMemoryCache cache, PollingService polle public void Configure(MiniProfilerOptions options) { - if (options.Storage == null) - { - options.Storage = new MiniProfilerCacheStorage(_cache, _poller, TimeSpan.FromMinutes(10)); - } + options.Storage ??= new MiniProfilerCacheStorage(_cache, _poller, TimeSpan.FromMinutes(10)); } } } diff --git a/src/Opserver.Web/Helpers/NavTab.cs b/src/Opserver.Web/Helpers/NavTab.cs index 98791b9de..e5e72d9e6 100644 --- a/src/Opserver.Web/Helpers/NavTab.cs +++ b/src/Opserver.Web/Helpers/NavTab.cs @@ -28,7 +28,7 @@ public NavTab(StatusModule module, string route) } public static List AllTabs { get; private set; } - private static Dictionary _controllerMappings = new Dictionary(); + private static Dictionary _controllerMappings = new(); public static NavTab Get(StatusController c) => _controllerMappings.TryGetValue(c.GetType(), out var tab) ? tab : null; public static NavTab GetByName(string tabName) => AllTabs.Find(t => t.Name == tabName); diff --git a/src/Opserver.Web/Helpers/TestItem.cs b/src/Opserver.Web/Helpers/TestItem.cs index 97a792454..4652ba9f9 100644 --- a/src/Opserver.Web/Helpers/TestItem.cs +++ b/src/Opserver.Web/Helpers/TestItem.cs @@ -5,11 +5,11 @@ namespace Opserver.Helpers { public sealed class TestItem : IMonitorStatus { - public static readonly TestItem Good = new TestItem(MonitorStatus.Good); - public static readonly TestItem Warning = new TestItem(MonitorStatus.Warning); - public static readonly TestItem Maintenance = new TestItem(MonitorStatus.Maintenance); - public static readonly TestItem Critical = new TestItem(MonitorStatus.Critical); - public static readonly TestItem Unknown = new TestItem(MonitorStatus.Unknown); + public static readonly TestItem Good = new(MonitorStatus.Good); + public static readonly TestItem Warning = new(MonitorStatus.Warning); + public static readonly TestItem Maintenance = new(MonitorStatus.Maintenance); + public static readonly TestItem Critical = new(MonitorStatus.Critical); + public static readonly TestItem Unknown = new(MonitorStatus.Unknown); public MonitorStatus MonitorStatus { get; } public string MonitorStatusReason { get; } diff --git a/src/Opserver.Web/Helpers/Theme.cs b/src/Opserver.Web/Helpers/Theme.cs index b6a70a1cf..86795f5ca 100644 --- a/src/Opserver.Web/Helpers/Theme.cs +++ b/src/Opserver.Web/Helpers/Theme.cs @@ -14,7 +14,7 @@ public static class Theme // Cookies need an expiration date! A sliding time period seems downright silly so... // I chose at random from https://en.wikipedia.org/wiki/List_of_dates_predicted_for_apocalyptic_events // "Members predict that the world will end in 2026, when an asteroid would collide with Earth..." - private static readonly DateTime CookieExpirationDate = new DateTime(2026, 1, 1); + private static readonly DateTime CookieExpirationDate = new(2026, 1, 1); public static string Get(HttpRequest request) => request.Cookies[CookieName] ?? Default; diff --git a/src/Opserver.Web/Opserver.Web.csproj b/src/Opserver.Web/Opserver.Web.csproj index d69dc84d8..7c3450e59 100644 --- a/src/Opserver.Web/Opserver.Web.csproj +++ b/src/Opserver.Web/Opserver.Web.csproj @@ -6,13 +6,12 @@ - - - - - - - + + + + + + @@ -23,8 +22,4 @@ - - - - diff --git a/src/Opserver.Web/Security/EveryonesAnAdminProvider.cs b/src/Opserver.Web/Security/EveryonesAnAdminProvider.cs index 654f694e6..17042599a 100644 --- a/src/Opserver.Web/Security/EveryonesAnAdminProvider.cs +++ b/src/Opserver.Web/Security/EveryonesAnAdminProvider.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using System.Security.Claims; +using System.Security.Claims; using Opserver.Models; namespace Opserver.Security diff --git a/src/Opserver.Web/Security/SecurityManager.cs b/src/Opserver.Web/Security/SecurityManager.cs index 7e90676ea..369132dbf 100644 --- a/src/Opserver.Web/Security/SecurityManager.cs +++ b/src/Opserver.Web/Security/SecurityManager.cs @@ -8,7 +8,7 @@ namespace Opserver.Security public class SecurityManager { public SecurityProvider CurrentProvider { get; } - public bool IsConfigured => CurrentProvider != null && !(CurrentProvider is UnconfiguredProvider); + public bool IsConfigured => CurrentProvider != null && CurrentProvider is not UnconfiguredProvider; /// /// Instantiates a new instane of . diff --git a/src/Opserver.Web/Security/SecurityProvider.cs b/src/Opserver.Web/Security/SecurityProvider.cs index 28689d013..493a680a7 100644 --- a/src/Opserver.Web/Security/SecurityProvider.cs +++ b/src/Opserver.Web/Security/SecurityProvider.cs @@ -13,7 +13,7 @@ namespace Opserver.Security public abstract class SecurityProvider { // The theory here is that there won't be that many unique combinations here. - private readonly ConcurrentDictionary _parsedGroups = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _parsedGroups = new(); /// /// Gets the name of this provider. @@ -88,7 +88,7 @@ public bool IsInternalIP(string ip) => /// /// Creates a representing an anonymous user. /// - protected ClaimsPrincipal CreateAnonymousPrincipal() => new ClaimsPrincipal(new ClaimsIdentity()); + protected ClaimsPrincipal CreateAnonymousPrincipal() => new(new ClaimsIdentity()); /// /// Creates a for the given username. @@ -97,7 +97,7 @@ protected ClaimsPrincipal CreateNamedPrincipal(string userName) { var claims = new List { - new Claim(ClaimTypes.Name, userName) + new(ClaimTypes.Name, userName) }; var identity = new ClaimsIdentity(claims, "login"); return new ClaimsPrincipal(identity); @@ -138,7 +138,7 @@ protected SecurityProvider(TSettings settings) : base(settings) public sealed override bool TryValidateToken(ISecurityProviderToken token, out ClaimsPrincipal claimsPrincipal) { - if (!(token is TToken typedToken)) + if (token is not TToken typedToken) { claimsPrincipal = CreateAnonymousPrincipal(); return false; diff --git a/src/Opserver.Web/Startup.cs b/src/Opserver.Web/Startup.cs index cda0d391c..fe1913668 100644 --- a/src/Opserver.Web/Startup.cs +++ b/src/Opserver.Web/Startup.cs @@ -28,6 +28,8 @@ public Startup(IConfiguration configuration) _configuration = configuration; } + private static readonly string[] _svgMime = new[] { "image/svg+xml" }; + public void ConfigureServices(IServiceCollection services) { // Register Opserver.Core config and polling @@ -45,7 +47,7 @@ public void ConfigureServices(IServiceCollection services) services.AddResponseCompression( options => { - options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] { "image/svg+xml" }); + options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(_svgMime); options.Providers.Add(); options.EnableForHttps = true; } diff --git a/src/Opserver.Web/Views/HAProxy/HAProxy.Model.cs b/src/Opserver.Web/Views/HAProxy/HAProxy.Model.cs index b09c01819..c91f69e16 100644 --- a/src/Opserver.Web/Views/HAProxy/HAProxy.Model.cs +++ b/src/Opserver.Web/Views/HAProxy/HAProxy.Model.cs @@ -15,21 +15,11 @@ public enum Views public Views View { get; set; } public bool AdminMode { get; set; } - public bool IsInstanceFilterable + public bool IsInstanceFilterable => View switch { - get - { - switch(View) - { - case Views.Admin: - case Views.Dashboard: - case Views.Detailed: - return true; - default: - return false; - } - } - } + Views.Admin or Views.Dashboard or Views.Detailed => true, + _ => false, + }; public bool Refresh { get; set; } public List Groups { get; set; } diff --git a/src/Opserver.Web/Views/SQL/Operations.Top.Model.cs b/src/Opserver.Web/Views/SQL/Operations.Top.Model.cs index 9a18aad8d..828f75a05 100644 --- a/src/Opserver.Web/Views/SQL/Operations.Top.Model.cs +++ b/src/Opserver.Web/Views/SQL/Operations.Top.Model.cs @@ -16,11 +16,11 @@ public class OperationsTopModel : DashboardModel public static HtmlString GetQueryString(SQLInstance.TopSearchOptions options) { var sb = StringBuilderCache.Get(); - if (options.MinExecs != Default.MinExecs) sb.Append("&").Append(nameof(options.MinExecs)).Append("=").Append(options.MinExecs.Value); - if (options.MinExecsPerMin != Default.MinExecsPerMin) sb.Append("&").Append(nameof(options.MinExecsPerMin)).Append("=").Append(options.MinExecsPerMin.Value); - if (options.Search != Default.Search) sb.Append("&").Append(nameof(options.Search)).Append("=").Append(options.Search.UrlEncode()); - if (options.Database != Default.Database) sb.Append("&").Append(nameof(options.Database)).Append("=").Append(options.Database.Value); - if (options.LastRunSeconds != Default.LastRunSeconds) sb.Append("&").Append(nameof(options.LastRunSeconds)).Append("=").Append(options.LastRunSeconds.Value); + if (options.MinExecs != Default.MinExecs) sb.Append('&').Append(nameof(options.MinExecs)).Append('=').Append(options.MinExecs.Value); + if (options.MinExecsPerMin != Default.MinExecsPerMin) sb.Append('&').Append(nameof(options.MinExecsPerMin)).Append('=').Append(options.MinExecsPerMin.Value); + if (options.Search != Default.Search) sb.Append('&').Append(nameof(options.Search)).Append('=').Append(options.Search.UrlEncode()); + if (options.Database != Default.Database) sb.Append('&').Append(nameof(options.Database)).Append('=').Append(options.Database.Value); + if (options.LastRunSeconds != Default.LastRunSeconds) sb.Append('&').Append(nameof(options.LastRunSeconds)).Append('=').Append(options.LastRunSeconds.Value); return sb.ToStringRecycle().AsHtml(); } diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index 559912403..b34b8e8b7 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -1,12 +1,11 @@ Library - 2.4.1 - - - + + + \ No newline at end of file diff --git a/tests/Opserver.Tests/Opserver.Tests.csproj b/tests/Opserver.Tests/Opserver.Tests.csproj index 5cb796eb7..08b25e45c 100644 --- a/tests/Opserver.Tests/Opserver.Tests.csproj +++ b/tests/Opserver.Tests/Opserver.Tests.csproj @@ -6,15 +6,8 @@ - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + + \ No newline at end of file