提交 c4a5f3d4875bdce2a643b02f32bf132cbff972de

作者 qianyingz
1 个父辈 170b08aa

巡检服务、监控功能

@@ -7,8 +7,11 @@ @@ -7,8 +7,11 @@
7 from flasgger import swag_from 7 from flasgger import swag_from
8 from flask import Blueprint 8 from flask import Blueprint
9 from app.util import BlueprintApi 9 from app.util import BlueprintApi
  10 +from . import monitor_info, monitoring, metrics, monitor_host_create, monitor_host_list, monitor_host_delete, monitor_host_edit
10 11
11 -from . import monitor_info, monitoring 12 +
  13 +user_socket_list = []
  14 +user_socket_dict = {}
12 15
13 16
14 class Monitor(BlueprintApi): 17 class Monitor(BlueprintApi):
@@ -32,3 +35,48 @@ class Monitor(BlueprintApi): @@ -32,3 +35,48 @@ class Monitor(BlueprintApi):
32 基础监控 35 基础监控
33 """ 36 """
34 return monitoring.Api().result 37 return monitoring.Api().result
  38 +
  39 + @staticmethod
  40 + @bp.route('/metrics', methods=['GET'])
  41 + @swag_from(metrics.Api.api_doc)
  42 + def metrics():
  43 + '''
  44 + 指标统计
  45 + '''
  46 + return metrics.Api().result
  47 +
  48 + @staticmethod
  49 + @bp.route('/RegisterHost', methods=['POST'])
  50 + @swag_from(monitor_host_create.Api.api_doc)
  51 + def monitor_host_create():
  52 + '''
  53 + 注册监控主机
  54 + '''
  55 + return monitor_host_create.Api().result
  56 +
  57 + @staticmethod
  58 + @bp.route('/HostList', methods=['GET'])
  59 + @swag_from(monitor_host_list.Api.api_doc)
  60 + def monitor_host_list():
  61 + '''
  62 + 获取监控主机列表
  63 + '''
  64 + return monitor_host_list.Api().result
  65 +
  66 + @staticmethod
  67 + @bp.route('/HostDelete', methods=['POST'])
  68 + @swag_from(monitor_host_delete.Api.api_doc)
  69 + def monitor_host_delete():
  70 + '''
  71 + 删除主机
  72 + '''
  73 + return monitor_host_delete.Api().result
  74 +
  75 + @staticmethod
  76 + @bp.route('/HostEdit', methods=['POST'])
  77 + @swag_from(monitor_host_edit.Api.api_doc)
  78 + def monitor_host_edit():
  79 + '''
  80 + 编辑主机配置
  81 + '''
  82 + return monitor_host_edit.Api().result
  1 +from datetime import datetime, timedelta
  2 +
  3 +from sqlalchemy.sql.functions import func
  4 +from .models import MonitorLog, db
  5 +from sqlalchemy import and_
  6 +from app.util.component.ApiTemplate import ApiTemplate
  7 +
  8 +
  9 +class Api(ApiTemplate):
  10 + api_name = "统计指标"
  11 +
  12 + def process(self):
  13 +
  14 + # 返回结果
  15 + res = {}
  16 + res["data"] = {}
  17 + logs = []
  18 + try:
  19 + server = self.para.get("server") # server
  20 + # metrics_type = self.para.get("metrics_type")
  21 + grain = self.para.get("grain")
  22 + count = int(self.para.get("count"))
  23 + start_time = self.para.get("start")
  24 + to_time = self.para.get("to")
  25 +
  26 + cur_now = datetime.now()
  27 + start_datetime = datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")
  28 + end_datetime = datetime.strptime(to_time, "%Y-%m-%d %H:%M:%S")
  29 +
  30 + if grain == "day":
  31 + # 粒度是一天
  32 + format = "%Y-%m-%d"
  33 + logs = db.session.query(MonitorLog.date_stamp.label("key"), func.avg(MonitorLog.cpu_usage).label("cpu_usage"),
  34 + func.avg(MonitorLog.total_mem).label(
  35 + "total_mem"),
  36 + func.avg(MonitorLog.available_mem).label(
  37 + "available_mem"),
  38 + func.avg(MonitorLog.used_mem).label(
  39 + "used_mem"),
  40 + func.avg(MonitorLog.disk).label(
  41 + "disk"),
  42 + func.avg(MonitorLog.disk_usage).label(
  43 + "disk_usage"),
  44 + func.avg(MonitorLog.net_recv).label(
  45 + "net_recv"),
  46 + func.avg(MonitorLog.net_send).label("net_send")).filter(and_(
  47 + MonitorLog.date_stamp <= end_datetime.strftime(
  48 + format),
  49 + MonitorLog.date_stamp > start_datetime.strftime(
  50 + format),
  51 + MonitorLog.server == server)).group_by(MonitorLog.date_stamp).order_by(MonitorLog.date_stamp.asc()).all()
  52 +
  53 + keys = []
  54 + keys_map = {}
  55 + while start_datetime <= end_datetime:
  56 + keys.append(self.get_monitor_log(
  57 + start_datetime.strftime('%Y-%m-%d')))
  58 + keys_map[start_datetime.strftime('%Y-%m-%d')] = len(keys)-1
  59 + start_datetime += timedelta(days=1)
  60 +
  61 + res["data"] = self.get_result(logs, keys, keys_map)
  62 + elif grain == "minu_five":
  63 + # 粒度是5分钟
  64 + cur_minu = int(end_datetime.strftime("%M")) % 5
  65 + logs = db.session.query(MonitorLog.hour_stamp.label("hour_stamp"),
  66 + MonitorLog.f_minu_stamp.label(
  67 + "minu_stamp"),
  68 + func.avg(MonitorLog.cpu_usage).label(
  69 + "cpu_usage"),
  70 + func.avg(MonitorLog.total_mem).label(
  71 + "total_mem"),
  72 + func.avg(MonitorLog.available_mem).label(
  73 + "available_mem"),
  74 + func.avg(MonitorLog.used_mem).label(
  75 + "used_mem"),
  76 + func.avg(MonitorLog.disk).label(
  77 + "disk"),
  78 + func.avg(MonitorLog.disk_usage).label(
  79 + "disk_usage"),
  80 + func.avg(MonitorLog.net_recv).label(
  81 + "net_recv"),
  82 + func.avg(MonitorLog.net_send).label("net_send")).filter(and_(
  83 + MonitorLog.time_stamp <= "{}:00".format(
  84 + end_datetime.strftime("%Y-%m-%d %H:%M")),
  85 + MonitorLog.time_stamp >= "{}:00".format(
  86 + start_datetime.strftime("%Y-%m-%d %H:%M")),
  87 + MonitorLog.server == server)).group_by(MonitorLog.date_stamp, MonitorLog.hour_stamp, MonitorLog.f_minu_stamp).order_by(
  88 + MonitorLog.hour_stamp.asc(), MonitorLog.f_minu_stamp.asc()).all()
  89 +
  90 + keys = []
  91 + keys_map = {}
  92 + while start_datetime <= end_datetime:
  93 + key = start_datetime.strftime('%H:%M')
  94 + keys.append(self.get_monitor_log(key))
  95 + keys_map[key] = len(keys)-1
  96 + start_datetime += timedelta(minutes=5)
  97 +
  98 + logs = list(map(lambda log:
  99 + {"key": "%02d:%02d" % (log.hour_stamp, log.minu_stamp*5+cur_minu),
  100 + "cpu_usage": log.cpu_usage, "total_mem": log.total_mem,
  101 + "available_mem": log.available_mem, "used_mem": log.used_mem, "disk": log.disk, "disk_usage": log.disk_usage,
  102 + "net_recv": log.net_recv, "net_send": log.net_send},
  103 + logs))
  104 +
  105 + res["data"] = self.get_result_from_list(logs, keys, keys_map)
  106 + elif grain == "minu_ten":
  107 + # 粒度是10分钟
  108 + cur_minu = int(end_datetime.strftime("%M")) % 10
  109 + logs = db.session.query(MonitorLog.hour_stamp.label("hour_stamp"),
  110 + MonitorLog.d_minu_stamp.label(
  111 + "minu_stamp"),
  112 + func.avg(MonitorLog.cpu_usage).label(
  113 + "cpu_usage"),
  114 + func.avg(MonitorLog.total_mem).label(
  115 + "total_mem"),
  116 + func.avg(MonitorLog.available_mem).label(
  117 + "available_mem"),
  118 + func.avg(MonitorLog.used_mem).label(
  119 + "used_mem"),
  120 + func.avg(MonitorLog.disk).label(
  121 + "disk"),
  122 + func.avg(MonitorLog.disk_usage).label(
  123 + "disk_usage"),
  124 + func.avg(MonitorLog.net_recv).label(
  125 + "net_recv"),
  126 + func.avg(MonitorLog.net_send).label("net_send")).filter(and_(
  127 + MonitorLog.time_stamp <= "{}:00".format(
  128 + end_datetime.strftime("%Y-%m-%d %H:%M")),
  129 + MonitorLog.time_stamp >= "{}:00".format(
  130 + start_datetime.strftime("%Y-%m-%d %H:%M")),
  131 + MonitorLog.server == server)).group_by(MonitorLog.date_stamp,
  132 + MonitorLog.hour_stamp,
  133 + MonitorLog.d_minu_stamp).order_by(MonitorLog.hour_stamp.asc(), MonitorLog.d_minu_stamp.asc()).all()
  134 + keys = []
  135 + keys_map = {}
  136 + while start_datetime <= end_datetime:
  137 + key = start_datetime.strftime('%H:%M')
  138 + keys.append(self.get_monitor_log(key))
  139 + keys_map[key] = len(keys)-1
  140 + start_datetime += timedelta(minutes=10)
  141 +
  142 + logs = list(map(lambda log:
  143 + {"key": "%02d:%02d" % (log.hour_stamp, log.minu_stamp*10+cur_minu),
  144 + "cpu_usage": log.cpu_usage, "total_mem": log.total_mem,
  145 + "available_mem": log.available_mem, "used_mem": log.used_mem, "disk": log.disk, "disk_usage": log.disk_usage,
  146 + "net_recv": log.net_recv, "net_send": log.net_send},
  147 + logs))
  148 +
  149 + res["data"] = self.get_result_from_list(logs, keys, keys_map)
  150 + elif grain == "hour":
  151 + # 粒度是一小时
  152 + logs = db.session.query(MonitorLog.hour_stamp.label("key"), func.avg(MonitorLog.cpu_usage).label("cpu_usage"),
  153 + func.avg(MonitorLog.total_mem).label(
  154 + "total_mem"),
  155 + func.avg(MonitorLog.available_mem).label(
  156 + "available_mem"),
  157 + func.avg(MonitorLog.used_mem).label(
  158 + "used_mem"),
  159 + func.avg(MonitorLog.disk).label(
  160 + "disk"),
  161 + func.avg(MonitorLog.disk_usage).label(
  162 + "disk_usage"),
  163 + func.avg(MonitorLog.net_recv).label(
  164 + "net_recv"),
  165 + func.avg(MonitorLog.net_send).label("net_send")).filter(and_(
  166 + MonitorLog.time_stamp <= "{}:59:59".format(
  167 + end_datetime.strftime("%Y-%m-%d %H")),
  168 + MonitorLog.time_stamp >= "{}:59:59".format(
  169 + start_datetime.strftime("%Y-%m-%d %H")),
  170 + MonitorLog.server == server)).group_by(MonitorLog.hour_stamp).order_by(MonitorLog.hour_stamp.asc()).all()
  171 + keys = []
  172 + keys_map = {}
  173 + while start_datetime <= end_datetime:
  174 + key = int(start_datetime.strftime('%H'))
  175 + keys.append(self.get_monitor_log("%02d时" % key))
  176 + keys_map[str(key)] = len(keys)-1
  177 + start_datetime += timedelta(hours=1)
  178 +
  179 + res["data"] = self.get_result(logs, keys, keys_map)
  180 + else:
  181 + # 按分钟统计
  182 + logs = db.session.query(MonitorLog.hour_stamp.label("hour_stamp"), MonitorLog.minu_stamp.label("minu_stamp"), func.avg(MonitorLog.cpu_usage).label("cpu_usage"),
  183 + func.avg(MonitorLog.total_mem).label(
  184 + "total_mem"),
  185 + func.avg(MonitorLog.available_mem).label(
  186 + "available_mem"),
  187 + func.avg(MonitorLog.used_mem).label("used_mem"),
  188 + func.avg(MonitorLog.disk).label(
  189 + "disk"),
  190 + func.avg(MonitorLog.disk_usage).label(
  191 + "disk_usage"),
  192 + func.avg(MonitorLog.net_recv).label(
  193 + "net_recv"),
  194 + func.avg(MonitorLog.net_send).label("net_send")).filter(and_(
  195 + MonitorLog.time_stamp <= end_datetime.strftime("%Y-%m-%d %H:%M:%S"),
  196 + MonitorLog.time_stamp >= start_datetime.strftime("%Y-%m-%d %H:%M:%S"),
  197 + MonitorLog.server == server)).group_by(MonitorLog.hour_stamp, MonitorLog.minu_stamp).order_by(
  198 + MonitorLog.hour_stamp.asc(), MonitorLog.minu_stamp.asc()).all()
  199 + keys = []
  200 + keys_map = {}
  201 + while start_datetime <= end_datetime:
  202 + key = start_datetime.strftime('%H:%M')
  203 + keys.append(self.get_monitor_log(key))
  204 + keys_map[key] = len(keys)-1
  205 + start_datetime += timedelta(minutes=1)
  206 +
  207 + logs = list(map(lambda log:
  208 + {"key": "%02d:%02d" % (log.hour_stamp, log.minu_stamp),
  209 + "cpu_usage": log.cpu_usage, "total_mem": log.total_mem,
  210 + "available_mem": log.available_mem, "used_mem": log.used_mem, "disk": log.disk, "disk_usage": log.disk_usage,
  211 + "net_recv": log.net_recv, "net_send": log.net_send},
  212 + logs))
  213 +
  214 + res["data"] = self.get_result_from_list(logs, keys, keys_map)
  215 + res["result"] = True
  216 + except Exception as e:
  217 + raise e
  218 + return res
  219 +
  220 + api_doc = {
  221 + "tags": ["监控接口"],
  222 + "parameters": [
  223 + {"name": "server",
  224 + "in": "query",
  225 + "type": "string",
  226 + "description": "服务器地址"},
  227 + {"name": "grain",
  228 + "in": "query",
  229 + "type": "string",
  230 + "description": "指标粒度:minu:分钟,minu_five:5分钟,minu_ten:10分钟,hour:1小时,day:每天"},
  231 + {"name": "count",
  232 + "in": "query",
  233 + "type": "string",
  234 + "description": "个数"},
  235 + {"name": "to",
  236 + "in": "query",
  237 + "type": "string",
  238 + "description": "查询终止时间"},
  239 + {"name": "start",
  240 + "in": "query",
  241 + "type": "string",
  242 + "description": "查询起始时间"}
  243 + ],
  244 + "responses": {
  245 + 200: {
  246 + "schema": {
  247 + "properties": {
  248 + }
  249 + }
  250 + }
  251 + }
  252 + }
  253 +
  254 + def get_monitor_log(self, key):
  255 + return {"key": key,
  256 + "cpu_usage": None, "total_mem": None,
  257 + "available_mem": None, "used_mem": None, "disk": None, "disk_usage": None,
  258 + "net_recv": None, "net_send": None}
  259 +
  260 + def get_result(self, logs, keys, keys_map):
  261 + keys_map_key=keys_map.keys()
  262 + for log in logs:
  263 + if str(log.key) in keys_map_key:
  264 + tmp = keys[keys_map[str(log.key)]]
  265 + if tmp != None:
  266 + tmp['cpu_usage'] = log.cpu_usage
  267 + tmp['total_mem'] = log.total_mem
  268 + tmp['available_mem'] = log.available_mem
  269 + tmp['used_mem'] = log.used_mem
  270 + tmp['disk'] = log.disk
  271 + tmp['disk_usage'] = log.disk_usage
  272 + tmp['net_recv'] = log.net_recv
  273 + tmp['net_send'] = log.net_send
  274 + return keys
  275 +
  276 + def get_result_from_list(self, logs, keys, keys_map):
  277 + keys_map_key=keys_map.keys()
  278 + for log in logs:
  279 + if str(log["key"]) in keys_map_key:
  280 + tmp = keys[keys_map[str(log["key"])]]
  281 + if tmp != None:
  282 + tmp['cpu_usage'] = log["cpu_usage"]
  283 + tmp['total_mem'] = log["total_mem"]
  284 + tmp['available_mem'] = log["available_mem"]
  285 + tmp['used_mem'] = log["used_mem"]
  286 + tmp['disk'] = log["disk"]
  287 + tmp['disk_usage'] = log["disk_usage"]
  288 + tmp['net_recv'] = log["net_recv"]
  289 + tmp['net_send'] = log["net_send"]
  290 + return keys
