Skip to content

Commit 84e6afb

Browse files
[otlp] Replace the current trace implementation with the new one (#6003)
1 parent 7eeddf5 commit 84e6afb

15 files changed

+183
-899
lines changed

src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs

Lines changed: 0 additions & 445 deletions
This file was deleted.

src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ExportClient/OtlpGrpcTraceExportClient.cs

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ExportClient/OtlpHttpTraceExportClient.cs

Lines changed: 0 additions & 69 deletions
This file was deleted.

src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ExportClient/ProtobufOtlpHttpExportClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClie
1111
/// <summary>Class for sending OTLP trace export request over HTTP.</summary>
1212
internal sealed class ProtobufOtlpHttpExportClient : ProtobufOtlpExportClient
1313
{
14-
private static readonly MediaTypeHeaderValue MediaHeaderValue = new("application/x-protobuf");
14+
internal static readonly MediaTypeHeaderValue MediaHeaderValue = new("application/x-protobuf");
1515
private static readonly ExportClientHttpResponse SuccessExportResponse = new(success: true, deadlineUtc: default, response: null, exception: null);
1616

1717
internal ProtobufOtlpHttpExportClient(OtlpExporterOptions options, HttpClient httpClient, string signalPath)

src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptionsExtensions.cs

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.Transmission;
1717
using LogOtlpCollector = OpenTelemetry.Proto.Collector.Logs.V1;
1818
using MetricsOtlpCollector = OpenTelemetry.Proto.Collector.Metrics.V1;
19-
using TraceOtlpCollector = OpenTelemetry.Proto.Collector.Trace.V1;
2019

2120
namespace OpenTelemetry.Exporter;
2221

@@ -99,42 +98,6 @@ public static THeaders GetHeaders<THeaders>(this OtlpExporterOptions options, Ac
9998
return headers;
10099
}
101100

102-
public static OtlpExporterTransmissionHandler<TraceOtlpCollector.ExportTraceServiceRequest> GetTraceExportTransmissionHandler(this OtlpExporterOptions options, ExperimentalOptions experimentalOptions)
103-
{
104-
var exportClient = GetTraceExportClient(options);
105-
106-
// `HttpClient.Timeout.TotalMilliseconds` would be populated with the correct timeout value for both the exporter configuration cases:
107-
// 1. User provides their own HttpClient. This case is straightforward as the user wants to use their `HttpClient` and thereby the same client's timeout value.
108-
// 2. If the user configures timeout via the exporter options, then the timeout set for the `HttpClient` initialized by the exporter will be set to user provided value.
109-
double timeoutMilliseconds = exportClient is OtlpHttpTraceExportClient httpTraceExportClient
110-
? httpTraceExportClient.HttpClient.Timeout.TotalMilliseconds
111-
: options.TimeoutMilliseconds;
112-
113-
if (experimentalOptions.EnableInMemoryRetry)
114-
{
115-
return new OtlpExporterRetryTransmissionHandler<TraceOtlpCollector.ExportTraceServiceRequest>(exportClient, timeoutMilliseconds);
116-
}
117-
else if (experimentalOptions.EnableDiskRetry)
118-
{
119-
Debug.Assert(!string.IsNullOrEmpty(experimentalOptions.DiskRetryDirectoryPath), $"{nameof(experimentalOptions.DiskRetryDirectoryPath)} is null or empty");
120-
121-
return new OtlpExporterPersistentStorageTransmissionHandler<TraceOtlpCollector.ExportTraceServiceRequest>(
122-
exportClient,
123-
timeoutMilliseconds,
124-
(byte[] data) =>
125-
{
126-
var request = new TraceOtlpCollector.ExportTraceServiceRequest();
127-
request.MergeFrom(data);
128-
return request;
129-
},
130-
Path.Combine(experimentalOptions.DiskRetryDirectoryPath, "traces"));
131-
}
132-
else
133-
{
134-
return new OtlpExporterTransmissionHandler<TraceOtlpCollector.ExportTraceServiceRequest>(exportClient, timeoutMilliseconds);
135-
}
136-
}
137-
138101
public static ProtobufOtlpExporterTransmissionHandler GetProtobufExportTransmissionHandler(this OtlpExporterOptions options, ExperimentalOptions experimentalOptions, OtlpSignalType otlpSignalType)
139102
{
140103
var exportClient = GetProtobufExportClient(options, otlpSignalType);
@@ -169,6 +132,11 @@ public static IProtobufExportClient GetProtobufExportClient(this OtlpExporterOpt
169132
{
170133
var httpClient = options.HttpClientFactory?.Invoke() ?? throw new InvalidOperationException("OtlpExporterOptions was missing HttpClientFactory or it returned null.");
171134

135+
if (options.Protocol != OtlpExportProtocol.Grpc && options.Protocol != OtlpExportProtocol.HttpProtobuf)
136+
{
137+
throw new NotSupportedException($"Protocol {options.Protocol} is not supported.");
138+
}
139+
172140
return otlpSignalType switch
173141
{
174142
OtlpSignalType.Traces => options.Protocol == OtlpExportProtocol.Grpc
@@ -255,16 +223,6 @@ public static IProtobufExportClient GetProtobufExportClient(this OtlpExporterOpt
255223
}
256224
}
257225

258-
public static IExportClient<TraceOtlpCollector.ExportTraceServiceRequest> GetTraceExportClient(this OtlpExporterOptions options) =>
259-
options.Protocol switch
260-
{
261-
OtlpExportProtocol.Grpc => new OtlpGrpcTraceExportClient(options),
262-
OtlpExportProtocol.HttpProtobuf => new OtlpHttpTraceExportClient(
263-
options,
264-
options.HttpClientFactory?.Invoke() ?? throw new InvalidOperationException("OtlpExporterOptions was missing HttpClientFactory or it returned null.")),
265-
_ => throw new NotSupportedException($"Protocol {options.Protocol} is not supported."),
266-
};
267-
268226
public static IExportClient<MetricsOtlpCollector.ExportMetricsServiceRequest> GetMetricsExportClient(this OtlpExporterOptions options) =>
269227
options.Protocol switch
270228
{
Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
// Copyright The OpenTelemetry Authors
22
// SPDX-License-Identifier: Apache-2.0
33

4+
using System.Buffers.Binary;
45
using System.Diagnostics;
56
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;
7+
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.Serializer;
68
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.Transmission;
7-
using OtlpCollector = OpenTelemetry.Proto.Collector.Trace.V1;
8-
using OtlpResource = OpenTelemetry.Proto.Resource.V1;
9+
using OpenTelemetry.Resources;
910

1011
namespace OpenTelemetry.Exporter;
1112

@@ -16,9 +17,15 @@ namespace OpenTelemetry.Exporter;
1617
public class OtlpTraceExporter : BaseExporter<Activity>
1718
{
1819
private readonly SdkLimitOptions sdkLimitOptions;
19-
private readonly OtlpExporterTransmissionHandler<OtlpCollector.ExportTraceServiceRequest> transmissionHandler;
20+
private readonly ProtobufOtlpExporterTransmissionHandler transmissionHandler;
21+
private readonly int startWritePosition;
2022

21-
private OtlpResource.Resource? processResource;
23+
private Resource? resource;
24+
25+
// Initial buffer size set to ~732KB.
26+
// This choice allows us to gradually grow the buffer while targeting a final capacity of around 100 MB,
27+
// by the 7th doubling to maintain efficient allocation without frequent resizing.
28+
private byte[] buffer = new byte[750000];
2229

2330
/// <summary>
2431
/// Initializes a new instance of the <see cref="OtlpTraceExporter"/> class.
@@ -40,31 +47,40 @@ internal OtlpTraceExporter(
4047
OtlpExporterOptions exporterOptions,
4148
SdkLimitOptions sdkLimitOptions,
4249
ExperimentalOptions experimentalOptions,
43-
OtlpExporterTransmissionHandler<OtlpCollector.ExportTraceServiceRequest>? transmissionHandler = null)
50+
ProtobufOtlpExporterTransmissionHandler? transmissionHandler = null)
4451
{
4552
Debug.Assert(exporterOptions != null, "exporterOptions was null");
4653
Debug.Assert(sdkLimitOptions != null, "sdkLimitOptions was null");
4754

4855
this.sdkLimitOptions = sdkLimitOptions!;
49-
50-
this.transmissionHandler = transmissionHandler ?? exporterOptions!.GetTraceExportTransmissionHandler(experimentalOptions);
56+
this.startWritePosition = exporterOptions!.Protocol == OtlpExportProtocol.Grpc ? 5 : 0;
57+
this.transmissionHandler = transmissionHandler ?? exporterOptions!.GetProtobufExportTransmissionHandler(experimentalOptions, OtlpSignalType.Traces);
5158
}
5259

53-
internal OtlpResource.Resource ProcessResource => this.processResource ??= this.ParentProvider.GetResource().ToOtlpResource();
60+
internal Resource Resource => this.resource ??= this.ParentProvider.GetResource();
5461

5562
/// <inheritdoc/>
5663
public override ExportResult Export(in Batch<Activity> activityBatch)
5764
{
5865
// Prevents the exporter's gRPC and HTTP operations from being instrumented.
5966
using var scope = SuppressInstrumentationScope.Begin();
6067

61-
var request = new OtlpCollector.ExportTraceServiceRequest();
62-
6368
try
6469
{
65-
request.AddBatch(this.sdkLimitOptions, this.ProcessResource, activityBatch);
70+
int writePosition = ProtobufOtlpTraceSerializer.WriteTraceData(this.buffer, this.startWritePosition, this.sdkLimitOptions, this.Resource, activityBatch);
71+
72+
if (this.startWritePosition == 5)
73+
{
74+
// Grpc payload consists of 3 parts
75+
// byte 0 - Specifying if the payload is compressed.
76+
// 1-4 byte - Specifies the length of payload in big endian format.
77+
// 5 and above - Protobuf serialized data.
78+
Span<byte> data = new Span<byte>(this.buffer, 1, 4);
79+
var dataLength = writePosition - 5;
80+
BinaryPrimitives.WriteUInt32BigEndian(data, (uint)dataLength);
81+
}
6682

67-
if (!this.transmissionHandler.TrySubmitRequest(request))
83+
if (!this.transmissionHandler.TrySubmitRequest(this.buffer, writePosition))
6884
{
6985
return ExportResult.Failure;
7086
}
@@ -74,17 +90,10 @@ public override ExportResult Export(in Batch<Activity> activityBatch)
7490
OpenTelemetryProtocolExporterEventSource.Log.ExportMethodException(ex);
7591
return ExportResult.Failure;
7692
}
77-
finally
78-
{
79-
request.Return();
80-
}
8193

8294
return ExportResult.Success;
8395
}
8496

8597
/// <inheritdoc />
86-
protected override bool OnShutdown(int timeoutMilliseconds)
87-
{
88-
return this.transmissionHandler.Shutdown(timeoutMilliseconds);
89-
}
98+
protected override bool OnShutdown(int timeoutMilliseconds) => this.transmissionHandler.Shutdown(timeoutMilliseconds);
9099
}

src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -136,16 +136,7 @@ internal static BaseProcessor<Activity> BuildOtlpExporterProcessor(
136136

137137
exporterOptions!.TryEnableIHttpClientFactoryIntegration(serviceProvider!, "OtlpTraceExporter");
138138

139-
BaseExporter<Activity> otlpExporter;
140-
141-
if (experimentalOptions != null && experimentalOptions.UseCustomProtobufSerializer)
142-
{
143-
otlpExporter = new ProtobufOtlpTraceExporter(exporterOptions!, sdkLimitOptions!, experimentalOptions!);
144-
}
145-
else
146-
{
147-
otlpExporter = new OtlpTraceExporter(exporterOptions!, sdkLimitOptions!, experimentalOptions!);
148-
}
139+
BaseExporter<Activity> otlpExporter = new OtlpTraceExporter(exporterOptions!, sdkLimitOptions!, experimentalOptions!);
149140

150141
if (configureExporterInstance != null)
151142
{

0 commit comments

Comments
 (0)