Domium.Observability.OpenTelemetry 0.1.2

There is a newer version of this package available.
See the version list below for details.
dotnet add package Domium.Observability.OpenTelemetry --version 0.1.2
                    
NuGet\Install-Package Domium.Observability.OpenTelemetry -Version 0.1.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Domium.Observability.OpenTelemetry" Version="0.1.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Domium.Observability.OpenTelemetry" Version="0.1.2" />
                    
Directory.Packages.props
<PackageReference Include="Domium.Observability.OpenTelemetry" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Domium.Observability.OpenTelemetry --version 0.1.2
                    
#r "nuget: Domium.Observability.OpenTelemetry, 0.1.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Domium.Observability.OpenTelemetry@0.1.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Domium.Observability.OpenTelemetry&version=0.1.2
                    
Install as a Cake Addin
#tool nuget:?package=Domium.Observability.OpenTelemetry&version=0.1.2
                    
Install as a Cake Tool

Domium

Domium is a lightweight DDD and CQRS foundation for modern .NET applications. It gives you focused building blocks for aggregate modeling, command and query pipelines, provider-selectable persistence, tenant-aware caching, eventing, and observability without forcing one infrastructure style on every application.

Why Domium

  • Model domain objects with aggregate roots, strongly typed IDs, value objects, audit metadata, soft delete support, and domain events.
  • Use a small CQRS application layer with command/query buses, validation, logging, transactions, and query caching behaviors.
  • Choose persistence per application: EF Core, Dapper, or both.
  • Keep read models independent from aggregate repositories.
  • Add provider packages only when needed: Redis, MassTransit, OpenTelemetry, EF Core, Dapper.
  • Publish and version each package independently through NuGet.

Package Map

Package Purpose
Domium.Domain.Abstractions Domain contracts for entities, aggregate roots, IDs, value objects, and domain events.
Domium.Domain Concrete domain primitives such as AggregateRoot<TId>, EntityBase<TId>, AggregateId<T>, and DomainEvent.
Domium.Application.Abstractions Command/query buses, handlers, validators, and pipeline contracts.
Domium.Application Command/query buses, pipeline behaviors, and domain event dispatching.
Domium.Persistence.Abstractions Provider-neutral aggregate repository and unit-of-work contracts.
Domium.Persistence.EntityFrameworkCore EF Core aggregate repository, DbContext base, unit of work, and EF-specific specifications.
Domium.Persistence.Dapper Dapper session, SQL executor, unit of work, and optional mapped aggregate repository.
Domium.Caching.Abstractions Cache store, policy, key, scope, and invalidation abstractions.
Domium.Caching Default cache policy, key, scope, and invalidation providers.
Domium.Caching.Memory In-memory cache store provider.
Domium.Caching.Redis Redis cache store provider.
Domium.Eventing.Abstractions Internal and external event contracts.
Domium.Eventing In-process internal event publishing and default no-op external publisher.
Domium.Eventing.MassTransit MassTransit external event publishing and consumer adapter.
Domium.Tenancy.Abstractions Tenant context contracts.
Domium.Tenancy AsyncLocal tenant context and disposable tenant scopes.
Domium.Observability ActivitySource, Meter, counters, and histograms.
Domium.Observability.OpenTelemetry OpenTelemetry tracing and metrics registration.
Domium.Extensions.DependencyInjection Main AddDomium composition entry point.

Installation

Install the packages you need. A typical application starts with:

dotnet add package Domium.Domain
dotnet add package Domium.Application
dotnet add package Domium.Extensions.DependencyInjection

Then add persistence and provider packages as needed:

dotnet add package Domium.Persistence.EntityFrameworkCore
dotnet add package Domium.Persistence.Dapper
dotnet add package Domium.Caching.Redis
dotnet add package Domium.Eventing.MassTransit
dotnet add package Domium.Observability.OpenTelemetry

Quick Start

Register Domium with the fluent API:

services.AddDomium(options =>
{
    options
        .UseValidation()
        .UseLogging()
        .UseTransactions()
        .UseCaching(cache =>
        {
            cache.Provider = DomiumCacheProvider.Memory;
            cache.DefaultExpiration = TimeSpan.FromMinutes(5);
        });
});

When handlers live outside the assembly that calls AddDomium, register those assemblies explicitly:

services.AddDomium(options =>
{
    options.AddApplicationAssembly(typeof(CreateOrderHandler).Assembly);
});

Domain Model

public sealed class OrderId(Guid value) : AggregateId<Guid>(value);

public sealed class Order : AggregateRoot<OrderId>
{
    private Order() : base(new OrderId(Guid.Empty))
    {
        Number = string.Empty;
    }

    public Order(OrderId id, string number) : base(id)
    {
        Number = number;
        RaiseDomainEvent(new OrderCreatedDomainEvent(id));
    }

    public string Number { get; private set; }
}

public sealed class OrderCreatedDomainEvent(OrderId orderId) : DomainEvent
{
    public OrderId OrderId { get; } = orderId;
}

