Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add base class for implementing retry strategies in otlp exporter #4872

Merged
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
48ff62c
add interface
vishweshbankwar Sep 13, 2023
f5f09b8
Merge branch 'main' into vibankwa/add-retry-base-for-otlp
vishweshbankwar Sep 15, 2023
0c41318
Merge branch 'main' into vibankwa/add-retry-base-for-otlp
vishweshbankwar Sep 19, 2023
9eda8f7
draft 2
vishweshbankwar Sep 21, 2023
7182b25
Remove persistent handler
vishweshbankwar Sep 21, 2023
83c4e93
rmv using
vishweshbankwar Sep 21, 2023
adf0726
Merge branch 'main' into vibankwa/add-retry-base-for-otlp
vishweshbankwar Sep 21, 2023
c0b13d1
fix integration test
vishweshbankwar Sep 21, 2023
2bb5bcb
Merge branch 'main' into vibankwa/add-retry-base-for-otlp
vishweshbankwar Sep 21, 2023
185c5be
fix whitespace
vishweshbankwar Sep 21, 2023
68ee2b3
Merge branch 'main' into vibankwa/add-retry-base-for-otlp
vishweshbankwar Sep 25, 2023
7a9efe9
Merge branch 'main' into vibankwa/add-retry-base-for-otlp
vishweshbankwar Sep 25, 2023
04a69b4
remarks
vishweshbankwar Sep 25, 2023
28394d3
fix AOT
vishweshbankwar Sep 25, 2023
0de8c82
nullable enable
vishweshbankwar Sep 25, 2023
95f85fc
Merge branch 'main' into vibankwa/add-retry-base-for-otlp
vishweshbankwar Jan 23, 2024
f20c8e6
nullable
vishweshbankwar Jan 23, 2024
64d2fbd
fix header
vishweshbankwar Jan 23, 2024
5cad7a3
revert additional changes
vishweshbankwar Jan 24, 2024
13a0659
Merge branch 'main' into vibankwa/add-retry-base-for-otlp
vishweshbankwar Jan 24, 2024
728323b
fix namespace
vishweshbankwar Jan 24, 2024
df16cc7
Merge branch 'vibankwa/add-retry-base-for-otlp' of https://github.com…
vishweshbankwar Jan 24, 2024
ce23a86
rmv using
vishweshbankwar Jan 24, 2024
2f6b891
Merge branch 'main' into vibankwa/add-retry-base-for-otlp
vishweshbankwar Jan 25, 2024
0fe45e7
rename
vishweshbankwar Jan 26, 2024
f4b114c
rename
vishweshbankwar Jan 26, 2024
9729f43
Merge branch 'main' into vibankwa/add-retry-base-for-otlp
CodeBlanch Jan 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
// limitations under the License.
// </copyright>

using Grpc.Core;
using OtlpCollector = OpenTelemetry.Proto.Collector.Trace.V1;

namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient;
Expand Down Expand Up @@ -43,16 +42,7 @@ public override bool SendExportRequest(OtlpCollector.ExportTraceServiceRequest r
{
var deadline = DateTime.UtcNow.AddMilliseconds(this.TimeoutMilliseconds);

try
{
this.traceClient.Export(request, headers: this.Headers, deadline: deadline, cancellationToken: cancellationToken);
}
catch (RpcException ex)
{
OpenTelemetryProtocolExporterEventSource.Log.FailedToReachCollector(this.Endpoint, ex);

return false;
}
this.traceClient.Export(request, headers: this.Headers, deadline: deadline, cancellationToken: cancellationToken);

return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
// limitations under the License.
// </copyright>

#if NET6_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
using System.Diagnostics.Tracing;
using OpenTelemetry.Internal;

Expand All @@ -35,11 +38,11 @@ public void FailedToReachCollector(Uri collectorUri, Exception ex)
}

[NonEvent]
public void ExportMethodException(Exception ex)
public void ExportMethodException(Exception ex, bool isRetry = false)
{
if (Log.IsEnabled(EventLevel.Error, EventKeywords.All))
{
this.ExportMethodException(ex.ToInvariantString());
this.ExportMethodException(ex.ToInvariantString(), isRetry);
}
}

Expand All @@ -55,10 +58,13 @@ public void CouldNotTranslateActivity(string className, string methodName)
this.WriteEvent(3, className, methodName);
}

