Skip to content

Latest commit

 

History

History
365 lines (273 loc) · 14.6 KB

File metadata and controls

365 lines (273 loc) · 14.6 KB

Contributing to SQL Server Performance Monitor

Thank you for your interest in contributing to the SQL Server Performance Monitor! This guide will help you understand the project structure, set up your development environment, and submit high-quality contributions.

Table of Contents

  1. Project Overview
  2. Development Setup
  3. Architecture Overview
  4. Contribution Paths
  5. Code Style Guidelines
  6. Pull Request Process
  7. Testing Guidelines

Project Overview

This repository contains two editions of the SQL Server Performance Monitor:

Full Edition — server-installed collectors with a separate dashboard:

Folder Description
install/ 50+ T-SQL scripts that create the PerformanceMonitor database
Installer/ CLI installer for the Full Edition database and collectors
Installer.Core/ Shared installation library (used by CLI installer and Dashboard)
Dashboard/ WPF dashboard — connects to PerformanceMonitor database, can also install/upgrade via Add Server

Lite Edition — standalone desktop app, nothing installed on the target server:

Folder Description
Lite/ Standalone WPF app with embedded DuckDB, collects directly from DMVs over the network

Development Setup

Prerequisites

  • Windows 10/11 (required for WPF)
  • .NET 8.0 SDK (download)
  • Visual Studio 2022 or VS Code with C# extension
  • SQL Server (2016 or later) for testing
  • Git for version control

Building from Source

# Clone the repository
git clone https://github.com/erikdarlingdata/PerformanceMonitor.git
cd PerformanceMonitor

# Build Full Dashboard
dotnet build Dashboard/Dashboard.csproj

# Build Lite Edition
dotnet build Lite/PerformanceMonitorLite.csproj

# Build CLI Installer (self-contained)
dotnet publish Installer/PerformanceMonitorInstaller.csproj -c Release

Running the Applications

Full Dashboard:

  1. Install the database on a SQL Server instance using the installer
  2. Run Dashboard/bin/Debug/net8.0-windows/Dashboard.exe
  3. Add your server connection and start monitoring

Lite Edition:

  1. Run Lite/bin/Debug/net8.0-windows/PerformanceMonitorLite.exe
  2. Add a SQL Server connection (requires VIEW SERVER STATE permission)
  3. Data collection begins automatically

Architecture Overview

Full Dashboard Architecture

The Full Dashboard has a clean separation between data collection and display:

┌─────────────────────────────────────────────────────────────────┐
│                    Monitored SQL Server                         │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  PerformanceMonitor Database                             │   │
│  │  ├── collect.* tables (raw collected data)               │   │
│  │  ├── dbo.collect_* procedures (29 collectors)            │   │
│  │  ├── report.* views (reporting layer)                    │   │
│  │  └── config.* tables (schedules, retention, logs)        │   │
│  └─────────────────────────────────────────────────────────┘   │
│                           ▲                                     │
│                           │ SQL Agent Jobs (every 1 min)        │
└───────────────────────────┼─────────────────────────────────────┘
                            │
                            │ SQL queries
                            ▼
┌─────────────────────────────────────────────────────────────────┐
│                    Dashboard Application                        │
│  ├── Services/DatabaseService.cs (data access layer)           │
│  ├── Models/*.cs (data transfer objects)                       │
│  ├── ServerTab.xaml (main monitoring UI)                       │
│  └── Mcp/*.cs (MCP server for LLM integration)                 │
└─────────────────────────────────────────────────────────────────┘

Key insight: T-SQL collectors run independently from the C# Dashboard. You can modify collectors without touching C# code, and vice versa.

Lite Edition Architecture

Warning: Lite has significantly more architectural complexity. A single new collector touches multiple layers:

┌─────────────────────────────────────────────────────────────────┐
│                    Remote SQL Server                            │
│  (No installation required - just VIEW SERVER STATE)            │
└───────────────────────────────────────────────────────────────┬─┘
                            │ DMV queries                       │
                            ▼                                   │
┌─────────────────────────────────────────────────────────────────┐
│                    Lite Application                             │
│                                                                 │
│  1. RemoteCollectorService.*.cs                                │
│     └── Queries SQL Server DMVs, stores in DuckDB              │
│                                                                 │
│  2. Database/Schema.cs                                         │
│     └── DuckDB table definitions (must match collector output) │
│                                                                 │
│  3. LocalDataService.*.cs                                      │
│     └── Reads from DuckDB for UI and MCP                       │
│                                                                 │
│  4. Controls/ServerTab.xaml.cs                                 │
│     └── UI display, charts, data grids                         │
│                                                                 │
│  5. Services/ArchiveService.cs + RetentionService.cs           │
│     └── Parquet archival and data cleanup                      │
│                                                                 │
│  6. ScheduleManager.cs                                         │
│     └── Controls when collectors run                           │
│                                                                 │
│  7. Mcp/*.cs                                                   │
│     └── Exposes data to LLM clients                            │
└─────────────────────────────────────────────────────────────────┘

There is no clean single-layer contribution path for Lite collectors. Adding a new collector requires changes across 5-7 files with careful coordination.


Contribution Paths

Where Contributions Are Welcome

Area Complexity Notes
Full Dashboard T-SQL collectors Low Clean, self-contained stored procedures
Full Dashboard reporting views Low SQL views in install/47_create_reporting_views.sql
Dashboard UI improvements Medium WPF/C# in Dashboard/ServerTab.xaml*
Lite UI improvements Medium WPF/C# in Lite/Controls/ServerTab.xaml*
Bug fixes (either edition) Varies Always welcome
Documentation Low README, comments, troubleshooting guides
MCP tool improvements Medium Dashboard/Mcp/ or Lite/Mcp/
New Lite collectors High See warning below

Adding a New Full Dashboard Collector

This is the cleanest contribution path. You need to:

  1. Create the collection table in install/02_create_tables.sql
  2. Create the collector procedure in a new file install/XX_collect_your_collector.sql
  3. Register in the schedule (handled automatically by install/41_schedule_management.sql)
  4. Optionally add reporting views in install/47_create_reporting_views.sql

See the existing collectors as templates. Each collector is self-contained.

Adding a New Lite Collector (Advanced)

Be aware: This is a significant undertaking. You must modify:

  1. Lite/Database/Schema.cs - Add DuckDB table definition
  2. Lite/Services/RemoteCollectorService.{YourCollector}.cs - SQL query + DuckDB insert logic
  3. Lite/Services/LocalDataService.{YourCollector}.cs - Query methods for UI/MCP
  4. Lite/Controls/ServerTab.xaml and .cs - UI elements, charts, grids
  5. Lite/Models/ - Any new data transfer objects
  6. Lite/config/collection_schedule.json - Default schedule entry
  7. Lite/Mcp/Mcp{Category}Tools.cs - MCP tool exposure (if applicable)

All of these must be coordinated. The schema must match what the collector inserts, the LocalDataService must query what the schema defines, the UI must display what LocalDataService returns, etc.

If you want to contribute a new Lite collector, please open an issue first to discuss the approach.


Code Style Guidelines

T-SQL Style

All T-SQL code must follow the project's coding standards. Key points:

  • Keywords: UPPERCASE (SELECT, FROM, WHERE)
  • Data types: lowercase, never abbreviated (integer not int, nvarchar(max) not nvarchar(MAX))
  • Object names: Use sysname for SQL Server identifiers
  • Indentation: 4 spaces (never tabs)
  • Table aliases: Always use AS keyword (FROM dbo.table AS t)
  • Column aliases: Use column_name = expression pattern
  • Commas: Trailing commas on multi-line lists
  • Comments: Use /* ... */ block comments, never --
  • Functions: Use COUNT_BIG() not COUNT(), ROWCOUNT_BIG() not @@ROWCOUNT

