在线预览:http://2019.qingshanboke.com/Home/performance
一、背景介绍
在.net平台开发,网站部署环境都是windows+IIS,很想知道服务器运行时,相关的各种参数。比如:CPU利用率,磁盘读写速度,网络带宽占用,网站链接数等等。能够有图表的方式显示就更好了。
用过阿里云的云监控的童鞋,对下面这个界面肯定不会陌生:
这是怎么实现的呢?经过一番查找,原来这些数据可以通过读取Windows性能计数器读取到,再将数据做出图表,也可以实现类似的效果。
二、实现思路
1.利用C#读取windows性能计数器数据。
2.将读取到的数据定期写入数据。
3.根据第2步采集的数据,利用百度EChart制作数据图表。
三、实施步骤
1.要读取windows性能计数器数据,首先得了解性能计数器是如何存储数据的。每个计数器都是由 分类名称(CategoryName),计数器名称(CounterName),实例名(InstanceName)。
public PerformanceCounter( string categoryName, string counterName, string instanceName )
可以通过控制面板打开性能监视器:
读取方式:
以读取cpu使用率为例:
var counter=PerformanceCounter("Processor", "% Processor Time", "_Total");
counter.NextValue();
即可取到当前运行值。
2.将读取性能计数器的方法可以封装成一个辅助类:
public class SysParams { public string NodeName { get; set; } public float CPUProcessorTime { get; set; } public float CPUPrivilegedTime { get; set; } public float CPUInterruptTime { get; set; } public float CPUDPCTime { get; set; } public float MEMAvailable { get; set; } public float MEMCommited { get; set; } public float MEMCommitLimit { get; set; } public float MEMCommitedPerc { get; set; } public float MEMPoolPaged { get; set; } publicfloat MEMPoolNonPaged { get; set; } public float MEMCached { get; set; } public float PageFile { get; set; } public float ProcessorQueueLengh { get; set; } public float DISCQueueLengh { get; set; } public float DISKRead {get; set;} public float DISKWrite { get; set; } public float DISKAverageTimeRead { get; set; } public float DISKAverageTimeWrite { get; set; } public float DISKTime { get; set; } public float HANDLECountCounter { get; set; } public float THREADCount { get; set; } public int CONTENTSwitches { get; set; } public int SYSTEMCalls { get; set; } public float NetTrafficSend { get; set; } public float NetTrafficReceive { get; set; } public DateTime SamplingTime { get; set; } private PerformanceCounter cpuProcessorTime = new PerformanceCounter("Processor", "% Processor Time", "_Total"); private PerformanceCounter cpuPrivilegedTime = new PerformanceCounter("Processor", "% Privileged Time", "_Total"); private PerformanceCounter cpuInterruptTime = new PerformanceCounter("Processor", "% Interrupt Time", "_Total"); private PerformanceCounter cpuDPCTime = new PerformanceCounter("Processor", "% DPC Time", "_Total"); private PerformanceCounter memAvailable = new PerformanceCounter("Memory", "Available MBytes", null); private PerformanceCounter memCommited = new PerformanceCounter("Memory", "Committed Bytes", null); private PerformanceCounter memCommitLimit = new PerformanceCounter("Memory", "Commit Limit", null); private PerformanceCounter memCommitedPerc = new PerformanceCounter("Memory", "% Committed Bytes In Use", null); private PerformanceCounter memPollPaged = new PerformanceCounter("Memory", "Pool Paged Bytes", null); private PerformanceCounter memPollNonPaged = new PerformanceCounter("Memory", "Pool Nonpaged Bytes", null); private PerformanceCounter memCached = new PerformanceCounter("Memory", "Cache Bytes", null); private PerformanceCounter pageFile = new PerformanceCounter("Paging File", "% Usage", "_Total"); private PerformanceCounter processorQueueLengh = new PerformanceCounter("System", "Processor Queue Length", null); private PerformanceCounter diskQueueLengh = new PerformanceCounter("PhysicalDisk", "Avg. Disk Queue Length", "_Total"); private PerformanceCounter diskRead = new PerformanceCounter("PhysicalDisk", "Disk Read Bytes/sec", "_Total"); private PerformanceCounter diskWrite = new PerformanceCounter("PhysicalDisk", "Disk Write Bytes/sec", "_Total"); private PerformanceCounter diskAverageTimeRead = new PerformanceCounter("PhysicalDisk", "Avg. Disk sec/Read", "_Total"); private PerformanceCounter diskAverageTimeWrite = new PerformanceCounter("PhysicalDisk", "Avg. Disk sec/Write", "_Total"); private PerformanceCounter diskTime = new PerformanceCounter("PhysicalDisk", "% Disk Time", "_Total"); private PerformanceCounter handleCountCounter = new PerformanceCounter("Process", "Handle Count", "_Total"); private PerformanceCounter threadCount = new PerformanceCounter("Process", "Thread Count", "_Total"); private PerformanceCounter contentSwitches = new PerformanceCounter("System", "Context Switches/sec", null); private PerformanceCounter systemCalls = new PerformanceCounter("System", "System Calls/sec", null); private PerformanceCounterCategory performanceNetCounterCategory; private PerformanceCounter[] trafficSentCounters; private PerformanceCounter[] trafficReceivedCounters; private string[] interfaces = null; public void initNetCounters() { // PerformanceCounter(CategoryName,CounterName,InstanceName) performanceNetCounterCategory = newPerformanceCounterCategory("Network Interface"); interfaces = performanceNetCounterCategory.GetInstanceNames(); int length = interfaces.Length; if (length > 0) { trafficSentCounters = newPerformanceCounter[length]; trafficReceivedCounters = newPerformanceCounter[length]; } for (int i = 0; i < length; i++) { // Initializes a new, read-only instance of the PerformanceCounter class. // 1st paramenter: "categoryName"-The name of the performance counter category (performance object) with which this performance counter is associated. // 2nd paramenter: "CounterName" -The name of the performance counter. // 3rd paramenter: "instanceName" -The name of the performance counter category instance, or an empty string (""), if the category contains a single instance. trafficReceivedCounters[i] = new PerformanceCounter("Network Interface", "Bytes Sent/sec", interfaces[i]); trafficSentCounters[i] =new PerformanceCounter("Network Interface", "Bytes Sent/sec", interfaces[i]); } // List of all names of the network interfaces for (int i = 0; i < length; i++) { Console.WriteLine("Name netInterface: {0}", performanceNetCounterCategory.GetInstanceNames()[i]); } } public void getProcessorCpuTime() { float tmp = cpuProcessorTime.NextValue(); CPUProcessorTime = (float)(Math.Round((double)tmp, 1)); // Environment.ProcessorCount: return the total number of cores } public void getCpuPrivilegedTime() { float tmp = cpuPrivilegedTime.NextValue(); CPUPrivilegedTime = (float)(Math.Round((double)tmp, 1)); } public void getCpuinterruptTime() { float tmp = cpuInterruptTime.NextValue(); CPUInterruptTime = (float)(Math.Round((double)tmp, 1)); } public void getcpuDPCTime() { float tmp = cpuDPCTime.NextValue(); CPUDPCTime = (float)(Math.Round((double)tmp, 1)); } public void getPageFile() { PageFile = pageFile.NextValue(); } public void getProcessorQueueLengh() { ProcessorQueueLengh = processorQueueLengh.NextValue(); } public void getMemAvailable() { MEMAvailable = memAvailable.NextValue(); } public void getMemCommited() { MEMCommited = memCommited.NextValue() / (1024 * 1024); } public void getMemCommitLimit() { MEMCommitLimit = memCommitLimit.NextValue() / (1024 * 1024); } public void getMemCommitedPerc() { float tmp = memCommitedPerc.NextValue(); // return the value of Memory Commit Limit MEMCommitedPerc = (float)(Math.Round((double)tmp, 1)); } public void getMemPoolPaged() { float tmp = memPollPaged.NextValue() / (1024 * 1024); MEMPoolPaged = (float)(Math.Round((double)tmp, 1)); } public void getMemPoolNonPaged() { float tmp = memPollNonPaged.NextValue() / (1024 * 1024); MEMPoolNonPaged = (float)(Math.Round((double)tmp, 1)); } public void getMemCachedBytes() { // return the value of Memory Cached in MBytes MEMCached = memCached.NextValue() / (1024 * 1024); } public void getDiskQueueLengh() { DISCQueueLengh = diskQueueLengh.NextValue(); } public void getDiskRead() { float tmp=diskRead.NextValue()/1024; DISKRead = (float)(Math.Round((double)tmp,1)); } public void getDiskWrite() { float tmp=diskWrite.NextValue()/1024; DISKWrite = (float)(Math.Round((double)tmp,1)); // round 1 digit decimal } public void getDiskAverageTimeRead() { float tmp = diskAverageTimeRead.NextValue() * 1000; DISKAverageTimeRead = (float)(Math.Round((double)tmp, 1)); // round 1 digit decimal } public void getDiskAverageTimeWrite() { float tmp = diskAverageTimeWrite.NextValue()*1000; DISKAverageTimeWrite = (float)(Math.Round((double)tmp, 1)); // round 1 digit decimal } public void getDiskTime() { float tmp = diskTime.NextValue(); DISKTime = (float)(Math.Round((double)tmp, 1)); } public void getHandleCountCounter() { HANDLECountCounter = handleCountCounter.NextValue(); } public void getThreadCount() { THREADCount = threadCount.NextValue(); } public void getContentSwitches() { CONTENTSwitches = (int)Math.Ceiling(contentSwitches.NextValue()); } public void getsystemCalls() { SYSTEMCalls = (int)Math.Ceiling(systemCalls.NextValue()); } public void getCurretTrafficSent() { int length = interfaces.Length; float sendSum = 0.0F; for (int i = 0; i < length; i++) { sendSum += trafficSentCounters[i].NextValue(); } float tmp = 8 * (sendSum / 1024); NetTrafficSend = (float)(Math.Round((double)tmp, 1)); } public void getCurretTrafficReceived() { int length = interfaces.Length; float receiveSum = 0.0F; for (int i = 0; i < length; i++) { receiveSum += trafficReceivedCounters[i].NextValue(); } float tmp = 8 * (receiveSum / 1024); NetTrafficReceive = (float)(Math.Round((double)tmp, 1)); } public void getSampleTime() { SamplingTime =DateTime.Now; } }3.百度ECharts的用法可以参考百度 官方的例子。
更多实现细节,可以参考文章:https://blogs.msdn.microsoft.com/faber/2014/11/20/tracking-windows-performance-counters-by-application/
四、实现效果
在线预览:http://qingshanboke.com/Home/performance