Created
April 10, 2020 08:14
-
-
Save liangchaoboy/a458a31ef485e2f9693fcdc65b99e6c5 to your computer and use it in GitHub Desktop.
视界云日志检测
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"bytes" | |
"encoding/json" | |
"flag" | |
"fmt" | |
"io" | |
"io/ioutil" | |
"math" | |
"net/http" | |
"os" | |
"strconv" | |
"strings" | |
"time" | |
) | |
type Result struct { | |
Status string `json:"status"` | |
Coeff float64 `json:"coeff"` | |
Code int `json:"code"` | |
Error string `json:"error"` | |
Domain string `json:"domain"` | |
Uid int `json:"uid"` | |
Fluxapi [12]int64 `json:"fluxapi"` | |
Fluxlog [12]int64 `json:"fluxlog"` | |
Rate [12]float64 `json:"rate"` | |
} | |
type DomainConfig struct { | |
Name string `json:"name"` | |
Rate float64 `json:"rate"` | |
} | |
type MonitorConfig struct { | |
Monitor []DomainConfig `json:"monitor"` | |
} | |
var path string | |
var action string | |
var dayTime string | |
var sjyDomain string | |
var h bool | |
var startTime string | |
var sjymonth string | |
var rate float64 | |
var domainsList string | |
func init() { | |
flag.BoolVar(&h, "h", false, "cmd help") | |
flag.StringVar(&path, "path", "", "补日志,文件格式为:时间 域名") | |
flag.StringVar(&action, "action", "", "执行操作") | |
flag.StringVar(&dayTime, "dayTime", "", "查询一个域名固定一天的日志缺失情况") | |
flag.StringVar(&sjyDomain, "sjyDomain", "", "查询一个域名固定一天的日志缺失情况") | |
flag.StringVar(&startTime, "startTime", "", "补日志开始时间") | |
flag.StringVar(&sjymonth, "sjymonth", "", "检查月份格式为:2019-10") | |
flag.Float64Var(&rate, "rate", 1.01, "默认检测阀值") | |
flag.StringVar(&domainsList, "domainsList", "", "域名列表") | |
flag.Usage = usage | |
} | |
func main() { | |
flag.Parse() | |
if h || action == "" { | |
usage() | |
} | |
if action == "fix" { | |
dofix(path) | |
} | |
if action == "fixDomainHour" { | |
fixlog(sjyDomain, startTime) | |
} | |
if action == "checkMonth" { | |
checkMonth(sjymonth, domainsList, rate) | |
} | |
if action == "dayCheck" { | |
dayCheck2(sjyDomain, rate, dayTime) | |
} | |
if action == "domainCheck" { | |
getRes2(sjyDomain, dayTime) | |
} | |
if action == "domainMonth" { | |
month(sjyDomain, rate, sjymonth) | |
} | |
if action == "timingTask" { | |
for { | |
timedTask(domainsList, rate) | |
time.Sleep(time.Second * 60 * 60) | |
} | |
} | |
} | |
func usage() { | |
fmt.Fprintf(os.Stderr, ` | |
Usage: | |
examples: | |
查看域名一天的日志情况: | |
sjyCheckLog -action=dayCheck -rate=1.03 -sjyDomain=muy.a.yximgs.com -dayTime=2020-10-02 | |
查看域名单个小时的日志情况: | |
sjyCheckLog -action=domainCheck -sjyDomain=muy.a.yximgs.com -dayTime=2020-10-02-11 | |
根据检查结果使用离线日志补日志: | |
sjyCheckLog -action=fix -path=/disk4/liangchao/sjy/cdn-log | |
补单个小时日志: | |
sjyCheckLog -action=fixDomainHour -sjyDomain=muymov.a.yximgs.com -startTime=2019-10-01-00-00 | |
查询域名单个月份日志情况: | |
sjyCheckLog -action=checkMonth -sjymonth=2020-09 -domainList="sjy.a.yximgs.com,gamedl.gionee.com" -rate=1.02 | |
查询单个域名单个月情况: | |
sjyCheckLog -action=domainMonth -rate=1.01 -sjyDomain=muymov.a.yximgs.com -sjymonth=2019-09 | |
每隔 3个小时查询一次当前时间的前3个小时日志缺失情况: | |
sjyCheckLog -action=timingTask | |
Options: | |
`) | |
flag.PrintDefaults() | |
} | |
func checkMonth(sjymonth string, domainList string, rate float64) { | |
domainLists := strings.Split(domainList, ",") | |
for _, k := range domainLists { | |
month(k, rate, sjymonth) | |
} | |
} | |
// sjymonth格式为: 2019-10 | |
func month(domain3 string, rate float64, sjymonth string) { | |
time.Now().Format("2006-01-02 15:04:05") | |
tn := time.Now() | |
mov := strings.Split(tn.String(), "-") | |
day, _ := strconv.Atoi(strings.Split(mov[2], " ")[0]) | |
monthInt, _ := strconv.Atoi(strings.Split(mov[1], " ")[0]) | |
sjyMonthInt, _ := strconv.Atoi(strings.Split(sjymonth, "-")[1]) | |
var todoDay int | |
if monthInt == sjyMonthInt { | |
todoDay = day - 1 | |
} else { | |
todoDay = 31 | |
} | |
for t := 1; t <= todoDay; t++ { | |
if t <= 9 { | |
dayCheck(domain3, rate, sjymonth+"-0"+strconv.Itoa(t)+"-") | |
} else { | |
dayCheck(domain3, rate, sjymonth+"-"+strconv.Itoa(t)+"-") | |
} | |
} | |
} | |
func dayCheck(domain2 string, rate float64, time string) { | |
for i := 0; i <= 23; i++ { | |
if i <= 9 { | |
getRes(domain2, rate, time+"0"+strconv.Itoa(i)) | |
} else { | |
getRes(domain2, rate, time+strconv.Itoa(i)) | |
} | |
} | |
} | |
// 查看一个域名指定一天的日志和api带宽情况 | |
// domain | |
// time 格式为 2019-09-10 | |
func dayCheck2(domain2 string, rate float64, time string) { | |
for i := 0; i <= 23; i++ { | |
if i <= 9 { | |
getRes(domain2, rate, time+"-0"+strconv.Itoa(i)) | |
} else { | |
getRes(domain2, rate, time+"-"+strconv.Itoa(i)) | |
} | |
} | |
} | |
func getRes(domain string, rate float64, time string) { | |
c := &http.Client{} | |
req, errReq := http.NewRequest("GET", "http://xs394:18500/v1/domain/status?domain="+domain+"&time="+time, nil) | |
if errReq != nil { | |
fmt.Println(errReq) | |
} | |
resp, err := c.Do(req) | |
if resp.StatusCode != 200 { | |
fmt.Printf("%s %s %d\n", time, domain, resp.StatusCode) | |
return | |
} | |
if err != nil { | |
fmt.Println(err) | |
} | |
defer resp.Body.Close() | |
body, err := ioutil.ReadAll(resp.Body) | |
if err != nil { | |
fmt.Println(err) | |
} | |
var res Result | |
json.Unmarshal(body, &res) | |
point := res.Rate[:] | |
fluApi := res.Fluxapi | |
fluLog := res.Fluxlog | |
if strings.Contains(res.Status, "OK") || strings.Contains(res.Status, "异常") { | |
maxPoint, minPoint := maxValueMin(point) | |
t := compareApitoLog(fluApi, fluLog) | |
if minPoint < 0.95 && t > 3750000000 { | |
fmt.Printf("%s %s 单个点带宽差值 %f mbps, 当前比值为 %f, %s \n", time, domain, t*8/300/1000/1000, minPoint, "小于 0.95") | |
} else { | |
if maxPoint > rate && t > 3750000000 { | |
fmt.Printf("%s %s 单个点带宽差值 %f mbps, 当前比值为 %f \n", time, domain, t*8/300/1000/1000, maxPoint) | |
} | |
} | |
} else { | |
fmt.Printf("%s %s %s\n", time, domain, res.Status) | |
} | |
} | |
func getRes2(domain string, time string) { | |
c := &http.Client{} | |
req, errReq := http.NewRequest("GET", "http://xs394:18500/v1/domain/status?domain="+domain+"&time="+time, nil) | |
if errReq != nil { | |
fmt.Println(errReq) | |
} | |
resp, err := c.Do(req) | |
if resp.StatusCode != 200 { | |
fmt.Printf("%s %s %d\n", time, domain, resp.StatusCode) | |
return | |
} | |
if err != nil { | |
fmt.Println(err) | |
} | |
defer resp.Body.Close() | |
body, err := ioutil.ReadAll(resp.Body) | |
if err != nil { | |
fmt.Println(err) | |
} | |
fmt.Println(string(body)) | |
} | |
func getRes3(domain string, rate float64, time string) string { | |
var finstr string | |
c := &http.Client{} | |
req, errReq := http.NewRequest("GET", "http://xs394:18500/v1/domain/status?domain="+domain+"&time="+time, nil) | |
if errReq != nil { | |
fmt.Println(errReq) | |
} | |
resp, err := c.Do(req) | |
if resp.StatusCode != 200 { | |
fs := fmt.Sprintf("%s %s %d\n", time, domain, resp.StatusCode) | |
return fs | |
} | |
if err != nil { | |
fmt.Println(err) | |
} | |
defer resp.Body.Close() | |
body, err := ioutil.ReadAll(resp.Body) | |
if err != nil { | |
fmt.Println(err) | |
} | |
var res Result | |
json.Unmarshal(body, &res) | |
point := res.Rate[:] | |
fluApi := res.Fluxapi | |
fluLog := res.Fluxlog | |
if strings.Contains(res.Status, "OK") || strings.Contains(res.Status, "异常") { | |
maxPoint, minPoint := maxValueMin(point) | |
t := compareApitoLog(fluApi, fluLog) | |
if minPoint < 0.95 && t > 3750000000 { | |
finstr += fmt.Sprintf("%s %s 单个点带宽差值 %f mbps, 当前比值为 %f %s \n", time, domain, t*8/300/1000/1000, minPoint, "小于 0.95") | |
} else { | |
if maxPoint > rate && t > 3750000000 { | |
finstr += fmt.Sprintf("%s %s 单个点带宽差值 %f mbps, 当前比值为 %f \n", time, domain, t*8/300/1000/1000, maxPoint) | |
} | |
} | |
} else { | |
finstr += fmt.Sprintf("%s %s %s\n", time, domain, res.Status) | |
} | |
return finstr | |
} | |
// 获取 api 和 log 的最大差值 | |
func compareApitoLog(api [12]int64, log [12]int64) float64 { | |
var t float64 = 0 | |
var result [12]int64 | |
for i := 0; i < 12; i++ { | |
result[i] = api[i] - log[i] | |
u := math.Abs(float64(result[i])) | |
if u > t { | |
t = u | |
} | |
} | |
return t | |
} | |
type FixlogStr struct { | |
Cdn string `json:"cdn"` | |
Domains [1]string `json:"domains"` | |
Start string `json:"start"` | |
End string `json:"end"` | |
UseOnlineLog bool `json:"useOnlineLog"` | |
Type int `json:"type"` | |
Force bool `json:"force"` | |
} | |
// 补日志 | |
func fixlog(domain string, startTime string) { | |
c := &http.Client{} | |
var endTime string | |
t := strings.Split(startTime, "-") | |
if t[3] == "23" { | |
newt, _ := strconv.Atoi(t[2]) | |
endTime = fmt.Sprintf("%s-%s-%d-00", t[0], t[1], newt+1) | |
} else { | |
w, _ := strconv.Atoi(t[3]) | |
if w < 9 { | |
endTime = fmt.Sprintf("%s-%s-%s-0%d", t[0], t[1], t[2], w+1) | |
} else { | |
endTime = fmt.Sprintf("%s-%s-%s-%d", t[0], t[1], t[2], w+1) | |
} | |
} | |
var domainstr [1]string | |
domainstr[0] = domain | |
fixlogTask := FixlogStr{ | |
Cdn:"all", | |
Domains:domainstr, | |
Start:startTime, | |
End:endTime, | |
UseOnlineLog: false, | |
Type:0, | |
Force:true, | |
} | |
jp, err := json.Marshal(fixlogTask) | |
if err != nil { | |
fmt.Println(err) | |
} | |
req, errReq := http.NewRequest("POST", "http://logsysetl.defy.internal.qiniu.io/v5/etl/retry", bytes.NewReader(jp)) | |
req.Header.Set("content-type", "application/json") | |
if errReq != nil { | |
fmt.Println(errReq) | |
} | |
resp, err := c.Do(req) | |
if err != nil { | |
fmt.Println(err) | |
} | |
defer resp.Body.Close() | |
body, err := ioutil.ReadAll(resp.Body) | |
fmt.Printf("%s\t%s\t%d\t%s\n", startTime, domain, resp.StatusCode, string(body)) | |
if resp.StatusCode != 200 { | |
fmt.Println(string(body)) | |
} | |
} | |
// 根据检查结果进行补日志, 格式为 时间、空格、域名 | |
func dofix(path string) { | |
f, err := os.Open(path) | |
if err != nil { | |
panic(err) | |
} | |
defer f.Close() | |
rd := bufio.NewReader(f) | |
for { | |
line, err := rd.ReadString('\n') //以'\n'为结束符读入一行 | |
if err != nil || io.EOF == err { | |
break | |
} | |
ttb := strings.Split(line, " ") | |
ttb1 := strings.Split(ttb[1], "\n") | |
if len(ttb) > 2 { | |
fixlog(ttb[1], ttb[0]) | |
} else { | |
if len(ttb) >= 2 { | |
fixlog(ttb1[0], ttb[0]) | |
} | |
} | |
time.Sleep(time.Second * 1) | |
} | |
} | |
func maxValueMin(t []float64) (float64, float64) { | |
max := t[0] | |
min := t[0] | |
for i := 1; i < len(t); i++ { | |
if max < t[i] { | |
max = t[i] | |
} | |
if min > t[i] { | |
min = t[i] | |
} | |
} | |
return max, min | |
} | |
type Tm struct { | |
Content string `json:"content"` | |
} | |
type Smessage struct { | |
Msgtype string `json:"msgtype"` | |
Text Tm `json:"text"` | |
Mentioned_mobile_list string `json:"mentioned_mobile_list"` | |
} | |
//发送补日志消息到企业微信中 | |
func sendFixMessage(str string) { | |
tm := Tm{ | |
Content: str, | |
} | |
p := Smessage{ | |
Msgtype: "text", | |
Text: tm, | |
} | |
jsp, err := json.Marshal(p) | |
fmt.Println(string(jsp)) | |
if err != nil { | |
fmt.Println(err) | |
} | |
c := &http.Client{} | |
req, errReq := http.NewRequest("POST", "**", bytes.NewReader(jsp)) | |
if errReq != nil { | |
fmt.Println(errReq) | |
} | |
req.Header.Set("content-type", "application/json") | |
resp, err := c.Do(req) | |
if err != nil { | |
fmt.Println(err) | |
} | |
defer resp.Body.Close() | |
body, err := ioutil.ReadAll(resp.Body) | |
fmt.Println(string(body)) | |
if resp.StatusCode != 200 { | |
fmt.Println(string(body)) | |
} | |
} | |
//定时检查任务,1个小时运行一次 | |
func timedTask(todoCheck string, rate float64) { | |
time.Now().Format("2006-01-02 15:04:05") | |
tn := time.Now() | |
currentTime := tn.Add(time.Second * 60 * 60 * 3 * -1) | |
tHour := currentTime.Hour() | |
v := strings.Split(currentTime.String(), " ") | |
timeTo := fmt.Sprintf("%s-%d", v[0], tHour) | |
if tn.Hour() == 10 { | |
timedTaskDay(todoCheck, rate) | |
} | |
var str string = "每小时视界云日志缺失提醒, 检测时间" + timeTo + ":\n\n" | |
tclist := strings.Split(todoCheck, ",") | |
for _, i := range tclist { | |
str += getRes3(i, rate, timeTo) | |
} | |
if len(str) < 70 { | |
fmt.Println(str + "\n 检测无缺失 \n") | |
} else { | |
sendFixMessage(str) | |
} | |
} | |
//定时任务,一天运行一次 | |
func timedTaskDay(todoCheck string, rate float64) { | |
time.Now().Format("2006-01-02 15:04:05") | |
tn := time.Now() | |
currentTime := tn.Add(time.Second * 60 * 60 * 24 * -1) | |
v := strings.Split(currentTime.String(), " ") | |
var str string = "每日视界云日志检测, 检测时间" + v[0] + ":\n\n" | |
sst := strings.Split(todoCheck, ",") | |
for _, j := range sst { | |
for i := 0; i <= 23; i++ { | |
if i <= 9 { | |
str += getRes3(j, rate, v[0]+"-0"+strconv.Itoa(i)) | |
} else { | |
str += getRes3(j, rate, v[0]+"-"+strconv.Itoa(i)) | |
} | |
} | |
} | |
if len(str) < 70 { | |
sendFixMessage(str + "\n 检测无缺失 \n") | |
} else { | |
sendFixMessage(str) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment