WebHost
Dosaic.Hosting.WebHost is the core orchestration package for any Dosaic-based service. It wires together plugin discovery, dependency injection, middleware pipeline configuration, health checks, OpenTelemetry, structured logging, CORS, response compression, IP rate limiting, and endpoint routing — all driven by the plugin interfaces from Dosaic.Hosting.Abstractions.
This package is mandatory. Without it no plugins can be loaded or configured.
Installation
Or as package references in your .csproj:
Usage
Replace the content of Program.cs with:
DosaicPluginTypes.All is a Type[] emitted at compile time by Dosaic.Hosting.Generator — no runtime reflection scanning is required.
For advanced scenarios (e.g. integration testing) you can separate build from run:
Features
AOT-compatible plugin discovery
Plugin types resolved from source-generated Type[] — no reflection at runtime
Structured logging
Serilog with span/thread enrichers, structured request logging
OpenTelemetry
Metrics, tracing (OTLP), and logging exporters; Prometheus scraping endpoint at /metrics
Health checks
Built-in liveness checks (API, disk, memory); plugin and attribute-driven registrations
CORS
Configurable policy via CorsPolicy config section
Response compression
Brotli + Gzip (fastest level), applied to HTTP and HTTPS
IP rate limiting
AspNetCoreRateLimit integration, configurable via ipRateLimiting section
Layered configuration
JSON, YAML, secrets files, env vars, CLI args — ordered by specificity
YAML input/output formatters
Controllers accept and return application/yaml in addition to JSON
Forwarded headers
All forwarded headers trusted (proxy-friendly)
Configurable Kestrel
Listening URLs and max request body size controlled via config
Plugin Lifecycle
PluginWebHostBuilder.Build() executes the following phases in order:
1 — Host Configuration (HostConfigurator)
HostConfigurator)Clears default configuration sources and rebuilds them in the defined loading order (see Configuration below)
Configures Kestrel: listening URLs (
host:urls), max request body size (host:maxRequestSize), server header suppressionBootstraps Serilog structured logging
2 — Service Configuration (ServiceConfigurator)
ServiceConfigurator)Registers default services: JSON serialization, memory cache, datetime providers, forwarded headers
Configures CORS, response compression, IP rate limiting
Adds MVC controllers with YAML formatters and custom validation error responses
Discovers and registers
[Configuration(...)]-attributed classes fromIConfigurationRegisters health checks: built-in liveness checks +
[HealthCheck]-attributed types + plugin-contributed checksConfigures OpenTelemetry metrics, tracing, and logging
Calls
IPluginServiceConfiguration.ConfigureServices()on all discovered plugins (sorted by origin)
3 — App Build
WebApplicationBuilder.Build() finalises the DI container.
4 — Application Configuration (AppConfigurator)
AppConfigurator)Enables forwarded headers, response compression, IP rate limiting, CORS, Prometheus endpoint, routing
Registers
[Middleware]-attributed types ordered by theirOrderpropertyCalls
IPluginApplicationConfiguration.ConfigureApplication()on all discovered pluginsMaps health endpoints (
/health/liveness,/health/readiness)Maps controllers
Calls
IPluginEndpointsConfiguration.ConfigureEndpoints()on all discovered plugins
5 — Instance Cleanup
TypeImplementationResolver.ClearInstances() disposes all plugin constructor instances created during build.
Plugin Sort Order
Dosaic.* namespace
sbyte.MinValue
First
Third-party plugins
0
Middle
Host assembly plugins
sbyte.MaxValue
Last
Configuration
Kestrel / Host
Environment variables (single _ maps to : hierarchy):
Configuration File Loading Order
Dosaic loads configuration in the following order (later sources override earlier ones):
appsettings.jsonappsettings.yaml/appsettings.ymlappsettings.*.jsonappsettings.*.yaml/appsettings.*.ymlappsettings.secrets.json/appsettings.secrets.yaml/appsettings.secrets.ymlappsettings.*.secrets.json/appsettings.*.secrets.yaml/appsettings.*.secrets.ymlEnvironment variables
Command-line arguments
Files are sorted by node count (number of .-separated segments) within each group. Secrets files always load after non-secrets files. Files whose names do not start with appsettings are ignored.
Additional Config Paths
You can load configuration files from additional directories. Those files are loaded before the main application directory.
Via environment variable:
Via command-line argument:
Subfolders are scanned recursively for
appsettings.*filesSupports
.json,.yaml,.ymlformatsNon-existent paths raise a
DirectoryNotFoundException
Environment Variable Mapping
Dosaic uses a custom provider that maps environment variable names to configuration keys by replacing _ with : (hierarchy separator). Double underscore __ is first collapsed to single _ before the mapping.
Logging (Serilog)
Environment variables:
CORS
If any of origins, methods, headers, or exposedHeaders are not specified, they default to ["*"].
IP Rate Limiting
Refer to AspNetCoreRateLimit documentation for the full schema.
OpenTelemetry
When telemetry:endpoint is configured, traces, metrics, and logs are exported via OTLP. Log messages are enriched with SpanId and TraceId. Use telemetry:name to explicitly set the service name used by OpenTelemetry resources for traces, metrics, and logs.
Without telemetry:endpoint, only the Prometheus scraping endpoint (/metrics) is active.
Metrics instrumentation (always active):
ASP.NET Core request metrics
HTTP client metrics
.NET runtime metrics
Process metrics
All custom
ActivitySourcemeters (*)
Tracing instrumentation (requires telemetry:endpoint):
ASP.NET Core (Swagger paths excluded)
HTTP client
All custom
ActivitySourcesources (*)B3 propagation (single and multi-header)
Health Endpoints
GET /health/liveness
liveness
GET /health/readiness
readiness
Both endpoints return a JSON body:
Built-in liveness checks registered automatically:
api
Always healthy — confirms the process is running
disk_space
Checks free space on all drives
memory
Asserts allocated memory is below 2 GB
Plugins can contribute additional checks via IPluginHealthChecksConfiguration.ConfigureHealthChecks(). Custom checks can also be auto-discovered by implementing IHealthCheck and annotating the class with [HealthCheck("name", ...tags)].
Last updated