1 # coding=utf-8 1 # coding=utf-8
2 -#author: 4N 2 +# author: 4N
3 #createtime: 2021/6/11 3 #createtime: 2021/6/11
4 #email: nheweijun@sina.com 4 #email: nheweijun@sina.com
5 5
6 6
7 -from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime, Time 7 +from datetime import datetime
  8 +from time import time
  9 +from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime, Time, Float, Binary
  10 +from sqlalchemy.orm import relationship
  11 +from sqlalchemy.sql.expression import column
8 from app.models import db 12 from app.models import db
9 13
  14 +
  15 +class MonitorLog(db.Model):
  16 + '''
  17 + '''
  18 + __tablename__ = "dmap_monitor_log"
  19 + guid = Column(String(256), primary_key=True)
  20 + server = Column(String(256))
  21 + date_stamp = Column(Text)
  22 + hour_stamp = Column(Integer)
  23 + minu_stamp = Column(Integer)
  24 + d_minu_stamp = Column(Integer) # 10min粒度 1-6
  25 + f_minu_stamp = Column(Integer) # 5min粒度 1~12
  26 + time_stamp = Column(DateTime) # 创建时间戳
  27 + cpu_usage = Column(Float)
  28 + total_mem = Column(Float)
  29 + available_mem = Column(Float)
  30 + used_mem = Column(Float)
  31 + disk = Column(Float)
  32 + disk_usage = Column(Float)
  33 + net_recv = Column(Float)
  34 + net_send = Column(Float)
  35 +
  36 +
  37 +class MonitorHost(db.Model):
  38 + '''
  39 + 监控服务器配置
  40 + '''
  41 + __tablename__ = "dmap_monitor_host"
  42 + srcid = Column(String(256), primary_key=True)
  43 + host = Column(String(256))
  44 + user = Column(String(256))
  45 + password = Column(String(256))
  46 + type = Column(String(256))
  47 + host_name=Column(String(256))
  1 +from .models import MonitorHost, db
  2 +from sqlalchemy import and_
  3 +from app.util.component.ApiTemplate import ApiTemplate
  4 +import uuid
  5 +
  6 +
  7 +class Api(ApiTemplate):
  8 + api_name = "注册主机"
  9 +
  10 + def para_check(self):
  11 + if not self.para.get("host"):
  12 + raise Exception("缺乏host参数")
  13 + if not self.para.get("user"):
  14 + raise Exception("缺乏user参数")
  15 + if not self.para.get("type"):
  16 + raise Exception("缺乏type参数")
  17 + if not self.para.get("passwd"):
  18 + raise Exception("缺乏passwd参数")
  19 +
  20 + def process(self):
  21 +
  22 + # 返回结果
  23 + res = {}
  24 + res["data"] = {}
  25 + try:
  26 + host = self.para.get("host") # server
  27 + user = self.para.get("user")
  28 + password = self.para.get("passwd")
  29 + type = self.para.get("type")
  30 + host_name = self.para.get("host_name")
  31 + srcid = uuid.uuid1().__str__()
  32 +
  33 + if(db.session.query(MonitorHost.host).filter(MonitorHost.host == host).count() > 0):
  34 + res['message'] = '禁止重复注册host'
  35 + res["result"] = False
  36 + else:
  37 + monitorHost = MonitorHost(
  38 + srcid=srcid, host=host, user=user, password=password, type=type, host_name=host_name)
  39 + db.session.add(monitorHost)
  40 + db.session.commit()
  41 + res['data'] = {'host': host, 'srcid': srcid}
  42 + res["result"] = True
  43 + except Exception as e:
  44 + db.session.rollback()
  45 + raise e
  46 + return res
  47 +
  48 + api_doc = {
  49 + "tags": ["监控接口"],
  50 + "parameters": [
  51 + {"name": "host",
  52 + "in": "formData",
  53 + "type": "string",
  54 + "description": "主机地址",
  55 + "required": "true"},
  56 + {"name": "user",
  57 + "in": "formData",
  58 + "type": "string",
  59 + "description": "用户",
  60 + "required": "true"},
  61 + {"name": "passwd",
  62 + "in": "formData",
  63 + "type": "string",
  64 + "description": "密码",
  65 + "required": "true"},
  66 + {"name": "type",
  67 + "in": "formData",
  68 + "type": "string",
  69 + "description": "服务器类型",
  70 + "required": "true"},
  71 + {"name": "host_name",
  72 + "in": "formData",
  73 + "type": "string",
  74 + "description": "主机名"}
  75 + ],
  76 + "responses": {
  77 + 200: {
  78 + "schema": {
  79 + "properties": {
  80 + }
  81 + }
  82 + }
  83 + }
  84 + }
  1 +from .models import MonitorHost, db
  2 +from sqlalchemy import and_
  3 +from app.util.component.ApiTemplate import ApiTemplate
  4 +import uuid
  5 +
  6 +
  7 +class Api(ApiTemplate):
  8 + api_name = "注销主机"
  9 +
  10 + def para_check(self):
  11 + if not self.para.get("srcid"):
  12 + raise Exception("缺乏host参数")
  13 +
  14 + def process(self):
  15 +
  16 + # 返回结果
  17 + res = {}
  18 + res["data"] = {}
  19 + try:
  20 + srcid = self.para.get("srcid") # server
  21 + monitor_host = MonitorHost.query.filter_by(
  22 + srcid=srcid).one_or_none()
  23 + if monitor_host:
  24 + db.session.delete(monitor_host)
  25 + db.session.commit()
  26 + res["result"] = True
  27 + res["message"] = "删除成功,srcid:{}".format(srcid)
  28 + else:
  29 + res['message'] = 'host不存在,无法注销'
  30 + res["result"] = False
  31 + except Exception as e:
  32 + db.session.rollback()
  33 + raise e
  34 + return res
  35 +
  36 + api_doc = {
  37 + "tags": ["监控接口"],
  38 + "parameters": [
  39 + {"name": "srcid",
  40 + "in": "formData",
  41 + "type": "string",
  42 + "description": "srcid值",
  43 + "required": "true"}
  44 + ],
  45 + "responses": {
  46 + 200: {
  47 + "schema": {
  48 + "properties": {
  49 + }
  50 + }
  51 + }
  52 + }
  53 + }
  1 +from .models import MonitorHost, MonitorLog, db
  2 +from sqlalchemy import and_
  3 +from app.util.component.ApiTemplate import ApiTemplate
  4 +import uuid
  5 +
  6 +
  7 +class Api(ApiTemplate):
  8 + api_name = "编辑主机配置"
  9 +
  10 + def para_check(self):
  11 + if not self.para.get("srcid"):
  12 + raise Exception("缺乏host参数")
  13 +
  14 + def process(self):
  15 +
  16 + # 返回结果
  17 + res = {}
  18 + res["data"] = {}
  19 + try:
  20 + srcid = self.para.get("srcid") # server
  21 + passwd = self.para.get("passwd")
  22 + host_name = self.para.get("host_name")
  23 + # Catalog.query.filter_by(guid=self.para.get("guid")).update({"name":self.para.get("name")})
  24 +
  25 + if passwd or host_name:
  26 + monitor_host = MonitorHost.query.filter_by(srcid=srcid)
  27 + if passwd:
  28 + monitor_host.update({"password": passwd})
  29 + if host_name:
  30 + monitor_host.update({"host_name": host_name})
  31 + db.session.commit()
  32 +
  33 + res["result"] = True
  34 + res["message"] = "更新成功".format(srcid)
  35 +
  36 + except Exception as e:
  37 + db.session.rollback()
  38 + raise e
  39 + return res
  40 +
  41 + api_doc = {
  42 + "tags": ["监控接口"],
  43 + "parameters": [
  44 + {"name": "srcid",
  45 + "in": "formData",
  46 + "type": "string",
  47 + "description": "srcid值",
  48 + "required": "true"},
  49 + {"name": "host_name",
  50 + "in": "formData",
  51 + "type": "string",
  52 + "description": "主机名"},
  53 + {"name": "passwd",
  54 + "in": "formData",
  55 + "type": "string",
  56 + "description": "密码"}
  57 + ],
  58 + "responses": {
  59 + 200: {
  60 + "schema": {
  61 + "properties": {
  62 + }
  63 + }
  64 + }
  65 + }
  66 + }
  1 +from sqlalchemy.sql.functions import func
  2 +from .models import MonitorHost, db
  3 +from sqlalchemy import and_
  4 +from app.util.component.ApiTemplate import ApiTemplate
  5 +
  6 +
  7 +class Api(ApiTemplate):
  8 + api_name = "监控主机列表"
  9 +
  10 + def process(self):
  11 +
  12 + # 返回结果
  13 + res = {}
  14 + res["data"] = []
  15 + logs = []
  16 + try:
  17 + datas = db.session.query(
  18 + MonitorHost.host.label("host"), MonitorHost.srcid.label(
  19 + "srcid"), MonitorHost.type.label("type"),
  20 + MonitorHost.host_name.label("host_name"),
  21 + MonitorHost.user.label("user")).all()
  22 + res["data"] = list(map(lambda data:
  23 + {'host': data.host, 'srcid': data.srcid,
  24 + 'type': data.type, 'host_name': data.host_name,
  25 + 'user': data.user},
  26 + datas))
  27 + res["result"] = True
  28 + except Exception as e:
  29 + raise e
  30 + return res
  31 +
  32 + api_doc = {
  33 + "tags": ["监控接口"],
  34 + "parameters": [
  35 + ],
  36 + "responses": {
  37 + 200: {
  38 + "schema": {
  39 + "properties": {
  40 + }
  41 + }
  42 + }
  43 + }
  44 + }
