Example #1
0
        public async Task RunAsync(DateTime oldestDate)
        {
            _Log.LogInformation($"Deleting URL histories older than {oldestDate}.");
            var count = await _Context.DeleteUrlHistoriesOlderThan(oldestDate);

            _Log.LogInformation($"Deleted {count} URL histories older than {oldestDate}.");
        }
        public async Task <ChannelConfigContainer> GetChannelConfigAsync(decimal channelId)
        {
            _Log.LogInformation($"Getting channel config for channel '{channelId}'.");
            var result = await _Context.GetChannelConfigAsync(channelId);

            _Log.LogInformation($"Got channel config for channel '{channelId}'.");
            return(result);
        }
Example #3
0
        public async Task <BroadcasterConfigContainer> GetBroadcasterConfigAsync(decimal channelId, string broadcaster)
        {
            _Log.LogInformation($"Getting channel config for channel '{channelId}'.");
            var result = await _Context.GetBroadcasterConfigAsync(channelId, broadcaster);

            _Log.LogInformation($"Got channel config for channel '{channelId}'.");
            return(result);
        }
Example #4
0
        public async Task <IActionResult> RunAsync()
        {
            _Log.LogInformation("Getting prefix dictionary.");
            var prefixDictionary = await _Context.GetPrefixDictionary();

            _Log.LogInformation($"Got {prefixDictionary.Count} prefixes.");
            return(new OkObjectResult(prefixDictionary));
        }
        public async Task <IActionResult> RunAsync(JobConfigContainer container, decimal channelId)
        {
            _Log.LogInformation($"Channel {channelId} posting job config.");
            var result = await _Context.SetJobConfig(channelId, container);

            _Log.LogInformation($"Channel {channelId} posted job config.");
            return(new OkObjectResult(result));
        }
        public async Task <ChannelConfigContainer> PostChannelConfigAsync(decimal channelId, ChannelConfigContainer container)
        {
            _Log.LogInformation($"Posting channel config for channel '{channelId}'.");
            var result = await _Context.SetChannelConfigAsync(channelId, container);

            _Log.LogInformation($"Posted channel config for channel '{channelId}'.");
            return(result);
        }
Example #7
0
        public async Task <IActionResult> RunAsync(decimal channelId)
        {
            _Log.LogInformation($"Channel {channelId} deleting job config.");
            await _Context.DeleteJobConfig(channelId);

            _Log.LogInformation($"Channel {channelId} deleted job config.");
            return(new NoContentResult());
        }
        public async Task <IActionResult> RunAsync(decimal channelId)
        {
            _Log.LogInformation($"Channel {channelId} getting job config.");
            var container = await _Context.GetJobConfig(channelId);

            _Log.LogInformation($"Channel {channelId} got job config.");
            return(new OkObjectResult(container));
        }
        private void SetupHttpConnection(string baseUrl)
        {
            if (!UriIncludesHttpPrefex(baseUrl) && !UriIncludesHttpsPrefex(baseUrl))
            {
                var errorMessage = $"URI is invalid because http(s) was not included in ${baseUrl}";
                _loggerWrapper.LogInformation(errorMessage, GetType().Name, nameof(SetupHttpConnection), null);
                throw new ArgumentException(errorMessage, nameof(baseUrl));
            }

            _loggerWrapper.LogInformation("Setting up http connection with base url of " + baseUrl, GetType().Name, nameof(SetupHttpConnection) + "()", null);

            IHttwrapConfiguration httwrapConfiguration = new HttwrapConfiguration(baseUrl);

            _httwrapClient = new HttwrapClient(httwrapConfiguration);
        }
Example #10
0
        public static void Main(string[] args)
        {
            var startUpCorrelationId = Guid.NewGuid().ToString();

            try
            {
                var configuration = InitialiseConfiguration(new ConfigurationBuilder(), args).Build();
                InitialiseLoggingAndErrorHandling(configuration);

                IWebHost host;

                using (_logger.BeginScopeWithCommonData(startUpCorrelationId, null, null, null, true, false))
                {
                    _logger.LogInformation("Logging is all set up and ready to go");

                    _logger.LogInformation("About to call BuildWebHost");

                    host = WebHost.CreateDefaultBuilder(args)
                           .UseNLog()
                           .ConfigureServices(services =>
                    {
                        services.AddPlatformServices();
                    })
                           .ConfigureAppConfiguration(cfg => InitialiseConfiguration(cfg, args))
                           .ConfigureAppMetricsHostingConfiguration(options =>
                    {
                        options.AllEndpointsPort = configuration.GetValue <int>("MetricsEndpoints:AllEndpointsPort");
                    })
                           .UseStartup <Startup>()
                           .Build();

                    _logger.LogInformation("About to call webHost.Run");
                }

                host.Run();
            }
            catch (Exception ex)
                when(PassToErrorHandler(ex))
                {
                    // Do not interfere with what would ordinarily happen if we didn't try to intercept because
                    // upstream components will likely be catching exceptions and / or the checking the return code

                    _logger.LogInformation("Microservice about to throw unhandled exception.  Process may be terminated.");
                    throw;
                }

            _logger.LogInformation("Microservice instance is shutting down.");
        }
Example #11
0
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]
            [RequestBodyType(typeof(GetNumberOfAddressesPerPostcodeInBoundaryRequest), "Get Number Of Addresses Per Postcode In Boundary")] GetNumberOfAddressesPerPostcodeInBoundaryRequest req,
            CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation("C# HTTP trigger function processed a request.");


                if (req.IsValid(out var validationResults))
                {
                    GetNumberOfAddressesPerPostcodeInBoundaryResponse response = await _mediator.Send(req, cancellationToken);

                    return(new OkObjectResult(ResponseWrapper <GetNumberOfAddressesPerPostcodeInBoundaryResponse, AddressServiceErrorCode> .CreateSuccessfulResponse(response)));
                }
                else
                {
                    return(new ObjectResult(ResponseWrapper <GetNumberOfAddressesPerPostcodeInBoundaryResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.ValidationError, validationResults))
                    {
                        StatusCode = 422
                    });;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"Unhandled error in {nameof(GetNumberOfAddressesPerPostcodeInBoundary)}", ex);
                return(new ObjectResult(ResponseWrapper <GetNumberOfAddressesPerPostcodeInBoundaryResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.UnhandledError, "Internal Error"))
                {
                    StatusCode = StatusCodes.Status500InternalServerError
                });
            }
        }
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage reqAsHttpRequestMessage,
            CancellationToken cancellationToken)
        {
            try
            {
                NewRelic.Api.Agent.NewRelic.SetTransactionName("AddressService", "GetPostcodeCoordinates");
                _logger.LogInformation("C# HTTP trigger function processed a request.");

                // accept compressed requests (can't do this with middleware)
                GetPostcodeCoordinatesRequest req = await HttpRequestMessageCompressionUtils.DeserialiseAsync <GetPostcodeCoordinatesRequest>(reqAsHttpRequestMessage);

                if (req.IsValid(out var validationResults))
                {
                    GetPostcodeCoordinatesResponse response = await _mediator.Send(req, cancellationToken);

                    return(new OkObjectResult(ResponseWrapper <GetPostcodeCoordinatesResponse, AddressServiceErrorCode> .CreateSuccessfulResponse(response)));
                }
                else
                {
                    return(new ObjectResult(ResponseWrapper <GetPostcodeCoordinatesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.ValidationError, validationResults))
                    {
                        StatusCode = 422
                    });
                }
            }
            catch (Exception ex)
            {
                _logger.LogErrorAndNotifyNewRelic($"Unhandled error in GetPostcodeCoordinates", ex);
                return(new ObjectResult(ResponseWrapper <GetPostcodeCoordinatesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.UnhandledError, "Internal Error"))
                {
                    StatusCode = StatusCodes.Status500InternalServerError
                });
            }
        }
