feat: metrics test.

This commit is contained in:
redglow
2026-07-29 11:40:39 +02:00
parent 5c4519ed26
commit d268fff7b4
5 changed files with 64 additions and 2 deletions
+7 -1
View File
@@ -1,10 +1,12 @@
using Godot; using Godot;
using GodotHostTest.AetherBind; using GodotHostTest.AetherBind;
using GodotHostTest.Game.Level; using GodotHostTest.Game.Level;
using GodotHostTest.Game.Metrics;
using GodotHostTest.Game.Score; using GodotHostTest.Game.Score;
using GodotHostTest.Game.Target; using GodotHostTest.Game.Target;
using GodotHostTest.Interfaces; using GodotHostTest.Interfaces;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using OwofGames.GodotHost;
using OwofGames.GodotHost.Observability; using OwofGames.GodotHost.Observability;
using OwofGames.GodotLume; using OwofGames.GodotLume;
@@ -23,12 +25,16 @@ public partial class GameServiceSource : RootServiceSource
// current level / level data management // current level / level data management
.AddInstance<ILevelDataProvider, LevelsData>(_levelsData) .AddInstance<ILevelDataProvider, LevelsData>(_levelsData)
.AddSingleton<ICurrentLevel, CurrentLevel>() .AddSingleton<ICurrentLevel, CurrentLevel>()
// metrics
.AddSingleton<IHostLifetime, MetricsHandler>()
// level scope services // level scope services
.AddLevelServices(); .AddLevelServices();
} }
protected override void ConfigureServices(IServiceCollection serviceCollection) protected override void ConfigureServices(IServiceCollection serviceCollection)
{ {
serviceCollection.AddObservability(builder => builder.AddGrpcExporter("http://localhost:4317")); serviceCollection.AddObservability(builder => builder
.AddGrpcExporter("http://localhost:4317")
.AddMeterName(MetricsHandler.MeterName));
} }
} }
+50
View File
@@ -0,0 +1,50 @@
using System;
using System.Diagnostics.Metrics;
using System.Reflection;
using GodotHostTest.Interfaces;
using OwofGames.GodotHost;
using R3;
namespace GodotHostTest.Game.Metrics;
public class MetricsHandler(IMeterFactory meterFactory, ITargetEventBus targetEventBus) : IHostLifetime
{
public static readonly string MeterName;
private static readonly string? MeterVersion;
private IDisposable? _disposables;
static MetricsHandler()
{
var assemblyName = Assembly.GetExecutingAssembly().GetName();
MeterName = assemblyName.Name!;
MeterVersion = assemblyName.Version?.ToString();
}
public void Startup()
{
// create meter
var assemblyName = Assembly.GetExecutingAssembly().GetName();
var meterName = assemblyName.Name!;
var meterVersion = assemblyName.Version?.ToString();
var meter = meterFactory.Create(meterName, meterVersion);
// create instruments
var hitTargetsCounter =
meter.CreateCounter<int>("targets.hit", description: "number of targets hit");
var missedTargetsCounter =
meter.CreateCounter<int>("targets.missed", description: "number of targets missed");
// feed instruments data, and contextually create the disposable to clean up at shutdown time
_disposables = Disposable.Combine(
targetEventBus.Hit.Subscribe(_ => hitTargetsCounter.Add(1)),
targetEventBus.TimedOut.Subscribe(_ => missedTargetsCounter.Add(1)),
meter
);
}
public void Shutdown()
{
_disposables?.Dispose();
meterFactory.Create("godot-host-test")?.Dispose();
}
}
+1
View File
@@ -0,0 +1 @@
uid://5ramu7es1104
+3
View File
@@ -17,6 +17,9 @@
<Reference Include="OwofGames.GodotHost"> <Reference Include="OwofGames.GodotHost">
<HintPath>..\OwofGames.Godot\OwofGames.GodotHost\bin\Debug\net8.0\OwofGames.GodotHost.dll</HintPath> <HintPath>..\OwofGames.Godot\OwofGames.GodotHost\bin\Debug\net8.0\OwofGames.GodotHost.dll</HintPath>
</Reference> </Reference>
<Reference Include="OwofGames.GodotHost.Abstractions">
<HintPath>..\OwofGames.Godot\OwofGames.GodotHost.Abstractions\bin\Debug\net8.0\OwofGames.GodotHost.Abstractions.dll</HintPath>
</Reference>
<Reference Include="OwofGames.GodotHost.Observability"> <Reference Include="OwofGames.GodotHost.Observability">
<HintPath>..\OwofGames.Godot\OwofGames.GodotHost.Observability\bin\Debug\net8.0\OwofGames.GodotHost.Observability.dll</HintPath> <HintPath>..\OwofGames.Godot\OwofGames.GodotHost.Observability\bin\Debug\net8.0\OwofGames.GodotHost.Observability.dll</HintPath>
</Reference> </Reference>
+3 -1
View File
@@ -2,6 +2,7 @@
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EAetherBind_002EObservability_002Fbin_002FDebug_002Fnet8_002E0_002FOwofGames_002EAetherBind_002EObservability_002Edll/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EAetherBind_002EObservability_002Fbin_002FDebug_002Fnet8_002E0_002FOwofGames_002EAetherBind_002EObservability_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EAetherBind_002ESourceGenerators_002Fbin_002FDebug_002Fnetstandard2_002E0_002FOwofGames_002EAetherBind_002ESourceGenerators_002Edll/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EAetherBind_002ESourceGenerators_002Fbin_002FDebug_002Fnetstandard2_002E0_002FOwofGames_002EAetherBind_002ESourceGenerators_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EAetherBind_002Fbin_002FDebug_002Fnet8_002E0_002FOwofGames_002EAetherBind_002Edll/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EAetherBind_002Fbin_002FDebug_002Fnet8_002E0_002FOwofGames_002EAetherBind_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EGodotHost_002EAbstractions_002Fbin_002FDebug_002Fnet8_002E0_002FOwofGames_002EGodotHost_002EAbstractions_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EGodotHost_002EObservability_002Fbin_002FDebug_002Fnet8_002E0_002FOwofGames_002EGodotHost_002EObservability_002Edll/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EGodotHost_002EObservability_002Fbin_002FDebug_002Fnet8_002E0_002FOwofGames_002EGodotHost_002EObservability_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EGodotHost_002Fbin_002FDebug_002Fnet8_002E0_002FOwofGames_002EGodotHost_002Edll/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EGodotHost_002Fbin_002FDebug_002Fnet8_002E0_002FOwofGames_002EGodotHost_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EGodotHost_002Fbin_002FDebug_002Fnet8_002E0_002FOwofGames_002EGodotLogger_002Edll/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/AddReferences/RecentPaths/=_002Fhome_002Fredglow_002Fsources_002FOwofGames_002EGodot_002FOwofGames_002EGodotHost_002Fbin_002FDebug_002Fnet8_002E0_002FOwofGames_002EGodotLogger_002Edll/@EntryIndexedValue">True</s:Boolean>
@@ -20,6 +21,7 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALoggerExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003F5328b8781cd9aafb0c784622d271e874977e837c6d30222a754bc2e6ac02f_003FLoggerExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALoggerExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003F5328b8781cd9aafb0c784622d271e874977e837c6d30222a754bc2e6ac02f_003FLoggerExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALoggerInformation_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003F58a2e8187d354ab2e42d1cca1ce63b1edb0381e3ac126b055eb2481382014_003FLoggerInformation_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALoggerInformation_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003F58a2e8187d354ab2e42d1cca1ce63b1edb0381e3ac126b055eb2481382014_003FLoggerInformation_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALogger_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003F342e7081b95d68bdbbd320f210c35f9376e2b2b914a05d1cfef054c46bee58_003FLogger_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALogger_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003F342e7081b95d68bdbbd320f210c35f9376e2b2b914a05d1cfef054c46bee58_003FLogger_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMeter_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ffe1d9b60c4be4b2dad7000c1d31f96862ef10_003F62_003F109f0e8c_003FMeter_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMethodBaseInvoker_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6cc9b871557b441baa469ce23b255f41dbb200_003F7b_003Fb6307b47_003FMethodBaseInvoker_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMethodBaseInvoker_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6cc9b871557b441baa469ce23b255f41dbb200_003F7b_003Fb6307b47_003FMethodBaseInvoker_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fcd2081581a57397285b1beba7fc14bdbc61c89e3ac09a962676d880d9dd3c_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fcd2081581a57397285b1beba7fc14bdbc61c89e3ac09a962676d880d9dd3c_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AOtlpHttpExportClient_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003F4033dea463e391648d47bc0d947734cc9785594d32f2e63e7fdaa66dc6f69_003FOtlpHttpExportClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AOtlpHttpExportClient_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003F4033dea463e391648d47bc0d947734cc9785594d32f2e63e7fdaa66dc6f69_003FOtlpHttpExportClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
@@ -32,7 +34,7 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F71c28e8d0d254cb69b7b78690e099f6183800_003F72_003F2da75270_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F71c28e8d0d254cb69b7b78690e099f6183800_003F72_003F2da75270_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATracerProviderSdk_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fcaafa02e3d88c337ab20dce7c21f1db259cd1cae52395b6888f68313fd50e6_003FTracerProviderSdk_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATracerProviderSdk_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fcaafa02e3d88c337ab20dce7c21f1db259cd1cae52395b6888f68313fd50e6_003FTracerProviderSdk_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/Environment/AssemblyExplorer/XmlDocument/@EntryValue">&lt;AssemblyExplorer&gt; <s:String x:Key="/Default/Environment/AssemblyExplorer/XmlDocument/@EntryValue">&lt;AssemblyExplorer&gt;
&lt;Assembly Path="/home/redglow/sources/OwofGames.Godot/OwofGames.AetherBind.Observability/bin/Debug/net8.0/OwofGames.AetherBind.Observability.dll" /&gt; &lt;Assembly Path="/home/redglow/sources/OwofGames.Godot/OwofGames.GodotHost/bin/Debug/net8.0/OwofGames.GodotHost.dll" /&gt;
&lt;/AssemblyExplorer&gt;</s:String> &lt;/AssemblyExplorer&gt;</s:String>
<s:String x:Key="/Default/Environment/Hierarchy/Build/BuildTool/DotNetCliExePath/@EntryValue">/usr/lib/dotnet/dotnet</s:String> <s:String x:Key="/Default/Environment/Hierarchy/Build/BuildTool/DotNetCliExePath/@EntryValue">/usr/lib/dotnet/dotnet</s:String>
<s:String x:Key="/Default/Environment/Hierarchy/Build/BuildTool/CustomBuildToolPath/@EntryValue">/usr/lib/dotnet/sdk/10.0.109/MSBuild.dll</s:String> <s:String x:Key="/Default/Environment/Hierarchy/Build/BuildTool/CustomBuildToolPath/@EntryValue">/usr/lib/dotnet/sdk/10.0.109/MSBuild.dll</s:String>