天天看點

使用Python實作一個簡單的項目監控

在公司裡做的一個接口系統,主要是對接第三方的系統接口,是以,這個系統裡會和很多其他公司的項目互動。随之而來一個很蛋疼的問題,這麼多公司的接口,不同公司接口的穩定性差别很大,通路量大的時候,有的不怎麼行的接口就各種出錯了。

這個接口系統剛剛開發不久,整個系統中,處于比較邊緣的位置,不像其他項目,有日志庫,還有短信告警,一旦出問題,很多情況下都是使用者回報回來,是以,我的想法是,拿起python,為這個項目寫一個監控。如果在調用某個第三方接口的過程中,大量出錯了,說明這個接口有有問題了,就可以更快的采取措施。

項目的也是有日志庫的,所有的info,error日志都是每隔一分鐘掃描入庫,日志庫是用的mysql,表裡有幾個特别重要的字段:

        level 日志級别

        message 日志内容

        file_name java代碼檔案

        log_time 日志時間

有日志庫,就不用自己去線上環境掃日志分析了,直接從日志庫入手。由于日志庫線上上時每隔1分鐘掃,那我就去日志庫每隔2分鐘掃一次,如果掃到有一定數量的error日志就報警,如果隻有一兩條錯誤就可以無視了,也就是短時間爆發大量錯誤日志,就可以斷定系統有問題了。報警方式就用發送郵件,是以,需要做下面幾件事情:

1. 操作mysql。

2. 發送郵件。

3. 定時任務。

4. 日志。

5. 運作腳本。

明确了以上幾件事情,就可以動手了。

操作資料庫

使用mysqldb這個驅動,直接操作資料庫,主要就是查詢操作。

擷取資料庫的連接配接:

​​?​​

<col>

1

2

3

4

5

6

7

8

​<code>​def​</code>​ ​<code>​get_con():​</code>​

​<code>​host ​</code>​​<code>​=​</code>​ ​<code>​"127.0.0.1"​</code>​

​<code>​port ​</code>​​<code>​=​</code>​ ​<code>​3306​</code>​

​<code>​logsdb ​</code>​​<code>​=​</code>​ ​<code>​"logsdb"​</code>​

​<code>​user ​</code>​​<code>​=​</code>​ ​<code>​"root"​</code>​

​<code>​password ​</code>​​<code>​=​</code>​ ​<code>​"never tell you"​</code>​

​<code>​con ​</code>​​<code>​=​</code>​ ​<code>​mysqldb.connect(host​</code>​​<code>​=​</code>​​<code>​host, user​</code>​​<code>​=​</code>​​<code>​user, passwd​</code>​​<code>​=​</code>​​<code>​password, db​</code>​​<code>​=​</code>​​<code>​logsdb, port​</code>​​<code>​=​</code>​​<code>​port, charset​</code>​​<code>​=​</code>​​<code>​"utf8"​</code>​​<code>​)​</code>​

​<code>​return​</code>​ ​<code>​con​</code>​

從日志庫裡擷取資料,擷取目前時間之前2分鐘的資料,首先,根據目前時間進行計算一下時間。之前,計算有問題,現在已經修改。

​<code>​def​</code>​ ​<code>​calculate_time():​</code>​

​<code>​now ​</code>​​<code>​=​</code>​ ​<code>​time.mktime(datetime.now().timetuple())​</code>​​<code>​-​</code>​​<code>​60​</code>​​<code>​*​</code>​​<code>​2​</code>​

​<code>​result ​</code>​​<code>​=​</code>​ ​<code>​time.strftime(​</code>​​<code>​'%y-%m-%d %h:%m:%s'​</code>​​<code>​, time.localtime(now))​</code>​

​<code>​return​</code>​ ​<code>​result​</code>​

然後,根據時間和日志級别去日志庫查詢資料

9

10

11

12

13

14

15

16

17

​<code>​def​</code>​ ​<code>​get_data():​</code>​

​<code>​select_time ​</code>​​<code>​=​</code>​ ​<code>​calculate_time()​</code>​

​<code>​logger.info(​</code>​​<code>​"select time:"​</code>​​<code>​+​</code>​​<code>​select_time)​</code>​

