#!/usr/bin/env python
#
# A simple server monitor demo use Tencent cloud PutMonitorData api
import json
import os
import re
import socket
import sys
import time
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.monitor.v20180724 import monitor_client, models
GLOBAL_CONF = None
def load_conf():
conf_path = os.path.expanduser("~/.ServerMonitor.json")
if not os.path.exists(conf_path):
print("config file %s not found!" % conf_path)
sys.exit(1)
config_error_msg = """load config error, sample format:
{
"SecretId": "xxxxxxx",
"SecretKey": "xxxxxxx",
"Region": "ap-guangzhou"
}
"""
try:
conf = json.loads(open(conf_path).read())
if not isinstance(conf, dict):
raise ValueError("config file format error")
except:
print(config_error_msg)
sys.exit(1)
if not conf.get("SecretId") or not conf.get("SecretKey") or not conf.get("Region"):
print(config_error_msg)
sys.exit(1)
return conf
def get_lan_ip():
"""
get lan ip use fake udp connection
this does not really 'connect' to any server
"""
# can be any routable address,
fake_dest = ("10.10.10.10", 53)
lan_ip = ""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(fake_dest)
lan_ip = s.getsockname()[0]
s.close()
except Exception, e:
pass
# print >>sys.stderr, e
return lan_ip
class MonitorBase(object):
def __init__(self, sleep_time):
self.sleep_time = sleep_time
self.result1 = None;
def get_metrics(self):
"""
collect metrics from system
return metrics as dict: { "key1":v1, "key2": v2 }
"""
return {}
def process(self):
"""
call get_metrics twice between sleep_time and calc final result to report
return metrics as dict: { "key1":v1, "key2": v2 }
"""
result = self.get_metrics()
if self.sleep_time == 0:
return result
self.result1 = result
time.sleep(self.sleep_time)
result2 = self.get_metrics()
metrics = {}
for key in result2.keys():
metrics[key] = long(result2[key]) - long(result.get(key, 0))
# workaround value wrap
if metrics[key] < 0:
metrics[key] += 4294967296
return metrics
def report(self):
"""
report metrics to cloud api
:return:
"""
metrics = self.process()
try:
cred = credential.Credential(GLOBAL_CONF["SecretId"], GLOBAL_CONF["SecretKey"])
http_profile = HttpProfile()
http_profile.endpoint = "monitor.tencentcloudapi.com"
client_profile = ClientProfile()
client_profile.httpProfile = http_profile
client = monitor_client.MonitorClient(cred, GLOBAL_CONF["Region"], client_profile)
req = models.PutMonitorDataRequest()
from pprint import pprint
# limit metrics to report
metrics_allowed = ["TcpActiveOpens", "TcpPassiveOpens", "TcpAttemptFails", "TcpEstabResets",
"TcpRetransSegs", "TcpExtListenOverflows", "UdpInDatagrams", "UdpOutDatagrams",
"UdpInErrors", "UdpNoPorts", "UdpSndbufErrors"]
report_data = {"Metrics": [], "AnnounceInstance": get_lan_ip()}
for k, v in metrics.items():
if k in metrics_allowed:
report_data["Metrics"].append({"MetricName": k, "Value": v})
req.from_json_string(json.dumps(report_data))
pprint(report_data)
resp = client.PutMonitorData(req)
print(resp.to_json_string())
except TencentCloudSDKException as err:
print(err)
class NetMonitor(MonitorBase):
"""
parse /proc/net/snmp & /proc/net/netstat
"""
def get_metrics(self):
snmp_dict = {}
snmp_lines = open("/proc/net/snmp").readlines()
netstat_lines = open("/proc/net/netstat").readlines()
snmp_lines.extend(netstat_lines)
sep = re.compile(r'[:\s]+')
n = 0
for line in snmp_lines:
n += 1
fields = sep.split(line.strip())
proto = fields.pop(0)
if n % 2 == 1:
# header line
keys = fields
else:
# value line
try:
values = [long(f) for f in fields]
except Exception, e:
print e
kv = dict(zip(keys, values))
proto_dict = snmp_dict.setdefault(proto, {})
proto_dict.update(kv)
return snmp_dict
class NetSnmpIpTcpUdp(NetMonitor):
"""
Get ip/tcp/udp information from /proc/net/snmp
"""
def get_metrics(self):
snmp_dict = super(NetSnmpIpTcpUdp, self).get_metrics()
metrics = {}
for proto in ("Tcp", "Ip", "Udp", "Icmp", "TcpExt"):
if proto not in snmp_dict:
continue
for k, v in snmp_dict[proto].items():
k = proto + k
metrics[k] = v
return metrics
def process(self):
report_dict = super(NetSnmpIpTcpUdp, self).process()
# CurrEstab is a tmp value, not inc value
report_dict['TcpCurrEstab'] = self.result1['TcpCurrEstab']
return report_dict
if name == "main":
GLOBAL_CONF = load_conf()
process_dict = {
NetSnmpIpTcpUdp: 60,
}
children = []
for key in process_dict.keys():
try:
pid = os.fork()
except OSError:
sys.exit("Unable to create child process!")
if pid == 0:
monitor = key(process_dict[key])
monitor.report()
sys.exit(0)
else:
children.append(pid)
for i in children:
os.wait()</code></pre></div></div><blockquote><p>代码中 SecretId、SecretKey、Region 等信息需要根据您的实际情况填写。
Region:地域,可查询自定义监控可用 地域列表。
SecretId 和 SecretKey,请前往 API 密钥管理 获取。