Example #13
0
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            GetJobsByFilterRequest req,
            CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation("GetJobsByFilter started");
                GetJobsByFilterResponse response = await _mediator.Send(req, cancellationToken);

                return(new OkObjectResult(ResponseWrapper <GetJobsByFilterResponse, RequestServiceErrorCode> .CreateSuccessfulResponse(response)));
            }
            catch (PostCodeException exc)
            {
                _logger.LogErrorAndNotifyNewRelic($"{req.Postcode} is an invalid postcode", exc);
                return(new ObjectResult(ResponseWrapper <GetJobsByFilterResponse, RequestServiceErrorCode> .CreateUnsuccessfulResponse(RequestServiceErrorCode.ValidationError, "Invalid Postcode"))
                {
                    StatusCode = StatusCodes.Status400BadRequest
                });
            }
            catch (Exception exc)
            {
                _logger.LogErrorAndNotifyNewRelic("Exception occured in GetJobsByFilter", exc);
                return(new ObjectResult(ResponseWrapper <GetJobsByFilterResponse, RequestServiceErrorCode> .CreateUnsuccessfulResponse(RequestServiceErrorCode.InternalServerError, "Internal Error"))
                {
                    StatusCode = StatusCodes.Status500InternalServerError
                });
            }
        }
        public async Task RunAsync(string trendingEndpoint)
        {
            var trendingResponse = await _GiphyWrapper.GetTrendingGifsAsync(trendingEndpoint);

            var count = await _Context.InsertNewTrendingGifs(trendingResponse.Data);

            _Log.LogInformation($"Inserted {count} URL caches.");
        }
        public async Task <ChannelConfigContainer> DeleteBroadcasterConfigAsync(decimal channelId, string broadcaster)
        {
            if (string.IsNullOrEmpty(broadcaster))
            {
                _Log.LogInformation($"Deleting broadcaster config for channel '{channelId}'.");
                await _Context.DeleteBroadcasterConfigAsync(channelId);

                _Log.LogInformation($"Deleted broadcaster config for channel '{channelId}'.");
            }
            else
            {
                _Log.LogInformation($"Deleting broadcaster config for channel '{channelId}' broadcaster '{broadcaster}'.");
                await _Context.DeleteBroadcasterConfigAsync(channelId, broadcaster);

                _Log.LogInformation($"Deleted broadcaster config for channel '{channelId}' broadcaster '{broadcaster}'.");
            }
            return(await _Context.GetChannelConfigAsync(channelId));
        }
Example #16
0
        public async Task <List <PendingJobConfig> > GetContainers(int nowHour, List <int> currentValidMinutes)
        {
            _Log.LogInformation("Getting job configs.");
            var containers = await _Context.GetJobConfigsToRun(nowHour, currentValidMinutes);

            _Log.LogInformation($"Got {containers.Count} containers.");
            return(containers);
        }
Example #17
0
        public IActionResult Delete([FromRoute] int id, bool suspendOnly)
        {
            using (var _repository = _unitOfWork.GetRepository <EntityModel.ReferenceDataItem>())
            {
                var entity = _repository.GetFirstOrDefault(predicate: e => e.ID == id);
                if (entity is null)
                {
                    _logging.LogInformation($"Cannot delete item with Id '{id}' because it does not exist.");
                    return(NotFound(id));
                }


                _repository.Delete(id);
            }
            _unitOfWork.SaveChanges();
            _logging.LogInformation($"Item with Id '{id}' deleted.");

            return(NoContent());
        }
 public async Task <IActionResult> RunAsync(int guildCount, long botId, List <StatPost> statPosts)
 {
     _Log.LogInformation("Posting stats.");
     foreach (var statPost in statPosts)
     {
         try
         {
             var requestUri = string.Format(statPost.UrlStringFormat, botId);
             var content    = $"{{\"{statPost.GuildCountPropertyName}\":{guildCount}}}";
             await _StatWrapper.PostStatAsync(requestUri, content, statPost.Token);
         }
         catch (StatPostException ex)
         {
             _Log.LogError(ex, $"Error posting stats.");
         }
     }
     _Log.LogInformation("Posted stats.");
     return(new NoContentResult());
 }
        public async Task Run([TimerTrigger("%TimedCacheRefresherCronExpression%")] TimerInfo timerInfo, CancellationToken cancellationToken, ILogger log)
        {
            _logger.LogInformation($"TimedCacheRefresher CRON trigger executed at : {DateTimeOffset.Now}");

            Stopwatch stopwatch = Stopwatch.StartNew();

            try
            {
                await _memDistCache.RefreshDataAsync(async (token) => await _volunteersForCacheGetter.GetAllVolunteersAsync(token), CacheKey.AllCachedVolunteerDtos.ToString(), cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogError("Error running TimedCacheRefresher", ex);
                throw;
            }

            stopwatch.Stop();

            _logger.LogInformation($"TimedCacheRefresher CRON trigger took: {stopwatch.Elapsed:%m' min '%s' sec'}");
        }
Example #20
0
        public async Task <PostBroadcasterConfigResponse> PostBroadcasterConfigAsync(string endpoint, string clientId, string accept, decimal channelId, string broadcaster, BroadcasterConfigContainer container)
        {
            _Log.LogInformation($"Checking that broadcaster '{broadcaster}' exists.");
            var userResponse = await _TwitchWrapper.GetUsers(endpoint, clientId, accept, broadcaster);

            if (!userResponse.Users.Any())
            {
                var errorMessage = $"Could not find streamer '{broadcaster}'.";
                _Log.LogInformation(errorMessage);
                return(new PostBroadcasterConfigResponse(errorMessage));
            }
            var displayName = userResponse.Users[0].DisplayName;

            _Log.LogInformation($"Found broadcaster '{broadcaster}' with display name '{displayName}'.");
            _Log.LogInformation($"Posting broadcaster config for channel '{channelId}' broadcaster '{displayName}'.");
            var result = await _Context.SetBroadcasterConfigAsync(channelId, displayName, container);

            _Log.LogInformation($"Posted broadcaster config for channel '{channelId}' broadcaster '{displayName}'.");
            return(new PostBroadcasterConfigResponse(result));
        }
Example #21
0
        public async Task<List<TEntity>> GetAll(string path, string token = null)
        {
            List<TEntity> result;

            _loggerWrapper.LogInformation("path: " + path, this.GetType().Name, nameof(GetAll) + "()", null);

            try
            {
                result = await HttpClientWrapper.GetAllAsync(path, token);
            }
            catch (Exception exception)
            {
                _loggerWrapper.LogError("Failed to retrieve items", this.GetType().Name, nameof(GetAll) + "()", null);
                _loggerWrapper.LogError(exception.Message, this.GetType().Name, nameof(GetAll) + "()", null);
                _loggerWrapper.LogError(exception.InnerException != null ? exception.InnerException.Message : null, this.GetType().Name, nameof(GetAll) + "()", null);

                throw new Exception("Failed to retrieve items", exception);
            }

            return result;
        }
        public IActionResult Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation("C# HTTP trigger function processed health check request.");

                return(new OkObjectResult("I'm alive!"));
            }
            catch (Exception ex)
            {
                _logger.LogErrorAndNotifyNewRelic($"Unhandled error in HealthCheck", ex, req);
                return(new InternalServerErrorResult());
            }
        }
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]
            [RequestBodyType(typeof(GetNearbyPostcodesRequest), "get nearby postcodes")] GetNearbyPostcodesRequest req,
            CancellationToken cancellationToken)
        {
            try
            {
                NewRelic.Api.Agent.NewRelic.SetTransactionName("AddressService", "GetNearbyPostcodes");
                _logger.LogInformation("C# HTTP trigger function processed a request.");

                // This validation logic belongs in a custom validation attribute on the Postcode property.  However, validationContext.GetService<IExternalService> always returned null in the validation attribute (despite DI working fine elsewhere).  I didn't want to spend a lot of time finding out why when there is lots to do so I've put the postcode validation logic here for now.
                if (!await _postcodeValidator.IsPostcodeValidAsync(req.Postcode))
                {
                    return(new ObjectResult(ResponseWrapper <GetNearbyPostcodesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.InvalidPostcode, "Invalid postcode"))
                    {
                        StatusCode = 422
                    });
                }

                if (req.IsValid(out var validationResults))
                {
                    GetNearbyPostcodesResponse response = await _mediator.Send(req, cancellationToken);

                    return(new OkObjectResult(ResponseWrapper <GetNearbyPostcodesResponse, AddressServiceErrorCode> .CreateSuccessfulResponse(response)));
                }
                else
                {
                    return(new ObjectResult(ResponseWrapper <GetNearbyPostcodesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.ValidationError, validationResults))
                    {
                        StatusCode = 422
                    });
                }
            }
            catch (Exception ex)
            {
                _logger.LogErrorAndNotifyNewRelic($"Unhandled error in GetNearbyPostcodes", ex, req);
                return(new ObjectResult(ResponseWrapper <GetNearbyPostcodesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.UnhandledError, "Internal Error"))
                {
                    StatusCode = StatusCodes.Status500InternalServerError
                });
            }
        }
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]
            [RequestBodyType(typeof(GetJobsAllocatedToUserRequest), "get jobs allocated to user request")] GetJobsAllocatedToUserRequest req,
            CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation("GetJobsAllocatedToUser started");
                GetJobsAllocatedToUserResponse response = await _mediator.Send(req, cancellationToken);

                return(new OkObjectResult(ResponseWrapper <GetJobsAllocatedToUserResponse, RequestServiceErrorCode> .CreateSuccessfulResponse(response)));
            }
            catch (Exception exc)
            {
                _logger.LogErrorAndNotifyNewRelic("Exception occured in GetJobsAllocatedToUser", exc);
                return(new ObjectResult(ResponseWrapper <GetJobsAllocatedToUserResponse, RequestServiceErrorCode> .CreateUnsuccessfulResponse(RequestServiceErrorCode.InternalServerError, "Internal Error"))
                {
                    StatusCode = StatusCodes.Status500InternalServerError
                });
            }
        }
