Skip to content

Commit 1253fe8

Browse files
authored
Merge pull request #22 from prom-client-net/new-options
New Options: CollectorRegistryInstance and UseDefaultCollectors
2 parents 247de38 + 66bc6b9 commit 1253fe8

File tree

5 files changed

+115
-53
lines changed

5 files changed

+115
-53
lines changed
Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
using System.Threading.Tasks;
2-
31
namespace Prometheus.Client.MetricServer
42
{
53
/// <summary>
64
/// MetricSever
75
/// </summary>
86
public interface IMetricServer
97
{
8+
/// <summary>
9+
/// Server is Running?
10+
/// </summary>
11+
bool IsRunning { get; }
12+
1013
/// <summary>
1114
/// Start server
1215
/// </summary>
@@ -16,10 +19,5 @@ public interface IMetricServer
1619
/// Stop server
1720
/// </summary>
1821
void Stop();
19-
20-
/// <summary>
21-
/// Server is Running?
22-
/// </summary>
23-
bool IsRunning { get; }
2422
}
2523
}

src/Prometheus.Client.MetricServer/MetricServer.cs

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,36 +16,54 @@ namespace Prometheus.Client.MetricServer
1616
public class MetricServer : IMetricServer
1717
{
1818
private readonly MetricServerOptions _options;
19-
private readonly ICollectorRegistry _registry;
2019
private IWebHost _host;
2120

2221
/// <summary>
23-
/// Constructor
22+
/// Constructor
2423
/// </summary>
24+
/// <param name="registry">Collector registry </param>
2525
/// <param name="options">Http server configuration options</param>
26-
public MetricServer(MetricServerOptions options)
27-
:this(null, options)
26+
[Obsolete("Use options.CollectorRegistryInstance for set CollectorRegistry")]
27+
public MetricServer(ICollectorRegistry registry, MetricServerOptions options)
2828
{
29+
options.CollectorRegistryInstance = registry;
30+
31+
if (string.IsNullOrEmpty(options.MapPath) || !options.MapPath.StartsWith("/"))
32+
throw new ArgumentException($"mapPath '{options.MapPath}' should start with '/'");
33+
34+
_options = options;
35+
36+
_options.CollectorRegistryInstance ??= Metrics.DefaultCollectorRegistry;
37+
38+
if (_options.UseDefaultCollectors)
39+
_options.CollectorRegistryInstance.UseDefaultCollectors();
2940
}
3041

3142
/// <summary>
32-
/// Constructor
43+
/// Constructor
3344
/// </summary>
34-
/// <param name="registry">Collector registry </param>
35-
/// <param name="options">Http server configuration options</param>
36-
public MetricServer(ICollectorRegistry registry, MetricServerOptions options)
45+
public MetricServer()
46+
: this(new MetricServerOptions())
47+
{
48+
}
49+
50+
/// <summary>
51+
/// Constructor
52+
/// </summary>
53+
public MetricServer(MetricServerOptions options)
3754
{
3855
if (options == null)
3956
throw new ArgumentNullException(nameof(options));
4057

41-
if (options.Port == 0)
42-
throw new ArgumentException("Port should be specified");
43-
4458
if (string.IsNullOrEmpty(options.MapPath) || !options.MapPath.StartsWith("/"))
4559
throw new ArgumentException($"mapPath '{options.MapPath}' should start with '/'");
4660

47-
_registry = registry;
4861
_options = options;
62+
63+
_options.CollectorRegistryInstance ??= Metrics.DefaultCollectorRegistry;
64+
65+
if (_options.UseDefaultCollectors)
66+
_options.CollectorRegistryInstance.UseDefaultCollectors();
4967
}
5068

5169
/// <inheritdoc />
@@ -69,7 +87,7 @@ public void Start()
6987
options.Listen(IPAddress.Any, _options.Port, listenOptions => { listenOptions.UseHttps(_options.Certificate); });
7088
})
7189
.UseUrls($"http{(_options.Certificate != null ? "s" : "")}://{_options.Host}:{_options.Port}")
72-
.ConfigureServices(services => { services.AddSingleton<IStartup>(new Startup(_registry, _options.MapPath)); })
90+
.ConfigureServices(services => { services.AddSingleton<IStartup>(new Startup(_options.CollectorRegistryInstance, _options.MapPath)); })
7391
.UseSetting(WebHostDefaults.ApplicationKey, typeof(Startup).GetTypeInfo().Assembly.FullName)
7492
.Build();
7593

