Skip to content

Commit 26ac74d

Browse files
authored
Added sanity check for the setter of PrometheusExporter's HTTP listeners. (#2771)
1 parent 18d73c5 commit 26ac74d

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterOptions.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class PrometheusExporterOptions
2929
internal Func<DateTimeOffset> GetUtcNowDateTimeOffset = () => DateTimeOffset.UtcNow;
3030

3131
private int scrapeResponseCacheDurationMilliseconds = 10 * 1000;
32+
private IReadOnlyCollection<string> httpListenerPrefixes = new string[] { "http://*:80/" };
3233

3334
#if NETCOREAPP3_1_OR_GREATER
3435
/// <summary>
@@ -48,7 +49,27 @@ public class PrometheusExporterOptions
4849
/// Gets or sets the prefixes to use for the http listener. Default
4950
/// value: http://*:80/.
5051
/// </summary>
51-
public IReadOnlyCollection<string> HttpListenerPrefixes { get; set; } = new string[] { "http://*:80/" };
52+
public IReadOnlyCollection<string> HttpListenerPrefixes
53+
{
54+
get => this.httpListenerPrefixes;
55+
set
56+
{
57+
_ = value ?? throw new ArgumentNullException(nameof(this.httpListenerPrefixes));
58+
59+
foreach (string inputUri in value)
60+
{
61+
if (!(Uri.TryCreate(inputUri, UriKind.Absolute, out var uri) &&
62+
(uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)))
63+
{
64+
throw new ArgumentException(
65+
"Prometheus server path should be a valid URI with http/https scheme.",
66+
nameof(this.httpListenerPrefixes));
67+
}
68+
}
69+
70+
this.httpListenerPrefixes = value;
71+
}
72+
}
5273

5374
/// <summary>
5475
/// Gets or sets the path to use for the scraping endpoint. Default value: /metrics.

test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusExporterHttpServerTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,5 +105,50 @@ public async Task PrometheusExporterHttpServerIntegration()
105105
"^# TYPE counter_double counter\ncounter_double{key1='value1',key2='value2'} 101.17 \\d+\n$".Replace('\'', '"'),
106106
await response.Content.ReadAsStringAsync().ConfigureAwait(false));
107107
}
108+
109+
[Theory]
110+
[InlineData("http://example.com")]
111+
[InlineData("https://example.com")]
112+
[InlineData("http://127.0.0.1")]
113+
[InlineData("http://example.com", "https://example.com", "http://127.0.0.1")]
114+
public void ServerEndpointSanityCheckPositiveTest(params string[] uris)
115+
{
116+
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
117+
.AddPrometheusExporter(opt =>
118+
{
119+
opt.HttpListenerPrefixes = uris;
120+
})
121+
.Build();
122+
}
123+
124+
[Theory]
125+
[InlineData("")]
126+
[InlineData(null)]
127+
[InlineData("ftp://example.com")]
128+
[InlineData("http://example.com", "https://example.com", "ftp://example.com")]
129+
public void ServerEndpointSanityCheckNegativeTest(params string[] uris)
130+
{
131+
try
132+
{
133+
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
134+
.AddPrometheusExporter(opt =>
135+
{
136+
opt.HttpListenerPrefixes = uris;
137+
})
138+
.Build();
139+
}
140+
catch (Exception ex)
141+
{
142+
if (ex is not ArgumentNullException)
143+
{
144+
Assert.Equal("System.ArgumentException", ex.GetType().ToString());
145+
#if NET461
146+
Assert.Equal("Prometheus server path should be a valid URI with http/https scheme.\r\nParameter name: httpListenerPrefixes", ex.Message);
147+
#else
148+
Assert.Equal("Prometheus server path should be a valid URI with http/https scheme. (Parameter 'httpListenerPrefixes')", ex.Message);
149+
#endif
150+
}
151+
}
152+
}
108153
}
109154
}

0 commit comments

Comments
 (0)