1616
1717package io .opentelemetry .exporters .otlp ;
1818
19+ import static io .opentelemetry .proto .metrics .v1 .AggregationTemporality .AGGREGATION_TEMPORALITY_CUMULATIVE ;
20+ import static io .opentelemetry .proto .metrics .v1 .AggregationTemporality .AGGREGATION_TEMPORALITY_DELTA ;
21+ import static io .opentelemetry .proto .metrics .v1 .AggregationTemporality .AGGREGATION_TEMPORALITY_UNSPECIFIED ;
22+
1923import io .opentelemetry .common .Labels ;
2024import io .opentelemetry .common .ReadableKeyValuePairs .KeyValueConsumer ;
2125import io .opentelemetry .proto .common .v1 .StringKeyValue ;
26+ import io .opentelemetry .proto .metrics .v1 .AggregationTemporality ;
2227import io .opentelemetry .proto .metrics .v1 .DoubleDataPoint ;
28+ import io .opentelemetry .proto .metrics .v1 .DoubleHistogram ;
29+ import io .opentelemetry .proto .metrics .v1 .DoubleHistogramDataPoint ;
30+ import io .opentelemetry .proto .metrics .v1 .DoubleSum ;
2331import io .opentelemetry .proto .metrics .v1 .InstrumentationLibraryMetrics ;
24- import io .opentelemetry .proto .metrics .v1 .Int64DataPoint ;
32+ import io .opentelemetry .proto .metrics .v1 .IntDataPoint ;
33+ import io .opentelemetry .proto .metrics .v1 .IntSum ;
2534import io .opentelemetry .proto .metrics .v1 .Metric ;
26- import io .opentelemetry .proto .metrics .v1 .MetricDescriptor ;
27- import io .opentelemetry .proto .metrics .v1 .MetricDescriptor .Temporality ;
2835import io .opentelemetry .proto .metrics .v1 .ResourceMetrics ;
29- import io .opentelemetry .proto .metrics .v1 .SummaryDataPoint ;
30- import io .opentelemetry .proto .metrics .v1 .SummaryDataPoint .ValueAtPercentile ;
3136import io .opentelemetry .sdk .common .InstrumentationLibraryInfo ;
3237import io .opentelemetry .sdk .metrics .data .MetricData ;
3338import io .opentelemetry .sdk .metrics .data .MetricData .Descriptor ;
@@ -91,74 +96,83 @@ static List<ResourceMetrics> toProtoResourceMetrics(Collection<MetricData> metri
9196 return result ;
9297 }
9398
99+ // fall through comment isn't working for some reason.
100+ @ SuppressWarnings ("fallthrough" )
94101 static Metric toProtoMetric (MetricData metricData ) {
102+ Descriptor descriptor = metricData .getDescriptor ();
95103 Metric .Builder builder =
96104 Metric .newBuilder ()
97- .setMetricDescriptor (toProtoMetricDescriptor (metricData .getDescriptor ()));
105+ .setName (descriptor .getName ())
106+ .setDescription (descriptor .getDescription ())
107+ .setUnit (descriptor .getUnit ());
98108
99109 // If no points available then return.
100110 if (metricData .getPoints ().isEmpty ()) {
101111 return builder .build ();
102112 }
103- switch (builder .getMetricDescriptor ().getType ()) {
104- case UNRECOGNIZED :
105- case INVALID_TYPE :
106- break ;
107- case MONOTONIC_INT64 :
108- case INT64 :
109- builder .addAllInt64DataPoints (
110- toInt64DataPoints (metricData .getPoints (), metricData .getDescriptor ()));
113+
114+ boolean monotonic = false ;
115+
116+ switch (descriptor .getType ()) {
117+ case MONOTONIC_LONG :
118+ monotonic = true ;
119+ // fall through
120+ case NON_MONOTONIC_LONG :
121+ builder .setIntSum (
122+ IntSum .newBuilder ()
123+ .setIsMonotonic (monotonic )
124+ .setAggregationTemporality (mapToTemporality (descriptor ))
125+ .addAllDataPoints (
126+ toIntDataPoints (metricData .getPoints (), metricData .getDescriptor ()))
127+ .build ());
111128 break ;
112129 case MONOTONIC_DOUBLE :
113- case DOUBLE :
114- builder .addAllDoubleDataPoints (
115- toDoubleDataPoints (metricData .getPoints (), metricData .getDescriptor ()));
116- break ;
117- case HISTOGRAM :
118- // TODO: Add support for histogram.
130+ monotonic = true ;
131+ // fall through
132+ case NON_MONOTONIC_DOUBLE :
133+ builder .setDoubleSum (
134+ DoubleSum .newBuilder ()
135+ .setIsMonotonic (monotonic )
136+ .setAggregationTemporality (mapToTemporality (descriptor ))
137+ .addAllDataPoints (
138+ toDoubleDataPoints (metricData .getPoints (), metricData .getDescriptor ()))
139+ .build ());
119140 break ;
120141 case SUMMARY :
121- builder .addAllSummaryDataPoints (
122- toSummaryDataPoints (metricData .getPoints (), metricData .getDescriptor ()));
142+ builder .setDoubleHistogram (
143+ DoubleHistogram .newBuilder ()
144+ .setAggregationTemporality (mapToTemporality (descriptor ))
145+ .addAllDataPoints (
146+ toSummaryDataPoints (metricData .getPoints (), metricData .getDescriptor ()))
147+ .build ());
123148 break ;
124149 }
125150 return builder .build ();
126151 }
127152
128- static MetricDescriptor toProtoMetricDescriptor (Descriptor descriptor ) {
129- return MetricDescriptor .newBuilder ()
130- .setName (descriptor .getName ())
131- .setDescription (descriptor .getDescription ())
132- .setUnit (descriptor .getUnit ())
133- .setType (toProtoMetricDescriptorType (descriptor .getType ()))
134- .setTemporality (mapToTemporality (descriptor ))
135- .build ();
136- }
137-
138- private static Temporality mapToTemporality (Descriptor descriptor ) {
153+ private static AggregationTemporality mapToTemporality (Descriptor descriptor ) {
139154 switch (descriptor .getType ()) {
140155 case NON_MONOTONIC_LONG :
141156 case NON_MONOTONIC_DOUBLE :
142157 case MONOTONIC_LONG :
143158 case MONOTONIC_DOUBLE :
144- return Temporality . CUMULATIVE ;
159+ return AGGREGATION_TEMPORALITY_CUMULATIVE ;
145160 case SUMMARY :
146- return Temporality . DELTA ;
161+ return AGGREGATION_TEMPORALITY_DELTA ;
147162 }
148- return Temporality . UNRECOGNIZED ;
163+ return AGGREGATION_TEMPORALITY_UNSPECIFIED ;
149164 }
150165
151- static Collection <Int64DataPoint > toInt64DataPoints (
152- Collection <Point > points , Descriptor descriptor ) {
153- List <Int64DataPoint > result = new ArrayList <>(points .size ());
166+ static List <IntDataPoint > toIntDataPoints (Collection <Point > points , Descriptor descriptor ) {
167+ List <IntDataPoint > result = new ArrayList <>(points .size ());
154168 for (Point point : points ) {
155169 LongPoint longPoint = (LongPoint ) point ;
156- Int64DataPoint .Builder builder =
157- Int64DataPoint .newBuilder ()
170+ IntDataPoint .Builder builder =
171+ IntDataPoint .newBuilder ()
158172 .setStartTimeUnixNano (longPoint .getStartEpochNanos ())
159173 .setTimeUnixNano (longPoint .getEpochNanos ())
160174 .setValue (longPoint .getValue ());
161- // Not calling directly addAllLabels because that generates couple of unnecessary allocations.
175+ // Avoid calling addAllLabels when not needed to save a couple allocations.
162176 if (descriptor .getConstantLabels () != null && !descriptor .getConstantLabels ().isEmpty ()) {
163177 builder .addAllLabels (toProtoLabels (descriptor .getConstantLabels ()));
164178 }
@@ -181,7 +195,7 @@ static Collection<DoubleDataPoint> toDoubleDataPoints(
181195 .setStartTimeUnixNano (doublePoint .getStartEpochNanos ())
182196 .setTimeUnixNano (doublePoint .getEpochNanos ())
183197 .setValue (doublePoint .getValue ());
184- // Not calling directly addAllLabels because that generates couple of unnecessary allocations.
198+ // Avoid calling addAllLabels when not needed to save a couple allocations.
185199 if (descriptor .getConstantLabels () != null && !descriptor .getConstantLabels ().isEmpty ()) {
186200 builder .addAllLabels (toProtoLabels (descriptor .getConstantLabels ()));
187201 }
@@ -194,32 +208,29 @@ static Collection<DoubleDataPoint> toDoubleDataPoints(
194208 return result ;
195209 }
196210
197- static Collection < SummaryDataPoint > toSummaryDataPoints (
211+ static List < DoubleHistogramDataPoint > toSummaryDataPoints (
198212 Collection <Point > points , Descriptor descriptor ) {
199- List <SummaryDataPoint > result = new ArrayList <>(points .size ());
213+ List <DoubleHistogramDataPoint > result = new ArrayList <>(points .size ());
200214 for (Point point : points ) {
201215 SummaryPoint summaryPoint = (SummaryPoint ) point ;
202- SummaryDataPoint .Builder builder =
203- SummaryDataPoint .newBuilder ()
216+ DoubleHistogramDataPoint .Builder builder =
217+ DoubleHistogramDataPoint .newBuilder ()
204218 .setStartTimeUnixNano (summaryPoint .getStartEpochNanos ())
205219 .setTimeUnixNano (summaryPoint .getEpochNanos ())
206220 .setCount (summaryPoint .getCount ())
207221 .setSum (summaryPoint .getSum ());
208- // Not calling directly addAllLabels because that generates couple of unnecessary allocations
209- // if empty list.
222+ // Avoid calling addAllLabels when not needed to save a couple allocations.
210223 if (descriptor .getConstantLabels () != null && !descriptor .getConstantLabels ().isEmpty ()) {
211224 builder .addAllLabels (toProtoLabels (descriptor .getConstantLabels ()));
212225 }
213- Collection <StringKeyValue > labels = toProtoLabels (summaryPoint .getLabels ());
226+ List <StringKeyValue > labels = toProtoLabels (summaryPoint .getLabels ());
214227 if (!labels .isEmpty ()) {
215228 builder .addAllLabels (labels );
216229 }
217230 // Not calling directly addAllPercentileValues because that generates couple of unnecessary
218231 // allocations if empty list.
219- List <ValueAtPercentile > valueAtPercentiles =
220- toProtoValueAtPercentiles (summaryPoint .getPercentileValues ());
221- if (!valueAtPercentiles .isEmpty ()) {
222- builder .addAllPercentileValues (valueAtPercentiles );
232+ if (!summaryPoint .getPercentileValues ().isEmpty ()) {
233+ addBucketValues (summaryPoint .getPercentileValues (), builder );
223234 }
224235 result .add (builder .build ());
225236 }
@@ -228,40 +239,22 @@ static Collection<SummaryDataPoint> toSummaryDataPoints(
228239
229240 // TODO: Consider to pass the Builder and directly add values.
230241 @ SuppressWarnings ("MixedMutabilityReturnType" )
231- static List <ValueAtPercentile > toProtoValueAtPercentiles (
232- Collection <MetricData .ValueAtPercentile > valueAtPercentiles ) {
233- if (valueAtPercentiles .isEmpty ()) {
234- return Collections .emptyList ();
235- }
236- List <ValueAtPercentile > result = new ArrayList <>(valueAtPercentiles .size ());
242+ static void addBucketValues (
243+ List <MetricData .ValueAtPercentile > valueAtPercentiles ,
244+ DoubleHistogramDataPoint .Builder builder ) {
245+
237246 for (MetricData .ValueAtPercentile valueAtPercentile : valueAtPercentiles ) {
238- result .add (
239- ValueAtPercentile .newBuilder ()
240- .setPercentile (valueAtPercentile .getPercentile ())
241- .setValue (valueAtPercentile .getValue ())
242- .build ());
247+ // TODO(jkwatson): Value of histogram should be long?
248+ builder .addBucketCounts ((long ) valueAtPercentile .getValue ());
249+ builder .addExplicitBounds (valueAtPercentile .getPercentile ());
243250 }
244- return result ;
245- }
246251
247- static MetricDescriptor .Type toProtoMetricDescriptorType (Descriptor .Type descriptorType ) {
248- switch (descriptorType ) {
249- case NON_MONOTONIC_LONG :
250- return MetricDescriptor .Type .INT64 ;
251- case NON_MONOTONIC_DOUBLE :
252- return MetricDescriptor .Type .DOUBLE ;
253- case MONOTONIC_LONG :
254- return MetricDescriptor .Type .MONOTONIC_INT64 ;
255- case MONOTONIC_DOUBLE :
256- return MetricDescriptor .Type .MONOTONIC_DOUBLE ;
257- case SUMMARY :
258- return MetricDescriptor .Type .SUMMARY ;
259- }
260- return MetricDescriptor .Type .UNRECOGNIZED ;
252+ // No recordings past the highest percentile (e.g., [highest percentile, +infinity]).
253+ builder .addBucketCounts (0 );
261254 }
262255
263256 @ SuppressWarnings ("MixedMutabilityReturnType" )
264- static Collection <StringKeyValue > toProtoLabels (Labels labels ) {
257+ static List <StringKeyValue > toProtoLabels (Labels labels ) {
265258 if (labels .isEmpty ()) {
266259 return Collections .emptyList ();
267260 }
0 commit comments