in src/Service/Startup.cs [89:321]
public void ConfigureServices(IServiceCollection services)
{
Startup.AddValidFilters();
services.AddSingleton(_hotReloadEventHandler);
string configFileName = Configuration.GetValue<string>("ConfigFileName") ?? FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME;
string? connectionString = Configuration.GetValue<string?>(
FileSystemRuntimeConfigLoader.RUNTIME_ENV_CONNECTION_STRING.Replace(FileSystemRuntimeConfigLoader.ENVIRONMENT_PREFIX, ""),
null);
IFileSystem fileSystem = new FileSystem();
FileSystemRuntimeConfigLoader configLoader = new(fileSystem, _hotReloadEventHandler, configFileName, connectionString);
RuntimeConfigProvider configProvider = new(configLoader);
_configProvider = configProvider;
services.AddSingleton(fileSystem);
services.AddSingleton(configLoader);
services.AddSingleton(configProvider);
bool runtimeConfigAvailable = configProvider.TryGetConfig(out RuntimeConfig? runtimeConfig);
if (runtimeConfigAvailable
&& runtimeConfig?.Runtime?.Telemetry?.ApplicationInsights is not null
&& runtimeConfig.Runtime.Telemetry.ApplicationInsights.Enabled)
{
// Add ApplicationTelemetry service and register
// custom ITelemetryInitializer implementation with the dependency injection
services.AddApplicationInsightsTelemetry();
services.AddSingleton<ITelemetryInitializer, AppInsightsTelemetryInitializer>();
}
if (runtimeConfigAvailable
&& runtimeConfig?.Runtime?.Telemetry?.OpenTelemetry is not null
&& runtimeConfig.Runtime.Telemetry.OpenTelemetry.Enabled)
{
services.Configure<OpenTelemetryLoggerOptions>(options =>
{
options.IncludeScopes = true;
options.ParseStateValues = true;
options.IncludeFormattedMessage = true;
});
services.AddOpenTelemetry()
.WithLogging(logging =>
{
logging.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(runtimeConfig.Runtime.Telemetry.OpenTelemetry.ServiceName!))
.AddOtlpExporter(configure =>
{
configure.Endpoint = new Uri(runtimeConfig.Runtime.Telemetry.OpenTelemetry.Endpoint!);
configure.Headers = runtimeConfig.Runtime.Telemetry.OpenTelemetry.Headers;
configure.Protocol = OtlpExportProtocol.Grpc;
});
})
.WithMetrics(metrics =>
{
metrics.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(runtimeConfig.Runtime.Telemetry.OpenTelemetry.ServiceName!))
.AddOtlpExporter(configure =>
{
configure.Endpoint = new Uri(runtimeConfig.Runtime.Telemetry.OpenTelemetry.Endpoint!);
configure.Headers = runtimeConfig.Runtime.Telemetry.OpenTelemetry.Headers;
configure.Protocol = OtlpExportProtocol.Grpc;
})
.AddMeter(TelemetryMetricsHelper.MeterName);
})
.WithTracing(tracing =>
{
tracing.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(runtimeConfig.Runtime.Telemetry.OpenTelemetry.ServiceName!))
.AddHttpClientInstrumentation()
.AddOtlpExporter(configure =>
{
configure.Endpoint = new Uri(runtimeConfig.Runtime.Telemetry.OpenTelemetry.Endpoint!);
configure.Headers = runtimeConfig.Runtime.Telemetry.OpenTelemetry.Headers;
configure.Protocol = OtlpExportProtocol.Grpc;
})
.AddSource(TelemetryTracesHelper.DABActivitySource.Name);
});
}
services.AddSingleton(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelInit = new(MinimumLogLevel, typeof(RuntimeConfigValidator).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelInit);
return loggerFactory.CreateLogger<RuntimeConfigValidator>();
});
services.AddSingleton<RuntimeConfigValidator>();
services.AddSingleton<CosmosClientProvider>();
services.AddHealthChecks()
.AddCheck<BasicHealthCheck>(nameof(BasicHealthCheck));
services.AddSingleton<ILogger<SqlQueryEngine>>(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelInit = new(MinimumLogLevel, typeof(SqlQueryEngine).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelInit);
return loggerFactory.CreateLogger<SqlQueryEngine>();
});
services.AddSingleton<ILogger<IQueryExecutor>>(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelInit = new(MinimumLogLevel, typeof(IQueryExecutor).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelInit);
return loggerFactory.CreateLogger<IQueryExecutor>();
});
services.AddSingleton<ILogger<ISqlMetadataProvider>>(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelInit = new(MinimumLogLevel, typeof(ISqlMetadataProvider).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelInit);
return loggerFactory.CreateLogger<ISqlMetadataProvider>();
});
// Below are the factory registrations that will enable multiple databases scenario.
// within these factories the various instances will be created based on the database type and datasourceName.
services.AddSingleton<IAbstractQueryManagerFactory, QueryManagerFactory>();
services.AddSingleton<IQueryEngineFactory, QueryEngineFactory>();
services.AddSingleton<IMutationEngineFactory, MutationEngineFactory>();
services.AddSingleton<IMetadataProviderFactory, MetadataProviderFactory>();
services.AddSingleton<GraphQLSchemaCreator>();
services.AddSingleton<GQLFilterParser>();
services.AddSingleton<RequestValidator>();
services.AddSingleton<RestService>();
services.AddSingleton<HealthCheckHelper>();
services.AddSingleton<HttpUtilities>();
services.AddSingleton<BasicHealthReportResponseWriter>();
services.AddSingleton<ComprehensiveHealthReportResponseWriter>();
// ILogger explicit creation required for logger to use --LogLevel startup argument specified.
services.AddSingleton<ILogger<BasicHealthReportResponseWriter>>(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelInit = new(MinimumLogLevel, typeof(BasicHealthReportResponseWriter).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelInit);
return loggerFactory.CreateLogger<BasicHealthReportResponseWriter>();
});
// ILogger explicit creation required for logger to use --LogLevel startup argument specified.
services.AddSingleton<ILogger<ComprehensiveHealthReportResponseWriter>>(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelInit = new(MinimumLogLevel, typeof(ComprehensiveHealthReportResponseWriter).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelInit);
return loggerFactory.CreateLogger<ComprehensiveHealthReportResponseWriter>();
});
// ILogger explicit creation required for logger to use --LogLevel startup argument specified.
services.AddSingleton<ILogger<HealthCheckHelper>>(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelInit = new(MinimumLogLevel, typeof(HealthCheckHelper).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelInit);
return loggerFactory.CreateLogger<HealthCheckHelper>();
});
// ILogger explicit creation required for logger to use --LogLevel startup argument specified.
services.AddSingleton<ILogger<HttpUtilities>>(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelInit = new(MinimumLogLevel, typeof(HttpUtilities).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelInit);
return loggerFactory.CreateLogger<HttpUtilities>();
});
services.AddSingleton<ILogger<RestController>>(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelInit = new(MinimumLogLevel, typeof(RestController).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelInit);
return loggerFactory.CreateLogger<RestController>();
});
services.AddSingleton<ILogger<ClientRoleHeaderAuthenticationMiddleware>>(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelRuntime = new(MinimumLogLevel, typeof(ClientRoleHeaderAuthenticationMiddleware).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelRuntime);
return loggerFactory.CreateLogger<ClientRoleHeaderAuthenticationMiddleware>();
});
services.AddSingleton<ILogger<ConfigurationController>>(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelInit = new(MinimumLogLevel, typeof(ConfigurationController).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelInit);
return loggerFactory.CreateLogger<ConfigurationController>();
});
//Enable accessing HttpContext in RestService to get ClaimsPrincipal.
services.AddHttpContextAccessor();
if (runtimeConfig is not null && runtimeConfig.Runtime?.Host?.Mode is HostMode.Development)
{
// Development mode implies support for "Hot Reload". The V2 authentication function
// wires up all DAB supported authentication providers (schemes) so that at request time,
// the runtime config defined authentication provider is used to authenticate requests.
ConfigureAuthenticationV2(services, configProvider);
}
else
{
ConfigureAuthentication(services, configProvider);
}
services.AddAuthorization();
services.AddSingleton<ILogger<IAuthorizationHandler>>(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelInit = new(MinimumLogLevel, typeof(IAuthorizationHandler).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelInit);
return loggerFactory.CreateLogger<IAuthorizationHandler>();
});
services.AddSingleton<ILogger<IAuthorizationResolver>>(implementationFactory: (serviceProvider) =>
{
LogLevelInitializer logLevelInit = new(MinimumLogLevel, typeof(IAuthorizationResolver).FullName, _configProvider, _hotReloadEventHandler);
ILoggerFactory? loggerFactory = CreateLoggerFactoryForHostedAndNonHostedScenario(serviceProvider, logLevelInit);
return loggerFactory.CreateLogger<IAuthorizationResolver>();
});
services.AddSingleton<IAuthorizationHandler, RestAuthorizationHandler>();
services.AddSingleton<IAuthorizationResolver, AuthorizationResolver>();
services.AddSingleton<IOpenApiDocumentor, OpenApiDocumentor>();
AddGraphQLService(services, runtimeConfig?.Runtime?.GraphQL);
// Subscribe the GraphQL schema refresh method to the specific hot-reload event
_hotReloadEventHandler.Subscribe(DabConfigEvents.GRAPHQL_SCHEMA_REFRESH_ON_CONFIG_CHANGED, (sender, args) => RefreshGraphQLSchema(services));
services.AddFusionCache()
.WithOptions(options =>
{
options.FactoryErrorsLogLevel = LogLevel.Debug;
options.EventHandlingErrorsLogLevel = LogLevel.Debug;
})
.WithDefaultEntryOptions(new FusionCacheEntryOptions
{
Duration = TimeSpan.FromSeconds(5)
});
services.AddSingleton<DabCacheService>();
services.AddControllers();
}