Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce Emulated PLC metrics #374

Closed
wants to merge 11 commits into from
19 changes: 6 additions & 13 deletions src/Helpers/Metrics.cs → src/Helpers/MetricsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace OpcPlc;
using System.Diagnostics.Metrics;
using System.Linq;

public static class MetricsConfig
public static class MetricsHelper
{
/// <summary>
/// The name of the service.
Expand All @@ -21,7 +21,6 @@ public static class MetricsConfig
private const string OPC_PLC_SESSION_COUNT_METRIC = "opc_plc_session_count";
private const string OPC_PLC_SUBSCRIPTION_COUNT_METRIC = "opc_plc_subscription_count";
private const string OPC_PLC_MONITORED_ITEM_COUNT_METRIC = "opc_plc_monitored_item_count";
private const string OPC_PLC_PUBLISHED_COUNT_METRIC = "opc_plc_published_count";
private const string OPC_PLC_PUBLISHED_COUNT_WITH_TYPE_METRIC = "opc_plc_published_count_with_type";
private const string OPC_PLC_TOTAL_ERRORS_METRIC = "opc_plc_total_errors";

Expand Down Expand Up @@ -103,7 +102,6 @@ private static string CLUSTER_NAME
private static readonly UpDownCounter<int> SessionCount = Meter.CreateUpDownCounter<int>(OPC_PLC_SESSION_COUNT_METRIC);
private static readonly UpDownCounter<int> SubscriptionCount = Meter.CreateUpDownCounter<int>(OPC_PLC_SUBSCRIPTION_COUNT_METRIC);
private static readonly UpDownCounter<int> MonitoredItemCount = Meter.CreateUpDownCounter<int>(OPC_PLC_MONITORED_ITEM_COUNT_METRIC);
private static readonly Counter<int> PublishedCount = Meter.CreateCounter<int>(OPC_PLC_PUBLISHED_COUNT_METRIC);
private static readonly Counter<int> PublishedCountWithType = Meter.CreateCounter<int>(OPC_PLC_PUBLISHED_COUNT_WITH_TYPE_METRIC);
private static readonly Counter<int> TotalErrors = Meter.CreateCounter<int>(OPC_PLC_TOTAL_ERRORS_METRIC);

Expand Down Expand Up @@ -135,11 +133,10 @@ public static void AddSubscriptionCount(string sessionId, string subscriptionId,
/// <summary>
/// Add a monitored item count.
/// </summary>
public static void AddMonitoredItemCount(string sessionId, string subscriptionId, int delta = 1)
public static void AddMonitoredItemCount(string sessionId, int delta = 1)
{
var dimensions = MergeWithBaseDimensions(
new KeyValuePair<string, object>("session", sessionId),
new KeyValuePair<string, object>("subscription", subscriptionId));
new KeyValuePair<string, object>("session", sessionId));
bhnaphade marked this conversation as resolved.
Show resolved Hide resolved
MonitoredItemCount.Add(delta, dimensions);
}

Expand All @@ -148,14 +145,11 @@ public static void AddMonitoredItemCount(string sessionId, string subscriptionId
/// </summary>
public static void AddPublishedCount(string sessionId, string subscriptionId, int dataPoints, int events)
{
var dimensions = ConvertDictionaryToKeyVaultPairArray(BaseDimensions);
PublishedCount.Add(1, dimensions);

if (dataPoints > 0)
{
var dataPointsDimensions = MergeWithBaseDimensions(
new KeyValuePair<string, object>("type", "data_point"));
PublishedCountWithType.Add(dataPoints, dataPointsDimensions);;
PublishedCountWithType.Add(dataPoints, dataPointsDimensions);
}

if (events > 0)
Expand All @@ -169,11 +163,10 @@ public static void AddPublishedCount(string sessionId, string subscriptionId, in
/// <summary>
/// Record total errors.
/// </summary>
public static void RecordTotalErrors(string operation, string errorType, int delta = 1)
public static void RecordTotalErrors(string operation, int delta = 1)
{
var dimensions = MergeWithBaseDimensions(
new KeyValuePair<string, object>("operation", operation),
new KeyValuePair<string, object>("error_type", errorType));
new KeyValuePair<string, object>("operation", operation));
TotalErrors.Add(delta, dimensions);
}

Expand Down
4 changes: 2 additions & 2 deletions src/Helpers/OtelHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public static void ConfigureOpenTelemetry(string serviceName, string exportEndpo

_ = Sdk.CreateMeterProviderBuilder()
.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService(MetricsConfig.ServiceName).AddTelemetrySdk())
.AddMeter(MetricsConfig.Meter.Name)
.AddService(MetricsHelper.ServiceName).AddTelemetrySdk())
.AddMeter(MetricsHelper.Meter.Name)
.AddRuntimeInstrumentation()
.AddOtlpExporter((exporterOptions, metricsReaderOptions) => {
exporterOptions.Endpoint = new Uri(exportEndpointUri);
Expand Down
16 changes: 8 additions & 8 deletions src/PlcServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace OpcPlc;
using System.IO;
using System.Reflection;
using System.Threading;
using Meters = OpcPlc.MetricsConfig;
using Meters = OpcPlc.MetricsHelper;

public partial class PlcServer : StandardServer
{
Expand Down Expand Up @@ -79,7 +79,7 @@ public override ResponseHeader CreateSession(
}
catch (Exception ex)
{
Meters.RecordTotalErrors(nameof(CreateSession), ex.GetType().ToString());
Meters.RecordTotalErrors(nameof(CreateSession));
_logger.LogError(ex, "Error creating session");
throw;
}
Expand Down Expand Up @@ -116,7 +116,7 @@ public override ResponseHeader CreateSubscription(
}
catch (Exception ex)
{
Meters.RecordTotalErrors(nameof(CreateSubscription), ex.GetType().ToString());
Meters.RecordTotalErrors(nameof(CreateSubscription));
_logger.LogError(ex, "Error creating subscription");
throw;
}
Expand All @@ -136,7 +136,7 @@ public override ResponseHeader CreateMonitoredItems(

var responseHeader = base.CreateMonitoredItems(requestHeader, subscriptionId, timestampsToReturn, itemsToCreate, out results, out diagnosticInfos);

Meters.AddMonitoredItemCount(context.SessionId.ToString(), subscriptionId.ToString(), itemsToCreate.Count);
Meters.AddMonitoredItemCount(context.SessionId.ToString(), itemsToCreate.Count);

_logger.LogDebug("{function} completed successfully with sessionId: {sessionId}, subscriptionId: {subscriptionId} and count: {count}",
nameof(CreateMonitoredItems),
Expand All @@ -148,7 +148,7 @@ public override ResponseHeader CreateMonitoredItems(
}
catch (Exception ex)
{
Meters.RecordTotalErrors(nameof(CreateMonitoredItems), ex.GetType().ToString());
Meters.RecordTotalErrors(nameof(CreateMonitoredItems));
_logger.LogError(ex, "Error creating monitored items");
throw;
}
Expand Down Expand Up @@ -201,7 +201,7 @@ public override ResponseHeader Publish(
}
catch (Exception ex)
{
Meters.RecordTotalErrors(nameof(Publish), ex.GetType().ToString());
Meters.RecordTotalErrors(nameof(Publish));
_logger.LogError(ex, "Error publishing");
throw;
}
Expand All @@ -225,7 +225,7 @@ public override ResponseHeader Read(
}
catch (Exception ex)
{
Meters.RecordTotalErrors(nameof(Read), ex.GetType().ToString());
Meters.RecordTotalErrors(nameof(Read));
_logger.LogError(ex, "Error reading");
throw;
}
Expand All @@ -243,7 +243,7 @@ public override ResponseHeader Write(RequestHeader requestHeader, WriteValueColl
}
catch (Exception ex)
{
Meters.RecordTotalErrors(nameof(Write), ex.GetType().ToString());
Meters.RecordTotalErrors(nameof(Write));
_logger.LogError(ex, "Error writing");
throw;
}
Expand Down
108 changes: 108 additions & 0 deletions tests/MetricsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
namespace OpcPlc.Tests;

using FluentAssertions;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Meters = OpcPlc.MetricsHelper;

/// <summary>
/// Tests for Metrics.
/// </summary>
internal class MetricsTests
{
private readonly MeterListener _meterListener;
private readonly Dictionary<string, object> _metrics;

public MetricsTests()
{
_metrics = new Dictionary<string, object>();
_meterListener = new MeterListener();
_meterListener.InstrumentPublished = (instrument, listener) => {
if (instrument.Meter.Name == MetricsHelper.Meter.Name)
{
listener.EnableMeasurementEvents(instrument);
}
};

_meterListener.SetMeasurementEventCallback(
(Instrument instrument, long measurement, ReadOnlySpan<KeyValuePair<string, object?>> tags, object? state) => {

Check warning on line 33 in tests/MetricsTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 33 in tests/MetricsTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 33 in tests/MetricsTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 33 in tests/MetricsTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
_metrics.Add(instrument.Name, measurement);
});

_meterListener.SetMeasurementEventCallback(
(Instrument instrument, double measurement, ReadOnlySpan<KeyValuePair<string, object?>> tags, object? state) => {

Check warning on line 38 in tests/MetricsTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 38 in tests/MetricsTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 38 in tests/MetricsTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 38 in tests/MetricsTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
_metrics.Add(instrument.Name, measurement);
});

_meterListener.SetMeasurementEventCallback(
(Instrument instrument, int measurement, ReadOnlySpan<KeyValuePair<string, object?>> tags, object? state) => {

Check warning on line 43 in tests/MetricsTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 43 in tests/MetricsTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
_metrics.Add(instrument.Name, measurement);
});

_meterListener.Start();
}

[SetUp]
public void SetUp()
{
_metrics.Clear();
}

[TearDown]
public void TearDown()
{
_meterListener.Dispose();
}

[Test]
public void TestAddSessionCount()
{
var sessionId = Guid.NewGuid().ToString();
Meters.AddSessionCount(sessionId.ToString());
_metrics.TryGetValue("opc_plc_session_count", out var counter).Should().BeTrue();
counter.Should().Be(1);
}

[Test]
public void TestAddSubscriptionCount()
{
var sessionId = Guid.NewGuid().ToString();
var subscriptionId = Guid.NewGuid().ToString();
Meters.AddSubscriptionCount(sessionId, subscriptionId);
_metrics.TryGetValue("opc_plc_subscription_count", out var counter).Should().BeTrue();
counter.Should().Be(1);
}

[Test]
public void TestAddMonitoredItemCount()
{
var sessionId = Guid.NewGuid().ToString();
Meters.AddMonitoredItemCount(sessionId);
_metrics.TryGetValue("opc_plc_monitored_item_count", out var counter).Should().BeTrue();
counter.Should().Be(1);
}

[Test]
public void TestAddPublishedCount()
{
var sessionId = Guid.NewGuid().ToString();
var subscriptionId = Guid.NewGuid().ToString();
Meters.AddPublishedCount(sessionId, subscriptionId, 1, 0);
_metrics.TryGetValue("opc_plc_published_count_with_type", out var counter).Should().BeTrue();
counter.Should().Be(1);
}

[Test]
public void TestRecordTotalErrors()
{
Meters.RecordTotalErrors("operation");
_metrics.TryGetValue("opc_plc_total_errors", out var counter).Should().BeTrue(); ;
counter.Should().Be(1);
}
}

Loading