Example #25
0
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "put", Route = null)]
            [RequestBodyType(typeof(PutUpdateJobStatusToInProgressRequest), "put update job status to in progress request")] PutUpdateJobStatusToInProgressRequest req,
            CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation("PutUpdateJobStatusToInProgress started");
                PutUpdateJobStatusToInProgressResponse response = await _mediator.Send(req, cancellationToken);

                return(new OkObjectResult(ResponseWrapper <PutUpdateJobStatusToInProgressResponse, RequestServiceErrorCode> .CreateSuccessfulResponse(response)));
            }
            catch (Exception exc)
            {
                _logger.LogErrorAndNotifyNewRelic("Exception occured in PutUpdateJobStatusToInProgress", exc);
                return(new ObjectResult(ResponseWrapper <PutUpdateJobStatusToInProgressResponse, RequestServiceErrorCode> .CreateUnsuccessfulResponse(RequestServiceErrorCode.InternalServerError, "Internal Error"))
                {
                    StatusCode = StatusCodes.Status500InternalServerError
                });
            }
        }
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]
            [RequestBodyType(typeof(GetDistanceBetweenPostcodesRequest), "Get Distance Between Postcodes")] GetDistanceBetweenPostcodesRequest req,
            CancellationToken cancellationToken)
        {
            try
            {
                var input = JsonConvert.SerializeObject(req);
                _logger.LogInformation(input);
                GetDistanceBetweenPostcodesResponse response = await _mediator.Send(req, cancellationToken);

                return(new OkObjectResult(ResponseWrapper <GetDistanceBetweenPostcodesResponse, AddressServiceErrorCode> .CreateSuccessfulResponse(response)));
            }
            catch (Exception exc)
            {
                _logger.LogErrorAndNotifyNewRelic("Exception occured in GetDistanceBetweenPostcodes", exc);
                _logger.LogError(exc.ToString(), exc);
                return(new ObjectResult(ResponseWrapper <GetDistanceBetweenPostcodesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.UnhandledError, "Internal Error"))
                {
                    StatusCode = StatusCodes.Status500InternalServerError
                });
            }
        }
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]
            [RequestBodyType(typeof(GetPostcodesRequest), "Get Postcodes")] GetPostcodesRequest req,
            CancellationToken cancellationToken)
        {
            try
            {
                NewRelic.Api.Agent.NewRelic.SetTransactionName("AddressService", "GetPostcodes");
                _logger.LogInformation("C# HTTP trigger function processed a request.");

                GetPostcodesResponse response = await _mediator.Send(req, cancellationToken);

                return(new OkObjectResult(ResponseWrapper <GetPostcodesResponse, AddressServiceErrorCode> .CreateSuccessfulResponse(response)));
            }
            catch (Exception ex)
            {
                _logger.LogErrorAndNotifyNewRelic($"Unhandled error in GetPostcodes", ex, req);
                return(new ObjectResult(ResponseWrapper <GetPostcodesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.UnhandledError, "Internal Error"))
                {
                    StatusCode = StatusCodes.Status500InternalServerError
                });
            }
        }
 public void Run([TimerTrigger("%TimedHealthCheckCronExpression%")] TimerInfo timerInfo)
 {
     _logger.LogInformation($"Health check CRON trigger executed at : {DateTimeOffset.Now}");
 }
Example #29
0
        public async Task <List <TEntity> > GetAllAsync(string urlExtension, string token = null)
        {
            _loggerWrapper.LogInformation(nameof(urlExtension) + ": " + urlExtension + " | " + nameof(token) + ": " + token, this.GetType().Name, nameof(GetAllAsync) + "()", null);

            return(await CheckExceptions(async() =>
                                         (await _httwrap.GetAsync(urlExtension, null, token != null ? GetCustomHeaders(token) : null))
                                         .ReadAs <List <TEntity> >()));
        }
