Skip to content

Commit efc55d5

Browse files
authored
Prometheus Exporter - New .MapPrometheusScrapingEndpoint() Extension Method (#3295)
1 parent c90ab4a commit efc55d5

File tree

4 files changed

+157
-1
lines changed

4 files changed

+157
-1
lines changed

src/OpenTelemetry.Exporter.Prometheus/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions
2+
Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions
23
OpenTelemetry.Exporter.PrometheusExporter
34
OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func<int, bool>
45
OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void
@@ -20,4 +21,7 @@ static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensio
2021
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
2122
static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string path) -> Microsoft.AspNetCore.Builder.IApplicationBuilder
2223
static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, System.Func<Microsoft.AspNetCore.Http.HttpContext, bool> predicate) -> Microsoft.AspNetCore.Builder.IApplicationBuilder
23-
static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action<OpenTelemetry.Exporter.PrometheusExporterOptions> configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder
24+
static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action<OpenTelemetry.Exporter.PrometheusExporterOptions> configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder
25+
static Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions.MapPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder
26+
static Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions.MapPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string path) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder
27+
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

src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
* Added `IEndpointRouteBuilder` extension methods to help with Prometheus
6+
middleware configuration on ASP.NET Core
7+
([#3295](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3295))
8+
59
## 1.3.0-rc.2
610

711
Released 2022-June-1
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// <copyright file="PrometheusExporterEndpointRouteBuilderExtensions.cs" company="OpenTelemetry Authors">
2+
// Copyright The OpenTelemetry Authors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// </copyright>
16+
17+
#if NETCOREAPP3_1_OR_GREATER
18+
19+
using System;
20+
using Microsoft.AspNetCore.Http;
21+
using Microsoft.AspNetCore.Routing;
22+
using Microsoft.Extensions.DependencyInjection;
23+
using OpenTelemetry.Exporter;
24+
using OpenTelemetry.Exporter.Prometheus;
25+
using OpenTelemetry.Internal;
26+
using OpenTelemetry.Metrics;
27+
28+
namespace Microsoft.AspNetCore.Builder
29+
{
30+
/// <summary>
31+
/// Provides extension methods for <see cref="IEndpointRouteBuilder"/> to add
32+
/// Prometheus scraping endpoint.
33+
/// </summary>
34+
public static class PrometheusExporterEndpointRouteBuilderExtensions
35+
{
36+
/// <summary>
37+
/// Adds OpenTelemetry Prometheus scraping endpoint middleware to an
38+
/// <see cref="IEndpointRouteBuilder"/> instance.
39+
/// </summary>
40+
/// <remarks>Note: A branched pipeline is created for the route
41+
/// specified by <see
42+
/// cref="PrometheusExporterOptions.ScrapeEndpointPath"/>.</remarks>
43+
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add
44+
/// middleware to.</param>
45+
/// <returns>A convention routes for the Prometheus scraping endpoint.</returns>
46+
public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEndpointRouteBuilder endpoints)
47+
=> MapPrometheusScrapingEndpoint(endpoints, path: null, meterProvider: null, configureBranchedPipeline: null);
48+
49+
/// <summary>
50+
/// Adds OpenTelemetry Prometheus scraping endpoint middleware to an
51+
/// <see cref="IEndpointRouteBuilder"/> instance.
52+
/// </summary>
53+
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add
54+
/// middleware to.</param>
55+
/// <param name="path">The path to use for the branched pipeline.</param>
56+
/// <returns>A convention routes for the Prometheus scraping endpoint.</returns>
57+
public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEndpointRouteBuilder endpoints, string path)
58+
{
59+
Guard.ThrowIfNull(path);
60+
return MapPrometheusScrapingEndpoint(endpoints, path, meterProvider: null, configureBranchedPipeline: null);
61+
}
62+
63+
/// <summary>
64+
/// Adds OpenTelemetry Prometheus scraping endpoint middleware to an
65+
/// <see cref="IEndpointRouteBuilder"/> instance.
66+
/// </summary>
67+
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add
68+
/// middleware to.</param>
69+
/// <param name="path">Optional path to use for the branched pipeline.
70+
/// If not provided then <see cref="PrometheusExporterOptions.ScrapeEndpointPath"/>
71+
/// is used.</param>
72+
/// <param name="meterProvider">Optional <see cref="MeterProvider"/>
73+
/// containing a <see cref="PrometheusExporter"/> otherwise the primary
74+
/// SDK provider will be resolved using application services.</param>
75+
/// <param name="configureBranchedPipeline">Optional callback to
76+
/// configure the branched pipeline. Called before registration of the
77+
/// Prometheus middleware.</param>
78+
/// <returns>A convention routes for the Prometheus scraping endpoint.</returns>
79+
public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(
80+
this IEndpointRouteBuilder endpoints,
81+
string path = null,
82+
MeterProvider meterProvider = null,
83+
Action<IApplicationBuilder> configureBranchedPipeline = null)
84+
{
85+
var builder = endpoints.CreateApplicationBuilder();
86+
87+
// Note: Order is important here. MeterProvider is accessed before
88+
// GetOptions<PrometheusExporterOptions> so that any changes made to
89+
// PrometheusExporterOptions in deferred AddPrometheusExporter
90+
// configure actions are reflected.
91+
meterProvider ??= endpoints.ServiceProvider.GetRequiredService<MeterProvider>();
92+
93+
if (path == null)
94+
{
95+
var options = endpoints.ServiceProvider.GetOptions<PrometheusExporterOptions>();
96+
path = options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath;
97+
}
98+
99+
if (!path.StartsWith("/"))
100+
{
101+
path = $"/{path}";
102+
}
103+
104+
configureBranchedPipeline?.Invoke(builder);
105+
106+
builder.UseMiddleware<PrometheusExporterMiddleware>(meterProvider);
107+
108+
return endpoints.Map(new PathString(path), builder.Build());
109+
}
110+
}
111+
}
112+
#endif

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,42 @@ public Task PrometheusExporterMiddlewareIntegration_NoMetrics()
167167
skipMetrics: true);
168168
}
169169

