From 75604ab1e8c6a78b0c1cfe043867fa3c3e3eecad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Kr=C3=A4mer?= Date: Tue, 17 Mar 2020 14:50:30 +0100 Subject: [PATCH] Added call options (#18) New options for ClientTracingConfiguration: * WaitForReady * FallbackCancellationToken --- README.md | 4 +++ .../ClientTracingConfiguration.cs | 7 ++++- .../ServerTracingConfiguration.cs | 2 +- src/OpenTracing.Contrib.Grpc/Extensions.cs | 2 +- .../GrpcTraceLogger.cs | 4 +-- .../Handler/InterceptedClientHandler.cs | 28 +++++++++++++++++-- .../Interceptors/ClientTracingInterceptor.cs | 23 ++++++++++++++- test/OpenTracing.Contrib.Grpc.Test/Program.cs | 1 + 8 files changed, 62 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4d116ec..0832df6 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,8 @@ A `ClientTracingInterceptor` also has default settings, which you can override b - `WithStreaming()`: Logs to the client span whenever a message is sent or a response is received. *Note:* This package supports streaming but has not been rigorously tested. If you come across any issues, please let us know. - `WithVerbosity()`: Logs to the client span additional events, such as call started, message sent, headers received, response received, and call complete. Default only logs if a call is cancelled. - `WithTracedAttributes(params ClientRequestAttribute[] attrs)`: Sets tags on the client span in case you want to track information about the RPC call. +- `WithWaitForReady()`: Enables WaitForReady on all RPC calls. +- `WithFallbackCancellationToken(CancellationToken cancellationToken)`: Sets the cancellation token if the RPC call hasn't defined one. ### Example ```csharp @@ -119,6 +121,8 @@ ClientTracingInterceptor tracingInterceptor = new ClientTracingInterceptor .WithOperationName(new CustomOperationNameConstructor()) .WithTracingAttributes(ClientTracingConfiguration.RequestAttribute.AllCallOptions, ClientTracingConfiguration.ClientRequestAttribute.Headers) + .WithWaitForReady() + .WithFallbackCancellationToken(cancellationToken) .Build(); ``` diff --git a/src/OpenTracing.Contrib.Grpc/Configuration/ClientTracingConfiguration.cs b/src/OpenTracing.Contrib.Grpc/Configuration/ClientTracingConfiguration.cs index b0e536f..7209f80 100644 --- a/src/OpenTracing.Contrib.Grpc/Configuration/ClientTracingConfiguration.cs +++ b/src/OpenTracing.Contrib.Grpc/Configuration/ClientTracingConfiguration.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading; using OpenTracing.Contrib.Grpc.OperationNameConstructor; namespace OpenTracing.Contrib.Grpc.Configuration @@ -17,16 +18,20 @@ public enum RequestAttribute } public ISet TracedAttributes { get; } + public bool WaitForReady { get; } + public CancellationToken FallbackCancellationToken { get; } internal ClientTracingConfiguration(ITracer tracer) : base(tracer) { TracedAttributes = new HashSet(); } - internal ClientTracingConfiguration(ITracer tracer, IOperationNameConstructor operationNameConstructor, bool streaming, bool verbose, ISet tracedAttributes) + internal ClientTracingConfiguration(ITracer tracer, IOperationNameConstructor operationNameConstructor, bool streaming, bool verbose, ISet tracedAttributes, bool waitForReady, CancellationToken fallbackCancellationToken) : base(tracer, operationNameConstructor, streaming, verbose) { TracedAttributes = tracedAttributes ?? new HashSet(); + WaitForReady = waitForReady; + FallbackCancellationToken = fallbackCancellationToken; } } } \ No newline at end of file diff --git a/src/OpenTracing.Contrib.Grpc/Configuration/ServerTracingConfiguration.cs b/src/OpenTracing.Contrib.Grpc/Configuration/ServerTracingConfiguration.cs index 74a1da9..851fc58 100644 --- a/src/OpenTracing.Contrib.Grpc/Configuration/ServerTracingConfiguration.cs +++ b/src/OpenTracing.Contrib.Grpc/Configuration/ServerTracingConfiguration.cs @@ -20,7 +20,7 @@ internal ServerTracingConfiguration(ITracer tracer) : base(tracer) TracedAttributes = new HashSet(); } - internal ServerTracingConfiguration(ITracer tracer, IOperationNameConstructor operationNameConstructor, bool streaming, bool verbose, ISet tracedAttributes) + internal ServerTracingConfiguration(ITracer tracer, IOperationNameConstructor operationNameConstructor, bool streaming, bool verbose, ISet tracedAttributes) : base(tracer, operationNameConstructor, streaming, verbose) { TracedAttributes = tracedAttributes ?? new HashSet(); diff --git a/src/OpenTracing.Contrib.Grpc/Extensions.cs b/src/OpenTracing.Contrib.Grpc/Extensions.cs index c6fc7ab..34c3b93 100644 --- a/src/OpenTracing.Contrib.Grpc/Extensions.cs +++ b/src/OpenTracing.Contrib.Grpc/Extensions.cs @@ -18,7 +18,7 @@ public static ISpan SetException(this ISpan span, Exception ex) {LogFields.ErrorObject, ex}, // Those fields will be removed once Configration.WithExpandExceptionLogs is implemented - {LogFields.ErrorKind, ex.GetType().Name}, + {LogFields.ErrorKind, ex.GetType().Name}, {LogFields.Message, ex.Message}, {LogFields.Stack, ex.StackTrace} }); diff --git a/src/OpenTracing.Contrib.Grpc/GrpcTraceLogger.cs b/src/OpenTracing.Contrib.Grpc/GrpcTraceLogger.cs index f94d8fe..b0d3542 100644 --- a/src/OpenTracing.Contrib.Grpc/GrpcTraceLogger.cs +++ b/src/OpenTracing.Contrib.Grpc/GrpcTraceLogger.cs @@ -5,8 +5,8 @@ namespace OpenTracing.Contrib.Grpc { - internal class GrpcTraceLogger - where TRequest : class + internal class GrpcTraceLogger + where TRequest : class where TResponse : class { private readonly ISpan _span; diff --git a/src/OpenTracing.Contrib.Grpc/Handler/InterceptedClientHandler.cs b/src/OpenTracing.Contrib.Grpc/Handler/InterceptedClientHandler.cs index 898e016..1b28bc3 100644 --- a/src/OpenTracing.Contrib.Grpc/Handler/InterceptedClientHandler.cs +++ b/src/OpenTracing.Contrib.Grpc/Handler/InterceptedClientHandler.cs @@ -23,10 +23,11 @@ public InterceptedClientHandler(ClientTracingConfiguration configuration, Client { _configuration = configuration; _context = context; - if (context.Options.Headers == null) + + var callOptions = ApplyConfigToCallOptions(_context.Options); + if (!Equals(callOptions, context.Options)) { - _context = new ClientInterceptorContext(context.Method, context.Host, - context.Options.WithHeaders(new Metadata())); // Add empty metadata to options + _context = new ClientInterceptorContext(context.Method, context.Host, callOptions); } var span = InitializeSpanWithHeaders(); @@ -34,6 +35,27 @@ public InterceptedClientHandler(ClientTracingConfiguration configuration, Client _configuration.Tracer.Inject(span.Context, BuiltinFormats.HttpHeaders, new MetadataCarrier(_context.Options.Headers)); } + private CallOptions ApplyConfigToCallOptions(CallOptions callOptions) + { + if (callOptions.Headers == null) + { + // Add empty metadata to options: + callOptions = callOptions.WithHeaders(new Metadata()); + } + + if (_configuration.WaitForReady && callOptions.IsWaitForReady != _configuration.WaitForReady) + { + callOptions = callOptions.WithWaitForReady(); + } + + if (_configuration.FallbackCancellationToken != default && callOptions.CancellationToken != _configuration.FallbackCancellationToken) + { + callOptions = callOptions.WithCancellationToken(_configuration.FallbackCancellationToken); + } + + return callOptions; + } + private ISpan InitializeSpanWithHeaders() { var operationName = _configuration.OperationNameConstructor.ConstructOperationName(_context.Method); diff --git a/src/OpenTracing.Contrib.Grpc/Interceptors/ClientTracingInterceptor.cs b/src/OpenTracing.Contrib.Grpc/Interceptors/ClientTracingInterceptor.cs index 7019ccd..3bf1e63 100644 --- a/src/OpenTracing.Contrib.Grpc/Interceptors/ClientTracingInterceptor.cs +++ b/src/OpenTracing.Contrib.Grpc/Interceptors/ClientTracingInterceptor.cs @@ -4,6 +4,7 @@ using OpenTracing.Contrib.Grpc.Configuration; using OpenTracing.Contrib.Grpc.Handler; using System.Collections.Generic; +using System.Threading; using OpenTracing.Contrib.Grpc.OperationNameConstructor; namespace OpenTracing.Contrib.Grpc.Interceptors @@ -61,6 +62,8 @@ public class Builder private bool _streaming; private bool _verbose; private ISet _tracedAttributes; + private bool _waitForReady; + private CancellationToken _cancellationToken; public Builder(ITracer tracer) { @@ -103,9 +106,27 @@ public Builder WithTracedAttributes(params ClientTracingConfiguration.RequestAtt return this; } + /// + /// Enables WaitForReady call option for all calls. + /// + /// this Builder configured to be verbose + public Builder WithWaitForReady() + { + _waitForReady = true; + return this; + } + + /// The cancellation token to set for all RPCs if none was set. + /// this Builder configured to be verbose + public Builder WithFallbackCancellationToken(CancellationToken cancellationToken) + { + _cancellationToken = cancellationToken; + return this; + } + public ClientTracingInterceptor Build() { - var configuration = new ClientTracingConfiguration(_tracer, _operationNameConstructor, _streaming, _verbose, _tracedAttributes); + var configuration = new ClientTracingConfiguration(_tracer, _operationNameConstructor, _streaming, _verbose, _tracedAttributes, _waitForReady, _cancellationToken); return new ClientTracingInterceptor(configuration); } } diff --git a/test/OpenTracing.Contrib.Grpc.Test/Program.cs b/test/OpenTracing.Contrib.Grpc.Test/Program.cs index 36a2e8b..229af6f 100644 --- a/test/OpenTracing.Contrib.Grpc.Test/Program.cs +++ b/test/OpenTracing.Contrib.Grpc.Test/Program.cs @@ -49,6 +49,7 @@ private static async Task MainAsync() .WithStreaming() .WithVerbosity() .WithTracedAttributes(ClientTracingConfiguration.RequestAttribute.AllCallOptions, ClientTracingConfiguration.RequestAttribute.Headers) + .WithWaitForReady() .Build(); var client = new Phone.PhoneClient(new Channel("localhost:8011", ChannelCredentials.Insecure).Intercept(tracingInterceptor));