Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 42 additions & 5 deletions src/OpenTelemetry/Metrics/MeterProviderSdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using System.Diagnostics;
using System.Diagnostics.Metrics;
using System.Linq;
using System.Text.RegularExpressions;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;

Expand Down Expand Up @@ -87,10 +88,20 @@ internal MeterProviderSdk(
}

// Setup Listener
var meterSourcesToSubscribe = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
foreach (var name in meterSources)
var meterSourcesToSubscribe = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var wildcardMode = false;
Regex regex = null;
if (meterSources.Any())
{
meterSourcesToSubscribe[name] = true;
foreach (var meterSource in meterSources)
{
if (meterSource.Contains('*'))
{
wildcardMode = true;
regex = GetWildcardRegex(meterSources);
break;
}
}
}

this.listener = new MeterListener();
Expand All @@ -99,7 +110,22 @@ internal MeterProviderSdk(
{
this.listener.InstrumentPublished = (instrument, listener) =>
{
if (meterSourcesToSubscribe.ContainsKey(instrument.Meter.Name))
if (wildcardMode)
{
if (ShouldListenTo(instrument.Meter.Name))
{
meterSourcesToSubscribe.Add(instrument.Meter.Name);
}
}
else
{
foreach (var meterSource in meterSources)
{
meterSourcesToSubscribe.Add(meterSource);
}
}

if (meterSourcesToSubscribe.Contains(instrument.Meter.Name))
{
// Creating list with initial capacity as the maximum
// possible size, to avoid any array resize/copy internally.
Expand Down Expand Up @@ -197,7 +223,7 @@ internal MeterProviderSdk(
{
this.listener.InstrumentPublished = (instrument, listener) =>
{
if (meterSourcesToSubscribe.ContainsKey(instrument.Meter.Name))
if (meterSourcesToSubscribe.Contains(instrument.Meter.Name))
{
var metricName = instrument.Name;
Metric metric = null;
Expand Down Expand Up @@ -243,6 +269,17 @@ internal MeterProviderSdk(

this.listener.MeasurementsCompleted = (instrument, state) => this.MeasurementsCompleted(instrument, state);
this.listener.Start();

static Regex GetWildcardRegex(IEnumerable<string> collection)
{
var pattern = '^' + string.Join("|", from name in collection select "(?:" + Regex.Escape(name).Replace("\\*", ".*") + ')') + '$';
return new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
}

bool ShouldListenTo(string instrumentName)
{
return regex.IsMatch(instrumentName);
}
}

internal Resource Resource { get; }
Expand Down
24 changes: 24 additions & 0 deletions test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,30 @@ void ProcessExport(Batch<Metric> batch)
Assert.Equal(1, metricCount);
}

[Fact]
public void MeterSourcesWildCardSupportTest()
{
var meterSources = new[] { "MeterSources.*", "MeterSources.*.Subset" };
using var meter1 = new Meter(meterSources[0]);
using var meter2 = new Meter(meterSources[1]);

var exportedItems = new List<Metric>();
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter(meter1.Name)
.AddMeter(meter2.Name)
.AddInMemoryExporter(exportedItems)
.AddView("name1", "renamed")
.Build();

var measurement = new Measurement<int>(100, new("name", "apple"), new("color", "red"));
meter1.CreateObservableGauge("myGauge1", () => measurement);
meter2.CreateObservableGauge("myGauge2", () => measurement);

meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Equal("myGauge1", exportedItems[0].Name);
Assert.Equal("myGauge2", exportedItems[1].Name);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
Expand Down