Domium.Observability.OpenTelemetry
0.1.2
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
<PackageReference Include="Domium.Observability.OpenTelemetry" Version="0.1.2" />
<PackageVersion Include="Domium.Observability.OpenTelemetry" Version="0.1.2" />
<PackageReference Include="Domium.Observability.OpenTelemetry" />
paket add Domium.Observability.OpenTelemetry --version 0.1.2
#r "nuget: Domium.Observability.OpenTelemetry, 0.1.2"
#:package Domium.Observability.OpenTelemetry@0.1.2
#addin nuget:?package=Domium.Observability.OpenTelemetry&version=0.1.2
#tool nuget:?package=Domium.Observability.OpenTelemetry&version=0.1.2
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 | Versions 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. |
-
.NETStandard 2.1
- Domium.Observability (>= 0.1.2)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.8)
- OpenTelemetry.Exporter.OpenTelemetryProtocol (>= 1.15.3)
- OpenTelemetry.Extensions.Hosting (>= 1.15.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.