示例#1
0
 //exponential backoff approach. => if you can not find the service try 5 times, and each time wait for 2 power of last waiting time value.
 private IAsyncPolicy <HttpResponseMessage> GetRetryPolicy()
 {
     return(HttpPolicyExtensions.HandleTransientHttpError().OrResult(response => response.StatusCode == HttpStatusCode.NotFound)
            .WaitAndRetryAsync(retryCount: 5, sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))));
 }
示例#2
0
        public async Task <DeveloperApiKeyResult> GetApiKeyOrNullAsync(bool invalidateCache = false)
        {
            if (!AuthService.IsLoggedIn())
            {
                return(null);
            }

            if (invalidateCache)
            {
                _apiKeyResult = null;
            }

            if (_apiKeyResult != null)
            {
                return(_apiKeyResult);
            }

            var url = $"{CliUrls.WwwAbpIo}api/license/api-key";

            using (var client = new CliHttpClient())
            {
                var response = await HttpPolicyExtensions
                               .HandleTransientHttpError()
                               .OrResult(msg => !msg.IsSuccessStatusCode)
                               .WaitAndRetryAsync(new[]
                {
                    TimeSpan.FromSeconds(1),
                    TimeSpan.FromSeconds(3),
                    TimeSpan.FromSeconds(7)
                },
                                                  (responseMessage, timeSpan, retryCount, context) =>
                {
                    if (responseMessage.Exception != null)
                    {
                        _logger.LogWarning(
                            $"{retryCount}. request attempt failed to {url} with an error: \"{responseMessage.Exception.Message}\". " +
                            $"Waiting {timeSpan.TotalSeconds} secs for the next try...");
                    }
                    else if (responseMessage.Result != null)
                    {
                        _logger.LogWarning(
                            $"{retryCount}. request attempt failed {url} with {(int)responseMessage.Result.StatusCode}-{responseMessage.Result.ReasonPhrase}. " +
                            $"Waiting {timeSpan.TotalSeconds} secs for the next try...");
                    }
                })
                               .ExecuteAsync(async() => await client.GetAsync(url).ConfigureAwait(false)).ConfigureAwait(false);

                if (!response.IsSuccessStatusCode)
                {
                    throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'");
                }

                await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response).ConfigureAwait(false);

                var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                var apiKeyResult = JsonSerializer.Deserialize <DeveloperApiKeyResult>(responseContent);

                return(apiKeyResult);
            }
        }
示例#3
0
 static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
 }
示例#4
0
 public static IAsyncPolicy <HttpResponseMessage> GetWaitAndRetryForeverPolicy() => HttpPolicyExtensions
 .HandleTransientHttpError()
 .WaitAndRetryForeverAsync(retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
示例#5
0
 private static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .CircuitBreakerAsync(2, TimeSpan.FromSeconds(30))); //After two times falls it will not retry until 30 sec.
 }
 private static IAsyncPolicy <HttpResponseMessage> GetRetryPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .WaitAndRetryAsync(retryCount: 6, sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))));
 }
示例#7
0
        internal HttpClientFactoryConfigurator(ILogger logger)
        {
            var retryPolicy = HttpPolicyExtensions
                              .HandleTransientHttpError()
                              .Or <TimeoutRejectedException>() // thrown by Polly's TimeoutPolicy if the inner call times out
                              .WaitAndRetryAsync(new[]
            {
                TimeSpan.FromSeconds(1),
                TimeSpan.FromSeconds(5),
                TimeSpan.FromSeconds(10)
            },
                                                 onRetry: (r, ts, n, ctx) =>
            {
                if (r.Result == default)     // no result, an exception was thrown
                {
                    logger.LogError(r.Exception, $"Retry[{n}]: {r.Exception.Message}");
                }
                else
                {
                    logger.LogError($"Retry[{n}]: ({r.Result.StatusCode}) {r.Result.ReasonPhrase}");
                }
            });

            var timeoutPolicy = Policy.TimeoutAsync <HttpResponseMessage>(20); // Timeout for an individual try

            var circuitBreakerPolicy = HttpPolicyExtensions
                                       .HandleTransientHttpError()
                                       .CircuitBreakerAsync(
                handledEventsAllowedBeforeBreaking: 3,
                durationOfBreak: TimeSpan.FromSeconds(30),
                onBreak: (r, ts, ctx) =>
            {
                if (r.Result == default)         // no result, an exception was thrown
                {
                    logger.LogError(r.Exception, $"Circuit Breaking: {r.Exception.Message}");
                }
                else
                {
                    logger.LogError($"Circuit Breaking: ({r.Result.StatusCode}) {r.Result.ReasonPhrase}");
                }
            },
                onReset: ctx =>
            {
                logger.LogWarning($"Circuit Resetting...");
            });


            ServiceProvider = new ServiceCollection()

                              .AddHttpClient("snapshot", client =>
            {
                //client.Timeout = Timeout.InfiniteTimeSpan; // default: 100 seconds
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                //client.DefaultRequestVersion = new Version(2, 0);
            })
                              .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler()
            {
                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
                AllowAutoRedirect      = false,
                //MaxConnectionsPerServer = 1 // The default: int.MaxValue
            })
                              //.SetHandlerLifetime(Timeout.InfiniteTimeSpan) // default: 2 minutes
                              .AddPolicyHandler(retryPolicy)
                              .AddPolicyHandler(timeoutPolicy)
                              .AddPolicyHandler(circuitBreakerPolicy)
                              .Services

                              .AddHttpClient("history", client =>
            {
                //client.Timeout = Timeout.InfiniteTimeSpan; // default: 100 seconds
                client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
            })
                              .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler()
            {
                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
                AllowAutoRedirect      = false,
                CookieContainer        = new CookieContainer(),
                //MaxConnectionsPerServer = 1 // The default: int.MaxValue
            })
                              //.SetHandlerLifetime(Timeout.InfiniteTimeSpan) // default: 2 minutes
                              .AddPolicyHandler(retryPolicy)
                              .AddPolicyHandler(timeoutPolicy)
                              .AddPolicyHandler(circuitBreakerPolicy)
                              .Services

                              .BuildServiceProvider();
        }
示例#8
0
 private IAsyncPolicy <HttpResponseMessage> GetRetryPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .WaitAndRetryAsync(10, retryTime => TimeSpan.FromSeconds(3)));
 }
示例#9
0
 private static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy()
 => HttpPolicyExtensions.HandleTransientHttpError().CircuitBreakerAsync(CircuitBreakAttempt, DurationOfCircuitBreak);
示例#10
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();

            services.AddControllers()
            .AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.Converters.Add(new StringEnumConverter());
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            });

            services.AddOData();

            services.AddOptions();
            services.AddMemoryCache();

#if (!CacheExists)
            services.AddDistributedMemoryCache();
#endif

#if (CacheSqlServer)
            services.AddDistributedSqlServerCache(options =>
            {
                options.ConnectionString = Configuration.GetConnectionString(Configuration.GetValue <string>("Cache:SqlServer:ConnectionStringKey"));
                options.SchemaName       = Configuration.GetValue <string>("Cache:SqlServer:SchemaName");
                options.TableName        = Configuration.GetValue <string>("Cache:SqlServer:TableName");
            });
#endif
#if (CacheRedis)
            services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = Configuration.GetConnectionString(Configuration.GetValue <string>("Cache:Redis:ConnectionStringKey"));
                options.InstanceName  = Configuration.GetValue <string>("Cache:Redis:InstanceName");
                //x Configuration.GetSection("Cache:Redis").Bind(options);
                options.ConfigurationOptions = ConfigurationOptions.Parse(options.Configuration);
                options.ConfigurationOptions.AbortOnConnectFail = true;
            });
