Desktop and other non-ASP.NET Core apps
Nafas.Observability.Server runs a standalone HTTP listener for WinForms, WPF, and console apps with no ASP.NET Core pipeline.
UseNafasDashboard needs an IApplicationBuilder to mount onto — a plain
WinForms, WPF, or console/worker app has no ASP.NET Core pipeline of its
own to provide one. Nafas.Observability.Server is a separate, optional
package for exactly that case: it runs a second, independent HTTP listener
(on its own port) that serves the same dashboard against the same running
app's real data — no Kestrel, no OWIN, just a minimal HTTP/1.1 server
directly on TcpListener.
Why not Kestrel or HttpListener? The last version of Kestrel ever
published as a plain NuGet package is 2.3.13 from 2019, with no HTTP/2 and
no security patches since. System.Net.HttpListener — the BCL's own
listener — turned out not to be usable for the LAN case either: on Windows
it's backed by HTTP.sys, which refuses to bind any prefix other than
"localhost" unless the process runs elevated or a URL ACL was reserved
beforehand (verified empirically).
Being plain netstandard2.0 like the core package itself, this also works
from classic .NET Framework 4.6.1+ apps, not just modern .NET — confirmed
against a real net48 console host, not just the TFM compatibility rules
(see Requirements for the one
net48-specific gotcha it also caught, around SQLite and PlatformTarget).
dotnet add package Nafas.Observability.Server
services.AddNafasServer(); // same as always -- storage + ingestion
services.AddNafasHttpServer(o =>
{
o.Enabled = true; // opt-in; does nothing while false
o.Port = 5099;
o.AccessMode = NafasHttpServerAccessMode.LocalhostOnly; // or .Lan
});
Then open http://localhost:5099/nafas.
Starting and stopping at runtime
NafasHttpServerOptions.Enabled is only read once at startup — to
start/stop/reconfigure it later (e.g. a settings screen's "enable
dashboard" checkbox), resolve NafasHttpServer from DI and call its
StartAsync/StopAsync directly.
Access modes
AccessMode only controls which network interface is bound —
LocalhostOnly (the default) binds loopback only, Lan binds every
interface so other devices on the network can reach the port via this
machine's own IP, with no administrator rights required either way (unlike
System.Net.HttpListener, verified empirically on both). It does not by
itself relax NafasServerOptions.Authorize (still local-requests-only by
default, see Security): set Authorize
explicitly too if Lan should actually let those requests through,
otherwise they still get a 403.
One request per connection
Not HTTP/1.1 keep-alive — this listener is a local/LAN admin tool, not a public high-throughput API, so giving up connection reuse (an extra TCP handshake per dashboard API call, imperceptible on localhost/LAN) removes an entire dimension of correctness surface instead.