SaveApis.Framework

Documentation for SaveApis.Framework

View on GitHub

Console Framework

SaveApis.Framework.Console provides a ready-to-use .NET Generic Host application for long-running background services and hosted workers — with structured logging, OpenTelemetry, and FluentValidation wired up via the Installer system.


Table of Contents


Overview

When to use: Use the Console Framework for background services, scheduled jobs, workers, or any process that runs continuously without an HTTP endpoint.

What it provides out of the box:

Key difference from the Web Framework: Built on Host.CreateApplicationBuilder (Generic Host) instead of WebApplicationBuilder. There is no HTTP pipeline — ConfigureApplication is used for host-level setup only.


Entry Point

Start the application from Program.cs:

using SaveApis.Framework;
using SaveApis.Framework.Console.Extensions;

await SaveApisApplication
    .AsConsole(
        args,
        (app, installer) =>
        {
            app.Name = "My.Worker";
            app.Namespace = "My.Org";

            installer.SetSoftwareAssembly(); // required for validator scanning
        }
    )
    .Build()
    .RunAsync()
    .ConfigureAwait(false);

Add your own installers before Build():

await SaveApisApplication
    .AsConsole(args, (app, installer) => { ... })
    .AddInstaller<MyWorkerInstaller>()
    .Build()
    .RunAsync();

Default Installers

The following installers are registered automatically when you call AsConsole():

# Installer Key Default Enabled
1 LoggingInstaller Logging
2 OpenTelemetryInstaller OpenTelemetry
3 ValidationInstaller Validation

LoggingInstaller

Key: Logging

Clears all default logging providers and installs Serilog with a formatted ANSI console sink.

Default minimum level: Information

Built-in overrides (always applied):

Configuration (section Logging):

Key Type Default Description
Logging:Default LogEventLevel Information Global minimum log level
Logging:Override:<source> LogEventLevel Per-source override

Example (appsettings.json):

{
  "Logging": {
    "Default": "Debug",
    "Override": {
      "MyNamespace.MyService": "Warning"
    }
  }
}

OpenTelemetryInstaller

Key: OpenTelemetry

Registers OpenTelemetry SDK with logging, metrics, and tracing exported via OTLP. The resource is configured with SaveApisApplication.Name, SaveApisApplication.Namespace, and Environment.MachineName.

Instrumentation included:

Note: ASP.NET Core instrumentation is not included (use the Web Framework for that).

Configuration (section OpenTelemetry):

Key Type Default Description
OpenTelemetry:Endpoint Uri (required) OTLP exporter endpoint
OpenTelemetry:Protocol OtlpExportProtocol Grpc Grpc or HttpProtobuf
OpenTelemetry:Logging:Enabled bool true Enable log export
OpenTelemetry:Metrics:Enabled bool true Enable metrics export
OpenTelemetry:Tracing:Enabled bool true Enable trace export

ValidationInstaller

Key: Validation

Scans SoftwareAssembly and all additional assemblies from InstallerContext.Assemblies for FluentValidation IValidator<T> implementations and registers them.

No configuration required.


Custom Installers

Inherit from BaseConsoleInstaller to create your own installer:

public class MyWorkerInstaller : BaseConsoleInstaller
{
    public override string InstallerKey => "MyWorker";

    public override IReadOnlyCollection<InstallerDependency> Dependencies =>
    [
        InstallerDependency.After<ValidationInstaller>(),
    ];

    public override void ConfigureBuilder(
        SaveApisConsoleApplicationBuilder builder,
        ConsoleInstallerContext context)
    {
        builder.Services.AddHostedService<MyWorker>();
        builder.Services.AddScoped<IMyRepository, MyRepository>();
    }
}

Register it in Program.cs:

await SaveApisApplication
    .AsConsole(args, (app, installer) => { ... })
    .AddInstaller<MyWorkerInstaller>()
    .Build()
    .RunAsync();

From the example project — two installers with a dependency between them:

// ServiceInstaller.cs
public class ServiceInstaller : BaseConsoleInstaller
{
    public override string InstallerKey => "Service";

    public override IReadOnlyCollection<InstallerDependency> Dependencies =>
        [InstallerDependency.Before<HttpClientInstaller>()];

    public override void ConfigureBuilder(
        SaveApisConsoleApplicationBuilder builder,
        ConsoleInstallerContext context)
    {
        builder.Services.AddHostedService<HostedService>();
    }
}

// HttpClientInstaller.cs
public class HttpClientInstaller : BaseConsoleInstaller
{
    public override string InstallerKey => "HttpClient";

    public override IReadOnlyCollection<InstallerDependency> Dependencies =>
        [InstallerDependency.After<ServiceInstaller>(DependencyRequirement.Optional)];

    public override void ConfigureBuilder(
        SaveApisConsoleApplicationBuilder builder,
        ConsoleInstallerContext context)
    {
        builder.Services
            .AddHttpClient<IGoogleClient, GoogleClient>()
            .ConfigureHttpClient(client =>
                client.BaseAddress = new Uri("https://www.google.com"));
    }
}

For the full installer API (lifecycle, dependencies, ShouldInstall, etc.) see the Base Framework documentation.


Enabling & Disabling Installers

Use the ConsoleInstallerContext extension methods in the configure callback:

(app, installer) =>
{
    installer.WithLogging(false);        // disable Serilog
    installer.WithOpenTelemetry(false);  // disable OpenTelemetry
    installer.WithValidation(false);     // disable FluentValidation
}

All methods default to true (enable) and accept false to disable.


Configuration Reference

Section Key Type Default Required
Logging Default LogEventLevel Information No
Logging Override:<source> LogEventLevel No
OpenTelemetry Endpoint Uri Yes (if enabled)
OpenTelemetry Protocol OtlpExportProtocol Grpc No
OpenTelemetry Logging:Enabled bool true No
OpenTelemetry Metrics:Enabled bool true No
OpenTelemetry Tracing:Enabled bool true No

Installer Sub-Pages

Installer Sub-Page
LoggingInstaller logging/
OpenTelemetryInstaller opentelemetry/
ValidationInstaller validation/