Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
4f3722b
Fix DuckDB file corruption during maintenance, overhaul maintenance s…
erikdarlingdata Feb 21, 2026
3546ebc
Merge pull request #221 from erikdarlingdata/feature/fix-duckdb-reade…
erikdarlingdata Feb 21, 2026
1a8985b
v1.4.0 feature work: config tab consolidation, DB drop on remove, Duc…
erikdarlingdata Feb 22, 2026
bbe1839
Merge pull request #224 from erikdarlingdata/feature/consolidate-conf…
erikdarlingdata Feb 22, 2026
50b1367
Add memory clerks tab to Lite with picker-driven chart (#145)
erikdarlingdata Feb 22, 2026
e94e0b7
Merge pull request #225 from erikdarlingdata/feature/memory-clerks-tab
erikdarlingdata Feb 22, 2026
77c9508
Visual polish: sort arrows, right-aligned numerics, initial sort indi…
erikdarlingdata Feb 22, 2026
47e3586
Merge pull request #227 from erikdarlingdata/feature/visual-polish-110
erikdarlingdata Feb 22, 2026
2dbf6d8
Add collector duration trends chart to Dashboard Collection Health (#…
erikdarlingdata Feb 22, 2026
84dd542
Merge pull request #229 from erikdarlingdata/feature/collector-durati…
erikdarlingdata Feb 22, 2026
3160f84
Add collection log drill-down and daily summary to Lite (#138)
erikdarlingdata Feb 22, 2026
47a42b9
Merge pull request #230 from erikdarlingdata/feature/lite-collection-…
erikdarlingdata Feb 22, 2026
64edb1d
Add Current Active Queries live snapshot view (#149)
erikdarlingdata Feb 22, 2026
8611446
Merge pull request #231 from erikdarlingdata/feature/live-snapshot-149
erikdarlingdata Feb 22, 2026
9f568b1
Add CLI --help flag and fix Lite status bar text color (#111)
erikdarlingdata Feb 22, 2026
5e47d96
Merge pull request #232 from erikdarlingdata/feature/onboarding-111
erikdarlingdata Feb 22, 2026
6cc5826
Add native graphical query plan viewer to Dashboard and Lite (#220)
erikdarlingdata Feb 23, 2026
31b6344
Plan viewer phase 2: properties panel, tooltips, SSMS parity
erikdarlingdata Feb 23, 2026
b2f7a87
Fix archive view column mismatch, wait_stats thread-safety, and perce…
erikdarlingdata Feb 23, 2026
5dd66f7
Fix collector health status bar text color to match other status text
erikdarlingdata Feb 23, 2026
a1a740e
Merge pull request #235 from erikdarlingdata/feature/fix-archive-view…
erikdarlingdata Feb 23, 2026
cc7b3d7
Merge branch 'dev' into feature/query-plan-viewer-220
erikdarlingdata Feb 23, 2026
49752d4
XSD-driven operator attribute completeness + Lite plan viewer gaps
erikdarlingdata Feb 23, 2026
fc78c34
Update NuGet packages.
OZTPR Feb 23, 2026
12ad229
fixes for:
OZTPR Feb 23, 2026
858dcf6
SSMS parity: close all 27 plan viewer gaps from XSD/vscode-mssql audit
erikdarlingdata Feb 23, 2026
84de71d
add a few more options to PR template
OZTPR Feb 23, 2026
0f45722
Merge pull request #238 from MisterZeus/update-nuget-again
erikdarlingdata Feb 23, 2026
e703185
Use per-collector retention from config.collection_schedule in data r…
erikdarlingdata Feb 23, 2026
70cf137
Merge pull request #239 from erikdarlingdata/feature/per-collector-re…
erikdarlingdata Feb 23, 2026
0421f83
Add user-configurable connection timeout setting (#236)
erikdarlingdata Feb 23, 2026
ef5eee3
Merge pull request #241 from erikdarlingdata/feature/configurable-tim…
erikdarlingdata Feb 23, 2026
57ee8d0
Actual execution plan support + #233 SET options in repro scripts
erikdarlingdata Feb 23, 2026
5e5f7e7
Tabbed plan viewer, query text display, and visual polish
erikdarlingdata Feb 23, 2026
304738c
Complete ShowPlan XSD v1.599 parser coverage + PlanAnalyzer
erikdarlingdata Feb 23, 2026
a4f1d13
Actual plan loading indicator + 6 new PlanAnalyzer rules + eager spoo…
erikdarlingdata Feb 23, 2026
2674456
Fix query_stats and procedure_stats collectors ignoring recent queries
erikdarlingdata Feb 23, 2026
20bb01e
Merge pull request #242 from erikdarlingdata/feature/query-stats-time…
erikdarlingdata Feb 23, 2026
9538732
Remove blank tooltips from warning and parallel badge icons
erikdarlingdata Feb 23, 2026
b4f2d43
Merge remote-tracking branch 'origin/dev' into feature/query-plan-vie…
erikdarlingdata Feb 23, 2026
1d1490a
Merge pull request #243 from erikdarlingdata/feature/query-plan-viewe…
erikdarlingdata Feb 23, 2026
9848938
Fix CSV export for non-US locales (issue #240)
erikdarlingdata Feb 23, 2026
d004f6d
Merge pull request #244 from erikdarlingdata/feature/csv-separator-240
erikdarlingdata Feb 23, 2026
ab4f8c0
Full Dashboard column parity for query_stats, procedure_stats, query_…
erikdarlingdata Feb 24, 2026
067f777
Merge pull request #250 from erikdarlingdata/feature/delta-calculator…
erikdarlingdata Feb 24, 2026
bb4e325
Issues #245-248: scrollbars, self-filtering, missing columns, context…
erikdarlingdata Feb 24, 2026
d399dee
Merge pull request #251 from erikdarlingdata/feature/issues-245-248
erikdarlingdata Feb 24, 2026
36a5ab7
Add Getting Started section to README with download instructions
erikdarlingdata Feb 24, 2026
7ddfbbf
Merge pull request #254 from erikdarlingdata/readme-getting-started
erikdarlingdata Feb 24, 2026
cea6907
Issue #255: Themed perfmon counter packs + 14 new counters
erikdarlingdata Feb 24, 2026
1a88993
Merge pull request #256 from erikdarlingdata/feature/perfmon-packs
erikdarlingdata Feb 24, 2026
0a9fc31
Issue #257: Fix truncated status text in Add Server dialog
erikdarlingdata Feb 24, 2026
3a2e1db
Merge pull request #259 from erikdarlingdata/fix/issue-257-status-tru…
erikdarlingdata Feb 24, 2026
66a3261
Issue #260: Migrate Query Store Regressions and Query Trace Patterns …
erikdarlingdata Feb 24, 2026
88ea3aa
Merge pull request #265 from erikdarlingdata/fix/issue-260-grid-filte…
erikdarlingdata Feb 24, 2026
2611d6e
Issue #261: Fix View Plan for Query Store and Query Store Regressions…
erikdarlingdata Feb 24, 2026
1e53514
Merge pull request #266 from erikdarlingdata/fix/issue-261-view-plan
erikdarlingdata Feb 24, 2026
2a7811c
Issue #263: Align Query Store drill-down time filter with main view
erikdarlingdata Feb 24, 2026
ac78acf
Merge pull request #267 from erikdarlingdata/fix/issue-263-drilldown-…
erikdarlingdata Feb 24, 2026
4dd4488
Fix execution count mismatches between main views and drill-downs
erikdarlingdata Feb 25, 2026
cbc95c3
Merge pull request #270 from erikdarlingdata/fix/execution-count-mism…
erikdarlingdata Feb 25, 2026
c54f2b9
Fix drill-down chart UX: sparse data markers, hover tooltips, window …
erikdarlingdata Feb 25, 2026
e56f560
Merge pull request #275 from erikdarlingdata/fix/issue-271-chart-ux
erikdarlingdata Feb 25, 2026
c2fc4e1
Issue #274: Query Store Regressions drill-down + TVF rewrite
erikdarlingdata Feb 25, 2026
a3d2f50
Merge pull request #276 from erikdarlingdata/fix/issue-274-regression…
erikdarlingdata Feb 25, 2026
be73f00
Issue #268: Show query identifiers in drill-down windows
erikdarlingdata Feb 25, 2026
0b3c5c7
Merge pull request #277 from erikdarlingdata/fix/issue-268-query-iden…
erikdarlingdata Feb 25, 2026
af95e63
Issue #269: Make plan viewer properties copyable
erikdarlingdata Feb 25, 2026
06f2580
Merge pull request #278 from erikdarlingdata/fix/issue-269-plan-prope…
erikdarlingdata Feb 25, 2026
6c7b38a
Issue #273: Trace pattern drill-down, missing columns, query text too…
erikdarlingdata Feb 25, 2026
98d5e56
Merge pull request #279 from erikdarlingdata/feature/issue-273-trace-…
erikdarlingdata Feb 25, 2026
9995376
Issue #281 Gap 1: Standardize memory grant stats collection and add c…
erikdarlingdata Feb 25, 2026
9cf649a
Merge pull request #283 from erikdarlingdata/feature/issue-281-memory…
erikdarlingdata Feb 25, 2026
ef4ed0c
Issue #281 Gap 2: File I/O throughput charts, file-level latency, que…
erikdarlingdata Feb 25, 2026
05a7fd9
Issue #280: Add Current Waits charts to Blocking tab in Dashboard and…
erikdarlingdata Feb 25, 2026
9b9161f
Merge pull request #286 from erikdarlingdata/worktree-issue-280-curre…
erikdarlingdata Feb 25, 2026
02296a4
Issue #281 Gap 4: Remove session_wait_stats (zero UI, full removal)
erikdarlingdata Feb 25, 2026
4bdbc6d
Merge pull request #285 from erikdarlingdata/feature/issue-281-memory…
erikdarlingdata Feb 25, 2026
64dc9fc
Issue #284: Standardize chart save/export filenames between Dashboard…
erikdarlingdata Feb 25, 2026
822eba3
Merge pull request #288 from erikdarlingdata/worktree-issue-284-chart…
erikdarlingdata Feb 25, 2026
482f4ef
Issue #287: Use database_query_store_options instead of is_query_stor…
erikdarlingdata Feb 25, 2026
c437185
Merge pull request #292 from erikdarlingdata/worktree-issue-287-qs-de…
erikdarlingdata Feb 25, 2026
8af09ee
Issue #281 medium gaps: Surface hidden columns in memory, procedure, …
erikdarlingdata Feb 25, 2026
d429c93
Merge pull request #293 from erikdarlingdata/worktree-issue-281-mediu…
erikdarlingdata Feb 25, 2026
1d66495
Issue #281 Gap 3: Surface min/max extremes in both apps, fix Query St…
erikdarlingdata Feb 25, 2026
c1d5151
Merge remote-tracking branch 'origin/dev' into feature/issue-281-memo…
erikdarlingdata Feb 25, 2026
7021b7d
Merge pull request #294 from erikdarlingdata/feature/issue-281-memory…
erikdarlingdata Feb 25, 2026
0922b01
Fix missing chart context menu on File I/O Throughput charts in Lite
erikdarlingdata Feb 25, 2026
61e5d84
Merge pull request #295 from erikdarlingdata/worktree-issue-281-mediu…
erikdarlingdata Feb 25, 2026
42943d4
Release prep v2.0.0: version bumps, changelog, upgrade scripts, fixes
erikdarlingdata Feb 25, 2026
31fbc12
Merge pull request #297 from erikdarlingdata/feature/release-2.0.0-prep
erikdarlingdata Feb 25, 2026
62c1949
Fix installer upgrade bugs and add Agent job cleanup on server removal
erikdarlingdata Feb 25, 2026
b8b0d63
Merge pull request #298 from erikdarlingdata/feature/installer-fixes-…
erikdarlingdata Feb 25, 2026
82aa75e
Make GUI installer publish as single-file self-contained exe
erikdarlingdata Feb 25, 2026
e033e0e
Merge pull request #300 from erikdarlingdata/fix/gui-installer-single…
erikdarlingdata Feb 26, 2026
4f5c0fd
Add missing perfmon counters to SQL collector, fix TempDB Pressure pack
erikdarlingdata Feb 26, 2026
2485799
Merge pull request #301 from erikdarlingdata/fix/perfmon-missing-coun…
erikdarlingdata Feb 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 4 additions & 2 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ A clear description of the change and why it's being made.
## Which component(s) does this affect?

- [ ] Full Dashboard
- [ ] Lite
- [ ] Lite Dashboard
- [ ] Lite Tests
- [ ] SQL collection scripts
- [ ] Installer
- [ ] CLI Installer
- [ ] GUI Installer
- [ ] Documentation

## How was this tested?
Expand Down
6 changes: 2 additions & 4 deletions .github/sql/ci_validate_installation.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ IF SCHEMA_ID(N'report') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: sche
PRINT '';

/*
Procedures in collect schema (37)
Procedures in collect schema (36)
*/
PRINT 'Checking collect procedures...';

Expand Down Expand Up @@ -65,7 +65,6 @@ IF OBJECT_ID(N'collect.tempdb_stats_collector', N'P') IS NULL BEGIN SE
IF OBJECT_ID(N'collect.plan_cache_stats_collector', N'P') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: collect.plan_cache_stats_collector'; END; SET @checked += 1;
IF OBJECT_ID(N'collect.session_stats_collector', N'P') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: collect.session_stats_collector'; END; SET @checked += 1;
IF OBJECT_ID(N'collect.waiting_tasks_collector', N'P') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: collect.waiting_tasks_collector'; END; SET @checked += 1;
IF OBJECT_ID(N'collect.session_wait_stats_collector', N'P') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: collect.session_wait_stats_collector'; END; SET @checked += 1;
IF OBJECT_ID(N'collect.server_configuration_collector', N'P') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: collect.server_configuration_collector'; END; SET @checked += 1;
IF OBJECT_ID(N'collect.database_configuration_collector', N'P') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: collect.database_configuration_collector'; END; SET @checked += 1;
IF OBJECT_ID(N'collect.configuration_issues_analyzer', N'P') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: collect.configuration_issues_analyzer'; END; SET @checked += 1;
Expand Down Expand Up @@ -142,7 +141,6 @@ IF OBJECT_ID(N'report.blocking_chain_analysis', N'V') IS NULL BEGIN
IF OBJECT_ID(N'report.tempdb_contention_analysis', N'V') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: report.tempdb_contention_analysis'; END; SET @checked += 1;
IF OBJECT_ID(N'report.parameter_sensitivity_detection', N'V') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: report.parameter_sensitivity_detection'; END; SET @checked += 1;
IF OBJECT_ID(N'report.scheduler_cpu_analysis', N'V') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: report.scheduler_cpu_analysis'; END; SET @checked += 1;
IF OBJECT_ID(N'report.session_wait_analysis', N'V') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: report.session_wait_analysis'; END; SET @checked += 1;
IF OBJECT_ID(N'report.critical_issues', N'V') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: report.critical_issues'; END; SET @checked += 1;
IF OBJECT_ID(N'report.memory_usage_trends', N'V') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: report.memory_usage_trends'; END; SET @checked += 1;
IF OBJECT_ID(N'report.running_jobs', N'V') IS NULL BEGIN SET @missing += 1; PRINT ' MISSING: report.running_jobs'; END; SET @checked += 1;
Expand Down Expand Up @@ -182,7 +180,7 @@ WHERE OBJECT_SCHEMA_NAME(t.object_id) = N'config';
PRINT ' collect schema tables: ' + CONVERT(varchar(10), @collect_tables);
PRINT ' config schema tables: ' + CONVERT(varchar(10), @config_tables);

IF @collect_tables < 20 BEGIN SET @missing += 1; PRINT ' MISSING: expected >= 20 collect tables, found ' + CONVERT(varchar(10), @collect_tables); END; SET @checked += 1;
IF @collect_tables < 19 BEGIN SET @missing += 1; PRINT ' MISSING: expected >= 20 collect tables, found ' + CONVERT(varchar(10), @collect_tables); END; SET @checked += 1;
IF @config_tables < 5 BEGIN SET @missing += 1; PRINT ' MISSING: expected >= 5 config tables, found ' + CONVERT(varchar(10), @config_tables); END; SET @checked += 1;

PRINT '';
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
run: dotnet publish Installer/PerformanceMonitorInstaller.csproj -c Release

- name: Publish GUI Installer
run: dotnet publish InstallerGui/InstallerGui.csproj -c Release -r win-x64 --self-contained
run: dotnet publish InstallerGui/InstallerGui.csproj -c Release

- name: Package release artifacts
if: github.event_name == 'release'
Expand All @@ -69,7 +69,7 @@ jobs:
New-Item -ItemType Directory -Force -Path "$instDir/upgrades"

Copy-Item 'Installer/bin/Release/net8.0/win-x64/publish/PerformanceMonitorInstaller.exe' $instDir
Copy-Item 'InstallerGui/bin/Release/net8.0-windows/win-x64/publish/InstallerGui.exe' $instDir -ErrorAction SilentlyContinue
Copy-Item 'InstallerGui/bin/Release/net8.0-windows/win-x64/publish/PerformanceMonitorInstallerGui.exe' $instDir -ErrorAction SilentlyContinue
Copy-Item 'install/*.sql' "$instDir/install/"
if (Test-Path 'upgrades') { Copy-Item 'upgrades/*' "$instDir/upgrades/" -Recurse -ErrorAction SilentlyContinue }
if (Test-Path 'README.md') { Copy-Item 'README.md' $instDir }
Expand Down
87 changes: 87 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,67 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.0.0] - 2026-02-25

### Important

- **Schema upgrade**: The `collect.memory_grant_stats` table gains new delta columns and drops unused warning columns. The `collect.session_wait_stats` table, its collector procedure, reporting view, and schedule entry are removed (zero UI coverage). Upgrade scripts run automatically via the CLI/GUI installer and use idempotent checks.

### Added

- **Graphical query plan viewer** — native ShowPlan rendering in both Dashboard and Lite with SSMS-parity operator icons, properties panel, tooltips, warning/parallelism badges, and tabbed plan display ([#220])
- **Actual execution plan support** — execute queries with SET STATISTICS XML ON to capture actual plans, with loading indicator and confirmation dialog ([#233])
- **PlanAnalyzer** — automated plan analysis with rules for missing indexes, eager spools, key lookups, implicit conversions, memory grants, and more
- **Current Active Queries live snapshot** — real-time view of running queries with estimated/live plan download ([#149])
- **Memory clerks tab** in Lite with picker-driven chart ([#145])
- **Current Waits charts** in Blocking tab for both Dashboard and Lite ([#280])
- **File I/O throughput charts** — read/write throughput trends, file-level latency breakdown, queued I/O overlay ([#281])
- **Memory grant stats charts** — standardized collection with delta framework integration and trend visualization ([#281])
- **CPU scheduler pressure status** — real-time scheduler, worker, runnable task counts with color-coded pressure level below CPU chart
- **Collection log drill-down** and daily summary in Lite ([#138])
- **Collector duration trends chart** in Dashboard Collection Health ([#138])
- **Themed perfmon counter packs** — 14 new counters with organized themed groups ([#255])
- **User-configurable connection timeout** setting ([#236])
- **Per-collector retention** — uses per-collector retention from `config.collection_schedule` in data retention ([#237])
- **Query identifiers** in drill-down windows — query hash, plan hash, SQL handle visible for identification ([#268])
- **Trace pattern drill-down** with missing columns and query text tooltips ([#273])
- **Query Store Regressions drill-down** with TVF rewrite for performance ([#274])
- **CLI `--help` flag** for installer ([#111])
- Sort arrows, right-aligned numerics, and initial sort indicators across all grids ([#110])
- Copyable plan viewer properties ([#269])
- Standardized chart save/export filenames between Dashboard and Lite ([#284])
- Full Dashboard column parity for query_stats, procedure_stats, and query_store_stats
- Min/max extremes surfaced in both apps — physical reads, rows, grant KB, spills, CLR time, log bytes ([#281])

### Changed

- Query Store detection uses `sys.database_query_store_options` instead of `sys.databases.is_query_store_on` for Azure SQL DB compatibility ([#287])
- Config tab consolidation, DB drop on server remove, DuckDB-first plan lookups, procedure stats parity
- Collector health status now detects consecutive recent failures — 5+ consecutive errors = FAILING, 3+ = WARNING
- Plan buttons now show a MessageBox when no plan is available instead of silently doing nothing
- CSV export uses locale-appropriate separators for non-US locales ([#240])
- Query Store Regressions and Query Trace Patterns migrated to popup grid filtering ([#260])
- NuGet packages updated; xUnit v3 migration

### Fixed

- **DuckDB file corruption** during maintenance — ReaderWriterLockSlim coordination, archive-all-and-reset at 512MB replaces compaction ([#218])
- Archive view column mismatch, wait_stats thread-safety, and percent_complete type cast ([#234])
- Collector health status bar text color ([#234])
- View Plan for Query Store and Query Store Regressions tabs ([#261])
- Query Store drill-down time filter alignment with main view ([#263])
- Execution count mismatches between main views and drill-downs
- Drill-down chart UX — sparse data markers, hover tooltips, window sizing ([#271])
- Truncated status text in Add Server dialog ([#257])
- Scrollbar visibility, self-filtering artifacts, missing columns, and context menus ([#245], [#246], [#247], [#248])
- query_stats and procedure_stats collectors ignoring recent queries
- Blank tooltips on warning and parallel badge icons
- Missing chart context menu on File I/O Throughput charts in Lite

### Removed

- `collect.session_wait_stats` table, `collect.session_wait_stats_collector` procedure, `report.session_wait_analysis` view, and schedule entry — zero UI coverage, never surfaced in Dashboard or Lite ([#281])

## [1.3.0] - 2026-02-20

### Important
Expand Down Expand Up @@ -119,6 +180,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Delta normalization for per-second rate calculations
- Dark theme UI

[2.0.0]: https://github.com/erikdarlingdata/PerformanceMonitor/compare/v1.3.0...v2.0.0
[1.3.0]: https://github.com/erikdarlingdata/PerformanceMonitor/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/erikdarlingdata/PerformanceMonitor/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/erikdarlingdata/PerformanceMonitor/compare/v1.0.0...v1.1.0
Expand Down Expand Up @@ -187,3 +249,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#206]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/206
[#210]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/210
[#214]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/214
[#218]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/218
[#220]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/220
[#233]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/233
[#234]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/234
[#236]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/236
[#237]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/237
[#240]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/240
[#245]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/245
[#246]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/246
[#247]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/247
[#248]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/248
[#255]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/255
[#257]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/257
[#260]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/260
[#261]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/261
[#263]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/263
[#268]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/268
[#269]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/269
[#271]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/271
[#273]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/273
[#274]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/274
[#280]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/280
[#281]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/281
[#284]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/284
[#287]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/287
16 changes: 13 additions & 3 deletions Dashboard/CollectionLogWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@
Title="Collection History" Height="600" Width="1000"
WindowStartupLocation="CenterOwner"
Background="{DynamicResource BackgroundBrush}">
<Window.Resources>
<ContextMenu x:Key="DataGridContextMenu">
<MenuItem Header="Copy Cell" Click="CopyCell_Click"/>
<MenuItem Header="Copy Row" Click="CopyRow_Click"/>
<MenuItem Header="Copy All Rows" Click="CopyAllRows_Click"/>
<Separator/>
<MenuItem Header="Export to CSV..." Click="ExportToCsv_Click"/>
</ContextMenu>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
Expand All @@ -28,7 +37,8 @@
CanUserSortColumns="True"
AlternatingRowBackground="{DynamicResource BackgroundLightBrush}"
GridLinesVisibility="All"
Margin="10">
Margin="10"
ContextMenu="{StaticResource DataGridContextMenu}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding CollectionTime, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Width="150">
<DataGridTextColumn.Header>
Expand All @@ -46,15 +56,15 @@
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding RowsCollected}" Width="120">
<DataGridTextColumn Binding="{Binding RowsCollected}" ElementStyle="{StaticResource NumericCell}" Width="120">
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<Button x:Name="RowsCollectedFilterButton" Style="{DynamicResource ColumnFilterButtonStyle}" Tag="RowsCollected" Click="LogFilter_Click" Margin="0,0,4,0"/>
<TextBlock Text="Rows Collected" FontWeight="Bold" VerticalAlignment="Center"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding DurationMs, StringFormat='{}{0:N0}'}" Width="110">
<DataGridTextColumn Binding="{Binding DurationMs, StringFormat='{}{0:N0}'}" ElementStyle="{StaticResource NumericCell}" Width="110">
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<Button x:Name="DurationFilterButton" Style="{DynamicResource ColumnFilterButtonStyle}" Tag="DurationMs" Click="LogFilter_Click" Margin="0,0,4,0"/>
Expand Down
74 changes: 74 additions & 0 deletions Dashboard/CollectionLogWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,80 @@ private void UpdateLogFilterButtonStyles()
}
}

private void CopyCell_Click(object sender, RoutedEventArgs e)
{
if (sender is MenuItem menuItem && menuItem.Parent is ContextMenu contextMenu)
{
var dataGrid = Helpers.TabHelpers.FindDataGridFromContextMenu(contextMenu);
if (dataGrid != null && dataGrid.CurrentCell.Item != null)
{
var cellContent = Helpers.TabHelpers.GetCellContent(dataGrid, dataGrid.CurrentCell);
if (!string.IsNullOrEmpty(cellContent))
Clipboard.SetDataObject(cellContent, false);
}
}
}

private void CopyRow_Click(object sender, RoutedEventArgs e)
{
if (sender is MenuItem menuItem && menuItem.Parent is ContextMenu contextMenu)
{
var dataGrid = Helpers.TabHelpers.FindDataGridFromContextMenu(contextMenu);
if (dataGrid?.SelectedItem != null)
Clipboard.SetDataObject(Helpers.TabHelpers.GetRowAsText(dataGrid, dataGrid.SelectedItem), false);
}
}

private void CopyAllRows_Click(object sender, RoutedEventArgs e)
{
if (sender is MenuItem menuItem && menuItem.Parent is ContextMenu contextMenu)
{
var dataGrid = Helpers.TabHelpers.FindDataGridFromContextMenu(contextMenu);
if (dataGrid != null && dataGrid.Items.Count > 0)
{
var sb = new System.Text.StringBuilder();
var headers = new List<string>();
foreach (var column in dataGrid.Columns)
headers.Add(Helpers.DataGridClipboardBehavior.GetHeaderText(column));
sb.AppendLine(string.Join("\t", headers));
foreach (var item in dataGrid.Items)
sb.AppendLine(Helpers.TabHelpers.GetRowAsText(dataGrid, item));
Clipboard.SetDataObject(sb.ToString(), false);
}
}
}

private void ExportToCsv_Click(object sender, RoutedEventArgs e)
{
if (sender is MenuItem menuItem && menuItem.Parent is ContextMenu contextMenu)
{
var dataGrid = Helpers.TabHelpers.FindDataGridFromContextMenu(contextMenu);
if (dataGrid != null && dataGrid.Items.Count > 0)
{
var dialog = new Microsoft.Win32.SaveFileDialog
{
FileName = $"collection_log_{DateTime.Now:yyyyMMdd_HHmmss}.csv",
DefaultExt = ".csv",
Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*"
};
if (dialog.ShowDialog() == true)
{
var sb = new System.Text.StringBuilder();
var headers = new List<string>();
foreach (var column in dataGrid.Columns)
headers.Add(Helpers.TabHelpers.EscapeCsvField(Helpers.DataGridClipboardBehavior.GetHeaderText(column)));
sb.AppendLine(string.Join(",", headers));
foreach (var item in dataGrid.Items)
{
var values = Helpers.TabHelpers.GetRowValues(dataGrid, item);
sb.AppendLine(string.Join(",", values.Select(v => Helpers.TabHelpers.EscapeCsvField(v))));
}
System.IO.File.WriteAllText(dialog.FileName, sb.ToString());
}
}
}
}

private void Close_Click(object sender, RoutedEventArgs e)
{
Close();
Expand Down
Loading