Getting Started — SQL Monitor
Portable Mode
Double-click DBLenseSQLMonitor.exe — no installation required. A connection dialog appears with four authentication modes:
- Windows Authentication — Domain-joined on-premises servers
- SQL Server Authentication — SQL login/password
- Azure Entra ID — Password — Azure SQL with Entra credentials
- Azure Entra ID — MFA — Azure SQL with multi-factor auth
After connecting, DBLense automatically detects whether the server is on-premises, Azure SQL Database, or Azure SQL Managed Instance, and adjusts its queries accordingly.
Enterprise Multi-Instance Edition
The portable dashboard above monitors one server at a time. The DBLense SQL Monitor Enterprise stack adds fleet monitoring with persistent history, alerting, and notifications across many SQL Servers — competing directly with Redgate SQL Monitor, SentryOne / SQL Sentry, and Idera SQL Diagnostic Manager.
Architecture
Three components plus an optional smoke-test harness:
| Component | Role |
|---|---|
Repository database (mon schema) | Hosted on any SQL Server 2016+. Stores every snapshot, alert rule, and alert event. Schema auto-deploys on first run (IF NOT EXISTS guards make redeploy safe). |
Collector Service (DBLenseSQLMonitor.Collector.exe) | .NET 8 Windows Service. Polls every enabled instance on the configured interval (default 60 s), runs 9 DMV captures per cycle, and persists snapshots. Logs to logs\collector-*.log via Serilog. |
Dashboard (DBLenseSQLMonitor.exe) | WPF application. Read-only viewer over the repository — KPI cards, 8 history tabs, instance manager, alert rule editor, alert event feed. |
Installation (production)
The recommended path is the unified DBLenseSQLMonitor-Setup.exe wizard. It installs and configures all three components — repository database, Collector Windows Service, and Dashboard — with options to install all together or any individual component on each host.
Recommended — Run the installer (≈ 2 minutes)
- Download
DBLenseSQLMonitor-Setup-<version>.zipfrom the product page, extract, then right-clickDBLenseSQLMonitor-Setup.exe→ Run as administrator (required for Windows Service registration). - Components page — tick which components to install on
this host:
- Repository Database (install once per environment).
- Collector Windows Service (install on monitoring host(s)).
- Dashboard UI (install on DBA workstations).
- Repository Database page — point at any SQL Server 2016+
instance, pick authentication (Windows, SQL Auth, Entra Password, Entra MFA),
and click Test connection. The wizard creates
DBLenseMonitorif it does not exist and deploys themon.*schema (12 tables). - Collector Service page — install path, service name, poll interval (default 60 s), and whether to start immediately.
- Dashboard page — install path, Desktop / Start Menu shortcuts, plus (if enabled) the initial monitored instance fields.
- Install page runs everything and shows a live log. On success you can launch the dashboard immediately.
The wizard skips component-specific pages for components you did not select, so a Dashboard-only DBA workstation install takes 3 clicks.
Build the installer from source
.\scripts\Package-DBLenseSQLMonitorSetup.ps1 -Configuration Release
# Produces: DBLenseSQLMonitor.Setup\publish-output\DBLenseSQLMonitor-Setup.exe
# artifacts\DBLenseSQLMonitor-Setup\DBLenseSQLMonitor-Setup-<date>.zip
The packager publishes the Collector + Dashboard as self-contained
win-x64, stages them as a payload inside the Setup output, and
zips the result for distribution.
Manual install (for locked-down / air-gapped environments)
Click to expand manual steps
# 1. Create the repository database
CREATE DATABASE DBLenseMonitor;
# Schema deploys on first connection — or run DBLenseSQLMonitor.Repository.RepositoryInstaller.
# 2. Publish + install the Collector service (PowerShell, elevated):
dotnet publish DBLenseSQLMonitor.Collector -c Release -r win-x64 --self-contained true -o "C:\Program Files\DBLense\SQLMonitor.Collector"
$exe = "C:\Program Files\DBLense\SQLMonitor.Collector\DBLenseSQLMonitor.Collector.exe"
sc.exe create DBLenseMonitorCollector binPath= "`"$exe`"" start= auto DisplayName= "DBLense SQL Monitor Collector"
sc.exe description DBLenseMonitorCollector "DBLense SQL Monitor — multi-instance collector"
sc.exe start DBLenseMonitorCollector
# 3. Publish + launch the Dashboard:
dotnet publish DBLenseSQLMonitor -c Release -r win-x64 --self-contained true -o "C:\Program Files\DBLense\SQLMonitor"
"C:\Program Files\DBLense\SQLMonitor\DBLenseSQLMonitor.exe"
Edit appsettings.json in the Collector folder and
%LocalAppData%\DBLenseSQLMonitor\repository.json for the
dashboard to point at the repository.
Verify the install
dotnet run --project DBLenseSQLMonitor.SmokeTest
You should see SMOKE TEST PASSED ✅ with row counts > 0
across all 9 collector tables.
First-Run Walkthrough
- Launch
DBLenseSQLMonitor.exe. The header shows "Repository: connected" in green when the connection string is valid. - The left sidebar is empty — no instances are registered yet. Click Add Instance.
- Fill in display name + server, choose authentication, click Test. The dialog reports edition / version / detected platform (OnPremises / AzureSqlDatabase / AzureSqlMI / AmazonRds).
- Click Save. The Collector picks up the new instance on its next cycle (within 60 s).
- After one cycle the KPI cards populate and tabs start showing data.
- Open the Alert Rules tab and create your first rule (see Alert Rules).
Registering Monitored Instances
The Add / Edit Instance dialog fields:
| Field | Description |
|---|---|
| Display name | Human-friendly label shown in lists and alerts (e.g. PROD-OLTP-01). |
| Server | Hostname, hostname\instance, IP, or Azure FQDN (myserver.database.windows.net). |
| Database | Initial catalog. Use master for on-prem / MI / RDS, or the user database for Azure SQL DB. |
| Windows Auth | Tick to use the Collector service account's identity. |
| Login / Password | SQL Auth — stored encrypted in the repository (DPAPI on the Collector host). |
| Environment | Production / Staging / QA / Development / Other. Used for filtering and alert routing. |
| Enabled | Untick to pause polling without deleting history. |
Click Test before saving. A green checkmark means: connection
succeeded, VIEW SERVER STATE works, and the platform was detected
correctly.
Dashboard Tour
Header — connection status, last refresh time,
Refresh button (manual refresh is rarely needed — the dashboard
auto-refreshes every 15 s via a DispatcherTimer).
Sidebar (left, 260 px) — registered instances. Click an instance to scope the KPI cards and tabs to it. The buttons below the list: Add, Edit, Delete.
KPI cards (top row, 6 tiles):
| Card | What it shows |
|---|---|
| Instance Count | Total enabled instances across the repository. |
| CPU % | Latest CPU snapshot for the selected instance (sql + other / idle breakdown). |
| Page Life Expectancy | Seconds. Lower than 300 on a busy OLTP box = memory pressure. |
| Active Sessions | Currently running user sessions. |
| Active Blocks | Sessions currently being blocked. |
| Active Alerts | Open (un-suppressed) alert events. |
Tabs (8):
| Tab | Data shown | Source DMV |
|---|---|---|
| Waits | Top 50 wait types since last snapshot, with delta wait_time_ms and waiting_tasks_count. | sys.dm_os_wait_stats |
| Top Queries | Top 25 queries by CPU / duration / executions with sql text snippet. | sys.dm_exec_query_stats + sys.dm_exec_sql_text |
| Blocking | Current blocking chains (head blocker → victims) with wait resource and SQL text. | sys.dm_exec_requests + sys.dm_exec_sessions |
| Databases | Size, free space, recovery model, log usage, last backup ages per database. | sys.databases + sys.master_files |
| File IO | Per-file read / write stalls, IO latency, throughput. | sys.dm_io_virtual_file_stats |
| Agent Jobs | Recent job runs with success / failure status and duration. | msdb.dbo.sysjobhistory |
| Alert Rules | Rule editor — add / edit / delete / disable rules. | mon.AlertRules |
| Alerts | Alert event feed — most recent first, severity-coloured. | mon.AlertEvents |
Alert Rules
An alert rule combines:
- Target instance — one specific instance, or (all instances) to apply globally.
- Metric — what to evaluate (see table below).
- Comparator —
>,<,>=,<=,=,!=. - Threshold — numeric value (parsed with invariant culture, so use
.not,). - Severity — Info, Warning, or Critical (drives event colour + notification routing).
- Suppression minutes — minimum gap between repeat alerts for the same rule + instance (default 10).
- Channels — semicolon-separated list, e.g.
email;windowsEvent;webhook.
| Metric | Source | Typical threshold |
|---|---|---|
CpuPercent | Ring buffer (on-prem) / dm_db_resource_stats (Azure) | > 85 Warning, > 95 Critical |
PageLifeExpectancy | dm_os_performance_counters | < 300 Warning |
ActiveSessions | dm_exec_sessions | depends on baseline |
ActiveBlocks | dm_exec_requests.blocking_session_id | > 0 Warning, > 5 Critical |
OldestBlockSeconds | dm_exec_requests.wait_time | > 30 Warning |
FailedAgentJobs | msdb.dbo.sysjobhistory | > 0 Warning |
DatabaseFreeSpacePct | sys.master_files + FILEPROPERTY | < 10 Warning, < 5 Critical |
LongRunningQuerySeconds | dm_exec_requests.total_elapsed_time | > 300 Warning |
Recommended baseline rule set (paste into the Alert Rules tab):
| Name | Metric / Comparator / Threshold | Severity |
|---|---|---|
| CPU sustained high | CpuPercent > 85 | Warning |
| CPU pegged | CpuPercent > 95 | Critical |
| PLE collapse | PageLifeExpectancy < 300 | Warning |
| Blocking chain present | ActiveBlocks > 0 | Warning |
| Blocking storm | ActiveBlocks > 5 | Critical |
| Long block | OldestBlockSeconds > 30 | Warning |
| Failed Agent job | FailedAgentJobs > 0 | Warning |
| Data file near full | DatabaseFreeSpacePct < 10 | Warning |
| Data file critical | DatabaseFreeSpacePct < 5 | Critical |
| Runaway query | LongRunningQuerySeconds > 300 | Warning |
Notification Channels
Channels are configured globally in
DBLenseSQLMonitor.Collector\appsettings.json under
"Notifications" and selected per-rule.
Email (SMTP)
"Notifications": {
"Email": {
"Enabled": true,
"SmtpHost": "smtp.office365.com",
"SmtpPort": 587,
"UseSsl": true,
"Username": "alerts@yourdomain.com",
"Password": "***",
"From": "alerts@yourdomain.com",
"To": [ "dba-oncall@yourdomain.com" ]
}
}
Windows Event Log
No config required — writes to the Application log with source DBLenseSQLMonitor. Useful for SCOM, Datadog, Splunk universal forwarder and any agent that tails the Event Log.
Webhook (Teams / Slack / PagerDuty)
"Notifications": {
"Webhook": {
"Enabled": true,
"Url": "https://hooks.slack.com/services/T000/B000/XXX",
"Format": "slack" // or "teams" | "pagerduty" | "generic"
}
}
Payload includes: rule name, instance display name, metric, observed value,
threshold, severity, captured-UTC, and a link back to the dashboard if
"DashboardUrl" is set.
Azure SQL & Amazon RDS Notes
| Platform | Detection | Behavioural differences |
|---|---|---|
| Azure SQL Database | SERVERPROPERTY('EngineEdition') = 5 | CPU comes from sys.dm_db_resource_stats (ring buffer is not exposed). Agent Jobs tab is hidden. Database-scoped DMVs only. |
| Azure SQL MI | SERVERPROPERTY('EngineEdition') = 8 | Full feature parity with on-prem except no Windows OS counters. |
| Amazon RDS for SQL Server | Presence of rdsadmin database | xp_readerrorlog and other sysadmin-only DMVs are auto-skipped. Use the RDS master user. |
Required Permissions
The Collector login on each monitored instance needs:
USE master;
CREATE LOGIN dblense_monitor WITH PASSWORD = 'StrongPwd!';
GRANT VIEW SERVER STATE TO dblense_monitor;
GRANT VIEW ANY DEFINITION TO dblense_monitor;
GRANT VIEW ANY DATABASE TO dblense_monitor;
-- For Agent Job monitoring:
USE msdb;
CREATE USER dblense_monitor FOR LOGIN dblense_monitor;
EXEC sp_addrolemember 'SQLAgentReaderRole', 'dblense_monitor';
On Azure SQL DB use VIEW DATABASE STATE on each monitored
database instead of VIEW SERVER STATE. On RDS use the RDS master
user (sysadmin permissions inside the RDS-allowed scope).
The Collector login on the repository database needs
db_owner on first deploy (to create the mon schema +
tables) and can be downgraded to db_datareader +
db_datawriter + EXECUTE on mon afterwards.
Tuning & Retention
| Setting | Where | Default | Notes |
|---|---|---|---|
| Poll interval | appsettings.json → Collector:PollIntervalSeconds | 60 | Drop to 30 for busy OLTP, raise to 300 for dev fleets. |
| Command timeout | SnapshotService.cs per query | 60 s | Bumped from 10 s during smoke testing — some DMVs are slow on under-spec hardware. |
| Snapshot retention | Manual purge job on the repository | — | Run a nightly DELETE FROM mon.<table> WHERE SnapshotUtc < DATEADD(day, -30, SYSUTCDATETIME()); |
| Alert suppression | Per-rule field | 10 min | Set to 0 to alert on every cycle (noisy — not recommended). |
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Header says "Repository: disconnected" | Connection string wrong / firewall | Verify App.config + ensure TCP 1433 reachable from dashboard host. |
| KPI cards stuck at 0 | Collector service not running | sc.exe query DBLenseMonitorCollector — start if STOPPED. Check logs\collector-*.log. |
| "Execution Timeout Expired" in logs | Slow DMV on heavily loaded server | Increase CommandTimeout in SnapshotService.cs. Re-publish service. |
| Alerts not firing | Suppression window still active, or metric not being captured | Check mon.AlertEvents directly. Confirm the relevant snapshot table has rows for the target instance. |
| Email channel silent | SMTP creds / firewall | Tail collector log — SMTP errors are logged at Warning level. Test SMTP from the Collector host with PowerShell Send-MailMessage. |
| Azure SQL DB CPU empty | Login lacks VIEW DATABASE STATE | Grant it; CPU comes from dm_db_resource_stats which requires that permission. |
| RDS instance probe fails | Using non-RDS-master login | Use the RDS master user — only it has the required DMV permissions on RDS. |