diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs b/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs index c19389e0..27e3da7a 100644 --- a/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs +++ b/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs @@ -37,6 +37,7 @@ public partial class Operations ) { using var receiveActivity = activityFactory.Start("Operations.Receive"); + metricsFactory.CreateCounter("Receive").Add(1); if (remoteTransport != null) { diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Send.cs b/src/Speckle.Sdk/Api/Operations/Operations.Send.cs index 39c16ee3..902625a3 100644 --- a/src/Speckle.Sdk/Api/Operations/Operations.Send.cs +++ b/src/Speckle.Sdk/Api/Operations/Operations.Send.cs @@ -78,6 +78,7 @@ public partial class Operations } // make sure all logs in the operation have the proper context + metricsFactory.CreateCounter("Send").Add(1); using var activity = activityFactory.Start(); activity?.SetTag("correlationId", Guid.NewGuid().ToString()); { diff --git a/src/Speckle.Sdk/Api/Operations/Operations.cs b/src/Speckle.Sdk/Api/Operations/Operations.cs index 62aec02c..dd050250 100644 --- a/src/Speckle.Sdk/Api/Operations/Operations.cs +++ b/src/Speckle.Sdk/Api/Operations/Operations.cs @@ -10,4 +10,8 @@ namespace Speckle.Sdk.Api; /// Push/Pull (methods to serialize and send data to one or more servers) /// [GenerateAutoInterface] -public partial class Operations(ILogger logger, ISdkActivityFactory activityFactory) : IOperations; +public partial class Operations( + ILogger logger, + ISdkActivityFactory activityFactory, + ISdkMetricsFactory metricsFactory +) : IOperations; diff --git a/src/Speckle.Sdk/Logging/ISdkActivityFactory.cs b/src/Speckle.Sdk/Logging/ISdkActivityFactory.cs index 04db90bb..6db37c9a 100644 --- a/src/Speckle.Sdk/Logging/ISdkActivityFactory.cs +++ b/src/Speckle.Sdk/Logging/ISdkActivityFactory.cs @@ -6,10 +6,3 @@ public interface ISdkActivityFactory : IDisposable { ISdkActivity? Start(string? name = default, [CallerMemberName] string source = ""); } - -public sealed class NullActivityFactory : ISdkActivityFactory -{ - public void Dispose() { } - - public ISdkActivity? Start(string? name = default, string source = "") => null; -} diff --git a/src/Speckle.Sdk/Logging/ISdkCounter.cs b/src/Speckle.Sdk/Logging/ISdkCounter.cs new file mode 100644 index 00000000..5566e2fa --- /dev/null +++ b/src/Speckle.Sdk/Logging/ISdkCounter.cs @@ -0,0 +1,16 @@ +namespace Speckle.Sdk.Logging; + +public interface ISdkCounter + where T : struct +{ + void Add(T value); + void Add(T value, KeyValuePair tag); + void Add(T value, KeyValuePair tag1, KeyValuePair tag2); + void Add( + T value, + KeyValuePair tag1, + KeyValuePair tag2, + KeyValuePair tag3 + ); + void Add(T value, params KeyValuePair[] tag); +} diff --git a/src/Speckle.Sdk/Logging/ISdkMetricsFactory.cs b/src/Speckle.Sdk/Logging/ISdkMetricsFactory.cs new file mode 100644 index 00000000..ecfcb3f1 --- /dev/null +++ b/src/Speckle.Sdk/Logging/ISdkMetricsFactory.cs @@ -0,0 +1,7 @@ +namespace Speckle.Sdk.Logging; + +public interface ISdkMetricsFactory +{ + ISdkCounter CreateCounter(string name, string? unit = default, string? description = default) + where T : struct; +} diff --git a/src/Speckle.Sdk/Logging/NullActivityFactory.cs b/src/Speckle.Sdk/Logging/NullActivityFactory.cs new file mode 100644 index 00000000..580cc5ef --- /dev/null +++ b/src/Speckle.Sdk/Logging/NullActivityFactory.cs @@ -0,0 +1,8 @@ +namespace Speckle.Sdk.Logging; + +public sealed class NullActivityFactory : ISdkActivityFactory +{ + public void Dispose() { } + + public ISdkActivity? Start(string? name = default, string source = "") => null; +} diff --git a/src/Speckle.Sdk/Logging/NullSdkCounter.cs b/src/Speckle.Sdk/Logging/NullSdkCounter.cs new file mode 100644 index 00000000..b1e6a6e0 --- /dev/null +++ b/src/Speckle.Sdk/Logging/NullSdkCounter.cs @@ -0,0 +1,20 @@ +namespace Speckle.Sdk.Logging; + +public sealed class NullSdkCounter : ISdkCounter + where T : struct +{ + public void Add(T value) { } + + public void Add(T value, KeyValuePair tag) { } + + public void Add(T value, KeyValuePair tag1, KeyValuePair tag2) { } + + public void Add( + T value, + KeyValuePair tag1, + KeyValuePair tag2, + KeyValuePair tag3 + ) { } + + public void Add(T value, params KeyValuePair[] tag) { } +} diff --git a/src/Speckle.Sdk/Logging/NullSdkMetricsFactory.cs b/src/Speckle.Sdk/Logging/NullSdkMetricsFactory.cs new file mode 100644 index 00000000..9496d3e6 --- /dev/null +++ b/src/Speckle.Sdk/Logging/NullSdkMetricsFactory.cs @@ -0,0 +1,7 @@ +namespace Speckle.Sdk.Logging; + +public sealed class NullSdkMetricsFactory : ISdkMetricsFactory +{ + public ISdkCounter CreateCounter(string name, string? unit = default, string? description = default) + where T : struct => new NullSdkCounter(); +} diff --git a/src/Speckle.Sdk/ServiceRegistration.cs b/src/Speckle.Sdk/ServiceRegistration.cs index f87acb4a..b2cf164f 100644 --- a/src/Speckle.Sdk/ServiceRegistration.cs +++ b/src/Speckle.Sdk/ServiceRegistration.cs @@ -27,7 +27,8 @@ public static class ServiceRegistration Slug = application.Slug, } ); - serviceCollection.AddSingleton(); + serviceCollection.TryAddSingleton(); + serviceCollection.TryAddSingleton(); serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly()); return serviceCollection; }