异常监测①——统计学方法(正态分布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的用户名,而不是数据库的用户名 |