@@ -27,6 +27,9 @@ class Api(ApiTemplate): @@ -27,6 +27,9 @@ class Api(ApiTemplate):
27 mem_total = int(psutil.virtual_memory()[0]) 27 mem_total = int(psutil.virtual_memory()[0])
28 mem_used = int(psutil.virtual_memory()[3]) 28 mem_used = int(psutil.virtual_memory()[3])
29 mem_per = int(psutil.virtual_memory()[2]) 29 mem_per = int(psutil.virtual_memory()[2])
  30 +
  31 + network_sent = int(psutil.net_io_counters()[0] / 8 ) # 每秒接受的kb
  32 + network_recv = int(psutil.net_io_counters()[1] / 8 )
30 33
31 res["data"]["memory"] = { 34 res["data"]["memory"] = {
32 'total': self.format_value(mem_total), 35 'total': self.format_value(mem_total),
@@ -36,8 +39,7 @@ class Api(ApiTemplate): @@ -36,8 +39,7 @@ class Api(ApiTemplate):
36 39
37 40
38 41
39 - network_sent = int(psutil.net_io_counters()[0] / 8 ) # 每秒接受的kb  
40 - network_recv = int(psutil.net_io_counters()[1] / 8 ) 42 +
41 43
42 res["data"]["network"] = { 44 res["data"]["network"] = {
43 'sent': self.format_value(network_sent), 45 'sent': self.format_value(network_sent),
@@ -74,8 +76,4 @@ class Api(ApiTemplate): @@ -74,8 +76,4 @@ class Api(ApiTemplate):
74 value = "{}KB".format(format(value / 1024.0, '.1f')) 76 value = "{}KB".format(format(value / 1024.0, '.1f'))
75 else: 77 else:
76 value = "{}B".format(format(value, '.1f')) 78 value = "{}B".format(format(value, '.1f'))
77 - return value  
78 -  
79 -if __name__ == '__main__':  
80 - api = Api()  
81 - api.process() 79 + return value
1 from app.models import * 1 from app.models import *
2 from app.util.component.ApiTemplate import ApiTemplate 2 from app.util.component.ApiTemplate import ApiTemplate
3 -import paramiko  
4 -import time  
5 - 3 +import json
  4 +import os
6 5
7 class Api(ApiTemplate): 6 class Api(ApiTemplate):
8 api_name = "远程监控" 7 api_name = "远程监控"
@@ -13,76 +12,17 @@ class Api(ApiTemplate): @@ -13,76 +12,17 @@ class Api(ApiTemplate):
13 res = {} 12 res = {}
14 res["data"] = {} 13 res["data"] = {}
15 try: 14 try:
16 - # 业务逻辑  
17 - client = paramiko.SSHClient()  
18 - client.set_missing_host_key_policy(paramiko.AutoAddPolicy)  
19 - client.connect(hostname='172.26.60.100',  
20 - username='root', password='DMap@123')  
21 - # cpu  
22 - order = "top -b -n1 | sed -n '3p' | awk '{print $2}'"  
23 - stdin, stdout, stderr = client.exec_command(order)  
24 - cpu_usage = stdout.read().decode().split("\n")[0] # cpu使用率  
25 -  
26 - # 内存  
27 - order = "free -h | sed -n '2p' | awk '{print $2}'"  
28 - stdin, stdout, stderr = client.exec_command(order)  
29 - totalMem = stdout.read().decode().split("\n")[0] # 总内存  
30 -  
31 - order = "free -h | sed -n '3p' | awk '{print $3}'"  
32 - stdin, stdout, stderr = client.exec_command(order)  
33 - freeMem = stdout.read().decode().split("\n")[0] # 空余内存  
34 -  
35 - # disk  
36 - order = "df -m | grep -v 'overlay\|Filesystem' | awk '{print $1,$2,$3}' | grep /dev | awk '{print $2}' | awk -v total=0 '{total+=$1}END{print total}'"  
37 - stdin, stdout, stderr = client.exec_command(order)  
38 - totalDisk = int(stdout.read().decode().split("\n")  
39 - [0]) # 总磁盘空间,单位Mb  
40 -  
41 - order = "df -m | grep -v 'overlay\|Filesystem' | awk '{print $1,$2,$3}' | grep /dev | awk '{print $3}' | awk -v total=0 '{total+=$1}END{print total}'"  
42 - stdin, stdout, stderr = client.exec_command(order)  
43 - usedDisk = int(stdout.read().decode().split("\n")  
44 - [0]) # 已使用磁盘空间,单位Mb  
45 -  
46 - # network  
47 - # 接收的字节数  
48 - rx_time = []  
49 - rx_bytes = []  
50 - tx_time = []  
51 - tx_bytes = []  
52 -  
53 - # 接收的字节数  
54 - order = "ifconfig | grep RX | grep -v 'errors'| awk -v total=0 '{total+=$5}END{print total}'"  
55 - i = 0  
56 - while i < 2:  
57 - i = i+1  
58 - stdin, stdout, stderr = client.exec_command(order)  
59 - rx_time.append(time.time())  
60 - rx_bytes.append(int(stdout.read().decode().split("\n")[0]))  
61 -  
62 - # 发送的字节数  
63 - order = "ifconfig | grep TX | grep -v 'errors'| awk -v total=0 '{total+=$5}END{print total}'"  
64 - i = 0  
65 - while i < 2:  
66 - i = i+1  
67 - stdin, stdout, stderr = client.exec_command(order)  
68 - tx_time.append(time.time())  
69 - tx_bytes.append(int(stdout.read().decode().split("\n")[0]))  
70 -  
71 - res["data"] = {  
72 - "cpuUsage": "{}%".format(cpu_usage),  
73 - "totalMemory": "{}".format(totalMem),  
74 - "freeMemory": "{}".format(freeMem),  
75 - "totalDisk": "{}".format(self.format_value(totalDisk*1024**2)),  
76 - "usedDisk": "{}".format(self.format_value(usedDisk*1024**2)),  
77 - "networkRecv": "{}".format(self.format_value((rx_bytes[1] - rx_bytes[0])/(rx_time[1]-rx_time[0]))),  
78 - "networkSend": "{}".format(self.format_value((tx_bytes[1] - tx_bytes[0])/(tx_time[1]-tx_time[0])))  
79 - }  
80 - 15 + base_dir = os.getcwd()
  16 +
  17 + # 监控文件
  18 + monitor_filepath = os.path.join(base_dir, 'file', 'monitor_log.txt')
  19 + monitor_file = open(monitor_filepath, "r")
  20 + log = monitor_file.read()
  21 + monitor_file.close()
  22 + res["data"]=json.loads(log)
81 res["result"] = True 23 res["result"] = True
82 except Exception as e: 24 except Exception as e:
83 raise e 25 raise e
84 - finally:  
85 - client.close()  
86 return res 26 return res
87 27
88 api_doc = { 28 api_doc = {
@@ -101,17 +41,22 @@ class Api(ApiTemplate): @@ -101,17 +41,22 @@ class Api(ApiTemplate):
101 } 41 }
102 42
103 def format_value(self, value): 43 def format_value(self, value):
104 - if value > 1024**3:  
105 - value = "{}GB".format(format(value/1024.0**3, '.1f')) 44 + # 1024*1024*1024
  45 + if value > 1_073_741_824:
  46 + value = "{}GB".format(format(value/1_073_741_824, '.1f'))
106 elif value > 1024**2: 47 elif value > 1024**2:
107 - value = "{}MB".format(format(value / 1024.0 ** 2, '.1f')) 48 + value = "{}MB".format(format(value / 1_048_576, '.1f'))
108 elif value > 1024: 49 elif value > 1024:
  50 + # 1024*1024
109 value = "{}KB".format(format(value / 1024.0, '.1f')) 51 value = "{}KB".format(format(value / 1024.0, '.1f'))
110 else: 52 else:
111 value = "{}B".format(format(value, '.1f')) 53 value = "{}B".format(format(value, '.1f'))
112 return value 54 return value
113 -  
114 -  
115 -if __name__ == '__main__':  
116 - api = Api()  
117 - api.process() 55 +
  56 +
  57 + def Mb_format_value(self,value):
  58 + if value > 1024:
  59 + value = "{}GB".format(format(value/1024, '.1f'))
  60 + else:
  61 + value = "{}MB".format(format(value, '.1f'))
  62 + return value
  1 +# import schedule
  2 +import os
  3 +import paramiko
  4 +from .models import MonitorHost, MonitorLog
  5 +import datetime
  6 +import math
  7 +import time
  8 +import uuid
  9 +import schedule
  10 +from app.util.component.RunContinuous import run_continuously
  11 +from app.util.component.PGUtil import PGUtil
  12 +import configure
  13 +
  14 +
  15 +def background_job():
  16 + try:
  17 + # print('Hello from the background thread')
  18 + # base_dir = os.getcwd()
  19 +
  20 + # 命令文件
  21 + # cmd_filepath = os.path.join(base_dir, "file", "monitor.txt")
  22 + # cmd_file = open(cmd_filepath, "r")
  23 + # cmd = cmd_file.read()
  24 + # cmd_file.close()
  25 + # servers = [{'sid': 'src1', 'hostname': '172.26.99.160',
  26 + # 'username': 'monitor', 'password': '123456'},
  27 + # {'sid': 'src2', 'hostname': '172.26.60.100',
  28 + # 'username': 'root', 'password': 'DMap@123'}]
  29 +
  30 + cur_time = datetime.datetime.now()
  31 + time_stamp = cur_time.strftime(
  32 + "%Y-%m-%d %H:%M:%S")
  33 + struct_time = time.strptime(time_stamp, "%Y-%m-%d %H:%M:%S")
  34 + d_minu_stamp = math.floor(struct_time.tm_min/10)
  35 + f_minu_stamp = math.floor(struct_time.tm_min/5)
  36 +
  37 + sys_session = PGUtil.get_db_session(
  38 + configure.SQLALCHEMY_DATABASE_URI)
  39 + sys_ds = PGUtil.open_pg_data_source(
  40 + 0, configure.SQLALCHEMY_DATABASE_URI)
  41 +
  42 + hosts = sys_session.query(
  43 + MonitorHost.host, MonitorHost.user, MonitorHost.password, MonitorHost.type, MonitorHost.srcid)
  44 + servers = list(map(lambda host:
  45 + {'hostname': host.host, 'username': host.user,
  46 + 'password': host.password, 'type': host.type,
  47 + 'sid': host.srcid},
  48 + hosts))
  49 + for info in servers:
  50 + try:
  51 + # 业务逻辑
  52 + client = paramiko.SSHClient()
  53 + client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
  54 + client.connect(hostname=info['hostname'],
  55 + username=info['username'], password=info['password'])
  56 +
  57 + # cpu
  58 + order = "top -b -n1 | sed -n '3p' | awk '{print $2}'"
  59 + stdin, stdout, stderr = client.exec_command(order)
  60 + cpu_usage = stdout.read().decode().split("\n")[0] # cpu使用率
  61 +
  62 + # 内存
  63 + order = "free -m | sed -n '2p' | awk '{print $2}'"
  64 + stdin, stdout, stderr = client.exec_command(order)
  65 + totalMem = stdout.read().decode().split("\n")[0] # 总内存
  66 +
  67 + order = "free -m | sed -n '2p' | awk '{print $7}'"
  68 + stdin, stdout, stderr = client.exec_command(order)
  69 + availableMem = stdout.read().decode().split("\n")[0] # 可用内存
  70 +
  71 + order = "free -m | sed -n '2p' | awk '{print $3}'"
  72 + stdin, stdout, stderr = client.exec_command(order)
  73 + usedMem = stdout.read().decode().split("\n")[0] # 已用内存
  74 +
  75 + # disk
  76 + order = "df -m | grep -v 'overlay\|Filesystem' | awk '{print $1,$2,$3}' | grep /dev | awk '{print $2}' | awk -v total=0 '{total+=$1}END{print total}'"
  77 + stdin, stdout, stderr = client.exec_command(order)
  78 + totalDisk = int(stdout.read().decode().split("\n")
  79 + [0]) # 总磁盘空间,单位Mb
  80 +
  81 + order = "df -m | grep -v 'overlay\|Filesystem' | awk '{print $1,$2,$3}' | grep /dev | awk '{print $3}' | awk -v total=0 '{total+=$1}END{print total}'"
  82 + stdin, stdout, stderr = client.exec_command(order)
  83 + usedDisk = int(stdout.read().decode().split("\n")
  84 + [0]) # 已使用磁盘空间,单位Mb
  85 +
  86 + # network
  87 + # 接收的字节数
  88 + rx_time = []
  89 + rx_bytes = []
  90 + tx_time = []
  91 + tx_bytes = []
  92 +
  93 + # 接收的字节数
  94 + order = "ifconfig | grep RX | grep -v 'errors'| awk -v total=0 '{total+=$5}END{print total}'"
  95 + i = 0
  96 + while i < 2:
  97 + i = i+1
  98 + stdin, stdout, stderr = client.exec_command(order)
  99 + rx_time.append(time.time())
  100 + rx_bytes.append(int(stdout.read().decode().split("\n")[0]))
  101 +
  102 + # 发送的字节数
  103 + order = "ifconfig | grep TX | grep -v 'errors'| awk -v total=0 '{total+=$5}END{print total}'"
  104 + i = 0
  105 + while i < 2:
  106 + i = i+1
  107 + stdin, stdout, stderr = client.exec_command(order)
  108 + tx_time.append(time.time())
  109 + tx_bytes.append(int(stdout.read().decode().split("\n")[0]))
  110 +
  111 + log_guid = uuid.uuid1().__str__()
  112 + monitor_log = MonitorLog(guid=log_guid,
  113 + server=info["hostname"],
  114 + time_stamp=cur_time,
  115 + cpu_usage=float(
  116 + "%.2f" % float(cpu_usage)),
  117 + total_mem=totalMem,
  118 + available_mem=availableMem,
  119 + used_mem=usedMem,
  120 + disk=totalDisk,
  121 + disk_usage=usedDisk,
  122 + net_recv=float("%.2f" % float((
  123 + rx_bytes[1] - rx_bytes[0])/(rx_time[1]-rx_time[0]))),
  124 + net_send=float("%.2f" % float((
  125 + tx_bytes[1] - tx_bytes[0])/(tx_time[1]-tx_time[0]))),
  126 + date_stamp=cur_time.strftime(
  127 + "%Y-%m-%d"),
  128 + hour_stamp=struct_time.tm_hour,
  129 + minu_stamp=struct_time.tm_min,
  130 + d_minu_stamp=1 if d_minu_stamp == 0 else d_minu_stamp,
  131 + f_minu_stamp=1 if f_minu_stamp == 0 else f_minu_stamp)
  132 +
  133 + sys_session.add(monitor_log)
  134 + sys_session.commit()
  135 +
  136 + # for line in stdout:
  137 + # data = json.loads(line)
  138 + # # print(type(data))
  139 + # print(data)
  140 + except Exception as e:
  141 + sys_session.rollback()
  142 + except e:
  143 + print('发生了异常:', e)
  144 + finally:
  145 + client.close()
  146 + if sys_session:
  147 + sys_session.close()
  148 + if sys_ds:
  149 + sys_ds.Destroy()
  150 +
  151 +
  152 +# 记录30条记录
  153 +logs = []
  154 +
  155 +
  156 +def start_schedule():
  157 + # # 1分钟巡检一次
  158 + schedule.every(2).minutes.do(background_job)
  159 + # schedule.every(5).seconds.do(background_job)
  160 + stop_run_continuously = run_continuously()
  161 + # Do some other things...
  162 + # # Stop the background thread
  163 + # time.sleep(10)
  164 + # stop_run_continuously.set()
  165 +
  166 +
  167 +def format_value(value):
  168 + # 1024*1024*1024
  169 + if value > 1_073_741_824:
  170 + value = "{}GB".format(format(value/1_073_741_824, '.1f'))
  171 + elif value > 1_048_576:
  172 + # 1024*1024
  173 + value = "{}MB".format(format(value / 1_048_576, '.1f'))
  174 + elif value > 1024:
  175 + value = "{}KB".format(format(value / 1024.0, '.1f'))
  176 + else:
  177 + value = "{}B".format(format(value, '.1f'))
  178 + return value
  179 +
  180 +
  181 +def Mb_format_value(value):
  182 + if value > 1024:
  183 + value = "{}GB".format(format(value/1024, '.1f'))
  184 + else:
  185 + value = "{}MB".format(format(value, '.1f'))
  186 + return value
  1 +import schedule
  2 +import threading
  3 +import time
  4 +
  5 +##多线程类
  6 +def run_continuously(interval=1):
  7 + """Continuously run, while executing pending jobs at each
  8 + elapsed time interval.
  9 + @return cease_continuous_run: threading. Event which can
  10 + be set to cease continuous run. Please note that it is
  11 + *intended behavior that run_continuously() does not run
  12 + missed jobs*. For example, if you've registered a job that
  13 + should run every minute and you set a continuous run
  14 + interval of one hour then your job won't be run 60 times
  15 + at each interval but only once.
  16 + """
  17 + cease_continuous_run = threading.Event()
  18 +
  19 + class ScheduleThread(threading.Thread):
  20 + @classmethod
  21 + def run(cls):
  22 + while not cease_continuous_run.is_set():
  23 + schedule.run_pending()
  24 + time.sleep(interval)
  25 +
  26 + continuous_thread = ScheduleThread()
  27 + #启动
  28 + continuous_thread.start()
  29 + return cease_continuous_run
@@ -5,7 +5,7 @@ deploy_ip_host = "172.26.40.105:8840" @@ -5,7 +5,7 @@ deploy_ip_host = "172.26.40.105:8840"
5 # 系统数据库 5 # 系统数据库
6 6
7 SQLALCHEMY_DATABASE_URI = "postgresql://postgres:chinadci@172.26.99.160:5432/dmap_dms_test" 7 SQLALCHEMY_DATABASE_URI = "postgresql://postgres:chinadci@172.26.99.160:5432/dmap_dms_test"
8 -# SQLALCHEMY_DATABASE_URI = "postgresql://postgres:postgres@localhost:5433/dmap_dms_test" 8 +#SQLALCHEMY_DATABASE_URI = "postgresql://postgres:postgres@localhost:5433/dmap_dms_test"
9 9
10 # 指定精华表所在位置(必须为空间库),设置为None则存放在各自的实体库中 10 # 指定精华表所在位置(必须为空间库),设置为None则存放在各自的实体库中
11 #VACUATE_DB_URI = None 11 #VACUATE_DB_URI = None
@@ -18,3 +18,4 @@ thrift==0.13.0 @@ -18,3 +18,4 @@ thrift==0.13.0
18 Authlib==0.13 18 Authlib==0.13
19 kazoo==2.8.0 19 kazoo==2.8.0
20 paramiko==2.8.0 20 paramiko==2.8.0
  21 +#schedule==1.1.0
@@ -2,8 +2,11 @@ @@ -2,8 +2,11 @@
2 from flask import Flask 2 from flask import Flask
3 from app import create_app 3 from app import create_app
4 import os 4 import os
  5 +from app.modules.monitor.schedule import start_schedule
  6 +
5 os.environ['AUTHLIB_INSECURE_TRANSPORT'] = '1' 7 os.environ['AUTHLIB_INSECURE_TRANSPORT'] = '1'
6 app: Flask = create_app() 8 app: Flask = create_app()
7 if __name__ == '__main__': 9 if __name__ == '__main__':
  10 + # start_schedule()
8 app.run(host="0.0.0.0", port="8840", threaded=True, debug=True) 11 app.run(host="0.0.0.0", port="8840", threaded=True, debug=True)
9 # app.run(host="0.0.0.0", port="8840", threaded=True) 12 # app.run(host="0.0.0.0", port="8840", threaded=True)
注册登录 后发表评论