Skip to content

Commit

Permalink
Prometheus: Expand UseOpenTelemetryPrometheusScrapingEndpoint extensi…
Browse files Browse the repository at this point in the history
…on (#3029)
  • Loading branch information
CodeBlanch authored Apr 13, 2022
1 parent f3b7b80 commit 26c3e0c
Show file tree
Hide file tree
Showing 5 changed files with 286 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@ 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 Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, OpenTelemetry.Metrics.MeterProvider meterProvider = null) -> Microsoft.AspNetCore.Builder.IApplicationBuilder
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
6 changes: 5 additions & 1 deletion src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

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

## 1.2.0-rc5

Released 2022-Apr-12
Expand All @@ -19,7 +23,7 @@ Released 2022-Mar-04
Released 2022-Feb-02

* Update default `httpListenerPrefixes` for PrometheusExporter to be `http://localhost:9464/`.
([2783](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2783))
([#2783](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2783))

## 1.2.0-rc1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,133 @@
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="IApplicationBuilder"/> to add Prometheus Scraper Endpoint.
/// Provides extension methods for <see cref="IApplicationBuilder"/> to add
/// Prometheus scraping endpoint.
/// </summary>
public static class PrometheusExporterApplicationBuilderExtensions
{
/// <summary>
/// Adds OpenTelemetry Prometheus scraping endpoint middleware to an
/// <see cref="IApplicationBuilder"/> instance.
/// </summary>
/// <remarks>Note: A branched pipeline is created for the route
/// specified by <see
/// cref="PrometheusExporterOptions.ScrapeEndpointPath"/>.</remarks>
/// <param name="app">The <see cref="IApplicationBuilder"/> to add
/// middleware to.</param>
/// <returns>A reference to the original <see
/// cref="IApplicationBuilder"/> for chaining calls.</returns>
public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app)
=> UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: null, path: null, configureBranchedPipeline: null);

/// <summary>
/// Adds OpenTelemetry Prometheus scraping endpoint middleware to an
/// <see cref="IApplicationBuilder"/> instance.
/// </summary>
/// <remarks>Note: A branched pipeline is created for the supplied
/// <paramref name="path"/>.</remarks>
/// <param name="app">The <see cref="IApplicationBuilder"/> to add
/// middleware to.</param>
/// <param name="path">Path to use for the branched pipeline.</param>
/// <returns>A reference to the original <see
/// cref="IApplicationBuilder"/> for chaining calls.</returns>
public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app, string path)
{
Guard.ThrowIfNull(path);
return UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: null, path: path, configureBranchedPipeline: null);
}

/// <summary>
/// Adds OpenTelemetry Prometheus scraping endpoint middleware to an
/// <see cref="IApplicationBuilder"/> instance.
/// </summary>
/// <remarks>Note: A branched pipeline is created for the supplied
/// <paramref name="predicate"/>.</remarks>
/// <param name="app">The <see cref="IApplicationBuilder"/> to add
/// middleware to.</param>
/// <param name="predicate">Predicate for deciding if a given
/// <see cref="HttpContext"/> should be branched.</param>
/// <returns>A reference to the original <see
/// cref="IApplicationBuilder"/> for chaining calls.</returns>
public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app, Func<HttpContext, bool> predicate)
{
Guard.ThrowIfNull(predicate);
return UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: predicate, path: null, configureBranchedPipeline: null);
}

/// <summary>
/// Adds OpenTelemetry Prometheus scraping endpoint middleware to an
/// <see cref="IApplicationBuilder"/> instance.
/// </summary>
/// <remarks>Note: A branched pipeline is created based on the <paramref
/// name="predicate"/> or <paramref name="path"/>. If neither <paramref
/// name="predicate"/> nor <paramref name="path"/> are provided then
/// <see cref="PrometheusExporterOptions.ScrapeEndpointPath"/> is
/// used.</remarks>
/// <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>
/// <returns>A reference to the <see cref="IApplicationBuilder"/> instance after the operation has completed.</returns>
public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app, MeterProvider meterProvider = null)
/// <param name="predicate">Optional predicate for deciding if a given
/// <see cref="HttpContext"/> should be branched. If supplied <paramref
/// name="path"/> is ignored.</param>
/// <param name="path">Optional path to use for the branched pipeline.
/// Ignored if <paramref name="predicate"/> is supplied.</param>
/// <param name="configureBranchedPipeline">Optional callback to
/// configure the branched pipeline. Called before registration of the
/// Prometheus middleware.</param>
/// <returns>A reference to the original <see
/// cref="IApplicationBuilder"/> for chaining calls.</returns>
public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(
this IApplicationBuilder app,
MeterProvider meterProvider,
Func<HttpContext, bool> predicate,
string path,
Action<IApplicationBuilder> configureBranchedPipeline)
{
var options = app.ApplicationServices.GetOptions<PrometheusExporterOptions>();
// 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 ??= app.ApplicationServices.GetRequiredService<MeterProvider>();

string path = options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath;
if (!path.StartsWith("/"))
if (predicate == null)
{
path = $"/{path}";
if (path == null)
{
var options = app.ApplicationServices.GetOptions<PrometheusExporterOptions>();

path = options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath;
}

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

return app.Map(
new PathString(path),
builder =>
{
configureBranchedPipeline?.Invoke(builder);
builder.UseMiddleware<PrometheusExporterMiddleware>(meterProvider);
});
}

return app.Map(
new PathString(path),
builder => builder.UseMiddleware<PrometheusExporterMiddleware>(meterProvider ?? app.ApplicationServices.GetRequiredService<MeterProvider>()));
return app.MapWhen(
context => predicate(context),
builder =>
{
configureBranchedPipeline?.Invoke(builder);
builder.UseMiddleware<PrometheusExporterMiddleware>(meterProvider);
});
}
}
}
Expand Down
20 changes: 19 additions & 1 deletion src/OpenTelemetry.Exporter.Prometheus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,26 @@ dotnet add package OpenTelemetry.Exporter.Prometheus
```csharp
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseOpenTelemetryPrometheusScrapingEndpoint();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
```

Overloads of the `UseOpenTelemetryPrometheusScrapingEndpoint` extension are
provided to change the path or for more advanced configuration a predicate
function can be used:

```csharp
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseOpenTelemetryPrometheusScrapingEndpoint(
context => context.Request.Path == "/internal/metrics"
&& context.Connection.LocalPort == 5067);
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
Expand Down
Loading

0 comments on commit 26c3e0c

Please sign in to comment.