#endif

#if (EntityFramework)
            const string databaseConnectionString = "MsSqlConnection";
            string       connectionString         = Configuration.GetConnectionString(databaseConnectionString);
            string       assemblyName             = Configuration.GetValue(typeof(string)
                                                                           , DbContextFactory.MigrationAssemblyNameConfiguration)
                                                    .ToString();
            services.AddDbContext <BurcinDatabaseDbContext>(options => options.UseSqlServer(connectionString
                                                                                            , sqlServerOptions =>
            {
                sqlServerOptions.MigrationsAssembly(assemblyName);
                sqlServerOptions.EnableRetryOnFailure(5
                                                      , TimeSpan.FromSeconds(30)
                                                      , null);
            }));
#endif

#if (BackgroundService)
            services.AddGracePeriodManagerService(Configuration);
#endif

            services.AddHelper(Configuration);

            services.TryAddEnumerable(ServiceDescriptor.Singleton <MatcherPolicy, DomainMatcherPolicy.DomainMatcherPolicy>());
            services.AddResponseCaching();
            services.AddResponseCompression();

#if (Swagger)
            services.AddSwaggerGen(options =>
            {
                options.IgnoreObsoleteActions();
                options.IgnoreObsoleteProperties();
                options.SwaggerDoc("v1"
                                   , new OpenApiInfo
                {
                    Title = "Burcin API"
                    ,
                    Version = "1.0"
                    ,
                    Description = "Burcin API"
                });
                // Set the comments path for the Swagger JSON and UI.
                string xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                string xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                options.IncludeXmlComments(xmlPath);
            });
            // Workaround: https://github.com/OData/WebApi/issues/1177
            SetOutputFormatters(services);
#endif

#if (BlazorApplication)
            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddScoped <ChefService>();
            services.AddSingleton <WeatherForecastService>();
#endif

            services.AddGoogleStorageService(Configuration);

#if (BlazorApplication || HealthChecks)
            AsyncRetryPolicy <HttpResponseMessage> retryPolicy = HttpPolicyExtensions
                                                                 .HandleTransientHttpError()
                                                                 .Or <TimeoutRejectedException>()
                                                                 .RetryAsync(5);
            services.AddHttpClient("Remote Services").AddPolicyHandler(retryPolicy);
#endif

#if (HealthChecks)
            services.AddSingleton <CustomHealthCheck>();
            services.AddHealthChecks()
            .AddCheck <CustomHealthCheck>(CustomHealthCheck.HealthCheckName
                                          , failureStatus: HealthStatus.Degraded
                                          , tags: new[]
            {
                "ready"
            })
            .AddCheck <SlowDependencyHealthCheck>(SlowDependencyHealthCheck.HealthCheckName
                                                  , failureStatus: null
                                                  , tags: new[]
            {
                "ready"
            })
            .AddAsyncCheck(name: "long_running"
                           , check: async cancellationToken =>
            {
                await Task.Delay(TimeSpan.FromSeconds(5)
                                 , cancellationToken);
                return(HealthCheckResult.Healthy("OK"));
            }
                           , tags: new[]
            {
                "self"
            })
            .AddWorkingSetHealthCheck((long)Ruya.Primitives.Constants.GigaByte * 1
                                      , name: "Memory (WorkingSet)"
                                      , failureStatus: HealthStatus.Degraded
                                      , tags: new[]
            {
                "self"
            })
            .AddDiskStorageHealthCheck(check =>
            {
                check.AddDrive(DriveInfo.GetDrives().First().Name
                               , 1024);
            }
                                       , name: "Disk Storage"
                                       , failureStatus: HealthStatus.Degraded
                                       , tags: new[]
            {
                "self"
            })
            .AddDnsResolveHealthCheck(setup => setup.ResolveHost("burcin.local")
                                      , name: "DNS"
                                      , failureStatus: HealthStatus.Degraded
                                      , tags: new[]
            {
                "self"
            })
            .AddPingHealthCheck(setup => setup.AddHost("burcin.local"
                                                       , (int)TimeSpan.FromSeconds(3)
                                                       .TotalMilliseconds)
                                , name: "Ping"
                                , failureStatus: HealthStatus.Degraded
                                , tags: new[]
            {
                "3rdParty"
            })
            .AddUrlGroup(new[]
            {
                new Uri("https://burcin.local")
            }
                         , name: "Remote Urls"
                         , failureStatus: HealthStatus.Degraded
                         , tags: new[]
            {
                "3rdParty"
            })

                                #if (EntityFramework)
            // TODO: Make the `MsSqlConnection` string constant. It exists in Program.cs too.
            .AddSqlServer(connectionString: Configuration["ConnectionStrings:MsSqlConnection"]
                          , name: "Microsoft SQL"
                          , failureStatus: HealthStatus.Unhealthy
                          , tags: new[]
            {
                "services"
            })
                                #endif
                                #if (CacheSqlServer)
            .AddSqlServer(connectionString: Configuration["ConnectionStrings:MsSqlCacheConnection"]
                          , name: "Microsoft SQL (Cache)"
                          , failureStatus: HealthStatus.Degraded
                          , tags: new[]
            {
                "services"
            })
                                #endif
                                #if (CacheRedis)
            .AddRedis(redisConnectionString: Configuration["ConnectionStrings:RedisCacheConnection"]
                      , name: "Redis"
                      , failureStatus: HealthStatus.Degraded
                      , tags: new[]
            {
                "services"
            })
                                #endif
            .AddRabbitMQ(rabbitConnectionString: Configuration["ConnectionStrings:RabbitMqConnection"]
                         , name: "RabbitMq"
                         , failureStatus: HealthStatus.Unhealthy
                         , tags: new[]
            {
                "services"
            })
            .AddElasticsearch(elasticsearchUri: Configuration["ConnectionStrings:ElasticSearchConnection"]
                              , name: "ElasticSearch"
                              , failureStatus: HealthStatus.Unhealthy
                              , tags: new[]
            {
                "services"
            })
            //.AddApplicationInsightsPublisher()
            //.AddPrometheusGatewayPublisher()
            //.AddSeqPublisher(options => options.Endpoint = Configuration["ConnectionStrings:SeqConnection"])
            ;
            services.AddHealthChecksUI();
                #endif
        }
示例#11
0
 static IAsyncPolicy <HttpResponseMessage> GetRetryPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))));
 }
示例#12
0
 public static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy(int handledEventsAllowedBeforeBreaking = 5, int durationOfBreakSeconds = 30)
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .CircuitBreakerAsync(5, TimeSpan.FromSeconds(durationOfBreakSeconds)));
 }
示例#13
0
 static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy(CircuitBreakingSettings settings)
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .CircuitBreakerAsync(settings.ConsecutiveFaults, settings.BreakTime));
 }
