Skip to content

Commit 56d22c3

Browse files
[OTLP] Use packed format for metric histograms
Use packed format for metric histograms. Initial code written and tweaked by Copilot. Passes integration tests with 0.133.0 and 0.136.0 of the OpenTelemetry Collector.
1 parent 1a50965 commit 56d22c3

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpMetricSerializer.cs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -292,14 +292,49 @@ private static int WriteMetric(byte[] buffer, int writePosition, Metric metric)
292292
writePosition = ProtobufSerializer.WriteDoubleWithTag(buffer, writePosition, ProtobufOtlpMetricFieldNumberConstants.HistogramDataPoint_Max, max);
293293
}
294294

295-
foreach (var histogramMeasurement in metricPoint.GetHistogramBuckets())
295+
// Collect all counts (assuming GetHistogramBuckets() returns in order)
296+
var bucketCounts = new List<ulong>();
297+
298+
foreach (var x in metricPoint.GetHistogramBuckets())
299+
{
300+
bucketCounts.Add((ulong)x.BucketCount);
301+
}
302+
303+
// Write packed repeated fixed64 bucket_counts
304+
var fieldNumber = ProtobufOtlpMetricFieldNumberConstants.HistogramDataPoint_Bucket_Counts;
305+
var tag2 = (fieldNumber << 3) | 2; // wire type 2 for length-delimited
306+
writePosition = ProtobufSerializer.WriteVarInt32(buffer, writePosition, (uint)tag2);
307+
308+
int length = bucketCounts.Count * 8;
309+
writePosition = ProtobufSerializer.WriteVarInt32(buffer, writePosition, (uint)length);
310+
311+
foreach (var bucketCount in bucketCounts)
312+
{
313+
writePosition = ProtobufSerializer.WriteFixed64LittleEndianFormat(buffer, writePosition, bucketCount);
314+
}
315+
316+
var explicitBounds = new List<double>();
317+
318+
foreach (var x in metricPoint.GetHistogramBuckets())
319+
{
320+
if (x.ExplicitBound != double.PositiveInfinity)
321+
{
322+
explicitBounds.Add(x.ExplicitBound);
323+
}
324+
}
325+
326+
if (explicitBounds.Count > 0)
296327
{
297-
var bucketCount = (ulong)histogramMeasurement.BucketCount;
298-
writePosition = ProtobufSerializer.WriteFixed64WithTag(buffer, writePosition, ProtobufOtlpMetricFieldNumberConstants.HistogramDataPoint_Bucket_Counts, bucketCount);
328+
var boundsFieldNumber = ProtobufOtlpMetricFieldNumberConstants.HistogramDataPoint_Explicit_Bounds;
329+
var boundsTag = (boundsFieldNumber << 3) | 2; // wire type 2
330+
writePosition = ProtobufSerializer.WriteVarInt32(buffer, writePosition, (uint)boundsTag);
331+
332+
int boundsLength = explicitBounds.Count * 8;
333+
writePosition = ProtobufSerializer.WriteVarInt32(buffer, writePosition, (uint)boundsLength);
299334

300-
if (histogramMeasurement.ExplicitBound != double.PositiveInfinity)
335+
foreach (var bound in explicitBounds)
301336
{
302-
writePosition = ProtobufSerializer.WriteDoubleWithTag(buffer, writePosition, ProtobufOtlpMetricFieldNumberConstants.HistogramDataPoint_Explicit_Bounds, histogramMeasurement.ExplicitBound);
337+
writePosition = ProtobufSerializer.WriteDouble(buffer, writePosition, bound);
303338
}
304339
}
305340

src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufSerializer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ internal static int WriteDoubleWithTag(byte[] buffer, int writePosition, int fie
160160
return writePosition;
161161
}
162162

163+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
164+
internal static int WriteDouble(byte[] buffer, int writePosition, double value)
165+
=> WriteFixed64LittleEndianFormat(buffer, writePosition, (ulong)BitConverter.DoubleToInt64Bits(value));
166+
163167
/// <summary>
164168
/// Computes the number of bytes required to encode a 64-bit unsigned integer in Protocol Buffers' varint format.
165169
/// </summary>

test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ services:
1919
"
2020
2121
otel-collector:
22-
image: otel/opentelemetry-collector:0.136.0@sha256:98fd3b410ae8a939be9588f1580c4b7c3da6ebba49f5363df4259a827aabb779
22+
image: otel/opentelemetry-collector:0.133.0
2323
volumes:
2424
- ./test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest:/cfg
2525
command: --config=/cfg/otel-collector-config.yaml

0 commit comments

Comments
 (0)