Skip to content

Commit

Permalink
Prometheus Exporter - New .MapPrometheusScrapingEndpoint() Extension …
Browse files Browse the repository at this point in the history
…Method (#3295)
  • Loading branch information
hannahchan authored Jun 7, 2022
1 parent c90ab4a commit efc55d5
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
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
Expand All @@ -20,4 +21,7 @@ static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensio
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 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
4 changes: 4 additions & 0 deletions src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

* Added `IEndpointRouteBuilder` extension methods to help with Prometheus
middleware configuration on ASP.NET Core
([#3295](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3295))

## 1.3.0-rc.2

Released 2022-June-1
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// <copyright file="PrometheusExporterEndpointRouteBuilderExtensions.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>

#if NETCOREAPP3_1_OR_GREATER

using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Exporter;
using OpenTelemetry.Exporter.Prometheus;
using OpenTelemetry.Internal;
using OpenTelemetry.Metrics;

namespace Microsoft.AspNetCore.Builder
{
/// <summary>
/// Provides extension methods for <see cref="IEndpointRouteBuilder"/> to add
/// Prometheus scraping endpoint.
/// </summary>
public static class PrometheusExporterEndpointRouteBuilderExtensions
{
/// <summary>
/// Adds OpenTelemetry Prometheus scraping endpoint middleware to an
/// <see cref="IEndpointRouteBuilder"/> instance.
/// </summary>
/// <remarks>Note: A branched pipeline is created for the route
/// specified by <see
/// cref="PrometheusExporterOptions.ScrapeEndpointPath"/>.</remarks>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add
/// middleware to.</param>
/// <returns>A convention routes for the Prometheus scraping endpoint.</returns>
public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEndpointRouteBuilder endpoints)
=> MapPrometheusScrapingEndpoint(endpoints, path: null, meterProvider: null, configureBranchedPipeline: null);

/// <summary>
/// Adds OpenTelemetry Prometheus scraping endpoint middleware to an
/// <see cref="IEndpointRouteBuilder"/> instance.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add
/// middleware to.</param>
/// <param name="path">The path to use for the branched pipeline.</param>
/// <returns>A convention routes for the Prometheus scraping endpoint.</returns>
public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEndpointRouteBuilder endpoints, string path)
{
Guard.ThrowIfNull(path);
return MapPrometheusScrapingEndpoint(endpoints, path, meterProvider: null, configureBranchedPipeline: null);
}

/// <summary>
/// Adds OpenTelemetry Prometheus scraping endpoint middleware to an
/// <see cref="IEndpointRouteBuilder"/> instance.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add
/// middleware to.</param>
/// <param name="path">Optional path to use for the branched pipeline.
/// 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>
/// <param name="configureBranchedPipeline">Optional callback to
/// configure the branched pipeline. Called before registration of the
/// Prometheus middleware.</param>
/// <returns>A convention routes for the Prometheus scraping endpoint.</returns>
public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(
this IEndpointRouteBuilder endpoints,
string path = null,
MeterProvider meterProvider = null,
Action<IApplicationBuilder> configureBranchedPipeline = null)
{
var builder = endpoints.CreateApplicationBuilder();

// Note: Order is important here. MeterProvider is accessed before
// GetOptions<PrometheusExporterOptions> so that any changes made to
// PrometheusExporterOptions in deferred AddPrometheusExporter
// configure actions are reflected.
meterProvider ??= endpoints.ServiceProvider.GetRequiredService<MeterProvider>();

if (path == null)
{
var options = endpoints.ServiceProvider.GetOptions<PrometheusExporterOptions>();
path = options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath;
}

if (!path.StartsWith("/"))
{
path = $"/{path}";
}

configureBranchedPipeline?.Invoke(builder);

builder.UseMiddleware<PrometheusExporterMiddleware>(meterProvider);

return endpoints.Map(new PathString(path), builder.Build());
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,42 @@ public Task PrometheusExporterMiddlewareIntegration_NoMetrics()
skipMetrics: true);
}

[Fact]
public Task PrometheusExporterMiddlewareIntegration_MapEndpoint()
{
return RunPrometheusExporterMiddlewareIntegrationTest(
"/metrics",
app => app.UseRouting().UseEndpoints(builder => builder.MapPrometheusScrapingEndpoint()),
services => services.AddRouting());
}

[Fact]
public Task PrometheusExporterMiddlewareIntegration_MapEndpoint_WithPathOverride()
{
return RunPrometheusExporterMiddlewareIntegrationTest(
"/metrics_path",
app => app.UseRouting().UseEndpoints(builder => builder.MapPrometheusScrapingEndpoint("metrics_path")),
services => services.AddRouting());
}

[Fact]
public async Task PrometheusExporterMiddlewareIntegration_MapEndpoint_WithMeterProvider()
{
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter(MeterName)
.AddPrometheusExporter()
.Build();

await RunPrometheusExporterMiddlewareIntegrationTest(
"/metrics",
app => app.UseRouting().UseEndpoints(builder => builder.MapPrometheusScrapingEndpoint(
path: null,
meterProvider: meterProvider,
configureBranchedPipeline: null)),
services => services.AddRouting(),
registerMeterProvider: false).ConfigureAwait(false);
}

private static async Task RunPrometheusExporterMiddlewareIntegrationTest(
string path,
Action<IApplicationBuilder> configure,
Expand Down

0 comments on commit efc55d5

Please sign in to comment.