示例#14
0
        private static async Task Main(string[] args)
        {
            var parsingResult = Parser.Default.ParseArguments <ProgramOptions>(args);

            if (parsingResult is Parsed <ProgramOptions> success)
            {
                Options = success.Value;
            }
            else
            {
                return;
            }

            var jitterer    = new Random();
            var retryPolicy = HttpPolicyExtensions
                              .HandleTransientHttpError()
                              .Or <TimeoutException>()
                              .Or <TaskCanceledException>(tex => !tex.CancellationToken.IsCancellationRequested)
                              .Or <IOException>(iex => iex.Message.Contains("Connection reset by peer"))
                              .WaitAndRetryAsync
                              (
                6,
                retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) +
                TimeSpan.FromMilliseconds(jitterer.Next(0, 100))
                              );

            await using var services = new ServiceCollection()
                                       .AddHttpClient <JetbrainsPlugins, JetbrainsPlugins>()
                                       .ConfigurePrimaryHttpMessageHandler
                                       (
                            () =>
                            new SocketsHttpHandler
            {
                AllowAutoRedirect = true,
            }
                                       )
                                       .ConfigureHttpClient
                                       (
                            client =>
            {
                // Timeouts are handled in the handler
                client.Timeout = Timeout.InfiniteTimeSpan;

                client.DefaultRequestHeaders.UserAgent.Clear();
                client.DefaultRequestHeaders.UserAgent.ParseAdd("JetBrains Rider/191.7141355");
            }
                                       )
                                       .ConfigureHttpMessageHandlerBuilder
                                       (
                            builder =>
            {
                var rateLimitingHandler = new RateLimitingHttpHandler
                                          (
                    TimeLimiter.GetFromMaxCountByInterval(128, TimeSpan.FromSeconds(1))
                                          );

                var timeoutHandler = new TimeoutHttpHandler();

                builder.AdditionalHandlers.Add(rateLimitingHandler);
                builder.AdditionalHandlers.Add(timeoutHandler);
            }
                                       )
                                       .AddPolicyHandler(retryPolicy)
                                       .Services
                                       .AddSingleton <RepositoryMirrorer>()
                                       .BuildServiceProvider();
            var mirrorer = services.GetRequiredService <RepositoryMirrorer>();

            using var cancellationSource = new CancellationTokenSource();
            await Console.Out.WriteLineAsync($"Fetching latest plugin versions for {Options.ProductVersions.Humanize()}...");

            await mirrorer.MirrorRepositoriesAsync(Options.ProductVersions, cancellationSource.Token);
        }
示例#15
0
        public static void RegisterServices(IServiceCollection services, IHostingEnvironment environment, IConfiguration configuration)
        {
            IdentityModelEventSource.ShowPII = true;

            //Application
            services.AddScoped <IUserService, UserService>();
            services.AddScoped <IUserQueryService, UserQueryService>();
            services.AddScoped <IUserPreferenceService, UserPreferenceService>();
            services.AddScoped <IUserActivityService, UserActivityService>();
            services.AddScoped <IUserActivityQueryService, UserActivityQueryService>();
            services.AddScoped <ICustomerService, CustomerService>();
            services.AddScoped <ICustomerMemberService, CustomerMemberService>();
            services.AddScoped <ICustomerQueryService, CustomerQueryService>();

            services.AddScoped <IIdentityService, IdentityService>();

            services.AddDbContext <CoreAuthDbContext>(options =>
                                                      options.UseLazyLoadingProxies()
                                                      .UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
                                                                    sqlServerOptionsAction: sqlOptions =>
            {
                sqlOptions.EnableRetryOnFailure(
                    maxRetryCount: 10,
                    maxRetryDelay: TimeSpan.FromSeconds(30),
                    errorNumbersToAdd: null);
            })
                                                      );

            services.AddIdentity <User, IdentityRole>(o =>
            {
                // SignIn settings
                // o.SignIn.RequireConfirmedEmail = true;

                // User settings
                o.User.RequireUniqueEmail = true;

                // Password settings
                o.Password.RequireDigit           = true;
                o.Password.RequireLowercase       = true;
                o.Password.RequireUppercase       = true;
                o.Password.RequireNonAlphanumeric = true;
                o.Password.RequiredLength         = 8;
            })
            .AddEntityFrameworkStores <CoreAuthDbContext>()
            .AddDefaultTokenProviders();

            services.ConfigureApplicationCookie(options =>
            {
                options.LoginPath        = $"/Identity/Account/Login";
                options.LogoutPath       = $"/Identity/Account/Logout";
                options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
            });

            var migrationsAssembly = typeof(CoreAuthDbContext).GetTypeInfo().Assembly.GetName().Name;

            services.AddIdentityServer(options =>
            {
                options.UserInteraction.LoginUrl  = "/Identity/Account/Login";
                options.UserInteraction.LogoutUrl = "/Identity/Account/Logout";

                options.Events.RaiseSuccessEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseErrorEvents   = true;
            })
            .AddDeveloperSigningCredential()
            .AddAspNetIdentity <User>()
            .AddConfigurationStore(options =>
            {
                options.ConfigureDbContext = builder =>
                                             builder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
                                                                  sqlServerOptionsAction: sqlOptions =>
                {
                    sqlOptions.MigrationsAssembly(migrationsAssembly);
                    sqlOptions.EnableRetryOnFailure(
                        maxRetryCount: 10,
                        maxRetryDelay: TimeSpan.FromSeconds(30),
                        errorNumbersToAdd: null);
                });
            })
            .AddOperationalStore(options =>
            {
                options.ConfigureDbContext = builder =>
                                             builder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
                                                                  sqlServerOptionsAction: sqlOptions =>
                {
                    sqlOptions.MigrationsAssembly(migrationsAssembly);
                    sqlOptions.EnableRetryOnFailure(
                        maxRetryCount: 10,
                        maxRetryDelay: TimeSpan.FromSeconds(30),
                        errorNumbersToAdd: null);
                });
                // this enables automatic token cleanup. this is optional.
                options.EnableTokenCleanup   = true;
                options.TokenCleanupInterval = 30;
            });

            services.AddHttpContextAccessor();
            services.AddHttpClient();

            // Domain
            services.AddScoped <IDomainManagerService, DomainManagerService>();

            // Infra - Data
            services.AddTransient <IUserRepository, UserSqlServerRepository>();
            services.AddTransient <ICustomerRepository, CustomerSqlServerRepository>();
            services.AddTransient <ICustomerMemberRepository, CustomerMemberSqlServerRepository>();


            //Polly Policies
            IPolicyRegistry <string> registry = services.AddPolicyRegistry();

            IAsyncPolicy <HttpResponseMessage> httpRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode && r.StatusCode != System.Net.HttpStatusCode.Conflict)
                .RetryAsync(3);

            registry.Add("SimpleHttpRetryPolicy", httpRetryPolicy);

            Random jitterer = new Random();

            IAsyncPolicy <HttpResponseMessage> httWaitAndpRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode && r.StatusCode != System.Net.HttpStatusCode.Conflict)
                .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
                                   + TimeSpan.FromMilliseconds(jitterer.Next(0, 100)));

            registry.Add("SimpleWaitAndRetryPolicy", httWaitAndpRetryPolicy);

            IAsyncPolicy <HttpResponseMessage> noOpPolicy = Policy.NoOpAsync()
                                                            .AsAsyncPolicy <HttpResponseMessage>();

            registry.Add("NoOpPolicy", noOpPolicy);

            services.AddHttpClient("RemoteServerFromService", client =>
            {
                client.DefaultRequestHeaders.Add("Accept", "application/json");
            })
            .AddPolicyHandlerFromRegistry((policyRegistry, httpRequestMessage) =>
            {
                if (httpRequestMessage.Method == HttpMethod.Get)
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("SimpleHttpRetryPolicy"));
                }
                else if (httpRequestMessage.Method == HttpMethod.Post)
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("NoOpPolicy"));
                }
                else
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("SimpleWaitAndRetryPolicy"));
                }
            })
            .AddPolicyHandler((httpRequestMessage) => {
                return(HttpPolicyExtensions.HandleTransientHttpError().CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
            });

            services.AddHttpClient("RemoteServerFromWorker", client =>
            {
                client.DefaultRequestHeaders.Add("Accept", "application/json");
            })
            .AddPolicyHandlerFromRegistry((policyRegistry, httpRequestMessage) =>
            {
                if (httpRequestMessage.Method == HttpMethod.Get)
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("SimpleHttpRetryPolicy"));
                }
                else if (httpRequestMessage.Method == HttpMethod.Post)
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("NoOpPolicy"));
                }
                else
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("SimpleWaitAndRetryPolicy"));
                }
            })
            .AddPolicyHandler((httpRequestMessage) => {
                return(HttpPolicyExtensions.HandleTransientHttpError().CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
            });
        }
