提交 dd3c65e1e88bd8fff7f47ed8f39343f8bb78a98b

作者 nheweijun
2 个父辈 1a2a2796 c4a5f3d4

merge

  1 +# coding=utf-8
  2 +# author: 4N
  3 +#createtime: 2021/5/18
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  7 +from flasgger import swag_from
  8 +from flask import Blueprint
  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
  11 +
  12 +
  13 +user_socket_list = []
  14 +user_socket_dict = {}
  15 +
  16 +
  17 +class Monitor(BlueprintApi):
  18 +
  19 + bp = Blueprint("Monitor", __name__, url_prefix="/API/Monitor")
  20 +
  21 + @staticmethod
  22 + @bp.route('/Info', methods=['GET'])
  23 + @swag_from(monitor_info.Api.api_doc)
  24 + def monitor_info():
  25 + """
  26 + 性能监控
  27 + """
  28 + return monitor_info.Api().result
  29 +
  30 + @staticmethod
  31 + @bp.route('/baseMonitoring', methods=['GET'])
  32 + @swag_from(monitoring.Api.api_doc)
  33 + def monitoring():
  34 + """
  35 + 基础监控
  36 + """
  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
  2 +# author: 4N
  3 +#createtime: 2021/6/11
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  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
  12 +from app.models import db
  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 + }
... ...
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/7/9
  4 +#email: nheweijun@sina.com
  5 +
  6 +from app.models import *
  7 +
  8 +from app.util.component.ApiTemplate import ApiTemplate
  9 +from app.util.component.ModelVisitor import ModelVisitor
  10 +import psutil
  11 +
  12 +class Api(ApiTemplate):
  13 + api_name = "监控"
  14 +
  15 + def process(self):
  16 +
  17 + # 返回结果
  18 + res = {}
  19 + res["data"] = {}
  20 + try:
  21 + # 业务逻辑
  22 + cpu_count = psutil.cpu_count(False)
  23 + cpu_per = int(psutil.cpu_percent())
  24 + res["data"]["cpu"] ={"count":cpu_count,"percent":"{}%".format(cpu_per)}
  25 +
  26 +
  27 + mem_total = int(psutil.virtual_memory()[0])
  28 + mem_used = int(psutil.virtual_memory()[3])
  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 )
  33 +
  34 + res["data"]["memory"] = {
  35 + 'total': self.format_value(mem_total),
  36 + 'used': self.format_value(mem_used),
  37 + 'percent': "{}%".format(mem_per)
  38 + }
  39 +
  40 +
  41 +
  42 +
  43 +
  44 + res["data"]["network"] = {
  45 + 'sent': self.format_value(network_sent),
  46 + 'recv': self.format_value(network_recv)
  47 + }
  48 +
  49 +
  50 + res["result"] = True
  51 + except Exception as e:
  52 + raise e
  53 + return res
  54 +
  55 + api_doc = {
  56 +
  57 + "tags": ["监控接口"],
  58 + "parameters": [
  59 + ],
  60 + "responses": {
  61 + 200: {
  62 + "schema": {
  63 + "properties": {
  64 + }
  65 + }
  66 + }
  67 + }
  68 + }
  69 +
  70 + def format_value(self,value):
  71 + if value>1024**3:
  72 + value = "{}GB".format(format(value/1024.0**3,'.1f'))
  73 + elif value>1024**2:
  74 + value = "{}MB".format(format(value / 1024.0 ** 2, '.1f'))
  75 + elif value>1024:
  76 + value = "{}KB".format(format(value / 1024.0, '.1f'))
  77 + else:
  78 + value = "{}B".format(format(value, '.1f'))
  79 + return value
\ No newline at end of file
... ...
  1 +from app.models import *
  2 +from app.util.component.ApiTemplate import ApiTemplate
  3 +import json
  4 +import os
  5 +
  6 +class Api(ApiTemplate):
  7 + api_name = "远程监控"
  8 +
  9 + def process(self):
  10 +
  11 + # 返回结果
  12 + res = {}
  13 + res["data"] = {}
  14 + try:
  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)
  23 + res["result"] = True
  24 + except Exception as e:
  25 + raise e
  26 + return res
  27 +
  28 + api_doc = {
  29 +
  30 + "tags": ["监控接口"],
  31 + "parameters": [
  32 + ],
  33 + "responses": {
  34 + 200: {
  35 + "schema": {
  36 + "properties": {
  37 + }
  38 + }
  39 + }
  40 + }
  41 + }
  42 +
  43 + def format_value(self, value):
  44 + # 1024*1024*1024
  45 + if value > 1_073_741_824:
  46 + value = "{}GB".format(format(value/1_073_741_824, '.1f'))
  47 + elif value > 1024**2:
  48 + value = "{}MB".format(format(value / 1_048_576, '.1f'))
  49 + elif value > 1024:
  50 + # 1024*1024
  51 + value = "{}KB".format(format(value / 1024.0, '.1f'))
  52 + else:
  53 + value = "{}B".format(format(value, '.1f'))
  54 + return value
  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
\ No newline at end of file
... ...
... ... @@ -4,10 +4,12 @@ import logging
4 4 deploy_ip_host = "172.26.40.105:8840"
5 5 # 系统数据库
6 6
  7 +
7 8 # SQLALCHEMY_DATABASE_URI = "postgresql://postgres:chinadci@172.26.60.100:5432/dmap_manager_test"
8 9 SQLALCHEMY_DATABASE_URI = "postgresql://postgres:chinadci@172.26.60.100:5432/dmap_manager"
9 10 # SQLALCHEMY_DATABASE_URI = "postgresql://postgres:postgres@localhost:5433/dmap_dms_test"
10 11
  12 +
11 13 # 指定精华表所在位置(必须为空间库),设置为None则存放在各自的实体库中
12 14 #VACUATE_DB_URI = None
13 15 VACUATE_DB_URI = SQLALCHEMY_DATABASE_URI
... ...
... ... @@ -18,4 +18,6 @@ thrift==0.13.0
18 18 Authlib==0.13
19 19 kazoo==2.8.0
20 20 paramiko==2.8.0
21   -requests==2.26.0
\ No newline at end of file
  21 +requests==2.26.0
  22 +schedule==1.1.0
  23 +
... ...
... ... @@ -2,8 +2,11 @@
2 2 from flask import Flask
3 3 from app import create_app
4 4 import os
  5 +from app.modules.monitor.schedule import start_schedule
  6 +
5 7 os.environ['AUTHLIB_INSECURE_TRANSPORT'] = '1'
6 8 app: Flask = create_app()
7 9 if __name__ == '__main__':
  10 + # start_schedule()
8 11 app.run(host="0.0.0.0", port="8840", threaded=True, debug=True)
9 12 # app.run(host="0.0.0.0", port="8840", threaded=True)
... ...
注册登录 后发表评论