[Event(4, Message = "Unknown error in export method: {0}", Level = EventLevel.Error)]
public void ExportMethodException(string ex)
#if NET6_0_OR_GREATER
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Parameters to this method are primitive and are trimmer safe.")]
#endif
[Event(4, Message = "Unknown error in export method. Message: '{0}'. IsRetry: {1}", Level = EventLevel.Error)]
vishweshbankwar marked this conversation as resolved.
Show resolved Hide resolved
public void ExportMethodException(string ex, bool isRetry)
{
this.WriteEvent(4, ex);
this.WriteEvent(4, ex, isRetry);
}

[Event(5, Message = "Could not translate metric from class '{0}' and method '{1}', metric will not be recorded.", Level = EventLevel.Informational)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// <copyright file="OtlpExporterTransmissionHandler.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
CodeBlanch marked this conversation as resolved.
Show resolved Hide resolved
//
// 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.
// </copyright>

vishweshbankwar marked this conversation as resolved.
Show resolved Hide resolved
using OpenTelemetry.Exporter;
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient;

namespace OpenTelemetry.ExporterOpenTelemetryProtocol.Implementation.Retry;

internal class OtlpExporterTransmissionHandler<T>
{
internal IExportClient<T> ExportClient;

public OtlpExporterOptions Options { get; internal set; }

/// <summary>
/// Sends export request to the server.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <returns>True if the request is sent successfully or else false.</returns>
public virtual bool SubmitRequest(T request)
{
try
{
return this.ExportClient.SendExportRequest(request);
}
catch (Exception ex)
{
OpenTelemetryProtocolExporterEventSource.Log.ExportMethodException(ex);
return this.OnSubmitRequestExceptionThrown(request, ex);
}
}

/// <summary>
/// Retries sending request to the server.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="exception">Exception encountered when trying to send request.</param>
/// <returns>True if the request is sent successfully or else false.</returns>
protected virtual bool RetryRequest(T request, out Exception exception)
{
try
{
var result = this.ExportClient.SendExportRequest(request);
exception = null;
return result;
}
catch (Exception ex)
{
OpenTelemetryProtocolExporterEventSource.Log.ExportMethodException(ex, isRetry: true);
exception = ex;
return false;
}
}

/// <summary>
/// Callback to call when encountered exception while sending request to server.
/// </summary>
/// <param name="request">The request that was attempted to send to the server.</param>
/// <param name="exception">Exception that was encountered during request processing.</param>
/// <returns>True or False, based on the implementation of handling errors.</returns>
protected virtual bool OnSubmitRequestExceptionThrown(T request, Exception exception)
{
return this.OnHandleDroppedRequest(request);
}

/// <summary>
/// Action to take when dropping request.
/// </summary>
/// <param name="request">The request that was attempted to send to the server.</param>
/// <returns>True or False, based on the implementation.</returns>
protected virtual bool OnHandleDroppedRequest(T request)
{
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Diagnostics;
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient;
using OpenTelemetry.ExporterOpenTelemetryProtocol.Implementation.Retry;
using OpenTelemetry.Internal;
using OtlpCollector = OpenTelemetry.Proto.Collector.Trace.V1;
using OtlpResource = OpenTelemetry.Proto.Resource.V1;
Expand All @@ -31,6 +32,7 @@ public class OtlpTraceExporter : BaseExporter<Activity>
{
private readonly SdkLimitOptions sdkLimitOptions;
private readonly IExportClient<OtlpCollector.ExportTraceServiceRequest> exportClient;
private readonly OtlpExporterTransmissionHandler<OtlpCollector.ExportTraceServiceRequest> transmissionHandler;

private OtlpResource.Resource processResource;

Expand All @@ -39,7 +41,7 @@ public class OtlpTraceExporter : BaseExporter<Activity>
/// </summary>
/// <param name="options">Configuration options for the export.</param>
public OtlpTraceExporter(OtlpExporterOptions options)
: this(options, new(), null)
: this(options, new(), null, null)
{
}

Expand All @@ -49,10 +51,12 @@ public OtlpTraceExporter(OtlpExporterOptions options)
/// <param name="exporterOptions"><see cref="OtlpExporterOptions"/>.</param>
/// <param name="sdkLimitOptions"><see cref="SdkLimitOptions"/>.</param>
/// <param name="exportClient">Client used for sending export request.</param>
/// <param name="transmissionHandler">Transmission handler for retrying failed requests.</param>
internal OtlpTraceExporter(
OtlpExporterOptions exporterOptions,
SdkLimitOptions sdkLimitOptions,
IExportClient<OtlpCollector.ExportTraceServiceRequest> exportClient = null)
IExportClient<OtlpCollector.ExportTraceServiceRequest> exportClient = null,
OtlpExporterTransmissionHandler<OtlpCollector.ExportTraceServiceRequest> transmissionHandler = null)
{
Debug.Assert(exporterOptions != null, "exporterOptions was null");
Debug.Assert(sdkLimitOptions != null, "sdkLimitOptions was null");
Expand All @@ -77,6 +81,13 @@ internal OtlpTraceExporter(
{
this.exportClient = exporterOptions.GetTraceExportClient();
}

transmissionHandler ??= new OtlpExporterTransmissionHandler<OtlpCollector.ExportTraceServiceRequest>();

transmissionHandler.ExportClient = this.exportClient;
transmissionHandler.Options = exporterOptions;
vishweshbankwar marked this conversation as resolved.
Show resolved Hide resolved

this.transmissionHandler = transmissionHandler;
}

internal OtlpResource.Resource ProcessResource => this.processResource ??= this.ParentProvider.GetResource().ToOtlpResource();
Expand All @@ -93,7 +104,7 @@ public override ExportResult Export(in Batch<Activity> activityBatch)
{
request.AddBatch(this.sdkLimitOptions, this.ProcessResource, activityBatch);

if (!this.exportClient.SendExportRequest(request))
if (!this.transmissionHandler.SubmitRequest(request))
{
return ExportResult.Failure;
}
Expand All @@ -114,6 +125,6 @@ public override ExportResult Export(in Batch<Activity> activityBatch)
/// <inheritdoc />
protected override bool OnShutdown(int timeoutMilliseconds)
{
return this.exportClient?.Shutdown(timeoutMilliseconds) ?? true;
return this.transmissionHandler.ExportClient?.Shutdown(timeoutMilliseconds) ?? true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@

using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using OpenTelemetry.Exporter;
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;
using OpenTelemetry.ExporterOpenTelemetryProtocol.Implementation.Retry;
using OpenTelemetry.Internal;
using OtlpCollector = OpenTelemetry.Proto.Collector.Trace.V1;

namespace OpenTelemetry.Trace;

Expand Down Expand Up @@ -72,6 +75,7 @@ public static TracerProviderBuilder AddOtlpExporter(

OtlpExporterOptions.RegisterOtlpExporterOptionsFactory(services);
services.RegisterOptionsFactory(configuration => new SdkLimitOptions(configuration));
services.TryAddSingleton<OtlpExporterTransmissionHandler<OtlpCollector.ExportTraceServiceRequest>>();
vishweshbankwar marked this conversation as resolved.
Show resolved Hide resolved
});

return builder.AddProcessor(sp =>
Expand Down Expand Up @@ -103,6 +107,8 @@ public static TracerProviderBuilder AddOtlpExporter(
// instance.
var sdkOptionsManager = sp.GetRequiredService<IOptionsMonitor<SdkLimitOptions>>().CurrentValue;

var transmissionmanager = sp.GetRequiredService<OtlpExporterTransmissionHandler<OtlpCollector.ExportTraceServiceRequest>>();

return BuildOtlpExporterProcessor(exporterOptions, sdkOptionsManager, sp);
});
}
Expand All @@ -111,11 +117,15 @@ internal static BaseProcessor<Activity> BuildOtlpExporterProcessor(
OtlpExporterOptions exporterOptions,
SdkLimitOptions sdkLimitOptions,
IServiceProvider serviceProvider,
OtlpExporterTransmissionHandler<OtlpCollector.ExportTraceServiceRequest> transmissionHandler = null,
Func<BaseExporter<Activity>, BaseExporter<Activity>> configureExporterInstance = null)
{
exporterOptions.TryEnableIHttpClientFactoryIntegration(serviceProvider, "OtlpTraceExporter");

BaseExporter<Activity> otlpExporter = new OtlpTraceExporter(exporterOptions, sdkLimitOptions);
BaseExporter<Activity> otlpExporter = new OtlpTraceExporter(
exporterOptions,
sdkLimitOptions,
transmissionHandler: transmissionHandler ?? serviceProvider.GetRequiredService<OtlpExporterTransmissionHandler<OtlpCollector.ExportTraceServiceRequest>>());

if (configureExporterInstance != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public void TraceExportResultIsSuccess(OtlpExportProtocol protocol, string endpo
exporterOptions,
DefaultSdkLimitOptions,
serviceProvider: null,
new ExporterOpenTelemetryProtocol.Implementation.Retry.OtlpExporterTransmissionHandler<Proto.Collector.Trace.V1.ExportTraceServiceRequest>(),
configureExporterInstance: otlpExporter =>
{
delegatingExporter = new DelegatingExporter<Activity>
Expand Down