​<code>​sql ​</code>​​<code>​=​</code>​ ​<code>​"select file_name,message from logsdb.app_logs_record "​</code>​ ​<code>​\​</code>​

​<code>​"where log_time &gt;"​</code>​​<code>​+​</code>​​<code>​"'"+select_time+"'"​</code>​ ​<code>​\​</code>​

​<code>​"and level="​</code>​​<code>​+​</code>​​<code>​"'error'"​</code>​ ​<code>​\​</code>​

​<code>​"order by log_time desc"​</code>​

​<code>​conn ​</code>​​<code>​=​</code>​ ​<code>​get_con()​</code>​

​<code>​cursor ​</code>​​<code>​=​</code>​ ​<code>​conn.cursor()​</code>​

​<code>​cursor.execute(sql)​</code>​

​<code>​results ​</code>​​<code>​=​</code>​ ​<code>​cursor.fetchall()​</code>​

​<code>​cursor.close()​</code>​

​<code>​conn.close()​</code>​

​<code>​return​</code>​ ​<code>​results​</code>​

發送郵件

使用python發送郵件比較簡單,使用标準庫smtplib就可以

這裡使用163郵箱進行發送,你可以使用其他郵箱或者企業郵箱都行,不過host和port要設定正确。

18

​<code>​def​</code>​ ​<code>​send_email(content):​</code>​

​<code>​sender ​</code>​​<code>​=​</code>​ ​<code>​"[email protected]"​</code>​

​<code>​receiver ​</code>​​<code>​=​</code>​ ​<code>​[​</code>​​<code>​"[email protected]"​</code>​​<code>​, ​</code>​​<code>​"[email protected]"​</code>​​<code>​]​</code>​

​<code>​host ​</code>​​<code>​=​</code>​ ​<code>​'smtp.163.com'​</code>​

​<code>​port ​</code>​​<code>​=​</code>​ ​<code>​465​</code>​

​<code>​msg ​</code>​​<code>​=​</code>​ ​<code>​mimetext(content)​</code>​

​<code>​msg[​</code>​​<code>​'from'​</code>​​<code>​] ​</code>​​<code>​=​</code>​ ​<code>​"[email protected]"​</code>​

​<code>​msg[​</code>​​<code>​'to'​</code>​​<code>​] ​</code>​​<code>​=​</code>​ ​<code>​"[email protected],[email protected]"​</code>​

​<code>​msg[​</code>​​<code>​'subject'​</code>​​<code>​] ​</code>​​<code>​=​</code>​ ​<code>​"system error warning"​</code>​

​<code>​try​</code>​​<code>​:​</code>​

​<code>​smtp ​</code>​​<code>​=​</code>​ ​<code>​smtplib.smtp_ssl(host, port)​</code>​

​<code>​smtp.login(sender, ​</code>​​<code>​'123456'​</code>​​<code>​)​</code>​

​<code>​smtp.sendmail(sender, receiver, msg.as_string())​</code>​

​<code>​logger.info(​</code>​​<code>​"send email success"​</code>​​<code>​)​</code>​

​<code>​except​</code>​ ​<code>​exception, e:​</code>​

​<code>​logger.error(e)​</code>​

定時任務

使用一個單獨的線程,每2分鐘掃描一次,如果error級别的日志條數超過5條,就發郵件通知。

​<code>​def​</code>​ ​<code>​task():​</code>​

​<code>​while​</code>​ ​<code>​true​</code>​​<code>​:​</code>​

​<code>​logger.info(​</code>​​<code>​"monitor running"​</code>​​<code>​)​</code>​

​<code>​results ​</code>​​<code>​=​</code>​ ​<code>​get_data()​</code>​

​<code>​if​</code>​ ​<code>​results ​</code>​​<code>​is​</code>​ ​<code>​not​</code>​ ​<code>​none​</code>​ ​<code>​and​</code>​ ​<code>​len​</code>​​<code>​(results) &gt; ​</code>​​<code>​5​</code>​​<code>​:​</code>​

​<code>​content ​</code>​​<code>​=​</code>​ ​<code>​"recharge error:"​</code>​

