diff --git a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporter.cs index f3975eddbf7..9931a414f36 100644 --- a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporter.cs @@ -24,6 +24,7 @@ namespace OpenTelemetry.Exporter /// Exporter of OpenTelemetry metrics to Prometheus. /// [AggregationTemporality(AggregationTemporality.Cumulative)] + [ExportModes(ExportModes.Pull)] public class PrometheusExporter : BaseExporter { internal readonly PrometheusExporterOptions Options; diff --git a/src/OpenTelemetry/Metrics/BaseExportingMetricReader.cs b/src/OpenTelemetry/Metrics/BaseExportingMetricReader.cs index 71257a81a19..0e1a9470126 100644 --- a/src/OpenTelemetry/Metrics/BaseExportingMetricReader.cs +++ b/src/OpenTelemetry/Metrics/BaseExportingMetricReader.cs @@ -23,19 +23,31 @@ public class BaseExportingMetricReader : MetricReader protected readonly BaseExporter exporter; protected bool disposed; + private readonly ExportModes supportedExportModes = ExportModes.Push | ExportModes.Pull; + public BaseExportingMetricReader(BaseExporter exporter) { this.exporter = exporter ?? throw new ArgumentNullException(nameof(exporter)); - var attributes = exporter.GetType().GetCustomAttributes(typeof(AggregationTemporalityAttribute), true); + var exportorType = exporter.GetType(); + var attributes = exportorType.GetCustomAttributes(typeof(AggregationTemporalityAttribute), true); + if (attributes.Length > 0) + { + var attr = (AggregationTemporalityAttribute)attributes[attributes.Length - 1]; + this.PreferredAggregationTemporality = attr.Preferred; + this.SupportedAggregationTemporality = attr.Supported; + } + + attributes = exportorType.GetCustomAttributes(typeof(ExportModesAttribute), true); if (attributes.Length > 0) { - AggregationTemporalityAttribute aggregationTemporality = (AggregationTemporalityAttribute)attributes[attributes.Length - 1]; - this.PreferredAggregationTemporality = aggregationTemporality.Preferred; - this.SupportedAggregationTemporality = aggregationTemporality.Supported; + var attr = (ExportModesAttribute)attributes[attributes.Length - 1]; + this.supportedExportModes = attr.Supported; } } + protected ExportModes SupportedExportModes => this.supportedExportModes; + public override void OnCollect(Batch metrics) { this.exporter.Export(metrics); diff --git a/src/OpenTelemetry/Metrics/ExportModes.cs b/src/OpenTelemetry/Metrics/ExportModes.cs new file mode 100644 index 00000000000..ee832bd9047 --- /dev/null +++ b/src/OpenTelemetry/Metrics/ExportModes.cs @@ -0,0 +1,47 @@ +// +// 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; + +namespace OpenTelemetry.Metrics +{ + [Flags] + public enum ExportModes : byte + { + /* + 0 0 0 0 0 0 0 0 + | | | | | | | | + | | | | | | | +--- Push + | | | | | | +----- Pull + | | | | | +------- (reserved) + | | | | +--------- (reserved) + | | | +----------- (reserved) + | | +------------- (reserved) + | +--------------- (reserved) + +----------------- (reserved) + */ + + /// + /// Push. + /// + Push = 0b1, + + /// + /// Pull. + /// + Pull = 0b10, + } +} diff --git a/src/OpenTelemetry/Metrics/ExportModesAttribute.cs b/src/OpenTelemetry/Metrics/ExportModesAttribute.cs new file mode 100644 index 00000000000..a3a74cf59fd --- /dev/null +++ b/src/OpenTelemetry/Metrics/ExportModesAttribute.cs @@ -0,0 +1,33 @@ +// +// 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; + +namespace OpenTelemetry.Metrics +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public sealed class ExportModesAttribute : Attribute + { + private ExportModes supportedExportModes; + + public ExportModesAttribute(ExportModes supported) + { + this.supportedExportModes = supported; + } + + public ExportModes Supported => this.supportedExportModes; + } +} diff --git a/src/OpenTelemetry/Metrics/PeriodicExportingMetricReader.cs b/src/OpenTelemetry/Metrics/PeriodicExportingMetricReader.cs index 2d8aa345403..11c142690fe 100644 --- a/src/OpenTelemetry/Metrics/PeriodicExportingMetricReader.cs +++ b/src/OpenTelemetry/Metrics/PeriodicExportingMetricReader.cs @@ -22,12 +22,23 @@ namespace OpenTelemetry.Metrics { public class PeriodicExportingMetricReader : BaseExportingMetricReader { + internal const int DefaultExportIntervalMilliseconds = 60000; + internal const int DefaultExportTimeoutMilliseconds = 30000; + private readonly Task exportTask; private readonly CancellationTokenSource token; - public PeriodicExportingMetricReader(BaseExporter exporter, int exportIntervalMs) + public PeriodicExportingMetricReader( + BaseExporter exporter, + int exportIntervalMilliseconds = DefaultExportIntervalMilliseconds, + int exportTimeoutMilliseconds = DefaultExportTimeoutMilliseconds) : base(exporter) { + if ((this.SupportedExportModes & ExportModes.Push) != ExportModes.Push) + { + throw new InvalidOperationException("The exporter does not support push mode."); + } + this.token = new CancellationTokenSource(); // TODO: Use dedicated thread. @@ -35,7 +46,7 @@ public PeriodicExportingMetricReader(BaseExporter exporter, int exportIn { while (!this.token.IsCancellationRequested) { - Task.Delay(exportIntervalMs).Wait(); + Task.Delay(exportIntervalMilliseconds).Wait(); this.Collect(); } });