示例#16
0
 private static IAsyncPolicy <HttpResponseMessage> GetRetryPolicy(IServiceProvider provider)
 => HttpPolicyExtensions.HandleTransientHttpError()
 .OrResult(httpResponseMessage => GetHttpStatusCodesWorthRetrying().Contains(httpResponseMessage.StatusCode))
 .WaitAndRetryAsync(RetryAttempt, retryAttempt
                    => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (result, timeSpan, attempt, _)
                    => provider.GetService <ILogger <IElasticClient> >().LogWarning(GetRetryMessage(timeSpan, attempt, result)));
示例#17
0
 /// <summary>
 /// Policy to break the retry policy after getting same error for 2 times consecutively
 /// </summary>
 /// <returns></returns>
 public static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy() =>
 HttpPolicyExtensions
 .HandleTransientHttpError()                                             // Only handle 408 or 5xx errors
 .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.Forbidden) // Configure for additional failures
 .CircuitBreakerAsync(2, TimeSpan.FromSeconds(6));
示例#18
0
 public static IAsyncPolicy <HttpResponseMessage> WaitAndRetry(int retryCount = 5) =>
 HttpPolicyExtensions
 .HandleTransientHttpError()
 .Or <HttpRequestException>()
 .Or <TimeoutRejectedException>()
 .WaitAndRetryAsync(retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
示例#19
0
 private static Polly.Retry.AsyncRetryPolicy <HttpResponseMessage> RetryPolicy(int retries)
 => HttpPolicyExtensions
 .HandleTransientHttpError()
 .Or <TimeoutRejectedException>()
 .RetryAsync(retries);
示例#20
0
 private IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPatternPolicy(HttpRequestMessage arg)
 {
     //Circuit breaket pattern to cut-off retrying to connect to a service after a given number of attempts
     //after
     return(HttpPolicyExtensions.HandleTransientHttpError().CircuitBreakerAsync(3, TimeSpan.FromSeconds(30)));
 }
示例#21
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            var cosmosConfig = new CosmosConfig(
                _settings.CosmosSettings.DatabaseName,
                _settings.CosmosSettings.EndpointUri,
                _settings.CosmosSettings.PrimaryKey,
                _settings.CosmosSettings.RequestTimeoutInSeconds
                );
            var cosmosContainers = new List <ContainerInfo>()
            {
                new ContainerInfo()
                {
                    Name         = "rmas",
                    PartitionKey = "PartitionKey"
                }
            };

            var avalaraConfig = new AvalaraConfig()
            {
                BaseApiUrl  = _settings.AvalaraSettings.BaseApiUrl,
                AccountID   = _settings.AvalaraSettings.AccountID,
                LicenseKey  = _settings.AvalaraSettings.LicenseKey,
                CompanyCode = _settings.AvalaraSettings.CompanyCode,
                CompanyID   = _settings.AvalaraSettings.CompanyID
            };

            var currencyConfig = new BlobServiceConfig()
            {
                ConnectionString = _settings.BlobSettings.ConnectionString,
                Container        = _settings.BlobSettings.ContainerNameExchangeRates
            };
            var assetConfig = new BlobServiceConfig()
            {
                ConnectionString = _settings.BlobSettings.ConnectionString,
                Container        = "assets",
                AccessType       = BlobContainerPublicAccessType.Container
            };

            var flurlClientFactory    = new PerBaseUrlFlurlClientFactory();
            var smartyStreetsUsClient = new ClientBuilder(_settings.SmartyStreetSettings.AuthID, _settings.SmartyStreetSettings.AuthToken).BuildUsStreetApiClient();

            services
            .Configure <KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            })
            .Configure <IISServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            })
            .AddSingleton <ISimpleCache, OrderCloud.Common.Services.LazyCacheService>()    // Replace LazyCacheService with RedisService if you have multiple server instances.
            .ConfigureServices()
            .AddOrderCloudUserAuth()
            .AddOrderCloudWebhookAuth(opts => opts.HashKey = _settings.OrderCloudSettings.WebhookHashKey)
            .InjectCosmosStore <LogQuery, OrchestrationLog>(cosmosConfig)
            .InjectCosmosStore <ReportTemplateQuery, ReportTemplate>(cosmosConfig)
            .AddCosmosDb(_settings.CosmosSettings.EndpointUri, _settings.CosmosSettings.PrimaryKey, _settings.CosmosSettings.DatabaseName, cosmosContainers)
            .Inject <IPortalService>()
            .Inject <ISmartyStreetsCommand>()
            .Inject <ICheckoutIntegrationCommand>()
            .Inject <IShipmentCommand>()
            .Inject <IOrderCommand>()
            .Inject <IPaymentCommand>()
            .Inject <IOrderSubmitCommand>()
            .Inject <IEnvironmentSeedCommand>()
            .Inject <IHSProductCommand>()
            .Inject <ILineItemCommand>()
            .Inject <IMeProductCommand>()
            .Inject <IHSCatalogCommand>()
            .Inject <ISendgridService>()
            .Inject <IHSSupplierCommand>()
            .Inject <ICreditCardCommand>()
            .Inject <ISupportAlertService>()
            .Inject <IOrderCalcService>()
            .Inject <IUserContextProvider>()
            .Inject <ISupplierApiClientHelper>()
            .AddSingleton <ISendGridClient>(x => new SendGridClient(_settings.SendgridSettings.ApiKey))
            .AddSingleton <IFlurlClientFactory>(x => flurlClientFactory)
            .AddSingleton <DownloadReportCommand>()
            .Inject <IRMARepo>()
            .Inject <IZohoClient>()
            .AddSingleton <IZohoCommand>(z => new ZohoCommand(new ZohoClient(
                                                                  new ZohoClientConfig()
            {
                ApiUrl         = "https://books.zoho.com/api/v3",
                AccessToken    = _settings.ZohoSettings.AccessToken,
                ClientId       = _settings.ZohoSettings.ClientId,
                ClientSecret   = _settings.ZohoSettings.ClientSecret,
                OrganizationID = _settings.ZohoSettings.OrgID
            }, flurlClientFactory),
                                                              new OrderCloudClient(new OrderCloudClientConfig
            {
                ApiUrl       = _settings.OrderCloudSettings.ApiUrl,
                AuthUrl      = _settings.OrderCloudSettings.ApiUrl,
                ClientId     = _settings.OrderCloudSettings.MiddlewareClientID,
                ClientSecret = _settings.OrderCloudSettings.MiddlewareClientSecret,
                Roles        = new[] { ApiRole.FullAccess }
            })))
            .AddSingleton <IOrderCloudIntegrationsExchangeRatesClient, OrderCloudIntegrationsExchangeRatesClient>()
            .AddSingleton <IAssetClient>(provider => new AssetClient(new OrderCloudIntegrationsBlobService(assetConfig), _settings))
            .AddSingleton <IExchangeRatesCommand>(provider => new ExchangeRatesCommand(new OrderCloudIntegrationsBlobService(currencyConfig), flurlClientFactory, provider.GetService <ISimpleCache>()))
            .AddSingleton <IAvalaraCommand>(x => new AvalaraCommand(
                                                avalaraConfig,
                                                new AvaTaxClient("four51_headstart", "v1", "four51_headstart", new Uri(avalaraConfig.BaseApiUrl)
                                                                 ).WithSecurity(_settings.AvalaraSettings.AccountID, _settings.AvalaraSettings.LicenseKey)))
            .AddSingleton <IEasyPostShippingService>(x => new EasyPostShippingService(new EasyPostConfig()
            {
                APIKey = _settings.EasyPostSettings.APIKey
            }))
            .AddSingleton <ISmartyStreetsService>(x => new SmartyStreetsService(_settings.SmartyStreetSettings, smartyStreetsUsClient))
            .AddSingleton <IOrderCloudIntegrationsCardConnectService>(x => new OrderCloudIntegrationsCardConnectService(_settings.CardConnectSettings, _settings.EnvironmentSettings.Environment.ToString(), flurlClientFactory))
            .AddSingleton <IOrderCloudClient>(provider => new OrderCloudClient(new OrderCloudClientConfig
            {
                ApiUrl       = _settings.OrderCloudSettings.ApiUrl,
                AuthUrl      = _settings.OrderCloudSettings.ApiUrl,
                ClientId     = _settings.OrderCloudSettings.MiddlewareClientID,
                ClientSecret = _settings.OrderCloudSettings.MiddlewareClientSecret,
                Roles        = new[]
                {
                    ApiRole.FullAccess
                }
            }))
            .AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo {
                    Title = "Headstart API", Version = "v1"
                });
                c.CustomSchemaIds(x => x.FullName);
            });
            var serviceProvider = services.BuildServiceProvider();

            services
            .AddApplicationInsightsTelemetry(new ApplicationInsightsServiceOptions
            {
                EnableAdaptiveSampling = false,     // retain all data
                InstrumentationKey     = _settings.ApplicationInsightsSettings.InstrumentationKey
            });


            ServicePointManager.DefaultConnectionLimit       = int.MaxValue;
            FlurlHttp.Configure(settings => settings.Timeout = TimeSpan.FromSeconds(_settings.FlurlSettings.TimeoutInSeconds == 0 ? 30 : _settings.FlurlSettings.TimeoutInSeconds));

            // This adds retry logic for any api call that fails with a transient error (server errors, timeouts, or rate limiting requests)
            // Will retry up to 3 times using exponential backoff and jitter, a mean of 3 seconds wait time in between retries
            // https://github.com/App-vNext/Polly/wiki/Retry-with-jitter#more-complex-jitter
            var delay  = Backoff.DecorrelatedJitterBackoffV2(medianFirstRetryDelay: TimeSpan.FromSeconds(3), retryCount: 3);
            var policy = HttpPolicyExtensions
                         .HandleTransientHttpError()
                         .OrResult(response => response.StatusCode == HttpStatusCode.TooManyRequests)
                         .WaitAndRetryAsync(delay);

            FlurlHttp.Configure(settings => settings.HttpClientFactory = new PollyFactory(policy));
        }
        private void ConfigureServices(IServiceCollection services)
        {
            string functionDirectory = Environment.GetEnvironmentVariable("FUNCTION_DIRECTORY");

            if (string.IsNullOrEmpty(functionDirectory))
            {
                functionDirectory = Directory.GetCurrentDirectory();
            }

            IConfigurationRoot Configuration = new ConfigurationBuilder()
                                               .SetBasePath(functionDirectory)
                                               .AddJsonFile("local.settings.json", optional: true)
                                               .AddJsonFile($"local.settings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true)
                                               .AddJsonFile("logging.json", optional: false)
                                               .AddJsonFile($"logging.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true)
                                               .AddEnvironmentVariables()
                                               .Build();

            //Basic Services
            services.AddTransient <IPasswordGeneratorService, PasswordGeneratorService>();
            services.AddTransient <IPipelineSpaceManagerService, PipelineSpaceManagerService>();
            services.AddTransient <IHttpClientWrapperService, HttpClientWrapperService>();

            //Polly Policies
            IPolicyRegistry <string> registry = services.AddPolicyRegistry();

            IAsyncPolicy <HttpResponseMessage> httpRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                .RetryAsync(3);

            registry.Add("SimpleHttpRetryPolicy", httpRetryPolicy);

            Random jitterer = new Random();

            IAsyncPolicy <HttpResponseMessage> httWaitAndpRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
                                   + TimeSpan.FromMilliseconds(jitterer.Next(0, 100)));

            registry.Add("SimpleWaitAndRetryPolicy", httWaitAndpRetryPolicy);

            IAsyncPolicy <HttpResponseMessage> noOpPolicy = Policy.NoOpAsync()
                                                            .AsAsyncPolicy <HttpResponseMessage>();

            registry.Add("NoOpPolicy", noOpPolicy);

            services.AddHttpClient("RemoteServerFromWorker", client =>
            {
                client.DefaultRequestHeaders.Add("Accept", "application/json");
            })
            .AddPolicyHandlerFromRegistry((policyRegistry, httpRequestMessage) =>
            {
                if (httpRequestMessage.Method == HttpMethod.Get)
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("SimpleHttpRetryPolicy"));
                }
                else if (httpRequestMessage.Method == HttpMethod.Post)
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("NoOpPolicy"));
                }
                else
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("SimpleWaitAndRetryPolicy"));
                }
            })
            .AddPolicyHandler((httpRequestMessage) =>
            {
                return(HttpPolicyExtensions.HandleTransientHttpError().CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
            });

            //Handler Services
            services.AddTransient <ProjectVSTSHandlerService>();
            services.AddTransient <ProjectBitbucketHandlerService>();
            services.AddTransient <ProjectGitHubHandlerService>();

            services.AddTransient <Func <DomainModels.ConfigurationManagementService, IProjectHandlerService> >(serviceProvider => key =>
            {
                switch (key)
                {
                case DomainModels.ConfigurationManagementService.VSTS:
                    return(serviceProvider.GetService <ProjectVSTSHandlerService>());

                case DomainModels.ConfigurationManagementService.Bitbucket:
                    return(serviceProvider.GetService <ProjectBitbucketHandlerService>());

                case DomainModels.ConfigurationManagementService.GitHub:
                    return(serviceProvider.GetService <ProjectGitHubHandlerService>());

                default:
                    throw new KeyNotFoundException();
                }
            });

            services.AddTransient <ProjectServiceVSTSHandlerService>();
            services.AddTransient <ProjectServiceBitbucketHandlerService>();
            services.AddTransient <ProjectServiceGitHubHandlerService>();

            services.AddTransient <Func <DomainModels.ConfigurationManagementService, IProjectServiceHandlerService> >(serviceProvider => key =>
            {
                switch (key)
                {
                case DomainModels.ConfigurationManagementService.VSTS:
                    return(serviceProvider.GetService <ProjectServiceVSTSHandlerService>());

                case DomainModels.ConfigurationManagementService.Bitbucket:
                    return(serviceProvider.GetService <ProjectServiceBitbucketHandlerService>());

                case DomainModels.ConfigurationManagementService.GitHub:
                    return(serviceProvider.GetService <ProjectServiceGitHubHandlerService>());

                default:
                    throw new KeyNotFoundException();
                }
            });

            services.AddTransient <ProjectFeatureVSTSHandlerService>();
            services.AddTransient <ProjectFeatureBitbucketHandlerService>();
            services.AddTransient <ProjectFeatureGitHubHandlerService>();

            services.AddTransient <Func <DomainModels.ConfigurationManagementService, IProjectFeatureHandlerService> >(serviceProvider => key =>
            {
                switch (key)
                {
                case DomainModels.ConfigurationManagementService.VSTS:
                    return(serviceProvider.GetService <ProjectFeatureVSTSHandlerService>());

                case DomainModels.ConfigurationManagementService.Bitbucket:
                    return(serviceProvider.GetService <ProjectFeatureBitbucketHandlerService>());

                case DomainModels.ConfigurationManagementService.GitHub:
                    return(serviceProvider.GetService <ProjectFeatureGitHubHandlerService>());

                default:
                    throw new KeyNotFoundException();
                }
            });

            services.AddTransient <CPSAWSService>();
            services.AddTransient <CPSAzureService>();

            services.AddTransient <Func <DomainModels.CloudProviderService, ICPSService> >(serviceProvider => key =>
            {
                switch (key)
                {
                case DomainModels.CloudProviderService.AWS:
                    return(serviceProvider.GetService <CPSAWSService>());

                case DomainModels.CloudProviderService.Azure:
                    return(serviceProvider.GetService <CPSAzureService>());

                default:
                    throw new KeyNotFoundException();
                }
            });

            services.AddTransient <IEventHandler <ProjectCreatedEvent>, ProjectCreatedHandler>();
            services.AddTransient <IEventHandler <ProjectImportedEvent>, ProjectImportedHandler>();

            services.AddTransient <IEventHandler <ProjectServiceCreatedEvent>, ProjectServiceCreatedHandler>();
            services.AddTransient <IEventHandler <ProjectServiceImportedEvent>, ProjectServiceImportedHandler>();
            services.AddTransient <IEventHandler <ProjectFeatureCreatedEvent>, ProjectFeatureCreatedHandler>();
            services.AddTransient <IEventHandler <ProjectFeatureServiceCreatedEvent>, ProjectFeatureServiceCreatedHandler>();

            services.AddTransient <IEventHandler <ProjectServiceBuildQueuedEvent>, ProjectServiceBuildQueuedHandler>();
            services.AddTransient <IEventHandler <ProjectFeatureServiceBuildQueuedEvent>, ProjectFeatureServiceBuildQueuedHandler>();

            services.AddTransient <IEventHandler <OrganizationDeletedEvent>, OrganizationDeletedHandler>();
            services.AddTransient <IEventHandler <ProjectDeletedEvent>, ProjectDeletedHandler>();
            services.AddTransient <IEventHandler <ProjectServiceDeletedEvent>, ProjectServiceDeletedHandler>();
            services.AddTransient <IEventHandler <ProjectFeatureDeletedEvent>, ProjectFeatureDeletedHandler>();
            services.AddTransient <IEventHandler <ProjectFeatureServiceDeletedEvent>, ProjectFeatureServiceDeletedHandler>();
            services.AddTransient <IEventHandler <ProjectFeatureCompletedEvent>, ProjectFeatureCompletedHandler>();

            services.AddTransient <IEventHandler <ProjectEnvironmentActivatedEvent>, ProjectEnvironmentActivatedHandler>();
            services.AddTransient <IEventHandler <ProjectEnvironmentCreatedEvent>, ProjectEnvironmentCreatedHandler>();
            services.AddTransient <IEventHandler <ProjectEnvironmentDeletedEvent>, ProjectEnvironmentDeletedHandler>();
            services.AddTransient <IEventHandler <ProjectEnvironmentInactivatedEvent>, ProjectEnvironmentInactivatedHandler>();

            services.AddTransient <IEventHandler <ProjectFeatureEnvironmentCreatedEvent>, ProjectFeatureEnvironmentCreatedHandler>();

            services.AddTransient <IEventHandler <OrganizationUserInvitedEvent>, OrganizationUserInvitedHandler>();
            services.AddTransient <IEventHandler <ProjectUserInvitedEvent>, ProjectUserInvitedHandler>();

            services.AddTransient <IEventHandler <ProjectServiceTemplateCreatedEvent>, ProjectServiceTemplateCreatedHandler>();

            services.AddTransient <IRealtimeService, RealtimeService>();


            if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")) && Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT").Equals("production", StringComparison.InvariantCultureIgnoreCase))
            {
                services.AddTransient <IEmailWorkerService, SendGridEmailWorkerService>();
            }
            else
            {
                services.AddTransient <IEmailWorkerService, PostmarkEmailWorkerService>();
            }

            services.Configure <ApplicationOptions>(options =>
            {
                options.Url          = Configuration["Application:Url"];
                options.ClientId     = Configuration["Application:ClientId"];
                options.ClientSecret = Configuration["Application:ClientSecret"];
                options.Scope        = Configuration["Application:Scope"];
            });

            services.Configure <VSTSServiceOptions>(options =>
            {
                options.AccessId     = Configuration["VSTS:AccessId"];
                options.AccessSecret = Configuration["VSTS:AccessSecret"];
                options.AccountId    = Configuration["VSTS:AccountId"];
                options.ApiVersion   = Configuration["VSTS:ApiVersion"];
            });

            services.Configure <FakeAccountServiceOptions>(options =>
            {
                options.AccessId     = Configuration["FakeVSTS:AccessId"];
                options.AccessSecret = Configuration["FakeVSTS:AccessSecret"];
                options.AccountId    = Configuration["FakeVSTS:AccountId"];
                options.ApiVersion   = Configuration["FakeVSTS:ApiVersion"];
            });

            services.Configure <NotificationOptions>(options =>
            {
                options.SendGrid        = new SendGridOptions();
                options.SendGrid.ApiKey = Configuration["Notification:SendGrid:ApiKey"];
                options.SendGrid.From   = Configuration["Notification:SendGrid:From"];
            });
        }
