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

[Geneva.Metrics] Add option to disable name validation #1006

Merged
Merged
4 changes: 4 additions & 0 deletions src/OpenTelemetry.Exporter.Geneva/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
* Update OpenTelemetry to 1.4.0
([#1038](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/1038))

* Add `DisableMetricNameValidation` connection string flag for controlling
metric name validation performed by the OpenTelemetry SDK.
([#1006](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/1006))

## 1.4.0-rc.4

Released 2023-Feb-13
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,20 @@ public string Namespace
set => this._parts[nameof(this.Namespace)] = value;
}

public bool DisableMetricNameValidation
{
get
{
if (!this._parts.TryGetValue(nameof(this.DisableMetricNameValidation), out var value))
{
return false;
}

return string.Equals(bool.TrueString, value, StringComparison.OrdinalIgnoreCase);
}
set => this._parts[nameof(this.DisableMetricNameValidation)] = value ? bool.TrueString : bool.FalseString;
}

private T ThrowIfNotExists<T>(string name)
{
if (!this._parts.TryGetValue(name, out var value))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using OpenTelemetry.Internal;
using OpenTelemetry.Metrics;

Expand Down Expand Up @@ -108,6 +110,11 @@ public GenevaMetricExporter(GenevaMetricExporterOptions options)
{
this.fixedPayloadStartIndex = sizeof(BinaryHeader);
}

if (connectionStringBuilder.DisableMetricNameValidation)
{
DisableOpenTelemetrySdkMetricNameValidation();
}
}

public override ExportResult Export(in Batch<Metric> batch)
Expand Down Expand Up @@ -258,6 +265,22 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing);
}

internal static PropertyInfo GetOpenTelemetryInstrumentNameRegexProperty()
{
var meterProviderBuilderSdkType = typeof(Sdk).Assembly.GetType("OpenTelemetry.Metrics.MeterProviderBuilderSdk", throwOnError: false)
?? throw new InvalidOperationException("OpenTelemetry.Metrics.MeterProviderBuilderSdk type could not be found reflectively.");

var instrumentNameRegexProperty = meterProviderBuilderSdkType.GetProperty("InstrumentNameRegex", BindingFlags.Public | BindingFlags.Static)
?? throw new InvalidOperationException("OpenTelemetry.Metrics.MeterProviderBuilderSdk.InstrumentNameRegex property could not be found reflectively.");

return instrumentNameRegexProperty;
}

internal static void DisableOpenTelemetrySdkMetricNameValidation()
{
GetOpenTelemetryInstrumentNameRegexProperty().SetValue(null, new Regex(".*", RegexOptions.Compiled));
}

internal unsafe ushort SerializeMetric(
MetricEventType eventType,
string metricName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,62 @@ public void SuccessfulExportOnLinux()
}
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void DisableMetricNameValidationTest(bool disableMetricNameValidation)
{
var instrumentNameRegexProperty = GenevaMetricExporter.GetOpenTelemetryInstrumentNameRegexProperty();
var initialInstrumentNameRegexValue = instrumentNameRegexProperty.GetValue(null);
Socket server = null;
try
{
var exportedMetrics = new List<Metric>();

using var meter = new Meter(Guid.NewGuid().ToString());

using (var provider = Sdk.CreateMeterProviderBuilder()
.AddMeter(meter.Name)
.AddGenevaMetricExporter(options =>
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
options.ConnectionString = $"Account=OTelMonitoringAccount;Namespace=OTelMetricNamespace;DisableMetricNameValidation={disableMetricNameValidation}";
}
else
{
var path = GenerateTempFilePath();
options.ConnectionString = $"Endpoint=unix:{path};Account=OTelMonitoringAccount;Namespace=OTelMetricNamespace;DisableMetricNameValidation={disableMetricNameValidation}";

var endpoint = new UnixDomainSocketEndPoint(path);
server = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP);
server.Bind(endpoint);
server.Listen(1);
}
})
.AddInMemoryExporter(exportedMetrics)
.Build())
{
var counter = meter.CreateCounter<int>("count/invalid");
counter.Add(1);
}

if (disableMetricNameValidation)
{
Assert.Single(exportedMetrics);
}
else
{
Assert.Empty(exportedMetrics);
}
}
finally
{
instrumentNameRegexProperty.SetValue(null, initialInstrumentNameRegexValue);
server?.Dispose();
}
}

private static string GenerateTempFilePath()
{
while (true)
Expand Down