/// <summary> /// <para>Sets up a module that enriches all requests with two auxiliary headers:</para> /// <list type="bullet"> /// <item><description><paramref name="priorityHeader"/> with the value of request's <see cref="RequestParameters.Priority"/></description></item> /// <item><description><paramref name="identityHeader"/> with the value of configuration's <see cref="IClusterClientConfiguration.ClientApplicationName"/></description></item> /// </list> /// </summary> public static void SetupAuxiliaryHeaders( this IClusterClientConfiguration configuration, string priorityHeader = HeaderNames.RequestPriority, string identityHeader = HeaderNames.ApplicationIdentity) { configuration.AddRequestModule(new AuxiliaryHeadersModule(priorityHeader, identityHeader)); }
/// <summary> /// Inject latency to the every request retry with default latency performer /// </summary> /// <example> /// <code> /// ------► + injected latency ---► replica(1..n) /// ↑__________retry (1..n)__________________| /// </code> /// </example> /// <param name="configuration">IClusterClientConfiguration instance</param> /// <param name="latencyProvider">Func returning latency to inject</param> /// <param name="rateProvider">Func returning injection probability (rate)</param> public static void InjectLatencyOnEveryRetry( this IClusterClientConfiguration configuration, Func <TimeSpan> latencyProvider, Func <double> rateProvider) { configuration.AddRequestModule(new LatencyModule(new LatencyPerformer(), new RateManager(), latencyProvider, rateProvider), RequestModule.RequestRetry, ModulePosition.After); }
/// <summary> /// <para>Adds given <paramref name="module"/> to configuration's <see cref="IClusterClientConfiguration.Modules"/> collection.</para> /// <para><paramref name="module"/> will be inserted into request module chain once near <paramref name="relatedModule"/>.</para> /// </summary> /// <param name="relatedModule">A module near which <paramref name="module"/> will be inserted.</param> /// <param name="module">A module to insert into request pipeline.</param> /// <param name="configuration">A configuration instance.</param> /// <param name="position">A relative position of <paramref name="module"/> from <paramref name="relatedModule"/>. This parameter is optional and has default value <see cref="ModulePosition.Before"/>.</param> public static void AddRequestModule( this IClusterClientConfiguration configuration, IRequestModule module, RequestModule relatedModule = RequestModule.Logging, ModulePosition position = ModulePosition.Before) { configuration.AddRequestModule(module, RequestModulesMapping.GetModuleType(relatedModule), position); }
/// <summary> /// Adds a <see cref="DistributedContextModule"/> to request modules pipeline and wraps transport with <see cref="DistributedContextTransport"/>. /// </summary> public static void SetupDistributedContext([NotNull] this IClusterClientConfiguration configuration) { configuration.AddRequestModule(new DistributedContextModule(), RequestModule.AuxiliaryHeaders); if (!(configuration.Transport is DistributedContextTransport)) { configuration.Transport = new DistributedContextTransport(configuration.Transport); } }
/// <summary> /// Sets up a replica budgeting mechanism with given parameters. /// </summary> /// <param name="configuration">A configuration to be modified.</param> /// <param name="storageKey">See <see cref="ReplicaBudgetingOptions.StorageKey"/>.</param> /// <param name="minutesToTrack">See <see cref="ReplicaBudgetingOptions.MinutesToTrack"/>.</param> /// <param name="minimumRequests">See <see cref="ReplicaBudgetingOptions.MinimumRequests"/>.</param> /// <param name="criticalRatio">See <see cref="ReplicaBudgetingOptions.CriticalRatio"/>.</param> public static void SetupReplicaBudgeting( this IClusterClientConfiguration configuration, string storageKey, int minutesToTrack = ClusterClientDefaults.ReplicaBudgetingMinutesToTrack, int minimumRequests = ClusterClientDefaults.ReplicaBudgetingMinimumRequests, double criticalRatio = ClusterClientDefaults.ReplicaBudgetingCriticalRatio) { var options = new ReplicaBudgetingOptions(storageKey, minutesToTrack, minimumRequests, criticalRatio); configuration.AddRequestModule(new ReplicaBudgetingModule(options), RequestModule.RequestExecution); }
public static void SetupSingular(this IClusterClientConfiguration configuration, SingularClientSettings settings) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (settings == null) { throw new ArgumentNullException(nameof(settings)); } configuration.RequestTransforms.Add( new AdHocRequestTransform( request => request .WithHeader(SingularHeaders.Environment, settings.TargetEnvironment) .WithHeader(SingularHeaders.Service, settings.TargetService))); configuration.TargetEnvironment = settings.TargetEnvironment; configuration.TargetServiceName = ServiceMeshEnvironmentInfo.UseLocalSingular ? $"{settings.TargetService} via ServiceMesh" : $"{settings.TargetService} via {SingularConstants.ServiceName}"; var clusterConfigClient = ClusterConfigClient.Default; configuration.ClusterProvider = settings.AlternativeClusterProvider ?? new ClusterConfigClusterProvider(clusterConfigClient, SingularConstants.CCTopologyName, configuration.Log); configuration.SetupWeighedReplicaOrdering( builder => { var datacenters = DatacentersProvider.Get(); builder.AddRelativeWeightModifier(new RelativeWeightSettings()); builder.SetupAvoidInactiveDatacentersWeightModifier(datacenters); builder.SetupBoostLocalDatacentersWeightModifier(datacenters); }); var forkingStrategy = Strategy.Forking(SingularClientConstants.ForkingStrategyParallelismLevel); var idempotencyIdentifier = IdempotencyIdentifierCache.Get(clusterConfigClient, settings.TargetEnvironment, settings.TargetService); configuration.DefaultRequestStrategy = new IdempotencySignBasedRequestStrategy(idempotencyIdentifier, Strategy.Sequential1, forkingStrategy); configuration.MaxReplicasUsedPerRequest = SingularClientConstants.ForkingStrategyParallelismLevel; if (ServiceMeshEnvironmentInfo.UseLocalSingular) { var serviceMeshRequestModule = new ServiceMeshRequestModule(configuration.Log, idempotencyIdentifier); configuration.AddRequestModule(serviceMeshRequestModule, RequestModule.RequestExecution); } InitializeMetricsProviderIfNeeded(configuration, settings.MetricContext, clusterConfigClient); }
private static void InitializeMetricsProviderIfNeeded(IClusterClientConfiguration configuration, IMetricContext?metricContext, IClusterConfigClient clusterConfigClient) { if (metricContext == null && MetricContextProvider.IsConfigured) { metricContext = MetricContextProvider.Get(); } if (metricContext != null) { var environment = clusterConfigClient.Get(SingularConstants.EnvironmentNamePath)?.Value; if (environment == SingularConstants.ProdEnvironment || environment == SingularConstants.CloudEnvironment) { var metricsProvider = MetricsProviderCache.Get(metricContext, environment, SloMetricsClientName); configuration.AddRequestModule(new MetricsModule(metricsProvider)); } } }
/// <summary> /// Sets up an adaptive client throttling mechanism with given parameters. /// </summary> /// <param name="configuration">A configuration to be modified.</param> /// <param name="storageKey">See <see cref="AdaptiveThrottlingOptions.StorageKey"/>.</param> /// <param name="minutesToTrack">See <see cref="AdaptiveThrottlingOptions.MinutesToTrack"/>.</param> /// <param name="minimumRequests">See <see cref="AdaptiveThrottlingOptions.MinimumRequests"/>.</param> /// <param name="criticalRatio">See <see cref="AdaptiveThrottlingOptions.CriticalRatio"/>.</param> /// <param name="maximumRejectProbability">See <see cref="AdaptiveThrottlingOptions.MaximumRejectProbability"/>.</param> public static void SetupAdaptiveThrottling( this IClusterClientConfiguration configuration, string storageKey, int minutesToTrack = ClusterClientDefaults.AdaptiveThrottlingMinutesToTrack, int minimumRequests = ClusterClientDefaults.AdaptiveThrottlingMinimumRequests, double criticalRatio = ClusterClientDefaults.AdaptiveThrottlingCriticalRatio, double maximumRejectProbability = ClusterClientDefaults.AdaptiveThrottlingRejectProbabilityCap) { var options = new AdaptiveThrottlingOptions( storageKey, minutesToTrack, minimumRequests, criticalRatio, maximumRejectProbability); configuration.AddRequestModule(new AdaptiveThrottlingModule(options), typeof(AbsoluteUrlSenderModule)); }
/// <summary> /// Sets up distributed tracing of HTTP requests using given <paramref name="configuration"/>. /// </summary> public static void SetupDistributedTracing([NotNull] this IClusterClientConfiguration config, [NotNull] TracingConfiguration configuration) { config.SetupDistributedContext(); var tracingTransport = new TracingTransport(config.Transport, configuration) { TargetServiceProvider = () => config.TargetServiceName, TargetEnvironmentProvider = () => config.TargetEnvironment }; var tracingModule = new TracingModule(configuration) { TargetServiceProvider = () => config.TargetServiceName, TargetEnvironmentProvider = () => config.TargetEnvironment }; config.Transport = tracingTransport; config.AddRequestModule(tracingModule, typeof(DistributedContextModule)); }
/// <summary> /// Enables fixing of undertuned <see cref="System.Threading.ThreadPool"/> limits upon encountering request timeouts. /// </summary> public static void SetupThreadPoolLimitsTuning(this IClusterClientConfiguration configuration) { configuration.AddRequestModule(ThreadPoolTuningModule.Instance, typeof(LoggingModule)); }
/// <summary> /// Enables HTTP request method validation. Valid HTTP methods listed in <see cref="RequestMethods" /> class. /// </summary> public static void SetupHttpMethodValidation(this IClusterClientConfiguration configuration) { configuration.AddRequestModule(new HttpMethodValidationModule(), typeof(RequestValidationModule), ModulePosition.After); }