[repo] Update dotnet format ci job (#4881)
Co-authored-by: Reiley Yang <reyang@microsoft.com> Co-authored-by: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> Co-authored-by: Mikel Blanchard <mblanchard@macrosssoftware.com>
This commit is contained in:
parent
ff9912f87a
commit
2de73b2c12
|
|
@ -23,8 +23,5 @@ jobs:
|
|||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v3
|
||||
|
||||
- name: Install format tool
|
||||
run: dotnet tool install -g dotnet-format
|
||||
|
||||
- name: dotnet format
|
||||
run: dotnet-format --folder --check
|
||||
run: dotnet format OpenTelemetry.sln --verify-no-changes
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ namespace OpenTelemetry.Logs;
|
|||
/// Contains extension methods for the <see cref="LoggerProviderBuilder"/> class.
|
||||
/// </summary>
|
||||
#if EXPOSE_EXPERIMENTAL_FEATURES
|
||||
public
|
||||
public
|
||||
#else
|
||||
internal
|
||||
#endif
|
||||
static class OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions
|
||||
static class OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions
|
||||
{
|
||||
#if EXPOSE_EXPERIMENTAL_FEATURES
|
||||
/// <summary>
|
||||
|
|
@ -59,9 +59,9 @@ namespace OpenTelemetry.Logs;
|
|||
#endif
|
||||
public static LoggerProviderBuilder AddInstrumentation<
|
||||
#if NET6_0_OR_GREATER
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
#endif
|
||||
T>(this LoggerProviderBuilder loggerProviderBuilder)
|
||||
T>(this LoggerProviderBuilder loggerProviderBuilder)
|
||||
where T : class
|
||||
{
|
||||
loggerProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());
|
||||
|
|
|
|||
|
|
@ -23,11 +23,11 @@ namespace OpenTelemetry.Logs;
|
|||
/// Extension methods for setting up OpenTelemetry logging services in an <see cref="IServiceCollection" />.
|
||||
/// </summary>
|
||||
#if EXPOSE_EXPERIMENTAL_FEATURES
|
||||
public
|
||||
public
|
||||
#else
|
||||
internal
|
||||
#endif
|
||||
static class OpenTelemetryDependencyInjectionLoggingServiceCollectionExtensions
|
||||
static class OpenTelemetryDependencyInjectionLoggingServiceCollectionExtensions
|
||||
{
|
||||
#if EXPOSE_EXPERIMENTAL_FEATURES
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ public static class OpenTelemetryDependencyInjectionMeterProviderBuilderExtensio
|
|||
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
|
||||
public static MeterProviderBuilder AddInstrumentation<
|
||||
#if NET6_0_OR_GREATER
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
#endif
|
||||
T>(this MeterProviderBuilder meterProviderBuilder)
|
||||
T>(this MeterProviderBuilder meterProviderBuilder)
|
||||
where T : class
|
||||
{
|
||||
meterProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ public static class OpenTelemetryDependencyInjectionTracerProviderBuilderExtensi
|
|||
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
|
||||
public static TracerProviderBuilder AddInstrumentation<
|
||||
#if NET6_0_OR_GREATER
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
#endif
|
||||
T>(this TracerProviderBuilder tracerProviderBuilder)
|
||||
T>(this TracerProviderBuilder tracerProviderBuilder)
|
||||
where T : class
|
||||
{
|
||||
tracerProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());
|
||||
|
|
|
|||
|
|
@ -67,12 +67,12 @@ internal static class OtlpRetry
|
|||
|
||||
public static bool TryGetHttpRetryResult(HttpStatusCode statusCode, DateTime? deadline, HttpResponseHeaders responseHeaders, int retryDelayMilliseconds, out RetryResult retryResult)
|
||||
{
|
||||
return OtlpRetry.TryGetRetryResult(statusCode, IsHttpStatusCodeRetryable, deadline, responseHeaders, TryGetHttpRetryDelay, retryDelayMilliseconds, out retryResult);
|
||||
return TryGetRetryResult(statusCode, IsHttpStatusCodeRetryable, deadline, responseHeaders, TryGetHttpRetryDelay, retryDelayMilliseconds, out retryResult);
|
||||
}
|
||||
|
||||
public static bool TryGetGrpcRetryResult(StatusCode statusCode, DateTime? deadline, Metadata trailers, int retryDelayMilliseconds, out RetryResult retryResult)
|
||||
{
|
||||
return OtlpRetry.TryGetRetryResult(statusCode, IsGrpcStatusCodeRetryable, deadline, trailers, TryGetGrpcRetryDelay, retryDelayMilliseconds, out retryResult);
|
||||
return TryGetRetryResult(statusCode, IsGrpcStatusCodeRetryable, deadline, trailers, TryGetGrpcRetryDelay, retryDelayMilliseconds, out retryResult);
|
||||
}
|
||||
|
||||
private static bool TryGetRetryResult<TStatusCode, TCarrier>(TStatusCode statusCode, Func<TStatusCode, bool, bool> isRetryable, DateTime? deadline, TCarrier carrier, Func<TStatusCode, TCarrier, TimeSpan?> throttleGetter, int nextRetryDelayMilliseconds, out RetryResult retryResult)
|
||||
|
|
|
|||
|
|
@ -165,9 +165,9 @@ internal
|
|||
#endif
|
||||
public static LoggerProviderBuilder AddProcessor<
|
||||
#if NET6_0_OR_GREATER
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
#endif
|
||||
T>(this LoggerProviderBuilder loggerProviderBuilder)
|
||||
T>(this LoggerProviderBuilder loggerProviderBuilder)
|
||||
where T : BaseProcessor<LogRecord>
|
||||
{
|
||||
loggerProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());
|
||||
|
|
|
|||
|
|
@ -64,9 +64,9 @@ public static class MeterProviderBuilderExtensions
|
|||
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
|
||||
public static MeterProviderBuilder AddReader<
|
||||
#if NET6_0_OR_GREATER
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
#endif
|
||||
T>(this MeterProviderBuilder meterProviderBuilder)
|
||||
T>(this MeterProviderBuilder meterProviderBuilder)
|
||||
where T : MetricReader
|
||||
{
|
||||
meterProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());
|
||||
|
|
|
|||
|
|
@ -83,9 +83,9 @@ public static class TracerProviderBuilderExtensions
|
|||
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
|
||||
public static TracerProviderBuilder SetSampler<
|
||||
#if NET6_0_OR_GREATER
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
#endif
|
||||
T>(this TracerProviderBuilder tracerProviderBuilder)
|
||||
T>(this TracerProviderBuilder tracerProviderBuilder)
|
||||
where T : Sampler
|
||||
{
|
||||
tracerProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());
|
||||
|
|
@ -203,9 +203,9 @@ public static class TracerProviderBuilderExtensions
|
|||
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
|
||||
public static TracerProviderBuilder AddProcessor<
|
||||
#if NET6_0_OR_GREATER
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
#endif
|
||||
T>(this TracerProviderBuilder tracerProviderBuilder)
|
||||
T>(this TracerProviderBuilder tracerProviderBuilder)
|
||||
where T : BaseProcessor<Activity>
|
||||
{
|
||||
tracerProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());
|
||||
|
|
|
|||
|
|
@ -19,90 +19,89 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
namespace OpenTelemetry.Exporter
|
||||
namespace OpenTelemetry.Exporter;
|
||||
|
||||
internal static class PeerServiceResolver
|
||||
{
|
||||
internal static class PeerServiceResolver
|
||||
private static readonly Dictionary<string, int> PeerServiceKeyResolutionDictionary = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
private static readonly Dictionary<string, int> PeerServiceKeyResolutionDictionary = new(StringComparer.OrdinalIgnoreCase)
|
||||
[SemanticConventions.AttributePeerService] = 0, // priority 0 (highest).
|
||||
["peer.hostname"] = 1,
|
||||
["peer.address"] = 1,
|
||||
[SemanticConventions.AttributeHttpHost] = 2, // peer.service for Http.
|
||||
[SemanticConventions.AttributeDbInstance] = 2, // peer.service for Redis.
|
||||
};
|
||||
|
||||
public interface IPeerServiceState
|
||||
{
|
||||
string? PeerService { get; set; }
|
||||
|
||||
int? PeerServicePriority { get; set; }
|
||||
|
||||
string? HostName { get; set; }
|
||||
|
||||
string? IpAddress { get; set; }
|
||||
|
||||
long Port { get; set; }
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void InspectTag<T>(ref T state, string key, string? value)
|
||||
where T : struct, IPeerServiceState
|
||||
{
|
||||
if (PeerServiceKeyResolutionDictionary.TryGetValue(key, out int priority)
|
||||
&& (state.PeerService == null || priority < state.PeerServicePriority))
|
||||
{
|
||||
[SemanticConventions.AttributePeerService] = 0, // priority 0 (highest).
|
||||
["peer.hostname"] = 1,
|
||||
["peer.address"] = 1,
|
||||
[SemanticConventions.AttributeHttpHost] = 2, // peer.service for Http.
|
||||
[SemanticConventions.AttributeDbInstance] = 2, // peer.service for Redis.
|
||||
};
|
||||
|
||||
public interface IPeerServiceState
|
||||
{
|
||||
string? PeerService { get; set; }
|
||||
|
||||
int? PeerServicePriority { get; set; }
|
||||
|
||||
string? HostName { get; set; }
|
||||
|
||||
string? IpAddress { get; set; }
|
||||
|
||||
long Port { get; set; }
|
||||
state.PeerService = value;
|
||||
state.PeerServicePriority = priority;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void InspectTag<T>(ref T state, string key, string? value)
|
||||
where T : struct, IPeerServiceState
|
||||
else if (key == SemanticConventions.AttributeNetPeerName)
|
||||
{
|
||||
if (PeerServiceKeyResolutionDictionary.TryGetValue(key, out int priority)
|
||||
&& (state.PeerService == null || priority < state.PeerServicePriority))
|
||||
{
|
||||
state.PeerService = value;
|
||||
state.PeerServicePriority = priority;
|
||||
}
|
||||
else if (key == SemanticConventions.AttributeNetPeerName)
|
||||
{
|
||||
state.HostName = value;
|
||||
}
|
||||
else if (key == SemanticConventions.AttributeNetPeerIp)
|
||||
{
|
||||
state.IpAddress = value;
|
||||
}
|
||||
else if (key == SemanticConventions.AttributeNetPeerPort && long.TryParse(value, out var port))
|
||||
{
|
||||
state.Port = port;
|
||||
}
|
||||
state.HostName = value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void InspectTag<T>(ref T state, string key, long value)
|
||||
where T : struct, IPeerServiceState
|
||||
else if (key == SemanticConventions.AttributeNetPeerIp)
|
||||
{
|
||||
if (key == SemanticConventions.AttributeNetPeerPort)
|
||||
{
|
||||
state.Port = value;
|
||||
}
|
||||
state.IpAddress = value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Resolve<T>(ref T state, out string? peerServiceName, out bool addAsTag)
|
||||
where T : struct, IPeerServiceState
|
||||
else if (key == SemanticConventions.AttributeNetPeerPort && long.TryParse(value, out var port))
|
||||
{
|
||||
peerServiceName = state.PeerService;
|
||||
state.Port = port;
|
||||
}
|
||||
}
|
||||
|
||||
// If priority = 0 that means peer.service was included in tags
|
||||
addAsTag = state.PeerServicePriority != 0;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void InspectTag<T>(ref T state, string key, long value)
|
||||
where T : struct, IPeerServiceState
|
||||
{
|
||||
if (key == SemanticConventions.AttributeNetPeerPort)
|
||||
{
|
||||
state.Port = value;
|
||||
}
|
||||
}
|
||||
|
||||
if (addAsTag)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Resolve<T>(ref T state, out string? peerServiceName, out bool addAsTag)
|
||||
where T : struct, IPeerServiceState
|
||||
{
|
||||
peerServiceName = state.PeerService;
|
||||
|
||||
// If priority = 0 that means peer.service was included in tags
|
||||
addAsTag = state.PeerServicePriority != 0;
|
||||
|
||||
if (addAsTag)
|
||||
{
|
||||
var hostNameOrIpAddress = state.HostName ?? state.IpAddress;
|
||||
|
||||
// peer.service has not already been included, but net.peer.name/ip and optionally net.peer.port are present
|
||||
if (hostNameOrIpAddress != null)
|
||||
{
|
||||
var hostNameOrIpAddress = state.HostName ?? state.IpAddress;
|
||||
|
||||
// peer.service has not already been included, but net.peer.name/ip and optionally net.peer.port are present
|
||||
if (hostNameOrIpAddress != null)
|
||||
{
|
||||
peerServiceName = state.Port == default
|
||||
? hostNameOrIpAddress
|
||||
: $"{hostNameOrIpAddress}:{state.Port}";
|
||||
}
|
||||
else if (state.PeerService != null)
|
||||
{
|
||||
peerServiceName = state.PeerService;
|
||||
}
|
||||
peerServiceName = state.Port == default
|
||||
? hostNameOrIpAddress
|
||||
: $"{hostNameOrIpAddress}:{state.Port}";
|
||||
}
|
||||
else if (state.PeerService != null)
|
||||
{
|
||||
peerServiceName = state.PeerService;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public class OtlpMetricsExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
void CheckMetricReaderDefaults()
|
||||
{
|
||||
var bindingFlags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
|
||||
var bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
|
||||
var metricReader = typeof(MetricReader)
|
||||
.Assembly
|
||||
|
|
|
|||
|
|
@ -19,198 +19,197 @@ using Google.Protobuf.WellKnownTypes;
|
|||
using Grpc.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient.Tests
|
||||
namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient.Tests;
|
||||
|
||||
public class OtlpRetryTests
|
||||
{
|
||||
public class OtlpRetryTests
|
||||
public static IEnumerable<object[]> GrpcRetryTestData => GrpcRetryTestCase.GetTestCases();
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GrpcRetryTestData))]
|
||||
public void TryGetGrpcRetryResultTest(GrpcRetryTestCase testCase)
|
||||
{
|
||||
public static IEnumerable<object[]> GrpcRetryTestData => GrpcRetryTestCase.GetTestCases();
|
||||
var attempts = 0;
|
||||
var nextRetryDelayMilliseconds = OtlpRetry.InitialBackoffMilliseconds;
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GrpcRetryTestData))]
|
||||
public void TryGetGrpcRetryResultTest(GrpcRetryTestCase testCase)
|
||||
foreach (var retryAttempt in testCase.RetryAttempts)
|
||||
{
|
||||
var attempts = 0;
|
||||
var nextRetryDelayMilliseconds = OtlpRetry.InitialBackoffMilliseconds;
|
||||
++attempts;
|
||||
var statusCode = retryAttempt.RpcException.StatusCode;
|
||||
var deadline = retryAttempt.CallOptions.Deadline;
|
||||
var trailers = retryAttempt.RpcException.Trailers;
|
||||
var success = OtlpRetry.TryGetGrpcRetryResult(statusCode, deadline, trailers, nextRetryDelayMilliseconds, out var retryResult);
|
||||
|
||||
foreach (var retryAttempt in testCase.RetryAttempts)
|
||||
Assert.Equal(retryAttempt.ExpectedSuccess, success);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
++attempts;
|
||||
var statusCode = retryAttempt.RpcException.StatusCode;
|
||||
var deadline = retryAttempt.CallOptions.Deadline;
|
||||
var trailers = retryAttempt.RpcException.Trailers;
|
||||
var success = OtlpRetry.TryGetGrpcRetryResult(statusCode, deadline, trailers, nextRetryDelayMilliseconds, out var retryResult);
|
||||
|
||||
Assert.Equal(retryAttempt.ExpectedSuccess, success);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
Assert.Equal(testCase.ExpectedRetryAttempts, attempts);
|
||||
break;
|
||||
}
|
||||
|
||||
if (retryResult.Throttled)
|
||||
{
|
||||
Assert.Equal(retryAttempt.ThrottleDelay, retryResult.RetryDelay);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(retryResult.RetryDelay >= TimeSpan.Zero);
|
||||
Assert.True(retryResult.RetryDelay < TimeSpan.FromMilliseconds(nextRetryDelayMilliseconds));
|
||||
}
|
||||
|
||||
Assert.Equal(retryAttempt.ExpectedNextRetryDelayMilliseconds, retryResult.NextRetryDelayMilliseconds);
|
||||
|
||||
nextRetryDelayMilliseconds = retryResult.NextRetryDelayMilliseconds;
|
||||
Assert.Equal(testCase.ExpectedRetryAttempts, attempts);
|
||||
break;
|
||||
}
|
||||
|
||||
Assert.Equal(testCase.ExpectedRetryAttempts, attempts);
|
||||
if (retryResult.Throttled)
|
||||
{
|
||||
Assert.Equal(retryAttempt.ThrottleDelay, retryResult.RetryDelay);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(retryResult.RetryDelay >= TimeSpan.Zero);
|
||||
Assert.True(retryResult.RetryDelay < TimeSpan.FromMilliseconds(nextRetryDelayMilliseconds));
|
||||
}
|
||||
|
||||
Assert.Equal(retryAttempt.ExpectedNextRetryDelayMilliseconds, retryResult.NextRetryDelayMilliseconds);
|
||||
|
||||
nextRetryDelayMilliseconds = retryResult.NextRetryDelayMilliseconds;
|
||||
}
|
||||
|
||||
public class GrpcRetryTestCase
|
||||
Assert.Equal(testCase.ExpectedRetryAttempts, attempts);
|
||||
}
|
||||
|
||||
public class GrpcRetryTestCase
|
||||
{
|
||||
public int ExpectedRetryAttempts;
|
||||
public GrpcRetryAttempt[] RetryAttempts;
|
||||
|
||||
private string testRunnerName;
|
||||
|
||||
private GrpcRetryTestCase(string testRunnerName, GrpcRetryAttempt[] retryAttempts, int expectedRetryAttempts = 1)
|
||||
{
|
||||
public int ExpectedRetryAttempts;
|
||||
public GrpcRetryAttempt[] RetryAttempts;
|
||||
this.ExpectedRetryAttempts = expectedRetryAttempts;
|
||||
this.RetryAttempts = retryAttempts;
|
||||
this.testRunnerName = testRunnerName;
|
||||
}
|
||||
|
||||
private string testRunnerName;
|
||||
public static IEnumerable<object[]> GetTestCases()
|
||||
{
|
||||
yield return new[] { new GrpcRetryTestCase("Cancelled", new GrpcRetryAttempt[] { new(StatusCode.Cancelled) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("DeadlineExceeded", new GrpcRetryAttempt[] { new(StatusCode.DeadlineExceeded) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("Aborted", new GrpcRetryAttempt[] { new(StatusCode.Aborted) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("OutOfRange", new GrpcRetryAttempt[] { new(StatusCode.OutOfRange) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("DataLoss", new GrpcRetryAttempt[] { new(StatusCode.DataLoss) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("Unavailable", new GrpcRetryAttempt[] { new(StatusCode.Unavailable) }) };
|
||||
|
||||
private GrpcRetryTestCase(string testRunnerName, GrpcRetryAttempt[] retryAttempts, int expectedRetryAttempts = 1)
|
||||
yield return new[] { new GrpcRetryTestCase("OK", new GrpcRetryAttempt[] { new(StatusCode.OK, expectedSuccess: false) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("PermissionDenied", new GrpcRetryAttempt[] { new(StatusCode.PermissionDenied, expectedSuccess: false) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("Unknown", new GrpcRetryAttempt[] { new(StatusCode.Unknown, expectedSuccess: false) }) };
|
||||
|
||||
yield return new[] { new GrpcRetryTestCase("ResourceExhausted w/o RetryInfo", new GrpcRetryAttempt[] { new(StatusCode.ResourceExhausted, expectedSuccess: false) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("ResourceExhausted w/ RetryInfo", new GrpcRetryAttempt[] { new(StatusCode.ResourceExhausted, throttleDelay: new Duration { Seconds = 2 }, expectedNextRetryDelayMilliseconds: 3000) }) };
|
||||
|
||||
yield return new[] { new GrpcRetryTestCase("Unavailable w/ RetryInfo", new GrpcRetryAttempt[] { new(StatusCode.Unavailable, throttleDelay: Duration.FromTimeSpan(TimeSpan.FromMilliseconds(2000)), expectedNextRetryDelayMilliseconds: 3000) }) };
|
||||
|
||||
yield return new[] { new GrpcRetryTestCase("Expired deadline", new GrpcRetryAttempt[] { new(StatusCode.Unavailable, deadlineExceeded: true, expectedSuccess: false) }) };
|
||||
|
||||
yield return new[]
|
||||
{
|
||||
this.ExpectedRetryAttempts = expectedRetryAttempts;
|
||||
this.RetryAttempts = retryAttempts;
|
||||
this.testRunnerName = testRunnerName;
|
||||
}
|
||||
new GrpcRetryTestCase(
|
||||
"Exponential backoff",
|
||||
new GrpcRetryAttempt[]
|
||||
{
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1500),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 2250),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 3375),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000),
|
||||
},
|
||||
expectedRetryAttempts: 5),
|
||||
};
|
||||
|
||||
public static IEnumerable<object[]> GetTestCases()
|
||||
yield return new[]
|
||||
{
|
||||
yield return new[] { new GrpcRetryTestCase("Cancelled", new GrpcRetryAttempt[] { new(StatusCode.Cancelled) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("DeadlineExceeded", new GrpcRetryAttempt[] { new(StatusCode.DeadlineExceeded) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("Aborted", new GrpcRetryAttempt[] { new(StatusCode.Aborted) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("OutOfRange", new GrpcRetryAttempt[] { new(StatusCode.OutOfRange) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("DataLoss", new GrpcRetryAttempt[] { new(StatusCode.DataLoss) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("Unavailable", new GrpcRetryAttempt[] { new(StatusCode.Unavailable) }) };
|
||||
new GrpcRetryTestCase(
|
||||
"Retry until non-retryable status code encountered",
|
||||
new GrpcRetryAttempt[]
|
||||
{
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1500),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 2250),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 3375),
|
||||
new(StatusCode.PermissionDenied, expectedSuccess: false),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000),
|
||||
},
|
||||
expectedRetryAttempts: 4),
|
||||
};
|
||||
|
||||
yield return new[] { new GrpcRetryTestCase("OK", new GrpcRetryAttempt[] { new(StatusCode.OK, expectedSuccess: false) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("PermissionDenied", new GrpcRetryAttempt[] { new(StatusCode.PermissionDenied, expectedSuccess: false) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("Unknown", new GrpcRetryAttempt[] { new(StatusCode.Unknown, expectedSuccess: false) }) };
|
||||
|
||||
yield return new[] { new GrpcRetryTestCase("ResourceExhausted w/o RetryInfo", new GrpcRetryAttempt[] { new(StatusCode.ResourceExhausted, expectedSuccess: false) }) };
|
||||
yield return new[] { new GrpcRetryTestCase("ResourceExhausted w/ RetryInfo", new GrpcRetryAttempt[] { new(StatusCode.ResourceExhausted, throttleDelay: new Duration { Seconds = 2 }, expectedNextRetryDelayMilliseconds: 3000) }) };
|
||||
|
||||
yield return new[] { new GrpcRetryTestCase("Unavailable w/ RetryInfo", new GrpcRetryAttempt[] { new(StatusCode.Unavailable, throttleDelay: Duration.FromTimeSpan(TimeSpan.FromMilliseconds(2000)), expectedNextRetryDelayMilliseconds: 3000) }) };
|
||||
|
||||
yield return new[] { new GrpcRetryTestCase("Expired deadline", new GrpcRetryAttempt[] { new(StatusCode.Unavailable, deadlineExceeded: true, expectedSuccess: false) }) };
|
||||
|
||||
yield return new[]
|
||||
{
|
||||
new GrpcRetryTestCase(
|
||||
"Exponential backoff",
|
||||
new GrpcRetryAttempt[]
|
||||
{
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1500),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 2250),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 3375),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000),
|
||||
},
|
||||
expectedRetryAttempts: 5),
|
||||
};
|
||||
|
||||
yield return new[]
|
||||
{
|
||||
new GrpcRetryTestCase(
|
||||
"Retry until non-retryable status code encountered",
|
||||
new GrpcRetryAttempt[]
|
||||
{
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1500),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 2250),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 3375),
|
||||
new(StatusCode.PermissionDenied, expectedSuccess: false),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000),
|
||||
},
|
||||
expectedRetryAttempts: 4),
|
||||
};
|
||||
|
||||
// Test throttling affects exponential backoff.
|
||||
yield return new[]
|
||||
{
|
||||
new GrpcRetryTestCase(
|
||||
"Exponential backoff after throttling",
|
||||
new GrpcRetryAttempt[]
|
||||
{
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1500),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 2250),
|
||||
new(StatusCode.Unavailable, throttleDelay: Duration.FromTimeSpan(TimeSpan.FromMilliseconds(500)), expectedNextRetryDelayMilliseconds: 750),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1125),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1688),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 2532),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 3798),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000),
|
||||
},
|
||||
expectedRetryAttempts: 9),
|
||||
};
|
||||
|
||||
yield return new[]
|
||||
{
|
||||
new GrpcRetryTestCase(
|
||||
"Ridiculous throttling delay",
|
||||
new GrpcRetryAttempt[]
|
||||
{
|
||||
new(StatusCode.Unavailable, throttleDelay: Duration.FromTimeSpan(TimeSpan.FromDays(3000000)), expectedNextRetryDelayMilliseconds: 5000),
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
// Test throttling affects exponential backoff.
|
||||
yield return new[]
|
||||
{
|
||||
return this.testRunnerName;
|
||||
}
|
||||
new GrpcRetryTestCase(
|
||||
"Exponential backoff after throttling",
|
||||
new GrpcRetryAttempt[]
|
||||
{
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1500),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 2250),
|
||||
new(StatusCode.Unavailable, throttleDelay: Duration.FromTimeSpan(TimeSpan.FromMilliseconds(500)), expectedNextRetryDelayMilliseconds: 750),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1125),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1688),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 2532),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 3798),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000),
|
||||
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000),
|
||||
},
|
||||
expectedRetryAttempts: 9),
|
||||
};
|
||||
|
||||
private static Metadata GenerateTrailers(Duration throttleDelay)
|
||||
yield return new[]
|
||||
{
|
||||
var metadata = new Metadata();
|
||||
new GrpcRetryTestCase(
|
||||
"Ridiculous throttling delay",
|
||||
new GrpcRetryAttempt[]
|
||||
{
|
||||
new(StatusCode.Unavailable, throttleDelay: Duration.FromTimeSpan(TimeSpan.FromDays(3000000)), expectedNextRetryDelayMilliseconds: 5000),
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
var retryInfo = new Google.Rpc.RetryInfo();
|
||||
retryInfo.RetryDelay = throttleDelay;
|
||||
public override string ToString()
|
||||
{
|
||||
return this.testRunnerName;
|
||||
}
|
||||
|
||||
var status = new Google.Rpc.Status();
|
||||
status.Details.Add(Any.Pack(retryInfo));
|
||||
private static Metadata GenerateTrailers(Duration throttleDelay)
|
||||
{
|
||||
var metadata = new Metadata();
|
||||
|
||||
var stream = new MemoryStream();
|
||||
status.WriteTo(stream);
|
||||
var retryInfo = new Google.Rpc.RetryInfo();
|
||||
retryInfo.RetryDelay = throttleDelay;
|
||||
|
||||
metadata.Add(OtlpRetry.GrpcStatusDetailsHeader, stream.ToArray());
|
||||
return metadata;
|
||||
}
|
||||
var status = new Google.Rpc.Status();
|
||||
status.Details.Add(Any.Pack(retryInfo));
|
||||
|
||||
public struct GrpcRetryAttempt
|
||||
var stream = new MemoryStream();
|
||||
status.WriteTo(stream);
|
||||
|
||||
metadata.Add(OtlpRetry.GrpcStatusDetailsHeader, stream.ToArray());
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public struct GrpcRetryAttempt
|
||||
{
|
||||
public RpcException RpcException;
|
||||
public CallOptions CallOptions;
|
||||
public TimeSpan? ThrottleDelay;
|
||||
public int? ExpectedNextRetryDelayMilliseconds;
|
||||
public bool ExpectedSuccess;
|
||||
|
||||
public GrpcRetryAttempt(
|
||||
StatusCode statusCode,
|
||||
bool deadlineExceeded = false,
|
||||
Duration throttleDelay = null,
|
||||
int expectedNextRetryDelayMilliseconds = 1500,
|
||||
bool expectedSuccess = true)
|
||||
{
|
||||
public RpcException RpcException;
|
||||
public CallOptions CallOptions;
|
||||
public TimeSpan? ThrottleDelay;
|
||||
public int? ExpectedNextRetryDelayMilliseconds;
|
||||
public bool ExpectedSuccess;
|
||||
var status = new Status(statusCode, "Error");
|
||||
this.RpcException = throttleDelay != null
|
||||
? new RpcException(status, GenerateTrailers(throttleDelay))
|
||||
: new RpcException(status);
|
||||
|
||||
public GrpcRetryAttempt(
|
||||
StatusCode statusCode,
|
||||
bool deadlineExceeded = false,
|
||||
Duration throttleDelay = null,
|
||||
int expectedNextRetryDelayMilliseconds = 1500,
|
||||
bool expectedSuccess = true)
|
||||
{
|
||||
var status = new Status(statusCode, "Error");
|
||||
this.RpcException = throttleDelay != null
|
||||
? new RpcException(status, GenerateTrailers(throttleDelay))
|
||||
: new RpcException(status);
|
||||
this.CallOptions = deadlineExceeded ? new CallOptions(deadline: DateTime.UtcNow.AddSeconds(-1)) : default;
|
||||
|
||||
this.CallOptions = deadlineExceeded ? new CallOptions(deadline: DateTime.UtcNow.AddSeconds(-1)) : default;
|
||||
this.ThrottleDelay = throttleDelay != null ? throttleDelay.ToTimeSpan() : null;
|
||||
|
||||
this.ThrottleDelay = throttleDelay != null ? throttleDelay.ToTimeSpan() : null;
|
||||
this.ExpectedNextRetryDelayMilliseconds = expectedNextRetryDelayMilliseconds;
|
||||
|
||||
this.ExpectedNextRetryDelayMilliseconds = expectedNextRetryDelayMilliseconds;
|
||||
|
||||
this.ExpectedSuccess = expectedSuccess;
|
||||
}
|
||||
this.ExpectedSuccess = expectedSuccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public class W3CTraceContextTests : IDisposable
|
|||
// disabling due to failing dotnet-format
|
||||
// TODO: investigate why dotnet-format fails.
|
||||
#pragma warning disable SA1008 // Opening parenthesis should be spaced correctly
|
||||
app.MapPost("/", async([FromBody] Data[] data) =>
|
||||
app.MapPost("/", async ([FromBody] Data[] data) =>
|
||||
{
|
||||
var result = string.Empty;
|
||||
if (data != null)
|
||||
|
|
|
|||
Loading…
Reference in New Issue