[Prometheus] Split up projects based on hosting mechanism. (#3430)

This commit is contained in:
Yun-Ting Lin 2022-07-28 16:02:53 -07:00 committed by GitHub
parent 2b1e75d7e9
commit cd6043bbf7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 737 additions and 323 deletions

View File

@ -195,8 +195,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "reporting-exceptions", "doc
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "customizing-the-sdk", "docs\trace\customizing-the-sdk\customizing-the-sdk.csproj", "{64E3D8BB-93AB-4571-93F7-ED8D64DFFD06}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Prometheus", "src\OpenTelemetry.Exporter.Prometheus\OpenTelemetry.Exporter.Prometheus.csproj", "{52158A12-E7EF-45A1-859F-06F9B17410CB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "learning-more-instruments", "docs\metrics\learning-more-instruments\learning-more-instruments.csproj", "{E7F491CC-C37E-4A56-9CA7-8F77F59E0614}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "getting-started", "docs\metrics\getting-started\getting-started.csproj", "{EA60B549-F712-4ABE-8E44-FCA83B78C06E}"
@ -209,8 +207,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "customizing-the-sdk", "docs
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Tests.Stress", "test\OpenTelemetry.Tests.Stress\OpenTelemetry.Tests.Stress.csproj", "{2770158A-D220-414B-ABC6-179371323579}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Prometheus.Tests", "test\OpenTelemetry.Exporter.Prometheus.Tests\OpenTelemetry.Exporter.Prometheus.Tests.csproj", "{380EE686-91F1-45B3-AEEB-755F0E5B068F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs", "src\OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs\OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs.csproj", "{6E1A5FA3-E024-4972-9EDC-11E36C5A0D6F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApp.AspNetCore.6.0", "test\TestApp.AspNetCore.6.0\TestApp.AspNetCore.6.0.csproj", "{0076C657-564F-4787-9FFF-52D9D55166E8}"
@ -239,6 +235,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.Ev
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.EventSource.Tests", "test\OpenTelemetry.Extensions.EventSource.Tests\OpenTelemetry.Extensions.EventSource.Tests.csproj", "{304FCFFF-97DE-484B-8D8C-612C644426E5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Prometheus.AspNetCore", "src\OpenTelemetry.Exporter.Prometheus.AspNetCore\OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj", "{921CF401-4C2F-4C6D-A750-0B5DC457C1F1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Prometheus.HttpListener", "src\OpenTelemetry.Exporter.Prometheus.HttpListener\OpenTelemetry.Exporter.Prometheus.HttpListener.csproj", "{6B0232B7-5F29-4FB5-B383-1AA02DFE1089}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Prometheus.Shared", "src\OpenTelemetry.Exporter.Prometheus.Shared\OpenTelemetry.Exporter.Prometheus.Shared.csproj", "{4AD27517-BAFC-413B-A8F0-988C3CEDC662}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests", "test\OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests\OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests.csproj", "{FBD12B0B-6731-4DD4-9C13-86F34593E974}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Prometheus.HttpListener.Tests", "test\OpenTelemetry.Exporter.Prometheus.HttpListener.Tests\OpenTelemetry.Exporter.Prometheus.HttpListener.Tests.csproj", "{4EF4364F-6E64-43CE-BED1-E6FE01024899}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Prometheus.Shared.Tests", "test\OpenTelemetry.Exporter.Prometheus.Shared.Tests\OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj", "{8E75AEE2-017B-474F-A96D-035DF76A1C9E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -405,10 +413,6 @@ Global
{64E3D8BB-93AB-4571-93F7-ED8D64DFFD06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{64E3D8BB-93AB-4571-93F7-ED8D64DFFD06}.Release|Any CPU.ActiveCfg = Release|Any CPU
{64E3D8BB-93AB-4571-93F7-ED8D64DFFD06}.Release|Any CPU.Build.0 = Release|Any CPU
{52158A12-E7EF-45A1-859F-06F9B17410CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{52158A12-E7EF-45A1-859F-06F9B17410CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52158A12-E7EF-45A1-859F-06F9B17410CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{52158A12-E7EF-45A1-859F-06F9B17410CB}.Release|Any CPU.Build.0 = Release|Any CPU
{E7F491CC-C37E-4A56-9CA7-8F77F59E0614}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E7F491CC-C37E-4A56-9CA7-8F77F59E0614}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E7F491CC-C37E-4A56-9CA7-8F77F59E0614}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -433,10 +437,6 @@ Global
{2770158A-D220-414B-ABC6-179371323579}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2770158A-D220-414B-ABC6-179371323579}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2770158A-D220-414B-ABC6-179371323579}.Release|Any CPU.Build.0 = Release|Any CPU
{380EE686-91F1-45B3-AEEB-755F0E5B068F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{380EE686-91F1-45B3-AEEB-755F0E5B068F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{380EE686-91F1-45B3-AEEB-755F0E5B068F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{380EE686-91F1-45B3-AEEB-755F0E5B068F}.Release|Any CPU.Build.0 = Release|Any CPU
{6E1A5FA3-E024-4972-9EDC-11E36C5A0D6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E1A5FA3-E024-4972-9EDC-11E36C5A0D6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E1A5FA3-E024-4972-9EDC-11E36C5A0D6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -493,6 +493,30 @@ Global
{304FCFFF-97DE-484B-8D8C-612C644426E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{304FCFFF-97DE-484B-8D8C-612C644426E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{304FCFFF-97DE-484B-8D8C-612C644426E5}.Release|Any CPU.Build.0 = Release|Any CPU
{921CF401-4C2F-4C6D-A750-0B5DC457C1F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{921CF401-4C2F-4C6D-A750-0B5DC457C1F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{921CF401-4C2F-4C6D-A750-0B5DC457C1F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{921CF401-4C2F-4C6D-A750-0B5DC457C1F1}.Release|Any CPU.Build.0 = Release|Any CPU
{6B0232B7-5F29-4FB5-B383-1AA02DFE1089}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B0232B7-5F29-4FB5-B383-1AA02DFE1089}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B0232B7-5F29-4FB5-B383-1AA02DFE1089}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B0232B7-5F29-4FB5-B383-1AA02DFE1089}.Release|Any CPU.Build.0 = Release|Any CPU
{4AD27517-BAFC-413B-A8F0-988C3CEDC662}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4AD27517-BAFC-413B-A8F0-988C3CEDC662}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4AD27517-BAFC-413B-A8F0-988C3CEDC662}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4AD27517-BAFC-413B-A8F0-988C3CEDC662}.Release|Any CPU.Build.0 = Release|Any CPU
{FBD12B0B-6731-4DD4-9C13-86F34593E974}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FBD12B0B-6731-4DD4-9C13-86F34593E974}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FBD12B0B-6731-4DD4-9C13-86F34593E974}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FBD12B0B-6731-4DD4-9C13-86F34593E974}.Release|Any CPU.Build.0 = Release|Any CPU
{4EF4364F-6E64-43CE-BED1-E6FE01024899}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4EF4364F-6E64-43CE-BED1-E6FE01024899}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4EF4364F-6E64-43CE-BED1-E6FE01024899}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4EF4364F-6E64-43CE-BED1-E6FE01024899}.Release|Any CPU.Build.0 = Release|Any CPU
{8E75AEE2-017B-474F-A96D-035DF76A1C9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8E75AEE2-017B-474F-A96D-035DF76A1C9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8E75AEE2-017B-474F-A96D-035DF76A1C9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8E75AEE2-017B-474F-A96D-035DF76A1C9E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -66,7 +66,8 @@ libraries](https://github.com/open-telemetry/opentelemetry-specification/blob/ma
* [Jaeger](./src/OpenTelemetry.Exporter.Jaeger/README.md)
* [OTLP](./src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md)
(OpenTelemetry Protocol)
* [Prometheus](./src/OpenTelemetry.Exporter.Prometheus/README.md)
* [Prometheus HttpListener](./src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md)
* [Prometheus AspNetCore](./src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md)
* [Zipkin](./src/OpenTelemetry.Exporter.Zipkin/README.md)
See the [OpenTelemetry registry](https://opentelemetry.io/registry/?s=net) for

View File

@ -423,7 +423,8 @@ Refer to the individual exporter docs to learn how to use them:
* [In-memory](../../../src/OpenTelemetry.Exporter.InMemory/README.md)
* [OTLP](../../../src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md)
(OpenTelemetry Protocol)
* [Prometheus](../../../src/OpenTelemetry.Exporter.Prometheus/README.md)
* [Prometheus HttpListener](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md)
* [Prometheus AspNetCore](../../../src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md)
### Resource

View File

@ -12,7 +12,8 @@ OpenTelemetry .NET SDK has provided the following built-in metric exporters:
* [InMemory](../../../src/OpenTelemetry.Exporter.InMemory/README.md)
* [Console](../../../src/OpenTelemetry.Exporter.Console/README.md)
* [OpenTelemetryProtocol](../../../src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md)
* [Prometheus](../../../src/OpenTelemetry.Exporter.Prometheus/README.md)
* [Prometheus HttpListener](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md)
* [Prometheus AspNetCore](../../../src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md)
Custom exporters can be implemented to send telemetry data to places which are
not covered by the built-in exporters:

View File

@ -31,7 +31,7 @@ public class Program
{
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("MyCompany.MyProduct.MyLibrary")
.AddPrometheusExporter(options => { options.StartHttpListener = true; })
.AddPrometheusHttpListener()
.Build();
Console.WriteLine("Press any key to exit");

View File

@ -23,10 +23,10 @@ dotnet run
```
Add a reference to [Prometheus
Exporter](../../../src/OpenTelemetry.Exporter.Prometheus/README.md):
Exporter Http Listener](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md):
```sh
dotnet add package --prerelease OpenTelemetry.Exporter.Prometheus
dotnet add package --prerelease OpenTelemetry.Exporter.Prometheus.HttpListener
```
Now, we are going to make some small tweaks to the example in the
@ -46,12 +46,13 @@ And replace the below line:
with
```csharp
.AddPrometheusExporter(options => { options.StartHttpListener = true; })
.AddPrometheusHttpListener()
```
With `AddPrometheusExporter()`, OpenTelemetry `PrometheusExporter` will export
`PrometheusHttpListener` is a wrapper that contains `PrometheusExporter`.
With `AddPrometheusHttpListener()`, OpenTelemetry `PrometheusExporter` will export
data via the endpoint defined by
[PrometheusExporterOptions.HttpListenerPrefixes](../../../src/OpenTelemetry.Exporter.Prometheus/README.md#httplistenerprefixes),
[PrometheusHttpListenerOptions.Prefixes](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md#prefixes),
which is `http://localhost:9464/` by default.
```mermaid
@ -60,7 +61,7 @@ graph LR
subgraph SDK
MeterProvider
MetricReader[BaseExportingMetricReader]
PrometheusExporter["PrometheusExporter<br/>(http://localhost:9464/)"]
PrometheusHttpListener["PrometheusHttpListener<br/>(http://localhost:9464/)"]
end
subgraph API
@ -69,7 +70,7 @@ end
Instrument --> | Measurements | MeterProvider
MeterProvider --> | Metrics | MetricReader --> | Pull | PrometheusExporter
MeterProvider --> | Metrics | MetricReader --> | Pull | PrometheusHttpListener
```
Also, for our learning purpose, use a while-loop to keep increasing the counter
@ -99,7 +100,7 @@ web browser:
![Browser UI](https://user-images.githubusercontent.com/17327289/151633547-736c6d91-62d2-4e66-a53f-2e16c44bfabc.png)
Now, we understand how we can configure `PrometheusExporter` to export metrics.
Now, we understand how we can configure `PrometheusHttpListener` to export metrics.
Next, we are going to learn about how to use Prometheus to collect the metrics.
## Collect metrics using Prometheus
@ -156,7 +157,7 @@ values we have set in `otel.yml`.
Congratulations!
Now we know how to configure Prometheus server and deploy OpenTelemetry
`PrometheusExporter` to export our metrics. Next, we are going to explore a tool
`PrometheusHttpListener` to export our metrics. Next, we are going to explore a tool
called Grafana, which has powerful visualizations for the metrics.
## Explore metrics using Grafana
@ -201,7 +202,7 @@ subgraph Prometheus
PrometheusDatabase
end
PrometheusExporter["PrometheusExporter<br/>(listening at #quot;http://localhost:9464/#quot;)"] -->|HTTP GET| PrometheusScraper{{"Prometheus scraper<br/>(polling #quot;http://localhost:9464/metrics#quot; every 10 seconds)"}}
PrometheusHttpListener["PrometheusHttpListener<br/>(listening at #quot;http://localhost:9464/#quot;)"] -->|HTTP GET| PrometheusScraper{{"Prometheus scraper<br/>(polling #quot;http://localhost:9464/metrics#quot; every 10 seconds)"}}
PrometheusScraper --> PrometheusDatabase[("Prometheus TSDB (time series database)")]
PrometheusDatabase -->|http://localhost:9090/graph| PrometheusUI["Browser<br/>(Prometheus Dashboard)"]
PrometheusDatabase -->|http://localhost:9090/api/| Grafana[Grafana Server]

View File

@ -1,5 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus\OpenTelemetry.Exporter.Prometheus.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.HttpListener\OpenTelemetry.Exporter.Prometheus.HttpListener.csproj" />
</ItemGroup>
</Project>

View File

@ -19,7 +19,7 @@
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.AspNetCore\OpenTelemetry.Instrumentation.AspNetCore.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.Http\OpenTelemetry.Instrumentation.Http.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus\OpenTelemetry.Exporter.Prometheus.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.AspNetCore\OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Zipkin\OpenTelemetry.Exporter.Zipkin.csproj" />
</ItemGroup>
</Project>

View File

@ -33,7 +33,7 @@
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Zipkin\OpenTelemetry.Exporter.Zipkin.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.InMemory\OpenTelemetry.Exporter.InMemory.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus\OpenTelemetry.Exporter.Prometheus.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.HttpListener\OpenTelemetry.Exporter.Prometheus.HttpListener.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs\OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs.csproj" />
</ItemGroup>
</Project>

View File

@ -51,12 +51,9 @@ internal class TestPrometheusExporter
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter(MyMeter.Name)
.AddMeter(MyMeter2.Name)
.AddPrometheusExporter(options =>
{
options.StartHttpListener = true;
options.HttpListenerPrefixes = new string[] { $"http://localhost:{port}/" };
options.ScrapeResponseCacheDurationMilliseconds = 0;
})
.AddPrometheusHttpListener(
exporterOptions => exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0,
listenerOptions => listenerOptions.Prefixes = new string[] { $"http://localhost:{port}/" })
.Build();
var process = Process.GetCurrentProcess();

View File

@ -1,27 +1,17 @@
Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions
Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions
OpenTelemetry.Exporter.PrometheusExporter
OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func<int, bool>
OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void
OpenTelemetry.Exporter.PrometheusExporter.PrometheusExporter(OpenTelemetry.Exporter.PrometheusExporterOptions options) -> void
OpenTelemetry.Exporter.PrometheusExporterOptions
OpenTelemetry.Exporter.PrometheusExporterOptions.HttpListenerPrefixes.get -> System.Collections.Generic.IReadOnlyCollection<string>
OpenTelemetry.Exporter.PrometheusExporterOptions.HttpListenerPrefixes.set -> void
OpenTelemetry.Exporter.PrometheusExporterOptions.PrometheusExporterOptions() -> void
OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> string
OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void
OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int
OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void
OpenTelemetry.Exporter.PrometheusExporterOptions.StartHttpListener.get -> bool
OpenTelemetry.Exporter.PrometheusExporterOptions.StartHttpListener.set -> void
OpenTelemetry.Exporter.Prometheus.AspNetCore.PrometheusExporterOptions
OpenTelemetry.Exporter.Prometheus.AspNetCore.PrometheusExporterOptions.PrometheusExporterOptions() -> void
OpenTelemetry.Exporter.Prometheus.AspNetCore.PrometheusExporterOptions.ScrapeEndpointPath.get -> string
OpenTelemetry.Exporter.Prometheus.AspNetCore.PrometheusExporterOptions.ScrapeEndpointPath.set -> void
OpenTelemetry.Exporter.Prometheus.AspNetCore.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int
OpenTelemetry.Exporter.Prometheus.AspNetCore.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void
OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions
override OpenTelemetry.Exporter.PrometheusExporter.Dispose(bool disposing) -> void
override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch<OpenTelemetry.Metrics.Metric> metrics) -> OpenTelemetry.ExportResult
static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) -> Microsoft.AspNetCore.Builder.IApplicationBuilder
static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, OpenTelemetry.Metrics.MeterProvider meterProvider, System.Func<Microsoft.AspNetCore.Http.HttpContext, bool> predicate, string path, System.Action<Microsoft.AspNetCore.Builder.IApplicationBuilder> configureBranchedPipeline) -> Microsoft.AspNetCore.Builder.IApplicationBuilder
static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string path) -> Microsoft.AspNetCore.Builder.IApplicationBuilder
static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, System.Func<Microsoft.AspNetCore.Http.HttpContext, bool> predicate) -> Microsoft.AspNetCore.Builder.IApplicationBuilder
static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action<OpenTelemetry.Exporter.PrometheusExporterOptions> configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder
static Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions.MapPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder
static Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions.MapPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string path) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder
static Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions.MapPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string path = null, OpenTelemetry.Metrics.MeterProvider meterProvider = null, System.Action<Microsoft.AspNetCore.Builder.IApplicationBuilder> configureBranchedPipeline = null) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder
static Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions.MapPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string path) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder
static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action<OpenTelemetry.Exporter.Prometheus.AspNetCore.PrometheusExporterOptions> configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder

View File

@ -0,0 +1,23 @@
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System.Runtime.CompilerServices;
#if SIGNED
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")]
#else
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests")]
#endif

View File

@ -2,6 +2,12 @@
## Unreleased
* Split up Prometheus projects based on its hosting mechanism, HttpListener and AspNetCore,
into their own projects and assemblies. The shared code for both hosting mechanism
now lives in the `OpenTelemetry.Exporter.Prometheus.Shared` project and will not
be released.
([#3430](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3430))
* Added `IEndpointRouteBuilder` extension methods to help with Prometheus
middleware configuration on ASP.NET Core
([#3295](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3295))

View File

@ -0,0 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<Description>AspNetCore middleware for hosting OpenTelemetry .NET Prometheus exporter</Description>
<PackageTags>$(PackageTags);prometheus;metrics</PackageTags>
<MinVerTagPrefix>core-</MinVerTagPrefix>
</PropertyGroup>
<!--Do not run ApiCompat as this package has never released a stable version.
Remove this property once we have released a stable version.-->
<PropertyGroup>
<RunApiCompat>false</RunApiCompat>
</PropertyGroup>
<PropertyGroup>
<DefineConstants>$(DefineConstants);PROMETHEUS_ASPNETCORE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\PrometheusCollectionManager.cs" Link="Includes/PrometheusCollectionManager.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\PrometheusExporter.cs" Link="Includes/PrometheusExporter.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\PrometheusExporterEventSource.cs" Link="Includes/PrometheusExporterEventSource.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\PrometheusExporterOptions.cs" Link="Includes/PrometheusExporterOptions.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\PrometheusSerializer.cs" Link="Includes/PrometheusSerializer.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\PrometheusSerializerExt.cs" Link="Includes/PrometheusSerializerExt.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\ExceptionExtensions.cs" Link="Includes\ExceptionExtensions.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\Guard.cs" Link="Includes\Guard.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>

View File

@ -19,8 +19,7 @@
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Exporter;
using OpenTelemetry.Exporter.Prometheus;
using OpenTelemetry.Exporter.Prometheus.AspNetCore;
using OpenTelemetry.Internal;
using OpenTelemetry.Metrics;
@ -93,8 +92,8 @@ namespace Microsoft.AspNetCore.Builder
/// <param name="app">The <see cref="IApplicationBuilder"/> to add
/// middleware to.</param>
/// <param name="meterProvider">Optional <see cref="MeterProvider"/>
/// containing a <see cref="PrometheusExporter"/> otherwise the primary
/// SDK provider will be resolved using application services.</param>
/// containing a Prometheus exporter otherwise the primary SDK provider
/// will be resolved using application services.</param>
/// <param name="predicate">Optional predicate for deciding if a given
/// <see cref="HttpContext"/> should be branched. If supplied <paramref
/// name="path"/> is ignored.</param>

View File

@ -20,8 +20,7 @@ using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Exporter;
using OpenTelemetry.Exporter.Prometheus;
using OpenTelemetry.Exporter.Prometheus.AspNetCore;
using OpenTelemetry.Internal;
using OpenTelemetry.Metrics;
@ -70,8 +69,8 @@ namespace Microsoft.AspNetCore.Builder
/// If not provided then <see cref="PrometheusExporterOptions.ScrapeEndpointPath"/>
/// is used.</param>
/// <param name="meterProvider">Optional <see cref="MeterProvider"/>
/// containing a <see cref="PrometheusExporter"/> otherwise the primary
/// SDK provider will be resolved using application services.</param>
/// containing a Prometheus exporter otherwise the primary SDK provider
/// will be resolved using application services.</param>
/// <param name="configureBranchedPipeline">Optional callback to
/// configure the branched pipeline. Called before registration of the
/// Prometheus middleware.</param>

View File

@ -15,11 +15,15 @@
// </copyright>
using System;
using OpenTelemetry.Exporter;
using OpenTelemetry.Exporter.Prometheus.AspNetCore;
using OpenTelemetry.Exporter.Prometheus.Shared;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Metrics
{
/// <summary>
/// Extension methods to simplify registering a PrometheusExporter.
/// </summary>
public static class PrometheusExporterMeterProviderBuilderExtensions
{
/// <summary>
@ -48,8 +52,10 @@ namespace OpenTelemetry.Metrics
configure?.Invoke(options);
var exporter = new PrometheusExporter(options);
var reader = new BaseExportingMetricReader(exporter);
reader.TemporalityPreference = MetricReaderTemporalityPreference.Cumulative;
var reader = new BaseExportingMetricReader(exporter)
{
TemporalityPreference = MetricReaderTemporalityPreference.Cumulative,
};
return builder.AddReader(reader);
}

View File

@ -19,10 +19,11 @@ using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using OpenTelemetry.Exporter.Prometheus.Shared;
using OpenTelemetry.Internal;
using OpenTelemetry.Metrics;
namespace OpenTelemetry.Exporter.Prometheus
namespace OpenTelemetry.Exporter.Prometheus.AspNetCore
{
/// <summary>
/// ASP.NET Core middleware for exposing a Prometheus metrics scraping endpoint.

View File

@ -1,18 +1,24 @@
# Prometheus Exporter for OpenTelemetry .NET
# Prometheus Exporter AspNetCore for OpenTelemetry .NET
[![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.Exporter.Prometheus.svg)](https://www.nuget.org/packages/OpenTelemetry.Exporter.Prometheus)
[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.Exporter.Prometheus.svg)](https://www.nuget.org/packages/OpenTelemetry.Exporter.Prometheus)
[![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.Exporter.Prometheus.AspNetCore.svg)](https://www.nuget.org/packages/OpenTelemetry.Exporter.Prometheus.AspNetCore)
[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.Exporter.Prometheus.AspNetCore.svg)](https://www.nuget.org/packages/OpenTelemetry.Exporter.Prometheus.AspNetCore)
An [OpenTelemetry Prometheus exporter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/prometheus.md)
for configuring an ASP.NET Core application with an endpoint for Prometheus
to scrape.
## Prerequisite
* [Get Prometheus](https://prometheus.io/docs/introduction/first_steps/)
## Steps to enable OpenTelemetry.Exporter.Prometheus
## Steps to enable OpenTelemetry.Exporter.Prometheus.AspNetCore
### Step 1: Install Package
Install
```shell
dotnet add package OpenTelemetry.Exporter.Prometheus
dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore
```
### Step 2: Configure OpenTelemetry MeterProvider
@ -32,14 +38,15 @@ dotnet add package OpenTelemetry.Exporter.Prometheus
register the Prometheus exporter.
```csharp
using var meterProvider = Sdk.CreateMeterProviderBuilder()
var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddPrometheusExporter()
.Build();
builder.Services.AddSingleton(meterProvider);
```
### Step 3: Configure Prometheus Scraping Endpoint
* On .NET Core 3.1+ register Prometheus scraping middleware using the
* Register Prometheus scraping middleware using the
`UseOpenTelemetryPrometheusScrapingEndpoint` extension:
```csharp
@ -72,46 +79,15 @@ dotnet add package OpenTelemetry.Exporter.Prometheus
}
```
* On .NET Framework an HTTP listener is automatically started which will respond
to scraping requests. See the [Configuration](#configuration) section for
details on the settings available. This may also be turned on in .NET Core (it
is OFF by default) when the ASP.NET Core pipeline is not available for
middleware registration.
## Configuration
The `PrometheusExporter` can be configured using the `PrometheusExporterOptions`
properties. Refer to
[`TestPrometheusExporter.cs`](../../examples/Console/TestPrometheusExporter.cs)
for example use.
### StartHttpListener
Set to `true` to start an HTTP listener which will respond to Prometheus scrape
requests using the [HttpListenerPrefixes](#httplistenerprefixes) and
[ScrapeEndpointPath](#scrapeendpointpath) options.
Defaults:
* On .NET Framework this is `true` by default.
* On .NET Core 3.1+ this is `false` by default. Users running ASP.NET Core
should use the `UseOpenTelemetryPrometheusScrapingEndpoint` extension to
register the scraping middleware instead of using the listener.
### HttpListenerPrefixes
Defines the prefixes which will be used by the listener when `StartHttpListener`
is `true`. The default value is `["http://localhost:9464/"]`. You may specify
multiple endpoints.
For details see:
[HttpListenerPrefixCollection.Add(String)](https://docs.microsoft.com/dotnet/api/system.net.httplistenerprefixcollection.add)
properties.
### ScrapeEndpointPath
Defines the path for the Prometheus scrape endpoint for
either the HTTP listener or the middleware registered by
Defines the path for the Prometheus scrape endpoint for the middleware
registered by
`UseOpenTelemetryPrometheusScrapingEndpoint`. Default value: `"/metrics"`.
### ScrapeResponseCacheDurationMilliseconds

View File

@ -0,0 +1,12 @@
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions.PrometheusExporterOptions() -> void
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions.ScrapeEndpointPath.get -> string
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions.ScrapeEndpointPath.set -> void
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.get -> System.Collections.Generic.IReadOnlyCollection<string>
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.set -> void
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.PrometheusHttpListenerOptions() -> void
OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions
static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action<OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions> configureExporterOptions = null, System.Action<OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions> configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder

View File

@ -0,0 +1,12 @@
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions.PrometheusExporterOptions() -> void
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions.ScrapeEndpointPath.get -> string
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions.ScrapeEndpointPath.set -> void
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.get -> System.Collections.Generic.IReadOnlyCollection<string>
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.set -> void
OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.PrometheusHttpListenerOptions() -> void
OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions
static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action<OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusExporterOptions> configureExporterOptions = null, System.Action<OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions> configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder

View File

@ -0,0 +1,94 @@
# Changelog
## Unreleased
* Split up Prometheus projects based on its hosting mechanism, HttpListener and AspNetCore,
into their own projects and assemblies. The shared code for both hosting mechanism
now lives in the `OpenTelemetry.Exporter.Prometheus.Shared` project and will not
be released.
([#3430](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3430))
## 1.3.0-rc.2
Released 2022-June-1
## 1.3.0-beta.2
Released 2022-May-16
## 1.3.0-beta.1
Released 2022-Apr-15
* Added `IApplicationBuilder` extension methods to help with Prometheus
middleware configuration on ASP.NET Core
([#3029](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3029))
* Changed Prometheus exporter to return 204 No Content and log a warning event
if there are no metrics to collect.
* Removes .NET Framework 4.6.1. The minimum .NET Framework
version supported is .NET 4.6.2. ([#3190](https://github.com/open-telemetry/opentelemetry-dotnet/issues/3190))
## 1.2.0-rc5
Released 2022-Apr-12
## 1.2.0-rc4
Released 2022-Mar-30
## 1.2.0-rc3
Released 2022-Mar-04
## 1.2.0-rc2
Released 2022-Feb-02
* Update default `httpListenerPrefixes` for PrometheusExporter to be `http://localhost:9464/`.
([#2783](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2783))
## 1.2.0-rc1
Released 2021-Nov-29
* Bug fix for handling Histogram with empty buckets.
([#2651](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2651))
## 1.2.0-beta2
Released 2021-Nov-19
* Added scrape endpoint response caching feature &
`ScrapeResponseCacheDurationMilliseconds` option
([#2610](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2610))
## 1.2.0-beta1
Released 2021-Oct-08
## 1.2.0-alpha4
Released 2021-Sep-23
## 1.2.0-alpha3
Released 2021-Sep-13
* Bug fixes
([#2289](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2289))
([#2309](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2309))
## 1.2.0-alpha2
Released 2021-Aug-24
* Revamped to support the new Metrics API/SDK.
Supports Counter, Gauge and Histogram.
## 1.0.0-rc1.1
Released 2020-Nov-17
* Initial release

View File

@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>netstandard2.0;net462</TargetFrameworks>
<Description>Stand-alone HttpListener for hosting OpenTelemetry .NET exporter</Description>
<PackageTags>$(PackageTags);prometheus;metrics</PackageTags>
<MinVerTagPrefix>core-</MinVerTagPrefix>
</PropertyGroup>
<!--Do not run ApiCompat as this package has never released a stable version.
Remove this property once we have released a stable version.-->
<PropertyGroup>
<RunApiCompat>false</RunApiCompat>
</PropertyGroup>
<PropertyGroup>
<DefineConstants>$(DefineConstants);PROMETHEUS_HTTPLISTENER</DefineConstants>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\PrometheusCollectionManager.cs" Link="Includes/PrometheusCollectionManager.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\PrometheusExporter.cs" Link="Includes/PrometheusExporter.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\PrometheusExporterEventSource.cs" Link="Includes/PrometheusExporterEventSource.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\PrometheusExporterOptions.cs" Link="Includes/PrometheusExporterOptions.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\PrometheusSerializer.cs" Link="Includes/PrometheusSerializer.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\PrometheusSerializerExt.cs" Link="Includes/PrometheusSerializerExt.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\ExceptionExtensions.cs" Link="Includes\ExceptionExtensions.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\Guard.cs" Link="Includes\Guard.cs" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,104 @@
// <copyright file="PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System;
using OpenTelemetry.Exporter.Prometheus.HttpListener;
using OpenTelemetry.Exporter.Prometheus.Shared;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Metrics
{
/// <summary>
/// Extension methods to simplify registering a PrometheusHttpListener.
/// </summary>
public static class PrometheusExporterHttpListenerMeterProviderBuilderExtensions
{
/// <summary>
/// Adds Prometheus exporter to MeterProviderBuilder.
/// </summary>
/// <param name="builder"><see cref="MeterProviderBuilder"/>builder to use.</param>
/// <param name="configureExporterOptions">Exporter configuration options.</param>
/// <param name="configureListenerOptions">HttpListener options.</param>
/// <returns>The instance of <see cref="MeterProviderBuilder"/>to chain calls.</returns>
public static MeterProviderBuilder AddPrometheusHttpListener(
this MeterProviderBuilder builder,
Action<PrometheusExporterOptions> configureExporterOptions = null,
Action<PrometheusHttpListenerOptions> configureListenerOptions = null)
{
Guard.ThrowIfNull(builder);
if (builder is IDeferredMeterProviderBuilder deferredMeterProviderBuilder)
{
return deferredMeterProviderBuilder.Configure((sp, builder) =>
{
AddPrometheusHttpListener(
builder,
sp.GetOptions<PrometheusExporterOptions>(),
sp.GetOptions<PrometheusHttpListenerOptions>(),
configureExporterOptions,
configureListenerOptions);
});
}
return AddPrometheusHttpListener(
builder,
new PrometheusExporterOptions(),
new PrometheusHttpListenerOptions(),
configureExporterOptions,
configureListenerOptions);
}
private static MeterProviderBuilder AddPrometheusHttpListener(
MeterProviderBuilder builder,
PrometheusExporterOptions exporterOptions,
PrometheusHttpListenerOptions listenerOptions,
Action<PrometheusExporterOptions> configureExporterOptions = null,
Action<PrometheusHttpListenerOptions> configureListenerOptions = null)
{
configureExporterOptions?.Invoke(exporterOptions);
configureListenerOptions?.Invoke(listenerOptions);
var exporter = new PrometheusExporter(exporterOptions);
var reader = new BaseExportingMetricReader(exporter)
{
TemporalityPreference = MetricReaderTemporalityPreference.Cumulative,
};
const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter HttpListener could not be started.";
try
{
var listener = new PrometheusHttpListener(exporter, listenerOptions);
exporter.OnDispose = () => listener.Dispose();
listener.Start();
}
catch (Exception ex)
{
try
{
reader.Dispose();
}
catch
{
}
throw new InvalidOperationException(HttpListenerStartFailureExceptionMessage, ex);
}
return builder.AddReader(reader);
}
}
}

View File

@ -1,4 +1,4 @@
// <copyright file="PrometheusExporterHttpServer.cs" company="OpenTelemetry Authors">
// <copyright file="PrometheusHttpListener.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -18,37 +18,36 @@ using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using OpenTelemetry.Exporter.Prometheus.Shared;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Exporter.Prometheus
namespace OpenTelemetry.Exporter.Prometheus.HttpListener
{
/// <summary>
/// An HTTP listener used to expose Prometheus metrics.
/// </summary>
internal sealed class PrometheusExporterHttpServer : IDisposable
internal sealed class PrometheusHttpListener : IDisposable
{
private readonly PrometheusExporter exporter;
private readonly HttpListener httpListener = new();
private readonly System.Net.HttpListener httpListener = new();
private readonly object syncObject = new();
private CancellationTokenSource tokenSource;
private Task workerThread;
/// <summary>
/// Initializes a new instance of the <see cref="PrometheusExporterHttpServer"/> class.
/// Initializes a new instance of the <see cref="PrometheusHttpListener"/> class.
/// </summary>
/// <param name="exporter">The <see cref="PrometheusExporter"/> instance.</param>
public PrometheusExporterHttpServer(PrometheusExporter exporter)
/// <param name="exporter"><see cref="PrometheusExporter"/>The exporter instance.</param>
/// <param name="options"><see cref="PrometheusHttpListenerOptions"/>The configured HttpListener options.</param>
public PrometheusHttpListener(PrometheusExporter exporter, PrometheusHttpListenerOptions options)
{
Guard.ThrowIfNull(exporter);
this.exporter = exporter;
if ((exporter.Options.HttpListenerPrefixes?.Count ?? 0) <= 0)
if ((options.Prefixes?.Count ?? 0) <= 0)
{
throw new ArgumentException("No HttpListenerPrefixes were specified on PrometheusExporterOptions.");
throw new ArgumentException("No Prefixes were specified on PrometheusHttpListenerOptions.");
}
string path = exporter.Options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath;
this.exporter = exporter;
string path = this.exporter.Options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath;
if (!path.StartsWith("/"))
{
path = $"/{path}";
@ -59,16 +58,16 @@ namespace OpenTelemetry.Exporter.Prometheus
path = $"{path}/";
}
foreach (string prefix in exporter.Options.HttpListenerPrefixes)
foreach (string prefix in options.Prefixes)
{
this.httpListener.Prefixes.Add($"{prefix.TrimEnd('/')}{path}");
}
}
/// <summary>
/// Start Http Server.
/// Start the HttpListener.
/// </summary>
/// <param name="token">An optional <see cref="CancellationToken"/> that can be used to stop the HTTP server.</param>
/// <param name="token">An optional <see cref="CancellationToken"/> that can be used to stop the HTTP listener.</param>
public void Start(CancellationToken token = default)
{
lock (this.syncObject)
@ -88,7 +87,7 @@ namespace OpenTelemetry.Exporter.Prometheus
}
/// <summary>
/// Stop exporter.
/// Gracefully stop the PrometheusHttpListener.
/// </summary>
public void Stop()
{
@ -108,9 +107,10 @@ namespace OpenTelemetry.Exporter.Prometheus
/// <inheritdoc/>
public void Dispose()
{
this.Stop();
if (this.httpListener != null && this.httpListener.IsListening)
{
this.Stop();
this.httpListener.Close();
}
}

View File

@ -0,0 +1,56 @@
// <copyright file="PrometheusHttpListenerOptions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System;
using System.Collections.Generic;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Exporter.Prometheus.HttpListener
{
/// <summary>
/// <see cref="PrometheusHttpListener"/> options.
/// </summary>
public class PrometheusHttpListenerOptions
{
private IReadOnlyCollection<string> prefixes = new string[] { "http://localhost:9464/" };
/// <summary>
/// Gets or sets the prefixes to use for the http listener.
/// Default value: http://localhost:9464/.
/// </summary>
public IReadOnlyCollection<string> Prefixes
{
get => this.prefixes;
set
{
Guard.ThrowIfNull(value);
foreach (string inputUri in value)
{
if (!(Uri.TryCreate(inputUri, UriKind.Absolute, out var uri) &&
(uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)))
{
throw new ArgumentException(
"Prometheus HttpListener prefix path should be a valid URI with http/https scheme.",
nameof(this.prefixes));
}
}
this.prefixes = value;
}
}
}
}

View File

@ -0,0 +1,72 @@
# Prometheus Exporter HttpListener for OpenTelemetry .NET
[![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.Exporter.Prometheus.HttpListener.svg)](https://www.nuget.org/packages/OpenTelemetry.Exporter.Prometheus.HttpListener)
[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.Exporter.Prometheus.HttpListener.svg)](https://www.nuget.org/packages/OpenTelemetry.Exporter.Prometheus.HttpListener)
An [OpenTelemetry Prometheus exporter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/prometheus.md)
that configures an [HttpListener](https://docs.microsoft.com/dotnet/api/system.net.httplistener)
instance for Prometheus to scrape.
## Prerequisite
* [Get Prometheus](https://prometheus.io/docs/introduction/first_steps/)
## Steps to enable OpenTelemetry.Exporter.Prometheus.HttpListener
### Step 1: Install Package
Install
```shell
dotnet add package OpenTelemetry.Exporter.Prometheus.HttpListener
```
### Step 2: Add PrometheusHttpListener
Add and configure `PrometheusHttpListener` with `PrometheusExporterOptions` as
the first argument and `PrometheusHttpListenerOptions` as the second argument.
For example:
```csharp
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter(MyMeter.Name)
.AddPrometheusHttpListener(
exporterOptions => exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0,
listenerOptions => listenerOptions.Prefixes = new string[] { "http://localhost:9464/" })
.Build();
```
### Prefixes
Defines the prefixes which will be used by the listener. The default value is `["http://localhost:9464/"]`.
You may specify multiple endpoints.
For details see:
[HttpListenerPrefixCollection.Add(String)](https://docs.microsoft.com/dotnet/api/system.net.httplistenerprefixcollection.add)
### ScrapeEndpointPath
Defines the path for the Prometheus scrape endpoint for by
`UseOpenTelemetryPrometheusScrapingEndpoint`. Default value: `"/metrics"`.
### ScrapeResponseCacheDurationMilliseconds
Configures scrape endpoint response caching. Multiple scrape requests within the
cache duration time period will receive the same previously generated response.
The default value is `10000` (10 seconds). Set to `0` to disable response
caching.
## Troubleshooting
This component uses an
[EventSource](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventsource)
with the name "OpenTelemetry-Exporter-Prometheus" for its internal logging.
Please refer to [SDK
troubleshooting](../OpenTelemetry/README.md#troubleshooting) for instructions on
seeing these internal logs.
## References
* [OpenTelemetry Project](https://opentelemetry.io/)
* [Prometheus](https://prometheus.io)

View File

@ -0,0 +1,6 @@
OpenTelemetry.Exporter.Prometheus.Shared.PrometheusExporterOptions
OpenTelemetry.Exporter.Prometheus.Shared.PrometheusExporterOptions.PrometheusExporterOptions() -> void
OpenTelemetry.Exporter.Prometheus.Shared.PrometheusExporterOptions.ScrapeEndpointPath.get -> string
OpenTelemetry.Exporter.Prometheus.Shared.PrometheusExporterOptions.ScrapeEndpointPath.set -> void
OpenTelemetry.Exporter.Prometheus.Shared.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int
OpenTelemetry.Exporter.Prometheus.Shared.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void

View File

@ -0,0 +1,6 @@
OpenTelemetry.Exporter.Prometheus.Shared.PrometheusExporterOptions
OpenTelemetry.Exporter.Prometheus.Shared.PrometheusExporterOptions.PrometheusExporterOptions() -> void
OpenTelemetry.Exporter.Prometheus.Shared.PrometheusExporterOptions.ScrapeEndpointPath.get -> string
OpenTelemetry.Exporter.Prometheus.Shared.PrometheusExporterOptions.ScrapeEndpointPath.set -> void
OpenTelemetry.Exporter.Prometheus.Shared.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int
OpenTelemetry.Exporter.Prometheus.Shared.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void

View File

@ -18,8 +18,8 @@ using System.Runtime.CompilerServices;
#if SIGNED
[assembly: InternalsVisibleTo("Benchmarks, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Shared.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")]
#else
[assembly: InternalsVisibleTo("Benchmarks")]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Tests")]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Shared.Tests")]
#endif

View File

@ -3,13 +3,8 @@
<PropertyGroup>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>netcoreapp3.1;net462</TargetFrameworks>
<Description>Prometheus exporter for OpenTelemetry .NET</Description>
<Description>Prometheus exporter shared code for both Prometheus exporter HttpListener and Prometheus exporter AspNetCore</Description>
<PackageTags>$(PackageTags);prometheus;metrics</PackageTags>
<MinVerTagPrefix>core-</MinVerTagPrefix>
</PropertyGroup>
<PropertyGroup>
<NoWarn>$(NoWarn),1591</NoWarn>
</PropertyGroup>
<!--Do not run ApiCompat as this package has never released a stable version.

View File

@ -20,7 +20,7 @@ using System.Threading;
using System.Threading.Tasks;
using OpenTelemetry.Metrics;
namespace OpenTelemetry.Exporter.Prometheus
namespace OpenTelemetry.Exporter.Prometheus.Shared
{
internal sealed class PrometheusCollectionManager
{

View File

@ -15,23 +15,26 @@
// </copyright>
using System;
using OpenTelemetry.Exporter.Prometheus;
#if PROMETHEUS_ASPNETCORE
using OpenTelemetry.Exporter.Prometheus.AspNetCore;
#elif PROMETHEUS_HTTPLISTENER
using OpenTelemetry.Exporter.Prometheus.HttpListener;
#endif
using OpenTelemetry.Metrics;
namespace OpenTelemetry.Exporter
namespace OpenTelemetry.Exporter.Prometheus.Shared
{
/// <summary>
/// Exporter of OpenTelemetry metrics to Prometheus.
/// </summary>
[ExportModes(ExportModes.Pull)]
public class PrometheusExporter : BaseExporter<Metric>, IPullMetricExporter
internal sealed class PrometheusExporter : BaseExporter<Metric>, IPullMetricExporter
{
internal const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started.";
internal readonly PrometheusExporterOptions Options;
private readonly PrometheusExporterHttpServer metricsHttpServer;
private Func<int, bool> funcCollect;
private Func<Batch<Metric>, ExportResult> funcExport;
private bool disposed;
private bool disposed = false;
/// <summary>
/// Initializes a new instance of the <see cref="PrometheusExporter"/> class.
@ -40,23 +43,12 @@ namespace OpenTelemetry.Exporter
public PrometheusExporter(PrometheusExporterOptions options)
{
this.Options = options;
if (options.StartHttpListener)
{
try
{
this.metricsHttpServer = new PrometheusExporterHttpServer(this);
this.metricsHttpServer.Start();
}
catch (Exception ex)
{
throw new InvalidOperationException(HttpListenerStartFailureExceptionMessage, ex);
}
}
this.CollectionManager = new PrometheusCollectionManager(this);
}
/// <summary>
/// Gets or sets the Collect delegate.
/// </summary>
public Func<int, bool> Collect
{
get => this.funcCollect;
@ -69,20 +61,24 @@ namespace OpenTelemetry.Exporter
set => this.funcExport = value;
}
internal Action OnDispose { get; set; }
internal PrometheusCollectionManager CollectionManager { get; }
/// <inheritdoc/>
public override ExportResult Export(in Batch<Metric> metrics)
{
return this.OnExport(metrics);
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
this.metricsHttpServer?.Dispose();
this.OnDispose?.Invoke();
}
this.disposed = true;

View File

@ -18,7 +18,7 @@ using System;
using System.Diagnostics.Tracing;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Exporter.Prometheus
namespace OpenTelemetry.Exporter.Prometheus.Shared
{
/// <summary>
/// EventSource events emitted from the project.

View File

@ -15,13 +15,18 @@
// </copyright>
using System;
using System.Collections.Generic;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Exporter
#if PROMETHEUS_ASPNETCORE
namespace OpenTelemetry.Exporter.Prometheus.AspNetCore
#elif PROMETHEUS_HTTPLISTENER
namespace OpenTelemetry.Exporter.Prometheus.HttpListener
#else
namespace OpenTelemetry.Exporter.Prometheus.Shared
#endif
{
/// <summary>
/// <see cref="PrometheusExporter"/> options.
/// Prometheus exporter options.
/// </summary>
public class PrometheusExporterOptions
{
@ -29,47 +34,6 @@ namespace OpenTelemetry.Exporter
internal Func<DateTimeOffset> GetUtcNowDateTimeOffset = () => DateTimeOffset.UtcNow;
private int scrapeResponseCacheDurationMilliseconds = 10 * 1000;
private IReadOnlyCollection<string> httpListenerPrefixes = new string[] { "http://localhost:9464/" };
#if NETCOREAPP3_1_OR_GREATER
/// <summary>
/// Gets or sets a value indicating whether or not an http listener
/// should be started. Default value: False.
/// </summary>
public bool StartHttpListener { get; set; }
#else
/// <summary>
/// Gets or sets a value indicating whether or not an http listener
/// should be started. Default value: True.
/// </summary>
public bool StartHttpListener { get; set; } = true;
#endif
/// <summary>
/// Gets or sets the prefixes to use for the http listener. Default
/// value: http://localhost:9464/.
/// </summary>
public IReadOnlyCollection<string> HttpListenerPrefixes
{
get => this.httpListenerPrefixes;
set
{
Guard.ThrowIfNull(value);
foreach (string inputUri in value)
{
if (!(Uri.TryCreate(inputUri, UriKind.Absolute, out var uri) &&
(uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)))
{
throw new ArgumentException(
"Prometheus server path should be a valid URI with http/https scheme.",
nameof(this.httpListenerPrefixes));
}
}
this.httpListenerPrefixes = value;
}
}
/// <summary>
/// Gets or sets the path to use for the scraping endpoint. Default value: /metrics.

View File

@ -22,7 +22,7 @@ using System.Globalization;
using System.Runtime.CompilerServices;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Exporter.Prometheus
namespace OpenTelemetry.Exporter.Prometheus.Shared
{
/// <summary>
/// Basic PrometheusSerializer which has no OpenTelemetry dependency.

View File

@ -16,7 +16,7 @@
using OpenTelemetry.Metrics;
namespace OpenTelemetry.Exporter.Prometheus
namespace OpenTelemetry.Exporter.Prometheus.Shared
{
/// <summary>
/// OpenTelemetry additions to the PrometheusSerializer.

View File

@ -1,18 +0,0 @@
OpenTelemetry.Exporter.PrometheusExporter
OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func<int, bool>
OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void
OpenTelemetry.Exporter.PrometheusExporter.PrometheusExporter(OpenTelemetry.Exporter.PrometheusExporterOptions options) -> void
OpenTelemetry.Exporter.PrometheusExporterOptions
OpenTelemetry.Exporter.PrometheusExporterOptions.HttpListenerPrefixes.get -> System.Collections.Generic.IReadOnlyCollection<string>
OpenTelemetry.Exporter.PrometheusExporterOptions.HttpListenerPrefixes.set -> void
OpenTelemetry.Exporter.PrometheusExporterOptions.PrometheusExporterOptions() -> void
OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> string
OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void
OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int
OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void
OpenTelemetry.Exporter.PrometheusExporterOptions.StartHttpListener.get -> bool
OpenTelemetry.Exporter.PrometheusExporterOptions.StartHttpListener.set -> void
OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions
override OpenTelemetry.Exporter.PrometheusExporter.Dispose(bool disposing) -> void
override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch<OpenTelemetry.Metrics.Metric> metrics) -> OpenTelemetry.ExportResult
static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action<OpenTelemetry.Exporter.PrometheusExporterOptions> configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder

View File

@ -18,9 +18,12 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("OpenTelemetry.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.InMemory" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Extensions.EventSource" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Shared" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.HttpListener" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Extensions.Hosting.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Extensions.Serilog" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)]

View File

@ -26,9 +26,9 @@
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.InMemory\OpenTelemetry.Exporter.InMemory.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj" Aliases="Jaeger" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj" Aliases="OpenTelemetryProtocol" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus\OpenTelemetry.Exporter.Prometheus.csproj" Aliases="Prometheus" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Zipkin\OpenTelemetry.Exporter.Zipkin.csproj" Aliases="Zipkin" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.AspNetCore\OpenTelemetry.Instrumentation.AspNetCore.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.Http\OpenTelemetry.Instrumentation.Http.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\OpenTelemetry.Exporter.Prometheus.Shared.csproj" />
</ItemGroup>
</Project>

View File

@ -14,15 +14,13 @@
// limitations under the License.
// </copyright>
extern alias Prometheus;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using BenchmarkDotNet.Attributes;
using OpenTelemetry;
using OpenTelemetry.Exporter.Prometheus.Shared;
using OpenTelemetry.Metrics;
using OpenTelemetry.Tests;
using Prometheus::OpenTelemetry.Exporter.Prometheus;
namespace Benchmarks.Exporter
{

View File

@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Unit test project for Prometheus Exporter for OpenTelemetry</Description>
<Description>Unit test project for Prometheus Exporter AspNetCore for OpenTelemetry</Description>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>net6.0;netcoreapp3.1</TargetFrameworks>
<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
@ -19,12 +20,8 @@
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.InMemory\OpenTelemetry.Exporter.InMemory.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus\OpenTelemetry.Exporter.Prometheus.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.Hosting\OpenTelemetry.Extensions.Hosting.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="6.0.0" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.AspNetCore\OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">

View File

@ -21,11 +21,12 @@ using System.Linq;
#endif
using System.Threading;
using System.Threading.Tasks;
using OpenTelemetry.Exporter.Prometheus.Shared;
using OpenTelemetry.Metrics;
using OpenTelemetry.Tests;
using Xunit;
namespace OpenTelemetry.Exporter.Prometheus.Tests
namespace OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests
{
public sealed class PrometheusCollectionManagerTests
{

View File

@ -31,7 +31,7 @@ using OpenTelemetry.Metrics;
using OpenTelemetry.Tests;
using Xunit;
namespace OpenTelemetry.Exporter.Prometheus.Tests
namespace OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests
{
public sealed class PrometheusExporterMiddlewareTests
{
@ -224,10 +224,6 @@ namespace OpenTelemetry.Exporter.Prometheus.Tests
.AddPrometheusExporter(o =>
{
configureOptions?.Invoke(o);
if (o.StartHttpListener)
{
throw new InvalidOperationException("StartHttpListener should be false on .NET Core 3.1+.");
}
}));
}

View File

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Unit test project for Prometheus Exporter HttpListener for OpenTelemetry</Description>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>net462</TargetFrameworks>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPkgVer)" />
<PackageReference Include="Moq" Version="$(MoqPkgVer)" />
<PackageReference Include="xunit" Version="$(XUnitPkgVer)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitRunnerVisualStudioPkgVer)">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<DotNetCliToolReference Include="dotnet-xunit" Version="$(DotNetXUnitCliVer)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.HttpListener\OpenTelemetry.Exporter.Prometheus.HttpListener.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests\Shared\Utils.cs" Link="Includes\Utils.cs" />
</ItemGroup>
</Project>

View File

@ -1,4 +1,4 @@
// <copyright file="PrometheusExporterHttpServerTests.cs" company="OpenTelemetry Authors">
// <copyright file="PrometheusExporterHttpListenerTests.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -24,24 +24,12 @@ using OpenTelemetry.Metrics;
using OpenTelemetry.Tests;
using Xunit;
namespace OpenTelemetry.Exporter.Prometheus.Tests
namespace OpenTelemetry.Exporter.Prometheus.HttpListener.Tests
{
public class PrometheusExporterHttpServerTests
public class PrometheusExporterHttpListenerTests
{
private readonly string meterName = Utils.GetCurrentMethodName();
[Fact]
public async Task PrometheusExporterHttpServerIntegration()
{
await this.RunPrometheusExporterHttpServerIntegrationTest();
}
[Fact]
public async Task PrometheusExporterHttpServerIntegration_NoMetrics()
{
await this.RunPrometheusExporterHttpServerIntegrationTest(skipMetrics: true);
}
[Theory]
[InlineData("http://example.com")]
[InlineData("https://example.com")]
@ -50,10 +38,7 @@ namespace OpenTelemetry.Exporter.Prometheus.Tests
public void ServerEndpointSanityCheckPositiveTest(params string[] uris)
{
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
.AddPrometheusExporter(opt =>
{
opt.HttpListenerPrefixes = uris;
})
.AddPrometheusHttpListener(null, listenerOptions => listenerOptions.Prefixes = uris)
.Build();
}
@ -67,10 +52,7 @@ namespace OpenTelemetry.Exporter.Prometheus.Tests
try
{
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
.AddPrometheusExporter(opt =>
{
opt.HttpListenerPrefixes = uris;
})
.AddPrometheusHttpListener(null, listenerOptions => listenerOptions.Prefixes = uris)
.Build();
}
catch (Exception ex)
@ -79,66 +61,45 @@ namespace OpenTelemetry.Exporter.Prometheus.Tests
{
Assert.Equal("System.ArgumentException", ex.GetType().ToString());
#if NETFRAMEWORK
Assert.Equal("Prometheus server path should be a valid URI with http/https scheme.\r\nParameter name: httpListenerPrefixes", ex.Message);
Assert.Equal("Prometheus HttpListener prefix path should be a valid URI with http/https scheme.\r\nParameter name: prefixes", ex.Message);
#else
Assert.Equal("Prometheus server path should be a valid URI with http/https scheme. (Parameter 'httpListenerPrefixes')", ex.Message);
Assert.Equal("Prometheus HttpListener prefix path should be a valid URI with http/https scheme. (Parameter 'prefixes')", ex.Message);
#endif
}
}
}
[Fact]
public async Task PrometheusExporterHttpServerIntegration()
{
await this.RunPrometheusExporterHttpServerIntegrationTest();
}
[Fact]
public async Task PrometheusExporterHttpServerIntegration_NoMetrics()
{
await this.RunPrometheusExporterHttpServerIntegrationTest(skipMetrics: true);
}
private async Task RunPrometheusExporterHttpServerIntegrationTest(bool skipMetrics = false)
{
Random random = new Random();
int retryAttempts = 5;
int port = 0;
int retryCount = 5;
MeterProvider provider;
string address = null;
MeterProvider provider;
using var meter = new Meter(this.meterName);
while (true)
while (retryAttempts-- != 0)
{
try
{
port = random.Next(2000, 5000);
provider = Sdk.CreateMeterProviderBuilder()
.AddMeter(meter.Name)
.AddPrometheusExporter(o =>
{
#if NETFRAMEWORK
bool expectedDefaultState = true;
#else
bool expectedDefaultState = false;
#endif
if (o.StartHttpListener != expectedDefaultState)
{
throw new InvalidOperationException("StartHttpListener value is unexpected.");
}
port = random.Next(2000, 5000);
address = $"http://localhost:{port}/";
if (!o.StartHttpListener)
{
o.StartHttpListener = true;
}
address = $"http://localhost:{port}/";
o.HttpListenerPrefixes = new string[] { address };
})
.Build();
break;
}
catch (Exception ex)
{
if (ex.Message != PrometheusExporter.HttpListenerStartFailureExceptionMessage)
{
throw;
}
if (retryCount-- <= 0)
{
throw new InvalidOperationException("HttpListener could not be started.");
}
}
provider = Sdk.CreateMeterProviderBuilder()
.AddMeter(meter.Name)
.AddPrometheusHttpListener(null, listenerOptions => listenerOptions.Prefixes = new string[] { address })
.Build();
}
var tags = new KeyValuePair<string, object>[]
@ -155,7 +116,6 @@ namespace OpenTelemetry.Exporter.Prometheus.Tests
}
using HttpClient client = new HttpClient();
using var response = await client.GetAsync($"{address}metrics").ConfigureAwait(false);
if (!skipMetrics)

View File

@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Unit test project of Prometheus exporter shared code for both Prometheus exporter HttpListener and Prometheus Exporter AspNetCore</Description>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPkgVer)" />
<PackageReference Include="Moq" Version="$(MoqPkgVer)" />
<PackageReference Include="xunit" Version="$(XUnitPkgVer)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitRunnerVisualStudioPkgVer)">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<DotNetCliToolReference Include="dotnet-xunit" Version="$(DotNetXUnitCliVer)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.InMemory\OpenTelemetry.Exporter.InMemory.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.Shared\OpenTelemetry.Exporter.Prometheus.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests\Shared\Utils.cs" Link="Includes\Utils.cs" />
</ItemGroup>
</Project>

View File

@ -21,7 +21,7 @@ using OpenTelemetry.Metrics;
using OpenTelemetry.Tests;
using Xunit;
namespace OpenTelemetry.Exporter.Prometheus.Tests
namespace OpenTelemetry.Exporter.Prometheus.Shared.Tests
{
public sealed class PrometheusSerializerTests
{

View File

@ -8,7 +8,7 @@
<ItemGroup>
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests.Stress\Skeleton.cs" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus\OpenTelemetry.Exporter.Prometheus.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.HttpListener\OpenTelemetry.Exporter.Prometheus.HttpListener.csproj" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="[6.0.0,)" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="$(RuntimeInstrumentationPkgVer)" />
</ItemGroup>

View File

@ -14,7 +14,7 @@
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests\Shared\Utils.cs" Link="Includes\Utils.cs" />
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests.Stress\Skeleton.cs" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus\OpenTelemetry.Exporter.Prometheus.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.HttpListener\OpenTelemetry.Exporter.Prometheus.HttpListener.csproj" />
</ItemGroup>
</Project>

View File

@ -46,12 +46,9 @@ public partial class Program
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter(TestMeter.Name)
.AddPrometheusExporter(options =>
{
options.StartHttpListener = true;
options.HttpListenerPrefixes = new string[] { $"http://localhost:9185/" };
options.ScrapeResponseCacheDurationMilliseconds = 0;
})
.AddPrometheusHttpListener(
exporterOptions => exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0,
listenerOptions => listenerOptions.Prefixes = new string[] { $"http://localhost:9185/" })
.Build();
Stress(prometheusPort: 9184);

View File

@ -10,6 +10,6 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus\OpenTelemetry.Exporter.Prometheus.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.HttpListener\OpenTelemetry.Exporter.Prometheus.HttpListener.csproj" />
</ItemGroup>
</Project>

View File

@ -41,7 +41,7 @@ Running (concurrency = 1), press <Esc> to stop...
```
The stress test metrics are exposed via
[PrometheusExporter](../../src/OpenTelemetry.Exporter.Prometheus/README.md),
[Prometheus HttpListener](../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md),
which can be accessed via
[http://localhost:9184/metrics/](http://localhost:9184/metrics/).

View File

@ -75,12 +75,9 @@ public partial class Program
using var meterProvider = prometheusPort != 0 ? Sdk.CreateMeterProviderBuilder()
.AddMeter(meter.Name)
.AddRuntimeInstrumentation()
.AddPrometheusExporter(options =>
{
options.StartHttpListener = true;
options.HttpListenerPrefixes = new string[] { $"http://localhost:{prometheusPort}/" };
options.ScrapeResponseCacheDurationMilliseconds = 0;
})
.AddPrometheusHttpListener(
exporterOptions => exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0,
listenerOptions => listenerOptions.Prefixes = new string[] { $"http://localhost:{prometheusPort}/" })
.Build() : null;
var statistics = new long[concurrency];