diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/ChartHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/ChartHelper.cs
index bec3398c8b76..4cc56866ef96 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/ChartHelper.cs
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/ChartHelper.cs
@@ -17,6 +17,7 @@ public enum ChartType
GPU,
Mem,
Net,
+ Dis,
}
public const int ChartHeight = 86;
@@ -28,6 +29,7 @@ public enum ChartType
private const string GPULineStyle = "fill:none;stroke:rgb(222,104,242);stroke-width:1";
private const string MemLineStyle = "fill:none;stroke:rgb(92,158,250);stroke-width:1";
private const string NetLineStyle = "fill:none;stroke:rgb(245,98,142);stroke-width:1";
+ private const string DisLineStyle = "fill:none;stroke:rgb(103,153,24);stroke-width:1";
private const string FillStyle = "fill:url(#gradientId);stroke:transparent";
@@ -43,6 +45,9 @@ public enum ChartType
private const string NetBrushStop1Style = "stop-color:rgb(245,98,142);stop-opacity:0.4";
private const string NetBrushStop2Style = "stop-color:rgb(130,0,47);stop-opacity:0.25";
+ private const string DisBrushStop1Style = "stop-color:rgb(103,153,24);stop-opacity:0.4";
+ private const string DisBrushStop2Style = "stop-color:rgb(45,62,15);stop-opacity:0.25";
+
private const string SvgElement = "svg";
private const string RectElement = "rect";
private const string PolylineElement = "polyline";
@@ -174,6 +179,10 @@ private static XElement CreateGradientDefinition(ChartType type)
stop1Style = NetBrushStop1Style;
stop2Style = NetBrushStop2Style;
break;
+ case ChartType.Dis:
+ stop1Style = DisBrushStop1Style;
+ stop2Style = DisBrushStop2Style;
+ break;
case ChartType.CPU:
default:
stop1Style = CPUBrushStop1Style;
@@ -213,6 +222,7 @@ private static string GetLineStyle(ChartType type)
ChartType.GPU => GPULineStyle,
ChartType.Mem => MemLineStyle,
ChartType.Net => NetLineStyle,
+ ChartType.Dis => DisLineStyle,
_ => CPULineStyle,
};
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/DataManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/DataManager.cs
index 8dc80db69826..aefc001de975 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/DataManager.cs
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/DataManager.cs
@@ -45,6 +45,14 @@ private void GetNetworkData()
}
}
+ private void GetDiskData()
+ {
+ lock (_systemData.DiskStats)
+ {
+ _systemData.DiskStats.GetData();
+ }
+ }
+
private void GetGPUData()
{
lock (_systemData.GPUStats)
@@ -107,6 +115,13 @@ private void UpdateTimer_Elapsed(object? sender, System.Timers.ElapsedEventArgs
break;
}
+ case DataType.Disk:
+ {
+ // disk
+ GetDiskData();
+ break;
+ }
+
case DataType.Battery:
{
GetBatteryData();
@@ -146,6 +161,7 @@ private void UpdateTimer_Elapsed(object? sender, System.Timers.ElapsedEventArgs
DataType.GPU => "GPU.FirstUpdate",
DataType.Memory => "Memory.FirstUpdate",
DataType.Network => "Network.FirstUpdate",
+ DataType.Disk => "Disk.FirstUpdate",
DataType.Battery => "Battery.FirstUpdate",
_ => null,
};
@@ -167,6 +183,14 @@ internal NetworkStats GetNetworkStats()
}
}
+ internal DiskStats GetDiskStats()
+ {
+ lock (_systemData.DiskStats)
+ {
+ return _systemData.DiskStats;
+ }
+ }
+
internal GPUStats GetGPUStats()
{
lock (_systemData.GPUStats)
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/DataType.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/DataType.cs
index e9af0f6986ad..700e9ccf4c72 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/DataType.cs
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/DataType.cs
@@ -37,4 +37,9 @@ public enum DataType
/// Battery related data.
///
Battery,
+
+ ///
+ /// Disk related data.
+ ///
+ Disk,
}
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/DiskStats.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/DiskStats.cs
new file mode 100644
index 000000000000..fafd40977e51
--- /dev/null
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/DiskStats.cs
@@ -0,0 +1,192 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Microsoft.CmdPal.Common;
+
+namespace CoreWidgetProvider.Helpers;
+
+internal sealed partial class DiskStats : PerformanceCounterSourceBase, IDisposable
+{
+ private readonly Dictionary> _diskCounters = new();
+ private bool _diskCounterReadFailureLogged;
+
+ private Dictionary DiskUsages { get; set; } = new();
+
+ private Dictionary> DiskChartValues { get; set; } = new();
+
+ public sealed class Data
+ {
+ public float Usage
+ {
+ get; set;
+ }
+
+ public float Read
+ {
+ get; set;
+ }
+
+ public float Written
+ {
+ get; set;
+ }
+ }
+
+ public DiskStats()
+ {
+ InitDiskPerfCounters();
+ }
+
+ private void InitDiskPerfCounters()
+ {
+ try
+ {
+ var perfCounterCategory = CreatePerformanceCounterCategory("PhysicalDisk");
+ if (perfCounterCategory is null)
+ {
+ return;
+ }
+
+ var instanceNames = perfCounterCategory.GetInstanceNames();
+ foreach (var instanceName in instanceNames)
+ {
+ if (string.Equals(instanceName, "_Total", StringComparison.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ try
+ {
+ var bytesRead = CreatePerformanceCounter("PhysicalDisk", "Disk Read Bytes/sec", instanceName, logFailure: false);
+ var bytesWritten = CreatePerformanceCounter("PhysicalDisk", "Disk Write Bytes/sec", instanceName, logFailure: false);
+ var diskTime = CreatePerformanceCounter("PhysicalDisk", "% Disk Time", instanceName, logFailure: false);
+ if (bytesRead is null || bytesWritten is null || diskTime is null)
+ {
+ bytesRead?.Dispose();
+ bytesWritten?.Dispose();
+ diskTime?.Dispose();
+ continue;
+ }
+
+ var instanceCounters = new List { bytesRead, bytesWritten, diskTime };
+ _diskCounters.Add(instanceName, instanceCounters);
+ DiskChartValues.Add(instanceName, new List());
+ DiskUsages.Add(instanceName, new Data());
+ }
+ catch (Exception)
+ {
+ // Skip interfaces whose counters cannot be initialized.
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ CoreLogger.LogError("Failed to initialize disk performance counters.", ex);
+ }
+ }
+
+ public void GetData()
+ {
+ foreach (var diskCounterWithName in _diskCounters)
+ {
+ try
+ {
+ var read = diskCounterWithName.Value[0].NextValue();
+ var written = diskCounterWithName.Value[1].NextValue();
+ var diskTimePercent = diskCounterWithName.Value[2].NextValue();
+ var name = diskCounterWithName.Key;
+
+ DiskUsages[name].Read = read;
+ DiskUsages[name].Written = written;
+ DiskUsages[name].Usage = diskTimePercent / 100f;
+
+ var chartValues = DiskChartValues[name];
+ lock (chartValues)
+ {
+ ChartHelper.AddNextChartValue(diskTimePercent, chartValues);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogFailureOnce(ref _diskCounterReadFailureLogged, "Failed while reading disk performance counters.", ex);
+ }
+ }
+ }
+
+ public string CreateDiskImageUrl(int diskChartIndex)
+ {
+ return ChartHelper.CreateImageUrl(DiskChartValues.ElementAt(diskChartIndex).Value, ChartHelper.ChartType.Dis);
+ }
+
+ public string GetDiskName(int diskIndex)
+ {
+ if (DiskChartValues.Count <= diskIndex)
+ {
+ return string.Empty;
+ }
+
+ return DiskChartValues.ElementAt(diskIndex).Key;
+ }
+
+ public Data GetDiskUsage(int diskIndex)
+ {
+ if (DiskChartValues.Count <= diskIndex)
+ {
+ return new Data();
+ }
+
+ var currDiskName = DiskChartValues.ElementAt(diskIndex).Key;
+ if (!DiskUsages.TryGetValue(currDiskName, out var value))
+ {
+ return new Data();
+ }
+
+ return value;
+ }
+
+ public int GetPrevDiskIndex(int diskIndex)
+ {
+ if (DiskChartValues.Count == 0)
+ {
+ return 0;
+ }
+
+ if (diskIndex == 0)
+ {
+ return DiskChartValues.Count - 1;
+ }
+
+ return diskIndex - 1;
+ }
+
+ public int GetNextDiskIndex(int diskIndex)
+ {
+ if (DiskChartValues.Count == 0)
+ {
+ return 0;
+ }
+
+ if (diskIndex == DiskChartValues.Count - 1)
+ {
+ return 0;
+ }
+
+ return diskIndex + 1;
+ }
+
+ public void Dispose()
+ {
+ foreach (var counterPair in _diskCounters)
+ {
+ foreach (var counter in counterPair.Value)
+ {
+ counter.Dispose();
+ }
+ }
+ }
+}
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/SystemData.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/SystemData.cs
index 55fdbc53dbc5..1abab760d247 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/SystemData.cs
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Helpers/SystemData.cs
@@ -13,6 +13,7 @@ internal sealed partial class SystemData
private readonly Lazy _memoryStats = new(() => CreateGuarded("Memory.Initialize", static () => new MemoryStats()));
private readonly Lazy _networkStats = new(() => CreateGuarded("Network.Initialize", static () => new NetworkStats()));
+ private readonly Lazy _diskStats = new(() => CreateGuarded("Disk.Initialize", static () => new DiskStats()));
private readonly Lazy _gpuStats = new(() => CreateGuarded("GPU.Initialize", static () => new GPUStats()));
private readonly Lazy _cpuStats = new(() => CreateGuarded("CPU.Initialize", static () => new CPUStats()));
private readonly Lazy _batteryStats = new(() => CreateGuarded("Battery.Initialize", static () => new BatteryStats()));
@@ -21,6 +22,8 @@ internal sealed partial class SystemData
public NetworkStats NetworkStats => _networkStats.Value;
+ public DiskStats DiskStats => _diskStats.Value;
+
public GPUStats GPUStats => _gpuStats.Value;
public CPUStats CpuStats => _cpuStats.Value;
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Templates/SystemDiskUsageTemplate.json b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Templates/SystemDiskUsageTemplate.json
new file mode 100644
index 000000000000..80194b3af0af
--- /dev/null
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DevHome/Templates/SystemDiskUsageTemplate.json
@@ -0,0 +1,88 @@
+{
+ "type": "AdaptiveCard",
+ "body": [
+ {
+ "type": "Container",
+ "$when": "${errorMessage != null}",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": "${errorMessage}",
+ "wrap": true,
+ "size": "small"
+ }
+ ],
+ "style": "warning"
+ },
+ {
+ "type": "Container",
+ "$when": "${errorMessage == null}",
+ "items": [
+ {
+ "type": "Image",
+ "url": "${diskGraphUrl}",
+ "height": "${chartHeight}",
+ "width": "${chartWidth}",
+ "$when": "${$host.widgetSize != \"small\"}",
+ "horizontalAlignment": "center"
+ },
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "items": [
+ {
+ "text": "%DiskUsage_Widget_Template/Sent%",
+ "type": "TextBlock",
+ "spacing": "none",
+ "size": "small",
+ "isSubtle": true
+ },
+ {
+ "text": "${diskRead}",
+ "type": "TextBlock",
+ "size": "large",
+ "weight": "bolder"
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "items": [
+ {
+ "text": "%DiskUsage_Widget_Template/Received%",
+ "type": "TextBlock",
+ "spacing": "none",
+ "size": "small",
+ "isSubtle": true,
+ "horizontalAlignment": "right"
+ },
+ {
+ "text": "${diskWrite}",
+ "type": "TextBlock",
+ "size": "large",
+ "weight": "bolder",
+ "horizontalAlignment": "right"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "text": "%DiskUsage_Widget_Template/Disk_Name%",
+ "type": "TextBlock",
+ "size": "small",
+ "isSubtle": true
+ },
+ {
+ "text": "${diskName}",
+ "type": "TextBlock",
+ "size": "medium"
+ }
+ ]
+ }
+ ],
+ "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
+ "version": "1.5"
+}
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DiskSpeedUnit.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DiskSpeedUnit.cs
new file mode 100644
index 000000000000..7fea63be5b6d
--- /dev/null
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/DiskSpeedUnit.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.CmdPal.Ext.PerformanceMonitor;
+
+///
+/// Controls the unit used to display disk read/write speed.
+///
+internal enum DiskSpeedUnit
+{
+ /// Bits per second (Kbps, Mbps, Gbps) — SI decimal prefixes.
+ BitsPerSecond,
+
+ /// Bytes per second (KB/s, MB/s, GB/s) — SI decimal prefixes.
+ BytesPerSecond,
+
+ /// Bytes per second (KiB/s, MiB/s, GiB/s) — IEC binary prefixes.
+ BinaryBytesPerSecond,
+}
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Icons.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Icons.cs
index 02b704d3d434..56fb01896c0f 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Icons.cs
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Icons.cs
@@ -19,6 +19,10 @@ internal static class Icons
internal static IconInfo HardDriveIcon => new("\uEDA2"); // HardDrive icon
+ internal static IconInfo FileReadIcon => new("\uE890"); // FileRead icon
+
+ internal static IconInfo FileWriteIcon => new("\uE70F"); // FileWrite icon
+
internal static IconInfo NetworkIcon => new("\uEC05"); // Network icon
internal static IconInfo NetworkUpIcon => new("\uE74A"); // Up arrow icon
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Microsoft.CmdPal.Ext.PerformanceMonitor.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Microsoft.CmdPal.Ext.PerformanceMonitor.csproj
index 9ec357605eaf..319296f5406e 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Microsoft.CmdPal.Ext.PerformanceMonitor.csproj
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Microsoft.CmdPal.Ext.PerformanceMonitor.csproj
@@ -50,6 +50,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceMonitorCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceMonitorCommandsProvider.cs
index 18864c1f8798..a3973043b0e0 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceMonitorCommandsProvider.cs
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceMonitorCommandsProvider.cs
@@ -29,6 +29,7 @@ public partial class PerformanceMonitorCommandsProvider : CommandProvider
private PerformanceWidgetsPage? _bandPage;
private PerformanceWidgetsPage? _cpuBandPage;
private PerformanceWidgetsPage? _memoryBandPage;
+ private PerformanceWidgetsPage? _diskBandPage;
private PerformanceWidgetsPage? _networkBandPage;
private PerformanceWidgetsPage? _gpuBandPage;
private PerformanceWidgetsPage? _batteryBandPage;
@@ -138,6 +139,7 @@ private void SetEnabledState()
_cpuBandPage = new PerformanceWidgetsPage(_settingsManager, true, PerformanceMetricKind.Cpu);
_memoryBandPage = new PerformanceWidgetsPage(_settingsManager, true, PerformanceMetricKind.Memory);
_networkBandPage = new PerformanceWidgetsPage(_settingsManager, true, PerformanceMetricKind.Network);
+ _diskBandPage = new PerformanceWidgetsPage(_settingsManager, true, PerformanceMetricKind.Disk);
_gpuBandPage = new PerformanceWidgetsPage(_settingsManager, true, PerformanceMetricKind.Gpu);
_batteryBandPage = new PerformanceWidgetsPage(_settingsManager, true, PerformanceMetricKind.Battery);
@@ -146,6 +148,7 @@ private void SetEnabledState()
new CommandItem(_cpuBandPage) { Title = Resources.GetResource("CPU_Usage_Title") },
new CommandItem(_memoryBandPage) { Title = Resources.GetResource("Memory_Usage_Title") },
new CommandItem(_networkBandPage) { Title = Resources.GetResource("Network_Usage_Title") },
+ new CommandItem(_diskBandPage) { Title = Resources.GetResource("Disk_Usage_Title") },
new CommandItem(_gpuBandPage) { Title = Resources.GetResource("GPU_Usage_Title") }
];
var batteryStats = new BatteryStats();
@@ -182,6 +185,9 @@ private void DisposeActivePages()
_memoryBandPage?.Dispose();
_memoryBandPage = null;
+ _diskBandPage?.Dispose();
+ _diskBandPage = null;
+
_networkBandPage?.Dispose();
_networkBandPage = null;
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceWidgetsPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceWidgetsPage.cs
index e1394a3e38c2..6e8a76d9ec48 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceWidgetsPage.cs
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceWidgetsPage.cs
@@ -31,6 +31,7 @@ internal enum PerformanceMetricKind
Cpu,
Memory,
Network,
+ Disk,
Gpu,
Battery,
}
@@ -59,6 +60,7 @@ internal sealed partial class PerformanceWidgetsPage : OnLoadStaticListPage, IDi
PerformanceMetricKind.Cpu => Icons.CpuIcon,
PerformanceMetricKind.Memory => Icons.MemoryIcon,
PerformanceMetricKind.Network => Icons.NetworkIcon,
+ PerformanceMetricKind.Disk => Icons.HardDriveIcon,
PerformanceMetricKind.Gpu => Icons.GpuIcon,
PerformanceMetricKind.Battery => _batteryPage?.CurrentIcon ?? Icons.BatteryIcon,
_ => Icons.PerformanceMonitorIcon,
@@ -74,6 +76,9 @@ internal sealed partial class PerformanceWidgetsPage : OnLoadStaticListPage, IDi
private readonly SystemMemoryUsageWidgetPage? _memoryPage;
private readonly ListItem? _memoryItem;
+ private readonly SystemDiskUsageWidgetPage? _diskPage;
+ private readonly ListItem? _diskItem;
+
private readonly SystemNetworkUsageWidgetPage? _networkPage;
private readonly ListItem? _networkItem;
@@ -89,6 +94,12 @@ internal sealed partial class PerformanceWidgetsPage : OnLoadStaticListPage, IDi
private string _networkUpSpeed = string.Empty;
private string _networkDownSpeed = string.Empty;
+ // For bands, we want two bands, one for read and one for write
+ private ListItem? _diskReadItem;
+ private ListItem? _diskWriteItem;
+ private string _diskReadSpeed = string.Empty;
+ private string _diskWriteSpeed = string.Empty;
+
public PerformanceWidgetsPage(SettingsManager settingsManager, bool isBandPage = false, PerformanceMetricKind? singleMetric = null)
{
_isBandPage = isBandPage;
@@ -163,6 +174,26 @@ public PerformanceWidgetsPage(SettingsManager settingsManager, bool isBandPage =
};
}
+ if (IncludesMetric(PerformanceMetricKind.Disk))
+ {
+ _diskPage = new SystemDiskUsageWidgetPage(settingsManager);
+ _diskItem = new ListItem(_diskPage)
+ {
+ Title = _diskPage.GetItemTitle(isBandPage),
+ MoreCommands = _diskPage.Commands,
+ };
+
+ _diskPage.Updated += (s, e) =>
+ {
+ _diskItem.Title = _diskPage.GetItemTitle(isBandPage);
+ _diskReadSpeed = _diskPage.GetReadSpeed();
+ _diskWriteSpeed = _diskPage.GetWriteSpeed();
+ _diskReadItem?.Title = $"{_diskReadSpeed}";
+ _diskWriteItem?.Title = $"{_diskWriteSpeed}";
+ RaiseItemsChanged();
+ };
+ }
+
if (IncludesMetric(PerformanceMetricKind.Gpu))
{
_gpuPage = new SystemGPUUsageWidgetPage();
@@ -217,6 +248,11 @@ public PerformanceWidgetsPage(SettingsManager settingsManager, bool isBandPage =
_networkItem.Subtitle = Resources.GetResource("Network_Usage_Subtitle");
}
+ if (_diskItem is not null)
+ {
+ _diskItem.Subtitle = Resources.GetResource("Disk_Usage_Subtitle");
+ }
+
if (_gpuItem is not null)
{
_gpuItem.Subtitle = Resources.GetResource("GPU_Usage_Subtitle");
@@ -234,6 +270,7 @@ protected override void Loaded()
_cpuPage?.PushActivate();
_memoryPage?.PushActivate();
_networkPage?.PushActivate();
+ _diskPage?.PushActivate();
_gpuPage?.PushActivate();
_batteryPage?.PushActivate();
}
@@ -243,6 +280,7 @@ protected override void Unloaded()
_cpuPage?.PopActivate();
_memoryPage?.PopActivate();
_networkPage?.PopActivate();
+ _diskPage?.PopActivate();
_gpuPage?.PopActivate();
_batteryPage?.PopActivate();
}
@@ -257,6 +295,7 @@ public override IListItem[] GetItems()
PerformanceMetricKind.Cpu => new IListItem[] { _cpuItem! },
PerformanceMetricKind.Memory => new IListItem[] { _memoryItem! },
PerformanceMetricKind.Network => new IListItem[] { _networkItem! },
+ PerformanceMetricKind.Disk => new IListItem[] { _diskItem! },
PerformanceMetricKind.Gpu => new IListItem[] { _gpuItem! },
PerformanceMetricKind.Battery => new IListItem[] { _batteryItem! },
_ => Array.Empty(),
@@ -267,14 +306,46 @@ public override IListItem[] GetItems()
{
// TODO add details
return _batteryItem is not null
- ? new[] { _cpuItem!, _memoryItem!, _networkItem!, _gpuItem!, _batteryItem! }
- : new[] { _cpuItem!, _memoryItem!, _networkItem!, _gpuItem! };
+ ? new[] { _cpuItem!, _memoryItem!, _networkItem!, _diskItem!, _gpuItem!, _batteryItem! }
+ : new[] { _cpuItem!, _memoryItem!, _networkItem!, _diskItem!, _gpuItem! };
}
else
{
+ _networkUpItem = new ListItem(_networkPage!)
+ {
+ Title = $"{_networkUpSpeed}",
+ Subtitle = Resources.GetResource("Network_Send_Subtitle"),
+ Icon = Icons.NetworkUpIcon,
+ MoreCommands = _networkPage!.Commands,
+ };
+
+ _networkDownItem = new ListItem(_networkPage!)
+ {
+ Title = $"{_networkDownSpeed}",
+ Subtitle = Resources.GetResource("Network_Receive_Subtitle"),
+ Icon = Icons.NetworkDownIcon,
+ MoreCommands = _networkPage!.Commands,
+ };
+
+ _diskReadItem = new ListItem(_diskPage!)
+ {
+ Title = $"{_diskReadSpeed}",
+ Subtitle = Resources.GetResource("Disk_Read_Subtitle"),
+ Icon = Icons.FileReadIcon,
+ MoreCommands = _diskPage!.Commands,
+ };
+
+ _diskWriteItem = new ListItem(_diskPage!)
+ {
+ Title = $"{_diskWriteSpeed}",
+ Subtitle = Resources.GetResource("Disk_Write_Subtitle"),
+ Icon = Icons.FileWriteIcon,
+ MoreCommands = _diskPage!.Commands,
+ };
+
return _batteryItem is not null
- ? new[] { _cpuItem!, _memoryItem!, _networkUpItem!, _networkDownItem!, _gpuItem!, _batteryItem! }
- : new[] { _cpuItem!, _memoryItem!, _networkUpItem!, _networkDownItem!, _gpuItem! };
+ ? new[] { _cpuItem!, _memoryItem!, _networkUpItem!, _networkDownItem!, _diskReadItem!, _diskWriteItem!, _gpuItem!, _batteryItem! }
+ : new[] { _cpuItem!, _memoryItem!, _networkUpItem!, _networkDownItem!, _diskReadItem!, _diskWriteItem!, _gpuItem! };
}
}
@@ -283,6 +354,7 @@ public void Dispose()
_cpuPage?.Dispose();
_memoryPage?.Dispose();
_networkPage?.Dispose();
+ _diskPage?.Dispose();
_gpuPage?.Dispose();
_batteryPage?.Dispose();
}
@@ -299,6 +371,7 @@ private static string GetMetricSuffix(PerformanceMetricKind metric)
PerformanceMetricKind.Cpu => "cpu",
PerformanceMetricKind.Memory => "memory",
PerformanceMetricKind.Network => "network",
+ PerformanceMetricKind.Disk => "disk",
PerformanceMetricKind.Gpu => "gpu",
PerformanceMetricKind.Battery => "battery",
_ => "unknown",
@@ -661,56 +734,56 @@ public void Dispose()
}
}
-internal sealed partial class SystemNetworkUsageWidgetPage : WidgetPage, IDisposable
+internal sealed partial class SystemDiskUsageWidgetPage : WidgetPage, IDisposable
{
- public override string Id => "com.microsoft.cmdpal.network_widget";
+ public override string Id => "com.microsoft.cmdpal.disk_widget";
- public override string Title => Resources.GetResource("Network_Usage_Title");
+ public override string Title => Resources.GetResource("Disk_Usage_Title");
- public override IconInfo Icon => Icons.NetworkIcon;
+ public override IconInfo Icon => Icons.HardDriveIcon;
private readonly DataManager _dataManager;
private readonly SettingsManager _settingsManager;
- private int _networkIndex;
+ private int _diskIndex;
- public SystemNetworkUsageWidgetPage(SettingsManager settingsManager)
+ public SystemDiskUsageWidgetPage(SettingsManager settingsManager)
{
_settingsManager = settingsManager;
- _dataManager = new(DataType.Network, () => UpdateWidget());
+ _dataManager = new(DataType.Disk, () => UpdateWidget());
Commands = [
- new CommandContextItem(new PrevNetworkCommand(this) { Name = Resources.GetResource("Previous_Network_Title") }),
- new CommandContextItem(new NextNetworkCommand(this) { Name = Resources.GetResource("Next_Network_Title") }),
+ new CommandContextItem(new PrevDiskCommand(this) { Name = Resources.GetResource("Previous_Disk_Title") }),
+ new CommandContextItem(new NextDiskCommand(this) { Name = Resources.GetResource("Next_Disk_Title") }),
new CommandContextItem(OpenTaskManagerCommand.Instance),
];
}
protected override void LoadContentData()
{
- // CoreLogger.LogDebug("Getting Network stats");
+ // CoreLogger.LogDebug("Getting Disk stats");
try
{
ContentData.Clear();
var timer = Stopwatch.StartNew();
- var currentData = _dataManager.GetNetworkStats();
+ var currentData = _dataManager.GetDiskStats();
var dataDuration = timer.ElapsedMilliseconds;
- var netName = currentData.GetNetworkName(_networkIndex);
- var networkStats = currentData.GetNetworkUsage(_networkIndex);
+ var diskName = currentData.GetDiskName(_diskIndex);
+ var diskStats = currentData.GetDiskUsage(_diskIndex);
- ContentData["networkUsage"] = FloatToPercentString(networkStats.Usage);
- ContentData["netSent"] = SpeedToString(networkStats.Sent);
- ContentData["netReceived"] = SpeedToString(networkStats.Received);
- ContentData["networkName"] = netName;
- ContentData["netGraphUrl"] = currentData.CreateNetImageUrl(_networkIndex);
+ ContentData["diskUsage"] = FloatToPercentString(diskStats.Usage);
+ ContentData["diskRead"] = SpeedToString(diskStats.Read);
+ ContentData["diskWrite"] = SpeedToString(diskStats.Written);
+ ContentData["diskName"] = diskName;
+ ContentData["diskGraphUrl"] = currentData.CreateDiskImageUrl(_diskIndex);
ContentData["chartHeight"] = ChartHelper.ChartHeight + "px";
ContentData["chartWidth"] = ChartHelper.ChartWidth + "px";
var contentDuration = timer.ElapsedMilliseconds - dataDuration;
- // CoreLogger.LogDebug($"Network stats retrieved in {dataDuration} ms, content prepared in {contentDuration} ms. (Total {timer.ElapsedMilliseconds} ms)");
+ // CoreLogger.LogDebug($"Disk stats retrieved in {dataDuration} ms, content prepared in {contentDuration} ms. (Total {timer.ElapsedMilliseconds} ms)");
}
catch (Exception e)
{
@@ -724,30 +797,30 @@ protected override string GetTemplatePath(WidgetPageState page)
{
return page switch
{
- WidgetPageState.Content => @"DevHome\Templates\SystemNetworkUsageTemplate.json",
- WidgetPageState.Loading => @"DevHome\Templates\SystemNetworkUsageTemplate.json",
+ WidgetPageState.Content => @"DevHome\Templates\SystemDiskUsageTemplate.json",
+ WidgetPageState.Loading => @"DevHome\Templates\SystemDiskUsageTemplate.json",
_ => throw new NotImplementedException(),
};
}
public string GetItemTitle(bool isBandPage)
{
- if (ContentData.TryGetValue("networkName", out var name) && ContentData.TryGetValue("networkUsage", out var usage))
+ if (ContentData.TryGetValue("diskName", out var name) && ContentData.TryGetValue("diskUsage", out var usage))
{
- return isBandPage ? usage : string.Format(CultureInfo.CurrentCulture, Resources.GetResource("Network_Usage_Label"), name, usage);
+ return isBandPage ? usage : string.Format(CultureInfo.CurrentCulture, Resources.GetResource("Disk_Usage_Label"), name, usage);
}
else
{
- return isBandPage ? Resources.GetResource("Network_Usage_Unknown") : Resources.GetResource("Network_Usage_Unknown_Label");
+ return isBandPage ? Resources.GetResource("Disk_Usage_Unknown") : Resources.GetResource("Disk_Usage_Unknown_Label");
}
}
- // up/down speed is always used for bands
- public string GetUpSpeed()
+ // read/write speed is always used for bands
+ public string GetReadSpeed()
{
- if (ContentData.TryGetValue("netSent", out var upSpeed))
+ if (ContentData.TryGetValue("diskRead", out var readSpeed))
{
- return upSpeed;
+ return readSpeed;
}
else
{
@@ -755,11 +828,11 @@ public string GetUpSpeed()
}
}
- public string GetDownSpeed()
+ public string GetWriteSpeed()
{
- if (ContentData.TryGetValue("netReceived", out var downSpeed))
+ if (ContentData.TryGetValue("diskWrite", out var writeSpeed))
{
- return downSpeed;
+ return writeSpeed;
}
else
{
@@ -769,123 +842,204 @@ public string GetDownSpeed()
private string SpeedToString(float bytesPerSec)
{
- return _settingsManager.NetworkSpeedUnit switch
+ return _settingsManager.DiskSpeedUnit switch
{
- NetworkSpeedUnit.BytesPerSecond => FormatAsBytesPerSecString(bytesPerSec),
- NetworkSpeedUnit.BinaryBytesPerSecond => FormatAsBinaryBytesPerSecString(bytesPerSec),
- _ => FormatAsBitsPerSecString(bytesPerSec),
+ DiskSpeedUnit.BytesPerSecond => FormatIncomingData.AsBytesPerSecString(bytesPerSec),
+ DiskSpeedUnit.BinaryBytesPerSecond => FormatIncomingData.AsBinaryBytesPerSecString(bytesPerSec),
+ _ => FormatIncomingData.AsBitsPerSecString(bytesPerSec),
};
}
- private static string FormatAsBitsPerSecString(float value)
+ internal override void PushActivate()
{
- // Bytes to bits
- value *= 8;
+ base.PushActivate();
+ if (IsActive)
+ {
+ _dataManager.Start();
+ }
+ }
- // bits to Kbits
- value /= 1024;
- if (value < 1024)
+ internal override void PopActivate()
+ {
+ base.PopActivate();
+ if (!IsActive)
{
- if (value < 100)
- {
- return string.Format(CultureInfo.InvariantCulture, "{0:0.0} Kbps", value);
- }
+ _dataManager.Stop();
+ }
+ }
- return string.Format(CultureInfo.InvariantCulture, "{0:0} Kbps", value);
+ private void HandlePrevDisk()
+ {
+ _diskIndex = _dataManager.GetDiskStats().GetPrevDiskIndex(_diskIndex);
+ UpdateWidget();
+ }
+
+ private void HandleNextDisk()
+ {
+ _diskIndex = _dataManager.GetDiskStats().GetNextDiskIndex(_diskIndex);
+ UpdateWidget();
+ }
+
+ public void Dispose()
+ {
+ _dataManager.Dispose();
+ }
+
+ private sealed partial class PrevDiskCommand : InvokableCommand
+ {
+ private readonly SystemDiskUsageWidgetPage _page;
+
+ public PrevDiskCommand(SystemDiskUsageWidgetPage page)
+ {
+ _page = page;
}
- // Kbits to Mbits
- value /= 1024;
- if (value < 1024)
+ public override string Id => "com.microsoft.cmdpal.disk_widget.prev";
+
+ public override IconInfo Icon => Icons.NavigateBackwardIcon;
+
+ public override ICommandResult Invoke()
{
- if (value < 100)
- {
- return string.Format(CultureInfo.InvariantCulture, "{0:0.0} Mbps", value);
- }
+ _page.HandlePrevDisk();
+ return CommandResult.KeepOpen();
+ }
+ }
- return string.Format(CultureInfo.InvariantCulture, "{0:0} Mbps", value);
+ private sealed partial class NextDiskCommand : InvokableCommand
+ {
+ private readonly SystemDiskUsageWidgetPage _page;
+
+ public NextDiskCommand(SystemDiskUsageWidgetPage page)
+ {
+ _page = page;
}
- // Mbits to Gbits
- value /= 1024;
- if (value < 100)
+ public override string Id => "com.microsoft.cmdpal.disk_widget.next";
+
+ public override IconInfo Icon => Icons.NavigateForwardIcon;
+
+ public override ICommandResult Invoke()
{
- return string.Format(CultureInfo.InvariantCulture, "{0:0.0} Gbps", value);
+ _page.HandleNextDisk();
+ return CommandResult.KeepOpen();
}
+ }
+}
- return string.Format(CultureInfo.InvariantCulture, "{0:0} Gbps", value);
+internal sealed partial class SystemNetworkUsageWidgetPage : WidgetPage, IDisposable
+{
+ public override string Id => "com.microsoft.cmdpal.network_widget";
+
+ public override string Title => Resources.GetResource("Network_Usage_Title");
+
+ public override IconInfo Icon => Icons.NetworkIcon;
+
+ private readonly DataManager _dataManager;
+ private readonly SettingsManager _settingsManager;
+ private int _networkIndex;
+
+ public SystemNetworkUsageWidgetPage(SettingsManager settingsManager)
+ {
+ _settingsManager = settingsManager;
+ _dataManager = new(DataType.Network, () => UpdateWidget());
+ Commands = [
+ new CommandContextItem(new PrevNetworkCommand(this) { Name = Resources.GetResource("Previous_Network_Title") }),
+ new CommandContextItem(new NextNetworkCommand(this) { Name = Resources.GetResource("Next_Network_Title") }),
+ new CommandContextItem(OpenTaskManagerCommand.Instance),
+ ];
}
- private static string FormatAsBytesPerSecString(float value)
+ protected override void LoadContentData()
{
- // Bytes to KB
- value /= 1024;
- if (value < 1024)
+ // CoreLogger.LogDebug("Getting Network stats");
+ try
{
- if (value < 100)
- {
- return string.Format(CultureInfo.InvariantCulture, "{0:0.0} KB/s", value);
- }
+ ContentData.Clear();
- return string.Format(CultureInfo.InvariantCulture, "{0:0} KB/s", value);
- }
+ var timer = Stopwatch.StartNew();
- // KB to MB
- value /= 1024;
- if (value < 1024)
- {
- if (value < 100)
- {
- return string.Format(CultureInfo.InvariantCulture, "{0:0.0} MB/s", value);
- }
+ var currentData = _dataManager.GetNetworkStats();
- return string.Format(CultureInfo.InvariantCulture, "{0:0} MB/s", value);
- }
+ var dataDuration = timer.ElapsedMilliseconds;
- // MB to GB
- value /= 1024;
- if (value < 100)
+ var netName = currentData.GetNetworkName(_networkIndex);
+ var networkStats = currentData.GetNetworkUsage(_networkIndex);
+
+ ContentData["networkUsage"] = FloatToPercentString(networkStats.Usage);
+ ContentData["netSent"] = SpeedToString(networkStats.Sent);
+ ContentData["netReceived"] = SpeedToString(networkStats.Received);
+ ContentData["networkName"] = netName;
+ ContentData["netGraphUrl"] = currentData.CreateNetImageUrl(_networkIndex);
+ ContentData["chartHeight"] = ChartHelper.ChartHeight + "px";
+ ContentData["chartWidth"] = ChartHelper.ChartWidth + "px";
+
+ var contentDuration = timer.ElapsedMilliseconds - dataDuration;
+
+ // CoreLogger.LogDebug($"Network stats retrieved in {dataDuration} ms, content prepared in {contentDuration} ms. (Total {timer.ElapsedMilliseconds} ms)");
+ }
+ catch (Exception e)
{
- return string.Format(CultureInfo.InvariantCulture, "{0:0.0} GB/s", value);
+ ContentData.Clear();
+ ContentData["errorMessage"] = e.Message;
+ return;
}
-
- return string.Format(CultureInfo.InvariantCulture, "{0:0} GB/s", value);
}
- private static string FormatAsBinaryBytesPerSecString(float value)
+ protected override string GetTemplatePath(WidgetPageState page)
{
- // Bytes to KiB
- value /= 1024;
- if (value < 1024)
+ return page switch
{
- if (value < 100)
- {
- return string.Format(CultureInfo.InvariantCulture, "{0:0.0} KiB/s", value);
- }
+ WidgetPageState.Content => @"DevHome\Templates\SystemNetworkUsageTemplate.json",
+ WidgetPageState.Loading => @"DevHome\Templates\SystemNetworkUsageTemplate.json",
+ _ => throw new NotImplementedException(),
+ };
+ }
- return string.Format(CultureInfo.InvariantCulture, "{0:0} KiB/s", value);
+ public string GetItemTitle(bool isBandPage)
+ {
+ if (ContentData.TryGetValue("networkName", out var name) && ContentData.TryGetValue("networkUsage", out var usage))
+ {
+ return isBandPage ? usage : string.Format(CultureInfo.CurrentCulture, Resources.GetResource("Network_Usage_Label"), name, usage);
}
-
- // KiB to MiB
- value /= 1024;
- if (value < 1024)
+ else
{
- if (value < 100)
- {
- return string.Format(CultureInfo.InvariantCulture, "{0:0.0} MiB/s", value);
- }
+ return isBandPage ? Resources.GetResource("Network_Usage_Unknown") : Resources.GetResource("Network_Usage_Unknown_Label");
+ }
+ }
- return string.Format(CultureInfo.InvariantCulture, "{0:0} MiB/s", value);
+ // up/down speed is always used for bands
+ public string GetUpSpeed()
+ {
+ if (ContentData.TryGetValue("netSent", out var upSpeed))
+ {
+ return upSpeed;
}
+ else
+ {
+ return "???";
+ }
+ }
- // MiB to GiB
- value /= 1024;
- if (value < 100)
+ public string GetDownSpeed()
+ {
+ if (ContentData.TryGetValue("netReceived", out var downSpeed))
{
- return string.Format(CultureInfo.InvariantCulture, "{0:0.0} GiB/s", value);
+ return downSpeed;
+ }
+ else
+ {
+ return "???";
}
+ }
- return string.Format(CultureInfo.InvariantCulture, "{0:0} GiB/s", value);
+ private string SpeedToString(float bytesPerSec)
+ {
+ return _settingsManager.NetworkSpeedUnit switch
+ {
+ NetworkSpeedUnit.BytesPerSecond => FormatIncomingData.AsBytesPerSecString(bytesPerSec),
+ NetworkSpeedUnit.BinaryBytesPerSecond => FormatIncomingData.AsBinaryBytesPerSecString(bytesPerSec),
+ _ => FormatIncomingData.AsBitsPerSecString(bytesPerSec),
+ };
}
internal override void PushActivate()
@@ -1304,3 +1458,117 @@ public override ICommandResult Invoke()
return CommandResult.Hide();
}
}
+
+internal static class FormatIncomingData
+{
+ public static string AsBitsPerSecString(float value)
+ {
+ // Bytes to bits
+ value *= 8;
+
+ // bits to Kbits
+ value /= 1024;
+ if (value < 1024)
+ {
+ if (value < 100)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0:0.0} Kbps", value);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "{0:0} Kbps", value);
+ }
+
+ // Kbits to Mbits
+ value /= 1024;
+ if (value < 1024)
+ {
+ if (value < 100)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0:0.0} Mbps", value);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "{0:0} Mbps", value);
+ }
+
+ // Mbits to Gbits
+ value /= 1024;
+ if (value < 100)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0:0.0} Gbps", value);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "{0:0} Gbps", value);
+ }
+
+ public static string AsBytesPerSecString(float value)
+ {
+ // Bytes to KB
+ value /= 1024;
+ if (value < 1024)
+ {
+ if (value < 100)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0:0.0} KB/s", value);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "{0:0} KB/s", value);
+ }
+
+ // KB to MB
+ value /= 1024;
+ if (value < 1024)
+ {
+ if (value < 100)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0:0.0} MB/s", value);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "{0:0} MB/s", value);
+ }
+
+ // MB to GB
+ value /= 1024;
+ if (value < 100)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0:0.0} GB/s", value);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "{0:0} GB/s", value);
+ }
+
+ public static string AsBinaryBytesPerSecString(float value)
+ {
+ // Bytes to KiB
+ value /= 1024;
+ if (value < 1024)
+ {
+ if (value < 100)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0:0.0} KiB/s", value);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "{0:0} KiB/s", value);
+ }
+
+ // KiB to MiB
+ value /= 1024;
+ if (value < 1024)
+ {
+ if (value < 100)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0:0.0} MiB/s", value);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "{0:0} MiB/s", value);
+ }
+
+ // MiB to GiB
+ value /= 1024;
+ if (value < 100)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0:0.0} GiB/s", value);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "{0:0} GiB/s", value);
+ }
+}
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/SettingsManager.cs
index fd975a65e7d0..2d6eedf7fdf1 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/SettingsManager.cs
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/SettingsManager.cs
@@ -30,6 +30,21 @@ internal sealed class SettingsManager : JsonSettingsManager
? unit
: NetworkSpeedUnit.BitsPerSecond;
+ private readonly ChoiceSetSetting _diskSpeedUnit = new(
+ Namespaced(nameof(DiskSpeedUnit)),
+ Resources.GetResource("Disk_Speed_Unit_Setting_Title"),
+ Resources.GetResource("Disk_Speed_Unit_Setting_Description"),
+ [
+ new ChoiceSetSetting.Choice(Resources.GetResource("Disk_Speed_Unit_BitsPerSec"), DiskSpeedUnit.BitsPerSecond.ToString("G")),
+ new ChoiceSetSetting.Choice(Resources.GetResource("Disk_Speed_Unit_BytesPerSec"), DiskSpeedUnit.BytesPerSecond.ToString("G")),
+ new ChoiceSetSetting.Choice(Resources.GetResource("Disk_Speed_Unit_BinaryBytesPerSec"), DiskSpeedUnit.BinaryBytesPerSecond.ToString("G")),
+ ]);
+
+ public DiskSpeedUnit DiskSpeedUnit =>
+ Enum.TryParse(_diskSpeedUnit.Value, out var unit)
+ ? unit
+ : DiskSpeedUnit.BytesPerSecond;
+
private static string SettingsJsonPath()
{
var directory = Utilities.BaseSettingsPath("Microsoft.CmdPal");
@@ -42,6 +57,7 @@ public SettingsManager()
FilePath = SettingsJsonPath();
Settings.Add(_networkSpeedUnit);
+ Settings.Add(_diskSpeedUnit);
LoadSettings();
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Strings/en-US/Resources.resw b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Strings/en-US/Resources.resw
index e6fa2862a5df..d8c3a7ab77c5 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Strings/en-US/Resources.resw
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Strings/en-US/Resources.resw
@@ -1,5 +1,64 @@
+
@@ -135,6 +194,24 @@
Ethernet
+
+ Utilization
+
+
+ Read
+
+
+ Write
+
+
+ Name
+
+
+ Previous disk
+
+
+ Next disk
+
Utilization
@@ -183,6 +260,9 @@
Network
+
+ Disk
+
GPU
@@ -257,6 +337,19 @@
Network Usage: ???
+
+ Disk Usage
+
+
+ Disk ({0}): {1}
+ {0} is the disk interface name, {1} is the usage percentage
+
+
+ ???
+
+
+ Disk Usage: ???
+
GPU Usage
@@ -331,6 +424,12 @@
Receive
+
+ Read
+
+
+ Write
+
Network speed unit
@@ -346,4 +445,19 @@
Binary bytes per second (KiB/s, MiB/s, GiB/s)
-
+
+ Disk speed unit
+
+
+ Choose the unit used to display disk transfer speed
+
+
+ Bits per second (Kbps, Mbps, Gbps)
+
+
+ Bytes per second (KB/s, MB/s, GB/s)
+
+
+ Binary bytes per second (KiB/s, MiB/s, GiB/s)
+
+
\ No newline at end of file