示例#23
0
        /// <summary>
        /// Initializes <see cref="IHost"/> with Sentry monitoring.
        /// </summary>
        public static IHost Init(Context context, string dsn)
        {
            SentrySdk.Init(context, o =>
            {
                // TODO: ShouldCan be deleted once this PR is released: https://github.com/getsentry/sentry-dotnet/pull/1750/files#diff-c55d438dd1d5f3731c0d04d0f1213af4873645b1daa44c4c6e1b24192110d8f8R166-R167
                // System.UnauthorizedAccessException: Access to the path '/proc/stat' is denied.
                o.DetectStartupTime = StartupTimeDetectionMode.Fast;
#if ANDROID
                // TODO: Should be added OOTB
                o.Release = $"{AppInfo.PackageName}@{AppInfo.VersionString}+{AppInfo.BuildString}";

                o.Android.AttachScreenshot        = true;
                o.Android.ProfilingEnabled        = true;
                o.Android.EnableAndroidSdkTracing = true; // Will double report transactions but to get profiler data
#endif
                o.TracesSampleRate = 1.0;
                o.Debug            = true;
#if DEBUG
                o.Environment = "development";
#else
                o.DiagnosticLevel = SentryLevel.Info;
#endif
                o.MaxBreadcrumbs        = 250;
                o.InitCacheFlushTimeout = TimeSpan.FromSeconds(5);
                o.AttachStacktrace      = true;
                o.Dsn            = dsn;
                o.SendDefaultPii = true;

                // TODO: This needs to be built-in
                o.BeforeSend += @event =>
                {
                    const string traceIdKey = "TraceIdentifier";
                    switch (@event.Exception)
                    {
                    case OperationCanceledException _:
                        return(null);

                    case var e when e?.Data.Contains(traceIdKey) == true:
                        @event.SetTag(traceIdKey, e.Data[traceIdKey]?.ToString() ?? "unknown");
                        break;
                    }

                    return(@event);
                };
                // TODO: https://github.com/getsentry/sentry-dotnet/issues/1751
                // o.BeforeBreadcrumb = breadcrumb
                //     // This logger adds 3 crumbs for each HTTP request and we already have a Sentry integration for HTTP
                //     // Which shows the right category, status code and a link
                //     => string.Equals(breadcrumb.Category, "System.Net.Http.HttpClient.ISymbolClient.LogicalHandler")
                //        || string.Equals(breadcrumb.Category, "System.Net.Http.HttpClient.ISymbolClient.ClientHandler")
                //         ? null
                //         : breadcrumb;
            });

            var tran = SentrySdk.StartTransaction("AppStart", "activity.load");

            SentrySdk.ConfigureScope(s =>
            {
                s.Transaction = tran;
                s.AddAttachment(new ScreenshotAttachment());
            });

            // TODO: Where is this span?
            var iocSpan   = tran.StartChild("container.init", "Initializing the IoC container");
            var userAgent = Java.Lang.JavaSystem.GetProperty("http.agent") ?? "Android/" + typeof(Host).Assembly.GetName().Version;
            var host      = Startup.Init(services =>
            {
                var messages = new []
                {
                    // Unable to resolve host "symbol-collector.services.sentry.io": No address associated with hostname
                    "No address associated with hostname",
                    // Read error: ssl=0x79ea0d6988: SSL_ERROR_WANT_READ occurred. You should never see this.
                    "You should never see this",
                    // handshake error: ssl=0x78f5b01b48: I/O error during system call, Try again
                    "Try again",
                    // failed to connect to symbol-collector.services.sentry.io/35.188.18.176 (port 443) from /10.22.91.71 (port 43860) after 86400000ms: isConnected failed: ETIMEDOUT (Connection timed out)
                    "Connection timed out",
                    // Read error: ssl=0x77f787e308: Failure in SSL library, usually a protocol error
                    // error:100003fc:SSL routines:OPENSSL_internal:SSLV3_ALERT_BAD_RECORD_MAC (external/boringssl/src/ssl/tls_record.cc:592 0x77f854d8c8:0x00000001)
                    "Failure in SSL library, usually a protocol error",
                };
                services.AddSingleton <AndroidMessageHandler>();
                services.AddHttpClient <ISymbolClient, SymbolClient>()
                .ConfigurePrimaryHttpMessageHandler <AndroidMessageHandler>()
                .AddPolicyHandler((s, r) =>
                                  HttpPolicyExtensions.HandleTransientHttpError()
                                  // Could be deleted if merged: https://github.com/App-vNext/Polly.Extensions.Http/pull/33
                                  // On Android web get WebException instead of HttpResponseMessage which HandleTransientHttpError covers
                                  .Or <IOException>(e => messages.Any(m => e.Message.Contains(m)))
                                  .Or <WebException>(e => messages.Any(m => e.Message.Contains(m)))
                                  .Or <SocketTimeoutException>()
                                  .SentryPolicy(s));

                services.AddSingleton <AndroidUploader>();
                services.AddOptions().Configure <SymbolClientOptions>(o =>
                {
                    o.UserAgent = userAgent;
                    o.BlockListedPaths.Add("/system/etc/.booking.data.aid");
                    o.BlockListedPaths.Add("/system/build.prop");
                    o.BlockListedPaths.Add("/system/vendor/bin/netstat");
                    o.BlockListedPaths.Add("/system/vendor/bin/swapoff");
                });
                services.AddOptions().Configure <ObjectFileParserOptions>(o =>
                {
                    o.IncludeHash = false;
                    o.UseFallbackObjectFileParser = false; // Android only, use only ELF parser.
                });
            });
            iocSpan.Finish();

            SentrySdk.ConfigureScope(s => s.SetTag("user-agent", userAgent));
            return(host);
        }
 private static IAsyncPolicy <HttpResponseMessage> GetRetryPolicy() =>
 HttpPolicyExtensions
 .HandleTransientHttpError()
 .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
 .WaitAndRetryAsync(5, retryAttempt =>
                    TimeSpan.FromMinutes(1));
