Zero-config dev-time diagnostics dashboard for ASP.NET Core.
Captures HTTP requests, EF Core queries with N+1 detection, outbound HTTP, cache hits/misses,
exceptions, logs, Hangfire jobs, and Lookout.Dump() — all correlated per-request in a browser dashboard.
dotnet add package Lookout.AspNetCore
For Hangfire job capture:
dotnet add package Lookout.Hangfire
Three lines in Program.cs:
builder.Services.AddLookout();
app.UseLookout();
app.MapLookout(); // mounts the dashboard as a route on your app at /lookoutThe dashboard is a route inside your existing app — same host, same port, no separate process. Run your app, then open https://localhost:{port}/lookout (where {port} is your app's port). Your first request appears the moment you hit any endpoint — no database setup, no configuration file.
Dev-only by default. Lookout throws
LookoutEnvironmentExceptionat startup ifIsDevelopment()is false, unless you explicitly setAllowInProduction = trueorAllowInEnvironments = ["Staging"]. There is no silent production exposure.
| Capture point | What you get |
|---|---|
| HTTP Requests | Method, path, status, duration, headers, user identity, body (opt-in) |
| EF Core Queries | SQL text, parameters, duration, rows affected, stack trace to your code |
| N+1 Detection | Flags 3+ identical-normalised queries per request with a grouped banner |
| Raw ADO.NET / Dapper | Via SqlClientDiagnosticListener (SQL Server); de-duped against EF |
| Outbound HTTP | All HttpClient calls via auto-registered DelegatingHandler |
| Memory Cache | IMemoryCache get (hit/miss), set, remove — hit ratio per key |
| Distributed Cache | IDistributedCache get/set/refresh/remove, provider tagged |
| Exceptions | Handled and unhandled — type, message, inner exceptions, stack |
| Logs | All ILogger output, scoped to the active request; level-filterable |
| Hangfire Jobs | Enqueue → execution cross-linked; child EF/HTTP/cache/log captures inside jobs |
Lookout.Dump() |
Inline object inspection from anywhere — caller file + line attached |
All entries are correlated by request ID and searchable full-text (SQLite FTS5).
![]() |
![]() |
| Request list — signal badges surface db, http, cache, log, job counts | N+1 banner — 12 identical queries grouped, stack trace to your code |
- Section-per-capture navigation — dedicated list page per capture type: Requests, Queries, Exceptions, Logs, Cache, Jobs, Dump, HTTP Clients
- Full-text search —
Cmd+K/Ctrl+Kacross all entries and tags - Keyboard navigation —
j/kto move,Enterto open,Escto go back - Mini-Gantt timeline — per-request coloured bars for each capture type
- Dark mode — system / light / dark cycle, persisted across sessions
- Source links — stack frames open directly in VS Code or Rider
- Tag-based filtering — click any tag chip to filter across all sections
- "Copy as cURL" — on every request detail
Lookout is built to stay safe in shared dev environments:
- Dev-only by default — throws at startup in Production unless explicitly opted in via
AllowInProduction = true - Loopback-only by default — warns at startup if bound to a non-loopback address; set
AllowNonLoopback = trueto suppress - CSRF protection — all mutating endpoints require a double-submit cookie (
__lookout-csrf) +X-Lookout-Csrf-Tokenheader - Retention bounded — 24-hour time window (configurable) + 50,000 entry cap; background pruning keeps storage in check
See the Security model docs page for the full picture.
All options are set via AddLookout(options => { ... }). Everything has a sane default — you only touch what you need.
builder.Services.AddLookout(options =>
{
options.RetentionWindow = TimeSpan.FromHours(24); // default
options.MaxEntries = 50_000; // default
options.CaptureRequestBody = true; // default
options.CaptureResponseBody = true; // default
options.Ef.N1DetectionMinOccurrences = 3; // default
// Allow in non-Production environments
options.AllowInEnvironments = ["Staging"];
});Full reference at a-ghanem1.github.io/Lookout/docs/configuration.
Full docs at a-ghanem1.github.io/Lookout:
- Quickstart — under 2 minutes to first capture
- Configuration reference
- Custom capture points
- Security model
- Troubleshooting
- Comparison to MiniProfiler and Aspire Dashboard
| Lookout | MiniProfiler.NET | Aspire Dashboard | |
|---|---|---|---|
| Zero-config install | ✅ | ✅ | ❌ requires AppHost |
| N+1 detection | ✅ | ❌ | ❌ |
| Exception + log capture | ✅ | ❌ | partial |
| Cache capture | ✅ | ❌ | ❌ |
| Hangfire job capture | ✅ | ❌ | ❌ |
| Standalone browser dashboard | ✅ | in-page widget | ✅ |
| Production observability | ❌ dev-only | ❌ | ✅ |
| Last major release | 2026 | 2022 | active |
Lookout is complementary to both, not a replacement. MiniProfiler's in-page widget is great for timing SQL in production pages; Aspire Dashboard is a full production observability platform. Lookout is the tool you run during development when you want to understand exactly what a single request did.
Issues and pull requests are welcome. The v2 wishlist issue tracks planned additions — a good place to find a first contribution.
Planned community PR targets post-v1: Quartz.NET, MassTransit, Wolverine, gRPC capture, IEmailSender / MailKit.
Apache 2.0 — see LICENSE.
Found a vulnerability? Please report it privately — see SECURITY.md. Do not open a public issue.

