Skip to content

Instantly share code, notes, and snippets.

@liangchaoboy
Created April 10, 2020 08:14
Show Gist options
  • Save liangchaoboy/a458a31ef485e2f9693fcdc65b99e6c5 to your computer and use it in GitHub Desktop.
Save liangchaoboy/a458a31ef485e2f9693fcdc65b99e6c5 to your computer and use it in GitHub Desktop.
视界云日志检测
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