mirror of
https://github.com/JustArchiNET/ArchiSteamFarm
synced 2024-11-10 07:04:27 +00:00
Fix monitoring integration with actual prometheus (#3183)
* Downgrade OpenTelemetry.Exporter.Prometheus.AspNetCore due to issues with latest version * Add unit to asf_bot_farming_minutes_remaining * Upgrade some packages released last night (already tested to work) * Don't forget about unit suffix * 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 * Remove module version from metrics as it does not work * Apply feedback * Deduplicate code * Reference related issue in upstream repo
This commit is contained in:
parent
8e055fe587
commit
9016a5109d
7 changed files with 94 additions and 24 deletions
10
.github/renovate.json5
vendored
10
.github/renovate.json5
vendored
|
@ -12,5 +12,13 @@
|
|||
],
|
||||
"git-submodules": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"packageRules": [
|
||||
{
|
||||
// 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" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -50,6 +50,21 @@ internal sealed class MonitoringPlugin : OfficialPlugin, IWebServiceProvider, IG
|
|||
|
||||
private const string MetricNamePrefix = "asf";
|
||||
|
||||
private const string UnknownLabelValueFallback = "unknown";
|
||||
|
||||
private static readonly Measurement<int> BuildInfo = new(
|
||||
1,
|
||||
new KeyValuePair<string, object?>(TagNames.Version, SharedInfo.Version.ToString()),
|
||||
new KeyValuePair<string, object?>(TagNames.Variant, SharedInfo.BuildInfo.Variant)
|
||||
);
|
||||
|
||||
private static readonly Measurement<int> RuntimeInfo = new(
|
||||
1,
|
||||
new KeyValuePair<string, object?>(TagNames.Framework, OS.Framework ?? UnknownLabelValueFallback),
|
||||
new KeyValuePair<string, object?>(TagNames.Runtime, OS.Runtime ?? UnknownLabelValueFallback),
|
||||
new KeyValuePair<string, object?>(TagNames.OS, OS.Description ?? UnknownLabelValueFallback)
|
||||
);
|
||||
|
||||
private static bool Enabled => ASF.GlobalConfig?.IPC ?? GlobalConfig.DefaultIPC;
|
||||
|
||||
[JsonInclude]
|
||||
|
@ -106,6 +121,18 @@ internal sealed class MonitoringPlugin : OfficialPlugin, IWebServiceProvider, IG
|
|||
|
||||
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(),
|
||||
|
@ -150,13 +177,15 @@ internal sealed class MonitoringPlugin : OfficialPlugin, IWebServiceProvider, IG
|
|||
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<Bot> bots = Bot.Bots?.Values ?? Array.Empty<Bot>();
|
||||
|
||||
return bots.Select(static bot => new Measurement<double>(bot.CardsFarmer.TimeRemaining.TotalMinutes, new KeyValuePair<string, object?>(TagNames.BotName, bot.BotName), new KeyValuePair<string, object?>(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(
|
||||
|
|
|
@ -27,5 +27,10 @@ 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 OS = "operating_system";
|
||||
internal const string Runtime = "runtime";
|
||||
internal const string SteamID = "steamid";
|
||||
internal const string Variant = "variant";
|
||||
internal const string Version = "version";
|
||||
}
|
||||
|
|
28
ArchiSteamFarm.OfficialPlugins.Monitoring/Units.cs
Normal file
28
ArchiSteamFarm.OfficialPlugins.Monitoring/Units.cs
Normal file
|
@ -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";
|
||||
}
|
|
@ -37,10 +37,20 @@ using System.Threading.Tasks;
|
|||
using ArchiSteamFarm.Localization;
|
||||
using ArchiSteamFarm.Storage;
|
||||
using ArchiSteamFarm.Web;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace ArchiSteamFarm.Core;
|
||||
|
||||
internal static class OS {
|
||||
[PublicAPI]
|
||||
public static string? Description => TrimAndNullifyEmptyString(RuntimeInformation.OSDescription);
|
||||
|
||||
[PublicAPI]
|
||||
public static string? Framework => TrimAndNullifyEmptyString(RuntimeInformation.FrameworkDescription);
|
||||
|
||||
[PublicAPI]
|
||||
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));
|
||||
|
||||
|
@ -58,25 +68,7 @@ internal static class OS {
|
|||
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;
|
||||
}
|
||||
|
@ -296,6 +288,14 @@ internal static class OS {
|
|||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
|
|
|
@ -102,7 +102,7 @@ public static class SharedInfo {
|
|||
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;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<PackageVersion Include="MSTest" Version="3.3.1" />
|
||||
<PackageVersion Include="Nito.AsyncEx.Coordination" Version="5.1.2" />
|
||||
<PackageVersion Include="NLog.Web.AspNetCore" Version="5.3.8" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.8.0-rc.1" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.7.0-rc.1" />
|
||||
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.8.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.8.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.8.0" />
|
||||
|
|
Loading…
Reference in a new issue