首页 > 其他分享 >性能计数器数据收集服务

性能计数器数据收集服务

时间:2022-11-30 10:35:37浏览次数:63  
标签:收集 性能 counter System snapshots 计数器 GO using NULL

Windows服务收集性能计数器的数据,将性能计数器数据写入数据库,项目虽小,其中用到了众多的开源项目Topshelf、NLog、Dapper,ASP.NET Web API,Newtonsoft.Json等等

本文演示了一个Windows服务收集性能计数器的数据,将性能计数器数据写入数据库。Windows服务中调用WebAPI服务中。下面简要介绍下我的改造,项目虽小,其中用到了众多的开源项目Topshelf、NLog、Dapper,ASP.NET Web API,Newtonsoft.Json等等:

1、数据库模型,以下是MS SQL Server的模型:

 USE [PerfmonCounter]
2: GO
3: /****** Object: Table [dbo].[service_counter_snapshots] Script Date: 01/25/2013 22:40:20 ******/
4: SET ANSI_NULLS ON
5: GO
6: SET QUOTED_IDENTIFIER ON
7: GO
8: SET ANSI_PADDING ON
9: GO
10: CREATE TABLE [dbo].[service_counter_snapshots](
11: [Id] [int] IDENTITY(1,1) NOT NULL,
12: [ServiceCounterId] [int] NOT NULL,
13: [SnapshotMachineName] [varchar](100) NULL,
14: [CreationTimeUtc] [datetime] NOT NULL,
15: [ServiceCounterValue] [float] NULL,
16: PRIMARY KEY CLUSTERED
17: (
18: [Id] ASC
19: )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
20: ) ON [PRIMARY]
21: GO
22: SET ANSI_PADDING OFF
23: GO
24: /****** Object: Table [dbo].[services] Script Date: 01/25/2013 22:40:20 ******/
25: SET ANSI_NULLS ON
26: GO
27: SET QUOTED_IDENTIFIER ON
28: GO
29: SET ANSI_PADDING ON
30: GO
31: CREATE TABLE [dbo].[services](
32: [Name] [varchar](100) NOT NULL,
33: [DisplayName] [varchar](1000) NULL,
34: PRIMARY KEY CLUSTERED
35: (
36: [Name] ASC
37: )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
38: ) ON [PRIMARY]
39: GO
40: SET ANSI_PADDING OFF
41: GO
42: /****** Object: Table [dbo].[service_counters] Script Date: 01/25/2013 22:40:20 ******/
43: SET ANSI_NULLS ON
44: GO
45: SET QUOTED_IDENTIFIER ON
46: GO
47: SET ANSI_PADDING ON
48: GO
49: CREATE TABLE [dbo].[service_counters](
50: [Id] [int] IDENTITY(1,1) NOT NULL,
51: [ServiceName] [varchar](100) NOT NULL,
52: [MachineName] [varchar](100) NULL,
53: [CategoryName] [varchar](100) NOT NULL,
54: [CounterName] [varchar](100) NOT NULL,
55: [InstanceName] [varchar](100) NULL,
56: [DisplayName] [varchar](1000) NULL,
57: [DisplayType] [varchar](7) NOT NULL,
58: PRIMARY KEY CLUSTERED
59: (
60: [Id] ASC
61: )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
62: ) ON [PRIMARY]
63: GO
64: SET ANSI_PADDING OFF
65: GO
66: /****** Object: Default [DF__service_c__Displ__08EA5793] Script Date: 01/25/2013 22:40:20 ******/
67: ALTER TABLE [dbo].[service_counters] ADD DEFAULT ('table') FOR [DisplayType]
68: GO
69: /****** Object: ForeignKey [FK__service_c__Servi__09DE7BCC] Script Date: 01/25/2013 22:40:20 ******/
70: ALTER TABLE [dbo].[service_counters] WITH CHECK ADD FOREIGN KEY([ServiceName])
71: REFERENCES [dbo].[services] ([Name])
72: GO


services表 存储我们需要监控的服务的进程。 每个服务都需要监控一系列的性能计数器 (存储在 service_counters 表)。数据收集服务在启动的时候根据service_counters 表创建 ​​System.Diagnostics.PerformanceCounter​​ class 的实例列表。 服务每隔一段时间收集一次性能计数器数据并把它存储到service_counter_snapshots 表。

所有的数据操作通过一个Restful服务接口DataCollectorController 进行操作。

   1:  using System;
