자동화 경보 의 사고방식
최근 메 인 제품 에서 화성 으로 옮 겨 져 기술 이 부족 한 나 는 스트레스 를 많이 받는다.코드 를 꺼 낼 때 도 온라인 환경 을 망 칠 까 봐 더욱 조 심 스 러 워 졌 다.
그래서 저 는 문 제 를 빨리 발견 하고 bug 를 고 칠 수 있 도록 모니터링 을 하려 고 합 니 다.회사 의 일부 규정 을 고려 하여 상세 하 게 소개 하지 않 겠 다.다음은 간단명료 하 게 묘사 하고 생각 이 있 으 면 된다.
사고방식 은 다음 과 같다.
1. Nginx ,
2. SVN blame 。
3. , 。
실현 과정 에서 많은 문제 에 부 딪 혔 다.대략 몇 가지 가 있 습 니 다. 1. 서버 포트 제한 이 비교적 죽 어서 자신 에 게 대외 방문 포트 를 따로 열 수 없습니다.2. 잘못된 트리거 를 반복 합 니 다.3. SVN blame 인증 문제 (해결 되 지 않 음...)
… …
전체적으로 클 라 이언 트 와 서버 모드 를 사용 하려 고 합 니 다.
클 라 이언 트 내용 은 다음 과 같 습 니 다.
Python 스 크 립 트 를 사용 하여 crontab 를 통 해 오류 로 그 를 감시 하고 해당 하 는 내용 과 일치 하 는 서버 에 보 냅 니 다.
#!/usr/bin python
# coding: utf8
import sys
reload(sys)
sys.setdefaultencoding("utf8")
import re
import json
import urllib2
import time
# 2017/11/17 16:05:01 [error] 4004#0: *246620391 FastCGI sent in stderr: "PHP message: PHP Fatal error: Function name must be a string in /home/wwwroot/api.newtv.com/live.class.php on line 2242" while reading response header from upstream, client: 192.168.30.100, server: api.changbalive.com, request: "GET /api.php?ac=recordsingsong&curuserid=2635267&channelsrc=appstore&version=1.9.5&token=T777936552f7571e&bless=0&macaddress=A4D0E95D-AB54-48A1-BCC8-3EB0A530B2A7&ismember=0&openudid=d7be3882344bb889cd6c451880df1a834f1af960&systemversion=10.3.3&device=iPhone7,1&broken=0&songid=867712&secret=483f47528d HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "api.changbalive.com"
# :tuple : , , , ,
def parse_errorlog(line):
reg = re.compile(r"(.*?) \[error\] .*?PHP message:(.*?): (.*?) in (.*?) on line (\d+).*");
result = re.findall(reg, line)
# print len(result)
# print result
return result
def get_errorlog(type='api_newtv_error.log'):
path = "/var/log/nginx/{}".format(type)
result = []
with open(path, 'r') as file:
lines = file.readlines()
file.close()
for line in lines:
if line is not None:
result.append(line)
return result
//TODO
// HTTP , emit Server
서버 내용
사용 한 서 류 는 대략 이렇게 몇 개 있다.
findbugauthor.sh receive.php utils.php
findbugauthor.sh
#!/usr/bin bash
export $PATH
DIRPATH=$1
FILENAME=$2
LINE=$3
cd $DIRPATH
AUTHOR=`svn blame $FILENAME | head -$LINE | tail -1 | awk '{print $2}'`
echo $AUTHOR
utils.php
header("Content-Type:text/html;charset=UTF-8");
function getuniquecode($path, $line){
$errorcode = md5("{$path}{$line}");
return $errorcode;
}
function phpPost( $url, $post = '', $timeout = 5 ){
if( empty( $url ) ){
return ;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
if( $post != '' && !empty( $post ) ){
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Content-Length: ' . strlen($post)));
}
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
function getbashoutput($path, $line) {
$dirpath = substr($path, 0, strpos($path, basename($path)));
$filename = basename($path);
$result = "";
exec("bash ./findbugauthor.sh {$dirpath} {$filename} {$line} 2>&1", $result);
return $result[1];
}
//getbashoutput("/home/wwwroot/ / ListService.php", 142);
class RedisHelper{
private static $_instance = null;
const APINEWTVERROR_KEY = "zpinewtvcom:error:zset";
const NOTIFY_KEY = "apinewtvcom:notify:hash";
private function __construct(){
$this->redis = new Redis();
$this->redis->connect("127.0.0.1", 6379, 7);
}
public static function getInstance(){
if( self::$_instance == null ) {
self::$_instance = new RedisHelper();
}
return self::$_instance;
}
public function incrErrorNumber($errorcode, $number=1){
$this->redis->zIncrBy(self::APINEWTVERROR_KEY, 1, $errorcode);
}
public function getErrorNumber($errorcode) {
return intval($this->redis->zScore(self::APINEWTVERROR_KEY, $errorcode));
}
public function updateNotifyDate($errorcode){
$this->redis->hSet(self::NOTIFY_KEY, $errorcode, date("Ymd"));
}
public function getNotifyDate($errorcode) {
return $this->redis->hGet(self::NOTIFY_KEY, $errorcode);
}
public function getFrequentErrors($number=7) {
return $this->redis->zRevRange(self::APINEWTVERROR_KEY, 0, $number, true);
}
}
$template = <<
class Notifier{
private static $instance = null;
private function __construct() {
$this->url = "https://oapi.dingtalk.com/robot/send?access_token=b716e1f39b7fc7afbea04b2 d4bb79db65a117d589f886d1757";
}
public static function getInstance(){
if(self::$instance==null) {
self::$instance = new Notifier();
}
return self::$instance;
}
public function notify($msg){
global $template;
$data = json_decode($template, true);
$data['text']['content'] = $msg;
$data['at']['atMobiles'] = array(15801479216 );
$data['at']['isAtAll'] = false;
$data['msgtype'] = "text";
$result = phpPost($this->url, json_encode($data));
return $result;
}
}
receive.php
header("Content-Type:text/html;charset=UTF-8");
require __DIR__."/utils.php";
$time = isset($_REQUEST['time'])?strval($_REQUEST['time']):"";
$level = isset($_REQUEST['level'])?strval($_REQUEST['level']):"";
$description = isset($_REQUEST['description'])?strval($_REQUEST['description']):"";
$fullpath = isset($_REQUEST['fullpath'])?strval($_REQUEST['fullpath']):"";
$linenumber = isset($_REQUEST['linenumber'])?intval($_REQUEST['linenumber']):0;
if(empty($time) || empty($level) || empty($description) || empty($fullpath) || empty($linenumber)) {
echo json_encode(array("errcode"=>-1, "errmsg"=>" "));
}
$errorcode = getuniquecode($fullpath, $linenumber);
$helper = RedisHelper::getInstance();
$helper->incrErrorNumber($errorcode);
$bugauthor = getbashoutput($fullpath, $linenumber);
$notify = Notifier::getInstance();
var_dump($errorcode);
echo "
";
$errors = $helper->getFrequentErrors(7);
var_dump($errors);
foreach($errors as $uniquecode=>$numbers) {
if(intval($errorcode) == intval($uniquecode)) {
$msg = "Bug :{$time}
Bug :{$level}
:{$description}
:{$fullpath}
:{$linenumber}
:{$bugauthor}
";
$notify->notify($msg);
}
}
실현 적 효과
부족 한 점
경보 의 촉발 메커니즘 이 아직 완선 되 지 않 았 다. 사실은 이 할 내용 이 많 을 것 이다. 서로 다른 장면 에 따라 서로 다른 전략 을 선택 하 는 것 이 중요 하지만 유연 하 게 처리 해 야 한다. 모든 좋 은 디자인 은 안 된다. 여기 서 관심 이 있 는 사람 은 스스로 생각 할 수 있다.
crontab 의 시간 간격 도 문제 입 니 다. 너무 작 으 면 서버 압력 에 약간의 영향 을 줍 니 다.시간 영화 가 너무 커서 신고 의 민감 도가 떨 어 지고 신고 의 의 미 를 잃 었 다.
전체적으로 말 하면 사고방식 은 매우 간단 하지만 정말 실현 되 고 개발 에 잘 응 용 될 수 있 기 때문에 아직도 갈 길이 멀다.여 기 는 벽돌 을 던 져 옥 을 끌 어 들 인 다 고 생각 하 세 요.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.