Example #30
0
        public void ConfigureServices(IServiceCollection services)
        {
            var env = services.BuildServiceProvider()
                      .GetRequiredService <IHostingEnvironment>();

            Logger.LogInformation("Registering second-line services in Startup.ConfigureServices");
            services.AddSingleton <IServiceCollection>(services);

            /*: configuration section "logging" : */
            services.AddLogging(builder =>
            {
                builder.AddConsole()
                .AddDebug();
            });

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearerConfiguration(Configuration);
            services.AddAuthorizationConfiguration(Configuration);

            /*: configuration section "responseCaching" : */
            if (ShouldUseCaching(Configuration, out var redisCacheOptions))
            {
                services.AddDistributedRedisCache(options =>
                {
                    options.Configuration = redisCacheOptions.Configuration;
                    options.InstanceName  = redisCacheOptions.InstanceName;
                });

                services.AddDistributedResponseCaching();
                services.AddTransient <IDistributedCacheManager, RedisDistributedCacheManager>();
            }

            // Database...
            var connectionStrings = new ConnectionStrings();

            Configuration.Bind("ConnectionStrings", connectionStrings);
            //if(env.IsDevelopment())
            //    services.AddDbContext<ReferenceDataDbContext>(options => { options.UseSqlite("Data Source=mydb.db"); });
            //else
            services.AddDbContext <ReferenceDataDbContext>(options => { options.UseSqlServer(connectionStrings.CoreReadDatabase); });
            services.AddUnitOfWork <ReferenceDataDbContext>();


            services.AddApiVersioning(options =>
            {
                options.ReportApiVersions = true;
            });

            services.AddVersionedApiExplorer(options =>
            {
                options.DefaultApiVersion = new ApiVersion(1, 0);
                options.AssumeDefaultVersionWhenUnspecified = true;
                options.GroupNameFormat           = "'v'VVV";
                options.SubstituteApiVersionInUrl = true;
            });

            services.AddOData( )
            .EnableApiVersioning(options =>
            {
            });
            services.AddODataApiExplorer(options =>
            {
                options.GroupNameFormat           = "'v'VVV";
                options.SubstituteApiVersionInUrl = true;
            });

            services.AddTransient <IConfigureOptions <SwaggerGenOptions>, ConfigureSwaggerOptions>();
            services.AddSwaggerGen(options =>
            {
                // add a custom operation filter which sets default values
                options.OperationFilter <SwaggerDefaultValues>();

                // tell swagger that we are using a JWT token
                // see: https://swagger.io/docs/specification/authentication/
                options.AddSecurityDefinition("Bearer", new ApiKeyScheme
                {
                    In          = "header", Type = "apiKey",
                    Name        = "Authorization",
                    Description = "JWT Authorization header using the Bearer scheme.",
                });

                // integrate xml comments
                // options.IncludeXmlComments(XmlCommentsFilePath);
            });
            services.AddPlatformComponents(options =>
            {
                options.AutoGenerateEmptyCorrelationId = false;
            });

            // Metrics
            services.AddMetricFromConfiguration(Configuration);
            services.AddHealthFromConfiguration(Configuration, builder =>
            {
                if (redisCacheOptions != null)
                {
                    //builder.HealthChecks
                    //   .AddRedisCheck(
                    //    "Redis connection check",
                    //    () => ConnectionMultiplexer.Connect(redisCacheOptions.Configuration),
                    //    TimeSpan.FromSeconds(90),
                    //    true);
                }

                if (!string.IsNullOrEmpty(connectionStrings.CoreReadDatabase))
                {
                    //builder.HealthChecks
                    //    .AddSqlCheck(
                    //        "Sql Database Check",
                    //        connectionStrings.CoreReadDatabase,
                    //        TimeSpan.FromSeconds(90),
                    //        true
                    //    );
                }
            });


            services.AddMvc(options =>
            {
                //options.Filters.Add(
                //    new ResponseCacheAttribute
                //    {
                //        Duration = 3600,
                //        Location = ResponseCacheLocation.Any,
                //        VaryByQueryKeys = new[] {"*"}
                //    });
            })
            .SetCompatibilityVersion(
                CompatibilityVersion.Version_2_1
                );

            AddCors(services);

            Logger.LogInformation("Startup.ConfigureServices completed");
        }