2: using System.Collections.Generic;
3: using System.Data;
4: using System.Linq;
5: using System.Web;
6: using Dapper;
7: using PerformanceCounterCollect.Models;
8:
9: namespace PerformanceCounterCollect.Web.Models
10: {
11: public class ServiceCounterSnapshotRepository: BaseRepository
12: {
13: public IEnumerable<ServiceCounterSnapshot> SaveServiceSnapshots(IEnumerable<ServiceCounterSnapshot> snapshots)
14: {
15: using (IDbConnection connection = OpenConnection())
16: {
17: foreach (var snapshot in snapshots)
18: {
19: // insert new snapshot to the database
20: int retVal = connection.Execute(
21: @"insert into service_counter_snapshots(ServiceCounterId,SnapshotMachineName,CreationTimeUtc,ServiceCounterValue) values (
22: @ServiceCounterId,@SnapshotMachineName,@CreationTimeUtc,@ServiceCounterValue)", snapshot);
23: SetIdentity<int>(connection, id => snapshot.Id = id);
24: }
25: }
26: return snapshots;
27: }
28: }
29: }


2、监控服务,也就是数据收集代理程序Monitoring Service:

 using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5: using System.Threading;
6: using System.Threading.Tasks;
7: using Topshelf;
8: using Topshelf.Logging;
9:
10: namespace PerformanceCounterCollect.Services
11: {
12: class PerfmonWorker: ServiceControl
13: {
14: private readonly LogWriter logger = HostLogger.Get<PerfmonWorker>();
15: public static bool ShouldStop { get; private set; }
16: private ManualResetEvent stopHandle;
17:
18: public bool Start(HostControl hostControl)
19: {
20: logger.Info("Starting PerfmonWorker...");
21:
22: stopHandle = new ManualResetEvent(false);
23:
24: ThreadPool.QueueUserWorkItem(new ServiceMonitor().Monitor, stopHandle);
25:
26: return true;
27: }
28:
29: public bool Stop(HostControl hostControl)
30: {
31: ShouldStop = true;
32: logger.Info("Stopping PerfmonWorker...");
33: // wait for all threads to finish
34: stopHandle.WaitOne(ServiceMonitor.SleepIntervalInMilliSecs + 10);
35:
36: return true;
37: }
38: }
39:
40: }


服务使用了Topshelf和NLog,具体参看《​​使用Topshelf 5步创建Windows 服务​​》。在服务启动的时候开启监控线程,执行方法​​ServiceMonitor.Monitor:​

using System;
2: using System.Collections.Generic;
3: using System.Diagnostics;
4: using System.Linq;
5: using System.Text;
6: using System.Threading;
7: using System.Threading.Tasks;
8: using PerformanceCounterCollect.Models;
9: using Topshelf.Logging;
10:
11: namespace PerformanceCounterCollect.Services
12: {
13: sealed class ServiceMonitor
14: {
15: public const int SleepIntervalInMilliSecs = 50000;
16:
17: private readonly LogWriter logger = HostLogger.Get<ServiceMonitor>();
18: private IList<Tuple<int, PerformanceCounter>> serviceCounters;
19:
20: public void Monitor(object state)
21: {
22: ManualResetEvent stopHandle = (ManualResetEvent)state;
23: String machineName = Environment.MachineName;
24: try
25: {
26: Initialize(machineName);
27: var snapshots = new ServiceCounterSnapshot[serviceCounters.Count];
28:
29: while (!PerfmonWorker.ShouldStop)
30: {
31: Thread.Sleep(SleepIntervalInMilliSecs);
32:
33: // this would be our timestamp value by which we will group the snapshots
34: DateTime timeStamp = DateTime.UtcNow;
35: // collect snapshots
36: for (int i = 0; i < serviceCounters.Count; i++)
37: {
38: var snapshot = new ServiceCounterSnapshot();
39: snapshot.CreationTimeUtc = timeStamp;
40: snapshot.SnapshotMachineName = machineName;
41: snapshot.ServiceCounterId = serviceCounters[i].Item1;
42: try
43: {
44: snapshot.ServiceCounterValue = serviceCounters[i].Item2.NextValue();
45: logger.DebugFormat("Performance counter {0} read value: {1}", GetPerfCounterPath(serviceCounters[i].Item2),
46: snapshot.ServiceCounterValue);
47: }
48: catch (InvalidOperationException)
49: {
50: snapshot.ServiceCounterValue = null;
51: logger.DebugFormat("Performance counter {0} didn't send any value.", GetPerfCounterPath(serviceCounters[i].Item2));
52: }
53: snapshots[i] = snapshot;
54: }
55: SaveServiceSnapshots(snapshots);
56: }
57: }
58: finally
59: {
60: stopHandle.Set();
61: }
62: }
63:
64: private void Initialize(String machineName)
65: {
66: try
67: {
68: var counters = new List<Tuple<int, PerformanceCounter>>();
69:
70: foreach (var counter in PerfmonClient.SelectServiceCounter(machineName))
71: {
72: logger.InfoFormat(@"Creating performance counter: {0}\{1}\{2}\{3}", counter.MachineName ?? ".", counter.CategoryName,
73: counter.CounterName, counter.InstanceName);
74: var perfCounter = new PerformanceCounter(counter.CategoryName, counter.CounterName, counter.InstanceName, counter.MachineName ?? ".");
75: counters.Add(new Tuple<int, PerformanceCounter>(counter.Id, perfCounter));
76: // first value doesn't matter so we should call the counter at least once
77: try { perfCounter.NextValue(); }
78: catch { }
79: }
80:
81:
82: serviceCounters = counters;
83: }
84: catch (Exception ex)
85: {
86: logger.Error(ex);
87: }
88: }
89:
90: private void SaveServiceSnapshots(IEnumerable<ServiceCounterSnapshot> snapshots)
91: {
92: PerfmonClient.SaveServiceSnapshots(snapshots);
93: }
94:
95: private String GetPerfCounterPath(PerformanceCounter cnt)
96: {
97: return String.Format(@"{0}\{1}\{2}\{3}", cnt.MachineName, cnt.CategoryName, cnt.CounterName, cnt.InstanceName);
98: }
99: }
100: }


