From 6e5d48daae28e49f01d3f0da8e1e520fbdfcf81b Mon Sep 17 00:00:00 2001 From: Abrynos <6608231+Abrynos@users.noreply.github.com> Date: Fri, 5 Apr 2024 20:13:36 +0200 Subject: [PATCH 1/9] Downgrade OpenTelemetry.Exporter.Prometheus.AspNetCore due to issues with latest version --- .github/renovate.json5 | 6 ++++++ Directory.Packages.props | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 200c54878961d..e88fbbb143f23 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -19,6 +19,12 @@ "allowedVersions": "<= 3.1", "matchManagers": [ "nuget" ], "matchPackageNames": [ "Microsoft.Extensions.Configuration.Json", "Microsoft.Extensions.Logging.Configuration" ] + }, + { + // TODO: <= 1.7.0-rc.1 for invalid response on monitoring endpoint, last failed version 1.8.0-rc.1 + "allowedVersions": "<= 1.7.0-rc.1", + "matchManagers": [ "nuget" ], + "matchPackageNames": [ "OpenTelemetry.Exporter.Prometheus.AspNetCore" ] } ] } diff --git a/Directory.Packages.props b/Directory.Packages.props index bc97708801c35..f5825cddc04b0 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,7 +10,7 @@ - + From 4fd554c8f4605eaa3f014871f8af867032bc5a13 Mon Sep 17 00:00:00 2001 From: Abrynos <6608231+Abrynos@users.noreply.github.com> Date: Fri, 5 Apr 2024 20:14:13 +0200 Subject: [PATCH 2/9] Add unit to asf_bot_farming_minutes_remaining --- .../MonitoringPlugin.cs | 3 +- .../Units.cs | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 ArchiSteamFarm.OfficialPlugins.Monitoring/Units.cs diff --git a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs index d64caf32f2244..159ad15c67af0 100644 --- a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs @@ -156,7 +156,8 @@ private void InitializeMeter() { return bots.Select(static bot => new Measurement(bot.CardsFarmer.TimeRemaining.TotalMinutes, new KeyValuePair(TagNames.BotName, bot.BotName), new KeyValuePair(TagNames.SteamID, bot.SteamID))); }, - description: "Approximate number of minutes remaining until each bot has finished farming all cards" + Units.Minutes, + "Approximate number of minutes remaining until each bot has finished farming all cards" ); Meter.CreateObservableGauge( diff --git a/ArchiSteamFarm.OfficialPlugins.Monitoring/Units.cs b/ArchiSteamFarm.OfficialPlugins.Monitoring/Units.cs new file mode 100644 index 0000000000000..e77f20da17a60 --- /dev/null +++ b/ArchiSteamFarm.OfficialPlugins.Monitoring/Units.cs @@ -0,0 +1,28 @@ +// ---------------------------------------------------------------------------------------------- +// _ _ _ ____ _ _____ +// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___ +// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \ +// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | | +// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_| +// ---------------------------------------------------------------------------------------------- +// | +// Copyright 2015-2024 Ɓukasz "JustArchi" Domeradzki +// Contact: JustArchi@JustArchi.net +// | +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// | +// http://www.apache.org/licenses/LICENSE-2.0 +// | +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace ArchiSteamFarm.OfficialPlugins.Monitoring; + +internal static class Units { + internal const string Minutes = "minutes"; +} From ef596ee3a894bfc18398f3705566d121f8b59885 Mon Sep 17 00:00:00 2001 From: Abrynos <6608231+Abrynos@users.noreply.github.com> Date: Fri, 5 Apr 2024 20:16:12 +0200 Subject: [PATCH 3/9] Upgrade some packages released last night (already tested to work) --- Directory.Packages.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index f5825cddc04b0..4feafce2f074a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,9 +12,9 @@ - - - + + + From f8719975dc25b3439a2b333f351c5202429dac91 Mon Sep 17 00:00:00 2001 From: Abrynos <6608231+Abrynos@users.noreply.github.com> Date: Fri, 5 Apr 2024 22:54:05 +0200 Subject: [PATCH 4/9] Don't forget about unit suffix --- ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs index 159ad15c67af0..78fdb8be30d3b 100644 --- a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs @@ -150,8 +150,9 @@ private void InitializeMeter() { description: "Number of Steam groups each bot is in" ); + // Keep in mind that we use a unit here and the unit needs to be a suffix to the name Meter.CreateObservableGauge( - $"{MetricNamePrefix}_bot_farming_minutes_remaining", static () => { + $"{MetricNamePrefix}_bot_farming_time_remaining_{Units.Minutes}", static () => { ICollection bots = Bot.Bots?.Values ?? Array.Empty(); return bots.Select(static bot => new Measurement(bot.CardsFarmer.TimeRemaining.TotalMinutes, new KeyValuePair(TagNames.BotName, bot.BotName), new KeyValuePair(TagNames.SteamID, bot.SteamID))); From 184323c248ba4cd21be04715bee1834bc7bf9753 Mon Sep 17 00:00:00 2001 From: Abrynos <6608231+Abrynos@users.noreply.github.com> Date: Sat, 6 Apr 2024 14:48:38 +0200 Subject: [PATCH 5/9] Add build and runtime information metrics It is not recommended to include this information as labels in all metrics. Instead, we add two special metrics with a constant value of "1" and restrict those static pieces of information to them --- .../MonitoringPlugin.cs | 50 +++++++++++++++++++ .../TagNames.cs | 6 +++ ArchiSteamFarm/SharedInfo.cs | 2 +- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs index 78fdb8be30d3b..fd29ed8c360e6 100644 --- a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs @@ -28,6 +28,7 @@ using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Metrics; using System.Linq; +using System.Runtime.InteropServices; using System.Text.Json.Serialization; using System.Threading.Tasks; using ArchiSteamFarm.Core; @@ -50,6 +51,16 @@ internal sealed class MonitoringPlugin : OfficialPlugin, IWebServiceProvider, IG private const string MetricNamePrefix = "asf"; + private static readonly Measurement BuildInfo = + new( + 1, + new KeyValuePair(TagNames.Version, SharedInfo.Version.ToString()), + new KeyValuePair(TagNames.Variant, SharedInfo.BuildInfo.Variant), + new KeyValuePair(TagNames.ModuleVersion, SharedInfo.ModuleVersion.ToString()) + ); + + private static readonly Measurement RuntimeInfo = CreateRuntimeInformation(); + private static bool Enabled => ASF.GlobalConfig?.IPC ?? GlobalConfig.DefaultIPC; [JsonInclude] @@ -98,6 +109,33 @@ public void OnConfiguringServices(IServiceCollection services) { public override Task OnLoaded() => Task.CompletedTask; + private static Measurement CreateRuntimeInformation() { + string framework = RuntimeInformation.FrameworkDescription.Trim(); + + if (framework.Length == 0) { + framework = "unknown"; + } + + string runtime = RuntimeInformation.RuntimeIdentifier.Trim(); + + if (runtime.Length == 0) { + runtime = "unknown"; + } + + string description = RuntimeInformation.OSDescription.Trim(); + + if (description.Length == 0) { + description = "unknown"; + } + + return new Measurement( + 1, + new KeyValuePair(TagNames.Framework, framework), + new KeyValuePair(TagNames.Runtime, runtime), + new KeyValuePair(TagNames.OS, description) + ); + } + [MemberNotNull(nameof(Meter))] private void InitializeMeter() { if (Meter != null) { @@ -106,6 +144,18 @@ private void InitializeMeter() { Meter = new Meter(MeterName, Version.ToString()); + Meter.CreateObservableGauge( + $"{MetricNamePrefix}_build_info", + static () => BuildInfo, + description: "Build information about ASF in form of label values" + ); + + Meter.CreateObservableGauge( + $"{MetricNamePrefix}_runtime_info", + static () => RuntimeInfo, + description: "Runtime information about ASF in form of label values" + ); + Meter.CreateObservableGauge( $"{MetricNamePrefix}_ipc_banned_ips", static () => ApiAuthenticationMiddleware.GetCurrentlyBannedIPs().Count(), diff --git a/ArchiSteamFarm.OfficialPlugins.Monitoring/TagNames.cs b/ArchiSteamFarm.OfficialPlugins.Monitoring/TagNames.cs index bbe3ea1543cb5..e97a7e395dae8 100644 --- a/ArchiSteamFarm.OfficialPlugins.Monitoring/TagNames.cs +++ b/ArchiSteamFarm.OfficialPlugins.Monitoring/TagNames.cs @@ -27,5 +27,11 @@ internal static class TagNames { internal const string BotName = "bot"; internal const string BotState = "state"; internal const string CurrencyCode = "currency"; + internal const string Framework = "framework"; + internal const string ModuleVersion = "module_version"; + internal const string OS = "operating_system"; + internal const string Runtime = "runtime"; internal const string SteamID = "steamid"; + internal const string Variant = "variant"; + internal const string Version = "version"; } diff --git a/ArchiSteamFarm/SharedInfo.cs b/ArchiSteamFarm/SharedInfo.cs index 1bb235540ae01..9fe556a9ef2cf 100644 --- a/ArchiSteamFarm/SharedInfo.cs +++ b/ArchiSteamFarm/SharedInfo.cs @@ -101,7 +101,7 @@ internal static string HomeDirectory { internal static string PublicIdentifier => $"{AssemblyName}{(BuildInfo.IsCustomBuild ? "-custom" : PluginsCore.HasCustomPluginsLoaded ? "-modded" : "")}"; internal static Version Version => Assembly.GetExecutingAssembly().GetName().Version ?? throw new InvalidOperationException(nameof(Version)); - private static Guid ModuleVersion => Assembly.GetExecutingAssembly().ManifestModule.ModuleVersionId; + internal static Guid ModuleVersion => Assembly.GetExecutingAssembly().ManifestModule.ModuleVersionId; private static string? CachedHomeDirectory; From e9052d7100936153a8fef5d1627ae3e23df37000 Mon Sep 17 00:00:00 2001 From: Abrynos <6608231+Abrynos@users.noreply.github.com> Date: Sat, 6 Apr 2024 16:02:15 +0200 Subject: [PATCH 6/9] Remove module version from metrics as it does not work --- ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs | 3 +-- ArchiSteamFarm.OfficialPlugins.Monitoring/TagNames.cs | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs index fd29ed8c360e6..4f5b56dd5b98f 100644 --- a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs @@ -55,8 +55,7 @@ internal sealed class MonitoringPlugin : OfficialPlugin, IWebServiceProvider, IG new( 1, new KeyValuePair(TagNames.Version, SharedInfo.Version.ToString()), - new KeyValuePair(TagNames.Variant, SharedInfo.BuildInfo.Variant), - new KeyValuePair(TagNames.ModuleVersion, SharedInfo.ModuleVersion.ToString()) + new KeyValuePair(TagNames.Variant, SharedInfo.BuildInfo.Variant) ); private static readonly Measurement RuntimeInfo = CreateRuntimeInformation(); diff --git a/ArchiSteamFarm.OfficialPlugins.Monitoring/TagNames.cs b/ArchiSteamFarm.OfficialPlugins.Monitoring/TagNames.cs index e97a7e395dae8..8945c3ea5f844 100644 --- a/ArchiSteamFarm.OfficialPlugins.Monitoring/TagNames.cs +++ b/ArchiSteamFarm.OfficialPlugins.Monitoring/TagNames.cs @@ -28,7 +28,6 @@ internal static class TagNames { internal const string BotState = "state"; internal const string CurrencyCode = "currency"; internal const string Framework = "framework"; - internal const string ModuleVersion = "module_version"; internal const string OS = "operating_system"; internal const string Runtime = "runtime"; internal const string SteamID = "steamid"; From f8beb1691bd8e1c4e87f14b4ed40cbb814fb25cc Mon Sep 17 00:00:00 2001 From: Abrynos <6608231+Abrynos@users.noreply.github.com> Date: Sun, 7 Apr 2024 18:15:58 +0200 Subject: [PATCH 7/9] Apply feedback --- .../MonitoringPlugin.cs | 48 +++++-------------- ArchiSteamFarm/Core/OS.cs | 48 +++++++++++-------- 2 files changed, 42 insertions(+), 54 deletions(-) diff --git a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs index 4f5b56dd5b98f..9d8c668954b4f 100644 --- a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs @@ -28,7 +28,6 @@ using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Metrics; using System.Linq; -using System.Runtime.InteropServices; using System.Text.Json.Serialization; using System.Threading.Tasks; using ArchiSteamFarm.Core; @@ -51,14 +50,20 @@ internal sealed class MonitoringPlugin : OfficialPlugin, IWebServiceProvider, IG private const string MetricNamePrefix = "asf"; - private static readonly Measurement BuildInfo = - new( - 1, - new KeyValuePair(TagNames.Version, SharedInfo.Version.ToString()), - new KeyValuePair(TagNames.Variant, SharedInfo.BuildInfo.Variant) - ); + private const string UnknownLabelValueFallback = "unknown"; + + private static readonly Measurement BuildInfo = new( + 1, + new KeyValuePair(TagNames.Version, SharedInfo.Version.ToString()), + new KeyValuePair(TagNames.Variant, SharedInfo.BuildInfo.Variant) + ); - private static readonly Measurement RuntimeInfo = CreateRuntimeInformation(); + private static readonly Measurement RuntimeInfo = new( + 1, + new KeyValuePair(TagNames.Framework, OS.Framework ?? UnknownLabelValueFallback), + new KeyValuePair(TagNames.Runtime, OS.Runtime ?? UnknownLabelValueFallback), + new KeyValuePair(TagNames.OS, OS.Description ?? UnknownLabelValueFallback) + ); private static bool Enabled => ASF.GlobalConfig?.IPC ?? GlobalConfig.DefaultIPC; @@ -108,33 +113,6 @@ public void OnConfiguringServices(IServiceCollection services) { public override Task OnLoaded() => Task.CompletedTask; - private static Measurement CreateRuntimeInformation() { - string framework = RuntimeInformation.FrameworkDescription.Trim(); - - if (framework.Length == 0) { - framework = "unknown"; - } - - string runtime = RuntimeInformation.RuntimeIdentifier.Trim(); - - if (runtime.Length == 0) { - runtime = "unknown"; - } - - string description = RuntimeInformation.OSDescription.Trim(); - - if (description.Length == 0) { - description = "unknown"; - } - - return new Measurement( - 1, - new KeyValuePair(TagNames.Framework, framework), - new KeyValuePair(TagNames.Runtime, runtime), - new KeyValuePair(TagNames.OS, description) - ); - } - [MemberNotNull(nameof(Meter))] private void InitializeMeter() { if (Meter != null) { diff --git a/ArchiSteamFarm/Core/OS.cs b/ArchiSteamFarm/Core/OS.cs index 38c61ef4639e8..45e9859a1b505 100644 --- a/ArchiSteamFarm/Core/OS.cs +++ b/ArchiSteamFarm/Core/OS.cs @@ -37,10 +37,38 @@ using ArchiSteamFarm.Localization; using ArchiSteamFarm.Storage; using ArchiSteamFarm.Web; +using JetBrains.Annotations; namespace ArchiSteamFarm.Core; internal static class OS { + [PublicAPI] + public static string? Description { + get { + string description = RuntimeInformation.OSDescription.Trim(); + + return description.Length == 0 ? null : description; + } + } + + [PublicAPI] + public static string? Framework { + get { + string framework = RuntimeInformation.FrameworkDescription.Trim(); + + return framework.Length == 0 ? null : framework; + } + } + + [PublicAPI] + public static string? Runtime { + get { + string runtime = RuntimeInformation.RuntimeIdentifier.Trim(); + + return runtime.Length == 0 ? null : runtime; + } + } + // We need to keep this one assigned and not calculated on-demand internal static readonly string ProcessFileName = Environment.ProcessPath ?? throw new InvalidOperationException(nameof(ProcessFileName)); @@ -58,25 +86,7 @@ internal static string Version { return BackingVersion; } - string framework = RuntimeInformation.FrameworkDescription.Trim(); - - if (framework.Length == 0) { - framework = "Unknown Framework"; - } - - string runtime = RuntimeInformation.RuntimeIdentifier.Trim(); - - if (runtime.Length == 0) { - runtime = "Unknown Runtime"; - } - - string description = RuntimeInformation.OSDescription.Trim(); - - if (description.Length == 0) { - description = "Unknown OS"; - } - - BackingVersion = $"{framework}; {runtime}; {description}"; + BackingVersion = $"{Framework ?? "Unknown Framework"}; {Runtime ?? "Unknown Runtime"}; {Description ?? "Unknown OS"}"; return BackingVersion; } From 99612596bef272eeb641d40751c39d96c65e0c11 Mon Sep 17 00:00:00 2001 From: Abrynos <6608231+Abrynos@users.noreply.github.com> Date: Sun, 7 Apr 2024 18:21:21 +0200 Subject: [PATCH 8/9] Deduplicate code --- ArchiSteamFarm/Core/OS.cs | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/ArchiSteamFarm/Core/OS.cs b/ArchiSteamFarm/Core/OS.cs index 45e9859a1b505..89758026026c2 100644 --- a/ArchiSteamFarm/Core/OS.cs +++ b/ArchiSteamFarm/Core/OS.cs @@ -43,31 +43,13 @@ namespace ArchiSteamFarm.Core; internal static class OS { [PublicAPI] - public static string? Description { - get { - string description = RuntimeInformation.OSDescription.Trim(); - - return description.Length == 0 ? null : description; - } - } + public static string? Description => TrimAndNullifyEmptyString(RuntimeInformation.OSDescription); [PublicAPI] - public static string? Framework { - get { - string framework = RuntimeInformation.FrameworkDescription.Trim(); - - return framework.Length == 0 ? null : framework; - } - } + public static string? Framework => TrimAndNullifyEmptyString(RuntimeInformation.FrameworkDescription); [PublicAPI] - public static string? Runtime { - get { - string runtime = RuntimeInformation.RuntimeIdentifier.Trim(); - - return runtime.Length == 0 ? null : runtime; - } - } + public static string? Runtime => TrimAndNullifyEmptyString(RuntimeInformation.RuntimeIdentifier); // We need to keep this one assigned and not calculated on-demand internal static readonly string ProcessFileName = Environment.ProcessPath ?? throw new InvalidOperationException(nameof(ProcessFileName)); @@ -306,6 +288,14 @@ private static void MinimizeConsoleWindow() { } } + private static string? TrimAndNullifyEmptyString(string s) { + ArgumentNullException.ThrowIfNull(s); + + s = s.Trim(); + + return s.Length == 0 ? null : s; + } + [SupportedOSPlatform("Windows")] private static void WindowsDisableQuickEditMode() { if (!OperatingSystem.IsWindows()) { From 22d9b12061f4da54cb46b8ac1a024d0e6ab0ed76 Mon Sep 17 00:00:00 2001 From: Abrynos <6608231+Abrynos@users.noreply.github.com> Date: Sun, 7 Apr 2024 18:35:49 +0200 Subject: [PATCH 9/9] Reference related issue in upstream repo --- .github/renovate.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 5a452b72ed5eb..043373b802aec 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -15,7 +15,7 @@ }, "packageRules": [ { - // TODO: <= 1.7.0-rc.1 for invalid response on monitoring endpoint, last failed version 1.8.0-rc.1 + // TODO: <= 1.7.0-rc.1 for invalid response on monitoring endpoint, last failed version 1.8.0-rc.1 - https://github.com/open-telemetry/opentelemetry-dotnet/issues/5506 "allowedVersions": "<= 1.7.0-rc.1", "matchManagers": [ "nuget" ], "matchPackageNames": [ "OpenTelemetry.Exporter.Prometheus.AspNetCore" ]