通过阿里云建设企业网站,国外服务器地址,如东网页设计,苏州网站建设找哪家文章目录关于监控服务器指标、CPU、内存、警报的一些解决方案Prometheus Grafana 配置 IRIS / Cach 监控服务器Prometheus简介特点架构图Grafana简介特点配置流程自定义Prometheus接口定义配置 Exporter 监控服务器系统资源简介配置流程使用 Alertmanager报警简介配置流程基于…
文章目录关于监控服务器指标、CPU、内存、警报的一些解决方案Prometheus Grafana 配置 IRIS / Caché 监控服务器Prometheus简介特点架构图Grafana简介特点配置流程自定义Prometheus接口定义配置 Exporter 监控服务器系统资源简介配置流程使用 Alertmanager报警简介配置流程基于M实现监控服务器并用邮件报警解析Prometheus数据接口信息使用嵌入式Python方式获取系统CPU、内存等python模块之psutil详解CPU相关Memory内存相关Disk相关Network相关Process相关通过嵌入式Python调用psutil库使用邮件发送报警信息使用M发送邮件发送消息通过配置文件csv文件来获取维护指标进行邮件报警。总结思考附关于监控服务器指标、CPU、内存、警报的一些解决方案
本文章主要介绍以下几个章节内容
Prometheus Grafana 配置 IRIS / Caché 监控服务器自定义Prometheus接口定义 - 配置 Caché 监控服务配置 Exporter 监控服务器系统资源使用 Alertmanager报警基于M实现监控服务器并用邮件报警 解析Prometheus数据接口信息使用嵌入式Python方式获取系统CPU、内存等使用邮件发送报警信息
Prometheus Grafana 配置 IRIS / Caché 监控服务器
首先我们介绍一下如何用IRIS结合Prometheus Grafana的使用在介绍如何配置之前我们先了简单了解一下工具。
Prometheus
简介 Prometheus是一个最初在SoundCloud上构建的开源系统监视和警报工具包 。 自2012年成立以来许多公司和组织都采用了Prometheus该项目拥有一个非常活跃的开发人员和用户社区。它现在是一个独立的开源项目可以独立于任何公司进行维护。为了强调这一点并澄清项目的治理结构Prometheus 于2016年加入 云计算本地计算基金会作为继Kubernetes之后的第二个托管项目。 特点
具有由度量名称和键/值对标识的时间序列数据的多维数据模型。一个灵活的查询语言 来利用这一维度。不依赖分布式存储单个服务器节点是自治的。时间序列收集通过 HTTP 上的拉模型发生。通过中间网关支持推送时间序列。通过服务发现或静态配置发现目标。多种图形和仪表板支持模式。
架构图 Grafana
简介 Grafana是一个跨平台的开源的度量分析和可视化工具可以通过将采集的数据查询然后可视化的展示并及时通知。 特点
展示方式快速灵活的客户端图表面板插件有许多不同方式的可视化指标和日志官方库中具有丰富的仪表盘插件比如热图、折线图、图表等多种展示方式。支持多种数据源GraphiteInfluxDBOpenTSDBPrometheusElasticsearchCloudWatch和KairosDB等。通知提醒以可视方式定义最重要指标的警报规则Grafana将不断计算并发送通知在数据达到阈值时通过Slack、PagerDuty等获得通知。混合展示在同一图表中混合使用不同的数据源可以基于每个查询指定数据源甚至自定义数据源。注释使用来自不同数据源的丰富事件注释图表将鼠标悬停在事件上会显示完整的事件元数据和标记。过滤器Ad-hoc过滤器允许动态创建新的键/值过滤器这些过滤器会自动应用于使用该数据源的所有查询。
配置流程
下载Prometheus选择操作系统下载对应安装包以windows为例。
下载地址https://prometheus.io/download/ 下载完成后直接解压在所需目录即可。解压后进入目录直接运行premetheus.exeprometheus默认端口为9090。 在浏览器输入地址、即可查看监控页面。
地址 - http://localhost:9090/ 配置监控服务器信息编辑 prometheus-2.27.1.windows-amd64/prometheus.yml文件。在scrape_configs:输入以下代码 这里以我的私有服务器地址为例https://8.142.29.250:2443/api/monitor/metrics。
输入以下代码 - job_name: 250-IRISmetrics_path: /api/monitor/metricsscheme: httpstls_config:insecure_skip_verify: truestatic_configs:- targets: [8.142.29.250:2443]其中
job_name - 服务器名称。metrics_path - 监控服务器地址路径。scheme - 网络协议。tls_config - insecure_skip_verify - 过滤完成验证。static_configs - targets - IP端口号。
prometheus.yml文件修改完成后重新启动prometheus.exe程序进入到Status-Targets下即可看到添加的监控服务器信息 监控具体指标点击Graph-勾选UseLocalime-输入监控指标iris_cpu_usage-点击Excute-选择监控时长范围30min。
iris_cpu_usage - 代表CPU使用率。 说明这里监控指标为服务器接口里的具体指标输入接口地址具体查看。 由于Prometheus展示的信息相对简单图表类型也比较少下面介绍如何使用Grafana展示数据。输入Grafana地址下载对应版本。
下载地址https://grafana.com/grafana/download? 下载后直接运行安装安装完成后进入grafana/bin目录下双击运行garafana-server.exe。 garafana默认端口为3030访问地址http://localhost:3000/默认用户名密码admin/admin 在grafana里添加数据源Data Source。 选择Prometheus。 填写数据源信息并保存。
Name - PrometheusUrl - http://localhost:9090 点击Savetest显示测试成功。 创建模版点击Dashboards-点击Browse-输入模版名称-New-NewDashboard。 点击Add a new panel。 选择数据源Data source指标iris_cpu_usage - Run query。
Title - 修改仪表盘名称。 输入仪表盘名称点击保存即可。 最终效果依次类推建立多个监控指标。
iris_csp_sessions - 会话使用数iris_cpu_usage - cpu使用率iris_system_alerts - 系统警报数iris_process_count - 进程数量iris_glo_ref_per_sec - Global每秒引用数量 自定义Prometheus接口定义
那么我们是否可以自定义Prometheus接口呢?
答案肯定是可以的整好 Caché 没有自带的监控服务所以我们给Caché 自定义个一个监控服务接口。
首先我们需要创建一个Rest接口类M.Metrics。
Class M.Metrics Extends %CSP.REST
{
}在Portal中配置Rest接口系统-安全管理-Web应用程序-编辑Web引用程序。
名称 - /api/metrics命名空间 - 选择Rest接口类所在命名空间分派类 - M.Metrics 编写Rest接口逻辑下面展示主要业务逻辑代码。
基础仪表盘接口
ClassMethod GetDashboardMetrics(ByRef array As %DynamicArray) As %Status
{s dashboard ##class(SYS.Stats.Dashboard).Sample()s properties ##class(%Dictionary.ClassDefinition).%OpenId(dashboard.%ClassName(1)).Propertiesfor i 1 : 1 : properties.Count() {s property properties.GetAt(i)s propertyName property.Names propertyValue $property(dashboard propertyName)if ((propertyValue ) ($match(propertyValue .*[-A-Za-z ].*))) {s metricsName ..CamelCase2Underscore(propertyName)s metricsValue propertyValues obj {}s obj.key metricsNames obj.val metricsValued array.%Push(obj)}}q $$$OK
}系统使用情况
d ##class(SYS.Metrics).GetMainMetrics( 0 .pValues .pStatus .pMsg)系统监视器统计
d ##class(SYS.Metrics).GetGlobalStatistics( 0 .pValues .pStatus .pMsg)ECP 数据统计
d ##class(SYS.Metrics).GetECPStatistics( 0 .pValues .pStatus .pMsg)磁盘和缓冲区数据统计
d ##class(SYS.Metrics).GetStatistics(0.pValues.pStatus.pMsg)许可数据统计
ClassMethod GetLicenseStatistics(ByRef array As %DynamicArray)
{s licenseUsed ##class(%SYSTEM.License).LUConsumed()s obj {}s obj.key ..#PREFIX _ _license_useds obj.val licenseUsedd array.%Push(obj)s licenseAvailable##class(%SYSTEM.License).LUAvailable()s obj {}s obj.key ..#PREFIX _ _license_avails obj.val licenseAvailabled array.%Push(obj)s licenseTotal##class(%SYSTEM.License).GetUserLimit()s obj {}s obj.key ..#PREFIX _ _license_totals obj.val licenseTotald array.%Push(obj)s obj {}s obj.key ..#PREFIX _ _license_loads obj.val $fn((licenseUsed / (licenseAvailable licenseUsed)) N 4)d array.%Push(obj)
}开放性事务数据统计
ClassMethod GetOpenTransactionStatistics(ByRef array As %DynamicArray)
{if ($zv [ Cache) {s index ^CacheTemp.SysMetrics} else {s index ^IRIS.Temp.SysMetrics}if (index(Transactions)) OK {s val 1} else {s val 0}s obj {}s obj.key ..#PREFIX _ _open_transactions obj.val vald array.%Push(obj)
}数据库情况
ClassMethod GetDatabaseStatistics(ByRef array As %DynamicArray)
{s statement ##class(%SQL.Statement).%New()s sc statement.%PrepareClassQuery(%SYS.DatabaseQuery FreeSpace)s rs statement.%Execute()while (rs.%Next()) {s databaseName rs.%Get(DatabaseName)s freeRate rs.%GetData(7)s availableNum rs.%Get(AvailableNum)s diskFreeSpaceNum rs.%Get(DiskFreeSpaceNum)s obj {}s obj.key ..#PREFIX _ _database_frees obj.val (100 - freeRate) / 100s tag {}s tag.id databaseNames obj.tag tagd array.%Push(obj)}
}把所有数据组装到一起。
ClassMethod GetMetrics()
{s array []#; 基础仪表盘d ..GetDashboardMetrics(.array)#; 系统使用情况d ##class(SYS.Metrics).GetMainMetrics( 0 .pValues .pStatus .pMsg)d ..ParseJson(.pValues .array)#; 系统监视器统计d ##class(SYS.Metrics).GetGlobalStatistics( 0 .pValues .pStatus .pMsg)d ..ParseJson(.pValues .array)#; ECP 数据统计d ##class(SYS.Metrics).GetECPStatistics( 0 .pValues .pStatus .pMsg)d ..ParseJson(.pValues .array)#; 磁盘和缓冲区数据统计d ##class(SYS.Metrics).GetStatistics(0.pValues.pStatus.pMsg)d ..ParseJson(.pValues .array)#; 许可数据统计d ..GetLicenseStatistics(.array)#; 开放性事务数据统计d ..GetOpenTransactionStatistics(.array)#; 数据库情况d ..GetDatabaseStatistics(.array)q array
}将数据解析成Prometheus数据格式。
prometheus将所有数据保存为timeseries data用metric name和label区分label是在metric name上的更细维度的划分其中的每一个实例是由一个float64和timestamp组成只不过timestamp是隐式加上去的#HELP代表指标的注释信息#TYPE用于定义样本的类型注释信息。如下示例
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile0} 0metrics name - 为go_gc_duration_secondslabel - 为quantile0float64 - 为0
ClassMethod Metrics2Prometheus() As %Status
{s %response.ContentType text/plain;version0.0.4;charsetutf-8s array ..GetMetrics()s iter array.%GetIterator()while iter.%GetNext(.key .json) { s str json.keyif (json.%IsDefined(tag)) {s tag json.tags tagIter tag.%GetIterator()s str str _ { while tagIter.%GetNext(.tagKey .tagVal) { s str str _ tagKey _ _ _ tagVal _ _ }s str $e(str 1 * - 1) _ } }w str _ _ json.val _ $c(10)}q $$$OK
}配置路由
XData UrlMap [ XMLNamespace http://www.intersystems.com/urlmap ]
{
RoutesRoute Url/prometheus MethodGET CallMetrics2Prometheus /Route Url/json MethodGET CallMetrics2Json /
/Routes
}在界面输入自定义配置的Prometheus接口地址。
prometheus格式地址接口http://localhost:57772/api/metrics/prometheus Json格式地址接口http://localhost:57772/api/metrics/json 在prometheus.yml配置文件中添加自定义的接口。代码如下 - job_name: localhost-Cachemetrics_path: /api/metrics/prometheusstatic_configs:- targets: [localhost:57772]重新启动prometheus查看配置界面。这样我们就可以给Caché配置一个自定义的接口拉。 配置 Exporter 监控服务器系统资源
通过服务器配置Exporter监控服务器的系统信息例如内存使用情况CPU使用情况。
简介 为Prometheus提供监控数据源的应用都可以被成为Exporter比如Node Exporter则用来提供节点相关的资源使用状况而Prometheus从这些不同的Exporter中获取监控数据然后可以在诸如Grafana这样的可视化工具中进行结果的显示。 广义上讲所有可以向Prometheus提供监控样本数据的程序都可以被称为一个Exporter。而Exporter的一个实例称为target如下所示Prometheus通过轮询的方式定期从这些target中获取样本数据。 配置流程
下载windows_exporter-0.21.0-amd64.msi文件后直接双击运行
下载地址https://github.com/prometheus-community/windows_exporter/releases windows_exporter默认端口号为9182运行后浏览器访问地址 出现以下信息说明安装成功。
地址http://localhost:9182/metrics 将Exporter接口添加到Prometheus中。 - job_name: localhost-Exportermetrics_path: /metricsstatic_configs:- targets: [localhost:9182]使用 Alertmanager报警
简介 Alertmanager是一个独立的告警模块接收Prometheus等客户端发来的警报之后通过分组、删除重复等处理并将它们通过路由发送给正确的接收器。 Prometheus 的报警分为两部分
Prometheus 服务器中的警报规则向警报管理器(Alertmanager)发送警报。警报管理器负责管理这些警报包括告警信息进行去重降噪分组等并通过丰富的告警通知渠道如电子邮件、微信、钉钉、Slack等常用沟通工具发出通知。
配置流程
下载Prometheus选择操作系统下载对应安装包下载完毕后并挤压以windows为例。
下载地址https://github.com/prometheus/alertmanager/releases 双击alertmanager.exe启动alertmanager服务浏览器访问端口地址可以看到默认提供的 UI 页面。
端口 - 9093地址 - http://localhost:9093/#/alerts AlertManager 默认配置文件为 alertmanager.yml打开配置文件配置使用 Email 方式通知报警信息这里以 QQ 邮箱为例配置信息如下
global - 全局配置包括报警解决后的超时时间、SMTP 相关配置、各种渠道通知的 API 地址等等。route - 用来设置报警的分发策略它是一个树状结构按照深度优先从左向右的顺序进行匹配。receivers - 配置告警消息接受者信息例如常用的 email、wechat、slack、webhook 等消息通知方式。inhibit_rules - 抑制规则配置当存在与另一组匹配的警报时抑制规则将禁用与一组匹配的警报目标。
global:resolve_timeout: 5msmtp_from: xxxxqq.comsmtp_smarthost: smtp.qq.com:465smtp_auth_username: xxxxqq.comsmtp_auth_password: xxxxxxxxxxxxxxsmtp_require_tls: falsesmtp_hello: qq.comroute:group_by: [alertname]group_wait: 5sgroup_interval: 5srepeat_interval: 5mreceiver: email
receivers:
- name: emailemail_configs:- to: xxxxxmediway.cnsend_resolved: trueinhibit_rules:- source_match:severity: criticaltarget_match:severity: warningequal: [alertname dev instance]接下来需要在 Prometheus 配置 AlertManager 服务地址以及告警规则新建报警规则文件 alert_rules.yml放在prometheus.yml同级路径下配置如下
name - 规则名称可自己定义。alert - 报警名称当触发报警时会作为邮件标题显示。expr - 报警规则为 PromQL 表达式验证特定节点如上述配置中up{job250-IRIS}为验证job250-IRIS是否还活着如果等于0则启动报警。for - 表示报警状态为 Pending 后等待 15s 变成 Firing 状态一旦变成 Firing 状态则将报警发送到 AlertManager。summary - 报警信息描述。
groups:- name: 服务器报警rules:- alert: yx服务器报警expr: up{job250-IRIS} 0for: 15slabels:status: warningannotations:summary: 服务器{{ $labels.instance }} 挂了description: 姚鑫服务器挂了.请立即查看!- alert: 本地Cache报警expr: up{joblocalhost-Cache} 0for: 15slabels:status: warningannotations:summary: 服务器{{ $labels.instance }} 挂了description: 本地Cache服务器挂了.请立即查看!- alert: 本地IRIS报警expr: up{joblocalhost-IRIS} 0for: 15slabels:status: warningannotations:summary: 服务器{{ $labels.instance }} 挂了description: 本地IRIS服务器挂了.请立即查看!- name: test-rulesrules:- alert: 内存报警expr: 100 - ((node_memory_MemAvailable_bytes * 100) / node_memory_MemTotal_bytes) 3for: 15slabels:status: warningannotations:summary: 服务器:{{$labels.instance}}内存使用率超过3%了description: 内存使用率: {{ $value }}value: {{ $value }}配置好报警规则文件后需要修改 prometheus.yml 配置文件添加 rules 规则文件
alerting:alertmanagers:- static_configs:- targets:- localhost:9093# - alertmanager:9093# Load rules once and periodically evaluate them according to the global evaluation_interval.
rule_files:- alert_rules.yml# - second_rules.yml配置完毕后打浏览器访问prometheus主页进入Alerts和Rules界面可查看报警规则信息
地址http://localhost:9090/alerts?search 测试报警功能将本地Caché关闭停库。 观察页面本地Cache警报状态。
Prometheus Alert 告警状态有三种Inactive、Pending、Firing。
Inactive - 非活动状态表示正在监控但是还未有任何警报触发。Pending - 表示这个警报将被触发。由于警报可以被分组、压抑/抑制或静默/静音所以等待验证一旦所有的验证都通过则将转到 Firing 状态。Firing - 将警报发送到AlertManager将按照配置将警报的发送给所有接收者。一旦警报解除则将状态转到 Inactive如此循环。
首先发现警报变为Pending状态。 过了15秒后变为Firing状态 触发报警根据定义的报警规则如果有触发告警的条件自动向配置的接收邮箱中发送邮件如下 基于M实现监控服务器并用邮件报警
解析Prometheus数据接口信息
获取接口信息
ClassMethod GetMetrics(url) As %Status
{#; 初始化request对象#dim request as %Net.HttpRequest ##class(%Net.HttpRequest).%New()#; 根据地址解析是否是https调用SSL配置d ##class(%Net.URLParser).Parse(url .components)s scheme components(scheme)if (scheme https) {s request.Https 1if ($zv [ IRIS) {s request.SSLConfiguration ISC.FeatureTracker.SSL.Config} else {s request.SSLConfiguration WebTerminalSSL} s request.SSLCheckServerIdentity 0 }#; 请求地址并返回流数据s sc request.Get(url)$$$ThrowOnError(sc)s response request.HttpResponses stream response.Dataq stream
}将接口信息转为Json格式
ClassMethod Metrics2Json(stream) As %Status
{s array []while (stream.AtEnd 0) {#; 读取每行信息s metrics stream.ReadLine()#; 过滤注释描述信息continue:(metrics [ # HELP)continue:(metrics [ # TYPE)#; 指标字符串s str $p(metrics 1)#; 指标值s value $p(metrics 2)#; 指标字名称s metricsName $p(str { 1)#; 指标字label信息s label $e($p(str { 2) 1 * - 1)s obj {}s obj.key metricsNames obj.val value#; 如果label不为空将label信息转为JSONif (label ) {s tag {}s len $l(label )for i 1 : 1 : len{s item $p(label , i)s key $p(item 1) s val $e($p(item 2) 2 *-1)d tag.%Set(key val)}s obj.tag tag}d array.%Push(obj)}q array
}调用方法。
/// w ##class(M.ParseMetrics).Main(https://localhost:2443/api/monitor/metrics).%ToJSON()
/// w ##class(M.ParseMetrics).Main(http://localhost:9182/metrics).%ToJSON()
/// w ##class(M.ParseMetrics).Main(http://localhost:57772/api/metrics/prometheus).%ToJSON()
ClassMethod Main(url) As %Status
{#; 获取指标接口信息s stream ..GetMetrics(url)#; 将接口信息转为JSON格式s json ..Metrics2Json(stream)q json
}调用自定义Caché接口
IMPw ##class(M.ParseMetrics).Main(http://localhost:57772/api/metrics/prometheus).%ToJSON() [{key:yx_application_errorsval:0}{key:yx_csp_sessionsval:1}{key:yx_cache_efficiencyval:235.85}{key:yx_disk_readsval:3316}{key:yx_disk_writesval:1881}{key:yx_ecp_app_srv_rateval:0}{key:yx_ecp_data_srv_rateval:0}{key:yx_glo_refsval:1225714}{key:yx_glo_refs_per_secval:439.00}{key:yx_glo_setsval:108449}{key:yx_journal_entriesval:17178}
...
{key:yx_database_freeval:.8988tag:{id:DHC-EPRMETADATA}}{key:yx_database_freeval:.45tag:{id:DHC-EPRQUALITYDATA}}{key:yx_database_freeval:.71tag:{id:DHC-EPRRBACINST}}{key:yx_database_freeval:.74tag:{id:DHC-EPRRBACMETA}}{key:yx_database_freeval:.78tag:{id:DHC-HEIS}}{key:yx_database_freeval:.48tag:{id:DHC-HL7}}{key:yx_database_freeval:.9936tag:{id:DHC-HR}}{key:yx_database_freeval:.0345tag:{id:DHC-LISDATA}}{key:yx_database_freeval:.9328tag:{id:DHC-LISSRC}}{key:yx_database_freeval:.9884tag:{id:DHC-LOGS}}{key:yx_database_freeval:.9098tag:{id:DHC-MEDSRC}}{key:yx_database_freeval:.8996tag:{id:DHC-MRQDATA}}{key:yx_database_freeval:.9871tag:{id:DHC-MRQSRC}}{key:yx_database_freeval:.1tag:{id:DHC-MSG}}{key:yx_database_freeval:.0481tag:{id:DHC-ORDDATA}}{key:yx_database_freeval:.0417tag:{id:DHC-ORDINDEX}}{key:yx_database_freeval:.8782tag:{id:PACS}}{key:yx_database_freeval:.6tag:{id:DHC-PISDATA}}{key:yx_database_freeval:.831tag:{id:DHC-PISSRC}}{key:yx_database_freeval:.9548tag:{id:DHC-RIS}}{key:yx_database_freeval:.9615tag:{id:DHC-SYS}}{key:yx_database_freeval:.9218tag:{id:DHC-TEMP}}{key:yx_database_freeval:.8096tag:{id:DHC-DWR}}{key:yx_database_freeval:.039tag:{id:DHC-WORKLOAD}}{key:yx_database_freeval:.1797tag:{id:IMP}}] 调用自定义IRIS接口
IMPw ##class(M.ParseMetrics).Main(https://localhost:2443/api/monitor/metrics).%ToJSON() [{key:iris_cpu_pctval:0tag:{id:CSPSRV}}{key:iris_cpu_pctval:0tag:{id:ECPWorker}}{key:iris_cpu_pctval:0tag:{id:GARCOL}}{key:iris_cpu_pctval:0tag:{id:JRNDMN}}
...
{key:iris_wqm_max_work_queue_depthval:0tag:{id:SYS}}{key:iris_wqm_waiting_worker_jobsval:1tag:{id:SYS}}] 调用自定义Exporter接口
IMPw ##class(M.ParseMetrics).Main(http://localhost:9182/metrics).%ToJSON()
[{key:go_gc_duration_seconds,val:0,tag:{quantile:0}},{key:go_gc_duration_seconds,val:0,tag:{quantile:0.25}},{key:go_gc_duration_seconds,val:0,tag:{quantile:0.5}},{key:go_gc_duration_seconds,val:0,tag:{quantile:0.75}},{key:go_gc_duration_seconds,val:0.0023476,tag:{quantile:1}},{key:go_gc_duration_seconds_sum,val:0.0038789},{key:go_gc_duration_seconds_count,val:87},{key:go_goroutines,val:14},{key:go_info,val:1,tag:
...
{key:go_threads,val:19},{key:process_cpu_seconds_total,val:2.015625},{key:process_max_fds,val:1.6777216e07},{key:process_open_fds,val:414},{key:process_resident_memory_bytes,val:3.5504128e07},{key:process_start_time_seconds,val:1.67670656e09},{key:process_virtual_memory_bytes,val:4.0259584e07},]使用嵌入式Python方式获取系统CPU、内存等
python模块之psutil详解
在讲嵌入式Python之前我们先了解一下psutil库 psutil是一个开源切跨平台的库其提供了便利的函数用来获取才做系统的信息比如CPU内存磁盘网络等。此外psutil还可以用来进行进程管理包括判断进程是否存在、获取进程列表、获取进程详细信息等。而且psutil还提供了许多命令行工具提供的功能包括pstoplsofnetstatifconfig whodfkillfreeniceioniceiostatiotopuptimepidofttytasksetpmap。 psutil是一个跨平台的库在官方网站上查到其支持如下操作系统。
LinuxWindowsOSXFreeBSDOpenBSDNetBSDSun SolarisAIX
CPU相关
函数描述psutil.cpu_count()cpu_count([logical])默认返回逻辑CPU的个数当设置logical的参数为False时返回物理CPU的个数。psutil.cpu_percent()cpu_percent([percpu][interval])返回CPU的利用率percpu为True时显示所有物理核心的利用率interval不为0时则阻塞时显示interval执行的时间内的平均利用率。psutil.cpu_times()cpu_times([percpu])以命名元组(namedtuple)的形式返回cpu的时间花费percpuTrue表示获取每个CPU的时间花费。psutil.cpu_times_percent()cpu_times_percent([percpu])功能和cpu_times大致相同看字面意思就能知道该函数返回的是耗时比例。psutil.cpu_stats()cpu_stats()以命名元组的形式返回CPU的统计信息包括上下文切换中断软中断和系统调用次数。psutil.cpu_freq()cpu_freq([percpu])返回cpu频率。
Memory内存相关
函数描述virtual_memory()以命名元组的形式返回内存使用情况包括总内存可用内存内存利用率buffer和cache等。单位为字节。swap_memory()以命名元组的形式返回swap/memory使用情况包含swap中页的换入和换出。
Disk相关
函数描述psutil.disk_io_counters()disk_io_counters([perdisk])以命名元组的形式返回磁盘io统计信息包括读、写的次数读、写的字节数等。 当perdisk的值为True则分别列出单个磁盘的统计信息(字典key为磁盘名称value为统计的namedtuple)。psutil.disk_partitions()disk_partitions([allFalse])以命名元组的形式返回所有已挂载的磁盘包含磁盘名称挂载点文件系统类型等信息。 当all等于True时返回包含/proc等特殊文件系统的挂载信息。psutil.disk_usage()disk_usage(path)以命名元组的形式返回path所在磁盘的使用情况包括磁盘的容量、已经使用的磁盘容量、磁盘的空间利用率等。
Network相关
函数详情psutil.net_io_counter([pernic])以命名元组的形式返回当前系统中每块网卡的网络io统计信息包括收发字节数收发包的数量、出错的情况和删包情况。当pernic为True时则列出所有网卡的统计信息。psutil.net_connections([kind])以列表的形式返回每个网络连接的详细信息(namedtuple)。命名元组包含fd family type laddr raddr status pid等信息。kind表示过滤的连接类型支持的值如下(默认为inet)。psutil.net_if_addrs()以字典的形式返回网卡的配置信息包括IP地址和mac地址、子网掩码和广播地址。psutil.net_if_stats()返回网卡的详细信息包括是否启动、通信类型、传输速度与mtu。psutil.users()以命名元组的方式返回当前登陆用户的信息包括用户名登陆时间终端与主机信息。psutil.boot_time()以时间戳的形式返回系统的启动时间。
Process相关
函数详情psutil.pids()以列表的形式返回当前正在运行的进程。psutil.pid_exists(1)判断给点定的pid是否存在。psutil.process_iter()迭代当前正在运行的进程返回的是每个进程的Process对象。psutil.Process()对进程进行封装可以使用该类的方法获取进行的详细信息或者给进程发送信号。
通过嵌入式Python调用psutil库
这里仅简单介绍个主要方法、其他获取系统资源方法由读者自行实现。
在安装路径C:\InterSystems\IRISHealth\bin输入cmd进入命令行控制台输入命令。安装 psutil库。
irispip install --target C:\InterSystems\IRISHealth\mgr\python psutil获取服务器CPU使用率
ClassMethod GetSystemCpu() As %String [ Language python ]
{from psutil.__init__ import cpu_percent,virtual_memoryreturn cpu_percent(interval2)
}USER w ##class(M.SystemMetrics).GetSystemCpu()
14.59999999999999964根据上图可以观察到获取的内容使用 1 - 是 IRIS监控接口、2 - 是M方法实现、 3 - 是任务管理器三者监控的CPU使用率基本使用是一致的。因为CPU使用率是瞬态的所以可以认为是准确的
获取服务系内存使用状态
ClassMethod GetSystemMemory() As %String [ Language python ]
{from psutil.__init__ import cpu_percent,virtual_memoryreturn virtual_memory()[2]
}USERw ##class(M.SystemMetrics).GetSystemMemory()
60根据上图可以观察到获取的内容使用 1 - 是 360监控、2 - 是任务管理器、 3 - 是M方法实现三者监控的内存使用是一致的。
使用邮件发送报警信息
这里考虑使用邮件来发送警报信息是因为
邮件相对其他方式来说比较方便只管发送不用管是否接收。IRIS自带发送邮件接口操作性大。相比其他方式例如微信公众号等还需要做接口交互。使用邮件相对简单。
那么下一个考虑的问题是通过什么方式来触发监控发邮件呢笔者考虑以下两点可以触发
通过挂任务的方式定时轮询。通过SessionEvent事件来触发。
这里仅提供代码示例具体使用哪种方式由读者自行决定。
使用M发送邮件发送消息
这里以QQ邮箱例配置信息与Alertmanager邮箱配置相同
ClassMethod SetMailConfig() As %Net.SMTP
{#; 配置smtp服务s server ##class(%Net.SMTP).%New()s server.smtpserver smtp.qq.coms server.port 465if ($zv [ IRIS) {s server.SSLConfiguration ISC.FeatureTracker.SSL.Config} else {s server.SSLConfiguration WebTerminalSSL} #; 配置邮箱s auth ##class(%Net.Authenticator).%New()s auth.UserName 454115408qq.coms auth.Password xxxxxxxxxxxxxxxxs server.authenticator auths server.AuthFrom auth.UserNameq server
}发送邮件具体方法
ClassMethod SendMailMessage(title, content) As %List
{#; 获取配置s server ..SetMailConfig()#; 初始化邮件对象s msg ##class(%Net.MailMessage).%New()#; 添加from - 发送人to - 接收人Cc - 抄送人s from server.authenticator.UserNames msg.From fromd msg.To.Insert(yaoxinmediway.cn)d msg.Cc.Insert(965274651qq.com)#; 填写邮件具体内容s msg.Subject titles msg.IsBinary 0s msg.IsHTML 0d msg.TextData.Write(content)#; 执行发送s sc server.Send(msg)$$$ThrowOnError(sc)q server.FailedSend
}测试邮件方法发送成功目标邮箱会接收到邮件。
IMPw ##class(M.Mail).SendMailMessage(yx发的邮件消息头,这是yx发的消息内容content) 10%Collection.ListOfDT通过配置文件csv文件来获取维护指标进行邮件报警。
使用csv文件通过手动的方式来维护需要监控的指标 key - 指标名称这里要与IRIS接口信息的具体指标保持一致。val - 报警的阈值。oper - 操作符。指具体报警时操作符。是大于val时报警还是小于val时报警或其他。desc - 指标描述信息。 读取csv文件将数据转为Json。
ClassMethod Csv2Json(filename)
{q:(##class(%File).Exists(filename)) $$$NOs stream ##class(%Stream.FileCharacter).%New()s stream.Filename filenames array []s keyStr while stream.AtEnd {s str stream.ReadLine()if ($i(count) 1) {s keyStr str}s obj {} s len $l(str, ,)for i 1 : 1 : len {s val $p(str, ,, i)s key $p(keyStr, ,, i)d obj.%Set(key, val)}d array.%Push(obj)}q array
}IMPw ##class(M.Mail).LoadFile(E:\temp\metrics.csv).%ToJSON()
[{key:iris_cpu_usage ,val:10,oper:},{key:iris_license_available,val:290,oper:},{key:iris_trans_open_count,val:0,oper:},{key:memory,val:40,oper:}]对比维护指标与接口指标超过阈值发送邮件进行警报。
注这里双循环时间复杂O2数据量大效率可能会比较低需要注意下。
ClassMethod Main(url As %String, filename As %String) As %Status
{#; 获取接口指标Jsons irismetrics ##class(M.ParseMetrics).Main(url)#; 获取Csv维护指标Jsons config ##class(M.Mail).Csv2Json(filename)#; 双向对比维护指标超过阈值发送邮件警报for i 1 : 1 : irismetrics.%Size() - 1{s metrics irismetrics.%Get(i)for j 1 : 1 : config.%Size() - 1{s obj config.%Get(j)if (obj.key metrics.key) {if (metrics.val _ obj.oper _ obj.val) {s content obj.desc _ 警报超过阈值: _ obj.vald ..SendMailMessage(来自系统的警报,content)ret $$$NO} }}}#; 监控内存使用率接口中没有监视内存选项所以调用嵌入式接口s memory ..GetSystemMemory()if (memory 30) {d ..SendMailMessage(来自系统的警报,内存使用率已经大于 _ 30 _ )}ret $$$YES
}USERw ##class(M.Mail).Main(https://localhost:2443/api/monitor/metrics, E:\temp\metrics.csv)
0注这里基本思路已经实现可以通过挂任务或其他方式来定时轮询。
总结
以上是个人关于监控服务器指标、CPU、内存、警报的一些理解由于个人能力有限欢迎大家提出意见共同交流。
思考
IRIS还提供了alert警报接口该接口提供alert.log警报日志内容基于以上方案思考如何通过M程序进行监控
接口地址https://localhost:2443/api/monitor/alerts该接口有警报时会提示报警信息调用一次后清空。 如果有警报警报信息如下
{time:02/19/23-15:49:22:650,severity:2,message:Previous system shutdown was abnormal, system forced down or crashed.}附
/api/monitor/metrics指标含义列表
指标描述iris_cpu_pct {idProcessType}IRIS 进程类型的 CPU 使用百分比。 ProcessType 可以是以下任何一项ECPWorker、ECPCliR、ECPCliW、ECPSrvR、ECPSrvW、LICENSESRV、WDAUX、WRTDMN、JRNDMN、GARCOL、CSPDMN、CSPSRV、ODBCSRC、MirrorMaster、MirrorPri、MirrorBack、MirrorPre、MirrorSvrR、MirrorJrnR、MirrorSK、MirrorCommiris_cpu_usage操作系统上所有程序的 CPU 使用率百分比iris_csp_activity {idIPaddress:port}Web 网关服务器自启动以来处理的 Web 请求数iris_csp_actual_connections {idIPAddress:port}Web 网关服务器与该服务器的当前连接数iris_csp_gateway_latency {idIPaddress:port}获取 iris_csp_ 指标时从 Web 网关服务器获得响应的时间以毫秒为单位iris_csp_in_use_connections {idIPaddress:port}正在处理 Web 请求的 Web 网关服务器与此服务器的当前连接数iris_csp_private_connections {idIPaddress:port}为状态感知应用程序保留的 Web 网关服务器与此服务器的当前连接数保留模式 1iris_csp_sessions此服务器上当前活动的 Web 会话 ID 数iris_cache_efficiency全局引用与物理读写的比率以百分比表示iris_db_expansion_size_mb {iddatabase}扩展数据库的数量以兆字节为单位iris_db_free_space {iddatabase}数据库中可用的可用空间以兆字节为单位此指标每天仅更新一次可能不会反映最近的更改。iris_db_latency {iddatabase}完成从数据库随机读取的时间量以毫秒为单位iris_db_max_size_mb {iddatabase}数据库可以增长到的最大大小以兆字节为单位iris_db_size_mb {iddatabase,dirpath}数据库大小以兆字节为单位iris_directory_space {iddatabase,dirpath}数据库目录存储卷上的可用空间以兆字节为单位iris_disk_percent_full {iddatabase,dirpath}数据库目录存储卷上的空间百分比iris_ecp_conn此 ECP 应用程序服务器上的活动客户端连接总数iris_ecp_conn_max来自此 ECP 应用程序服务器的最大活动客户端连接数iris_ecp_connections此 ECP 应用程序服务器与其配置的 ECP 数据服务器同步时同步的服务器数iris_ecp_latencyECP 应用服务器和 ECP 数据服务器之间的延迟以毫秒为单位iris_ecps_conn每秒与此 ECP 数据服务器的活动客户端连接总数iris_ecps_conn_max与此 ECP 数据服务器的最大活动客户端连接数iris_glo_a_seize_per_sec每秒全局资源上的 Aseizes 数iris_glo_n_seize_per_sec每秒全局资源上的 Nseizes 数iris_glo_ref_per_sec每秒对位于本地数据库上的全局变量的引用数iris_glo_ref_rem_per_sec每秒对位于远程数据库上的全局变量的引用数iris_glo_seize_per_sec每秒占用全局资源的次数iris_glo_update_per_sec每秒对本地数据库上的全局变量进行更新SET 和 KILL 命令的次数iris_glo_update_rem_per_sec每秒对位于远程数据库上的全局变量的更新SET 和 KILL 命令数iris_jrn_block_per_sec每秒写入磁盘的日志块iris_jrn_free_space {idJournalType,dirpath}每个日志目录的存储卷上可用的可用空间以兆字节为单位。 JournalType 可以是 WIJ、primary 或 secondaryiris_jrn_size {idJournalType}每个日志文件的当前大小以兆字节为单位。 JournalType 可以是 WIJ、primary 或 secondaryiris_license_available当前未使用的许可证数量iris_license_consumed当前使用的许可证数量iris_license_percent_used当前使用的许可证的百分比iris_log_reads_per_sec每秒逻辑读取iris_obj_a_seize_per_sec每秒对象资源上的 Aseizes 数iris_obj_del_per_sec每秒删除的对象数iris_obj_hit_per_sec进程内存中每秒的对象引用数iris_obj_load_per_sec每秒从磁盘加载的对象数不在共享内存中iris_obj_miss_per_sec每秒在内存中找不到的对象引用数iris_obj_new_per_sec每秒初始化的对象数iris_obj_seize_per_sec每秒占用对象资源的次数iris_page_space_percent_used已用最大分配页面文件空间的百分比iris_phys_mem_percent_used当前使用的物理内存 (RAM) 的百分比iris_phys_reads_per_sec每秒从磁盘读取的物理数据库块iris_phys_writes_per_sec每秒写入磁盘的物理数据库块iris_process_count活跃的 IRIS 进程总数iris_rtn_a_seize_per_sec每秒例程资源上的 Aseizes 数iris_rtn_call_local_per_sec每秒对位于远程数据库上的全局变量的本地例程调用数iris_rtn_call_miss_per_sec每秒在内存中找不到的例程调用数iris_rtn_call_remote_per_sec每秒远程例程调用次数iris_rtn_load_per_sec每秒从本地加载或保存到磁盘的例程数iris_rtn_load_rem_per_sec每秒从磁盘远程加载或保存到磁盘的例程数iris_rtn_seize_per_sec每秒占用例程资源的次数iris_sam_get_db_sensors_seconds收集 iris_db* 传感器所花费的时间以秒为单位iris_sam_get_jrn_sensors_seconds收集 iris_jrn* 传感器所花费的时间以秒为单位iris_sam_get_sql_sensors_seconds收集 iris_sql* 传感器所花费的时间以秒为单位iris_sam_get_wqm_sensors_seconds收集 iris_wqm* 传感器所花费的时间以秒为单位iris_smh_available {idpurpose}按目的可用的共享内存以千字节为单位iris_smh_percent_full {idpurpose}按目的使用的已分配共享内存的百分比iris_smh_total为当前实例分配的共享内存以千字节为单位iris_smh_total_percent_full当前实例使用的已分配共享内存的百分比iris_smh_used {idpurpose}按目的使用的共享内存以千字节为单位iris_sql_active_queries {idnamespace}当前执行的 SQL语句数iris_sql_active_queries_95_percentile {idnamespace}对于当前的活动 SQL 语句集自语句开始执行以来经过的第 95 个百分位数的时间iris_sql_active_queries_99_percentile {idnamespace}对于当前活动的 SQL 语句集自语句开始执行以来经过的第 99 个百分位数的时间iris_sql_queries_avg_runtime {idnamespace}平均 SQL 语句运行时间以秒为单位iris_sql_queries_avg_runtime_std_dev {idnamespace}平均 SQL 语句运行时间的标准偏差iris_sql_queries_per_second {idnamespace}每秒平均 SQL 语句数iris_system_alerts自系统启动以来发布到消息日志的警报数iris_system_alerts_log当前位于警报日志中的警报数iris_system_alerts_new/api/monitor/alerts 端点上是否有新警报作为布尔值iris_system_state表示系统监视器健康状态的数字iris_trans_open_count当前实例上打开的事务数iris_trans_open_secs当前实例上打开事务的平均持续时间以秒为单位iris_trans_open_secs_max当前实例上当前打开的最长事务的iris_wd_buffer_redirty写入守护进程在最近一个周期中写入并且也在前一个周期中写入的数据库缓冲区数iris_wd_buffer_write写入守护进程在其最近周期写入的数据库缓冲区数iris_wd_cycle_time完成最近的写入守护进程周期所花费的时间量以毫秒为单位iris_wd_proc_in_global在最近的写入守护进程周期开始时主动持有全局缓冲区的进程数iris_wd_size_write写入守护程序在其最近周期写入的数据库缓冲区的大小以千字节为单位iris_wd_sleep写入守护进程在其最近的周期开始之前处于非活动状态的时间量以毫秒为单位iris_wd_temp_queue写入守护进程在其最近周期开始时使用的内存缓冲区数iris_wd_temp_write写入守护进程在其最近周期中写入的内存缓冲区数iris_wdwij_time写入守护进程在其最近的周期内写入 WIJ 文件所花费的时间以毫秒为单位iris_wd_write_time写守护进程在其最近的周期内将缓冲区写入数据库所花费的时间以毫秒为单位iris_wij_writes_per_secWIJ 每秒物理块写入iris_wqm_active_worker_jobs {idcategory}未被阻塞的运行逻辑的平均工作者作业数iris_wqm_commands_per_sec {idcategory}平均每秒在此工作队列管理类别中执行的命令数iris_wqm_globals_per_sec {idcategory}平均每秒在此工作队列管理类别中运行的全局引用数iris_wqm_max_active_worker_jobs {idcategory}自上次记录日志条目以来的最大活动工作人员数iris_wqm_max_work_queue_depth {idcategory}自上次记录以来此工作队列管理类别队列中的最大条目数iris_wqm_waiting_worker_jobs {idcategory}等待一个组连接并为其工作的空闲工人作业的平均数量