​在Monitor​​​ 方法中初始化完要采集的性能计数器实例后开启一个主循环,定期的收集数据,如果相关的性能计数器实例没有运行,计数器将会抛出​​InvalidOperationException​​ 我们就把它设置为null。数据集的数据通过WebAPI发回服务器端存储,这样就可以实现性能计数器的集中存储了。

3、使用方法

使用很简单,首先定义我们要收集的数据

insert into services values ('notepad', 'notepad process test');

insert into service_counters values ( 'notepad', ‘GEFFZHANG-PC’, 'process', '% Processor Time', 'notepad', null, 'graph');

insert into service_counters values ( 'notepad', ‘GEFFZHANG-PC’, 'process', 'working set', 'notepad', null, 'graph');

然后启动我们的性能计数器收集服务

性能计数器数据收集服务_数据




代码参见项目 ​​https://github.com/geffzhang/PerformanceCounterCollect/​

​WMI Performance Counter Logging Console App​



标签:收集,性能,counter,System,snapshots,计数器,GO,using,NULL
From: https://blog.51cto.com/shanyou/5897726

相关文章

  • sysbench性能测试工具安装
    sysbench工具安装安装1、 将下载的sysbench压缩包上传到测试主机的任意目录,并解压。tarxvfsysbench-0.5.tar.gz2、 在root权限下安装如下依赖yum installgccli......
  • StorageReview公布浪潮固态硬盘与浪潮服务器性能测试报告
    近日,StorageReview公布浪潮服务器NF5280M6配备NS8500G2固态硬盘的性能测试报告。报告显示,搭载12块浪潮NS8500G2固态硬盘的NF5280M6服务器,在64K大数据块顺序性能测试中获......
  • Android:性能优化工具之内存泄露-LeakCanary
    目录​​一简介​​​​二使用​​​​三进阶用法​​​​四hprof分析复杂内存泄露问题​​​​五使用小结​​​​六使用踩坑​​​​6.1权限​​​​6.2 NullPoi......
  • 浪潮超融合inMerge1100刷新VMmark基准测试性能纪录
    近日,VMmark发布了最新的性能测试结果,浪潮信息inMerge1100超融合产品以25.74分的成绩,刷新了vSAN架构(Intel双路平台)的虚拟化性能测试记录。自2006年云计算概念问世以来,从服务......
  • python性能调优之key-query
    近期接触到一个性能调优的问题,需要在mongodb中比对大约100G的csv文件的key在mongodb中是否存在baseline首先做一个什么优化都没有的情况下的基准测试:bat......
  • 虹科分享 | 网络仿真器 | 预测云中对象存储系统的实际性能
    对象存储是一种在云中存储非结构化数据的方法,从理论上讲,它使得以其原始格式存储几乎无限量的数据成为可能。在这种存储架构中,数据被作为对象进行管理,而传统的系统则将数据作......
  • 【python】locust模块_性能测试
    简介Locust是一款易于使用的分布式负载测试工具,完全基于事件,即一个locust节点也可以在一个进程中支持数千并发用户,不使用回调,通过gevent使用轻量级过程(即在自己的进程......
  • [ZMQ] ZeroMQ rk3308 性能测试
    目录stepLatencyTest(one-waylatency)tcpinprocThroughputTesttcpinprocstepadbpush所有附件到udisk目录adbpush的文件添加执行权限LatencyTest(one-waylaten......
  • DRF 知识点收集
    drf序列化器中的read_only和write_only选项参考网址https://www.cnblogs.com/jx-zzc/p/16522675.htmlread_only:表示只读,不能进行修改,也不会存入db(校验过后)......
  • Java的性能优势与版本
    Java的性能和优势简单性Java没有指针运算,也不需要分配内存,语法基于C语言面向对象面向对象编程-万物皆对象可移植性跨平台移植,一次编写到处运行高性能即......