170+
[Fact]
171+
public Task PrometheusExporterMiddlewareIntegration_MapEndpoint()
172+
{
173+
return RunPrometheusExporterMiddlewareIntegrationTest(
174+
"/metrics",
175+
app => app.UseRouting().UseEndpoints(builder => builder.MapPrometheusScrapingEndpoint()),
176+
services => services.AddRouting());
177+
}
178+
179+
[Fact]
180+
public Task PrometheusExporterMiddlewareIntegration_MapEndpoint_WithPathOverride()
181+
{
182+
return RunPrometheusExporterMiddlewareIntegrationTest(
183+
"/metrics_path",
184+
app => app.UseRouting().UseEndpoints(builder => builder.MapPrometheusScrapingEndpoint("metrics_path")),
185+
services => services.AddRouting());
186+
}
187+
188+
[Fact]
189+
public async Task PrometheusExporterMiddlewareIntegration_MapEndpoint_WithMeterProvider()
190+
{
191+
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
192+
.AddMeter(MeterName)
193+
.AddPrometheusExporter()
194+
.Build();
195+
196+
await RunPrometheusExporterMiddlewareIntegrationTest(
197+
"/metrics",
198+
app => app.UseRouting().UseEndpoints(builder => builder.MapPrometheusScrapingEndpoint(
199+
path: null,
200+
meterProvider: meterProvider,
201+
configureBranchedPipeline: null)),
202+
services => services.AddRouting(),
203+
registerMeterProvider: false).ConfigureAwait(false);
204+
}
205+
170206
private static async Task RunPrometheusExporterMiddlewareIntegrationTest(
171207
string path,
172208
Action<IApplicationBuilder> configure,

0 commit comments

Comments
 (0)