Commands And Queries

Commands change the domain model:

public sealed record CreateOrderCommand(string Number) : ICommand;

public sealed class CreateOrderHandler(IRepository<Order, OrderId> repository)
    : ICommandHandler<CreateOrderCommand>
{
    public Task HandleAsync(
        CreateOrderCommand command,
        CancellationToken cancellationToken = default)
    {
        var order = new Order(new OrderId(Guid.NewGuid()), command.Number);
        return repository.AddAsync(order, cancellationToken);
    }
}

Queries return read models or DTOs:

public sealed record GetOrderQuery(Guid Id) : IQuery<OrderReadModel>;

public sealed record OrderReadModel(Guid Id, string Number);

Persistence

Domium keeps the core repository intentionally small:

IRepository<TAggregate, TId>

This repository is for aggregate load/save behavior. Provider-specific querying belongs to the provider package or to query handlers.

EF Core

services.AddDomiumEntityFrameworkCore<AppDbContext>(options =>
{
    options.UseSqlServer(connectionString);
});

services.AddDomium(options => options.UseTransactions());

Use the core repository for aggregate persistence:

var order = await repository.GetByIdAsync(orderId, cancellationToken);
await repository.UpdateAsync(order, cancellationToken);

EF-specific specifications are available through IEfRepository<TAggregate, TId>:

var orders = await efRepository.FindAsync(
    new ActiveOrdersSpecification(),
    cancellationToken);

Dapper

Dapper can be used for explicit SQL in query handlers:

var orders = await sql.QueryAsync<OrderReadModel>(
    "select Id, Number from Orders where TenantId = @TenantId",
    new { TenantId = tenantId },
    cancellationToken);

Register Dapper infrastructure:

services.AddDomiumDapper(options =>
{
    options.UseConnectionFactory<SqlConnectionFactory>();
});

If the application wants Dapper as the aggregate repository provider, opt in and supply explicit aggregate mapping:

services.AddScoped<IDapperAggregateMapper<Order, OrderId>, OrderMapper>();

services.AddDomiumDapper(options =>
{
    options
        .UseConnectionFactory<SqlConnectionFactory>()
        .UseAggregateRepositories();
});

The mapper owns SQL and materialization:

public sealed class OrderMapper : IDapperAggregateMapper<Order, OrderId>
{
    public string SelectByIdSql => "select Id, Number from Orders where Id = @Id";
    public string InsertSql => "insert into Orders (Id, Number) values (@Id, @Number)";
    public string UpdateSql => "update Orders set Number = @Number where Id = @Id";
    public string DeleteSql => "delete from Orders where Id = @Id";

    public object GetIdParameters(OrderId id) => new { Id = id.Value };
    public object GetInsertParameters(Order order) => new { Id = order.Id.Value, order.Number };
    public object GetUpdateParameters(Order order) => new { Id = order.Id.Value, order.Number };
    public object GetDeleteParameters(Order order) => new { Id = order.Id.Value };

    public Order Map(object row)
    {
        // Map from the provider row shape into the aggregate.
        throw new NotImplementedException();
    }
}

Query Caching

Use in-memory caching:

services.AddDomium(options =>
{
    options.UseCaching(cache =>
    {
        cache.Provider = DomiumCacheProvider.Memory;
        cache.DefaultExpiration = TimeSpan.FromMinutes(5);
    });
});

Use Redis caching:

services.AddDomiumRedisCacheStore("localhost");

services.AddDomium(options =>
{
    options.UseCaching(cache =>
    {
        cache.Provider = DomiumCacheProvider.Redis;
        cache.DefaultExpiration = TimeSpan.FromMinutes(5);
    });
});

Register query cache policies through IDomiumQueryCachePolicyRegistry.

Tenancy

Tenant scope is ambient and async-flow aware:

using var scope = tenantScopeFactory.BeginScope("tenant-42");

Tenant-scoped cache policies fail clearly when no tenant context exists.

Eventing

Internal events are in-process. External events are transport-provider specific.

services.AddDomiumMassTransitEventing();

services.AddMassTransit(configurator =>
{
    configurator.AddDomiumExternalEventConsumer<OrderSubmitted>();
    configurator.UsingRabbitMq((context, cfg) => cfg.ConfigureEndpoints(context));
});

Observability

services.AddDomiumOpenTelemetry(options =>
{
    options.ServiceName = "Orders.Api";
    options.Environment = "Production";
    options.Otlp.Enabled = true;
    options.Otlp.Endpoint = "http://localhost:4317";
});

Domium emits activities and metrics under the Domium source/meter.

Documentation

Build

dotnet restore Domium.slnx
dotnet build Domium.slnx --configuration Release --no-restore
dotnet test Domium.slnx --configuration Release --no-build
dotnet pack Domium.slnx --configuration Release --no-build --output artifacts/packages

License

Domium is licensed under the MIT license.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.3 92 5/20/2026
0.1.2 91 5/17/2026
0.1.1 97 5/17/2026
0.1.0 89 5/17/2026