Skip to content

Commit

Permalink
[prometheus-httplistener] Throw an exception if the listener cannot b…
Browse files Browse the repository at this point in the history
…e started (#5304)
  • Loading branch information
CodeBlanch authored Feb 1, 2024
1 parent 9fd01f7 commit 8b54074
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

## Unreleased

* Export OpenMetrics format from Prometheus exporters ([#5107](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5107))
* Export OpenMetrics format from Prometheus exporters
([#5107](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5107))

* For requests with OpenMetrics format, scope info is automatically added
([#5086](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5086)
[#5182](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5182))

* **Breaking change** Updated the `PrometheusHttpListener` to throw an exception
if it can't be started.
([#5304](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5304))

## 1.7.0-rc.1

Released 2023-Nov-29
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public void Start(CancellationToken token = default)
return;
}

this.httpListener.Start();

// link the passed in token if not null
this.tokenSource = token == default ?
new CancellationTokenSource() :
Expand Down Expand Up @@ -91,7 +93,7 @@ public void Dispose()
{
this.Stop();

if (this.httpListener != null && this.httpListener.IsListening)
if (this.httpListener.IsListening)
{
this.httpListener.Close();
}
Expand All @@ -111,8 +113,6 @@ private static bool AcceptsOpenMetrics(HttpListenerRequest request)

private void WorkerProc()
{
this.httpListener.Start();

try
{
using var scope = SuppressInstrumentationScope.Begin();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void TestAddPrometheusHttpListener_NamedOptions()
services.Configure<PrometheusHttpListenerOptions>("Exporter2", o => namedExporterOptionsConfigureOptionsInvocations++);
})
.AddPrometheusHttpListener()
.AddPrometheusHttpListener("Exporter2", o => { })
.AddPrometheusHttpListener("Exporter2", o => o.ScrapeEndpointPath = "/metrics2")
.Build();

Assert.Equal(1, defaultExporterOptionsConfigureOptionsInvocations);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,15 @@ public class PrometheusHttpListenerTests
[InlineData("http://example.com")]
public void UriPrefixesPositiveTest(params string[] uriPrefixes)
{
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
.AddPrometheusHttpListener(options => options.UriPrefixes = uriPrefixes)
.Build();
TestPrometheusHttpListenerUriPrefixOptions(uriPrefixes);
}

[Fact]
public void UriPrefixesNull()
{
Assert.Throws<ArgumentNullException>(() =>
{
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
.AddPrometheusHttpListener(options => options.UriPrefixes = null)
.Build();
TestPrometheusHttpListenerUriPrefixOptions(null);
});
}

Expand All @@ -50,20 +46,16 @@ public void UriPrefixesEmptyList()
{
Assert.Throws<ArgumentException>(() =>
{
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
.AddPrometheusHttpListener(options => options.UriPrefixes = new string[] { })
.Build();
TestPrometheusHttpListenerUriPrefixOptions(new string[] { });
});
}

[Fact]
public void UriPrefixesInvalid()
{
Assert.Throws<InvalidOperationException>(() =>
Assert.Throws<ArgumentException>(() =>
{
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
.AddPrometheusHttpListener(options => options.UriPrefixes = new string[] { "ftp://example.com" })
.Build();
TestPrometheusHttpListenerUriPrefixOptions(new string[] { "ftp://example.com" });
});
}

Expand Down Expand Up @@ -91,6 +83,77 @@ public async Task PrometheusExporterHttpServerIntegration_UseOpenMetricsVersionH
await this.RunPrometheusExporterHttpServerIntegrationTest(acceptHeader: "application/openmetrics-text; version=1.0.0");
}

[Fact]
public void PrometheusHttpListenerThrowsOnStart()
{
Random random = new Random();
int retryAttempts = 5;
int port = 0;
string address = null;

PrometheusExporter exporter = null;
PrometheusHttpListener listener = null;

// Step 1: Start a listener on a random port.
while (retryAttempts-- != 0)
{
port = random.Next(2000, 5000);
address = $"http://localhost:{port}/";

try
{
exporter = new PrometheusExporter(new());
listener = new PrometheusHttpListener(
exporter,
new()
{
UriPrefixes = new string[] { address },
});

listener.Start();

break;
}
catch
{
// ignored
}
}

if (retryAttempts == 0)
{
throw new InvalidOperationException("PrometheusHttpListener could not be started");
}

// Step 2: Make sure if we start a second listener on the same port an exception is thrown.
Assert.Throws<HttpListenerException>(() =>
{
using var exporter = new PrometheusExporter(new());
using var listener = new PrometheusHttpListener(
exporter,
new()
{
UriPrefixes = new string[] { address },
});

listener.Start();
});

exporter?.Dispose();
listener?.Dispose();
}

private static void TestPrometheusHttpListenerUriPrefixOptions(string[] uriPrefixes)
{
using var exporter = new PrometheusExporter(new());
using var listener = new PrometheusHttpListener(
exporter,
new()
{
UriPrefixes = uriPrefixes,
});
}

private async Task RunPrometheusExporterHttpServerIntegrationTest(bool skipMetrics = false, string acceptHeader = "application/openmetrics-text")
{
var requestOpenMetrics = acceptHeader.StartsWith("application/openmetrics-text");
Expand Down

0 comments on commit 8b54074

Please sign in to comment.