@@ -89,10 +107,10 @@ public void Stop()
89107
internal class Startup : IStartup
90108
{
91109
private const string _contentType = "text/plain; version=0.0.4";
92-
93-
private ICollectorRegistry _registry;
94110
private readonly string _mapPath;
95111

112+
private readonly ICollectorRegistry _registry;
113+
96114
public Startup(ICollectorRegistry registry, string mapPath)
97115
{
98116
_registry = registry;
@@ -111,20 +129,15 @@ public IServiceProvider ConfigureServices(IServiceCollection services)
111129

112130
public void Configure(IApplicationBuilder app)
113131
{
114-
_registry ??= (ICollectorRegistry)app.ApplicationServices.GetService(typeof(ICollectorRegistry))
115-
?? Metrics.DefaultCollectorRegistry;
116-
117132
app.Map(_mapPath, coreapp =>
118133
{
119134
coreapp.Run(async context =>
120135
{
121136
var response = context.Response;
122137
response.ContentType = _contentType;
123138

124-
using (var outputStream = response.Body)
125-
{
126-
await ScrapeHandler.ProcessAsync(_registry, outputStream);
127-
}
139+
using var outputStream = response.Body;
140+
await ScrapeHandler.ProcessAsync(_registry, outputStream);
128141
});
129142
});
130143
}
Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,41 @@
11
using System.Security.Cryptography.X509Certificates;
2+
using Prometheus.Client.Collectors;
23

34
namespace Prometheus.Client.MetricServer
45
{
56
/// <summary>
6-
/// Metric Server Options
7+
/// Metric Server Options
78
/// </summary>
89
public class MetricServerOptions
910
{
1011
/// <summary>
11-
/// Host name
12+
/// Host name
1213
/// </summary>
1314
public string Host { get; set; } = "*";
1415

1516
/// <summary>
16-
/// Port number to listen
17+
/// Port number to listen
1718
/// </summary>
18-
public int Port { get; set; }
19+
public int Port { get; set; } = 5000;
1920

2021
/// <summary>
21-
/// Endpoint path
22+
/// Endpoint path
2223
/// </summary>
2324
public string MapPath { get; set; } = "/metrics";
2425

2526
/// <summary>
26-
/// Https certificate
27+
/// Https certificate
2728
/// </summary>
2829
public X509Certificate2 Certificate { get; set; }
30+
31+
/// <summary>
32+
/// Collector Registry instance
33+
/// </summary>
34+
public ICollectorRegistry CollectorRegistryInstance { get; set; }
35+
36+
/// <summary>
37+
/// Use default collectors(dotnet and process stats)
38+
/// </summary>
39+
public bool UseDefaultCollectors { get; set; } = false;
2940
}
3041
}

src/Prometheus.Client.MetricServer/Prometheus.Client.MetricServer.csproj

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<Description>MetricServer for the Prometheus.Client</Description>
3+
<Description>Standalone Kestrel server for the Prometheus.Client</Description>
44
<Copyright>2020 © Serge K, Oleksandr Poliakov</Copyright>
55
<AssemblyTitle>Prometheus.Client.MetricServer</AssemblyTitle>
6-
<VersionPrefix>4.1.0</VersionPrefix>
6+
<VersionPrefix>4.2.0</VersionPrefix>
77
<Authors>Serge K, Oleksandr Poliakov</Authors>
8-
<TargetFrameworks>netstandard2.0;netstandard2.1;netcoreapp3.1</TargetFrameworks>
8+
<TargetFrameworks>netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0</TargetFrameworks>
99
<LangVersion>latest</LangVersion>
1010
<AssemblyName>Prometheus.Client.MetricServer</AssemblyName>
1111
<PackageId>Prometheus.Client.MetricServer</PackageId>
1212
<PackageTags>prometheus;metrics</PackageTags>
1313
<PackageIcon>icon.png</PackageIcon>
14-
<PackageProjectUrl>https://github.com/PrometheusClientNet/Prometheus.Client.MetricServer</PackageProjectUrl>
14+
<PackageProjectUrl>https://github.com/prom-client-net/Prometheus.Client.MetricServer</PackageProjectUrl>
1515
<PackageLicenseExpression>MIT</PackageLicenseExpression>
1616
<RepositoryType>git</RepositoryType>
17-
<RepositoryUrl>https://github.com/PrometheusClientNet/Prometheus.Client.MetricServer</RepositoryUrl>
17+
<RepositoryUrl>https://github.com/prom-client-net/Prometheus.Client.MetricServer</RepositoryUrl>
1818
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
1919
<GenerateDocumentationFile>true</GenerateDocumentationFile>
2020
<SignAssembly>true</SignAssembly>
@@ -31,13 +31,13 @@
3131
</None>
3232
</ItemGroup>
3333
<ItemGroup>
34-
<PackageReference Include="Prometheus.Client" Version="4.4.0" />
34+
<PackageReference Include="Prometheus.Client" Version="[4.4.0,5.0.0)" />
3535
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
3636
</ItemGroup>
37-
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
37+
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1' OR '$(TargetFramework)' == 'net5.0'">
3838
<FrameworkReference Include="Microsoft.AspNetCore.App" />
3939
</ItemGroup>
40-
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
40+
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'netstandard2.1'">
4141
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
4242
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.2.0" />
4343
</ItemGroup>

tests/Prometheus.Client.MetricServer.Tests/MetricServerTests.cs

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public MetricServerTests(ITestOutputHelper testOutputHelper)
1919
}
2020

2121
[Fact]
22-
public void Start_Stop_IsRunning()
22+
public void Start_Stop_LegacyConstructor_IsRunning()
2323
{
2424
var metricServer = new MetricServer(new CollectorRegistry(), new MetricServerOptions { Port = _port });
2525
metricServer.Start();
@@ -28,17 +28,27 @@ public void Start_Stop_IsRunning()
2828
Assert.False(metricServer.IsRunning);
2929
}
3030

31+
[Fact]
32+
public void Start_Stop_DefaultPort_IsRunning()
33+
{
34+
var metricServer = new MetricServer();
35+
metricServer.Start();
36+
Assert.True(metricServer.IsRunning);
37+
metricServer.Stop();
38+
Assert.False(metricServer.IsRunning);
39+
}
40+
3141
[Fact]
3242
public async Task Base_MapPath()
3343
{
34-
var metricServer = new MetricServer(new MetricServerOptions { Port = _port});
44+
var metricServer = new MetricServer(new MetricServerOptions { Port = _port });
3545
try
3646
{
3747
metricServer.Start();
3848
var counter = Metrics.DefaultFactory.CreateCounter("test_counter", "help");
3949
counter.Inc();
4050
using var httpClient = new HttpClient();
41-
var response = await httpClient.GetStringAsync($"http://localhost:{_port}/metrics");
51+
string response = await httpClient.GetStringAsync($"http://localhost:{_port}/metrics");
4252
Assert.False(string.IsNullOrEmpty(response));
4353
}
4454
catch (Exception ex)
@@ -62,7 +72,7 @@ public async Task MapPath_WithEndSlash()
6272
var counter = Metrics.DefaultFactory.CreateCounter("test_counter", "help");
6373
counter.Inc();
6474
using var httpClient = new HttpClient();
65-
var response = await httpClient.GetStringAsync($"http://localhost:{_port}/test/");
75+
string response = await httpClient.GetStringAsync($"http://localhost:{_port}/test/");
6676
Assert.False(string.IsNullOrEmpty(response));
6777
}
6878
catch (Exception ex)
@@ -80,7 +90,6 @@ public async Task MapPath_WithEndSlash()
8090
public void Wrong_MapPath()
8191
{
8292
Assert.Throws<ArgumentException>(() => new MetricServer(
83-
new CollectorRegistry(),
8493
new MetricServerOptions { Port = _port, MapPath = "temp" }));
8594
}
8695

@@ -97,7 +106,7 @@ public async Task MapPath(string mapPath)
97106
var counter = Metrics.DefaultFactory.CreateCounter("test_counter", "help");
98107
counter.Inc();
99108
using var httpClient = new HttpClient();
100-
var response = await httpClient.GetStringAsync($"http://localhost:{_port}" + mapPath);
109+
string response = await httpClient.GetStringAsync($"http://localhost:{_port}" + mapPath);
101110
Assert.False(string.IsNullOrEmpty(response));
102111
}
103112
catch (Exception ex)
@@ -112,11 +121,11 @@ public async Task MapPath(string mapPath)
112121
}
113122

