v6.3.0
v6.3.0 — first-class logging and metrics
This release makes the engine observable through the tools you already use. Point Serilog (or
NLog, or the console) at it and every executed query shows up in your logs — the same way EF Core
does it, with no logger-specific packages to install.
Logging — Microsoft.Extensions.Logging, EF-style
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("eQuantic.Core.Data", LogEventLevel.Information)
.WriteTo.Console()
.CreateLogger();Add the assembly's category to your configuration and executed queries log with placeholders,
elapsed time and row counts. Categories are stable (eQuantic.Core.Data.{provider}.Command,
and eQuantic.Core.Data.cosmosdb.Request) with stable event ids, so any
Microsoft.Extensions.Logging sink — Serilog, NLog, the ASP.NET console — plugs in through the
providers it already ships. No eQuantic.Core.Data.Serilog package needed: the mechanism serves
every logger on day one.
| Event | Id | Level | Carries |
|---|---|---|---|
CommandExecuted |
10001 | Information | statement (placeholders), elapsed, rows; Cosmos adds status + RU charge |
CommandFailed |
10002 | Error | statement + exception |
CommitExecuted |
10101 | Information | staged writes flushed, elapsed |
ClientEvaluation |
10201 | Warning | a residual that ran client-side (behind its opt-in) |
AllowFiltering |
10202 | Warning | a Cassandra query running as a declared scan |
QuerySplit |
10203 | Warning | an OR filter fanned out into parallel native queries |
ConcurrencyConflict |
10301 | Warning | expected vs affected on a lost race |
Beyond what EF logs
The pushdown gates log at Warning — an opt-in that quietly became a hot path's habit surfaces
in production logs, not in an incident review. And Cosmos DB logs the request charge (RU) per
operation, the number Cosmos operators actually chase.
Values are opt-in, always
Parameter values never log by default — statements carry placeholders, the same policy the traces
follow. Turn them on the way you turn EF's on, deliberately, per environment:
services.AddSingleton(new DataConventions { EnableSensitiveDataLogging = true });Metrics — one Meter for the dashboards
services.AddOpenTelemetry().WithMetrics(m => m.AddMeter("eQuantic.Core.Data").AddOtlpExporter());Command counters and a duration histogram, commit/write counters, and — the differentiator — the
gate counters (equantic.client_evaluations, equantic.allow_filtering,
equantic.query_splits, equantic.concurrency_conflicts) that make the engine's honesty
graphable: a rising client-evaluation line is an alert, not an archaeology project.
How it's wired
One seam per provider, each the store's natural one — a delegating DbCommand on the relational
engine (catches reads, aggregates, set-based writes and includes in one place), the
prepared-statement executor on Cassandra, the driver's own command events on MongoDB, a
RequestHandler in the pipeline on Cosmos DB. An ILoggerFactory from DI is optional; without one
the engine logs to a null logger and costs nothing.
Verification
Suites green on real stores: PostgreSQL 55 (the logging contract itself pinned — stable category,
placeholder default, sensitive opt-in, commit event), Cassandra 94, MongoDB 131, Cosmos DB 41,
core 62.
Compatibility: no breaking changes; adds a floored Microsoft.Extensions.Logging.Abstractions
dependency (8.0.0 on net8, 10.0.0 on net10 — your own generation, never forced upward). Requires
eQuantic.Core.DataModel 4.0.0 / eQuantic.Core.Domain 4.0.0 (as since v6.0.0). Full guide:
Operations → Observability.