How it's built internally
A tour of the internals for anyone evaluating Nafas beyond the quick start.
For anyone evaluating this beyond the quick start:
- Ingestion is entirely in-process: an
ILoggerProvider, anActivityListener, and aMeterListener, each writing into a bounded per-signalChannel<T>(capacity 20,000, drop-on-full). A single hosted service drains all three, batches writes (up to 500 records or every second, whichever comes first), and persists them. - Storage is a thin interface (
INafasIngestionWriter/INafasQueryStore) with two concrete implementations, SQLite and SQL Server — no ORM, parameterized SQL, schema created and migrated at startup. - Alert evaluation (
NafasAlertEvaluationHostedService) is a pollingBackgroundServicereusing the same query layer the dashboard's KPI views use, tracking one open-incident-per-rule at a time. - Real-time delivery to the browser is an in-process pub/sub
(
NafasLiveFeed) fed by the ingestion writer and alert evaluator, read by the dashboard's SSE endpoints — nothing here is a polling query. - The dashboard UI is a Vue 3 + Vite SPA (PrimeVue, Pinia, Chart.js, vue-i18n for English/Persian), built ahead of time and embedded directly into the assembly as embedded resources — a consumer installing the package gets the whole UI with no separate static-file deployment step, and no Node.js runtime on the host machine.
- The whole API surface is a small hand-rolled router rather than ASP.NET
Core's
IEndpointRouteBuilder, because endpoint routing has beenFrameworkReference-only since ASP.NET Core 3.0 and is unavailable to anetstandard2.xclass library.