Example:

SELECT
    database_name = d.name,
    index_count = COUNT_BIG(i.index_id),
    total_size_mb = SUM(a.total_pages) * 8 / 1024
FROM sys.databases AS d
JOIN sys.indexes AS i
  ON i.database_id = d.database_id
WHERE d.database_id > 4
AND   d.state_desc = N'ONLINE'
GROUP BY
    d.name
ORDER BY
    total_size_mb DESC
OPTION(RECOMPILE);

The full T-SQL style guide is in CLAUDE.md.

C# Style

Follow standard C# conventions:

  • Naming: PascalCase for public members, _camelCase for private fields
  • Async/await: Use for all I/O operations
  • Null handling: Use nullable reference types, check for null appropriately
  • Comments: XML documentation for public APIs
  • File organization: One class per file, partial classes for large services

WPF-specific:

  • Use data binding where practical
  • Keep code-behind focused on UI logic
  • Services handle data access and business logic

Pull Request Process

Before You Start

  1. Check existing issues - Your idea may already be discussed
  2. Open an issue first for significant changes
  3. Fork the repository and create a feature branch

Branch Naming

Use descriptive branch names:

  • feature/add-memory-pressure-collector
  • fix/dashboard-connection-timeout
  • docs/update-readme-lite-section

Commit Messages

Write clear, descriptive commit messages:

Add memory pressure event collector

- Created collect.memory_pressure_events table
- Added dbo.collect_memory_pressure procedure
- Queries sys.dm_os_ring_buffers for memory broker events
- Runs every 5 minutes on default schedule

PR Checklist

Before submitting:

  • Code follows the style guidelines above
  • T-SQL has been tested with @debug = 1
  • C# code compiles without warnings
  • No hardcoded paths or credentials
  • Changes are documented (comments, README if applicable)
  • New files have copyright headers

Review Process

  1. Submit your PR with a clear description
  2. Maintainers will review within a few days
  3. Address any feedback
  4. Once approved, your PR will be merged

Testing Guidelines

Testing T-SQL Collectors

Run collectors with debug output:

/* Test the collector */
EXECUTE dbo.collect_your_collector
    @debug = 1;

/* Verify data was collected */
SELECT TOP (10) *
FROM collect.your_table
ORDER BY collection_time DESC;

/* Check collection log for errors */
SELECT TOP (10) *
FROM config.collection_log
WHERE collector_name = N'your_collector'
ORDER BY collection_time DESC;

Use the troubleshooting scripts:

  • install/99_installer_troubleshooting.sql - Quick health check
  • install/99_user_troubleshooting.sql - Detailed diagnostics

Testing Dashboard Changes

  1. Build and run the Dashboard
  2. Connect to a test SQL Server with PerformanceMonitor installed
  3. Verify your changes appear correctly
  4. Test with different time ranges
  5. Check that CSV export still works (right-click any grid)

Testing Lite Changes

  1. Build and run the Lite application
  2. Connect to a test SQL Server (VIEW SERVER STATE permission required)
  3. Wait for initial collection (1-5 minutes)
  4. Verify data appears in the appropriate tab
  5. Test auto-refresh functionality
  6. If you added MCP tools, test with Claude Code:
    claude mcp add --transport http --scope user sql-monitor http://localhost:5151/
    

SQL Server Versions

Test against multiple versions if possible:

  • SQL Server 2016 (minimum supported)
  • SQL Server 2019
  • SQL Server 2022
  • Azure SQL Database (Lite only)

Some DMVs behave differently across versions. Handle version differences gracefully.


Questions?

  • Bug reports: Open a GitHub issue using the bug report template
  • Feature requests: Open a GitHub issue using the feature request template
  • General questions: Start a GitHub Discussion

Thank you for contributing!