示例#25
0
 private IAsyncPolicy <HttpResponseMessage> GetRetryPolicy()
 {
     return(HttpPolicyExtensions.HandleTransientHttpError().
            OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound).
            WaitAndRetryAsync(10, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))));
 }
 public static IAsyncPolicy <HttpResponseMessage> Basic(int allowedUnsuccessfulCalls, int durationOfBreakInSeconds) =>
 HttpPolicyExtensions.HandleTransientHttpError()
 .Or <TaskCanceledException>()
 .Or <TimeoutException>()
 .CircuitBreakerAsync(allowedUnsuccessfulCalls, TimeSpan.FromSeconds(durationOfBreakInSeconds),
                      (result, breakDuration) => throw new BrokenCircuitException("Service inoperative. Circuit is open"),
示例#27
0
 /// <summary>
 /// 熔断策略
 /// </summary>
 public static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError() // System.Net.Http.HttpRequestException情况
            .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
 }
示例#28
0
文件: Startup.cs 项目: Azure/ace-luna
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure <CookiePolicyOptions>(
                options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded    = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
            .AddAzureAD(options => this.configuration.Bind("AzureAd", options));

            services.AddAuthentication(AzureADDefaults.JwtBearerAuthenticationScheme)
            .AddAzureADBearer(options => this.configuration.Bind("AzureAd", options));

            AADAuthHelper.AdminList = this.configuration["ISVPortal:AdminAccounts"].Split(';', StringSplitOptions.RemoveEmptyEntries);

            AADAuthHelper.AdminTenantId = this.configuration["ISVPortal:AdminTenant"];

            services.Configure <JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options =>
            {
                // This is a Microsoft identity platform web API.
                options.Authority += "/v2.0";

                // The web API accepts as audiences both the Client ID (options.Audience) and api://{ClientID}.
                options.TokenValidationParameters.ValidAudiences = new[]
                {
                    options.Audience,
                    $"api://{options.Audience}",
                    this.configuration["AzureAD:ClientId"],
                    $"api://{this.configuration["AzureAD:ClientId"]}"
                };
                options.ClaimsIssuer = @"https://sts.windows.net/{tenantid}/";

                // Instead of using the default validation (validating against a single tenant,
                // as we do in line-of-business apps),
                // we inject our own multitenant validation logic (which even accepts both v1 and v2 tokens).
                options.TokenValidationParameters.IssuerValidator = AadIssuerValidator.GetIssuerValidator(options.Authority).Validate;
            });

            services.Configure <CookieAuthenticationOptions>(
                AzureADDefaults.CookieScheme,
                options => options.AccessDeniedPath = "/Subscriptions/NotAuthorized");

            services.Configure <OpenIdConnectOptions>(
                AzureADDefaults.OpenIdScheme,
                options =>
            {
                //options.Authority = options.Authority + "/v2.0/"; // Azure AD v2.0

                options.TokenValidationParameters.ValidateIssuer =
                    false;         // accept several tenants (here simplified)
            });


            services.Configure <DashboardOptions>(this.configuration.GetSection("Dashboard"));

            services.Configure <AzureOptions>(this.configuration.GetSection("Azure"));

            services.Configure <ApiBehaviorOptions>(x =>
            {
                x.InvalidModelStateResponseFactory = context =>
                {
                    var problemDetails = new ErrorModel(context);
                    return(new BadRequestObjectResult(problemDetails)
                    {
                        ContentTypes = { "application/problem+json", "application/problem+xml" }
                    });
                };
            });

            services.AddOptions <SecuredFulfillmentClientConfiguration>().Configure(
                options => {
                this.configuration.Bind("FulfillmentClient", options);
                this.configuration.Bind("SecuredCredentials:Marketplace", options);
            }
                );
            services.AddHttpClient <IFulfillmentClient, FulfillmentClient>()
            .SetHandlerLifetime(TimeSpan.FromMinutes(5))      //Set lifetime to five minutes
            .AddPolicyHandler(
                (services, request) => HttpPolicyExtensions.HandleTransientHttpError()
                .OrResult(msg => ExceptionUtils.IsHttpErrorCodeRetryable(msg.StatusCode))
                .WaitAndRetryAsync(
                    3,
                    retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
                    onRetry: (result, timeSpan, retryCount, context) =>
            {
                if (result.Exception != null)
                {
                    services.GetService <ILogger <IFulfillmentClient> >()?
                    .LogWarning($"An exception occurred on retry {retryCount} at {context.OperationKey} with message {result.Exception.Message}");
                }
                else
                {
                    services.GetService <ILogger <IFulfillmentClient> >()?
                    .LogError($"An unsuccessful status code {result.Result.StatusCode} was received on retry {retryCount} at {context.OperationKey}");
                }
            }
                    ));

            // Hack to save the host name and port during the handling the request. Please see the WebhookController and ContosoWebhookHandler implementations
            services.AddSingleton <ContosoWebhookHandlerOptions>();


            services.TryAddScoped <IWebhookProcessor, WebhookProcessor>();

            services.TryAddScoped <IFulfillmentManager, FulfillmentManager>();

            // Register the provisioning client
            services.AddOptions <SecuredProvisioningClientConfiguration>().Configure(
                options => {
                this.configuration.Bind("ProvisioningClient", options);
                this.configuration.Bind("SecuredCredentials:ResourceManager", options);
            }
                );
            //services.TryAddScoped<IProvisioningClient, ProvisioningClient>();
            services.AddHttpClient <IProvisioningClient, ProvisioningClient>()
            .SetHandlerLifetime(TimeSpan.FromMinutes(5));


            services.AddHttpClient <ICustomMeteringClient, CustomMeteringClient>();

            // Get the connection string from appsettings.json
            string connectionString = this.configuration.GetValue <string>(this.configuration["SecuredCredentials:Database:ConnectionString"]);

            // Database context must be registered with the dependency injection (DI) container
            services.AddDbContext <SqlDbContext>(options =>
                                                 options.UseSqlServer(connectionString));

            // Register the db context interface
            services.TryAddScoped <ISqlDbContext, SqlDbContext>();


            services.AddOptions <StorageAccountConfigurationOption>().Configure(
                options => {
                this.configuration.Bind("SecuredCredentials:StorageAccount", options);
            }
                );

            // Register the storage utility interface
            services.TryAddScoped <IStorageUtility, StorageUtility>();
            services.TryAddScoped <IKeyVaultHelper, KeyVaultHelper>();
            // Register the provisioning helper
            services.TryAddScoped <IMarketplaceNotificationHandler, ProvisioningHelper>();

            // Register the entity services
            services.TryAddScoped <IOfferService, OfferService>();
            services.TryAddScoped <IArmTemplateService, ArmTemplateService>();
            services.TryAddScoped <IPlanService, PlanService>();
            services.TryAddScoped <ISubscriptionService, SubscriptionService>();
            services.TryAddScoped <IAadSecretTmpService, AadSecretTmpService>();
            services.TryAddScoped <IArmTemplateParameterService, ArmTemplateParameterService>();
            services.TryAddScoped <ICustomMeterService, CustomMeterService>();
            services.TryAddScoped <ICustomMeterDimensionService, CustomMeterDimensionService>();
            services.TryAddScoped <IIpConfigService, IpConfigService>();
            services.TryAddScoped <IOfferParameterService, OfferParameterService>();
            services.TryAddScoped <IRestrictedUserService, RestrictedUserService>();
            services.TryAddScoped <IWebhookService, WebhookService>();
            services.TryAddScoped <IWebhookParameterService, WebhookParameterService>();
            services.TryAddScoped <IProvisioningService, ProvisioningService>();
            services.TryAddScoped <IIpAddressService, IpAddressService>();
            services.TryAddScoped <ISubscriptionParameterService, SubscriptionParameterService>();
            services.TryAddScoped <IWebhookWebhookParameterService, WebhookWebhookParameterService>();
            services.TryAddScoped <IArmTemplateArmTemplateParameterService, ArmTemplateArmTemplateParameterService>();
            services.TryAddScoped <ITelemetryDataConnectorService, TelemetryDataConnectorService>();
            services.TryAddScoped <ISubscriptionCustomMeterUsageService, SubscriptionCustomMeterUsageService>();

            services.TryAddScoped <ICustomMeterEventService, CustomMeterEventService>();
            // Register luna db client
            services.AddHttpClient("Luna", x => { x.BaseAddress = new Uri(configuration.GetValue <string>("LunaClient:BaseUri")); });
            services.TryAddScoped <LunaClient>();


            services.AddCors();

            services.AddRazorPages();

            services.AddApiVersioning(o => {
                DateTime groupVersion = DateTime.ParseExact(apiVersion, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
                ApiVersion latest     = new ApiVersion(groupVersion);

                o.ReportApiVersions = true;
                o.AssumeDefaultVersionWhenUnspecified = true;
                o.DefaultApiVersion = latest;

                o.Conventions.Controller <OfferController>().HasApiVersion(latest);
                o.Conventions.Controller <ArmTemplateController>().HasApiVersion(latest);
                o.Conventions.Controller <PlanController>().HasApiVersion(latest);
                o.Conventions.Controller <SubscriptionController>().HasApiVersion(latest);
                o.Conventions.Controller <ArmTemplateParameterController>().HasApiVersion(latest);
                o.Conventions.Controller <CustomMeterController>().HasApiVersion(latest);
                o.Conventions.Controller <CustomMeterDimensionController>().HasApiVersion(latest);
                o.Conventions.Controller <IpConfigController>().HasApiVersion(latest);
                o.Conventions.Controller <OfferParameterController>().HasApiVersion(latest);
                o.Conventions.Controller <RestrictedUserController>().HasApiVersion(latest);
                o.Conventions.Controller <WebhookController>().HasApiVersion(latest);
                o.Conventions.Controller <WebhookParameterController>().HasApiVersion(latest);
            });

            // Register the Swagger generator, defining 1 or more Swagger documents
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc(apiVersion, new OpenApiInfo {
                    Title = "Luna Dashboard API", Version = apiVersion
                });

                // Set the comments path for the Swagger JSON and UI.
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath);
            });
            services.AddApplicationInsightsTelemetry();
        }
 public TransientRetryHandler(Func <PolicyBuilder <HttpResponseMessage>, IAsyncPolicy <HttpResponseMessage> > configurePolicy)
     : base(configurePolicy(HttpPolicyExtensions.HandleTransientHttpError()))
 {
 }
示例#30
0
 // circuit braker approach : if you get http error, try the request for 3 times and if you still have problems,after 30 secs break all requests to this service.
 private IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPatternPolicy()
 {
     return(HttpPolicyExtensions.HandleTransientHttpError().CircuitBreakerAsync(handledEventsAllowedBeforeBreaking: 3, TimeSpan.FromSeconds(30)));
 }