diff --git a/examples/Console/TestPrometheusExporter.cs b/examples/Console/TestPrometheusExporter.cs index 17fbe05e435..3e717f25002 100644 --- a/examples/Console/TestPrometheusExporter.cs +++ b/examples/Console/TestPrometheusExporter.cs @@ -14,6 +14,7 @@ // limitations under the License. // +using System; using System.Collections.Generic; using System.Diagnostics.Metrics; using System.Threading; @@ -27,7 +28,9 @@ namespace Examples.Console internal class TestPrometheusExporter { private static readonly Meter MyMeter = new Meter("TestMeter", "0.0.1"); - private static readonly Counter Counter = MyMeter.CreateCounter("counter"); + private static readonly Counter Counter = MyMeter.CreateCounter("myCounter"); + private static readonly Histogram MyHistogram = MyMeter.CreateHistogram("myHistogram"); + private static readonly Random RandomGenerator = new Random(); internal static object Run(int port, int totalDurationInMins) { @@ -49,6 +52,19 @@ internal static object Run(int port, int totalDurationInMins) .AddPrometheusExporter(opt => opt.Url = $"http://localhost:{port}/metrics/") .Build(); + ObservableGauge gauge = MyMeter.CreateObservableGauge( + "Gauge", + () => + { + var tag1 = new KeyValuePair("tag1", "value1"); + var tag2 = new KeyValuePair("tag2", "value2"); + + return new List>() + { + new Measurement(RandomGenerator.Next(1, 1000), tag1, tag2), + }; + }); + using var token = new CancellationTokenSource(); Task writeMetricTask = new Task(() => { @@ -63,6 +79,12 @@ internal static object Run(int port, int totalDurationInMins) 100, new KeyValuePair("tag1", "anothervalue"), new KeyValuePair("tag2", "somethingelse")); + + MyHistogram.Record( + RandomGenerator.Next(1, 1500), + new KeyValuePair("tag1", "value1"), + new KeyValuePair("tag2", "value2")); + Task.Delay(10).Wait(); } }); diff --git a/src/OpenTelemetry.Api/CHANGELOG.md b/src/OpenTelemetry.Api/CHANGELOG.md index db9fc530363..6dae313a6e8 100644 --- a/src/OpenTelemetry.Api/CHANGELOG.md +++ b/src/OpenTelemetry.Api/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.2.0-alpha2 + +Released 2021-Aug-24 + ## 1.2.0-alpha1 Released 2021-Jul-23 diff --git a/src/OpenTelemetry.Exporter.Console/CHANGELOG.md b/src/OpenTelemetry.Exporter.Console/CHANGELOG.md index 8de5ce58c91..d25002518de 100644 --- a/src/OpenTelemetry.Exporter.Console/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Console/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +## 1.2.0-alpha2 + +Released 2021-Aug-24 + +* Add Histogram Metrics support. +* Changed default temporality to be cumulative. + ## 1.2.0-alpha1 Released 2021-Jul-23 diff --git a/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md b/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md index e9367ea4bd7..7b6c20942e9 100644 --- a/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.2.0-alpha2 + +Released 2021-Aug-24 + * Add Metrics support.([#2192](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2192)) diff --git a/src/OpenTelemetry.Exporter.Jaeger/CHANGELOG.md b/src/OpenTelemetry.Exporter.Jaeger/CHANGELOG.md index 740395daa8c..0038d2d7ea1 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Jaeger/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.2.0-alpha2 + +Released 2021-Aug-24 + ## 1.2.0-alpha1 Released 2021-Jul-23 diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index c464714f603..fee82e55b4d 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -2,12 +2,18 @@ ## Unreleased +## 1.2.0-alpha2 + +Released 2021-Aug-24 + * The `OtlpExporterOptions` defaults can be overridden using `OTEL_EXPORTER_OTLP_ENDPOINT`, `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_EXPORTER_OTLP_TIMEOUT` envionmental variables as defined in the [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md). ([#2188](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2188)) +* Changed default temporality for Metrics to be cumulative. + ## 1.2.0-alpha1 Released 2021-Jul-23 diff --git a/src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md b/src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md index 62f86e96ddd..fbf38f93510 100644 --- a/src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Prometheus/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +## 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 diff --git a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterExtensions.cs index c2ddc69fd06..0bc3d5cac5f 100644 --- a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterExtensions.cs @@ -15,6 +15,7 @@ // using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; using OpenTelemetry.Exporter.Prometheus.Implementation; @@ -28,12 +29,13 @@ namespace OpenTelemetry.Exporter public static class PrometheusExporterExtensions { private const string PrometheusCounterType = "counter"; - private const string PrometheusSummaryType = "summary"; - private const string PrometheusSummarySumPostFix = "_sum"; - private const string PrometheusSummaryCountPostFix = "_count"; - private const string PrometheusSummaryQuantileLabelName = "quantile"; - private const string PrometheusSummaryQuantileLabelValueForMin = "0"; - private const string PrometheusSummaryQuantileLabelValueForMax = "1"; + private const string PrometheusGaugeType = "gauge"; + private const string PrometheusHistogramType = "histogram"; + private const string PrometheusHistogramSumPostFix = "_sum"; + private const string PrometheusHistogramCountPostFix = "_count"; + private const string PrometheusHistogramBucketPostFix = "_bucket"; + private const string PrometheusHistogramBucketLabelPositiveInfinity = "+Inf"; + private const string PrometheusHistogramBucketLabelLessThan = "le"; /// /// Serialize to Prometheus Format. @@ -48,7 +50,7 @@ public static void WriteMetricsCollection(this PrometheusExporter exporter, Stre { var builder = new PrometheusMetricBuilder() .WithName(metric.Name) - .WithDescription(metric.Name); + .WithDescription(metric.Description); // TODO: Use switch case for higher perf. if (metric.MetricType == MetricType.LongSum) @@ -59,6 +61,25 @@ public static void WriteMetricsCollection(this PrometheusExporter exporter, Stre { WriteSum(writer, builder, metric.Attributes, (metric as ISumMetricDouble).DoubleSum); } + else if (metric.MetricType == MetricType.DoubleGauge) + { + var gaugeMetric = metric as IGaugeMetric; + var doubleValue = (double)gaugeMetric.LastValue.Value; + WriteGauge(writer, builder, metric.Attributes, doubleValue); + } + else if (metric.MetricType == MetricType.LongGauge) + { + var gaugeMetric = metric as IGaugeMetric; + var longValue = (long)gaugeMetric.LastValue.Value; + + // TODO: Prometheus only supports float/double + WriteGauge(writer, builder, metric.Attributes, longValue); + } + else if (metric.MetricType == MetricType.Histogram) + { + var histogramMetric = metric as IHistogramMetric; + WriteHistogram(writer, builder, metric.Attributes, metric.Name, histogramMetric.PopulationSum, histogramMetric.PopulationCount, histogramMetric.Buckets); + } } } } @@ -93,48 +114,79 @@ private static void WriteSum(StreamWriter writer, PrometheusMetricBuilder builde builder.Write(writer); } - private static void WriteSummary( + private static void WriteGauge(StreamWriter writer, PrometheusMetricBuilder builder, IEnumerable> labels, double doubleValue) + { + builder = builder.WithType(PrometheusGaugeType); + + var metricValueBuilder = builder.AddValue(); + metricValueBuilder = metricValueBuilder.WithValue(doubleValue); + + foreach (var label in labels) + { + metricValueBuilder.WithLabel(label.Key, label.Value.ToString()); + } + + builder.Write(writer); + } + + private static void WriteHistogram( StreamWriter writer, PrometheusMetricBuilder builder, - IEnumerable> labels, + IEnumerable> labels, string metricName, double sum, long count, - double min, - double max) + IEnumerable buckets) { - builder = builder.WithType(PrometheusSummaryType); + /* For Histogram we emit one row for Sum, Count and as + * many rows as number of buckets. + * myHistogram_sum{tag1="value1",tag2="value2"} 258330 1629860660991 + * myHistogram_count{tag1="value1",tag2="value2"} 355 1629860660991 + * myHistogram_bucket{tag1="value1",tag2="value2",le="0"} 0 1629860660991 + * myHistogram_bucket{tag1="value1",tag2="value2",le="5"} 2 1629860660991 + * myHistogram_bucket{tag1="value1",tag2="value2",le="10"} 4 1629860660991 + * myHistogram_bucket{tag1="value1",tag2="value2",le="25"} 6 1629860660991 + * myHistogram_bucket{tag1="value1",tag2="value2",le="50"} 12 1629860660991 + * myHistogram_bucket{tag1="value1",tag2="value2",le="75"} 19 1629860660991 + * myHistogram_bucket{tag1="value1",tag2="value2",le="100"} 26 1629860660991 + * myHistogram_bucket{tag1="value1",tag2="value2",le="250"} 65 1629860660991 + * myHistogram_bucket{tag1="value1",tag2="value2",le="500"} 128 1629860660991 + * myHistogram_bucket{tag1="value1",tag2="value2",le="1000"} 241 1629860660991 + * myHistogram_bucket{tag1="value1",tag2="value2",le="+Inf"} 355 1629860660991 + */ + builder = builder.WithType(PrometheusHistogramType); + var metricValueBuilderSum = builder.AddValue(); + metricValueBuilderSum.WithName(metricName + PrometheusHistogramSumPostFix); + metricValueBuilderSum = metricValueBuilderSum.WithValue(sum); foreach (var label in labels) { - /* For Summary we emit one row for Sum, Count, Min, Max. - Min,Max exports as quantile 0 and 1. - In future, when OpenTelemetry implements more aggregation - algorithms, this section will need to be revisited. - Sample output: - MyMeasure_sum{dim1="value1"} 750 1587013352982 - MyMeasure_count{dim1="value1"} 5 1587013352982 - MyMeasure{dim1="value2",quantile="0"} 150 1587013352982 - MyMeasure{dim1="value2",quantile="1"} 150 1587013352982 - */ - builder.AddValue() - .WithName(metricName + PrometheusSummarySumPostFix) - .WithLabel(label.Key, label.Value) - .WithValue(sum); - builder.AddValue() - .WithName(metricName + PrometheusSummaryCountPostFix) - .WithLabel(label.Key, label.Value) - .WithValue(count); - builder.AddValue() - .WithName(metricName) - .WithLabel(label.Key, label.Value) - .WithLabel(PrometheusSummaryQuantileLabelName, PrometheusSummaryQuantileLabelValueForMin) - .WithValue(min); - builder.AddValue() - .WithName(metricName) - .WithLabel(label.Key, label.Value) - .WithLabel(PrometheusSummaryQuantileLabelName, PrometheusSummaryQuantileLabelValueForMax) - .WithValue(max); + metricValueBuilderSum.WithLabel(label.Key, label.Value.ToString()); + } + + var metricValueBuilderCount = builder.AddValue(); + metricValueBuilderCount.WithName(metricName + PrometheusHistogramCountPostFix); + metricValueBuilderCount = metricValueBuilderCount.WithValue(count); + foreach (var label in labels) + { + metricValueBuilderCount.WithLabel(label.Key, label.Value.ToString()); + } + + long totalCount = 0; + foreach (var bucket in buckets) + { + totalCount += bucket.Count; + var metricValueBuilderBuckets = builder.AddValue(); + metricValueBuilderBuckets.WithName(metricName + PrometheusHistogramBucketPostFix); + metricValueBuilderBuckets = metricValueBuilderBuckets.WithValue(totalCount); + foreach (var label in labels) + { + metricValueBuilderBuckets.WithLabel(label.Key, label.Value.ToString()); + } + + var bucketName = double.IsPositiveInfinity(bucket.HighBoundary) ? + PrometheusHistogramBucketLabelPositiveInfinity : bucket.HighBoundary.ToString(CultureInfo.InvariantCulture); + metricValueBuilderBuckets.WithLabel(PrometheusHistogramBucketLabelLessThan, bucketName); } builder.Write(writer); diff --git a/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md b/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md index 1e1dac0d3ff..55111117e8c 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.2.0-alpha2 + +Released 2021-Aug-24 + * Enabling endpoint configuration in ZipkinExporterOptions via `OTEL_EXPORTER_ZIPKIN_ENDPOINT` environment variable. ([#1453](https://github.com/open-telemetry/opentelemetry-dotnet/issues/1453)) diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index f3d9fd1eb9f..219f9fd011e 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +## 1.2.0-alpha2 + +Released 2021-Aug-24 + +* More Metrics features. All instrument types, push/pull + exporters, Delta/Cumulative temporality supported. + * `ResourceBuilder.CreateDefault` has detectors for `OTEL_RESOURCE_ATTRIBUTES`, `OTEL_SERVICE_NAME` environment variables so that explicit `AddEnvironmentVariableDetector` call is not needed. ([#2247](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2247))