異常監測①——統計學方法(正態分佈3σ原則、箱型圖四分位距法、經驗閾值、累積法)
Table of Contents
需求
需要建立一個自動監測機制,主要監測 數據處理 這個環節是否發生了異常。
異常:缺、多、數值不對
可能發生的異常有:
①在某段時間內數據未及時處理,堆積到了下一次應處理時間才處理;
②某個時間節點應該有但沒有,或數據不全-如應記錄從0點-24點的,但實際只有8-19點的;
③上傳頻率與原設定不同(如應是5min一條,在5分鐘內上傳多條的情況)
方案
考慮從表、指標 兩個維度進行監測:
表維度 | 指標維度 |
數據量(每隔頻率f新增數據量) | 指標一類(數值型);指標二類(非數值型) |
表維度主要考慮:數據量;由於項目中數據處理機制是固定頻率進行處理,且從上述列出的異常情況看,異常都會在固定頻率新增的數據量上顯示出來,所以數量角度監測的目標是 一定頻率新增的數據量。
確認第一階段目標:實現固定頻率f 表新增數量監測。
實現
固定頻率定時跑腳本——> sched.scheduler(後改爲crontab)
從庫中讀f頻率新增數據量——>pymongo
將統計結果寫入表——>pymongo
判斷異常——>3∂原則、四分位距法、經驗閾值、累積法
異常結果發送郵件報警——>requests.post(2019.12新增企業微信報警功能)
判斷異常:對符合正態分佈的數據集,使用3σ原則判斷
其他分佈數據集,使用四分位距法判斷異常
參考文章:
理論 | 實現 | |
3σ原則 | ||
四分位距法 |
|
箱線圖代碼 |
問題記錄
|
問題 |
解決 |
備註 |
|
dataframe轉一維array |
|
|
|
kstest 的pvalue=0 |
|
|
|
各類時間轉換 |
|
datetime.datetime.fromtimestamp(tn) + datetime.timedelta(hours=-8)
max_acceptTime=max_record[0]+datetime.timedelta(hours=8) |
定時機制 |
scheduler執行順序&原理 |
|
|
scheduler多任務延遲問題 |
|
|
|
crontab |
舉例1: */1 * * * * python /Users/zy/PycharmProjects/GuassTest/test1.py >> /Users/zy/testresult.log 2>&1 舉例2: */10 * * * * /Users/zy/anaconda3/bin/python3 /Users/zy/PycharmProjects/abnormalDetectCrontab/detect.py >> /Users/zy/abnormalresult.log 2>&1 |
報錯 No module named…時是因爲安裝了多個版本的python,要指定用哪個版本的python去執行crontab命令(先which python3獲得python路徑,將原命令 python py文件路徑 改爲 python路徑 py文件路徑) |
python-crontab 僅能用來配置crontab任務,不能執行(只能實現crontab -e的功能) |
啓動crontab |
sudo /usr/sbin/cron start |
sudo /usr/sbin/cron stop 爲暫停任務 |
|
停止crontab |
killall -g cronTest.py |
關閉 SIP 的情況下,試着運行 "sudo launchctl unload -w /System/Library/LaunchDaemons/com.vix.cron.plist" |
|
輸出重定向 |
*/1 * * * * python /Users/zy/PycharmProjects/GuassTest/test1.py >> /Users/zy/testresult.log 2>&1 |
初始的輸出結果在 /var/mail/ 裏,但當日誌信息會非常大,可能會影響系統的正常運行;所以重定向到其他文件裏; 也可忽略日誌輸出 >/dev/null 2>&1 |
|
清理郵件日誌 |
|
|
|
|
|
|
|
pymongo |
生成objectid |
from bson import objectid objectid.ObjectId() |
|
datetime、unix時間戳、string型時間 轉換 |
|
|
|
|
mongo連接報錯 raise AutoReconnect(msg) pymongo.errors.AutoReconnect: 47.97.98.146:4409: [Errno 60] Operation timed out |
連接mongodb超時(網絡斷開連接或mongodb的host等變更導致) |
|
auth failed |
檢查點 ① contest = MongoClient('mongodb://{0}:{1}@{2}:{3}/sentry'.format(username, passwd, host, port)) (非root用戶需要加具體的 /database) ② 查詢部分寫的不對,createtime等取的異常
|
>>> uri = 'mongodb://host/my_database' https://api.mongodb.com/python/current/api/pymongo/mongo_client.html#module-pymongo.mongo_client |
|
|
pymongo.errors.CursorNotFound: Cursor not found |
連接庫後執行後續操作的時間過長 |
|
多線程下pymongo連接過多 |
在循環外寫連接,循環內直接調用連接進行查詢(避免每次循環都連接一次) |
|
|
|
|
|
|
發郵件 |
發送郵件報錯 raise ConnectionError(err, request=request) requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response')) |
|
|
|
dataframe轉html表單 |
|
|
|
pymongo丟失時區;取出的是ISODate 而不是local |
mydf['created_at']=mydf['created_at'].dt.tz_localize('UTC’). dt.tz_convert('America/Montreal') |
data['createtime'] = data['createtime'].dt.tz_localize('UTC').dt.tz_convert('Asia/Shanghai’) #將dataframe中的createtime改爲中國上海時區
|
|
pandas 的series整列截斷 |
trade_date = dt['trade_date'].astype(str) result = trade_date.str.slice(5, 7) |
|
環境配置 |
config配置 |
|
|
|
pipenv搭建虛擬環境 |
|
|
git |
git衝突 Your branch is ahead of 'origin/master' by 1 commit |
先pull,再push |
|
代碼規範問題 |
1)變量、函數等命名語義化,不縮寫(儘量沒有波浪線提醒,像abnormaldetectcount 要寫成abnormal_detect_count); 2)重複較多函數 進行封裝 3)特殊功能函數,考慮僅實現功能,需要的參數放到配置文件 4)可配的時間間隔用 t、3t表示,而不是直接傳1、3… 5)用到較多次的字符串等,用一個常量替代(各個模塊使用的同一庫名local) |
|
|
ssh |
sshtunnel.BaseSSHTunnelForwarderError: Could not establish session to SSH gateway |
ssh_username 應該是登錄遠程rds的用戶名,而不是數據庫的用戶名 |