Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public enum ChartType
GPU,
Mem,
Net,
Dis,
}

public const int ChartHeight = 86;
Expand All @@ -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";

Expand All @@ -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";
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -213,6 +222,7 @@ private static string GetLineStyle(ChartType type)
ChartType.GPU => GPULineStyle,
ChartType.Mem => MemLineStyle,
ChartType.Net => NetLineStyle,
ChartType.Dis => DisLineStyle,
_ => CPULineStyle,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ private void GetNetworkData()
}
}

private void GetDiskData()
{
lock (_systemData.DiskStats)
{
_systemData.DiskStats.GetData();
}
}

private void GetGPUData()
{
lock (_systemData.GPUStats)
Expand Down Expand Up @@ -107,6 +115,13 @@ private void UpdateTimer_Elapsed(object? sender, System.Timers.ElapsedEventArgs
break;
}

case DataType.Disk:
{
// disk
GetDiskData();
break;
}

case DataType.Battery:
{
GetBatteryData();
Expand Down Expand Up @@ -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,
};
Expand All @@ -167,6 +183,14 @@ internal NetworkStats GetNetworkStats()
}
}

internal DiskStats GetDiskStats()
{
lock (_systemData.DiskStats)
{
return _systemData.DiskStats;
}
}

internal GPUStats GetGPUStats()
{
lock (_systemData.GPUStats)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,9 @@ public enum DataType
/// Battery related data.
/// </summary>
Battery,

/// <summary>
/// Disk related data.
/// </summary>
Disk,
}
Original file line number Diff line number Diff line change
@@ -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<string, List<PerformanceCounter>> _diskCounters = new();
private bool _diskCounterReadFailureLogged;

private Dictionary<string, Data> DiskUsages { get; set; } = new();

private Dictionary<string, List<float>> 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<PerformanceCounter> { bytesRead, bytesWritten, diskTime };
_diskCounters.Add(instanceName, instanceCounters);
DiskChartValues.Add(instanceName, new List<float>());
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();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal sealed partial class SystemData

private readonly Lazy<MemoryStats> _memoryStats = new(() => CreateGuarded("Memory.Initialize", static () => new MemoryStats()));
private readonly Lazy<NetworkStats> _networkStats = new(() => CreateGuarded("Network.Initialize", static () => new NetworkStats()));
private readonly Lazy<DiskStats> _diskStats = new(() => CreateGuarded("Disk.Initialize", static () => new DiskStats()));
private readonly Lazy<GPUStats> _gpuStats = new(() => CreateGuarded("GPU.Initialize", static () => new GPUStats()));
private readonly Lazy<CPUStats> _cpuStats = new(() => CreateGuarded("CPU.Initialize", static () => new CPUStats()));
private readonly Lazy<BatteryStats> _batteryStats = new(() => CreateGuarded("Battery.Initialize", static () => new BatteryStats()));
Expand All @@ -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;
Expand Down
Loading