​<code>​logger.info(​</code>​​<code>​"a lot of error,so send mail"​</code>​​<code>​)​</code>​

​<code>​for​</code>​ ​<code>​r ​</code>​​<code>​in​</code>​ ​<code>​results:​</code>​

​<code>​content ​</code>​​<code>​+​</code>​​<code>​=​</code>​ ​<code>​r[​</code>​​<code>​1​</code>​​<code>​]​</code>​​<code>​+​</code>​​<code>​'\n'​</code>​

​<code>​send_email(content)​</code>​

​<code>​sleep(​</code>​​<code>​2​</code>​​<code>​*​</code>​​<code>​60​</code>​​<code>​)​</code>​

日志

為這個小小的腳本配置一下日志log.py,讓日志可以輸出到檔案和控制台中。

​<code>​# coding=utf-8​</code>​

​<code>​import​</code>​ ​<code>​logging​</code>​

​<code>​logger ​</code>​​<code>​=​</code>​ ​<code>​logging.getlogger(​</code>​​<code>​'mylogger'​</code>​​<code>​)​</code>​

​<code>​logger.setlevel(logging.debug)​</code>​

​<code>​fh ​</code>​​<code>​=​</code>​ ​<code>​logging.filehandler(​</code>​​<code>​'monitor.log'​</code>​​<code>​)​</code>​

​<code>​fh.setlevel(logging.info)​</code>​

​<code>​ch ​</code>​​<code>​=​</code>​ ​<code>​logging.streamhandler()​</code>​

​<code>​ch.setlevel(logging.info)​</code>​

​<code>​formatter ​</code>​​<code>​=​</code>​ ​<code>​logging.formatter(​</code>​​<code>​'%(asctime)s - %(name)s - %(levelname)s - %(message)s'​</code>​​<code>​)​</code>​

​<code>​fh.setformatter(formatter)​</code>​

​<code>​ch.setformatter(formatter)​</code>​

​<code>​logger.addhandler(fh)​</code>​

​<code>​logger.addhandler(ch)​</code>​

是以,最後,這個監控小程式就是這樣的app_monitor.py

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

​<code>​import​</code>​ ​<code>​threading​</code>​

​<code>​import​</code>​ ​<code>​mysqldb​</code>​

​<code>​from​</code>​ ​<code>​datetime ​</code>​​<code>​import​</code>​ ​<code>​datetime​</code>​

​<code>​import​</code>​ ​<code>​time​</code>​

​<code>​import​</code>​ ​<code>​smtplib​</code>​

​<code>​from​</code>​ ​<code>​email.mime.text ​</code>​​<code>​import​</code>​ ​<code>​mimetext​</code>​

​<code>​from​</code>​ ​<code>​log ​</code>​​<code>​import​</code>​ ​<code>​logger​</code>​

​<code>​time.sleep(​</code>​​<code>​2​</code>​​<code>​*​</code>​​<code>​60​</code>​​<code>​)​</code>​

​<code>​def​</code>​ ​<code>​run_monitor():​</code>​

​<code>​monitor ​</code>​​<code>​=​</code>​ ​<code>​threading.thread(target​</code>​​<code>​=​</code>​​<code>​task)​</code>​

​<code>​monitor.start()​</code>​

​<code>​if​</code>​ ​<code>​__name__ ​</code>​​<code>​=​</code>​​<code>​=​</code>​ ​<code>​"__main__"​</code>​​<code>​:​</code>​

​<code>​run_monitor()​</code>​

運作腳本

腳本在伺服器上運作,使用supervisor進行管理。

在伺服器(centos6)上安裝supervisor,然後在/etc/supervisor.conf中加入一下配置:

複制代碼代碼如下:

[program:app-monitor]

command = python /root/monitor/app_monitor.py

directory = /root/monitor

user = root

然後在終端中運作supervisord啟動supervisor。

在終端中運作supervisorctl,進入shell,運作status檢視腳本的運作狀态。

總結

這個小監控思路很清晰,還可以繼續修改,比如:監控特定的接口,發送短信通知等等。

因為有日志庫,就少了去線上正式環境掃描日志的麻煩,是以,如果沒有日志庫,就要自己上線上環境掃描,在正式線上環境一定要小心哇~