114123
[Fact]
115-
public async Task FindMetric()
124+
public async Task Find_Metric()
116125
{
117126
var registry = new CollectorRegistry();
118127
var factory = new MetricFactory(registry);
119-
var metricServer = new MetricServer(registry, new MetricServerOptions { Port = _port });
128+
var metricServer = new MetricServer(new MetricServerOptions { Port = _port, CollectorRegistryInstance = registry});
120129

121130
try
122131
{
@@ -127,7 +136,7 @@ public async Task FindMetric()
127136
counter.Inc();
128137

129138
using var httpClient = new HttpClient();
130-
var response = await httpClient.GetStringAsync($"http://localhost:{_port}/metrics");
139+
string response = await httpClient.GetStringAsync($"http://localhost:{_port}/metrics");
131140
Assert.Contains(metricName, response);
132141
}
133142
catch (Exception ex)
@@ -144,7 +153,7 @@ public async Task FindMetric()
144153
[Fact]
145154
public async Task Url_NotFound()
146155
{
147-
var metricServer = new MetricServer(new CollectorRegistry(), new MetricServerOptions { Port = _port });
156+
var metricServer = new MetricServer(new MetricServerOptions { Port = _port });
148157
try
149158
{
150159
metricServer.Start();
@@ -165,5 +174,36 @@ public async Task Url_NotFound()
165174
metricServer.Stop();
166175
}
167176
}
177+
178+
[Fact]
179+
public async Task Find_Default_Metric()
180+
{
181+
var registry = new CollectorRegistry();
182+
var metricServer = new MetricServer(new MetricServerOptions
183+
{
184+
Port = _port,
185+
CollectorRegistryInstance = registry,
186+
UseDefaultCollectors = true
187+
});
188+
189+
try
190+
{
191+
metricServer.Start();
192+
193+
using var httpClient = new HttpClient();
194+
string response = await httpClient.GetStringAsync($"http://localhost:{_port}/metrics");
195+
Assert.Contains("dotnet_collection_count_total", response);
196+
Assert.Contains("process_cpu_seconds_total", response);
197+
}
198+
catch (Exception ex)
199+
{
200+
_testOutputHelper.WriteLine(ex.ToString());
201+
throw;
202+
}
203+
finally
204+
{
205+
metricServer.Stop();
206+
}
207+
}
168208
}
169209
}

0 commit comments

Comments
 (0)