From 93b6bcd87bbc443e5877a50afad005f895bcf8b0 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Wed, 6 Jul 2022 15:45:11 -0700 Subject: [PATCH 01/52] added 3 src projects and 3 test projects --- OpenTelemetry.sln | 36 ++ .../.publicApi/net462/PublicAPI.Shipped.txt | 0 .../.publicApi/net462/PublicAPI.Unshipped.txt | 0 .../netcoreapp3.1/PublicAPI.Shipped.txt | 0 .../netcoreapp3.1/PublicAPI.Unshipped.txt | 9 + ...etry.Exporter.Prometheus.AspNetCore.csproj | 41 ++ ...eusExporterApplicationBuilderExtensions.cs | 154 +++++++ ...sExporterEndpointRouteBuilderExtensions.cs | 112 +++++ .../PrometheusExporterMiddleware.cs | 105 +++++ .../README.md | 106 +++++ .../.publicApi/net462/PublicAPI.Shipped.txt | 0 .../.publicApi/net462/PublicAPI.Unshipped.txt | 7 + ...ry.Exporter.Prometheus.HttpListener.csproj | 44 ++ ...pListenerMeterProviderBuilderExtensions.cs | 84 ++++ .../PrometheusHttpListener.cs | 205 ++++++++++ .../PrometheusHttpListenerOptions.cs | 53 +++ .../README.md | 71 ++++ .../.publicApi/net462/PublicAPI.Shipped.txt | 0 .../.publicApi/net462/PublicAPI.Unshipped.txt | 12 + .../netcoreapp3.1/PublicAPI.Shipped.txt | 0 .../netcoreapp3.1/PublicAPI.Unshipped.txt | 12 + .../AssemblyInfo.cs | 29 ++ .../CHANGELOG.md | 92 +++++ ...elemetry.Exporter.Prometheus.Shared.csproj | 39 ++ .../PrometheusCollectionManager.cs | 240 +++++++++++ .../PrometheusExporter.cs | 63 +++ .../PrometheusExporterEventSource.cs | 84 ++++ ...sExporterMeterProviderBuilderExtensions.cs | 59 +++ .../PrometheusExporterOptions.cs | 54 +++ .../PrometheusSerializer.cs | 308 ++++++++++++++ .../PrometheusSerializerExt.cs | 200 +++++++++ .../README.md | 138 +++++++ src/OpenTelemetry/AssemblyInfo.cs | 4 + ...xporter.Prometheus.AspNetCore.Tests.csproj | 35 ++ .../PrometheusExporterMiddlewareTests.cs | 293 +++++++++++++ ...orter.Prometheus.HttpListener.Tests.csproj | 31 ++ .../PrometheusExporterHttpListenerTests.cs | 137 +++++++ ...ry.Exporter.Prometheus.Shared.Tests.csproj | 33 ++ .../PrometheusCollectionManagerTests.cs | 161 ++++++++ .../PrometheusSerializerTests.cs | 387 ++++++++++++++++++ 40 files changed, 3438 insertions(+) create mode 100644 src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net462/PublicAPI.Shipped.txt create mode 100644 src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net462/PublicAPI.Unshipped.txt create mode 100644 src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Shipped.txt create mode 100644 src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt create mode 100644 src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj create mode 100644 src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterApplicationBuilderExtensions.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterEndpointRouteBuilderExtensions.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMiddleware.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md create mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Shipped.txt create mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt create mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj create mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListenerOptions.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Shipped.txt create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Shipped.txt create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/AssemblyInfo.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/CHANGELOG.md create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterMeterProviderBuilderExtensions.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs create mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/README.md create mode 100644 test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests.csproj create mode 100644 test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusExporterMiddlewareTests.cs create mode 100644 test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests.csproj create mode 100644 test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusExporterHttpListenerTests.cs create mode 100644 test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj create mode 100644 test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/PrometheusCollectionManagerTests.cs create mode 100644 test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/PrometheusSerializerTests.cs diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln index 8e4c8bca6b8..5e602b37fe6 100644 --- a/OpenTelemetry.sln +++ b/OpenTelemetry.sln @@ -229,6 +229,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "correlation", "docs\logs\co EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Tests.Stress.Logs", "test\OpenTelemetry.Tests.Stress.Logs\OpenTelemetry.Tests.Stress.Logs.csproj", "{4298057B-24E0-47B3-BB76-C17E81AF6B39}" 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 @@ -463,6 +475,30 @@ Global {4298057B-24E0-47B3-BB76-C17E81AF6B39}.Debug|Any CPU.Build.0 = Debug|Any CPU {4298057B-24E0-47B3-BB76-C17E81AF6B39}.Release|Any CPU.ActiveCfg = Release|Any CPU {4298057B-24E0-47B3-BB76-C17E81AF6B39}.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 diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net462/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net462/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..7e944dd0810 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -0,0 +1,9 @@ +Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions +Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions +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 predicate, string path, System.Action 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 predicate) -> Microsoft.AspNetCore.Builder.IApplicationBuilder +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 = null, OpenTelemetry.Metrics.MeterProvider meterProvider = null, System.Action configureBranchedPipeline = null) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder +static Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions.MapPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string path) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj new file mode 100644 index 00000000000..a61fee79a66 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj @@ -0,0 +1,41 @@ + + + + + netcoreapp3.1 + Prometheus exporter for AspNetCore for OpenTelemetry .NET + $(PackageTags);prometheus;metrics + core- + + + + $(NoWarn),1591 + + + + + false + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterApplicationBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterApplicationBuilderExtensions.cs new file mode 100644 index 00000000000..364c430b27d --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterApplicationBuilderExtensions.cs @@ -0,0 +1,154 @@ +// +// 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. +// + +#if NETCOREAPP3_1_OR_GREATER + +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using OpenTelemetry.Exporter; +using OpenTelemetry.Exporter.Prometheus.AspNetCore; +using OpenTelemetry.Internal; +using OpenTelemetry.Metrics; + +namespace Microsoft.AspNetCore.Builder +{ + /// + /// Provides extension methods for to add + /// Prometheus scraping endpoint. + /// + public static class PrometheusExporterApplicationBuilderExtensions + { + /// + /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an + /// instance. + /// + /// Note: A branched pipeline is created for the route + /// specified by . + /// The to add + /// middleware to. + /// A reference to the original for chaining calls. + public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app) + => UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: null, path: null, configureBranchedPipeline: null); + + /// + /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an + /// instance. + /// + /// Note: A branched pipeline is created for the supplied + /// . + /// The to add + /// middleware to. + /// Path to use for the branched pipeline. + /// A reference to the original for chaining calls. + public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app, string path) + { + Guard.ThrowIfNull(path); + return UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: null, path: path, configureBranchedPipeline: null); + } + + /// + /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an + /// instance. + /// + /// Note: A branched pipeline is created for the supplied + /// . + /// The to add + /// middleware to. + /// Predicate for deciding if a given + /// should be branched. + /// A reference to the original for chaining calls. + public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app, Func predicate) + { + Guard.ThrowIfNull(predicate); + return UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: predicate, path: null, configureBranchedPipeline: null); + } + + /// + /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an + /// instance. + /// + /// Note: A branched pipeline is created based on the or . If neither nor are provided then + /// is + /// used. + /// The to add + /// middleware to. + /// Optional + /// containing a otherwise the primary + /// SDK provider will be resolved using application services. + /// Optional predicate for deciding if a given + /// should be branched. If supplied is ignored. + /// Optional path to use for the branched pipeline. + /// Ignored if is supplied. + /// Optional callback to + /// configure the branched pipeline. Called before registration of the + /// Prometheus middleware. + /// A reference to the original for chaining calls. + public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint( + this IApplicationBuilder app, + MeterProvider meterProvider, + Func predicate, + string path, + Action configureBranchedPipeline) + { + // Note: Order is important here. MeterProvider is accessed before + // GetOptions so that any changes made to + // PrometheusExporterOptions in deferred AddPrometheusExporter + // configure actions are reflected. + meterProvider ??= app.ApplicationServices.GetRequiredService(); + + if (predicate == null) + { + if (path == null) + { + var options = app.ApplicationServices.GetOptions(); + + path = options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath; + } + + if (!path.StartsWith("/")) + { + path = $"/{path}"; + } + + return app.Map( + new PathString(path), + builder => + { + configureBranchedPipeline?.Invoke(builder); + builder.UseMiddleware(meterProvider); + }); + } + + return app.MapWhen( + context => predicate(context), + builder => + { + configureBranchedPipeline?.Invoke(builder); + builder.UseMiddleware(meterProvider); + }); + } + } +} +#endif diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterEndpointRouteBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterEndpointRouteBuilderExtensions.cs new file mode 100644 index 00000000000..ed964fb7951 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterEndpointRouteBuilderExtensions.cs @@ -0,0 +1,112 @@ +// +// 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. +// + +#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.AspNetCore; +using OpenTelemetry.Internal; +using OpenTelemetry.Metrics; + +namespace Microsoft.AspNetCore.Builder +{ + /// + /// Provides extension methods for to add + /// Prometheus scraping endpoint. + /// + public static class PrometheusExporterEndpointRouteBuilderExtensions + { + /// + /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an + /// instance. + /// + /// Note: A branched pipeline is created for the route + /// specified by . + /// The to add + /// middleware to. + /// A convention routes for the Prometheus scraping endpoint. + public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEndpointRouteBuilder endpoints) + => MapPrometheusScrapingEndpoint(endpoints, path: null, meterProvider: null, configureBranchedPipeline: null); + + /// + /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an + /// instance. + /// + /// The to add + /// middleware to. + /// The path to use for the branched pipeline. + /// A convention routes for the Prometheus scraping endpoint. + public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEndpointRouteBuilder endpoints, string path) + { + Guard.ThrowIfNull(path); + return MapPrometheusScrapingEndpoint(endpoints, path, meterProvider: null, configureBranchedPipeline: null); + } + + /// + /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an + /// instance. + /// + /// The to add + /// middleware to. + /// Optional path to use for the branched pipeline. + /// If not provided then + /// is used. + /// Optional + /// containing a otherwise the primary + /// SDK provider will be resolved using application services. + /// Optional callback to + /// configure the branched pipeline. Called before registration of the + /// Prometheus middleware. + /// A convention routes for the Prometheus scraping endpoint. + public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint( + this IEndpointRouteBuilder endpoints, + string path = null, + MeterProvider meterProvider = null, + Action configureBranchedPipeline = null) + { + var builder = endpoints.CreateApplicationBuilder(); + + // Note: Order is important here. MeterProvider is accessed before + // GetOptions so that any changes made to + // PrometheusExporterOptions in deferred AddPrometheusExporter + // configure actions are reflected. + meterProvider ??= endpoints.ServiceProvider.GetRequiredService(); + + if (path == null) + { + var options = endpoints.ServiceProvider.GetOptions(); + path = options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath; + } + + if (!path.StartsWith("/")) + { + path = $"/{path}"; + } + + configureBranchedPipeline?.Invoke(builder); + + builder.UseMiddleware(meterProvider); + + return endpoints.Map(new PathString(path), builder.Build()); + } + } +} +#endif diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMiddleware.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMiddleware.cs new file mode 100644 index 00000000000..99bc08ba44b --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMiddleware.cs @@ -0,0 +1,105 @@ +// +// 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. +// + +#if NETCOREAPP3_1_OR_GREATER +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using OpenTelemetry.Internal; +using OpenTelemetry.Metrics; + +namespace OpenTelemetry.Exporter.Prometheus.AspNetCore +{ + /// + /// ASP.NET Core middleware for exposing a Prometheus metrics scraping endpoint. + /// + internal sealed class PrometheusExporterMiddleware + { + private readonly PrometheusExporter exporter; + + /// + /// Initializes a new instance of the class. + /// + /// . + /// . + public PrometheusExporterMiddleware(MeterProvider meterProvider, RequestDelegate next) + { + Guard.ThrowIfNull(meterProvider); + + if (!meterProvider.TryFindExporter(out PrometheusExporter exporter)) + { + throw new ArgumentException("A PrometheusExporter could not be found configured on the provided MeterProvider."); + } + + this.exporter = exporter; + } + + internal PrometheusExporterMiddleware(PrometheusExporter exporter) + { + this.exporter = exporter; + } + + /// + /// Invoke. + /// + /// context. + /// Task. + public async Task InvokeAsync(HttpContext httpContext) + { + Debug.Assert(httpContext != null, "httpContext should not be null"); + + var response = httpContext.Response; + + try + { + var collectionResponse = await this.exporter.CollectionManager.EnterCollect().ConfigureAwait(false); + try + { + if (collectionResponse.View.Count > 0) + { + response.StatusCode = 200; + response.Headers.Add("Last-Modified", collectionResponse.GeneratedAtUtc.ToString("R")); + response.ContentType = "text/plain; charset=utf-8; version=0.0.4"; + + await response.Body.WriteAsync(collectionResponse.View.Array, 0, collectionResponse.View.Count).ConfigureAwait(false); + } + else + { + // It's not expected to have no metrics to collect, but it's not necessarily a failure, either. + response.StatusCode = 204; + PrometheusExporterEventSource.Log.NoMetrics(); + } + } + finally + { + this.exporter.CollectionManager.ExitCollect(); + } + } + catch (Exception ex) + { + PrometheusExporterEventSource.Log.FailedExport(ex); + if (!response.HasStarted) + { + response.StatusCode = 500; + } + } + + this.exporter.OnExport = null; + } + } +} +#endif diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md new file mode 100644 index 00000000000..0e9b528bb11 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md @@ -0,0 +1,106 @@ +# Prometheus Exporter AspNetCore for OpenTelemetry .NET + +## Prerequisite + +* [Get Prometheus](https://prometheus.io/docs/introduction/first_steps/) + +## Steps to enable OpenTelemetry.Exporter.Prometheus.AspNetCore + +### Step 1: Install Package + +Install + +```shell +dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore +``` + +### Step 2: Configure OpenTelemetry MeterProvider + +* When using OpenTelemetry.Extensions.Hosting package on .NET Core 3.1+: + + ```csharp + services.AddOpenTelemetryMetrics(builder => + { + builder.AddPrometheusExporter(); + }); + ``` + +* Or configure directly: + + Call the `AddPrometheusExporter` `MeterProviderBuilder` extension to + register the Prometheus exporter. + + ```csharp + using var meterProvider = Sdk.CreateMeterProviderBuilder() + .AddPrometheusExporter() + .Build(); + ``` + +### Step 3: Configure Prometheus Scraping Endpoint + +* On .NET Core 3.1+ register Prometheus scraping middleware using the + `UseOpenTelemetryPrometheusScrapingEndpoint` extension: + + ```csharp + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + 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(); + }); + } + ``` + +## Configuration + +The `PrometheusExporter` can be configured using the `PrometheusExporterOptions` +properties. Refer to +[`TestPrometheusExporter.cs`](../../examples/Console/TestPrometheusExporter.cs) +for example use. + +### ScrapeEndpointPath + +Defines the path for the Prometheus scrape endpoint for +either the HTTP listener or the middleware registered 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) diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..346555d9a3a --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt @@ -0,0 +1,7 @@ +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Dispose() -> void +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.PrometheusHttpListener(OpenTelemetry.Exporter.PrometheusExporter exporter, OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions options) -> void +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Start(System.Threading.CancellationToken token = default(System.Threading.CancellationToken)) -> void +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Stop() -> void +OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions +static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder \ No newline at end of file diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj new file mode 100644 index 00000000000..ea186defdc9 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj @@ -0,0 +1,44 @@ + + + + + net462 + Prometheus exporter HttpListener for OpenTelemetry .NET + $(PackageTags);prometheus;metrics + core- + + + + $(NoWarn),1591 + + + + $(NoWarn),1702 + + + + $(NoWarn),RS0016 + + + + + false + + + + + + + + + + + + + + + + + + diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs new file mode 100644 index 00000000000..f8504baa03d --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs @@ -0,0 +1,84 @@ +// +// 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. +// + +using System; +using OpenTelemetry.Exporter; +using OpenTelemetry.Exporter.Prometheus.HttpListener; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Metrics +{ + public static class PrometheusExporterHttpListenerMeterProviderBuilderExtensions + { + public static MeterProviderBuilder AddPrometheusHttpListener( + this MeterProviderBuilder builder, + Action configureExporterOptions = null, + Action configureListenerOptions = null) + { + Guard.ThrowIfNull(builder); + + if (builder is IDeferredMeterProviderBuilder deferredMeterProviderBuilder) + { + return deferredMeterProviderBuilder.Configure((sp, builder) => + { + AddPrometheusHttpListener( + builder, + sp.GetOptions(), + sp.GetOptions(), + configureExporterOptions, + configureListenerOptions); + }); + } + + return AddPrometheusHttpListener( + builder, + new PrometheusExporterOptions(), + new PrometheusHttpListenerOptions(), + configureExporterOptions, + configureListenerOptions); + } + + private static MeterProviderBuilder AddPrometheusHttpListener( + MeterProviderBuilder builder, + PrometheusExporterOptions exporterOptions, + PrometheusHttpListenerOptions listenerOptions, + Action configureExporterOptions = null, + Action configureListenerOptions = null) + { + configureExporterOptions?.Invoke(exporterOptions); + var exporter = new PrometheusExporter(exporterOptions); + var reader = new BaseExportingMetricReader(exporter) + { + TemporalityPreference = MetricReaderTemporalityPreference.Cumulative, + }; + + configureListenerOptions?.Invoke(listenerOptions); + var listener = new PrometheusHttpListener(exporter, listenerOptions); + + const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started."; + try + { + listener.Start(); + } + catch (Exception ex) + { + throw new InvalidOperationException(HttpListenerStartFailureExceptionMessage, ex); + } + + return builder.AddReader(reader); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs new file mode 100644 index 00000000000..4cbee0a2a8a --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs @@ -0,0 +1,205 @@ +// +// 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. +// + +using System; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Exporter.Prometheus.HttpListener +{ + public sealed class PrometheusHttpListener : IDisposable + { + private readonly PrometheusExporter exporter; + private readonly System.Net.HttpListener httpListener = new(); + private readonly object syncObject = new(); + + private CancellationTokenSource tokenSource; + private Task workerThread; + private bool disposed; + + /// + /// Initializes a new instance of the class. + /// + /// The exporter instance. + /// The configured HttpListener options. + public PrometheusHttpListener(PrometheusExporter exporter, PrometheusHttpListenerOptions options) + { + Guard.ThrowIfNull(exporter); + + if ((options.Prefixes?.Count ?? 0) <= 0) + { + throw new ArgumentException("No Prefixes were specified on PrometheusHttpListenerOptions."); + } + + this.exporter = exporter; + string path = this.exporter.Options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath; + if (!path.StartsWith("/")) + { + path = $"/{path}"; + } + + if (!path.EndsWith("/")) + { + path = $"{path}/"; + } + + foreach (string prefix in options.Prefixes) + { + this.httpListener.Prefixes.Add($"{prefix.TrimEnd('/')}{path}"); + } + } + + /// + /// Start the HttpListener. + /// + /// An optional that can be used to stop the HTTP listener. + public void Start(CancellationToken token = default) + { + lock (this.syncObject) + { + if (this.tokenSource != null) + { + return; + } + + // link the passed in token if not null + this.tokenSource = token == default ? + new CancellationTokenSource() : + CancellationTokenSource.CreateLinkedTokenSource(token); + + this.workerThread = Task.Factory.StartNew(this.WorkerProc, default, TaskCreationOptions.LongRunning, TaskScheduler.Default); + } + } + + /// + /// Stop the HttpListener. + /// + public void Stop() + { + lock (this.syncObject) + { + if (this.tokenSource == null) + { + return; + } + + this.tokenSource.Cancel(); + this.workerThread.Wait(); + this.tokenSource = null; + } + } + + public void Dispose() + { + this.Dispose(true); + } + + private void Dispose(bool disposing) + { + if (!this.disposed) + { + if (disposing && this.httpListener != null && this.httpListener.IsListening) + { + this.Stop(); + this.httpListener.Close(); + this.Dispose(); + } + + this.disposed = true; + } + } + + private void WorkerProc() + { + this.httpListener.Start(); + + try + { + using var scope = SuppressInstrumentationScope.Begin(); + while (!this.tokenSource.IsCancellationRequested) + { + var ctxTask = this.httpListener.GetContextAsync(); + ctxTask.Wait(this.tokenSource.Token); + var ctx = ctxTask.Result; + + Task.Run(() => this.ProcessRequestAsync(ctx)); + } + } + catch (OperationCanceledException ex) + { + PrometheusExporterEventSource.Log.CanceledExport(ex); + } + finally + { + try + { + this.httpListener.Stop(); + this.httpListener.Close(); + } + catch (Exception exFromFinally) + { + PrometheusExporterEventSource.Log.FailedShutdown(exFromFinally); + } + } + } + + private async Task ProcessRequestAsync(HttpListenerContext context) + { + try + { + var collectionResponse = await this.exporter.CollectionManager.EnterCollect().ConfigureAwait(false); + try + { + context.Response.Headers.Add("Server", string.Empty); + if (collectionResponse.View.Count > 0) + { + context.Response.StatusCode = 200; + context.Response.Headers.Add("Last-Modified", collectionResponse.GeneratedAtUtc.ToString("R")); + context.Response.ContentType = "text/plain; charset=utf-8; version=0.0.4"; + + await context.Response.OutputStream.WriteAsync(collectionResponse.View.Array, 0, collectionResponse.View.Count).ConfigureAwait(false); + } + else + { + // It's not expected to have no metrics to collect, but it's not necessarily a failure, either. + context.Response.StatusCode = 204; + PrometheusExporterEventSource.Log.NoMetrics(); + } + } + finally + { + this.exporter.CollectionManager.ExitCollect(); + } + } + catch (Exception ex) + { + PrometheusExporterEventSource.Log.FailedExport(ex); + + context.Response.StatusCode = 500; + } + + try + { + context.Response.Close(); + } + catch + { + } + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListenerOptions.cs b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListenerOptions.cs new file mode 100644 index 00000000000..88f58ad29bb --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListenerOptions.cs @@ -0,0 +1,53 @@ +// +// 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. +// + +using System; +using System.Collections.Generic; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Exporter.Prometheus.HttpListener +{ + public class PrometheusHttpListenerOptions + { + private IReadOnlyCollection prefixes = new string[] { "http://localhost:9464/" }; + + /// + /// Gets or sets the prefixes to use for the http listener. Default + /// value: http://localhost:9464/. + /// + public IReadOnlyCollection 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 server path should be a valid URI with http/https scheme.", + nameof(this.prefixes)); + } + } + + this.prefixes = value; + } + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md new file mode 100644 index 00000000000..2dd8193505f --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md @@ -0,0 +1,71 @@ +# Prometheus Exporter HttpListener for OpenTelemetry .NET + +## 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.HttpListenerPrefixes = new string[] { "http://localhost:9464/" }; + }) + .Build(); +``` + +#### HttpListenerPrefixes + +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) diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..9b2a2be8c33 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt @@ -0,0 +1,12 @@ +OpenTelemetry.Exporter.PrometheusExporter +OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func +OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void +OpenTelemetry.Exporter.PrometheusExporterOptions +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.Metrics.PrometheusExporterMeterProviderBuilderExtensions +override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult +static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..9b2a2be8c33 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -0,0 +1,12 @@ +OpenTelemetry.Exporter.PrometheusExporter +OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func +OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void +OpenTelemetry.Exporter.PrometheusExporterOptions +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.Metrics.PrometheusExporterMeterProviderBuilderExtensions +override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult +static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/AssemblyInfo.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/AssemblyInfo.cs new file mode 100644 index 00000000000..aa9d15cbc50 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/AssemblyInfo.cs @@ -0,0 +1,29 @@ +// +// 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. +// + +using System.Runtime.CompilerServices; + +#if SIGNED +[assembly: InternalsVisibleTo("Benchmarks, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Shared.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.HttpListener, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] +#else +[assembly: InternalsVisibleTo("Benchmarks")] +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Shared.Tests")] +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore")] +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.HttpListener")] +#endif diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/CHANGELOG.md b/src/OpenTelemetry.Exporter.Prometheus.Shared/CHANGELOG.md new file mode 100644 index 00000000000..5787a17c1db --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/CHANGELOG.md @@ -0,0 +1,92 @@ +# Changelog + +## 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 + +## 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 diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj new file mode 100644 index 00000000000..d2757f77cf0 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj @@ -0,0 +1,39 @@ + + + + + netcoreapp3.1;net462 + $(TargetFrameworks);net462 + Prometheus exporter shared code for both Prometheus exporter HttpListener and Prometheus Exporter AspNetCore + $(PackageTags);prometheus;metrics + core- + + + + $(NoWarn),1591 + + + + $(NoWarn),RS0016 + + + + + false + + + + + + + + + + + + + + + + diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs new file mode 100644 index 00000000000..8f672645ba0 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs @@ -0,0 +1,240 @@ +// +// 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. +// + +using System; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using OpenTelemetry.Metrics; + +namespace OpenTelemetry.Exporter.Prometheus +{ + internal sealed class PrometheusCollectionManager + { + private readonly PrometheusExporter exporter; + private readonly int scrapeResponseCacheDurationInMilliseconds; + private readonly Func, ExportResult> onCollectRef; + private byte[] buffer = new byte[85000]; // encourage the object to live in LOH (large object heap) + private int globalLockState; + private ArraySegment previousDataView; + private DateTime? previousDataViewGeneratedAtUtc; + private int readerCount; + private bool collectionRunning; + private TaskCompletionSource collectionTcs; + + public PrometheusCollectionManager(PrometheusExporter exporter) + { + this.exporter = exporter; + this.scrapeResponseCacheDurationInMilliseconds = this.exporter.Options.ScrapeResponseCacheDurationMilliseconds; + this.onCollectRef = this.OnCollect; + } + +#if NETCOREAPP3_1_OR_GREATER + public ValueTask EnterCollect() +#else + public Task EnterCollect() +#endif + { + this.EnterGlobalLock(); + + // If we are within {ScrapeResponseCacheDurationMilliseconds} of the + // last successful collect, return the previous view. + if (this.previousDataViewGeneratedAtUtc.HasValue + && this.scrapeResponseCacheDurationInMilliseconds > 0 + && this.previousDataViewGeneratedAtUtc.Value.AddMilliseconds(this.scrapeResponseCacheDurationInMilliseconds) >= DateTime.UtcNow) + { + Interlocked.Increment(ref this.readerCount); + this.ExitGlobalLock(); +#if NETCOREAPP3_1_OR_GREATER + return new ValueTask(new CollectionResponse(this.previousDataView, this.previousDataViewGeneratedAtUtc.Value, fromCache: true)); +#else + return Task.FromResult(new CollectionResponse(this.previousDataView, this.previousDataViewGeneratedAtUtc.Value, fromCache: true)); +#endif + } + + // If a collection is already running, return a task to wait on the result. + if (this.collectionRunning) + { + if (this.collectionTcs == null) + { + this.collectionTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + } + + Interlocked.Increment(ref this.readerCount); + this.ExitGlobalLock(); +#if NETCOREAPP3_1_OR_GREATER + return new ValueTask(this.collectionTcs.Task); +#else + return this.collectionTcs.Task; +#endif + } + + this.WaitForReadersToComplete(); + + // Start a collection on the current thread. + this.collectionRunning = true; + this.previousDataViewGeneratedAtUtc = null; + Interlocked.Increment(ref this.readerCount); + this.ExitGlobalLock(); + + CollectionResponse response; + bool result = this.ExecuteCollect(); + if (result) + { + this.previousDataViewGeneratedAtUtc = DateTime.UtcNow; + response = new CollectionResponse(this.previousDataView, this.previousDataViewGeneratedAtUtc.Value, fromCache: false); + } + else + { + response = default; + } + + this.EnterGlobalLock(); + + this.collectionRunning = false; + + if (this.collectionTcs != null) + { + this.collectionTcs.SetResult(response); + this.collectionTcs = null; + } + + this.ExitGlobalLock(); + +#if NETCOREAPP3_1_OR_GREATER + return new ValueTask(response); +#else + return Task.FromResult(response); +#endif + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExitCollect() + { + Interlocked.Decrement(ref this.readerCount); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void EnterGlobalLock() + { + SpinWait lockWait = default; + while (true) + { + if (Interlocked.CompareExchange(ref this.globalLockState, 1, this.globalLockState) != 0) + { + lockWait.SpinOnce(); + continue; + } + + break; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void ExitGlobalLock() + { + this.globalLockState = 0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void WaitForReadersToComplete() + { + SpinWait readWait = default; + while (true) + { + if (Interlocked.CompareExchange(ref this.readerCount, 0, this.readerCount) != 0) + { + readWait.SpinOnce(); + continue; + } + + break; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private bool ExecuteCollect() + { + this.exporter.OnExport = this.onCollectRef; + bool result = this.exporter.Collect(Timeout.Infinite); + this.exporter.OnExport = null; + return result; + } + + private ExportResult OnCollect(Batch metrics) + { + int cursor = 0; + + try + { + foreach (var metric in metrics) + { + while (true) + { + try + { + cursor = PrometheusSerializer.WriteMetric(this.buffer, cursor, metric); + break; + } + catch (IndexOutOfRangeException) + { + int bufferSize = this.buffer.Length * 2; + + // there are two cases we might run into the following condition: + // 1. we have many metrics to be exported - in this case we probably want + // to put some upper limit and allow the user to configure it. + // 2. we got an IndexOutOfRangeException which was triggered by some other + // code instead of the buffer[cursor++] - in this case we should give up + // at certain point rather than allocating like crazy. + if (bufferSize > 100 * 1024 * 1024) + { + throw; + } + + var newBuffer = new byte[bufferSize]; + this.buffer.CopyTo(newBuffer, 0); + this.buffer = newBuffer; + } + } + } + + this.previousDataView = new ArraySegment(this.buffer, 0, Math.Max(cursor - 1, 0)); + return ExportResult.Success; + } + catch (Exception) + { + this.previousDataView = new ArraySegment(Array.Empty(), 0, 0); + return ExportResult.Failure; + } + } + + public readonly struct CollectionResponse + { + public CollectionResponse(ArraySegment view, DateTime generatedAtUtc, bool fromCache) + { + this.View = view; + this.GeneratedAtUtc = generatedAtUtc; + this.FromCache = fromCache; + } + + public ArraySegment View { get; } + + public DateTime GeneratedAtUtc { get; } + + public bool FromCache { get; } + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs new file mode 100644 index 00000000000..c28ea44c752 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs @@ -0,0 +1,63 @@ +// +// 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. +// + +using System; +using OpenTelemetry.Exporter.Prometheus; +using OpenTelemetry.Metrics; + +namespace OpenTelemetry.Exporter +{ + /// + /// Exporter of OpenTelemetry metrics to Prometheus. + /// + [ExportModes(ExportModes.Pull)] + public class PrometheusExporter : BaseExporter, IPullMetricExporter + { + internal const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started."; + internal readonly PrometheusExporterOptions Options; + private Func funcCollect; + private Func, ExportResult> funcExport; + + /// + /// Initializes a new instance of the class. + /// + /// Options for the exporter. + internal PrometheusExporter(PrometheusExporterOptions options) + { + this.Options = options; + this.CollectionManager = new PrometheusCollectionManager(this); + } + + public Func Collect + { + get => this.funcCollect; + set => this.funcCollect = value; + } + + internal Func, ExportResult> OnExport + { + get => this.funcExport; + set => this.funcExport = value; + } + + internal PrometheusCollectionManager CollectionManager { get; } + + public override ExportResult Export(in Batch metrics) + { + return this.OnExport(metrics); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs new file mode 100644 index 00000000000..c308d588335 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs @@ -0,0 +1,84 @@ +// +// 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. +// + +using System; +using System.Diagnostics.Tracing; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Exporter.Prometheus +{ + /// + /// EventSource events emitted from the project. + /// + [EventSource(Name = "OpenTelemetry-Exporter-Prometheus")] + + // TODO: make it internal and use Internal Visible to the httpListener + internal sealed class PrometheusExporterEventSource : EventSource + { + public static PrometheusExporterEventSource Log = new(); + + [NonEvent] + public void FailedExport(Exception ex) + { + if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) + { + this.FailedExport(ex.ToInvariantString()); + } + } + + [NonEvent] + public void FailedShutdown(Exception ex) + { + if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) + { + this.FailedShutdown(ex.ToInvariantString()); + } + } + + [NonEvent] + public void CanceledExport(Exception ex) + { + if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) + { + this.CanceledExport(ex.ToInvariantString()); + } + } + + [Event(1, Message = "Failed to export metrics: '{0}'", Level = EventLevel.Error)] + public void FailedExport(string exception) + { + this.WriteEvent(1, exception); + } + + [Event(2, Message = "Canceled to export metrics: '{0}'", Level = EventLevel.Error)] + public void CanceledExport(string exception) + { + this.WriteEvent(2, exception); + } + + [Event(3, Message = "Failed to shutdown Metrics server '{0}'", Level = EventLevel.Error)] + public void FailedShutdown(string exception) + { + this.WriteEvent(3, exception); + } + + [Event(4, Message = "No metrics are available for export.", Level = EventLevel.Warning)] + public void NoMetrics() + { + this.WriteEvent(4); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterMeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterMeterProviderBuilderExtensions.cs new file mode 100644 index 00000000000..ce17cca6e63 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterMeterProviderBuilderExtensions.cs @@ -0,0 +1,59 @@ +// +// 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. +// + +using System; +using OpenTelemetry.Exporter; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Metrics +{ + public static class PrometheusExporterMeterProviderBuilderExtensions + { + /// + /// Adds to the . + /// + /// builder to use. + /// Exporter configuration options. + /// The instance of to chain the calls. + public static MeterProviderBuilder AddPrometheusExporter(this MeterProviderBuilder builder, Action configure = null) + { + Guard.ThrowIfNull(builder); + + if (builder is IDeferredMeterProviderBuilder deferredMeterProviderBuilder) + { + return deferredMeterProviderBuilder.Configure((sp, builder) => + { + AddPrometheusExporter(builder, sp.GetOptions(), configure); + }); + } + + return AddPrometheusExporter(builder, new PrometheusExporterOptions(), configure); + } + + private static MeterProviderBuilder AddPrometheusExporter(MeterProviderBuilder builder, PrometheusExporterOptions options, Action configure = null) + { + configure?.Invoke(options); + + var exporter = new PrometheusExporter(options); + var reader = new BaseExportingMetricReader(exporter) + { + TemporalityPreference = MetricReaderTemporalityPreference.Cumulative, + }; + + return builder.AddReader(reader); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs new file mode 100644 index 00000000000..6dc1bfa870f --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs @@ -0,0 +1,54 @@ +// +// 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. +// + +using System; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Exporter +{ + /// + /// options. + /// + public class PrometheusExporterOptions + { + internal const string DefaultScrapeEndpointPath = "/metrics"; + internal Func GetUtcNowDateTimeOffset = () => DateTimeOffset.UtcNow; + + private int scrapeResponseCacheDurationMilliseconds = 10 * 1000; + + /// + /// Gets or sets the path to use for the scraping endpoint. Default value: /metrics. + /// + public string ScrapeEndpointPath { get; set; } = DefaultScrapeEndpointPath; + + /// + /// Gets or sets the cache duration in milliseconds for scrape responses. Default value: 10,000 (10 seconds). + /// + /// + /// Note: Specify 0 to disable response caching. + /// + public int ScrapeResponseCacheDurationMilliseconds + { + get => this.scrapeResponseCacheDurationMilliseconds; + set + { + Guard.ThrowIfOutOfRange(value, min: 0); + + this.scrapeResponseCacheDurationMilliseconds = value; + } + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs new file mode 100644 index 00000000000..dfe95008ae8 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs @@ -0,0 +1,308 @@ +// +// 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. +// + +#if NETCOREAPP3_1_OR_GREATER +using System; +#endif +using System.Diagnostics; +using System.Globalization; +using System.Runtime.CompilerServices; + +namespace OpenTelemetry.Exporter.Prometheus +{ + /// + /// Basic PrometheusSerializer which has no OpenTelemetry dependency. + /// + internal static partial class PrometheusSerializer + { +#pragma warning disable SA1310 // Field name should not contain an underscore + private const byte ASCII_QUOTATION_MARK = 0x22; // '"' + private const byte ASCII_FULL_STOP = 0x2E; // '.' + private const byte ASCII_HYPHEN_MINUS = 0x2D; // '-' + private const byte ASCII_REVERSE_SOLIDUS = 0x5C; // '\\' + private const byte ASCII_LINEFEED = 0x0A; // `\n` +#pragma warning restore SA1310 // Field name should not contain an underscore + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteDouble(byte[] buffer, int cursor, double value) + { +#if NETCOREAPP3_1_OR_GREATER + if (double.IsFinite(value)) +#else + if (!double.IsInfinity(value) && !double.IsNaN(value)) +#endif + { +#if NETCOREAPP3_1_OR_GREATER + Span span = stackalloc char[128]; + + var result = value.TryFormat(span, out var cchWritten, "G", CultureInfo.InvariantCulture); + Debug.Assert(result, $"{nameof(result)} should be true."); + + for (int i = 0; i < cchWritten; i++) + { + buffer[cursor++] = unchecked((byte)span[i]); + } +#else + cursor = WriteAsciiStringNoEscape(buffer, cursor, value.ToString(CultureInfo.InvariantCulture)); +#endif + } + else if (double.IsPositiveInfinity(value)) + { + cursor = WriteAsciiStringNoEscape(buffer, cursor, "+Inf"); + } + else if (double.IsNegativeInfinity(value)) + { + cursor = WriteAsciiStringNoEscape(buffer, cursor, "-Inf"); + } + else + { + Debug.Assert(double.IsNaN(value), $"{nameof(value)} should be NaN."); + cursor = WriteAsciiStringNoEscape(buffer, cursor, "Nan"); + } + + return cursor; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteLong(byte[] buffer, int cursor, long value) + { +#if NETCOREAPP3_1_OR_GREATER + Span span = stackalloc char[20]; + + var result = value.TryFormat(span, out var cchWritten, "G", CultureInfo.InvariantCulture); + Debug.Assert(result, $"{nameof(result)} should be true."); + + for (int i = 0; i < cchWritten; i++) + { + buffer[cursor++] = unchecked((byte)span[i]); + } +#else + cursor = WriteAsciiStringNoEscape(buffer, cursor, value.ToString(CultureInfo.InvariantCulture)); +#endif + + return cursor; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteAsciiStringNoEscape(byte[] buffer, int cursor, string value) + { + for (int i = 0; i < value.Length; i++) + { + buffer[cursor++] = unchecked((byte)value[i]); + } + + return cursor; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteUnicodeNoEscape(byte[] buffer, int cursor, ushort ordinal) + { + if (ordinal <= 0x7F) + { + buffer[cursor++] = unchecked((byte)ordinal); + } + else if (ordinal <= 0x07FF) + { + buffer[cursor++] = unchecked((byte)(0b_1100_0000 | (ordinal >> 6))); + buffer[cursor++] = unchecked((byte)(0b_1000_0000 | (ordinal & 0b_0011_1111))); + } + else if (ordinal <= 0xFFFF) + { + buffer[cursor++] = unchecked((byte)(0b_1110_0000 | (ordinal >> 12))); + buffer[cursor++] = unchecked((byte)(0b_1000_0000 | ((ordinal >> 6) & 0b_0011_1111))); + buffer[cursor++] = unchecked((byte)(0b_1000_0000 | (ordinal & 0b_0011_1111))); + } + else + { + Debug.Assert(ordinal <= 0xFFFF, ".NET string should not go beyond Unicode BMP."); + } + + return cursor; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteUnicodeString(byte[] buffer, int cursor, string value) + { + for (int i = 0; i < value.Length; i++) + { + var ordinal = (ushort)value[i]; + switch (ordinal) + { + case ASCII_REVERSE_SOLIDUS: + buffer[cursor++] = ASCII_REVERSE_SOLIDUS; + buffer[cursor++] = ASCII_REVERSE_SOLIDUS; + break; + case ASCII_LINEFEED: + buffer[cursor++] = ASCII_REVERSE_SOLIDUS; + buffer[cursor++] = unchecked((byte)'n'); + break; + default: + cursor = WriteUnicodeNoEscape(buffer, cursor, ordinal); + break; + } + } + + return cursor; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteLabelKey(byte[] buffer, int cursor, string value) + { + Debug.Assert(!string.IsNullOrEmpty(value), $"{nameof(value)} should not be null or empty."); + + var ordinal = (ushort)value[0]; + + if (ordinal >= (ushort)'0' && ordinal <= (ushort)'9') + { + buffer[cursor++] = unchecked((byte)'_'); + } + + for (int i = 0; i < value.Length; i++) + { + ordinal = (ushort)value[i]; + + if ((ordinal >= (ushort)'A' && ordinal <= (ushort)'Z') || + (ordinal >= (ushort)'a' && ordinal <= (ushort)'z') || + (ordinal >= (ushort)'0' && ordinal <= (ushort)'9')) + { + buffer[cursor++] = unchecked((byte)ordinal); + } + else + { + buffer[cursor++] = unchecked((byte)'_'); + } + } + + return cursor; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteLabelValue(byte[] buffer, int cursor, string value) + { + Debug.Assert(value != null, $"{nameof(value)} should not be null."); + + for (int i = 0; i < value.Length; i++) + { + var ordinal = (ushort)value[i]; + switch (ordinal) + { + case ASCII_QUOTATION_MARK: + buffer[cursor++] = ASCII_REVERSE_SOLIDUS; + buffer[cursor++] = ASCII_QUOTATION_MARK; + break; + case ASCII_REVERSE_SOLIDUS: + buffer[cursor++] = ASCII_REVERSE_SOLIDUS; + buffer[cursor++] = ASCII_REVERSE_SOLIDUS; + break; + case ASCII_LINEFEED: + buffer[cursor++] = ASCII_REVERSE_SOLIDUS; + buffer[cursor++] = unchecked((byte)'n'); + break; + default: + cursor = WriteUnicodeNoEscape(buffer, cursor, ordinal); + break; + } + } + + return cursor; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteLabel(byte[] buffer, int cursor, string labelKey, object labelValue) + { + cursor = WriteLabelKey(buffer, cursor, labelKey); + buffer[cursor++] = unchecked((byte)'='); + buffer[cursor++] = unchecked((byte)'"'); + + // In Prometheus, a label with an empty label value is considered equivalent to a label that does not exist. + cursor = WriteLabelValue(buffer, cursor, labelValue?.ToString() ?? string.Empty); + buffer[cursor++] = unchecked((byte)'"'); + + return cursor; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteMetricName(byte[] buffer, int cursor, string metricName, string metricUnit = null) + { + Debug.Assert(!string.IsNullOrEmpty(metricName), $"{nameof(metricName)} should not be null or empty."); + + for (int i = 0; i < metricName.Length; i++) + { + var ordinal = (ushort)metricName[i]; + buffer[cursor++] = ordinal switch + { + ASCII_FULL_STOP or ASCII_HYPHEN_MINUS => unchecked((byte)'_'), + _ => unchecked((byte)ordinal), + }; + } + + if (!string.IsNullOrEmpty(metricUnit)) + { + buffer[cursor++] = unchecked((byte)'_'); + + for (int i = 0; i < metricUnit.Length; i++) + { + var ordinal = (ushort)metricUnit[i]; + + if ((ordinal >= (ushort)'A' && ordinal <= (ushort)'Z') || + (ordinal >= (ushort)'a' && ordinal <= (ushort)'z') || + (ordinal >= (ushort)'0' && ordinal <= (ushort)'9')) + { + buffer[cursor++] = unchecked((byte)ordinal); + } + else + { + buffer[cursor++] = unchecked((byte)'_'); + } + } + } + + return cursor; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteHelpText(byte[] buffer, int cursor, string metricName, string metricUnit = null, string metricDescription = null) + { + cursor = WriteAsciiStringNoEscape(buffer, cursor, "# HELP "); + cursor = WriteMetricName(buffer, cursor, metricName, metricUnit); + + if (!string.IsNullOrEmpty(metricDescription)) + { + buffer[cursor++] = unchecked((byte)' '); + cursor = WriteUnicodeString(buffer, cursor, metricDescription); + } + + buffer[cursor++] = ASCII_LINEFEED; + + return cursor; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteTypeInfo(byte[] buffer, int cursor, string metricName, string metricUnit, string metricType) + { + Debug.Assert(!string.IsNullOrEmpty(metricType), $"{nameof(metricType)} should not be null or empty."); + + cursor = WriteAsciiStringNoEscape(buffer, cursor, "# TYPE "); + cursor = WriteMetricName(buffer, cursor, metricName, metricUnit); + buffer[cursor++] = unchecked((byte)' '); + cursor = WriteAsciiStringNoEscape(buffer, cursor, metricType); + + buffer[cursor++] = ASCII_LINEFEED; + + return cursor; + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs new file mode 100644 index 00000000000..805a51a2488 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs @@ -0,0 +1,200 @@ +// +// 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. +// + +using OpenTelemetry.Metrics; + +namespace OpenTelemetry.Exporter.Prometheus +{ + /// + /// OpenTelemetry additions to the PrometheusSerializer. + /// + internal static partial class PrometheusSerializer + { + private static readonly string[] MetricTypes = new string[] + { + "untyped", "counter", "gauge", "summary", "histogram", "histogram", "histogram", "histogram", "untyped", + }; + + public static int WriteMetric(byte[] buffer, int cursor, Metric metric) + { + if (!string.IsNullOrWhiteSpace(metric.Description)) + { + cursor = WriteHelpText(buffer, cursor, metric.Name, metric.Unit, metric.Description); + } + + int metricType = (int)metric.MetricType >> 4; + cursor = WriteTypeInfo(buffer, cursor, metric.Name, metric.Unit, MetricTypes[metricType]); + + if (!metric.MetricType.IsHistogram()) + { + foreach (ref readonly var metricPoint in metric.GetMetricPoints()) + { + var tags = metricPoint.Tags; + var timestamp = metricPoint.EndTime.ToUnixTimeMilliseconds(); + + // Counter and Gauge + cursor = WriteMetricName(buffer, cursor, metric.Name, metric.Unit); + + if (tags.Count > 0) + { + buffer[cursor++] = unchecked((byte)'{'); + + foreach (var tag in tags) + { + cursor = WriteLabel(buffer, cursor, tag.Key, tag.Value); + buffer[cursor++] = unchecked((byte)','); + } + + buffer[cursor - 1] = unchecked((byte)'}'); // Note: We write the '}' over the last written comma, which is extra. + } + + buffer[cursor++] = unchecked((byte)' '); + + // TODO: MetricType is same for all MetricPoints + // within a given Metric, so this check can avoided + // for each MetricPoint + if (((int)metric.MetricType & 0b_0000_1111) == 0x0a /* I8 */) + { + if (metric.MetricType.IsSum()) + { + cursor = WriteLong(buffer, cursor, metricPoint.GetSumLong()); + } + else + { + cursor = WriteLong(buffer, cursor, metricPoint.GetGaugeLastValueLong()); + } + } + else + { + if (metric.MetricType.IsSum()) + { + cursor = WriteDouble(buffer, cursor, metricPoint.GetSumDouble()); + } + else + { + cursor = WriteDouble(buffer, cursor, metricPoint.GetGaugeLastValueDouble()); + } + } + + buffer[cursor++] = unchecked((byte)' '); + + cursor = WriteLong(buffer, cursor, timestamp); + + buffer[cursor++] = ASCII_LINEFEED; + } + } + else + { + foreach (ref readonly var metricPoint in metric.GetMetricPoints()) + { + var tags = metricPoint.Tags; + var timestamp = metricPoint.EndTime.ToUnixTimeMilliseconds(); + + long totalCount = 0; + foreach (var histogramMeasurement in metricPoint.GetHistogramBuckets()) + { + totalCount += histogramMeasurement.BucketCount; + + cursor = WriteMetricName(buffer, cursor, metric.Name, metric.Unit); + cursor = WriteAsciiStringNoEscape(buffer, cursor, "_bucket{"); + + foreach (var tag in tags) + { + cursor = WriteLabel(buffer, cursor, tag.Key, tag.Value); + buffer[cursor++] = unchecked((byte)','); + } + + cursor = WriteAsciiStringNoEscape(buffer, cursor, "le=\""); + + if (histogramMeasurement.ExplicitBound != double.PositiveInfinity) + { + cursor = WriteDouble(buffer, cursor, histogramMeasurement.ExplicitBound); + } + else + { + cursor = WriteAsciiStringNoEscape(buffer, cursor, "+Inf"); + } + + cursor = WriteAsciiStringNoEscape(buffer, cursor, "\"} "); + + cursor = WriteLong(buffer, cursor, totalCount); + buffer[cursor++] = unchecked((byte)' '); + + cursor = WriteLong(buffer, cursor, timestamp); + + buffer[cursor++] = ASCII_LINEFEED; + } + + // Histogram sum + cursor = WriteMetricName(buffer, cursor, metric.Name, metric.Unit); + cursor = WriteAsciiStringNoEscape(buffer, cursor, "_sum"); + + if (tags.Count > 0) + { + buffer[cursor++] = unchecked((byte)'{'); + + foreach (var tag in tags) + { + cursor = WriteLabel(buffer, cursor, tag.Key, tag.Value); + buffer[cursor++] = unchecked((byte)','); + } + + buffer[cursor - 1] = unchecked((byte)'}'); // Note: We write the '}' over the last written comma, which is extra. + } + + buffer[cursor++] = unchecked((byte)' '); + + cursor = WriteDouble(buffer, cursor, metricPoint.GetHistogramSum()); + buffer[cursor++] = unchecked((byte)' '); + + cursor = WriteLong(buffer, cursor, timestamp); + + buffer[cursor++] = ASCII_LINEFEED; + + // Histogram count + cursor = WriteMetricName(buffer, cursor, metric.Name, metric.Unit); + cursor = WriteAsciiStringNoEscape(buffer, cursor, "_count"); + + if (tags.Count > 0) + { + buffer[cursor++] = unchecked((byte)'{'); + + foreach (var tag in tags) + { + cursor = WriteLabel(buffer, cursor, tag.Key, tag.Value); + buffer[cursor++] = unchecked((byte)','); + } + + buffer[cursor - 1] = unchecked((byte)'}'); // Note: We write the '}' over the last written comma, which is extra. + } + + buffer[cursor++] = unchecked((byte)' '); + + cursor = WriteLong(buffer, cursor, metricPoint.GetHistogramCount()); + buffer[cursor++] = unchecked((byte)' '); + + cursor = WriteLong(buffer, cursor, timestamp); + + buffer[cursor++] = ASCII_LINEFEED; + } + } + + buffer[cursor++] = ASCII_LINEFEED; + + return cursor; + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/README.md b/src/OpenTelemetry.Exporter.Prometheus.Shared/README.md new file mode 100644 index 00000000000..fa3b1a61107 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/README.md @@ -0,0 +1,138 @@ + # Prometheus Exporter 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) + +## Prerequisite + +* [Get Prometheus](https://prometheus.io/docs/introduction/first_steps/) + +## Steps to enable OpenTelemetry.Exporter.Prometheus + +### Step 1: Install Package + +Depending on the hosting mechanism you will be using: + +Install + +```shell +dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore +``` + +or + +```shell +dotnet add package OpenTelemetry.Exporter.Prometheus.HttpListener +``` + +### Step 2: Configure OpenTelemetry MeterProvider + +* When using OpenTelemetry.Extensions.Hosting package on .NET Core 3.1+: + + ```csharp + services.AddOpenTelemetryMetrics(builder => + { + builder.AddPrometheusExporter(); + }); + ``` + +* Or configure directly: + + Call the `AddPrometheusExporter` `MeterProviderBuilder` extension to + register the Prometheus exporter. + + ```csharp + using var meterProvider = Sdk.CreateMeterProviderBuilder() + .AddPrometheusExporter() + .Build(); + ``` + +### Step 3: Configure Prometheus Scraping Endpoint + +* On .NET Core 3.1+ register Prometheus scraping middleware using the + `UseOpenTelemetryPrometheusScrapingEndpoint` extension: + + ```csharp + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + 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(); + }); + } + ``` + +## Configuration + +The `PrometheusExporter` can be configured using the `PrometheusExporterOptions` +properties. Refer to +[`TestPrometheusExporter.cs`](../../examples/Console/TestPrometheusExporter.cs) +for example use. + +### HttpListener + +Configure `HttpListener` with the already constructed meterProvider instance and +passed in `PrometheusHttpListenerOptions` for configuration. +Use `listener.Start()` to allow the listener to start receiving incoming requests. + +```csharp +this.listener = new PrometheusHttpListener( + this.meterProvider, + o => o.HttpListenerPrefixes = new string[] { "http://localhost:9464/metrics" }); +this.listener.Start(); +``` + +#### HttpListenerPrefixes + +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 +either the HTTP listener or the middleware registered 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) diff --git a/src/OpenTelemetry/AssemblyInfo.cs b/src/OpenTelemetry/AssemblyInfo.cs index 545b35a13e8..868e2539a8e 100644 --- a/src/OpenTelemetry/AssemblyInfo.cs +++ b/src/OpenTelemetry/AssemblyInfo.cs @@ -20,6 +20,10 @@ [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.Exporter.Prometheus.Shared" + AssemblyInfo.PublicKey)] +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore" + AssemblyInfo.PublicKey)] +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.HttpListener" + AssemblyInfo.PublicKey)] +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Shared.Tests" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("OpenTelemetry.Extensions.Hosting.Tests" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)] [assembly: InternalsVisibleTo("Benchmarks" + AssemblyInfo.PublicKey)] diff --git a/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests.csproj b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests.csproj new file mode 100644 index 00000000000..d0940145313 --- /dev/null +++ b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests.csproj @@ -0,0 +1,35 @@ + + + Unit test project for Prometheus Exporter AspNetCore for OpenTelemetry + + netcoreapp3.1 + + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + + + + + + + + + + + diff --git a/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusExporterMiddlewareTests.cs b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusExporterMiddlewareTests.cs new file mode 100644 index 00000000000..ff8b0bdc484 --- /dev/null +++ b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusExporterMiddlewareTests.cs @@ -0,0 +1,293 @@ +// +// 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. +// + +#if !NETFRAMEWORK +using System; +using System.Collections.Generic; +using System.Diagnostics.Metrics; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using OpenTelemetry.Metrics; +using OpenTelemetry.Tests; +using Xunit; + +namespace OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests +{ + public sealed class PrometheusExporterMiddlewareTests + { + private static readonly string MeterName = Utils.GetCurrentMethodName(); + + [Fact] + public Task PrometheusExporterMiddlewareIntegration() + { + return RunPrometheusExporterMiddlewareIntegrationTest( + "/metrics", + app => app.UseOpenTelemetryPrometheusScrapingEndpoint()); + } + + [Fact] + public Task PrometheusExporterMiddlewareIntegration_Options() + { + return RunPrometheusExporterMiddlewareIntegrationTest( + "/metrics_options", + app => app.UseOpenTelemetryPrometheusScrapingEndpoint(), + services => services.Configure(o => o.ScrapeEndpointPath = "metrics_options")); + } + + [Fact] + public Task PrometheusExporterMiddlewareIntegration_OptionsFallback() + { + return RunPrometheusExporterMiddlewareIntegrationTest( + "/metrics", + app => app.UseOpenTelemetryPrometheusScrapingEndpoint(), + services => services.Configure(o => o.ScrapeEndpointPath = null)); + } + + [Fact] + public Task PrometheusExporterMiddlewareIntegration_OptionsViaAddPrometheusExporter() + { + return RunPrometheusExporterMiddlewareIntegrationTest( + "/metrics_from_AddPrometheusExporter", + app => app.UseOpenTelemetryPrometheusScrapingEndpoint(), + configureOptions: o => o.ScrapeEndpointPath = "/metrics_from_AddPrometheusExporter"); + } + + [Fact] + public Task PrometheusExporterMiddlewareIntegration_PathOverride() + { + return RunPrometheusExporterMiddlewareIntegrationTest( + "/metrics_override", + app => app.UseOpenTelemetryPrometheusScrapingEndpoint("/metrics_override")); + } + + [Fact] + public Task PrometheusExporterMiddlewareIntegration_Predicate() + { + return RunPrometheusExporterMiddlewareIntegrationTest( + "/metrics_predicate?enabled=true", + app => app.UseOpenTelemetryPrometheusScrapingEndpoint(httpcontext => httpcontext.Request.Path == "/metrics_predicate" && httpcontext.Request.Query["enabled"] == "true")); + } + + [Fact] + public Task PrometheusExporterMiddlewareIntegration_MixedPredicateAndPath() + { + return RunPrometheusExporterMiddlewareIntegrationTest( + "/metrics_predicate", + app => app.UseOpenTelemetryPrometheusScrapingEndpoint( + meterProvider: null, + predicate: httpcontext => httpcontext.Request.Path == "/metrics_predicate", + path: "/metrics_path", + configureBranchedPipeline: branch => branch.Use((context, next) => + { + context.Response.Headers.Add("X-MiddlewareExecuted", "true"); + return next(); + })), + services => services.Configure(o => o.ScrapeEndpointPath = "/metrics_options"), + validateResponse: rsp => + { + if (!rsp.Headers.TryGetValues("X-MiddlewareExecuted", out IEnumerable headers)) + { + headers = Array.Empty(); + } + + Assert.Equal("true", headers.FirstOrDefault()); + }); + } + + [Fact] + public Task PrometheusExporterMiddlewareIntegration_MixedPath() + { + return RunPrometheusExporterMiddlewareIntegrationTest( + "/metrics_path", + app => app.UseOpenTelemetryPrometheusScrapingEndpoint( + meterProvider: null, + predicate: null, + path: "/metrics_path", + configureBranchedPipeline: branch => branch.Use((context, next) => + { + context.Response.Headers.Add("X-MiddlewareExecuted", "true"); + return next(); + })), + services => services.Configure(o => o.ScrapeEndpointPath = "/metrics_options"), + validateResponse: rsp => + { + if (!rsp.Headers.TryGetValues("X-MiddlewareExecuted", out IEnumerable headers)) + { + headers = Array.Empty(); + } + + Assert.Equal("true", headers.FirstOrDefault()); + }); + } + + [Fact] + public async Task PrometheusExporterMiddlewareIntegration_MeterProvider() + { + using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder() + .AddMeter(MeterName) + .AddPrometheusExporter() + .Build(); + + await RunPrometheusExporterMiddlewareIntegrationTest( + "/metrics", + app => app.UseOpenTelemetryPrometheusScrapingEndpoint( + meterProvider: meterProvider, + predicate: null, + path: null, + configureBranchedPipeline: null), + registerMeterProvider: false).ConfigureAwait(false); + } + + [Fact] + public Task PrometheusExporterMiddlewareIntegration_NoMetrics() + { + return RunPrometheusExporterMiddlewareIntegrationTest( + "/metrics", + app => app.UseOpenTelemetryPrometheusScrapingEndpoint(), + 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 configure, + Action configureServices = null, + Action validateResponse = null, + bool registerMeterProvider = true, + Action configureOptions = null, + bool skipMetrics = false) + { + using var host = await new HostBuilder() + .ConfigureWebHost(webBuilder => webBuilder + .UseTestServer() + .ConfigureServices(services => + { + if (registerMeterProvider) + { + services.AddOpenTelemetryMetrics(builder => builder + .AddMeter(MeterName) + .AddPrometheusExporter(o => + { + configureOptions?.Invoke(o); + })); + } + + configureServices?.Invoke(services); + }) + .Configure(configure)) + .StartAsync(); + + var tags = new KeyValuePair[] + { + new KeyValuePair("key1", "value1"), + new KeyValuePair("key2", "value2"), + }; + + using var meter = new Meter(MeterName); + + var beginTimestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); + + var counter = meter.CreateCounter("counter_double"); + if (!skipMetrics) + { + counter.Add(100.18D, tags); + counter.Add(0.99D, tags); + } + + using var response = await host.GetTestClient().GetAsync(path).ConfigureAwait(false); + + var endTimestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); + + if (!skipMetrics) + { + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.True(response.Content.Headers.Contains("Last-Modified")); + Assert.Equal("text/plain; charset=utf-8; version=0.0.4", response.Content.Headers.ContentType.ToString()); + + string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + + string[] lines = content.Split('\n'); + + Assert.Equal( + $"# TYPE counter_double counter", + lines[0]); + + Assert.Contains( + $"counter_double{{key1=\"value1\",key2=\"value2\"}} 101.17", + lines[1]); + + var index = content.LastIndexOf(' '); + + Assert.Equal('\n', content[^1]); + + var timestamp = long.Parse(content.Substring(index, content.Length - index - 1)); + + Assert.True(beginTimestamp <= timestamp && timestamp <= endTimestamp); + } + else + { + Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); + } + + validateResponse?.Invoke(response); + + await host.StopAsync().ConfigureAwait(false); + } + } +} +#endif diff --git a/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests.csproj b/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests.csproj new file mode 100644 index 00000000000..4bfbfc6def1 --- /dev/null +++ b/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests.csproj @@ -0,0 +1,31 @@ + + + Unit test project for Prometheus Exporter HttpListener for OpenTelemetry + + net462 + + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + + + + + + + diff --git a/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusExporterHttpListenerTests.cs b/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusExporterHttpListenerTests.cs new file mode 100644 index 00000000000..532893700f8 --- /dev/null +++ b/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusExporterHttpListenerTests.cs @@ -0,0 +1,137 @@ +// +// 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. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics.Metrics; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using OpenTelemetry.Metrics; +using OpenTelemetry.Tests; +using Xunit; + +namespace OpenTelemetry.Exporter.Prometheus.HttpListener.Tests +{ + public class PrometheusExporterHttpListenerTests + { + private readonly string meterName = Utils.GetCurrentMethodName(); + + [Theory] + [InlineData("http://example.com")] + [InlineData("https://example.com")] + [InlineData("http://127.0.0.1")] + [InlineData("http://example.com", "https://example.com", "http://127.0.0.1")] + public void ServerEndpointSanityCheckPositiveTest(params string[] uris) + { + using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder() + .AddPrometheusHttpListener(null, listenerOptions => listenerOptions.Prefixes = uris) + .Build(); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + [InlineData("ftp://example.com")] + [InlineData("http://example.com", "https://example.com", "ftp://example.com")] + public void ServerEndpointSanityCheckNegativeTest(params string[] uris) + { + try + { + using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder() + .AddPrometheusHttpListener(null, listenerOptions => listenerOptions.Prefixes = uris) + .Build(); + } + catch (Exception ex) + { + if (ex is not ArgumentNullException) + { + 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: prefixes", ex.Message); +#else + Assert.Equal("Prometheus server 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; + string address = null; + + MeterProvider provider; + using var meter = new Meter(this.meterName); + + while (retryAttempts-- != 0) + { + port = random.Next(2000, 5000); + address = $"http://localhost:{port}/"; + + provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddPrometheusHttpListener(null, listenerOptions => listenerOptions.Prefixes = new string[] { address }) + .Build(); + } + + var tags = new KeyValuePair[] + { + new KeyValuePair("key1", "value1"), + new KeyValuePair("key2", "value2"), + }; + + var counter = meter.CreateCounter("counter_double"); + if (!skipMetrics) + { + counter.Add(100.18D, tags); + counter.Add(0.99D, tags); + } + + using HttpClient client = new HttpClient(); + using var response = await client.GetAsync($"{address}metrics").ConfigureAwait(false); + + if (!skipMetrics) + { + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.True(response.Content.Headers.Contains("Last-Modified")); + Assert.Equal("text/plain; charset=utf-8; version=0.0.4", response.Content.Headers.ContentType.ToString()); + + Assert.Matches( + "^# TYPE counter_double counter\ncounter_double{key1='value1',key2='value2'} 101.17 \\d+\n$".Replace('\'', '"'), + await response.Content.ReadAsStringAsync().ConfigureAwait(false)); + } + else + { + Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); + } + } + } +} diff --git a/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj b/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj new file mode 100644 index 00000000000..cac030243cf --- /dev/null +++ b/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj @@ -0,0 +1,33 @@ + + + Unit test project of Prometheus exporter shared code for both Prometheus exporter HttpListener and Prometheus Exporter AspNetCore + + netcoreapp3.1;net462 + $(TargetFrameworks);net462 + + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + + + + + + + + diff --git a/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/PrometheusCollectionManagerTests.cs b/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/PrometheusCollectionManagerTests.cs new file mode 100644 index 00000000000..aa41207db3c --- /dev/null +++ b/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/PrometheusCollectionManagerTests.cs @@ -0,0 +1,161 @@ +// +// 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. +// + +using System; +using System.Diagnostics.Metrics; +#if NETFRAMEWORK +using System.Linq; +#endif +using System.Threading; +using System.Threading.Tasks; +using OpenTelemetry.Metrics; +using OpenTelemetry.Tests; +using Xunit; + +namespace OpenTelemetry.Exporter.Prometheus.Shared.Tests +{ + public sealed class PrometheusCollectionManagerTests + { + [Fact] + public async Task EnterExitCollectTest() + { + using var meter = new Meter(Utils.GetCurrentMethodName()); + + using (var provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddPrometheusExporter() + .Build()) + { + if (!provider.TryFindExporter(out PrometheusExporter exporter)) + { + throw new InvalidOperationException("PrometheusExporter could not be found on MeterProvider."); + } + + int runningCollectCount = 0; + var collectFunc = exporter.Collect; + exporter.Collect = (timeout) => + { + bool result = collectFunc(timeout); + runningCollectCount++; + Thread.Sleep(5000); + return result; + }; + + var counter = meter.CreateCounter("counter_int", description: "Prometheus help text goes here \n escaping."); + counter.Add(100); + + Task[] collectTasks = new Task[10]; + for (int i = 0; i < collectTasks.Length; i++) + { + collectTasks[i] = Task.Run(async () => + { + var response = await exporter.CollectionManager.EnterCollect().ConfigureAwait(false); + try + { + return new Response + { + CollectionResponse = response, + ViewPayload = response.View.ToArray(), + }; + } + finally + { + exporter.CollectionManager.ExitCollect(); + } + }); + } + + await Task.WhenAll(collectTasks).ConfigureAwait(false); + + Assert.Equal(1, runningCollectCount); + + var firstResponse = collectTasks[0].Result; + + Assert.False(firstResponse.CollectionResponse.FromCache); + + for (int i = 1; i < collectTasks.Length; i++) + { + Assert.Equal(firstResponse.ViewPayload, collectTasks[i].Result.ViewPayload); + Assert.Equal(firstResponse.CollectionResponse.GeneratedAtUtc, collectTasks[i].Result.CollectionResponse.GeneratedAtUtc); + } + + counter.Add(100); + + // This should use the cache and ignore the second counter update. + var task = exporter.CollectionManager.EnterCollect(); + Assert.True(task.IsCompleted); + var response = await task.ConfigureAwait(false); + try + { + Assert.Equal(1, runningCollectCount); + Assert.True(response.FromCache); + Assert.Equal(firstResponse.CollectionResponse.GeneratedAtUtc, response.GeneratedAtUtc); + } + finally + { + exporter.CollectionManager.ExitCollect(); + } + + Thread.Sleep(exporter.Options.ScrapeResponseCacheDurationMilliseconds); + + counter.Add(100); + + for (int i = 0; i < collectTasks.Length; i++) + { + collectTasks[i] = Task.Run(async () => + { + var response = await exporter.CollectionManager.EnterCollect().ConfigureAwait(false); + try + { + return new Response + { + CollectionResponse = response, + ViewPayload = response.View.ToArray(), + }; + } + finally + { + exporter.CollectionManager.ExitCollect(); + } + }); + } + + await Task.WhenAll(collectTasks).ConfigureAwait(false); + + Assert.Equal(2, runningCollectCount); + Assert.NotEqual(firstResponse.ViewPayload, collectTasks[0].Result.ViewPayload); + Assert.NotEqual(firstResponse.CollectionResponse.GeneratedAtUtc, collectTasks[0].Result.CollectionResponse.GeneratedAtUtc); + + firstResponse = collectTasks[0].Result; + + Assert.False(firstResponse.CollectionResponse.FromCache); + + for (int i = 1; i < collectTasks.Length; i++) + { + Assert.Equal(firstResponse.ViewPayload, collectTasks[i].Result.ViewPayload); + Assert.Equal(firstResponse.CollectionResponse.GeneratedAtUtc, collectTasks[i].Result.CollectionResponse.GeneratedAtUtc); + } + } + } + + private class Response + { + public PrometheusCollectionManager.CollectionResponse CollectionResponse; + + public byte[] ViewPayload; + } + } +} diff --git a/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/PrometheusSerializerTests.cs b/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/PrometheusSerializerTests.cs new file mode 100644 index 00000000000..1def2012b8e --- /dev/null +++ b/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/PrometheusSerializerTests.cs @@ -0,0 +1,387 @@ +// +// 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. +// + +using System.Collections.Generic; +using System.Diagnostics.Metrics; +using System.Text; +using OpenTelemetry.Metrics; +using OpenTelemetry.Tests; +using Xunit; + +namespace OpenTelemetry.Exporter.Prometheus.Shared.Tests +{ + public sealed class PrometheusSerializerTests + { + [Fact] + public void GaugeZeroDimension() + { + var buffer = new byte[85000]; + var metrics = new List(); + + using var meter = new Meter(Utils.GetCurrentMethodName()); + using var provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddInMemoryExporter(metrics) + .Build(); + + meter.CreateObservableGauge("test_gauge", () => 123); + + provider.ForceFlush(); + + var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); + Assert.Matches( + ("^" + + "# TYPE test_gauge gauge\n" + + "test_gauge 123 \\d+\n" + + "$").Replace('\'', '"'), + Encoding.UTF8.GetString(buffer, 0, cursor)); + } + + [Fact] + public void GaugeZeroDimensionWithDescription() + { + var buffer = new byte[85000]; + var metrics = new List(); + + using var meter = new Meter(Utils.GetCurrentMethodName()); + using var provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddInMemoryExporter(metrics) + .Build(); + + meter.CreateObservableGauge("test_gauge", () => 123, description: "Hello, world!"); + + provider.ForceFlush(); + + var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); + Assert.Matches( + ("^" + + "# HELP test_gauge Hello, world!\n" + + "# TYPE test_gauge gauge\n" + + "test_gauge 123 \\d+\n" + + "$").Replace('\'', '"'), + Encoding.UTF8.GetString(buffer, 0, cursor)); + } + + [Fact] + public void GaugeZeroDimensionWithUnit() + { + var buffer = new byte[85000]; + var metrics = new List(); + + using var meter = new Meter(Utils.GetCurrentMethodName()); + using var provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddInMemoryExporter(metrics) + .Build(); + + meter.CreateObservableGauge("test_gauge", () => 123, unit: "seconds"); + + provider.ForceFlush(); + + var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); + Assert.Matches( + ("^" + + "# TYPE test_gauge_seconds gauge\n" + + "test_gauge_seconds 123 \\d+\n" + + "$").Replace('\'', '"'), + Encoding.UTF8.GetString(buffer, 0, cursor)); + } + + [Fact] + public void GaugeOneDimension() + { + var buffer = new byte[85000]; + var metrics = new List(); + + using var meter = new Meter(Utils.GetCurrentMethodName()); + using var provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddInMemoryExporter(metrics) + .Build(); + + meter.CreateObservableGauge( + "test_gauge", + () => new Measurement(123, new KeyValuePair("tagKey", "tagValue"))); + + provider.ForceFlush(); + + var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); + Assert.Matches( + ("^" + + "# TYPE test_gauge gauge\n" + + "test_gauge{tagKey='tagValue'} 123 \\d+\n" + + "$").Replace('\'', '"'), + Encoding.UTF8.GetString(buffer, 0, cursor)); + } + + [Fact] + public void GaugeDoubleSubnormal() + { + var buffer = new byte[85000]; + var metrics = new List(); + + using var meter = new Meter(Utils.GetCurrentMethodName()); + using var provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddInMemoryExporter(metrics) + .Build(); + + meter.CreateObservableGauge("test_gauge", () => new List> + { + new(double.NegativeInfinity, new("x", "1"), new("y", "2")), + new(double.PositiveInfinity, new("x", "3"), new("y", "4")), + new(double.NaN, new("x", "5"), new("y", "6")), + }); + + provider.ForceFlush(); + + var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); + Assert.Matches( + ("^" + + "# TYPE test_gauge gauge\n" + + "test_gauge{x='1',y='2'} -Inf \\d+\n" + + "test_gauge{x='3',y='4'} \\+Inf \\d+\n" + + "test_gauge{x='5',y='6'} Nan \\d+\n" + + "$").Replace('\'', '"'), + Encoding.UTF8.GetString(buffer, 0, cursor)); + } + + [Fact] + public void SumDoubleInfinites() + { + var buffer = new byte[85000]; + var metrics = new List(); + + using var meter = new Meter(Utils.GetCurrentMethodName()); + using var provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddInMemoryExporter(metrics) + .Build(); + + var counter = meter.CreateCounter("test_counter"); + counter.Add(1.0E308); + counter.Add(1.0E308); + + provider.ForceFlush(); + + var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); + Assert.Matches( + ("^" + + "# TYPE test_counter counter\n" + + "test_counter \\+Inf \\d+\n" + + "$").Replace('\'', '"'), + Encoding.UTF8.GetString(buffer, 0, cursor)); + } + + [Fact] + public void HistogramZeroDimension() + { + var buffer = new byte[85000]; + var metrics = new List(); + + using var meter = new Meter(Utils.GetCurrentMethodName()); + using var provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddInMemoryExporter(metrics) + .Build(); + + var histogram = meter.CreateHistogram("test_histogram"); + histogram.Record(18); + histogram.Record(100); + + provider.ForceFlush(); + + var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); + Assert.Matches( + ("^" + + "# TYPE test_histogram histogram\n" + + "test_histogram_bucket{le='0'} 0 \\d+\n" + + "test_histogram_bucket{le='5'} 0 \\d+\n" + + "test_histogram_bucket{le='10'} 0 \\d+\n" + + "test_histogram_bucket{le='25'} 1 \\d+\n" + + "test_histogram_bucket{le='50'} 1 \\d+\n" + + "test_histogram_bucket{le='75'} 1 \\d+\n" + + "test_histogram_bucket{le='100'} 2 \\d+\n" + + "test_histogram_bucket{le='250'} 2 \\d+\n" + + "test_histogram_bucket{le='500'} 2 \\d+\n" + + "test_histogram_bucket{le='1000'} 2 \\d+\n" + + "test_histogram_bucket{le='\\+Inf'} 2 \\d+\n" + + "test_histogram_sum 118 \\d+\n" + + "test_histogram_count 2 \\d+\n" + + "$").Replace('\'', '"'), + Encoding.UTF8.GetString(buffer, 0, cursor)); + } + + [Fact] + public void HistogramOneDimension() + { + var buffer = new byte[85000]; + var metrics = new List(); + + using var meter = new Meter(Utils.GetCurrentMethodName()); + using var provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddInMemoryExporter(metrics) + .Build(); + + var histogram = meter.CreateHistogram("test_histogram"); + histogram.Record(18, new KeyValuePair("x", "1")); + histogram.Record(100, new KeyValuePair("x", "1")); + + provider.ForceFlush(); + + var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); + Assert.Matches( + ("^" + + "# TYPE test_histogram histogram\n" + + "test_histogram_bucket{x='1',le='0'} 0 \\d+\n" + + "test_histogram_bucket{x='1',le='5'} 0 \\d+\n" + + "test_histogram_bucket{x='1',le='10'} 0 \\d+\n" + + "test_histogram_bucket{x='1',le='25'} 1 \\d+\n" + + "test_histogram_bucket{x='1',le='50'} 1 \\d+\n" + + "test_histogram_bucket{x='1',le='75'} 1 \\d+\n" + + "test_histogram_bucket{x='1',le='100'} 2 \\d+\n" + + "test_histogram_bucket{x='1',le='250'} 2 \\d+\n" + + "test_histogram_bucket{x='1',le='500'} 2 \\d+\n" + + "test_histogram_bucket{x='1',le='1000'} 2 \\d+\n" + + "test_histogram_bucket{x='1',le='\\+Inf'} 2 \\d+\n" + + "test_histogram_sum{x='1'} 118 \\d+\n" + + "test_histogram_count{x='1'} 2 \\d+\n" + + "$").Replace('\'', '"'), + Encoding.UTF8.GetString(buffer, 0, cursor)); + } + + [Fact] + public void HistogramTwoDimensions() + { + var buffer = new byte[85000]; + var metrics = new List(); + + using var meter = new Meter(Utils.GetCurrentMethodName()); + using var provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddInMemoryExporter(metrics) + .Build(); + + var histogram = meter.CreateHistogram("test_histogram"); + histogram.Record(18, new("x", "1"), new("y", "2")); + histogram.Record(100, new("x", "1"), new("y", "2")); + + provider.ForceFlush(); + + var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); + Assert.Matches( + ("^" + + "# TYPE test_histogram histogram\n" + + "test_histogram_bucket{x='1',y='2',le='0'} 0 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='5'} 0 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='10'} 0 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='25'} 1 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='50'} 1 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='75'} 1 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='100'} 2 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='250'} 2 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='500'} 2 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='1000'} 2 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='\\+Inf'} 2 \\d+\n" + + "test_histogram_sum{x='1',y='2'} 118 \\d+\n" + + "test_histogram_count{x='1',y='2'} 2 \\d+\n" + + "$").Replace('\'', '"'), + Encoding.UTF8.GetString(buffer, 0, cursor)); + } + + [Fact] + public void HistogramInfinites() + { + var buffer = new byte[85000]; + var metrics = new List(); + + using var meter = new Meter(Utils.GetCurrentMethodName()); + using var provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddInMemoryExporter(metrics) + .Build(); + + var histogram = meter.CreateHistogram("test_histogram"); + histogram.Record(18); + histogram.Record(double.PositiveInfinity); + histogram.Record(double.PositiveInfinity); + + provider.ForceFlush(); + + var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); + Assert.Matches( + ("^" + + "# TYPE test_histogram histogram\n" + + "test_histogram_bucket{le='0'} 0 \\d+\n" + + "test_histogram_bucket{le='5'} 0 \\d+\n" + + "test_histogram_bucket{le='10'} 0 \\d+\n" + + "test_histogram_bucket{le='25'} 1 \\d+\n" + + "test_histogram_bucket{le='50'} 1 \\d+\n" + + "test_histogram_bucket{le='75'} 1 \\d+\n" + + "test_histogram_bucket{le='100'} 1 \\d+\n" + + "test_histogram_bucket{le='250'} 1 \\d+\n" + + "test_histogram_bucket{le='500'} 1 \\d+\n" + + "test_histogram_bucket{le='1000'} 1 \\d+\n" + + "test_histogram_bucket{le='\\+Inf'} 3 \\d+\n" + + "test_histogram_sum \\+Inf \\d+\n" + + "test_histogram_count 3 \\d+\n" + + "$").Replace('\'', '"'), + Encoding.UTF8.GetString(buffer, 0, cursor)); + } + + [Fact] + public void HistogramNaN() + { + var buffer = new byte[85000]; + var metrics = new List(); + + using var meter = new Meter(Utils.GetCurrentMethodName()); + using var provider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddInMemoryExporter(metrics) + .Build(); + + var histogram = meter.CreateHistogram("test_histogram"); + histogram.Record(18); + histogram.Record(double.PositiveInfinity); + histogram.Record(double.NaN); + + provider.ForceFlush(); + + var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); + Assert.Matches( + ("^" + + "# TYPE test_histogram histogram\n" + + "test_histogram_bucket{le='0'} 0 \\d+\n" + + "test_histogram_bucket{le='5'} 0 \\d+\n" + + "test_histogram_bucket{le='10'} 0 \\d+\n" + + "test_histogram_bucket{le='25'} 1 \\d+\n" + + "test_histogram_bucket{le='50'} 1 \\d+\n" + + "test_histogram_bucket{le='75'} 1 \\d+\n" + + "test_histogram_bucket{le='100'} 1 \\d+\n" + + "test_histogram_bucket{le='250'} 1 \\d+\n" + + "test_histogram_bucket{le='500'} 1 \\d+\n" + + "test_histogram_bucket{le='1000'} 1 \\d+\n" + + "test_histogram_bucket{le='\\+Inf'} 3 \\d+\n" + + "test_histogram_sum Nan \\d+\n" + + "test_histogram_count 3 \\d+\n" + + "$").Replace('\'', '"'), + Encoding.UTF8.GetString(buffer, 0, cursor)); + } + } +} From 3ebf95a832b294d339c895b68d3696fdca3b45c3 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Wed, 6 Jul 2022 16:08:48 -0700 Subject: [PATCH 02/52] RS0016 of the shared project exists --- .../PrometheusExporterMiddleware.cs | 1 + .../PrometheusHttpListener.cs | 1 + .../OpenTelemetry.Exporter.Prometheus.Shared.csproj | 4 ---- .../PrometheusCollectionManager.cs | 2 +- .../PrometheusExporter.cs | 2 +- .../PrometheusExporterEventSource.cs | 2 +- .../PrometheusSerializer.cs | 2 +- .../PrometheusSerializerExt.cs | 2 +- 8 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMiddleware.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMiddleware.cs index 99bc08ba44b..bebf084ce33 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMiddleware.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMiddleware.cs @@ -19,6 +19,7 @@ using System.Diagnostics; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using OpenTelemetry.Exporter.Prometheus.Shared; using OpenTelemetry.Internal; using OpenTelemetry.Metrics; diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs index 4cbee0a2a8a..f051f9200d5 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs @@ -18,6 +18,7 @@ using System.Net; using System.Threading; using System.Threading.Tasks; +using OpenTelemetry.Exporter.Prometheus.Shared; using OpenTelemetry.Internal; namespace OpenTelemetry.Exporter.Prometheus.HttpListener diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj index d2757f77cf0..4be9c289645 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj @@ -12,10 +12,6 @@ $(NoWarn),1591 - - - $(NoWarn),RS0016 - diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs index 8f672645ba0..87f3d6bff02 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs @@ -20,7 +20,7 @@ using System.Threading.Tasks; using OpenTelemetry.Metrics; -namespace OpenTelemetry.Exporter.Prometheus +namespace OpenTelemetry.Exporter.Prometheus.Shared { internal sealed class PrometheusCollectionManager { diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs index c28ea44c752..bc5a2dcefe1 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs @@ -15,7 +15,7 @@ // using System; -using OpenTelemetry.Exporter.Prometheus; +using OpenTelemetry.Exporter.Prometheus.Shared; using OpenTelemetry.Metrics; namespace OpenTelemetry.Exporter diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs index c308d588335..e6e881a0471 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs @@ -18,7 +18,7 @@ using System.Diagnostics.Tracing; using OpenTelemetry.Internal; -namespace OpenTelemetry.Exporter.Prometheus +namespace OpenTelemetry.Exporter.Prometheus.Shared { /// /// EventSource events emitted from the project. diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs index dfe95008ae8..a93ad686de8 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs @@ -21,7 +21,7 @@ using System.Globalization; using System.Runtime.CompilerServices; -namespace OpenTelemetry.Exporter.Prometheus +namespace OpenTelemetry.Exporter.Prometheus.Shared { /// /// Basic PrometheusSerializer which has no OpenTelemetry dependency. diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs index 805a51a2488..1178c3069b6 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs @@ -16,7 +16,7 @@ using OpenTelemetry.Metrics; -namespace OpenTelemetry.Exporter.Prometheus +namespace OpenTelemetry.Exporter.Prometheus.Shared { /// /// OpenTelemetry additions to the PrometheusSerializer. From d2bf46f2009142b0663947feaebc67ce6154eaf8 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Wed, 6 Jul 2022 16:12:30 -0700 Subject: [PATCH 03/52] lint --- src/OpenTelemetry.Exporter.Prometheus.Shared/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/README.md b/src/OpenTelemetry.Exporter.Prometheus.Shared/README.md index fa3b1a61107..e9409b46f4e 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/README.md @@ -1,4 +1,4 @@ - # Prometheus Exporter for OpenTelemetry .NET +# Prometheus Exporter 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) From 0677773bf5667e9670e3ad81e61bb749893c47a0 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Wed, 6 Jul 2022 17:32:21 -0700 Subject: [PATCH 04/52] removed original prometheus project --- OpenTelemetry.sln | 12 - .../Program.cs | 2 +- .../getting-started-prometheus-grafana.csproj | 6 +- .../AspNetCore/Examples.AspNetCore.csproj | 2 +- examples/Console/Examples.Console.csproj | 2 +- examples/Console/TestPrometheusExporter.cs | 12 +- ...ry.Exporter.Prometheus.HttpListener.csproj | 3 +- ...elemetry.Exporter.Prometheus.Shared.csproj | 1 - .../.publicApi/net462/PublicAPI.Shipped.txt | 0 .../.publicApi/net462/PublicAPI.Unshipped.txt | 18 - .../netcoreapp3.1/PublicAPI.Shipped.txt | 0 .../netcoreapp3.1/PublicAPI.Unshipped.txt | 27 -- .../AssemblyInfo.cs | 25 -- .../CHANGELOG.md | 92 ----- .../PrometheusCollectionManager.cs | 240 ----------- .../PrometheusExporterEventSource.cs | 82 ---- .../PrometheusExporterHttpServer.cs | 196 --------- .../PrometheusExporterMiddleware.cs | 105 ----- .../Implementation/PrometheusSerializer.cs | 308 -------------- .../Implementation/PrometheusSerializerExt.cs | 200 --------- .../OpenTelemetry.Exporter.Prometheus.csproj | 34 -- .../PrometheusExporter.cs | 94 ----- ...eusExporterApplicationBuilderExtensions.cs | 154 ------- ...sExporterEndpointRouteBuilderExtensions.cs | 112 ----- ...sExporterMeterProviderBuilderExtensions.cs | 57 --- .../PrometheusExporterOptions.cs | 96 ----- .../README.md | 136 ------ test/Benchmarks/Benchmarks.csproj | 2 +- .../PrometheusSerializerBenchmarks.cs | 4 +- ...Telemetry.Exporter.Prometheus.Tests.csproj | 38 -- .../PrometheusCollectionManagerTests.cs | 161 -------- .../PrometheusExporterHttpServerTests.cs | 177 -------- .../PrometheusExporterMiddlewareTests.cs | 297 -------------- .../PrometheusSerializerTests.cs | 387 ------------------ .../OpenTelemetry.Tests.Stress.Logs.csproj | 2 +- .../OpenTelemetry.Tests.Stress.Metrics.csproj | 2 +- .../Program.cs | 10 +- .../OpenTelemetry.Tests.Stress.csproj | 2 +- test/OpenTelemetry.Tests.Stress/Skeleton.cs | 11 +- 39 files changed, 30 insertions(+), 3079 deletions(-) delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/.publicApi/net462/PublicAPI.Shipped.txt delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/.publicApi/net462/PublicAPI.Unshipped.txt delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/.publicApi/netcoreapp3.1/PublicAPI.Shipped.txt delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/AssemblyInfo.cs delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusCollectionManager.cs delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusExporterEventSource.cs delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusExporterHttpServer.cs delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusExporterMiddleware.cs delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusSerializer.cs delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusSerializerExt.cs delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/OpenTelemetry.Exporter.Prometheus.csproj delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/PrometheusExporter.cs delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterApplicationBuilderExtensions.cs delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterEndpointRouteBuilderExtensions.cs delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterMeterProviderBuilderExtensions.cs delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterOptions.cs delete mode 100644 src/OpenTelemetry.Exporter.Prometheus/README.md delete mode 100644 test/OpenTelemetry.Exporter.Prometheus.Tests/OpenTelemetry.Exporter.Prometheus.Tests.csproj delete mode 100644 test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusCollectionManagerTests.cs delete mode 100644 test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusExporterHttpServerTests.cs delete mode 100644 test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusExporterMiddlewareTests.cs delete mode 100644 test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusSerializerTests.cs diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln index 5e602b37fe6..3a0f535ec41 100644 --- a/OpenTelemetry.sln +++ b/OpenTelemetry.sln @@ -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}" @@ -407,10 +403,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 @@ -435,10 +427,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 diff --git a/docs/metrics/getting-started-prometheus-grafana/Program.cs b/docs/metrics/getting-started-prometheus-grafana/Program.cs index 2e176c39f79..32bfa1c65e1 100644 --- a/docs/metrics/getting-started-prometheus-grafana/Program.cs +++ b/docs/metrics/getting-started-prometheus-grafana/Program.cs @@ -31,7 +31,7 @@ public static void Main() { using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter("MyCompany.MyProduct.MyLibrary") - .AddPrometheusExporter(options => { options.StartHttpListener = true; }) + .AddPrometheusHttpListener() .Build(); Console.WriteLine("Press any key to exit"); diff --git a/docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj b/docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj index 4913a024a94..270cf2e8507 100644 --- a/docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj +++ b/docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj @@ -1,5 +1,5 @@ - - - + + + diff --git a/examples/AspNetCore/Examples.AspNetCore.csproj b/examples/AspNetCore/Examples.AspNetCore.csproj index d92150ac7f8..a1f897d4dcf 100644 --- a/examples/AspNetCore/Examples.AspNetCore.csproj +++ b/examples/AspNetCore/Examples.AspNetCore.csproj @@ -19,7 +19,7 @@ - + diff --git a/examples/Console/Examples.Console.csproj b/examples/Console/Examples.Console.csproj index 830e6dfe32c..8239cd4f5f1 100644 --- a/examples/Console/Examples.Console.csproj +++ b/examples/Console/Examples.Console.csproj @@ -33,7 +33,7 @@ - + diff --git a/examples/Console/TestPrometheusExporter.cs b/examples/Console/TestPrometheusExporter.cs index 935e2530000..434203afc02 100644 --- a/examples/Console/TestPrometheusExporter.cs +++ b/examples/Console/TestPrometheusExporter.cs @@ -48,15 +48,17 @@ internal static object Run(int port) - targets: ["localhost:9464"] */ + Action configureListenerOptions = listenerOptions => + listenerOptions.Prefixes = new string[] { $"http://localhost:{port}/" }; using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(MyMeter.Name) .AddMeter(MyMeter2.Name) - .AddPrometheusExporter(options => + .AddPrometheusHttpListener( + exporterOptions => { - options.StartHttpListener = true; - options.HttpListenerPrefixes = new string[] { $"http://localhost:{port}/" }; - options.ScrapeResponseCacheDurationMilliseconds = 0; - }) + exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0; + }, + configureListenerOptions: configureListenerOptions) .Build(); var process = Process.GetCurrentProcess(); diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj index ea186defdc9..46176cd5271 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj @@ -27,9 +27,8 @@ - + - diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj index 4be9c289645..b000b81a6b4 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj @@ -12,7 +12,6 @@ $(NoWarn),1591 - diff --git a/src/OpenTelemetry.Exporter.Prometheus/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.Prometheus/.publicApi/net462/PublicAPI.Shipped.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/OpenTelemetry.Exporter.Prometheus/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus/.publicApi/net462/PublicAPI.Unshipped.txt deleted file mode 100644 index 70bd44b3df7..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/.publicApi/net462/PublicAPI.Unshipped.txt +++ /dev/null @@ -1,18 +0,0 @@ -OpenTelemetry.Exporter.PrometheusExporter -OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func -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 -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 metrics) -> OpenTelemetry.ExportResult -static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder \ No newline at end of file diff --git a/src/OpenTelemetry.Exporter.Prometheus/.publicApi/netcoreapp3.1/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.Prometheus/.publicApi/netcoreapp3.1/PublicAPI.Shipped.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/OpenTelemetry.Exporter.Prometheus/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt deleted file mode 100644 index 0c45b3f187c..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ /dev/null @@ -1,27 +0,0 @@ -Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions -Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions -OpenTelemetry.Exporter.PrometheusExporter -OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func -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 -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 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 predicate, string path, System.Action 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 predicate) -> Microsoft.AspNetCore.Builder.IApplicationBuilder -static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action 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 configureBranchedPipeline = null) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus/AssemblyInfo.cs b/src/OpenTelemetry.Exporter.Prometheus/AssemblyInfo.cs deleted file mode 100644 index 619668af3b4..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/AssemblyInfo.cs +++ /dev/null @@ -1,25 +0,0 @@ -// -// 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. -// - -using System.Runtime.CompilerServices; - -#if SIGNED -[assembly: InternalsVisibleTo("Benchmarks, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] -[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] -#else -[assembly: InternalsVisibleTo("Benchmarks")] -[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Tests")] -#endif diff --git a/src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md b/src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md deleted file mode 100644 index 5787a17c1db..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md +++ /dev/null @@ -1,92 +0,0 @@ -# Changelog - -## 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 - -## 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 diff --git a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusCollectionManager.cs b/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusCollectionManager.cs deleted file mode 100644 index 8f672645ba0..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusCollectionManager.cs +++ /dev/null @@ -1,240 +0,0 @@ -// -// 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. -// - -using System; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using OpenTelemetry.Metrics; - -namespace OpenTelemetry.Exporter.Prometheus -{ - internal sealed class PrometheusCollectionManager - { - private readonly PrometheusExporter exporter; - private readonly int scrapeResponseCacheDurationInMilliseconds; - private readonly Func, ExportResult> onCollectRef; - private byte[] buffer = new byte[85000]; // encourage the object to live in LOH (large object heap) - private int globalLockState; - private ArraySegment previousDataView; - private DateTime? previousDataViewGeneratedAtUtc; - private int readerCount; - private bool collectionRunning; - private TaskCompletionSource collectionTcs; - - public PrometheusCollectionManager(PrometheusExporter exporter) - { - this.exporter = exporter; - this.scrapeResponseCacheDurationInMilliseconds = this.exporter.Options.ScrapeResponseCacheDurationMilliseconds; - this.onCollectRef = this.OnCollect; - } - -#if NETCOREAPP3_1_OR_GREATER - public ValueTask EnterCollect() -#else - public Task EnterCollect() -#endif - { - this.EnterGlobalLock(); - - // If we are within {ScrapeResponseCacheDurationMilliseconds} of the - // last successful collect, return the previous view. - if (this.previousDataViewGeneratedAtUtc.HasValue - && this.scrapeResponseCacheDurationInMilliseconds > 0 - && this.previousDataViewGeneratedAtUtc.Value.AddMilliseconds(this.scrapeResponseCacheDurationInMilliseconds) >= DateTime.UtcNow) - { - Interlocked.Increment(ref this.readerCount); - this.ExitGlobalLock(); -#if NETCOREAPP3_1_OR_GREATER - return new ValueTask(new CollectionResponse(this.previousDataView, this.previousDataViewGeneratedAtUtc.Value, fromCache: true)); -#else - return Task.FromResult(new CollectionResponse(this.previousDataView, this.previousDataViewGeneratedAtUtc.Value, fromCache: true)); -#endif - } - - // If a collection is already running, return a task to wait on the result. - if (this.collectionRunning) - { - if (this.collectionTcs == null) - { - this.collectionTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - } - - Interlocked.Increment(ref this.readerCount); - this.ExitGlobalLock(); -#if NETCOREAPP3_1_OR_GREATER - return new ValueTask(this.collectionTcs.Task); -#else - return this.collectionTcs.Task; -#endif - } - - this.WaitForReadersToComplete(); - - // Start a collection on the current thread. - this.collectionRunning = true; - this.previousDataViewGeneratedAtUtc = null; - Interlocked.Increment(ref this.readerCount); - this.ExitGlobalLock(); - - CollectionResponse response; - bool result = this.ExecuteCollect(); - if (result) - { - this.previousDataViewGeneratedAtUtc = DateTime.UtcNow; - response = new CollectionResponse(this.previousDataView, this.previousDataViewGeneratedAtUtc.Value, fromCache: false); - } - else - { - response = default; - } - - this.EnterGlobalLock(); - - this.collectionRunning = false; - - if (this.collectionTcs != null) - { - this.collectionTcs.SetResult(response); - this.collectionTcs = null; - } - - this.ExitGlobalLock(); - -#if NETCOREAPP3_1_OR_GREATER - return new ValueTask(response); -#else - return Task.FromResult(response); -#endif - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ExitCollect() - { - Interlocked.Decrement(ref this.readerCount); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void EnterGlobalLock() - { - SpinWait lockWait = default; - while (true) - { - if (Interlocked.CompareExchange(ref this.globalLockState, 1, this.globalLockState) != 0) - { - lockWait.SpinOnce(); - continue; - } - - break; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ExitGlobalLock() - { - this.globalLockState = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void WaitForReadersToComplete() - { - SpinWait readWait = default; - while (true) - { - if (Interlocked.CompareExchange(ref this.readerCount, 0, this.readerCount) != 0) - { - readWait.SpinOnce(); - continue; - } - - break; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool ExecuteCollect() - { - this.exporter.OnExport = this.onCollectRef; - bool result = this.exporter.Collect(Timeout.Infinite); - this.exporter.OnExport = null; - return result; - } - - private ExportResult OnCollect(Batch metrics) - { - int cursor = 0; - - try - { - foreach (var metric in metrics) - { - while (true) - { - try - { - cursor = PrometheusSerializer.WriteMetric(this.buffer, cursor, metric); - break; - } - catch (IndexOutOfRangeException) - { - int bufferSize = this.buffer.Length * 2; - - // there are two cases we might run into the following condition: - // 1. we have many metrics to be exported - in this case we probably want - // to put some upper limit and allow the user to configure it. - // 2. we got an IndexOutOfRangeException which was triggered by some other - // code instead of the buffer[cursor++] - in this case we should give up - // at certain point rather than allocating like crazy. - if (bufferSize > 100 * 1024 * 1024) - { - throw; - } - - var newBuffer = new byte[bufferSize]; - this.buffer.CopyTo(newBuffer, 0); - this.buffer = newBuffer; - } - } - } - - this.previousDataView = new ArraySegment(this.buffer, 0, Math.Max(cursor - 1, 0)); - return ExportResult.Success; - } - catch (Exception) - { - this.previousDataView = new ArraySegment(Array.Empty(), 0, 0); - return ExportResult.Failure; - } - } - - public readonly struct CollectionResponse - { - public CollectionResponse(ArraySegment view, DateTime generatedAtUtc, bool fromCache) - { - this.View = view; - this.GeneratedAtUtc = generatedAtUtc; - this.FromCache = fromCache; - } - - public ArraySegment View { get; } - - public DateTime GeneratedAtUtc { get; } - - public bool FromCache { get; } - } - } -} diff --git a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusExporterEventSource.cs b/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusExporterEventSource.cs deleted file mode 100644 index b678cb436e2..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusExporterEventSource.cs +++ /dev/null @@ -1,82 +0,0 @@ -// -// 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. -// - -using System; -using System.Diagnostics.Tracing; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Exporter.Prometheus -{ - /// - /// EventSource events emitted from the project. - /// - [EventSource(Name = "OpenTelemetry-Exporter-Prometheus")] - internal sealed class PrometheusExporterEventSource : EventSource - { - public static PrometheusExporterEventSource Log = new(); - - [NonEvent] - public void FailedExport(Exception ex) - { - if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) - { - this.FailedExport(ex.ToInvariantString()); - } - } - - [NonEvent] - public void FailedShutdown(Exception ex) - { - if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) - { - this.FailedShutdown(ex.ToInvariantString()); - } - } - - [NonEvent] - public void CanceledExport(Exception ex) - { - if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) - { - this.CanceledExport(ex.ToInvariantString()); - } - } - - [Event(1, Message = "Failed to export metrics: '{0}'", Level = EventLevel.Error)] - public void FailedExport(string exception) - { - this.WriteEvent(1, exception); - } - - [Event(2, Message = "Canceled to export metrics: '{0}'", Level = EventLevel.Error)] - public void CanceledExport(string exception) - { - this.WriteEvent(2, exception); - } - - [Event(3, Message = "Failed to shutdown Metrics server '{0}'", Level = EventLevel.Error)] - public void FailedShutdown(string exception) - { - this.WriteEvent(3, exception); - } - - [Event(4, Message = "No metrics are available for export.", Level = EventLevel.Warning)] - public void NoMetrics() - { - this.WriteEvent(4); - } - } -} diff --git a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusExporterHttpServer.cs b/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusExporterHttpServer.cs deleted file mode 100644 index 554f5cf3470..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusExporterHttpServer.cs +++ /dev/null @@ -1,196 +0,0 @@ -// -// 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. -// - -using System; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Exporter.Prometheus -{ - /// - /// An HTTP listener used to expose Prometheus metrics. - /// - internal sealed class PrometheusExporterHttpServer : IDisposable - { - private readonly PrometheusExporter exporter; - private readonly HttpListener httpListener = new(); - private readonly object syncObject = new(); - - private CancellationTokenSource tokenSource; - private Task workerThread; - - /// - /// Initializes a new instance of the class. - /// - /// The instance. - public PrometheusExporterHttpServer(PrometheusExporter exporter) - { - Guard.ThrowIfNull(exporter); - - this.exporter = exporter; - if ((exporter.Options.HttpListenerPrefixes?.Count ?? 0) <= 0) - { - throw new ArgumentException("No HttpListenerPrefixes were specified on PrometheusExporterOptions."); - } - - string path = exporter.Options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath; - if (!path.StartsWith("/")) - { - path = $"/{path}"; - } - - if (!path.EndsWith("/")) - { - path = $"{path}/"; - } - - foreach (string prefix in exporter.Options.HttpListenerPrefixes) - { - this.httpListener.Prefixes.Add($"{prefix.TrimEnd('/')}{path}"); - } - } - - /// - /// Start Http Server. - /// - /// An optional that can be used to stop the HTTP server. - public void Start(CancellationToken token = default) - { - lock (this.syncObject) - { - if (this.tokenSource != null) - { - return; - } - - // link the passed in token if not null - this.tokenSource = token == default ? - new CancellationTokenSource() : - CancellationTokenSource.CreateLinkedTokenSource(token); - - this.workerThread = Task.Factory.StartNew(this.WorkerProc, default, TaskCreationOptions.LongRunning, TaskScheduler.Default); - } - } - - /// - /// Stop exporter. - /// - public void Stop() - { - lock (this.syncObject) - { - if (this.tokenSource == null) - { - return; - } - - this.tokenSource.Cancel(); - this.workerThread.Wait(); - this.tokenSource = null; - } - } - - /// - public void Dispose() - { - if (this.httpListener != null && this.httpListener.IsListening) - { - this.Stop(); - this.httpListener.Close(); - } - } - - private void WorkerProc() - { - this.httpListener.Start(); - - try - { - using var scope = SuppressInstrumentationScope.Begin(); - while (!this.tokenSource.IsCancellationRequested) - { - var ctxTask = this.httpListener.GetContextAsync(); - ctxTask.Wait(this.tokenSource.Token); - var ctx = ctxTask.Result; - - Task.Run(() => this.ProcessRequestAsync(ctx)); - } - } - catch (OperationCanceledException ex) - { - PrometheusExporterEventSource.Log.CanceledExport(ex); - } - finally - { - try - { - this.httpListener.Stop(); - this.httpListener.Close(); - } - catch (Exception exFromFinally) - { - PrometheusExporterEventSource.Log.FailedShutdown(exFromFinally); - } - } - } - - private async Task ProcessRequestAsync(HttpListenerContext context) - { - try - { - var collectionResponse = await this.exporter.CollectionManager.EnterCollect().ConfigureAwait(false); - try - { - context.Response.Headers.Add("Server", string.Empty); - if (collectionResponse.View.Count > 0) - { - context.Response.StatusCode = 200; - context.Response.Headers.Add("Last-Modified", collectionResponse.GeneratedAtUtc.ToString("R")); - context.Response.ContentType = "text/plain; charset=utf-8; version=0.0.4"; - - await context.Response.OutputStream.WriteAsync(collectionResponse.View.Array, 0, collectionResponse.View.Count).ConfigureAwait(false); - } - else - { - // It's not expected to have no metrics to collect, but it's not necessarily a failure, either. - context.Response.StatusCode = 204; - PrometheusExporterEventSource.Log.NoMetrics(); - } - } - finally - { - this.exporter.CollectionManager.ExitCollect(); - } - } - catch (Exception ex) - { - PrometheusExporterEventSource.Log.FailedExport(ex); - - context.Response.StatusCode = 500; - } - - try - { - context.Response.Close(); - } - catch - { - } - } - } -} diff --git a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusExporterMiddleware.cs b/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusExporterMiddleware.cs deleted file mode 100644 index 826ca135763..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusExporterMiddleware.cs +++ /dev/null @@ -1,105 +0,0 @@ -// -// 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. -// - -#if NETCOREAPP3_1_OR_GREATER -using System; -using System.Diagnostics; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using OpenTelemetry.Internal; -using OpenTelemetry.Metrics; - -namespace OpenTelemetry.Exporter.Prometheus -{ - /// - /// ASP.NET Core middleware for exposing a Prometheus metrics scraping endpoint. - /// - internal sealed class PrometheusExporterMiddleware - { - private readonly PrometheusExporter exporter; - - /// - /// Initializes a new instance of the class. - /// - /// . - /// . - public PrometheusExporterMiddleware(MeterProvider meterProvider, RequestDelegate next) - { - Guard.ThrowIfNull(meterProvider); - - if (!meterProvider.TryFindExporter(out PrometheusExporter exporter)) - { - throw new ArgumentException("A PrometheusExporter could not be found configured on the provided MeterProvider."); - } - - this.exporter = exporter; - } - - internal PrometheusExporterMiddleware(PrometheusExporter exporter) - { - this.exporter = exporter; - } - - /// - /// Invoke. - /// - /// context. - /// Task. - public async Task InvokeAsync(HttpContext httpContext) - { - Debug.Assert(httpContext != null, "httpContext should not be null"); - - var response = httpContext.Response; - - try - { - var collectionResponse = await this.exporter.CollectionManager.EnterCollect().ConfigureAwait(false); - try - { - if (collectionResponse.View.Count > 0) - { - response.StatusCode = 200; - response.Headers.Add("Last-Modified", collectionResponse.GeneratedAtUtc.ToString("R")); - response.ContentType = "text/plain; charset=utf-8; version=0.0.4"; - - await response.Body.WriteAsync(collectionResponse.View.Array, 0, collectionResponse.View.Count).ConfigureAwait(false); - } - else - { - // It's not expected to have no metrics to collect, but it's not necessarily a failure, either. - response.StatusCode = 204; - PrometheusExporterEventSource.Log.NoMetrics(); - } - } - finally - { - this.exporter.CollectionManager.ExitCollect(); - } - } - catch (Exception ex) - { - PrometheusExporterEventSource.Log.FailedExport(ex); - if (!response.HasStarted) - { - response.StatusCode = 500; - } - } - - this.exporter.OnExport = null; - } - } -} -#endif diff --git a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusSerializer.cs b/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusSerializer.cs deleted file mode 100644 index dfe95008ae8..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusSerializer.cs +++ /dev/null @@ -1,308 +0,0 @@ -// -// 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. -// - -#if NETCOREAPP3_1_OR_GREATER -using System; -#endif -using System.Diagnostics; -using System.Globalization; -using System.Runtime.CompilerServices; - -namespace OpenTelemetry.Exporter.Prometheus -{ - /// - /// Basic PrometheusSerializer which has no OpenTelemetry dependency. - /// - internal static partial class PrometheusSerializer - { -#pragma warning disable SA1310 // Field name should not contain an underscore - private const byte ASCII_QUOTATION_MARK = 0x22; // '"' - private const byte ASCII_FULL_STOP = 0x2E; // '.' - private const byte ASCII_HYPHEN_MINUS = 0x2D; // '-' - private const byte ASCII_REVERSE_SOLIDUS = 0x5C; // '\\' - private const byte ASCII_LINEFEED = 0x0A; // `\n` -#pragma warning restore SA1310 // Field name should not contain an underscore - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int WriteDouble(byte[] buffer, int cursor, double value) - { -#if NETCOREAPP3_1_OR_GREATER - if (double.IsFinite(value)) -#else - if (!double.IsInfinity(value) && !double.IsNaN(value)) -#endif - { -#if NETCOREAPP3_1_OR_GREATER - Span span = stackalloc char[128]; - - var result = value.TryFormat(span, out var cchWritten, "G", CultureInfo.InvariantCulture); - Debug.Assert(result, $"{nameof(result)} should be true."); - - for (int i = 0; i < cchWritten; i++) - { - buffer[cursor++] = unchecked((byte)span[i]); - } -#else - cursor = WriteAsciiStringNoEscape(buffer, cursor, value.ToString(CultureInfo.InvariantCulture)); -#endif - } - else if (double.IsPositiveInfinity(value)) - { - cursor = WriteAsciiStringNoEscape(buffer, cursor, "+Inf"); - } - else if (double.IsNegativeInfinity(value)) - { - cursor = WriteAsciiStringNoEscape(buffer, cursor, "-Inf"); - } - else - { - Debug.Assert(double.IsNaN(value), $"{nameof(value)} should be NaN."); - cursor = WriteAsciiStringNoEscape(buffer, cursor, "Nan"); - } - - return cursor; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int WriteLong(byte[] buffer, int cursor, long value) - { -#if NETCOREAPP3_1_OR_GREATER - Span span = stackalloc char[20]; - - var result = value.TryFormat(span, out var cchWritten, "G", CultureInfo.InvariantCulture); - Debug.Assert(result, $"{nameof(result)} should be true."); - - for (int i = 0; i < cchWritten; i++) - { - buffer[cursor++] = unchecked((byte)span[i]); - } -#else - cursor = WriteAsciiStringNoEscape(buffer, cursor, value.ToString(CultureInfo.InvariantCulture)); -#endif - - return cursor; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int WriteAsciiStringNoEscape(byte[] buffer, int cursor, string value) - { - for (int i = 0; i < value.Length; i++) - { - buffer[cursor++] = unchecked((byte)value[i]); - } - - return cursor; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int WriteUnicodeNoEscape(byte[] buffer, int cursor, ushort ordinal) - { - if (ordinal <= 0x7F) - { - buffer[cursor++] = unchecked((byte)ordinal); - } - else if (ordinal <= 0x07FF) - { - buffer[cursor++] = unchecked((byte)(0b_1100_0000 | (ordinal >> 6))); - buffer[cursor++] = unchecked((byte)(0b_1000_0000 | (ordinal & 0b_0011_1111))); - } - else if (ordinal <= 0xFFFF) - { - buffer[cursor++] = unchecked((byte)(0b_1110_0000 | (ordinal >> 12))); - buffer[cursor++] = unchecked((byte)(0b_1000_0000 | ((ordinal >> 6) & 0b_0011_1111))); - buffer[cursor++] = unchecked((byte)(0b_1000_0000 | (ordinal & 0b_0011_1111))); - } - else - { - Debug.Assert(ordinal <= 0xFFFF, ".NET string should not go beyond Unicode BMP."); - } - - return cursor; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int WriteUnicodeString(byte[] buffer, int cursor, string value) - { - for (int i = 0; i < value.Length; i++) - { - var ordinal = (ushort)value[i]; - switch (ordinal) - { - case ASCII_REVERSE_SOLIDUS: - buffer[cursor++] = ASCII_REVERSE_SOLIDUS; - buffer[cursor++] = ASCII_REVERSE_SOLIDUS; - break; - case ASCII_LINEFEED: - buffer[cursor++] = ASCII_REVERSE_SOLIDUS; - buffer[cursor++] = unchecked((byte)'n'); - break; - default: - cursor = WriteUnicodeNoEscape(buffer, cursor, ordinal); - break; - } - } - - return cursor; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int WriteLabelKey(byte[] buffer, int cursor, string value) - { - Debug.Assert(!string.IsNullOrEmpty(value), $"{nameof(value)} should not be null or empty."); - - var ordinal = (ushort)value[0]; - - if (ordinal >= (ushort)'0' && ordinal <= (ushort)'9') - { - buffer[cursor++] = unchecked((byte)'_'); - } - - for (int i = 0; i < value.Length; i++) - { - ordinal = (ushort)value[i]; - - if ((ordinal >= (ushort)'A' && ordinal <= (ushort)'Z') || - (ordinal >= (ushort)'a' && ordinal <= (ushort)'z') || - (ordinal >= (ushort)'0' && ordinal <= (ushort)'9')) - { - buffer[cursor++] = unchecked((byte)ordinal); - } - else - { - buffer[cursor++] = unchecked((byte)'_'); - } - } - - return cursor; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int WriteLabelValue(byte[] buffer, int cursor, string value) - { - Debug.Assert(value != null, $"{nameof(value)} should not be null."); - - for (int i = 0; i < value.Length; i++) - { - var ordinal = (ushort)value[i]; - switch (ordinal) - { - case ASCII_QUOTATION_MARK: - buffer[cursor++] = ASCII_REVERSE_SOLIDUS; - buffer[cursor++] = ASCII_QUOTATION_MARK; - break; - case ASCII_REVERSE_SOLIDUS: - buffer[cursor++] = ASCII_REVERSE_SOLIDUS; - buffer[cursor++] = ASCII_REVERSE_SOLIDUS; - break; - case ASCII_LINEFEED: - buffer[cursor++] = ASCII_REVERSE_SOLIDUS; - buffer[cursor++] = unchecked((byte)'n'); - break; - default: - cursor = WriteUnicodeNoEscape(buffer, cursor, ordinal); - break; - } - } - - return cursor; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int WriteLabel(byte[] buffer, int cursor, string labelKey, object labelValue) - { - cursor = WriteLabelKey(buffer, cursor, labelKey); - buffer[cursor++] = unchecked((byte)'='); - buffer[cursor++] = unchecked((byte)'"'); - - // In Prometheus, a label with an empty label value is considered equivalent to a label that does not exist. - cursor = WriteLabelValue(buffer, cursor, labelValue?.ToString() ?? string.Empty); - buffer[cursor++] = unchecked((byte)'"'); - - return cursor; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int WriteMetricName(byte[] buffer, int cursor, string metricName, string metricUnit = null) - { - Debug.Assert(!string.IsNullOrEmpty(metricName), $"{nameof(metricName)} should not be null or empty."); - - for (int i = 0; i < metricName.Length; i++) - { - var ordinal = (ushort)metricName[i]; - buffer[cursor++] = ordinal switch - { - ASCII_FULL_STOP or ASCII_HYPHEN_MINUS => unchecked((byte)'_'), - _ => unchecked((byte)ordinal), - }; - } - - if (!string.IsNullOrEmpty(metricUnit)) - { - buffer[cursor++] = unchecked((byte)'_'); - - for (int i = 0; i < metricUnit.Length; i++) - { - var ordinal = (ushort)metricUnit[i]; - - if ((ordinal >= (ushort)'A' && ordinal <= (ushort)'Z') || - (ordinal >= (ushort)'a' && ordinal <= (ushort)'z') || - (ordinal >= (ushort)'0' && ordinal <= (ushort)'9')) - { - buffer[cursor++] = unchecked((byte)ordinal); - } - else - { - buffer[cursor++] = unchecked((byte)'_'); - } - } - } - - return cursor; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int WriteHelpText(byte[] buffer, int cursor, string metricName, string metricUnit = null, string metricDescription = null) - { - cursor = WriteAsciiStringNoEscape(buffer, cursor, "# HELP "); - cursor = WriteMetricName(buffer, cursor, metricName, metricUnit); - - if (!string.IsNullOrEmpty(metricDescription)) - { - buffer[cursor++] = unchecked((byte)' '); - cursor = WriteUnicodeString(buffer, cursor, metricDescription); - } - - buffer[cursor++] = ASCII_LINEFEED; - - return cursor; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int WriteTypeInfo(byte[] buffer, int cursor, string metricName, string metricUnit, string metricType) - { - Debug.Assert(!string.IsNullOrEmpty(metricType), $"{nameof(metricType)} should not be null or empty."); - - cursor = WriteAsciiStringNoEscape(buffer, cursor, "# TYPE "); - cursor = WriteMetricName(buffer, cursor, metricName, metricUnit); - buffer[cursor++] = unchecked((byte)' '); - cursor = WriteAsciiStringNoEscape(buffer, cursor, metricType); - - buffer[cursor++] = ASCII_LINEFEED; - - return cursor; - } - } -} diff --git a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusSerializerExt.cs b/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusSerializerExt.cs deleted file mode 100644 index 805a51a2488..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusSerializerExt.cs +++ /dev/null @@ -1,200 +0,0 @@ -// -// 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. -// - -using OpenTelemetry.Metrics; - -namespace OpenTelemetry.Exporter.Prometheus -{ - /// - /// OpenTelemetry additions to the PrometheusSerializer. - /// - internal static partial class PrometheusSerializer - { - private static readonly string[] MetricTypes = new string[] - { - "untyped", "counter", "gauge", "summary", "histogram", "histogram", "histogram", "histogram", "untyped", - }; - - public static int WriteMetric(byte[] buffer, int cursor, Metric metric) - { - if (!string.IsNullOrWhiteSpace(metric.Description)) - { - cursor = WriteHelpText(buffer, cursor, metric.Name, metric.Unit, metric.Description); - } - - int metricType = (int)metric.MetricType >> 4; - cursor = WriteTypeInfo(buffer, cursor, metric.Name, metric.Unit, MetricTypes[metricType]); - - if (!metric.MetricType.IsHistogram()) - { - foreach (ref readonly var metricPoint in metric.GetMetricPoints()) - { - var tags = metricPoint.Tags; - var timestamp = metricPoint.EndTime.ToUnixTimeMilliseconds(); - - // Counter and Gauge - cursor = WriteMetricName(buffer, cursor, metric.Name, metric.Unit); - - if (tags.Count > 0) - { - buffer[cursor++] = unchecked((byte)'{'); - - foreach (var tag in tags) - { - cursor = WriteLabel(buffer, cursor, tag.Key, tag.Value); - buffer[cursor++] = unchecked((byte)','); - } - - buffer[cursor - 1] = unchecked((byte)'}'); // Note: We write the '}' over the last written comma, which is extra. - } - - buffer[cursor++] = unchecked((byte)' '); - - // TODO: MetricType is same for all MetricPoints - // within a given Metric, so this check can avoided - // for each MetricPoint - if (((int)metric.MetricType & 0b_0000_1111) == 0x0a /* I8 */) - { - if (metric.MetricType.IsSum()) - { - cursor = WriteLong(buffer, cursor, metricPoint.GetSumLong()); - } - else - { - cursor = WriteLong(buffer, cursor, metricPoint.GetGaugeLastValueLong()); - } - } - else - { - if (metric.MetricType.IsSum()) - { - cursor = WriteDouble(buffer, cursor, metricPoint.GetSumDouble()); - } - else - { - cursor = WriteDouble(buffer, cursor, metricPoint.GetGaugeLastValueDouble()); - } - } - - buffer[cursor++] = unchecked((byte)' '); - - cursor = WriteLong(buffer, cursor, timestamp); - - buffer[cursor++] = ASCII_LINEFEED; - } - } - else - { - foreach (ref readonly var metricPoint in metric.GetMetricPoints()) - { - var tags = metricPoint.Tags; - var timestamp = metricPoint.EndTime.ToUnixTimeMilliseconds(); - - long totalCount = 0; - foreach (var histogramMeasurement in metricPoint.GetHistogramBuckets()) - { - totalCount += histogramMeasurement.BucketCount; - - cursor = WriteMetricName(buffer, cursor, metric.Name, metric.Unit); - cursor = WriteAsciiStringNoEscape(buffer, cursor, "_bucket{"); - - foreach (var tag in tags) - { - cursor = WriteLabel(buffer, cursor, tag.Key, tag.Value); - buffer[cursor++] = unchecked((byte)','); - } - - cursor = WriteAsciiStringNoEscape(buffer, cursor, "le=\""); - - if (histogramMeasurement.ExplicitBound != double.PositiveInfinity) - { - cursor = WriteDouble(buffer, cursor, histogramMeasurement.ExplicitBound); - } - else - { - cursor = WriteAsciiStringNoEscape(buffer, cursor, "+Inf"); - } - - cursor = WriteAsciiStringNoEscape(buffer, cursor, "\"} "); - - cursor = WriteLong(buffer, cursor, totalCount); - buffer[cursor++] = unchecked((byte)' '); - - cursor = WriteLong(buffer, cursor, timestamp); - - buffer[cursor++] = ASCII_LINEFEED; - } - - // Histogram sum - cursor = WriteMetricName(buffer, cursor, metric.Name, metric.Unit); - cursor = WriteAsciiStringNoEscape(buffer, cursor, "_sum"); - - if (tags.Count > 0) - { - buffer[cursor++] = unchecked((byte)'{'); - - foreach (var tag in tags) - { - cursor = WriteLabel(buffer, cursor, tag.Key, tag.Value); - buffer[cursor++] = unchecked((byte)','); - } - - buffer[cursor - 1] = unchecked((byte)'}'); // Note: We write the '}' over the last written comma, which is extra. - } - - buffer[cursor++] = unchecked((byte)' '); - - cursor = WriteDouble(buffer, cursor, metricPoint.GetHistogramSum()); - buffer[cursor++] = unchecked((byte)' '); - - cursor = WriteLong(buffer, cursor, timestamp); - - buffer[cursor++] = ASCII_LINEFEED; - - // Histogram count - cursor = WriteMetricName(buffer, cursor, metric.Name, metric.Unit); - cursor = WriteAsciiStringNoEscape(buffer, cursor, "_count"); - - if (tags.Count > 0) - { - buffer[cursor++] = unchecked((byte)'{'); - - foreach (var tag in tags) - { - cursor = WriteLabel(buffer, cursor, tag.Key, tag.Value); - buffer[cursor++] = unchecked((byte)','); - } - - buffer[cursor - 1] = unchecked((byte)'}'); // Note: We write the '}' over the last written comma, which is extra. - } - - buffer[cursor++] = unchecked((byte)' '); - - cursor = WriteLong(buffer, cursor, metricPoint.GetHistogramCount()); - buffer[cursor++] = unchecked((byte)' '); - - cursor = WriteLong(buffer, cursor, timestamp); - - buffer[cursor++] = ASCII_LINEFEED; - } - } - - buffer[cursor++] = ASCII_LINEFEED; - - return cursor; - } - } -} diff --git a/src/OpenTelemetry.Exporter.Prometheus/OpenTelemetry.Exporter.Prometheus.csproj b/src/OpenTelemetry.Exporter.Prometheus/OpenTelemetry.Exporter.Prometheus.csproj deleted file mode 100644 index c53448ea4d7..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/OpenTelemetry.Exporter.Prometheus.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - - netcoreapp3.1;net462 - Prometheus exporter for OpenTelemetry .NET - $(PackageTags);prometheus;metrics - core- - - - - $(NoWarn),1591 - - - - - false - - - - - - - - - - - - - - - - diff --git a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporter.cs deleted file mode 100644 index 4af4eb17fc9..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporter.cs +++ /dev/null @@ -1,94 +0,0 @@ -// -// 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. -// - -using System; -using OpenTelemetry.Exporter.Prometheus; -using OpenTelemetry.Metrics; - -namespace OpenTelemetry.Exporter -{ - /// - /// Exporter of OpenTelemetry metrics to Prometheus. - /// - [ExportModes(ExportModes.Pull)] - public class PrometheusExporter : BaseExporter, IPullMetricExporter - { - internal const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started."; - internal readonly PrometheusExporterOptions Options; - private readonly PrometheusExporterHttpServer metricsHttpServer; - private Func funcCollect; - private Func, ExportResult> funcExport; - private bool disposed; - - /// - /// Initializes a new instance of the class. - /// - /// Options for the 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); - } - - public Func Collect - { - get => this.funcCollect; - set => this.funcCollect = value; - } - - internal Func, ExportResult> OnExport - { - get => this.funcExport; - set => this.funcExport = value; - } - - internal PrometheusCollectionManager CollectionManager { get; } - - public override ExportResult Export(in Batch metrics) - { - return this.OnExport(metrics); - } - - protected override void Dispose(bool disposing) - { - if (!this.disposed) - { - if (disposing) - { - this.metricsHttpServer?.Dispose(); - } - - this.disposed = true; - } - - base.Dispose(disposing); - } - } -} diff --git a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterApplicationBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterApplicationBuilderExtensions.cs deleted file mode 100644 index ef96f4722f8..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterApplicationBuilderExtensions.cs +++ /dev/null @@ -1,154 +0,0 @@ -// -// 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. -// - -#if NETCOREAPP3_1_OR_GREATER - -using System; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using OpenTelemetry.Exporter; -using OpenTelemetry.Exporter.Prometheus; -using OpenTelemetry.Internal; -using OpenTelemetry.Metrics; - -namespace Microsoft.AspNetCore.Builder -{ - /// - /// Provides extension methods for to add - /// Prometheus scraping endpoint. - /// - public static class PrometheusExporterApplicationBuilderExtensions - { - /// - /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an - /// instance. - /// - /// Note: A branched pipeline is created for the route - /// specified by . - /// The to add - /// middleware to. - /// A reference to the original for chaining calls. - public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app) - => UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: null, path: null, configureBranchedPipeline: null); - - /// - /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an - /// instance. - /// - /// Note: A branched pipeline is created for the supplied - /// . - /// The to add - /// middleware to. - /// Path to use for the branched pipeline. - /// A reference to the original for chaining calls. - public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app, string path) - { - Guard.ThrowIfNull(path); - return UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: null, path: path, configureBranchedPipeline: null); - } - - /// - /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an - /// instance. - /// - /// Note: A branched pipeline is created for the supplied - /// . - /// The to add - /// middleware to. - /// Predicate for deciding if a given - /// should be branched. - /// A reference to the original for chaining calls. - public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app, Func predicate) - { - Guard.ThrowIfNull(predicate); - return UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: predicate, path: null, configureBranchedPipeline: null); - } - - /// - /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an - /// instance. - /// - /// Note: A branched pipeline is created based on the or . If neither nor are provided then - /// is - /// used. - /// The to add - /// middleware to. - /// Optional - /// containing a otherwise the primary - /// SDK provider will be resolved using application services. - /// Optional predicate for deciding if a given - /// should be branched. If supplied is ignored. - /// Optional path to use for the branched pipeline. - /// Ignored if is supplied. - /// Optional callback to - /// configure the branched pipeline. Called before registration of the - /// Prometheus middleware. - /// A reference to the original for chaining calls. - public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint( - this IApplicationBuilder app, - MeterProvider meterProvider, - Func predicate, - string path, - Action configureBranchedPipeline) - { - // Note: Order is important here. MeterProvider is accessed before - // GetOptions so that any changes made to - // PrometheusExporterOptions in deferred AddPrometheusExporter - // configure actions are reflected. - meterProvider ??= app.ApplicationServices.GetRequiredService(); - - if (predicate == null) - { - if (path == null) - { - var options = app.ApplicationServices.GetOptions(); - - path = options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath; - } - - if (!path.StartsWith("/")) - { - path = $"/{path}"; - } - - return app.Map( - new PathString(path), - builder => - { - configureBranchedPipeline?.Invoke(builder); - builder.UseMiddleware(meterProvider); - }); - } - - return app.MapWhen( - context => predicate(context), - builder => - { - configureBranchedPipeline?.Invoke(builder); - builder.UseMiddleware(meterProvider); - }); - } - } -} -#endif diff --git a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterEndpointRouteBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterEndpointRouteBuilderExtensions.cs deleted file mode 100644 index 02b58a34201..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterEndpointRouteBuilderExtensions.cs +++ /dev/null @@ -1,112 +0,0 @@ -// -// 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. -// - -#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 -{ - /// - /// Provides extension methods for to add - /// Prometheus scraping endpoint. - /// - public static class PrometheusExporterEndpointRouteBuilderExtensions - { - /// - /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an - /// instance. - /// - /// Note: A branched pipeline is created for the route - /// specified by . - /// The to add - /// middleware to. - /// A convention routes for the Prometheus scraping endpoint. - public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEndpointRouteBuilder endpoints) - => MapPrometheusScrapingEndpoint(endpoints, path: null, meterProvider: null, configureBranchedPipeline: null); - - /// - /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an - /// instance. - /// - /// The to add - /// middleware to. - /// The path to use for the branched pipeline. - /// A convention routes for the Prometheus scraping endpoint. - public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEndpointRouteBuilder endpoints, string path) - { - Guard.ThrowIfNull(path); - return MapPrometheusScrapingEndpoint(endpoints, path, meterProvider: null, configureBranchedPipeline: null); - } - - /// - /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an - /// instance. - /// - /// The to add - /// middleware to. - /// Optional path to use for the branched pipeline. - /// If not provided then - /// is used. - /// Optional - /// containing a otherwise the primary - /// SDK provider will be resolved using application services. - /// Optional callback to - /// configure the branched pipeline. Called before registration of the - /// Prometheus middleware. - /// A convention routes for the Prometheus scraping endpoint. - public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint( - this IEndpointRouteBuilder endpoints, - string path = null, - MeterProvider meterProvider = null, - Action configureBranchedPipeline = null) - { - var builder = endpoints.CreateApplicationBuilder(); - - // Note: Order is important here. MeterProvider is accessed before - // GetOptions so that any changes made to - // PrometheusExporterOptions in deferred AddPrometheusExporter - // configure actions are reflected. - meterProvider ??= endpoints.ServiceProvider.GetRequiredService(); - - if (path == null) - { - var options = endpoints.ServiceProvider.GetOptions(); - path = options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath; - } - - if (!path.StartsWith("/")) - { - path = $"/{path}"; - } - - configureBranchedPipeline?.Invoke(builder); - - builder.UseMiddleware(meterProvider); - - return endpoints.Map(new PathString(path), builder.Build()); - } - } -} -#endif diff --git a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterMeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterMeterProviderBuilderExtensions.cs deleted file mode 100644 index ada7d1c90d1..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterMeterProviderBuilderExtensions.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// 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. -// - -using System; -using OpenTelemetry.Exporter; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Metrics -{ - public static class PrometheusExporterMeterProviderBuilderExtensions - { - /// - /// Adds to the . - /// - /// builder to use. - /// Exporter configuration options. - /// The instance of to chain the calls. - public static MeterProviderBuilder AddPrometheusExporter(this MeterProviderBuilder builder, Action configure = null) - { - Guard.ThrowIfNull(builder); - - if (builder is IDeferredMeterProviderBuilder deferredMeterProviderBuilder) - { - return deferredMeterProviderBuilder.Configure((sp, builder) => - { - AddPrometheusExporter(builder, sp.GetOptions(), configure); - }); - } - - return AddPrometheusExporter(builder, new PrometheusExporterOptions(), configure); - } - - private static MeterProviderBuilder AddPrometheusExporter(MeterProviderBuilder builder, PrometheusExporterOptions options, Action configure = null) - { - configure?.Invoke(options); - - var exporter = new PrometheusExporter(options); - var reader = new BaseExportingMetricReader(exporter); - reader.TemporalityPreference = MetricReaderTemporalityPreference.Cumulative; - - return builder.AddReader(reader); - } - } -} diff --git a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterOptions.cs b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterOptions.cs deleted file mode 100644 index 4039e5863e4..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterOptions.cs +++ /dev/null @@ -1,96 +0,0 @@ -// -// 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. -// - -using System; -using System.Collections.Generic; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Exporter -{ - /// - /// options. - /// - public class PrometheusExporterOptions - { - internal const string DefaultScrapeEndpointPath = "/metrics"; - internal Func GetUtcNowDateTimeOffset = () => DateTimeOffset.UtcNow; - - private int scrapeResponseCacheDurationMilliseconds = 10 * 1000; - private IReadOnlyCollection httpListenerPrefixes = new string[] { "http://localhost:9464/" }; - -#if NETCOREAPP3_1_OR_GREATER - /// - /// Gets or sets a value indicating whether or not an http listener - /// should be started. Default value: False. - /// - public bool StartHttpListener { get; set; } -#else - /// - /// Gets or sets a value indicating whether or not an http listener - /// should be started. Default value: True. - /// - public bool StartHttpListener { get; set; } = true; -#endif - - /// - /// Gets or sets the prefixes to use for the http listener. Default - /// value: http://localhost:9464/. - /// - public IReadOnlyCollection 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; - } - } - - /// - /// Gets or sets the path to use for the scraping endpoint. Default value: /metrics. - /// - public string ScrapeEndpointPath { get; set; } = DefaultScrapeEndpointPath; - - /// - /// Gets or sets the cache duration in milliseconds for scrape responses. Default value: 10,000 (10 seconds). - /// - /// - /// Note: Specify 0 to disable response caching. - /// - public int ScrapeResponseCacheDurationMilliseconds - { - get => this.scrapeResponseCacheDurationMilliseconds; - set - { - Guard.ThrowIfOutOfRange(value, min: 0); - - this.scrapeResponseCacheDurationMilliseconds = value; - } - } - } -} diff --git a/src/OpenTelemetry.Exporter.Prometheus/README.md b/src/OpenTelemetry.Exporter.Prometheus/README.md deleted file mode 100644 index ecac7ad4d41..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus/README.md +++ /dev/null @@ -1,136 +0,0 @@ -# Prometheus Exporter 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) - -## Prerequisite - -* [Get Prometheus](https://prometheus.io/docs/introduction/first_steps/) - -## Steps to enable OpenTelemetry.Exporter.Prometheus - -### Step 1: Install Package - -```shell -dotnet add package OpenTelemetry.Exporter.Prometheus -``` - -### Step 2: Configure OpenTelemetry MeterProvider - -* When using OpenTelemetry.Extensions.Hosting package on .NET Core 3.1+: - - ```csharp - services.AddOpenTelemetryMetrics(builder => - { - builder.AddPrometheusExporter(); - }); - ``` - -* Or configure directly: - - Call the `AddPrometheusExporter` `MeterProviderBuilder` extension to - register the Prometheus exporter. - - ```csharp - using var meterProvider = Sdk.CreateMeterProviderBuilder() - .AddPrometheusExporter() - .Build(); - ``` - -### Step 3: Configure Prometheus Scraping Endpoint - -* On .NET Core 3.1+ register Prometheus scraping middleware using the - `UseOpenTelemetryPrometheusScrapingEndpoint` extension: - - ```csharp - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - 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(); - }); - } - ``` - -* 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) - -### ScrapeEndpointPath - -Defines the path for the Prometheus scrape endpoint for -either the HTTP listener or the middleware registered 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) diff --git a/test/Benchmarks/Benchmarks.csproj b/test/Benchmarks/Benchmarks.csproj index d8d2357f96d..0f6ca704c69 100644 --- a/test/Benchmarks/Benchmarks.csproj +++ b/test/Benchmarks/Benchmarks.csproj @@ -26,9 +26,9 @@ - + diff --git a/test/Benchmarks/Exporter/PrometheusSerializerBenchmarks.cs b/test/Benchmarks/Exporter/PrometheusSerializerBenchmarks.cs index 8538b36664e..efd31fa6f86 100644 --- a/test/Benchmarks/Exporter/PrometheusSerializerBenchmarks.cs +++ b/test/Benchmarks/Exporter/PrometheusSerializerBenchmarks.cs @@ -14,15 +14,13 @@ // limitations under the License. // -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 { diff --git a/test/OpenTelemetry.Exporter.Prometheus.Tests/OpenTelemetry.Exporter.Prometheus.Tests.csproj b/test/OpenTelemetry.Exporter.Prometheus.Tests/OpenTelemetry.Exporter.Prometheus.Tests.csproj deleted file mode 100644 index 5b025339874..00000000000 --- a/test/OpenTelemetry.Exporter.Prometheus.Tests/OpenTelemetry.Exporter.Prometheus.Tests.csproj +++ /dev/null @@ -1,38 +0,0 @@ - - - Unit test project for Prometheus Exporter for OpenTelemetry - - net6.0;netcoreapp3.1 - $(TargetFrameworks);net462 - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusCollectionManagerTests.cs b/test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusCollectionManagerTests.cs deleted file mode 100644 index 60945c6f997..00000000000 --- a/test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusCollectionManagerTests.cs +++ /dev/null @@ -1,161 +0,0 @@ -// -// 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. -// - -using System; -using System.Diagnostics.Metrics; -#if NETFRAMEWORK -using System.Linq; -#endif -using System.Threading; -using System.Threading.Tasks; -using OpenTelemetry.Metrics; -using OpenTelemetry.Tests; -using Xunit; - -namespace OpenTelemetry.Exporter.Prometheus.Tests -{ - public sealed class PrometheusCollectionManagerTests - { - [Fact] - public async Task EnterExitCollectTest() - { - using var meter = new Meter(Utils.GetCurrentMethodName()); - - using (var provider = Sdk.CreateMeterProviderBuilder() - .AddMeter(meter.Name) - .AddPrometheusExporter() - .Build()) - { - if (!provider.TryFindExporter(out PrometheusExporter exporter)) - { - throw new InvalidOperationException("PrometheusExporter could not be found on MeterProvider."); - } - - int runningCollectCount = 0; - var collectFunc = exporter.Collect; - exporter.Collect = (timeout) => - { - bool result = collectFunc(timeout); - runningCollectCount++; - Thread.Sleep(5000); - return result; - }; - - var counter = meter.CreateCounter("counter_int", description: "Prometheus help text goes here \n escaping."); - counter.Add(100); - - Task[] collectTasks = new Task[10]; - for (int i = 0; i < collectTasks.Length; i++) - { - collectTasks[i] = Task.Run(async () => - { - var response = await exporter.CollectionManager.EnterCollect().ConfigureAwait(false); - try - { - return new Response - { - CollectionResponse = response, - ViewPayload = response.View.ToArray(), - }; - } - finally - { - exporter.CollectionManager.ExitCollect(); - } - }); - } - - await Task.WhenAll(collectTasks).ConfigureAwait(false); - - Assert.Equal(1, runningCollectCount); - - var firstResponse = collectTasks[0].Result; - - Assert.False(firstResponse.CollectionResponse.FromCache); - - for (int i = 1; i < collectTasks.Length; i++) - { - Assert.Equal(firstResponse.ViewPayload, collectTasks[i].Result.ViewPayload); - Assert.Equal(firstResponse.CollectionResponse.GeneratedAtUtc, collectTasks[i].Result.CollectionResponse.GeneratedAtUtc); - } - - counter.Add(100); - - // This should use the cache and ignore the second counter update. - var task = exporter.CollectionManager.EnterCollect(); - Assert.True(task.IsCompleted); - var response = await task.ConfigureAwait(false); - try - { - Assert.Equal(1, runningCollectCount); - Assert.True(response.FromCache); - Assert.Equal(firstResponse.CollectionResponse.GeneratedAtUtc, response.GeneratedAtUtc); - } - finally - { - exporter.CollectionManager.ExitCollect(); - } - - Thread.Sleep(exporter.Options.ScrapeResponseCacheDurationMilliseconds); - - counter.Add(100); - - for (int i = 0; i < collectTasks.Length; i++) - { - collectTasks[i] = Task.Run(async () => - { - var response = await exporter.CollectionManager.EnterCollect().ConfigureAwait(false); - try - { - return new Response - { - CollectionResponse = response, - ViewPayload = response.View.ToArray(), - }; - } - finally - { - exporter.CollectionManager.ExitCollect(); - } - }); - } - - await Task.WhenAll(collectTasks).ConfigureAwait(false); - - Assert.Equal(2, runningCollectCount); - Assert.NotEqual(firstResponse.ViewPayload, collectTasks[0].Result.ViewPayload); - Assert.NotEqual(firstResponse.CollectionResponse.GeneratedAtUtc, collectTasks[0].Result.CollectionResponse.GeneratedAtUtc); - - firstResponse = collectTasks[0].Result; - - Assert.False(firstResponse.CollectionResponse.FromCache); - - for (int i = 1; i < collectTasks.Length; i++) - { - Assert.Equal(firstResponse.ViewPayload, collectTasks[i].Result.ViewPayload); - Assert.Equal(firstResponse.CollectionResponse.GeneratedAtUtc, collectTasks[i].Result.CollectionResponse.GeneratedAtUtc); - } - } - } - - private class Response - { - public PrometheusCollectionManager.CollectionResponse CollectionResponse; - - public byte[] ViewPayload; - } - } -} diff --git a/test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusExporterHttpServerTests.cs b/test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusExporterHttpServerTests.cs deleted file mode 100644 index 6ba169505d8..00000000000 --- a/test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusExporterHttpServerTests.cs +++ /dev/null @@ -1,177 +0,0 @@ -// -// 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. -// - -using System; -using System.Collections.Generic; -using System.Diagnostics.Metrics; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using OpenTelemetry.Metrics; -using OpenTelemetry.Tests; -using Xunit; - -namespace OpenTelemetry.Exporter.Prometheus.Tests -{ - public class PrometheusExporterHttpServerTests - { - 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")] - [InlineData("http://127.0.0.1")] - [InlineData("http://example.com", "https://example.com", "http://127.0.0.1")] - public void ServerEndpointSanityCheckPositiveTest(params string[] uris) - { - using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder() - .AddPrometheusExporter(opt => - { - opt.HttpListenerPrefixes = uris; - }) - .Build(); - } - - [Theory] - [InlineData("")] - [InlineData(null)] - [InlineData("ftp://example.com")] - [InlineData("http://example.com", "https://example.com", "ftp://example.com")] - public void ServerEndpointSanityCheckNegativeTest(params string[] uris) - { - try - { - using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder() - .AddPrometheusExporter(opt => - { - opt.HttpListenerPrefixes = uris; - }) - .Build(); - } - catch (Exception ex) - { - if (ex is not ArgumentNullException) - { - 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); -#else - Assert.Equal("Prometheus server path should be a valid URI with http/https scheme. (Parameter 'httpListenerPrefixes')", ex.Message); -#endif - } - } - } - - private async Task RunPrometheusExporterHttpServerIntegrationTest(bool skipMetrics = false) - { - Random random = new Random(); - int port = 0; - int retryCount = 5; - MeterProvider provider; - string address = null; - - using var meter = new Meter(this.meterName); - - while (true) - { - 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."); - } - - 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."); - } - } - } - - var tags = new KeyValuePair[] - { - new KeyValuePair("key1", "value1"), - new KeyValuePair("key2", "value2"), - }; - - var counter = meter.CreateCounter("counter_double"); - if (!skipMetrics) - { - counter.Add(100.18D, tags); - counter.Add(0.99D, tags); - } - - using HttpClient client = new HttpClient(); - - using var response = await client.GetAsync($"{address}metrics").ConfigureAwait(false); - - if (!skipMetrics) - { - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.True(response.Content.Headers.Contains("Last-Modified")); - Assert.Equal("text/plain; charset=utf-8; version=0.0.4", response.Content.Headers.ContentType.ToString()); - - Assert.Matches( - "^# TYPE counter_double counter\ncounter_double{key1='value1',key2='value2'} 101.17 \\d+\n$".Replace('\'', '"'), - await response.Content.ReadAsStringAsync().ConfigureAwait(false)); - } - else - { - Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); - } - } - } -} diff --git a/test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusExporterMiddlewareTests.cs b/test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusExporterMiddlewareTests.cs deleted file mode 100644 index a11ea430423..00000000000 --- a/test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusExporterMiddlewareTests.cs +++ /dev/null @@ -1,297 +0,0 @@ -// -// 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. -// - -#if !NETFRAMEWORK -using System; -using System.Collections.Generic; -using System.Diagnostics.Metrics; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using OpenTelemetry.Metrics; -using OpenTelemetry.Tests; -using Xunit; - -namespace OpenTelemetry.Exporter.Prometheus.Tests -{ - public sealed class PrometheusExporterMiddlewareTests - { - private static readonly string MeterName = Utils.GetCurrentMethodName(); - - [Fact] - public Task PrometheusExporterMiddlewareIntegration() - { - return RunPrometheusExporterMiddlewareIntegrationTest( - "/metrics", - app => app.UseOpenTelemetryPrometheusScrapingEndpoint()); - } - - [Fact] - public Task PrometheusExporterMiddlewareIntegration_Options() - { - return RunPrometheusExporterMiddlewareIntegrationTest( - "/metrics_options", - app => app.UseOpenTelemetryPrometheusScrapingEndpoint(), - services => services.Configure(o => o.ScrapeEndpointPath = "metrics_options")); - } - - [Fact] - public Task PrometheusExporterMiddlewareIntegration_OptionsFallback() - { - return RunPrometheusExporterMiddlewareIntegrationTest( - "/metrics", - app => app.UseOpenTelemetryPrometheusScrapingEndpoint(), - services => services.Configure(o => o.ScrapeEndpointPath = null)); - } - - [Fact] - public Task PrometheusExporterMiddlewareIntegration_OptionsViaAddPrometheusExporter() - { - return RunPrometheusExporterMiddlewareIntegrationTest( - "/metrics_from_AddPrometheusExporter", - app => app.UseOpenTelemetryPrometheusScrapingEndpoint(), - configureOptions: o => o.ScrapeEndpointPath = "/metrics_from_AddPrometheusExporter"); - } - - [Fact] - public Task PrometheusExporterMiddlewareIntegration_PathOverride() - { - return RunPrometheusExporterMiddlewareIntegrationTest( - "/metrics_override", - app => app.UseOpenTelemetryPrometheusScrapingEndpoint("/metrics_override")); - } - - [Fact] - public Task PrometheusExporterMiddlewareIntegration_Predicate() - { - return RunPrometheusExporterMiddlewareIntegrationTest( - "/metrics_predicate?enabled=true", - app => app.UseOpenTelemetryPrometheusScrapingEndpoint(httpcontext => httpcontext.Request.Path == "/metrics_predicate" && httpcontext.Request.Query["enabled"] == "true")); - } - - [Fact] - public Task PrometheusExporterMiddlewareIntegration_MixedPredicateAndPath() - { - return RunPrometheusExporterMiddlewareIntegrationTest( - "/metrics_predicate", - app => app.UseOpenTelemetryPrometheusScrapingEndpoint( - meterProvider: null, - predicate: httpcontext => httpcontext.Request.Path == "/metrics_predicate", - path: "/metrics_path", - configureBranchedPipeline: branch => branch.Use((context, next) => - { - context.Response.Headers.Add("X-MiddlewareExecuted", "true"); - return next(); - })), - services => services.Configure(o => o.ScrapeEndpointPath = "/metrics_options"), - validateResponse: rsp => - { - if (!rsp.Headers.TryGetValues("X-MiddlewareExecuted", out IEnumerable headers)) - { - headers = Array.Empty(); - } - - Assert.Equal("true", headers.FirstOrDefault()); - }); - } - - [Fact] - public Task PrometheusExporterMiddlewareIntegration_MixedPath() - { - return RunPrometheusExporterMiddlewareIntegrationTest( - "/metrics_path", - app => app.UseOpenTelemetryPrometheusScrapingEndpoint( - meterProvider: null, - predicate: null, - path: "/metrics_path", - configureBranchedPipeline: branch => branch.Use((context, next) => - { - context.Response.Headers.Add("X-MiddlewareExecuted", "true"); - return next(); - })), - services => services.Configure(o => o.ScrapeEndpointPath = "/metrics_options"), - validateResponse: rsp => - { - if (!rsp.Headers.TryGetValues("X-MiddlewareExecuted", out IEnumerable headers)) - { - headers = Array.Empty(); - } - - Assert.Equal("true", headers.FirstOrDefault()); - }); - } - - [Fact] - public async Task PrometheusExporterMiddlewareIntegration_MeterProvider() - { - using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder() - .AddMeter(MeterName) - .AddPrometheusExporter() - .Build(); - - await RunPrometheusExporterMiddlewareIntegrationTest( - "/metrics", - app => app.UseOpenTelemetryPrometheusScrapingEndpoint( - meterProvider: meterProvider, - predicate: null, - path: null, - configureBranchedPipeline: null), - registerMeterProvider: false).ConfigureAwait(false); - } - - [Fact] - public Task PrometheusExporterMiddlewareIntegration_NoMetrics() - { - return RunPrometheusExporterMiddlewareIntegrationTest( - "/metrics", - app => app.UseOpenTelemetryPrometheusScrapingEndpoint(), - 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 configure, - Action configureServices = null, - Action validateResponse = null, - bool registerMeterProvider = true, - Action configureOptions = null, - bool skipMetrics = false) - { - using var host = await new HostBuilder() - .ConfigureWebHost(webBuilder => webBuilder - .UseTestServer() - .ConfigureServices(services => - { - if (registerMeterProvider) - { - services.AddOpenTelemetryMetrics(builder => builder - .AddMeter(MeterName) - .AddPrometheusExporter(o => - { - configureOptions?.Invoke(o); - if (o.StartHttpListener) - { - throw new InvalidOperationException("StartHttpListener should be false on .NET Core 3.1+."); - } - })); - } - - configureServices?.Invoke(services); - }) - .Configure(configure)) - .StartAsync(); - - var tags = new KeyValuePair[] - { - new KeyValuePair("key1", "value1"), - new KeyValuePair("key2", "value2"), - }; - - using var meter = new Meter(MeterName); - - var beginTimestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); - - var counter = meter.CreateCounter("counter_double"); - if (!skipMetrics) - { - counter.Add(100.18D, tags); - counter.Add(0.99D, tags); - } - - using var response = await host.GetTestClient().GetAsync(path).ConfigureAwait(false); - - var endTimestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); - - if (!skipMetrics) - { - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.True(response.Content.Headers.Contains("Last-Modified")); - Assert.Equal("text/plain; charset=utf-8; version=0.0.4", response.Content.Headers.ContentType.ToString()); - - string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - - string[] lines = content.Split('\n'); - - Assert.Equal( - $"# TYPE counter_double counter", - lines[0]); - - Assert.Contains( - $"counter_double{{key1=\"value1\",key2=\"value2\"}} 101.17", - lines[1]); - - var index = content.LastIndexOf(' '); - - Assert.Equal('\n', content[^1]); - - var timestamp = long.Parse(content.Substring(index, content.Length - index - 1)); - - Assert.True(beginTimestamp <= timestamp && timestamp <= endTimestamp); - } - else - { - Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); - } - - validateResponse?.Invoke(response); - - await host.StopAsync().ConfigureAwait(false); - } - } -} -#endif diff --git a/test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusSerializerTests.cs b/test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusSerializerTests.cs deleted file mode 100644 index cb2ea1d5641..00000000000 --- a/test/OpenTelemetry.Exporter.Prometheus.Tests/PrometheusSerializerTests.cs +++ /dev/null @@ -1,387 +0,0 @@ -// -// 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. -// - -using System.Collections.Generic; -using System.Diagnostics.Metrics; -using System.Text; -using OpenTelemetry.Metrics; -using OpenTelemetry.Tests; -using Xunit; - -namespace OpenTelemetry.Exporter.Prometheus.Tests -{ - public sealed class PrometheusSerializerTests - { - [Fact] - public void GaugeZeroDimension() - { - var buffer = new byte[85000]; - var metrics = new List(); - - using var meter = new Meter(Utils.GetCurrentMethodName()); - using var provider = Sdk.CreateMeterProviderBuilder() - .AddMeter(meter.Name) - .AddInMemoryExporter(metrics) - .Build(); - - meter.CreateObservableGauge("test_gauge", () => 123); - - provider.ForceFlush(); - - var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); - Assert.Matches( - ("^" - + "# TYPE test_gauge gauge\n" - + "test_gauge 123 \\d+\n" - + "$").Replace('\'', '"'), - Encoding.UTF8.GetString(buffer, 0, cursor)); - } - - [Fact] - public void GaugeZeroDimensionWithDescription() - { - var buffer = new byte[85000]; - var metrics = new List(); - - using var meter = new Meter(Utils.GetCurrentMethodName()); - using var provider = Sdk.CreateMeterProviderBuilder() - .AddMeter(meter.Name) - .AddInMemoryExporter(metrics) - .Build(); - - meter.CreateObservableGauge("test_gauge", () => 123, description: "Hello, world!"); - - provider.ForceFlush(); - - var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); - Assert.Matches( - ("^" - + "# HELP test_gauge Hello, world!\n" - + "# TYPE test_gauge gauge\n" - + "test_gauge 123 \\d+\n" - + "$").Replace('\'', '"'), - Encoding.UTF8.GetString(buffer, 0, cursor)); - } - - [Fact] - public void GaugeZeroDimensionWithUnit() - { - var buffer = new byte[85000]; - var metrics = new List(); - - using var meter = new Meter(Utils.GetCurrentMethodName()); - using var provider = Sdk.CreateMeterProviderBuilder() - .AddMeter(meter.Name) - .AddInMemoryExporter(metrics) - .Build(); - - meter.CreateObservableGauge("test_gauge", () => 123, unit: "seconds"); - - provider.ForceFlush(); - - var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); - Assert.Matches( - ("^" - + "# TYPE test_gauge_seconds gauge\n" - + "test_gauge_seconds 123 \\d+\n" - + "$").Replace('\'', '"'), - Encoding.UTF8.GetString(buffer, 0, cursor)); - } - - [Fact] - public void GaugeOneDimension() - { - var buffer = new byte[85000]; - var metrics = new List(); - - using var meter = new Meter(Utils.GetCurrentMethodName()); - using var provider = Sdk.CreateMeterProviderBuilder() - .AddMeter(meter.Name) - .AddInMemoryExporter(metrics) - .Build(); - - meter.CreateObservableGauge( - "test_gauge", - () => new Measurement(123, new KeyValuePair("tagKey", "tagValue"))); - - provider.ForceFlush(); - - var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); - Assert.Matches( - ("^" - + "# TYPE test_gauge gauge\n" - + "test_gauge{tagKey='tagValue'} 123 \\d+\n" - + "$").Replace('\'', '"'), - Encoding.UTF8.GetString(buffer, 0, cursor)); - } - - [Fact] - public void GaugeDoubleSubnormal() - { - var buffer = new byte[85000]; - var metrics = new List(); - - using var meter = new Meter(Utils.GetCurrentMethodName()); - using var provider = Sdk.CreateMeterProviderBuilder() - .AddMeter(meter.Name) - .AddInMemoryExporter(metrics) - .Build(); - - meter.CreateObservableGauge("test_gauge", () => new List> - { - new(double.NegativeInfinity, new("x", "1"), new("y", "2")), - new(double.PositiveInfinity, new("x", "3"), new("y", "4")), - new(double.NaN, new("x", "5"), new("y", "6")), - }); - - provider.ForceFlush(); - - var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); - Assert.Matches( - ("^" - + "# TYPE test_gauge gauge\n" - + "test_gauge{x='1',y='2'} -Inf \\d+\n" - + "test_gauge{x='3',y='4'} \\+Inf \\d+\n" - + "test_gauge{x='5',y='6'} Nan \\d+\n" - + "$").Replace('\'', '"'), - Encoding.UTF8.GetString(buffer, 0, cursor)); - } - - [Fact] - public void SumDoubleInfinites() - { - var buffer = new byte[85000]; - var metrics = new List(); - - using var meter = new Meter(Utils.GetCurrentMethodName()); - using var provider = Sdk.CreateMeterProviderBuilder() - .AddMeter(meter.Name) - .AddInMemoryExporter(metrics) - .Build(); - - var counter = meter.CreateCounter("test_counter"); - counter.Add(1.0E308); - counter.Add(1.0E308); - - provider.ForceFlush(); - - var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); - Assert.Matches( - ("^" - + "# TYPE test_counter counter\n" - + "test_counter \\+Inf \\d+\n" - + "$").Replace('\'', '"'), - Encoding.UTF8.GetString(buffer, 0, cursor)); - } - - [Fact] - public void HistogramZeroDimension() - { - var buffer = new byte[85000]; - var metrics = new List(); - - using var meter = new Meter(Utils.GetCurrentMethodName()); - using var provider = Sdk.CreateMeterProviderBuilder() - .AddMeter(meter.Name) - .AddInMemoryExporter(metrics) - .Build(); - - var histogram = meter.CreateHistogram("test_histogram"); - histogram.Record(18); - histogram.Record(100); - - provider.ForceFlush(); - - var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); - Assert.Matches( - ("^" - + "# TYPE test_histogram histogram\n" - + "test_histogram_bucket{le='0'} 0 \\d+\n" - + "test_histogram_bucket{le='5'} 0 \\d+\n" - + "test_histogram_bucket{le='10'} 0 \\d+\n" - + "test_histogram_bucket{le='25'} 1 \\d+\n" - + "test_histogram_bucket{le='50'} 1 \\d+\n" - + "test_histogram_bucket{le='75'} 1 \\d+\n" - + "test_histogram_bucket{le='100'} 2 \\d+\n" - + "test_histogram_bucket{le='250'} 2 \\d+\n" - + "test_histogram_bucket{le='500'} 2 \\d+\n" - + "test_histogram_bucket{le='1000'} 2 \\d+\n" - + "test_histogram_bucket{le='\\+Inf'} 2 \\d+\n" - + "test_histogram_sum 118 \\d+\n" - + "test_histogram_count 2 \\d+\n" - + "$").Replace('\'', '"'), - Encoding.UTF8.GetString(buffer, 0, cursor)); - } - - [Fact] - public void HistogramOneDimension() - { - var buffer = new byte[85000]; - var metrics = new List(); - - using var meter = new Meter(Utils.GetCurrentMethodName()); - using var provider = Sdk.CreateMeterProviderBuilder() - .AddMeter(meter.Name) - .AddInMemoryExporter(metrics) - .Build(); - - var histogram = meter.CreateHistogram("test_histogram"); - histogram.Record(18, new KeyValuePair("x", "1")); - histogram.Record(100, new KeyValuePair("x", "1")); - - provider.ForceFlush(); - - var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); - Assert.Matches( - ("^" - + "# TYPE test_histogram histogram\n" - + "test_histogram_bucket{x='1',le='0'} 0 \\d+\n" - + "test_histogram_bucket{x='1',le='5'} 0 \\d+\n" - + "test_histogram_bucket{x='1',le='10'} 0 \\d+\n" - + "test_histogram_bucket{x='1',le='25'} 1 \\d+\n" - + "test_histogram_bucket{x='1',le='50'} 1 \\d+\n" - + "test_histogram_bucket{x='1',le='75'} 1 \\d+\n" - + "test_histogram_bucket{x='1',le='100'} 2 \\d+\n" - + "test_histogram_bucket{x='1',le='250'} 2 \\d+\n" - + "test_histogram_bucket{x='1',le='500'} 2 \\d+\n" - + "test_histogram_bucket{x='1',le='1000'} 2 \\d+\n" - + "test_histogram_bucket{x='1',le='\\+Inf'} 2 \\d+\n" - + "test_histogram_sum{x='1'} 118 \\d+\n" - + "test_histogram_count{x='1'} 2 \\d+\n" - + "$").Replace('\'', '"'), - Encoding.UTF8.GetString(buffer, 0, cursor)); - } - - [Fact] - public void HistogramTwoDimensions() - { - var buffer = new byte[85000]; - var metrics = new List(); - - using var meter = new Meter(Utils.GetCurrentMethodName()); - using var provider = Sdk.CreateMeterProviderBuilder() - .AddMeter(meter.Name) - .AddInMemoryExporter(metrics) - .Build(); - - var histogram = meter.CreateHistogram("test_histogram"); - histogram.Record(18, new("x", "1"), new("y", "2")); - histogram.Record(100, new("x", "1"), new("y", "2")); - - provider.ForceFlush(); - - var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); - Assert.Matches( - ("^" - + "# TYPE test_histogram histogram\n" - + "test_histogram_bucket{x='1',y='2',le='0'} 0 \\d+\n" - + "test_histogram_bucket{x='1',y='2',le='5'} 0 \\d+\n" - + "test_histogram_bucket{x='1',y='2',le='10'} 0 \\d+\n" - + "test_histogram_bucket{x='1',y='2',le='25'} 1 \\d+\n" - + "test_histogram_bucket{x='1',y='2',le='50'} 1 \\d+\n" - + "test_histogram_bucket{x='1',y='2',le='75'} 1 \\d+\n" - + "test_histogram_bucket{x='1',y='2',le='100'} 2 \\d+\n" - + "test_histogram_bucket{x='1',y='2',le='250'} 2 \\d+\n" - + "test_histogram_bucket{x='1',y='2',le='500'} 2 \\d+\n" - + "test_histogram_bucket{x='1',y='2',le='1000'} 2 \\d+\n" - + "test_histogram_bucket{x='1',y='2',le='\\+Inf'} 2 \\d+\n" - + "test_histogram_sum{x='1',y='2'} 118 \\d+\n" - + "test_histogram_count{x='1',y='2'} 2 \\d+\n" - + "$").Replace('\'', '"'), - Encoding.UTF8.GetString(buffer, 0, cursor)); - } - - [Fact] - public void HistogramInfinites() - { - var buffer = new byte[85000]; - var metrics = new List(); - - using var meter = new Meter(Utils.GetCurrentMethodName()); - using var provider = Sdk.CreateMeterProviderBuilder() - .AddMeter(meter.Name) - .AddInMemoryExporter(metrics) - .Build(); - - var histogram = meter.CreateHistogram("test_histogram"); - histogram.Record(18); - histogram.Record(double.PositiveInfinity); - histogram.Record(double.PositiveInfinity); - - provider.ForceFlush(); - - var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); - Assert.Matches( - ("^" - + "# TYPE test_histogram histogram\n" - + "test_histogram_bucket{le='0'} 0 \\d+\n" - + "test_histogram_bucket{le='5'} 0 \\d+\n" - + "test_histogram_bucket{le='10'} 0 \\d+\n" - + "test_histogram_bucket{le='25'} 1 \\d+\n" - + "test_histogram_bucket{le='50'} 1 \\d+\n" - + "test_histogram_bucket{le='75'} 1 \\d+\n" - + "test_histogram_bucket{le='100'} 1 \\d+\n" - + "test_histogram_bucket{le='250'} 1 \\d+\n" - + "test_histogram_bucket{le='500'} 1 \\d+\n" - + "test_histogram_bucket{le='1000'} 1 \\d+\n" - + "test_histogram_bucket{le='\\+Inf'} 3 \\d+\n" - + "test_histogram_sum \\+Inf \\d+\n" - + "test_histogram_count 3 \\d+\n" - + "$").Replace('\'', '"'), - Encoding.UTF8.GetString(buffer, 0, cursor)); - } - - [Fact] - public void HistogramNaN() - { - var buffer = new byte[85000]; - var metrics = new List(); - - using var meter = new Meter(Utils.GetCurrentMethodName()); - using var provider = Sdk.CreateMeterProviderBuilder() - .AddMeter(meter.Name) - .AddInMemoryExporter(metrics) - .Build(); - - var histogram = meter.CreateHistogram("test_histogram"); - histogram.Record(18); - histogram.Record(double.PositiveInfinity); - histogram.Record(double.NaN); - - provider.ForceFlush(); - - var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]); - Assert.Matches( - ("^" - + "# TYPE test_histogram histogram\n" - + "test_histogram_bucket{le='0'} 0 \\d+\n" - + "test_histogram_bucket{le='5'} 0 \\d+\n" - + "test_histogram_bucket{le='10'} 0 \\d+\n" - + "test_histogram_bucket{le='25'} 1 \\d+\n" - + "test_histogram_bucket{le='50'} 1 \\d+\n" - + "test_histogram_bucket{le='75'} 1 \\d+\n" - + "test_histogram_bucket{le='100'} 1 \\d+\n" - + "test_histogram_bucket{le='250'} 1 \\d+\n" - + "test_histogram_bucket{le='500'} 1 \\d+\n" - + "test_histogram_bucket{le='1000'} 1 \\d+\n" - + "test_histogram_bucket{le='\\+Inf'} 3 \\d+\n" - + "test_histogram_sum Nan \\d+\n" - + "test_histogram_count 3 \\d+\n" - + "$").Replace('\'', '"'), - Encoding.UTF8.GetString(buffer, 0, cursor)); - } - } -} diff --git a/test/OpenTelemetry.Tests.Stress.Logs/OpenTelemetry.Tests.Stress.Logs.csproj b/test/OpenTelemetry.Tests.Stress.Logs/OpenTelemetry.Tests.Stress.Logs.csproj index 8093f8d6d6f..ff88e203fb4 100644 --- a/test/OpenTelemetry.Tests.Stress.Logs/OpenTelemetry.Tests.Stress.Logs.csproj +++ b/test/OpenTelemetry.Tests.Stress.Logs/OpenTelemetry.Tests.Stress.Logs.csproj @@ -8,7 +8,7 @@ - + diff --git a/test/OpenTelemetry.Tests.Stress.Metrics/OpenTelemetry.Tests.Stress.Metrics.csproj b/test/OpenTelemetry.Tests.Stress.Metrics/OpenTelemetry.Tests.Stress.Metrics.csproj index 46fcfb47bd2..49134943927 100644 --- a/test/OpenTelemetry.Tests.Stress.Metrics/OpenTelemetry.Tests.Stress.Metrics.csproj +++ b/test/OpenTelemetry.Tests.Stress.Metrics/OpenTelemetry.Tests.Stress.Metrics.csproj @@ -14,7 +14,7 @@ - + diff --git a/test/OpenTelemetry.Tests.Stress.Metrics/Program.cs b/test/OpenTelemetry.Tests.Stress.Metrics/Program.cs index 8838a1854c9..8d671b4c7c9 100644 --- a/test/OpenTelemetry.Tests.Stress.Metrics/Program.cs +++ b/test/OpenTelemetry.Tests.Stress.Metrics/Program.cs @@ -46,12 +46,12 @@ public static void Main() using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(TestMeter.Name) - .AddPrometheusExporter(options => + .AddPrometheusHttpListener( + exporterOptions => { - options.StartHttpListener = true; - options.HttpListenerPrefixes = new string[] { $"http://localhost:9185/" }; - options.ScrapeResponseCacheDurationMilliseconds = 0; - }) + exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0; + }, + listenerOptions => listenerOptions.Prefixes = new string[] { $"http://localhost:9185/" }) .Build(); Stress(prometheusPort: 9184); diff --git a/test/OpenTelemetry.Tests.Stress/OpenTelemetry.Tests.Stress.csproj b/test/OpenTelemetry.Tests.Stress/OpenTelemetry.Tests.Stress.csproj index 32481d41662..73b65c17227 100644 --- a/test/OpenTelemetry.Tests.Stress/OpenTelemetry.Tests.Stress.csproj +++ b/test/OpenTelemetry.Tests.Stress/OpenTelemetry.Tests.Stress.csproj @@ -10,6 +10,6 @@ - + diff --git a/test/OpenTelemetry.Tests.Stress/Skeleton.cs b/test/OpenTelemetry.Tests.Stress/Skeleton.cs index adcf5cbbe22..e09c12a83a6 100644 --- a/test/OpenTelemetry.Tests.Stress/Skeleton.cs +++ b/test/OpenTelemetry.Tests.Stress/Skeleton.cs @@ -78,12 +78,13 @@ public static void Stress(int concurrency = 0, int prometheusPort = 0) using var meterProvider = prometheusPort != 0 ? Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddRuntimeInstrumentation() - .AddPrometheusExporter(options => + .AddPrometheusHttpListener( + exporterOptions => { - options.StartHttpListener = true; - options.HttpListenerPrefixes = new string[] { $"http://localhost:{prometheusPort}/" }; - options.ScrapeResponseCacheDurationMilliseconds = 0; - }) + exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0; + }, + listenerOptions => + listenerOptions.Prefixes = new string[] { $"http://localhost:{prometheusPort}/", }) .Build() : null; var statistics = new long[concurrency]; From 9fae7a12fa2154d3f1f78fff76b8425b92b72bf0 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Thu, 7 Jul 2022 12:11:14 -0700 Subject: [PATCH 05/52] fix docs links --- docs/metrics/customizing-the-sdk/README.md | 3 ++- docs/metrics/extending-the-sdk/README.md | 3 ++- .../README.md | 21 ++++++++++--------- .../README.md | 2 +- src/OpenTelemetry/AssemblyInfo.cs | 1 - test/OpenTelemetry.Tests.Stress/README.md | 2 +- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/docs/metrics/customizing-the-sdk/README.md b/docs/metrics/customizing-the-sdk/README.md index 5491faf1914..eeeb64ef819 100644 --- a/docs/metrics/customizing-the-sdk/README.md +++ b/docs/metrics/customizing-the-sdk/README.md @@ -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 diff --git a/docs/metrics/extending-the-sdk/README.md b/docs/metrics/extending-the-sdk/README.md index 7671bb420ca..0777c8f8f1b 100644 --- a/docs/metrics/extending-the-sdk/README.md +++ b/docs/metrics/extending-the-sdk/README.md @@ -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: diff --git a/docs/metrics/getting-started-prometheus-grafana/README.md b/docs/metrics/getting-started-prometheus-grafana/README.md index e58245a6b04..61b066d50f1 100644 --- a/docs/metrics/getting-started-prometheus-grafana/README.md +++ b/docs/metrics/getting-started-prometheus-grafana/README.md @@ -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), +[PrometheusExporterOptions.Prefixes](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md#httplistenerprefixes), which is `http://localhost:9464/` by default. ```mermaid @@ -60,7 +61,7 @@ graph LR subgraph SDK MeterProvider MetricReader[BaseExportingMetricReader] - PrometheusExporter["PrometheusExporter
(http://localhost:9464/)"] + PrometheusHttpListener["PrometheusHttpListener
(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
(listening at #quot;http://localhost:9464/#quot;)"] -->|HTTP GET| PrometheusScraper{{"Prometheus scraper
(polling #quot;http://localhost:9464/metrics#quot; every 10 seconds)"}} +PrometheusHttpListener["PrometheusHttpListener
(listening at #quot;http://localhost:9464/#quot;)"] -->|HTTP GET| PrometheusScraper{{"Prometheus scraper
(polling #quot;http://localhost:9464/metrics#quot; every 10 seconds)"}} PrometheusScraper --> PrometheusDatabase[("Prometheus TSDB (time series database)")] PrometheusDatabase -->|http://localhost:9090/graph| PrometheusUI["Browser
(Prometheus Dashboard)"] PrometheusDatabase -->|http://localhost:9090/api/| Grafana[Grafana Server] diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md index 0e9b528bb11..29c9088a4b5 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md @@ -38,7 +38,7 @@ dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore ### 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 diff --git a/src/OpenTelemetry/AssemblyInfo.cs b/src/OpenTelemetry/AssemblyInfo.cs index 868e2539a8e..e9a02b45bc6 100644 --- a/src/OpenTelemetry/AssemblyInfo.cs +++ b/src/OpenTelemetry/AssemblyInfo.cs @@ -18,7 +18,6 @@ [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.Exporter.Prometheus.Shared" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore" + AssemblyInfo.PublicKey)] diff --git a/test/OpenTelemetry.Tests.Stress/README.md b/test/OpenTelemetry.Tests.Stress/README.md index 4b7b10ddb77..0d3cc381ec0 100644 --- a/test/OpenTelemetry.Tests.Stress/README.md +++ b/test/OpenTelemetry.Tests.Stress/README.md @@ -41,7 +41,7 @@ Running (concurrency = 1), press 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/): From fd111e11e7d01ee1aea07389e130b6817d90da90 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Thu, 7 Jul 2022 14:17:32 -0700 Subject: [PATCH 06/52] partial fix --- .../.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt index 7e944dd0810..db75beb3953 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -1,5 +1,6 @@ Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions +OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions 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 predicate, string path, System.Action configureBranchedPipeline) -> Microsoft.AspNetCore.Builder.IApplicationBuilder static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string path) -> Microsoft.AspNetCore.Builder.IApplicationBuilder @@ -7,3 +8,4 @@ static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensio 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 = null, OpenTelemetry.Metrics.MeterProvider meterProvider = null, System.Action 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 configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder From 037f697da3c634c0549aedf7e455ac34fb017fbc Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Thu, 7 Jul 2022 14:24:11 -0700 Subject: [PATCH 07/52] fixes api --- .../.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt index db75beb3953..8b9927b7222 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -1,6 +1,16 @@ Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions +OpenTelemetry.Exporter.PrometheusExporter +OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func +OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void +OpenTelemetry.Exporter.PrometheusExporterOptions +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.Metrics.PrometheusExporterMeterProviderBuilderExtensions +override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch 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 predicate, string path, System.Action configureBranchedPipeline) -> Microsoft.AspNetCore.Builder.IApplicationBuilder static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string path) -> Microsoft.AspNetCore.Builder.IApplicationBuilder From 735ae6843342266e08679c8415de7e857ed77b44 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Thu, 7 Jul 2022 14:25:38 -0700 Subject: [PATCH 08/52] fix doc --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 30ee80bb0df..a02200ddfd1 100644 --- a/README.md +++ b/README.md @@ -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 From 727e5579c1f54a3dabd9f46f903d63ad1f108c99 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Thu, 7 Jul 2022 14:34:17 -0700 Subject: [PATCH 09/52] listener api --- .../.publicApi/net462/PublicAPI.Unshipped.txt | 14 ++++++++++++++ ...lemetry.Exporter.Prometheus.HttpListener.csproj | 4 ---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt index 346555d9a3a..5c99083f6de 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt @@ -3,5 +3,19 @@ OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Dispose() OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.PrometheusHttpListener(OpenTelemetry.Exporter.PrometheusExporter exporter, OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions options) -> void OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Start(System.Threading.CancellationToken token = default(System.Threading.CancellationToken)) -> void OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Stop() -> void +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.get -> System.Collections.Generic.IReadOnlyCollection +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.set -> void +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.PrometheusHttpListenerOptions() -> void +OpenTelemetry.Exporter.PrometheusExporter +OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func +OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void +OpenTelemetry.Exporter.PrometheusExporterOptions +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.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions +override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder \ No newline at end of file diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj index 46176cd5271..c9f57b60386 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj @@ -16,10 +16,6 @@ $(NoWarn),1702 - - $(NoWarn),RS0016 - - From 147fe100e5ad4a9e82503dfe0242de1dad0e6936 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Thu, 7 Jul 2022 15:46:47 -0700 Subject: [PATCH 10/52] comment --- src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md index 29c9088a4b5..00fad0c4196 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md @@ -80,8 +80,8 @@ for example use. ### 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 From 0e1335764e55ad5d4683918f4c1f3b3729cf7477 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Fri, 8 Jul 2022 14:20:47 -0700 Subject: [PATCH 11/52] added nestandard2.0 to httpListener --- .../getting-started-prometheus-grafana.csproj | 3 +++ .../netstandard2.0/PublicAPI.Shipped.txt | 0 .../netstandard2.0/PublicAPI.Unshipped.txt | 21 +++++++++++++++++++ ...ry.Exporter.Prometheus.HttpListener.csproj | 2 +- 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Shipped.txt create mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt diff --git a/docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj b/docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj index 270cf2e8507..1fcceb2b39b 100644 --- a/docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj +++ b/docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj @@ -1,4 +1,7 @@ + + netstandard2.0 + diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..5c99083f6de --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -0,0 +1,21 @@ +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Dispose() -> void +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.PrometheusHttpListener(OpenTelemetry.Exporter.PrometheusExporter exporter, OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions options) -> void +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Start(System.Threading.CancellationToken token = default(System.Threading.CancellationToken)) -> void +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Stop() -> void +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.get -> System.Collections.Generic.IReadOnlyCollection +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.set -> void +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.PrometheusHttpListenerOptions() -> void +OpenTelemetry.Exporter.PrometheusExporter +OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func +OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void +OpenTelemetry.Exporter.PrometheusExporterOptions +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.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions +override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult +static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder \ No newline at end of file diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj index c9f57b60386..4d497aabaf7 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj @@ -2,7 +2,7 @@ - net462 + net462;netstandard2.0 Prometheus exporter HttpListener for OpenTelemetry .NET $(PackageTags);prometheus;metrics core- From d201b247d678589a18889b93ba074465d6fabd50 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Fri, 8 Jul 2022 17:54:18 -0700 Subject: [PATCH 12/52] comments --- examples/Console/TestPrometheusExporter.cs | 9 ++------ .../README.md | 7 +++--- .../.publicApi/net462/PublicAPI.Unshipped.txt | 7 +----- .../netstandard2.0/PublicAPI.Unshipped.txt | 7 +----- ...ry.Exporter.Prometheus.HttpListener.csproj | 9 +------- ...pListenerMeterProviderBuilderExtensions.cs | 10 +++++++++ .../PrometheusHttpListener.cs | 22 +++++-------------- .../PrometheusHttpListenerOptions.cs | 3 +++ .../README.md | 12 +++------- .../AssemblyInfo.cs | 4 ---- ...elemetry.Exporter.Prometheus.Shared.csproj | 5 ++--- .../PrometheusExporter.cs | 4 ++++ ...sExporterMeterProviderBuilderExtensions.cs | 3 +++ .../Program.cs | 7 ++---- test/OpenTelemetry.Tests.Stress/Skeleton.cs | 8 ++----- 15 files changed, 43 insertions(+), 74 deletions(-) diff --git a/examples/Console/TestPrometheusExporter.cs b/examples/Console/TestPrometheusExporter.cs index 434203afc02..29fc3879f39 100644 --- a/examples/Console/TestPrometheusExporter.cs +++ b/examples/Console/TestPrometheusExporter.cs @@ -48,17 +48,12 @@ internal static object Run(int port) - targets: ["localhost:9464"] */ - Action configureListenerOptions = listenerOptions => - listenerOptions.Prefixes = new string[] { $"http://localhost:{port}/" }; using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(MyMeter.Name) .AddMeter(MyMeter2.Name) .AddPrometheusHttpListener( - exporterOptions => - { - exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0; - }, - configureListenerOptions: configureListenerOptions) + exporterOptions => exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0, + listenerOptions => listenerOptions.Prefixes = new string[] { $"http://localhost:{port}/" }) .Build(); var process = Process.GetCurrentProcess(); diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md index 00fad0c4196..3af10277c46 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md @@ -31,9 +31,10 @@ dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore 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 @@ -74,9 +75,7 @@ dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore ## Configuration The `PrometheusExporter` can be configured using the `PrometheusExporterOptions` -properties. Refer to -[`TestPrometheusExporter.cs`](../../examples/Console/TestPrometheusExporter.cs) -for example use. +properties. ### ScrapeEndpointPath diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt index 5c99083f6de..5454232f617 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,8 +1,3 @@ -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Dispose() -> void -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.PrometheusHttpListener(OpenTelemetry.Exporter.PrometheusExporter exporter, OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions options) -> void -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Start(System.Threading.CancellationToken token = default(System.Threading.CancellationToken)) -> void -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Stop() -> void OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.get -> System.Collections.Generic.IReadOnlyCollection OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.set -> void @@ -18,4 +13,4 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMill OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult -static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder \ No newline at end of file +static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index 5c99083f6de..5454232f617 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,8 +1,3 @@ -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Dispose() -> void -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.PrometheusHttpListener(OpenTelemetry.Exporter.PrometheusExporter exporter, OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions options) -> void -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Start(System.Threading.CancellationToken token = default(System.Threading.CancellationToken)) -> void -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListener.Stop() -> void OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.get -> System.Collections.Generic.IReadOnlyCollection OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.set -> void @@ -18,4 +13,4 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMill OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult -static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder \ No newline at end of file +static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj index 4d497aabaf7..4abea287f9e 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj @@ -8,14 +8,6 @@ core- - - $(NoWarn),1591 - - - - $(NoWarn),1702 - - @@ -25,6 +17,7 @@ + diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs index f8504baa03d..21689aa50d4 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs @@ -21,8 +21,18 @@ namespace OpenTelemetry.Metrics { + /// + /// Extension methods to simplify registering a PrometheusHttpListener. + /// public static class PrometheusExporterHttpListenerMeterProviderBuilderExtensions { + /// + /// Adds Prometheus exporter to MeterProviderBuilder. + /// + /// builder to use. + /// Exporter configuration options. + /// HttpListener options. + /// The instance of to chain calls. public static MeterProviderBuilder AddPrometheusHttpListener( this MeterProviderBuilder builder, Action configureExporterOptions = null, diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs index f051f9200d5..28700603b1b 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListener.cs @@ -23,7 +23,7 @@ namespace OpenTelemetry.Exporter.Prometheus.HttpListener { - public sealed class PrometheusHttpListener : IDisposable + internal sealed class PrometheusHttpListener : IDisposable { private readonly PrometheusExporter exporter; private readonly System.Net.HttpListener httpListener = new(); @@ -31,7 +31,6 @@ public sealed class PrometheusHttpListener : IDisposable private CancellationTokenSource tokenSource; private Task workerThread; - private bool disposed; /// /// Initializes a new instance of the class. @@ -88,7 +87,7 @@ public void Start(CancellationToken token = default) } /// - /// Stop the HttpListener. + /// Gracefully stop the PrometheusHttpListener. /// public void Stop() { @@ -105,23 +104,14 @@ public void Stop() } } + /// public void Dispose() { - this.Dispose(true); - } + this.Stop(); - private void Dispose(bool disposing) - { - if (!this.disposed) + if (this.httpListener != null && this.httpListener.IsListening) { - if (disposing && this.httpListener != null && this.httpListener.IsListening) - { - this.Stop(); - this.httpListener.Close(); - this.Dispose(); - } - - this.disposed = true; + this.httpListener.Close(); } } diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListenerOptions.cs b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListenerOptions.cs index 88f58ad29bb..3979a204a92 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListenerOptions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListenerOptions.cs @@ -20,6 +20,9 @@ namespace OpenTelemetry.Exporter.Prometheus.HttpListener { + /// + /// options. + /// public class PrometheusHttpListenerOptions { private IReadOnlyCollection prefixes = new string[] { "http://localhost:9464/" }; diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md index 2dd8193505f..d42c4c8ed78 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md @@ -25,18 +25,12 @@ For example: using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(MyMeter.Name) .AddPrometheusHttpListener( - exporterOptions => - { - exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0; - }, - listenerOptions => - { - listenerOptions.HttpListenerPrefixes = new string[] { "http://localhost:9464/" }; - }) + exporterOptions => exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0, + listenerOptions => listenerOptions.Prefixes = new string[] { "http://localhost:9464/" }) .Build(); ``` -#### HttpListenerPrefixes +#### Prefixes Defines the prefixes which will be used by the listener. The default value is `["http://localhost:9464/"]`. You may specify multiple endpoints. diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/AssemblyInfo.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/AssemblyInfo.cs index aa9d15cbc50..d4361cf0913 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/AssemblyInfo.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/AssemblyInfo.cs @@ -19,11 +19,7 @@ #if SIGNED [assembly: InternalsVisibleTo("Benchmarks, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] [assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Shared.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] -[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] -[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.HttpListener, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] #else [assembly: InternalsVisibleTo("Benchmarks")] [assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Shared.Tests")] -[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore")] -[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.HttpListener")] #endif diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj index b000b81a6b4..72029cdad80 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj @@ -6,12 +6,11 @@ $(TargetFrameworks);net462 Prometheus exporter shared code for both Prometheus exporter HttpListener and Prometheus Exporter AspNetCore $(PackageTags);prometheus;metrics - core- - + diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs index bc5a2dcefe1..1d01a7b6764 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs @@ -41,6 +41,9 @@ internal PrometheusExporter(PrometheusExporterOptions options) this.CollectionManager = new PrometheusCollectionManager(this); } + /// + /// Gets or sets the Collect delegate. + /// public Func Collect { get => this.funcCollect; @@ -55,6 +58,7 @@ internal Func, ExportResult> OnExport internal PrometheusCollectionManager CollectionManager { get; } + /// public override ExportResult Export(in Batch metrics) { return this.OnExport(metrics); diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterMeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterMeterProviderBuilderExtensions.cs index ce17cca6e63..7efb8e00fae 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterMeterProviderBuilderExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterMeterProviderBuilderExtensions.cs @@ -20,6 +20,9 @@ namespace OpenTelemetry.Metrics { + /// + /// Extension methods to simplify registering a PrometheusExporter. + /// public static class PrometheusExporterMeterProviderBuilderExtensions { /// diff --git a/test/OpenTelemetry.Tests.Stress.Metrics/Program.cs b/test/OpenTelemetry.Tests.Stress.Metrics/Program.cs index 8d671b4c7c9..6a56c5a4bcb 100644 --- a/test/OpenTelemetry.Tests.Stress.Metrics/Program.cs +++ b/test/OpenTelemetry.Tests.Stress.Metrics/Program.cs @@ -47,11 +47,8 @@ public static void Main() using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(TestMeter.Name) .AddPrometheusHttpListener( - exporterOptions => - { - exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0; - }, - listenerOptions => listenerOptions.Prefixes = new string[] { $"http://localhost:9185/" }) + exporterOptions => exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0, + listenerOptions => listenerOptions.Prefixes = new string[] { $"http://localhost:9185/" }) .Build(); Stress(prometheusPort: 9184); diff --git a/test/OpenTelemetry.Tests.Stress/Skeleton.cs b/test/OpenTelemetry.Tests.Stress/Skeleton.cs index e09c12a83a6..be7493e2809 100644 --- a/test/OpenTelemetry.Tests.Stress/Skeleton.cs +++ b/test/OpenTelemetry.Tests.Stress/Skeleton.cs @@ -79,12 +79,8 @@ public static void Stress(int concurrency = 0, int prometheusPort = 0) .AddMeter(meter.Name) .AddRuntimeInstrumentation() .AddPrometheusHttpListener( - exporterOptions => - { - exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0; - }, - listenerOptions => - listenerOptions.Prefixes = new string[] { $"http://localhost:{prometheusPort}/", }) + exporterOptions => exporterOptions.ScrapeResponseCacheDurationMilliseconds = 0, + listenerOptions => listenerOptions.Prefixes = new string[] { $"http://localhost:{prometheusPort}/" }) .Build() : null; var statistics = new long[concurrency]; From d5391f151aad3444e9974dab00ae817bc809f71f Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Sat, 9 Jul 2022 14:23:53 -0700 Subject: [PATCH 13/52] changelog --- .../CHANGELOG.md | 8 +- .../CHANGELOG.md | 94 +++++++++++++++++++ 2 files changed, 99 insertions(+), 3 deletions(-) rename src/{OpenTelemetry.Exporter.Prometheus.Shared => OpenTelemetry.Exporter.Prometheus.AspNetCore}/CHANGELOG.md (83%) create mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/CHANGELOG.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md similarity index 83% rename from src/OpenTelemetry.Exporter.Prometheus.Shared/CHANGELOG.md rename to src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md index 5787a17c1db..9cf8e708eb5 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md @@ -2,9 +2,11 @@ ## 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)) +* 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 diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md new file mode 100644 index 00000000000..9cf8e708eb5 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md @@ -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 From aeede5a1ca7ea3dd3557dbd4ef769d09d62e5065 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Sat, 9 Jul 2022 14:25:38 -0700 Subject: [PATCH 14/52] space --- .../CHANGELOG.md | 8 ++++---- .../CHANGELOG.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md index 9cf8e708eb5..9f4ac19cfa2 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md @@ -3,10 +3,10 @@ ## 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)) + 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 diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md index 9cf8e708eb5..9f4ac19cfa2 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md @@ -3,10 +3,10 @@ ## 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)) + 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 From b3213df490502f54212ca5b309eb907a71cfb9af Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Sat, 9 Jul 2022 14:36:20 -0700 Subject: [PATCH 15/52] nits --- ...eusExporterHttpListenerMeterProviderBuilderExtensions.cs | 2 +- .../PrometheusHttpListenerOptions.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs index 21689aa50d4..b3ec9bf5df5 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs @@ -78,7 +78,7 @@ private static MeterProviderBuilder AddPrometheusHttpListener( configureListenerOptions?.Invoke(listenerOptions); var listener = new PrometheusHttpListener(exporter, listenerOptions); - const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started."; + const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter HttpListener could not be started."; try { listener.Start(); diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListenerOptions.cs b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListenerOptions.cs index 3979a204a92..264a5f229fd 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListenerOptions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusHttpListenerOptions.cs @@ -28,8 +28,8 @@ public class PrometheusHttpListenerOptions private IReadOnlyCollection prefixes = new string[] { "http://localhost:9464/" }; /// - /// Gets or sets the prefixes to use for the http listener. Default - /// value: http://localhost:9464/. + /// Gets or sets the prefixes to use for the http listener. + /// Default value: http://localhost:9464/. /// public IReadOnlyCollection Prefixes { @@ -44,7 +44,7 @@ public IReadOnlyCollection Prefixes (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))) { throw new ArgumentException( - "Prometheus server path should be a valid URI with http/https scheme.", + "Prometheus HttpListener prefix path should be a valid URI with http/https scheme.", nameof(this.prefixes)); } } From 3d66bc379be2086e5fdc0db00df73a0380a5d292 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Sat, 9 Jul 2022 14:53:43 -0700 Subject: [PATCH 16/52] fix link --- docs/metrics/getting-started-prometheus-grafana/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/metrics/getting-started-prometheus-grafana/README.md b/docs/metrics/getting-started-prometheus-grafana/README.md index 61b066d50f1..db0d7767bba 100644 --- a/docs/metrics/getting-started-prometheus-grafana/README.md +++ b/docs/metrics/getting-started-prometheus-grafana/README.md @@ -52,7 +52,7 @@ with `PrometheusHttpListener` is a wrapper that contains `PrometheusExporter`. With `AddPrometheusHttpListener()`, OpenTelemetry `PrometheusExporter` will export data via the endpoint defined by -[PrometheusExporterOptions.Prefixes](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md#httplistenerprefixes), +[PrometheusExporterOptions.Prefixes](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md#Prefixes), which is `http://localhost:9464/` by default. ```mermaid From b5cbf7ba5a269f339be4ce345f84a35a2767bcfe Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Sat, 9 Jul 2022 14:58:28 -0700 Subject: [PATCH 17/52] space --- .../OpenTelemetry.Exporter.Prometheus.HttpListener.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj index 4abea287f9e..05b7f401052 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj @@ -17,7 +17,7 @@ - + From 7a105d1a5f3f142ed11a41d7bb6f7eb9843d02c0 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Sat, 9 Jul 2022 15:12:11 -0700 Subject: [PATCH 18/52] fix test --- src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md | 2 +- .../PrometheusExporterHttpListenerTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md index d42c4c8ed78..4d5813aed68 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md @@ -30,7 +30,7 @@ using var meterProvider = Sdk.CreateMeterProviderBuilder() .Build(); ``` -#### Prefixes +### Prefixes Defines the prefixes which will be used by the listener. The default value is `["http://localhost:9464/"]`. You may specify multiple endpoints. diff --git a/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusExporterHttpListenerTests.cs b/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusExporterHttpListenerTests.cs index 532893700f8..d197ffea85a 100644 --- a/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusExporterHttpListenerTests.cs +++ b/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusExporterHttpListenerTests.cs @@ -61,9 +61,9 @@ public void ServerEndpointSanityCheckNegativeTest(params string[] uris) { 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: prefixes", 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 'prefixes')", ex.Message); + Assert.Equal("Prometheus HttpListener prefix path should be a valid URI with http/https scheme. (Parameter 'prefixes')", ex.Message); #endif } } From 0416582278bef57783a05e786535c5672e30a27e Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Sat, 9 Jul 2022 15:17:55 -0700 Subject: [PATCH 19/52] bookmark --- docs/metrics/getting-started-prometheus-grafana/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/metrics/getting-started-prometheus-grafana/README.md b/docs/metrics/getting-started-prometheus-grafana/README.md index db0d7767bba..0b533f69d5c 100644 --- a/docs/metrics/getting-started-prometheus-grafana/README.md +++ b/docs/metrics/getting-started-prometheus-grafana/README.md @@ -52,7 +52,7 @@ with `PrometheusHttpListener` is a wrapper that contains `PrometheusExporter`. With `AddPrometheusHttpListener()`, OpenTelemetry `PrometheusExporter` will export data via the endpoint defined by -[PrometheusExporterOptions.Prefixes](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md#Prefixes), +[PrometheusExporterOptions.Prefixes](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md#prefixes), which is `http://localhost:9464/` by default. ```mermaid From 3519e37afa7c80cd44167025d1a5253efa494fe3 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Sat, 9 Jul 2022 15:28:00 -0700 Subject: [PATCH 20/52] trigger CI From c93c9b15921bc35328fd05aa0c108bf923c7e35a Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Mon, 11 Jul 2022 11:24:36 -0700 Subject: [PATCH 21/52] Fixes to get solution building. --- .../OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj | 1 + .../OpenTelemetry.Exporter.Prometheus.HttpListener.csproj | 3 ++- .../OpenTelemetry.Exporter.Prometheus.Shared.csproj | 5 +---- .../OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj index a61fee79a66..47583a14afa 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj @@ -17,6 +17,7 @@ false + diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj index 05b7f401052..3c2be7e47ea 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj @@ -2,7 +2,8 @@ - net462;netstandard2.0 + netstandard2.0 + $(TargetFrameworks);net462 Prometheus exporter HttpListener for OpenTelemetry .NET $(PackageTags);prometheus;metrics core- diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj index 72029cdad80..b8767bca9e6 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj @@ -2,15 +2,12 @@ - netcoreapp3.1;net462 + netcoreapp3.1 $(TargetFrameworks);net462 Prometheus exporter shared code for both Prometheus exporter HttpListener and Prometheus Exporter AspNetCore $(PackageTags);prometheus;metrics - diff --git a/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj b/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj index cac030243cf..2c57ab5113d 100644 --- a/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj +++ b/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj @@ -2,7 +2,7 @@ Unit test project of Prometheus exporter shared code for both Prometheus exporter HttpListener and Prometheus Exporter AspNetCore - netcoreapp3.1;net462 + netcoreapp3.1 $(TargetFrameworks);net462 false From 011958b34bb6220d4fb0b7065a8897fc4e3dc3eb Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Mon, 11 Jul 2022 11:58:52 -0700 Subject: [PATCH 22/52] access modifier of prometheusExporter and APIs --- .../.publicApi/net462/PublicAPI.Shipped.txt | 0 .../.publicApi/net462/PublicAPI.Unshipped.txt | 0 .../.publicApi/net462/PublicAPI.Shipped.txt | 0 .../.publicApi/net462/PublicAPI.Unshipped.txt | 16 ---------------- .../netcoreapp3.1/PublicAPI.Unshipped.txt | 1 + .../PrometheusExporter.cs | 2 +- 6 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net462/PublicAPI.Shipped.txt delete mode 100644 src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net462/PublicAPI.Unshipped.txt delete mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Shipped.txt delete mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net462/PublicAPI.Shipped.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net462/PublicAPI.Unshipped.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Shipped.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt deleted file mode 100644 index 5454232f617..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt +++ /dev/null @@ -1,16 +0,0 @@ -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.get -> System.Collections.Generic.IReadOnlyCollection -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.set -> void -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.PrometheusHttpListenerOptions() -> void -OpenTelemetry.Exporter.PrometheusExporter -OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func -OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void -OpenTelemetry.Exporter.PrometheusExporterOptions -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.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions -override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult -static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt index 9b2a2be8c33..f8c89e7f1f8 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -1,6 +1,7 @@ OpenTelemetry.Exporter.PrometheusExporter OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void +OpenTelemetry.Exporter.PrometheusExporter.PrometheusExporter(OpenTelemetry.Exporter.PrometheusExporterOptions options) -> void OpenTelemetry.Exporter.PrometheusExporterOptions OpenTelemetry.Exporter.PrometheusExporterOptions.PrometheusExporterOptions() -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> string diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs index 1d01a7b6764..d1ec4abe1a3 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs @@ -35,7 +35,7 @@ public class PrometheusExporter : BaseExporter, IPullMetricExporter /// Initializes a new instance of the class. /// /// Options for the exporter. - internal PrometheusExporter(PrometheusExporterOptions options) + public PrometheusExporter(PrometheusExporterOptions options) { this.Options = options; this.CollectionManager = new PrometheusCollectionManager(this); From 69d0af18033753956a9cd11373466dda342e366a Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Mon, 11 Jul 2022 11:59:49 -0700 Subject: [PATCH 23/52] Tweak targets. --- .../OpenTelemetry.Exporter.Prometheus.HttpListener.csproj | 3 +-- .../OpenTelemetry.Exporter.Prometheus.Shared.csproj | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj index 3c2be7e47ea..8a04fe0c343 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj @@ -2,8 +2,7 @@ - netstandard2.0 - $(TargetFrameworks);net462 + netstandard2.0;net462 Prometheus exporter HttpListener for OpenTelemetry .NET $(PackageTags);prometheus;metrics core- diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj index b8767bca9e6..057fb21c058 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj @@ -2,8 +2,7 @@ - netcoreapp3.1 - $(TargetFrameworks);net462 + netcoreapp3.1;net462 Prometheus exporter shared code for both Prometheus exporter HttpListener and Prometheus Exporter AspNetCore $(PackageTags);prometheus;metrics From 608c16b2181864c4bb3d89327f8d9dc7d72d2ef7 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Mon, 11 Jul 2022 12:03:56 -0700 Subject: [PATCH 24/52] Public API for net462. --- .../.publicApi/net462/PublicAPI.Shipped.txt | 0 .../.publicApi/net462/PublicAPI.Unshipped.txt | 16 ++++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Shipped.txt create mode 100644 src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..5454232f617 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt @@ -0,0 +1,16 @@ +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.get -> System.Collections.Generic.IReadOnlyCollection +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.set -> void +OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.PrometheusHttpListenerOptions() -> void +OpenTelemetry.Exporter.PrometheusExporter +OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func +OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void +OpenTelemetry.Exporter.PrometheusExporterOptions +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.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions +override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult +static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder From 4a5fb5879099298788bf85d68e552dc22dde4f93 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Mon, 11 Jul 2022 12:13:13 -0700 Subject: [PATCH 25/52] Public API update. --- .../.publicApi/net462/PublicAPI.Unshipped.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt index 9b2a2be8c33..f8c89e7f1f8 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,6 +1,7 @@ OpenTelemetry.Exporter.PrometheusExporter OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void +OpenTelemetry.Exporter.PrometheusExporter.PrometheusExporter(OpenTelemetry.Exporter.PrometheusExporterOptions options) -> void OpenTelemetry.Exporter.PrometheusExporterOptions OpenTelemetry.Exporter.PrometheusExporterOptions.PrometheusExporterOptions() -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> string From e32d2eba9c22d18970f71f98f2f9a16a4f850cd1 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Mon, 11 Jul 2022 12:16:37 -0700 Subject: [PATCH 26/52] Public API fixes. --- .../.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt | 1 + .../.publicApi/net462/PublicAPI.Unshipped.txt | 1 + .../.publicApi/netstandard2.0/PublicAPI.Unshipped.txt | 1 + 3 files changed, 3 insertions(+) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt index 8b9927b7222..726c193d19f 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -3,6 +3,7 @@ Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions OpenTelemetry.Exporter.PrometheusExporter OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void +OpenTelemetry.Exporter.PrometheusExporter.PrometheusExporter(OpenTelemetry.Exporter.PrometheusExporterOptions options) -> void OpenTelemetry.Exporter.PrometheusExporterOptions OpenTelemetry.Exporter.PrometheusExporterOptions.PrometheusExporterOptions() -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> string diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt index 5454232f617..51b83f17e83 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt @@ -5,6 +5,7 @@ OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Pro OpenTelemetry.Exporter.PrometheusExporter OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void +OpenTelemetry.Exporter.PrometheusExporter.PrometheusExporter(OpenTelemetry.Exporter.PrometheusExporterOptions options) -> void OpenTelemetry.Exporter.PrometheusExporterOptions OpenTelemetry.Exporter.PrometheusExporterOptions.PrometheusExporterOptions() -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> string diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index 5454232f617..51b83f17e83 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -5,6 +5,7 @@ OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Pro OpenTelemetry.Exporter.PrometheusExporter OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void +OpenTelemetry.Exporter.PrometheusExporter.PrometheusExporter(OpenTelemetry.Exporter.PrometheusExporterOptions options) -> void OpenTelemetry.Exporter.PrometheusExporterOptions OpenTelemetry.Exporter.PrometheusExporterOptions.PrometheusExporterOptions() -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> string From 17fa0b73bd4dd4950236255aad20dd8394ffa2e7 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Mon, 11 Jul 2022 12:43:21 -0700 Subject: [PATCH 27/52] Dispose PrometheusHttpListener when exporter is disposed. --- .../netcoreapp3.1/PublicAPI.Unshipped.txt | 1 + .../.publicApi/net462/PublicAPI.Unshipped.txt | 1 + .../netstandard2.0/PublicAPI.Unshipped.txt | 1 + ...HttpListenerMeterProviderBuilderExtensions.cs | 16 +++++++++++++--- .../.publicApi/net462/PublicAPI.Unshipped.txt | 1 + .../netcoreapp3.1/PublicAPI.Unshipped.txt | 1 + .../PrometheusExporter.cs | 13 +++++++++++++ 7 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt index 726c193d19f..2c4fffefc45 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -11,6 +11,7 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions +override OpenTelemetry.Exporter.PrometheusExporter.Dispose(bool disposing) -> void override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch 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 predicate, string path, System.Action configureBranchedPipeline) -> Microsoft.AspNetCore.Builder.IApplicationBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt index 51b83f17e83..b61a7ab7fdd 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt @@ -13,5 +13,6 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions +override OpenTelemetry.Exporter.PrometheusExporter.Dispose(bool disposing) -> void override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index 51b83f17e83..b61a7ab7fdd 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -13,5 +13,6 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions +override OpenTelemetry.Exporter.PrometheusExporter.Dispose(bool disposing) -> void override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs index b3ec9bf5df5..a0794c67460 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs @@ -69,22 +69,32 @@ private static MeterProviderBuilder AddPrometheusHttpListener( Action configureListenerOptions = null) { configureExporterOptions?.Invoke(exporterOptions); + configureListenerOptions?.Invoke(listenerOptions); + var exporter = new PrometheusExporter(exporterOptions); + var reader = new BaseExportingMetricReader(exporter) { TemporalityPreference = MetricReaderTemporalityPreference.Cumulative, }; - configureListenerOptions?.Invoke(listenerOptions); - var listener = new PrometheusHttpListener(exporter, listenerOptions); - 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); } diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt index f8c89e7f1f8..45bdb060c82 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt @@ -9,5 +9,6 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions +override OpenTelemetry.Exporter.PrometheusExporter.Dispose(bool disposing) -> void override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt index f8c89e7f1f8..45bdb060c82 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -9,5 +9,6 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions +override OpenTelemetry.Exporter.PrometheusExporter.Dispose(bool disposing) -> void override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs index d1ec4abe1a3..9f2e5d015b8 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs @@ -56,6 +56,8 @@ internal Func, ExportResult> OnExport set => this.funcExport = value; } + internal Action OnDispose { get; set; } + internal PrometheusCollectionManager CollectionManager { get; } /// @@ -63,5 +65,16 @@ public override ExportResult Export(in Batch metrics) { return this.OnExport(metrics); } + + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + this.OnDispose?.Invoke(); + } + + base.Dispose(disposing); + } } } From 2378c433e1e1237bfff406de1a110bc695bf7bad Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Tue, 12 Jul 2022 17:22:04 -0700 Subject: [PATCH 28/52] Update docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj Co-authored-by: Alan West <3676547+alanwest@users.noreply.github.com> --- .../getting-started-prometheus-grafana.csproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj b/docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj index 1fcceb2b39b..455ed30ceb4 100644 --- a/docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj +++ b/docs/metrics/getting-started-prometheus-grafana/getting-started-prometheus-grafana.csproj @@ -1,8 +1,8 @@ - - netstandard2.0 - - - - + + netstandard2.0 + + + + From 64db84d2810a70bb3d6222e90ad22e1de5027bfc Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Tue, 12 Jul 2022 17:26:25 -0700 Subject: [PATCH 29/52] restored AspNetCore changelog --- src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md index 9f4ac19cfa2..f2df4b1a83b 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md @@ -8,6 +8,10 @@ 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)) + ## 1.3.0-rc.2 Released 2022-June-1 From fabc80f6dfb57d73b4451f889f463acdf493c6c1 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Wed, 13 Jul 2022 18:08:43 -0700 Subject: [PATCH 30/52] make PrometheusExporter internal --- .../.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt | 6 ------ .../.publicApi/net462/PublicAPI.Unshipped.txt | 6 ------ .../.publicApi/netstandard2.0/PublicAPI.Unshipped.txt | 6 ------ .../.publicApi/net462/PublicAPI.Unshipped.txt | 6 ------ .../.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt | 6 ------ .../PrometheusExporter.cs | 2 +- 6 files changed, 1 insertion(+), 31 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt index 2c4fffefc45..46dbf03b1ed 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -1,9 +1,5 @@ Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions -OpenTelemetry.Exporter.PrometheusExporter -OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func -OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void -OpenTelemetry.Exporter.PrometheusExporter.PrometheusExporter(OpenTelemetry.Exporter.PrometheusExporterOptions options) -> void OpenTelemetry.Exporter.PrometheusExporterOptions OpenTelemetry.Exporter.PrometheusExporterOptions.PrometheusExporterOptions() -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> string @@ -11,8 +7,6 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions -override OpenTelemetry.Exporter.PrometheusExporter.Dispose(bool disposing) -> void -override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch 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 predicate, string path, System.Action configureBranchedPipeline) -> Microsoft.AspNetCore.Builder.IApplicationBuilder static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string path) -> Microsoft.AspNetCore.Builder.IApplicationBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt index b61a7ab7fdd..81c33776666 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt @@ -2,10 +2,6 @@ OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.get -> System.Collections.Generic.IReadOnlyCollection OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.set -> void OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.PrometheusHttpListenerOptions() -> void -OpenTelemetry.Exporter.PrometheusExporter -OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func -OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void -OpenTelemetry.Exporter.PrometheusExporter.PrometheusExporter(OpenTelemetry.Exporter.PrometheusExporterOptions options) -> void OpenTelemetry.Exporter.PrometheusExporterOptions OpenTelemetry.Exporter.PrometheusExporterOptions.PrometheusExporterOptions() -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> string @@ -13,6 +9,4 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions -override OpenTelemetry.Exporter.PrometheusExporter.Dispose(bool disposing) -> void -override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index b61a7ab7fdd..81c33776666 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -2,10 +2,6 @@ OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.get -> System.Collections.Generic.IReadOnlyCollection OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.set -> void OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.PrometheusHttpListenerOptions() -> void -OpenTelemetry.Exporter.PrometheusExporter -OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func -OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void -OpenTelemetry.Exporter.PrometheusExporter.PrometheusExporter(OpenTelemetry.Exporter.PrometheusExporterOptions options) -> void OpenTelemetry.Exporter.PrometheusExporterOptions OpenTelemetry.Exporter.PrometheusExporterOptions.PrometheusExporterOptions() -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> string @@ -13,6 +9,4 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions -override OpenTelemetry.Exporter.PrometheusExporter.Dispose(bool disposing) -> void -override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt index 45bdb060c82..ea157e8ffaa 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,7 +1,3 @@ -OpenTelemetry.Exporter.PrometheusExporter -OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func -OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void -OpenTelemetry.Exporter.PrometheusExporter.PrometheusExporter(OpenTelemetry.Exporter.PrometheusExporterOptions options) -> void OpenTelemetry.Exporter.PrometheusExporterOptions OpenTelemetry.Exporter.PrometheusExporterOptions.PrometheusExporterOptions() -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> string @@ -9,6 +5,4 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions -override OpenTelemetry.Exporter.PrometheusExporter.Dispose(bool disposing) -> void -override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt index 45bdb060c82..ea157e8ffaa 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -1,7 +1,3 @@ -OpenTelemetry.Exporter.PrometheusExporter -OpenTelemetry.Exporter.PrometheusExporter.Collect.get -> System.Func -OpenTelemetry.Exporter.PrometheusExporter.Collect.set -> void -OpenTelemetry.Exporter.PrometheusExporter.PrometheusExporter(OpenTelemetry.Exporter.PrometheusExporterOptions options) -> void OpenTelemetry.Exporter.PrometheusExporterOptions OpenTelemetry.Exporter.PrometheusExporterOptions.PrometheusExporterOptions() -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> string @@ -9,6 +5,4 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions -override OpenTelemetry.Exporter.PrometheusExporter.Dispose(bool disposing) -> void -override OpenTelemetry.Exporter.PrometheusExporter.Export(in OpenTelemetry.Batch metrics) -> OpenTelemetry.ExportResult static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs index 9f2e5d015b8..e965dded2c7 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Exporter /// Exporter of OpenTelemetry metrics to Prometheus. /// [ExportModes(ExportModes.Pull)] - public class PrometheusExporter : BaseExporter, IPullMetricExporter + internal class PrometheusExporter : BaseExporter, IPullMetricExporter { internal const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started."; internal readonly PrometheusExporterOptions Options; From bbb50cf6a694336e262c52026a1789dc03acbebd Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Fri, 15 Jul 2022 15:46:06 -0700 Subject: [PATCH 31/52] comments --- docs/metrics/getting-started-prometheus-grafana/README.md | 2 +- test/Benchmarks/Benchmarks.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/metrics/getting-started-prometheus-grafana/README.md b/docs/metrics/getting-started-prometheus-grafana/README.md index 0b533f69d5c..62953f4f130 100644 --- a/docs/metrics/getting-started-prometheus-grafana/README.md +++ b/docs/metrics/getting-started-prometheus-grafana/README.md @@ -52,7 +52,7 @@ with `PrometheusHttpListener` is a wrapper that contains `PrometheusExporter`. With `AddPrometheusHttpListener()`, OpenTelemetry `PrometheusExporter` will export data via the endpoint defined by -[PrometheusExporterOptions.Prefixes](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md#prefixes), +[PrometheusHttpListenerOptions.Prefixes](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md#prefixes), which is `http://localhost:9464/` by default. ```mermaid diff --git a/test/Benchmarks/Benchmarks.csproj b/test/Benchmarks/Benchmarks.csproj index 0f6ca704c69..3a3cc739d91 100644 --- a/test/Benchmarks/Benchmarks.csproj +++ b/test/Benchmarks/Benchmarks.csproj @@ -29,6 +29,6 @@ - + From aa8cee12210ccd0de5ec0be6dc748b43194c90ce Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Fri, 15 Jul 2022 17:31:51 -0700 Subject: [PATCH 32/52] trigger CI From 6cb19a47011167cbfe509775d33dcac4f42b6a3a Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Mon, 18 Jul 2022 12:09:27 -0700 Subject: [PATCH 33/52] trigger CI From 76b15c89c2e9d99655fcd8344a92567407e20ad8 Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Mon, 18 Jul 2022 12:21:26 -0700 Subject: [PATCH 34/52] trigger CI From 908918e75dcc4a8ffe1ee993c7d345c2191dc2c6 Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Mon, 18 Jul 2022 18:20:57 -0700 Subject: [PATCH 35/52] move prometheusExporterMeterProviderBuilderExtensions and test file --- .../AssemblyInfo.cs | 23 +++++++++++++++++++ ...etry.Exporter.Prometheus.AspNetCore.csproj | 1 - ...sExporterMeterProviderBuilderExtensions.cs | 0 .../.publicApi/net462/PublicAPI.Unshipped.txt | 2 -- .../netcoreapp3.1/PublicAPI.Unshipped.txt | 2 -- .../PrometheusExporterEventSource.cs | 1 - src/OpenTelemetry/AssemblyInfo.cs | 2 +- .../PrometheusCollectionManagerTests.cs | 0 8 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 src/OpenTelemetry.Exporter.Prometheus.AspNetCore/AssemblyInfo.cs rename src/{OpenTelemetry.Exporter.Prometheus.Shared => OpenTelemetry.Exporter.Prometheus.AspNetCore}/PrometheusExporterMeterProviderBuilderExtensions.cs (100%) rename test/{OpenTelemetry.Exporter.Prometheus.Shared.Tests => OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests}/PrometheusCollectionManagerTests.cs (100%) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/AssemblyInfo.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/AssemblyInfo.cs new file mode 100644 index 00000000000..636158dbab4 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/AssemblyInfo.cs @@ -0,0 +1,23 @@ +// +// 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. +// + +using System.Runtime.CompilerServices; + +#if SIGNED +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] +#else +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests")] +#endif diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj index 47583a14afa..c14d0e97682 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj @@ -22,7 +22,6 @@ - diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterMeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs similarity index 100% rename from src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterMeterProviderBuilderExtensions.cs rename to src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt index ea157e8ffaa..30ab45f945d 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt @@ -4,5 +4,3 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> strin OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void -OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions -static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt index ea157e8ffaa..30ab45f945d 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -4,5 +4,3 @@ OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.get -> strin OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeEndpointPath.set -> void OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.get -> int OpenTelemetry.Exporter.PrometheusExporterOptions.ScrapeResponseCacheDurationMilliseconds.set -> void -OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions -static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs index e6e881a0471..f2a65798db1 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs @@ -25,7 +25,6 @@ namespace OpenTelemetry.Exporter.Prometheus.Shared ///
[EventSource(Name = "OpenTelemetry-Exporter-Prometheus")] - // TODO: make it internal and use Internal Visible to the httpListener internal sealed class PrometheusExporterEventSource : EventSource { public static PrometheusExporterEventSource Log = new(); diff --git a/src/OpenTelemetry/AssemblyInfo.cs b/src/OpenTelemetry/AssemblyInfo.cs index f2c95d36191..9e5fb36bee6 100644 --- a/src/OpenTelemetry/AssemblyInfo.cs +++ b/src/OpenTelemetry/AssemblyInfo.cs @@ -21,8 +21,8 @@ [assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Tests" + 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.Exporter.Prometheus.Shared.Tests" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("OpenTelemetry.Extensions.Hosting.Tests" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("OpenTelemetry.Extensions.Serilog" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)] diff --git a/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/PrometheusCollectionManagerTests.cs b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs similarity index 100% rename from test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/PrometheusCollectionManagerTests.cs rename to test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs From f9d70bb6563db96cd48d48c7e296580cd89b3bea Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Tue, 19 Jul 2022 16:20:52 -0700 Subject: [PATCH 36/52] line ending --- .../AssemblyInfo.cs | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/AssemblyInfo.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/AssemblyInfo.cs index 636158dbab4..574fd52fb83 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/AssemblyInfo.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/AssemblyInfo.cs @@ -1,23 +1,23 @@ -// -// 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. -// - -using System.Runtime.CompilerServices; - -#if SIGNED -[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] -#else -[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests")] -#endif +// +// 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. +// + +using System.Runtime.CompilerServices; + +#if SIGNED +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] +#else +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests")] +#endif From 7c0ca4f2375aeb22df17120fb2802e43c1304f14 Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Wed, 20 Jul 2022 16:08:50 -0700 Subject: [PATCH 37/52] namespace update when users reference AspNetCore and Listener projects simultaneously --- .../netcoreapp3.1/PublicAPI.Unshipped.txt | 34 ++-- ...etry.Exporter.Prometheus.AspNetCore.csproj | 7 +- ...sExporterMeterProviderBuilderExtensions.cs | 125 ++++++------- .../.publicApi/net462/PublicAPI.Unshipped.txt | 24 +-- .../netstandard2.0/PublicAPI.Unshipped.txt | 24 +-- ...ry.Exporter.Prometheus.HttpListener.csproj | 4 + .../.publicApi/net462/PublicAPI.Unshipped.txt | 12 +- .../netcoreapp3.1/PublicAPI.Unshipped.txt | 12 +- .../PrometheusCollectionManager.cs | 6 + .../PrometheusExporter.cs | 166 +++++++++--------- .../PrometheusExporterOptions.cs | 8 +- .../PrometheusSerializer.cs | 6 + .../PrometheusSerializerExt.cs | 6 + .../PrometheusCollectionManagerTests.cs | 4 +- 14 files changed, 237 insertions(+), 201 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt index 46dbf03b1ed..fea5e0ad8fe 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -1,17 +1,17 @@ -Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions -Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions -OpenTelemetry.Exporter.PrometheusExporterOptions -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.Metrics.PrometheusExporterMeterProviderBuilderExtensions -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 predicate, string path, System.Action 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 predicate) -> Microsoft.AspNetCore.Builder.IApplicationBuilder -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 = null, OpenTelemetry.Metrics.MeterProvider meterProvider = null, System.Action 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 configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder +Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions +Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions +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 +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 predicate, string path, System.Action 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 predicate) -> Microsoft.AspNetCore.Builder.IApplicationBuilder +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 = null, OpenTelemetry.Metrics.MeterProvider meterProvider = null, System.Action 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 configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj index c14d0e97682..67eb1580d6e 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj @@ -8,9 +8,6 @@ core- - - $(NoWarn),1591 - @@ -18,6 +15,10 @@ false + + $(DefineConstants);PROMETHEUS_ASPNETCORE + + diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs index 7efb8e00fae..9c25055aad6 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs @@ -1,62 +1,63 @@ -// -// 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. -// - -using System; -using OpenTelemetry.Exporter; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Metrics -{ - /// - /// Extension methods to simplify registering a PrometheusExporter. - /// - public static class PrometheusExporterMeterProviderBuilderExtensions - { - /// - /// Adds to the . - /// - /// builder to use. - /// Exporter configuration options. - /// The instance of to chain the calls. - public static MeterProviderBuilder AddPrometheusExporter(this MeterProviderBuilder builder, Action configure = null) - { - Guard.ThrowIfNull(builder); - - if (builder is IDeferredMeterProviderBuilder deferredMeterProviderBuilder) - { - return deferredMeterProviderBuilder.Configure((sp, builder) => - { - AddPrometheusExporter(builder, sp.GetOptions(), configure); - }); - } - - return AddPrometheusExporter(builder, new PrometheusExporterOptions(), configure); - } - - private static MeterProviderBuilder AddPrometheusExporter(MeterProviderBuilder builder, PrometheusExporterOptions options, Action configure = null) - { - configure?.Invoke(options); - - var exporter = new PrometheusExporter(options); - var reader = new BaseExportingMetricReader(exporter) - { - TemporalityPreference = MetricReaderTemporalityPreference.Cumulative, - }; - - return builder.AddReader(reader); - } - } -} +// +// 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. +// + +using System; +using OpenTelemetry.Exporter; +using OpenTelemetry.Exporter.Prometheus.AspNetCore; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Metrics +{ + /// + /// Extension methods to simplify registering a PrometheusExporter. + /// + public static class PrometheusExporterMeterProviderBuilderExtensions + { + /// + /// Adds to the . + /// + /// builder to use. + /// Exporter configuration options. + /// The instance of to chain the calls. + public static MeterProviderBuilder AddPrometheusExporter(this MeterProviderBuilder builder, Action configure = null) + { + Guard.ThrowIfNull(builder); + + if (builder is IDeferredMeterProviderBuilder deferredMeterProviderBuilder) + { + return deferredMeterProviderBuilder.Configure((sp, builder) => + { + AddPrometheusExporter(builder, sp.GetOptions(), configure); + }); + } + + return AddPrometheusExporter(builder, new PrometheusExporterOptions(), configure); + } + + private static MeterProviderBuilder AddPrometheusExporter(MeterProviderBuilder builder, PrometheusExporterOptions options, Action configure = null) + { + configure?.Invoke(options); + + var exporter = new PrometheusExporter(options); + var reader = new BaseExportingMetricReader(exporter) + { + TemporalityPreference = MetricReaderTemporalityPreference.Cumulative, + }; + + return builder.AddReader(reader); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt index 81c33776666..de45c685b8f 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,12 +1,12 @@ -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.get -> System.Collections.Generic.IReadOnlyCollection -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.set -> void -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.PrometheusHttpListenerOptions() -> void -OpenTelemetry.Exporter.PrometheusExporterOptions -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.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions -static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder +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 +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 configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index 81c33776666..de45c685b8f 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,12 +1,12 @@ -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.get -> System.Collections.Generic.IReadOnlyCollection -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.Prefixes.set -> void -OpenTelemetry.Exporter.Prometheus.HttpListener.PrometheusHttpListenerOptions.PrometheusHttpListenerOptions() -> void -OpenTelemetry.Exporter.PrometheusExporterOptions -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.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions -static OpenTelemetry.Metrics.PrometheusExporterHttpListenerMeterProviderBuilderExtensions.AddPrometheusHttpListener(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder +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 +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 configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj index 8a04fe0c343..bfda6619887 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj @@ -14,6 +14,10 @@ false + + $(DefineConstants);PROMETHEUS_ASPNETCORE_HTTPLISTENER + + diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt index 30ab45f945d..539467ab62d 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,6 +1,6 @@ -OpenTelemetry.Exporter.PrometheusExporterOptions -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.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 diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt index 30ab45f945d..539467ab62d 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -1,6 +1,6 @@ -OpenTelemetry.Exporter.PrometheusExporterOptions -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.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 diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs index 87f3d6bff02..e56976e7e71 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs @@ -20,7 +20,13 @@ using System.Threading.Tasks; using OpenTelemetry.Metrics; +#if PROMETHEUS_ASPNETCORE +namespace OpenTelemetry.Exporter.Prometheus.AspNetCore +#elif PROMETHEUS_ASPNETCORE_HTTPLISTENER +namespace OpenTelemetry.Exporter.Prometheus.HttpListener +#else namespace OpenTelemetry.Exporter.Prometheus.Shared +#endif { internal sealed class PrometheusCollectionManager { diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs index e965dded2c7..12cbf3835b7 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs @@ -1,80 +1,86 @@ -// -// 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. -// - -using System; -using OpenTelemetry.Exporter.Prometheus.Shared; -using OpenTelemetry.Metrics; - -namespace OpenTelemetry.Exporter -{ - /// - /// Exporter of OpenTelemetry metrics to Prometheus. - /// - [ExportModes(ExportModes.Pull)] - internal class PrometheusExporter : BaseExporter, IPullMetricExporter - { - internal const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started."; - internal readonly PrometheusExporterOptions Options; - private Func funcCollect; - private Func, ExportResult> funcExport; - - /// - /// Initializes a new instance of the class. - /// - /// Options for the exporter. - public PrometheusExporter(PrometheusExporterOptions options) - { - this.Options = options; - this.CollectionManager = new PrometheusCollectionManager(this); - } - - /// - /// Gets or sets the Collect delegate. - /// - public Func Collect - { - get => this.funcCollect; - set => this.funcCollect = value; - } - - internal Func, ExportResult> OnExport - { - get => this.funcExport; - set => this.funcExport = value; - } - - internal Action OnDispose { get; set; } - - internal PrometheusCollectionManager CollectionManager { get; } - - /// - public override ExportResult Export(in Batch metrics) - { - return this.OnExport(metrics); - } - - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - this.OnDispose?.Invoke(); - } - - base.Dispose(disposing); - } - } -} +// +// 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. +// + +using System; +#if PROMETHEUS_ASPNETCORE +using OpenTelemetry.Exporter.Prometheus.AspNetCore; +#elif PROMETHEUS_ASPNETCORE_HTTPLISTENER +using OpenTelemetry.Exporter.Prometheus.HttpListener; +#else +using OpenTelemetry.Exporter.Prometheus.Shared; +#endif +using OpenTelemetry.Metrics; + +namespace OpenTelemetry.Exporter +{ + /// + /// Exporter of OpenTelemetry metrics to Prometheus. + /// + [ExportModes(ExportModes.Pull)] + internal class PrometheusExporter : BaseExporter, IPullMetricExporter + { + internal const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started."; + internal readonly PrometheusExporterOptions Options; + private Func funcCollect; + private Func, ExportResult> funcExport; + + /// + /// Initializes a new instance of the class. + /// + /// Options for the exporter. + public PrometheusExporter(PrometheusExporterOptions options) + { + this.Options = options; + this.CollectionManager = new PrometheusCollectionManager(this); + } + + /// + /// Gets or sets the Collect delegate. + /// + public Func Collect + { + get => this.funcCollect; + set => this.funcCollect = value; + } + + internal Func, ExportResult> OnExport + { + get => this.funcExport; + set => this.funcExport = value; + } + + internal Action OnDispose { get; set; } + + internal PrometheusCollectionManager CollectionManager { get; } + + /// + public override ExportResult Export(in Batch metrics) + { + return this.OnExport(metrics); + } + + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + this.OnDispose?.Invoke(); + } + + base.Dispose(disposing); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs index 6dc1bfa870f..b8f45415511 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs @@ -17,7 +17,13 @@ using System; using OpenTelemetry.Internal; -namespace OpenTelemetry.Exporter +#if PROMETHEUS_ASPNETCORE +namespace OpenTelemetry.Exporter.Prometheus.AspNetCore +#elif PROMETHEUS_ASPNETCORE_HTTPLISTENER +namespace OpenTelemetry.Exporter.Prometheus.HttpListener +#else +namespace OpenTelemetry.Exporter.Prometheus.Shared +#endif { /// /// options. diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs index a93ad686de8..bf06480ec3e 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs @@ -21,7 +21,13 @@ using System.Globalization; using System.Runtime.CompilerServices; +#if PROMETHEUS_ASPNETCORE +namespace OpenTelemetry.Exporter.Prometheus.AspNetCore +#elif PROMETHEUS_ASPNETCORE_HTTPLISTENER +namespace OpenTelemetry.Exporter.Prometheus.HttpListener +#else namespace OpenTelemetry.Exporter.Prometheus.Shared +#endif { /// /// Basic PrometheusSerializer which has no OpenTelemetry dependency. diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs index 1178c3069b6..c8dc8490f41 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs @@ -16,7 +16,13 @@ using OpenTelemetry.Metrics; +#if PROMETHEUS_ASPNETCORE +namespace OpenTelemetry.Exporter.Prometheus.AspNetCore +#elif PROMETHEUS_ASPNETCORE_HTTPLISTENER +namespace OpenTelemetry.Exporter.Prometheus.HttpListener +#else namespace OpenTelemetry.Exporter.Prometheus.Shared +#endif { /// /// OpenTelemetry additions to the PrometheusSerializer. diff --git a/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs index aa41207db3c..0ca893925f4 100644 --- a/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs +++ b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs @@ -20,12 +20,12 @@ using System.Linq; #endif using System.Threading; -using System.Threading.Tasks; +using System.Threading.Tasks; using OpenTelemetry.Metrics; using OpenTelemetry.Tests; using Xunit; -namespace OpenTelemetry.Exporter.Prometheus.Shared.Tests +namespace OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests { public sealed class PrometheusCollectionManagerTests { From 4f6975b5b3d81a13ca9df1d9bcbdd0a0d622ede6 Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Wed, 20 Jul 2022 16:22:17 -0700 Subject: [PATCH 38/52] LF --- .../PrometheusCollectionManagerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs index 0ca893925f4..bc60596ad9b 100644 --- a/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs +++ b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs @@ -20,7 +20,7 @@ using System.Linq; #endif using System.Threading; -using System.Threading.Tasks; +using System.Threading.Tasks; using OpenTelemetry.Metrics; using OpenTelemetry.Tests; using Xunit; From a7f65a99ee027dcca4f8909d8c183d56cbe90f42 Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Wed, 20 Jul 2022 16:29:13 -0700 Subject: [PATCH 39/52] ditto --- .../netcoreapp3.1/PublicAPI.Unshipped.txt | 34 ++--- ...sExporterMeterProviderBuilderExtensions.cs | 126 +++++++++--------- .../.publicApi/net462/PublicAPI.Unshipped.txt | 24 ++-- .../netstandard2.0/PublicAPI.Unshipped.txt | 24 ++-- .../.publicApi/net462/PublicAPI.Unshipped.txt | 12 +- 5 files changed, 110 insertions(+), 110 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt index fea5e0ad8fe..f9271183c1c 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -1,17 +1,17 @@ -Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions -Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions -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 -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 predicate, string path, System.Action 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 predicate) -> Microsoft.AspNetCore.Builder.IApplicationBuilder -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 = null, OpenTelemetry.Metrics.MeterProvider meterProvider = null, System.Action 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 configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder +Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions +Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions +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 +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 predicate, string path, System.Action 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 predicate) -> Microsoft.AspNetCore.Builder.IApplicationBuilder +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 = null, OpenTelemetry.Metrics.MeterProvider meterProvider = null, System.Action 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 configure = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs index 9c25055aad6..698e1a67963 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs @@ -1,63 +1,63 @@ -// -// 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. -// - -using System; -using OpenTelemetry.Exporter; -using OpenTelemetry.Exporter.Prometheus.AspNetCore; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Metrics -{ - /// - /// Extension methods to simplify registering a PrometheusExporter. - /// - public static class PrometheusExporterMeterProviderBuilderExtensions - { - /// - /// Adds to the . - /// - /// builder to use. - /// Exporter configuration options. - /// The instance of to chain the calls. - public static MeterProviderBuilder AddPrometheusExporter(this MeterProviderBuilder builder, Action configure = null) - { - Guard.ThrowIfNull(builder); - - if (builder is IDeferredMeterProviderBuilder deferredMeterProviderBuilder) - { - return deferredMeterProviderBuilder.Configure((sp, builder) => - { - AddPrometheusExporter(builder, sp.GetOptions(), configure); - }); - } - - return AddPrometheusExporter(builder, new PrometheusExporterOptions(), configure); - } - - private static MeterProviderBuilder AddPrometheusExporter(MeterProviderBuilder builder, PrometheusExporterOptions options, Action configure = null) - { - configure?.Invoke(options); - - var exporter = new PrometheusExporter(options); - var reader = new BaseExportingMetricReader(exporter) - { - TemporalityPreference = MetricReaderTemporalityPreference.Cumulative, - }; - - return builder.AddReader(reader); - } - } -} +// +// 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. +// + +using System; +using OpenTelemetry.Exporter; +using OpenTelemetry.Exporter.Prometheus.AspNetCore; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Metrics +{ + /// + /// Extension methods to simplify registering a PrometheusExporter. + /// + public static class PrometheusExporterMeterProviderBuilderExtensions + { + /// + /// Adds to the . + /// + /// builder to use. + /// Exporter configuration options. + /// The instance of to chain the calls. + public static MeterProviderBuilder AddPrometheusExporter(this MeterProviderBuilder builder, Action configure = null) + { + Guard.ThrowIfNull(builder); + + if (builder is IDeferredMeterProviderBuilder deferredMeterProviderBuilder) + { + return deferredMeterProviderBuilder.Configure((sp, builder) => + { + AddPrometheusExporter(builder, sp.GetOptions(), configure); + }); + } + + return AddPrometheusExporter(builder, new PrometheusExporterOptions(), configure); + } + + private static MeterProviderBuilder AddPrometheusExporter(MeterProviderBuilder builder, PrometheusExporterOptions options, Action configure = null) + { + configure?.Invoke(options); + + var exporter = new PrometheusExporter(options); + var reader = new BaseExportingMetricReader(exporter) + { + TemporalityPreference = MetricReaderTemporalityPreference.Cumulative, + }; + + return builder.AddReader(reader); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt index de45c685b8f..a8f01b6d787 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,12 +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 -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 configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder +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 +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 configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index de45c685b8f..a8f01b6d787 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,12 +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 -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 configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder +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 +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 configureExporterOptions = null, System.Action configureListenerOptions = null) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt index 539467ab62d..d61e4fb9ed9 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,6 +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 +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 From 233114a4c9b3f7aebd29a0e8239b84c11b7717ad Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Wed, 20 Jul 2022 16:31:34 -0700 Subject: [PATCH 40/52] ditto --- .../PrometheusExporter.cs | 172 +++++++++--------- 1 file changed, 86 insertions(+), 86 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs index 12cbf3835b7..c1ce078e9a3 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs @@ -1,86 +1,86 @@ -// -// 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. -// - -using System; -#if PROMETHEUS_ASPNETCORE -using OpenTelemetry.Exporter.Prometheus.AspNetCore; -#elif PROMETHEUS_ASPNETCORE_HTTPLISTENER -using OpenTelemetry.Exporter.Prometheus.HttpListener; -#else -using OpenTelemetry.Exporter.Prometheus.Shared; -#endif -using OpenTelemetry.Metrics; - -namespace OpenTelemetry.Exporter -{ - /// - /// Exporter of OpenTelemetry metrics to Prometheus. - /// - [ExportModes(ExportModes.Pull)] - internal class PrometheusExporter : BaseExporter, IPullMetricExporter - { - internal const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started."; - internal readonly PrometheusExporterOptions Options; - private Func funcCollect; - private Func, ExportResult> funcExport; - - /// - /// Initializes a new instance of the class. - /// - /// Options for the exporter. - public PrometheusExporter(PrometheusExporterOptions options) - { - this.Options = options; - this.CollectionManager = new PrometheusCollectionManager(this); - } - - /// - /// Gets or sets the Collect delegate. - /// - public Func Collect - { - get => this.funcCollect; - set => this.funcCollect = value; - } - - internal Func, ExportResult> OnExport - { - get => this.funcExport; - set => this.funcExport = value; - } - - internal Action OnDispose { get; set; } - - internal PrometheusCollectionManager CollectionManager { get; } - - /// - public override ExportResult Export(in Batch metrics) - { - return this.OnExport(metrics); - } - - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - this.OnDispose?.Invoke(); - } - - base.Dispose(disposing); - } - } -} +// +// 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. +// + +using System; +#if PROMETHEUS_ASPNETCORE +using OpenTelemetry.Exporter.Prometheus.AspNetCore; +#elif PROMETHEUS_ASPNETCORE_HTTPLISTENER +using OpenTelemetry.Exporter.Prometheus.HttpListener; +#else +using OpenTelemetry.Exporter.Prometheus.Shared; +#endif +using OpenTelemetry.Metrics; + +namespace OpenTelemetry.Exporter +{ + /// + /// Exporter of OpenTelemetry metrics to Prometheus. + /// + [ExportModes(ExportModes.Pull)] + internal class PrometheusExporter : BaseExporter, IPullMetricExporter + { + internal const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started."; + internal readonly PrometheusExporterOptions Options; + private Func funcCollect; + private Func, ExportResult> funcExport; + + /// + /// Initializes a new instance of the class. + /// + /// Options for the exporter. + public PrometheusExporter(PrometheusExporterOptions options) + { + this.Options = options; + this.CollectionManager = new PrometheusCollectionManager(this); + } + + /// + /// Gets or sets the Collect delegate. + /// + public Func Collect + { + get => this.funcCollect; + set => this.funcCollect = value; + } + + internal Func, ExportResult> OnExport + { + get => this.funcExport; + set => this.funcExport = value; + } + + internal Action OnDispose { get; set; } + + internal PrometheusCollectionManager CollectionManager { get; } + + /// + public override ExportResult Export(in Batch metrics) + { + return this.OnExport(metrics); + } + + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + this.OnDispose?.Invoke(); + } + + base.Dispose(disposing); + } + } +} From ee137cd8edf31072d1c67cb537515611404e9eec Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Mon, 25 Jul 2022 16:20:19 -0700 Subject: [PATCH 41/52] Update src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md Co-authored-by: Alan West <3676547+alanwest@users.noreply.github.com> --- src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md index 4d5813aed68..bc855e69393 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md @@ -1,5 +1,10 @@ # 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/) From da80136606c0c39c4fe11cfc0b5f88e5702f3a53 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Mon, 25 Jul 2022 16:20:33 -0700 Subject: [PATCH 42/52] Update src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md Co-authored-by: Alan West <3676547+alanwest@users.noreply.github.com> --- src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md index 3af10277c46..a1542a300b0 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md @@ -1,5 +1,10 @@ # Prometheus Exporter AspNetCore for OpenTelemetry .NET +[![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/) From 9bd7930869a16f8d26622c982c4c71a8c0e9b2d5 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Tue, 26 Jul 2022 15:36:32 -0700 Subject: [PATCH 43/52] Namespace tweaks. --- .../PrometheusExporterApplicationBuilderExtensions.cs | 5 ++--- ...rometheusExporterEndpointRouteBuilderExtensions.cs | 5 ++--- ...rometheusExporterMeterProviderBuilderExtensions.cs | 2 +- ...orterHttpListenerMeterProviderBuilderExtensions.cs | 2 +- .../PrometheusCollectionManager.cs | 11 +++++------ .../PrometheusExporter.cs | 6 ++---- .../PrometheusExporterOptions.cs | 2 +- .../PrometheusSerializer.cs | 6 ------ .../PrometheusSerializerExt.cs | 6 ------ .../PrometheusCollectionManagerTests.cs | 1 + 10 files changed, 15 insertions(+), 31 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterApplicationBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterApplicationBuilderExtensions.cs index 364c430b27d..00fe170e6fb 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterApplicationBuilderExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterApplicationBuilderExtensions.cs @@ -19,7 +19,6 @@ using System; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; -using OpenTelemetry.Exporter; using OpenTelemetry.Exporter.Prometheus.AspNetCore; using OpenTelemetry.Internal; using OpenTelemetry.Metrics; @@ -93,8 +92,8 @@ public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(thi /// The to add /// middleware to. /// Optional - /// containing a otherwise the primary - /// SDK provider will be resolved using application services. + /// containing a Prometheus exporter otherwise the primary SDK provider + /// will be resolved using application services. /// Optional predicate for deciding if a given /// should be branched. If supplied is ignored. diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterEndpointRouteBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterEndpointRouteBuilderExtensions.cs index ed964fb7951..372a96e8a81 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterEndpointRouteBuilderExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterEndpointRouteBuilderExtensions.cs @@ -20,7 +20,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; -using OpenTelemetry.Exporter; using OpenTelemetry.Exporter.Prometheus.AspNetCore; using OpenTelemetry.Internal; using OpenTelemetry.Metrics; @@ -70,8 +69,8 @@ public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEnd /// If not provided then /// is used. /// Optional - /// containing a otherwise the primary - /// SDK provider will be resolved using application services. + /// containing a Prometheus exporter otherwise the primary SDK provider + /// will be resolved using application services. /// Optional callback to /// configure the branched pipeline. Called before registration of the /// Prometheus middleware. diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs index 698e1a67963..fd6809d68ee 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterMeterProviderBuilderExtensions.cs @@ -15,8 +15,8 @@ // using System; -using OpenTelemetry.Exporter; using OpenTelemetry.Exporter.Prometheus.AspNetCore; +using OpenTelemetry.Exporter.Prometheus.Shared; using OpenTelemetry.Internal; namespace OpenTelemetry.Metrics diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs index a0794c67460..9ab648b6be0 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/PrometheusExporterHttpListenerMeterProviderBuilderExtensions.cs @@ -15,8 +15,8 @@ // using System; -using OpenTelemetry.Exporter; using OpenTelemetry.Exporter.Prometheus.HttpListener; +using OpenTelemetry.Exporter.Prometheus.Shared; using OpenTelemetry.Internal; namespace OpenTelemetry.Metrics diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs index e56976e7e71..09598467bba 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs @@ -18,15 +18,14 @@ using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; -using OpenTelemetry.Metrics; - #if PROMETHEUS_ASPNETCORE -namespace OpenTelemetry.Exporter.Prometheus.AspNetCore +using OpenTelemetry.Exporter.Prometheus.AspNetCore; #elif PROMETHEUS_ASPNETCORE_HTTPLISTENER -namespace OpenTelemetry.Exporter.Prometheus.HttpListener -#else -namespace OpenTelemetry.Exporter.Prometheus.Shared +using OpenTelemetry.Exporter.Prometheus.HttpListener; #endif +using OpenTelemetry.Metrics; + +namespace OpenTelemetry.Exporter.Prometheus.Shared { internal sealed class PrometheusCollectionManager { diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs index c1ce078e9a3..c4786a770ad 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs @@ -19,18 +19,16 @@ using OpenTelemetry.Exporter.Prometheus.AspNetCore; #elif PROMETHEUS_ASPNETCORE_HTTPLISTENER using OpenTelemetry.Exporter.Prometheus.HttpListener; -#else -using OpenTelemetry.Exporter.Prometheus.Shared; #endif using OpenTelemetry.Metrics; -namespace OpenTelemetry.Exporter +namespace OpenTelemetry.Exporter.Prometheus.Shared { /// /// Exporter of OpenTelemetry metrics to Prometheus. /// [ExportModes(ExportModes.Pull)] - internal class PrometheusExporter : BaseExporter, IPullMetricExporter + internal sealed class PrometheusExporter : BaseExporter, IPullMetricExporter { internal const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started."; internal readonly PrometheusExporterOptions Options; diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs index b8f45415511..d1c4028c827 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs @@ -26,7 +26,7 @@ namespace OpenTelemetry.Exporter.Prometheus.Shared #endif { /// - /// options. + /// Prometheus exporter options. /// public class PrometheusExporterOptions { diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs index bf06480ec3e..a93ad686de8 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializer.cs @@ -21,13 +21,7 @@ using System.Globalization; using System.Runtime.CompilerServices; -#if PROMETHEUS_ASPNETCORE -namespace OpenTelemetry.Exporter.Prometheus.AspNetCore -#elif PROMETHEUS_ASPNETCORE_HTTPLISTENER -namespace OpenTelemetry.Exporter.Prometheus.HttpListener -#else namespace OpenTelemetry.Exporter.Prometheus.Shared -#endif { /// /// Basic PrometheusSerializer which has no OpenTelemetry dependency. diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs index c8dc8490f41..1178c3069b6 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusSerializerExt.cs @@ -16,13 +16,7 @@ using OpenTelemetry.Metrics; -#if PROMETHEUS_ASPNETCORE -namespace OpenTelemetry.Exporter.Prometheus.AspNetCore -#elif PROMETHEUS_ASPNETCORE_HTTPLISTENER -namespace OpenTelemetry.Exporter.Prometheus.HttpListener -#else namespace OpenTelemetry.Exporter.Prometheus.Shared -#endif { /// /// OpenTelemetry additions to the PrometheusSerializer. diff --git a/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs index bc60596ad9b..adeb3ac29c0 100644 --- a/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs +++ b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusCollectionManagerTests.cs @@ -21,6 +21,7 @@ #endif using System.Threading; using System.Threading.Tasks; +using OpenTelemetry.Exporter.Prometheus.Shared; using OpenTelemetry.Metrics; using OpenTelemetry.Tests; using Xunit; From 50152087ef5ddc7c400b27de3206ae88b3488042 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Tue, 26 Jul 2022 16:20:59 -0700 Subject: [PATCH 44/52] rename compiler constant --- .../OpenTelemetry.Exporter.Prometheus.HttpListener.csproj | 2 +- .../PrometheusCollectionManager.cs | 2 +- .../PrometheusExporter.cs | 2 +- .../PrometheusExporterOptions.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj index bfda6619887..22aee96a2bc 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj @@ -15,7 +15,7 @@ - $(DefineConstants);PROMETHEUS_ASPNETCORE_HTTPLISTENER + $(DefineConstants);PROMETHEUS_HTTPLISTENER diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs index 09598467bba..14ebefa63bb 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs @@ -20,7 +20,7 @@ using System.Threading.Tasks; #if PROMETHEUS_ASPNETCORE using OpenTelemetry.Exporter.Prometheus.AspNetCore; -#elif PROMETHEUS_ASPNETCORE_HTTPLISTENER +#elif PROMETHEUS_HTTPLISTENER using OpenTelemetry.Exporter.Prometheus.HttpListener; #endif using OpenTelemetry.Metrics; diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs index c4786a770ad..6dda84af247 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs @@ -17,7 +17,7 @@ using System; #if PROMETHEUS_ASPNETCORE using OpenTelemetry.Exporter.Prometheus.AspNetCore; -#elif PROMETHEUS_ASPNETCORE_HTTPLISTENER +#elif PROMETHEUS_HTTPLISTENER using OpenTelemetry.Exporter.Prometheus.HttpListener; #endif using OpenTelemetry.Metrics; diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs index d1c4028c827..6c5cbd53db5 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterOptions.cs @@ -19,7 +19,7 @@ #if PROMETHEUS_ASPNETCORE namespace OpenTelemetry.Exporter.Prometheus.AspNetCore -#elif PROMETHEUS_ASPNETCORE_HTTPLISTENER +#elif PROMETHEUS_HTTPLISTENER namespace OpenTelemetry.Exporter.Prometheus.HttpListener #else namespace OpenTelemetry.Exporter.Prometheus.Shared From 0f953f55883e0dc27e48663b38f88371f3013a9f Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Tue, 26 Jul 2022 16:44:01 -0700 Subject: [PATCH 45/52] comments --- .../PrometheusCollectionManager.cs | 5 - .../README.md | 138 ------------------ ...orter.Prometheus.HttpListener.Tests.csproj | 2 - 3 files changed, 145 deletions(-) delete mode 100644 src/OpenTelemetry.Exporter.Prometheus.Shared/README.md diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs index 14ebefa63bb..87f3d6bff02 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusCollectionManager.cs @@ -18,11 +18,6 @@ using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; -#if PROMETHEUS_ASPNETCORE -using OpenTelemetry.Exporter.Prometheus.AspNetCore; -#elif PROMETHEUS_HTTPLISTENER -using OpenTelemetry.Exporter.Prometheus.HttpListener; -#endif using OpenTelemetry.Metrics; namespace OpenTelemetry.Exporter.Prometheus.Shared diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/README.md b/src/OpenTelemetry.Exporter.Prometheus.Shared/README.md deleted file mode 100644 index e9409b46f4e..00000000000 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/README.md +++ /dev/null @@ -1,138 +0,0 @@ -# Prometheus Exporter 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) - -## Prerequisite - -* [Get Prometheus](https://prometheus.io/docs/introduction/first_steps/) - -## Steps to enable OpenTelemetry.Exporter.Prometheus - -### Step 1: Install Package - -Depending on the hosting mechanism you will be using: - -Install - -```shell -dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore -``` - -or - -```shell -dotnet add package OpenTelemetry.Exporter.Prometheus.HttpListener -``` - -### Step 2: Configure OpenTelemetry MeterProvider - -* When using OpenTelemetry.Extensions.Hosting package on .NET Core 3.1+: - - ```csharp - services.AddOpenTelemetryMetrics(builder => - { - builder.AddPrometheusExporter(); - }); - ``` - -* Or configure directly: - - Call the `AddPrometheusExporter` `MeterProviderBuilder` extension to - register the Prometheus exporter. - - ```csharp - using var meterProvider = Sdk.CreateMeterProviderBuilder() - .AddPrometheusExporter() - .Build(); - ``` - -### Step 3: Configure Prometheus Scraping Endpoint - -* On .NET Core 3.1+ register Prometheus scraping middleware using the - `UseOpenTelemetryPrometheusScrapingEndpoint` extension: - - ```csharp - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - 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(); - }); - } - ``` - -## Configuration - -The `PrometheusExporter` can be configured using the `PrometheusExporterOptions` -properties. Refer to -[`TestPrometheusExporter.cs`](../../examples/Console/TestPrometheusExporter.cs) -for example use. - -### HttpListener - -Configure `HttpListener` with the already constructed meterProvider instance and -passed in `PrometheusHttpListenerOptions` for configuration. -Use `listener.Start()` to allow the listener to start receiving incoming requests. - -```csharp -this.listener = new PrometheusHttpListener( - this.meterProvider, - o => o.HttpListenerPrefixes = new string[] { "http://localhost:9464/metrics" }); -this.listener.Start(); -``` - -#### HttpListenerPrefixes - -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 -either the HTTP listener or the middleware registered 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) diff --git a/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests.csproj b/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests.csproj index 4bfbfc6def1..22b68c4e9ea 100644 --- a/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests.csproj +++ b/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests.csproj @@ -19,8 +19,6 @@ - - From f1caae691d5a00c5230c73e57e894578c55b387a Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Tue, 26 Jul 2022 16:47:05 -0700 Subject: [PATCH 46/52] removed non-existing nuget urls to pass the markdown lint check --- src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md | 3 --- src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md index a1542a300b0..2c9fcd946a8 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md @@ -1,8 +1,5 @@ # Prometheus Exporter AspNetCore for OpenTelemetry .NET -[![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 diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md index bc855e69393..431d68eb5c1 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md @@ -1,8 +1,5 @@ # 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 From b66a2f6d2281371bb44f7eb0f62b8a9e8de34e08 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Tue, 26 Jul 2022 16:51:44 -0700 Subject: [PATCH 47/52] Revert "removed non-existing nuget urls to pass the markdown lint check" This reverts commit f1caae691d5a00c5230c73e57e894578c55b387a. --- src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md | 3 +++ src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md index 2c9fcd946a8..a1542a300b0 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md @@ -1,5 +1,8 @@ # Prometheus Exporter AspNetCore for OpenTelemetry .NET +[![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 diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md index 431d68eb5c1..bc855e69393 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md @@ -1,5 +1,8 @@ # 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 From 82ff0c13f5ce5b00846dcda36e30ed6c85503c39 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Tue, 26 Jul 2022 16:54:17 -0700 Subject: [PATCH 48/52] fix markdown --- src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md | 3 ++- src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md index a1542a300b0..5699b844257 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md @@ -3,7 +3,8 @@ [![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. +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 diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md index bc855e69393..31f4568f951 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md @@ -3,7 +3,8 @@ [![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. +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 From 7ca9fd252d63cb453317ea573383d4fecd569f67 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Tue, 26 Jul 2022 17:11:31 -0700 Subject: [PATCH 49/52] ditto --- src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md | 3 ++- src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md index 5699b844257..855c20637a6 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md @@ -4,7 +4,8 @@ [![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. +for configuring an ASP.NET Core application with an endpoint for Prometheus +to scrape. ## Prerequisite diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md index 31f4568f951..8e772a4754e 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md @@ -4,7 +4,8 @@ [![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. +that configures an [HttpListener](https://docs.microsoft.com/dotnet/api/system.net.httplistener) +instance for Prometheus to scrape. ## Prerequisite From cf9a910b397330a372e49969c4fdd92b822df397 Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Wed, 27 Jul 2022 14:27:25 -0700 Subject: [PATCH 50/52] addressed comments --- .../OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj | 3 +-- .../OpenTelemetry.Exporter.Prometheus.HttpListener.csproj | 2 +- .../OpenTelemetry.Exporter.Prometheus.Shared.csproj | 2 +- .../PrometheusExporter.cs | 8 ++++++-- .../PrometheusExporterEventSource.cs | 1 - 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj index 67eb1580d6e..e7453e0bf52 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj @@ -3,12 +3,11 @@ netcoreapp3.1 - Prometheus exporter for AspNetCore for OpenTelemetry .NET + AspNetCore middleware for hosting OpenTelemetry .NET Prometheus exporter $(PackageTags);prometheus;metrics core- - diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj index 22aee96a2bc..7769147c0f6 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/OpenTelemetry.Exporter.Prometheus.HttpListener.csproj @@ -3,7 +3,7 @@ netstandard2.0;net462 - Prometheus exporter HttpListener for OpenTelemetry .NET + Stand-alone HttpListener for hosting OpenTelemetry .NET exporter $(PackageTags);prometheus;metrics core- diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj index 057fb21c058..169e97169c4 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/OpenTelemetry.Exporter.Prometheus.Shared.csproj @@ -3,7 +3,7 @@ netcoreapp3.1;net462 - Prometheus exporter shared code for both Prometheus exporter HttpListener and Prometheus Exporter AspNetCore + Prometheus exporter shared code for both Prometheus exporter HttpListener and Prometheus exporter AspNetCore $(PackageTags);prometheus;metrics diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs index 6dda84af247..d782f4aaa2a 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs @@ -32,6 +32,7 @@ internal sealed class PrometheusExporter : BaseExporter, IPullMetricExpo { internal const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started."; internal readonly PrometheusExporterOptions Options; + private readonly bool disposed = false; private Func funcCollect; private Func, ExportResult> funcExport; @@ -73,9 +74,12 @@ public override ExportResult Export(in Batch metrics) /// protected override void Dispose(bool disposing) { - if (disposing) + if (!this.disposed) { - this.OnDispose?.Invoke(); + if (disposing) + { + this.OnDispose?.Invoke(); + } } base.Dispose(disposing); diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs index f2a65798db1..34f296c4451 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporterEventSource.cs @@ -24,7 +24,6 @@ namespace OpenTelemetry.Exporter.Prometheus.Shared /// EventSource events emitted from the project. /// [EventSource(Name = "OpenTelemetry-Exporter-Prometheus")] - internal sealed class PrometheusExporterEventSource : EventSource { public static PrometheusExporterEventSource Log = new(); From 009cb7d4297f6129bb2a58acf1f028288013adf8 Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Wed, 27 Jul 2022 15:00:28 -0700 Subject: [PATCH 51/52] bug fix --- .../PrometheusExporter.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs index d782f4aaa2a..25cd97c7a4b 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.Shared/PrometheusExporter.cs @@ -32,9 +32,9 @@ internal sealed class PrometheusExporter : BaseExporter, IPullMetricExpo { internal const string HttpListenerStartFailureExceptionMessage = "PrometheusExporter http listener could not be started."; internal readonly PrometheusExporterOptions Options; - private readonly bool disposed = false; private Func funcCollect; private Func, ExportResult> funcExport; + private bool disposed = false; /// /// Initializes a new instance of the class. @@ -80,6 +80,8 @@ protected override void Dispose(bool disposing) { this.OnDispose?.Invoke(); } + + this.disposed = true; } base.Dispose(disposing); From 6dfc90c63ffab142aedee79bdeda5f2a3bf08a9d Mon Sep 17 00:00:00 2001 From: Yun-Ting Date: Thu, 28 Jul 2022 11:12:13 -0700 Subject: [PATCH 52/52] removed unnecessary proj ref --- .../OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj b/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj index 2c57ab5113d..640b3541f2e 100644 --- a/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj +++ b/test/OpenTelemetry.Exporter.Prometheus.Shared.Tests/OpenTelemetry.Exporter.Prometheus.Shared.Tests.csproj @@ -22,7 +22,6 @@ -