package ml
import (
"github.com/dmitryikh/leaves"
)
var modelML *leaves.Ensemble
// 初始化加载模型
func initML() {
if modelML != nil {
return
}
useTransformation := true
var err error
modelML, err = leaves.LGEnsembleFromFile("./model.txt", useTransformation)
if err != nil {
panic(err)
}
}
// 预测
func Predict(fvals []float64) bool {
initML()
p := modelML.PredictSingle(fvals, 0)
return p > 0.5
}
参考: LightGBM简单例子
进一步封装代码
package analysis
import (
"bytes"
"fmt"
"math/rand"
"analysis/ml"
"strings"
"time"
)
// 机器学习模型使用的特征
// 数据源改成MOD的新版本特征集合
// 带 vs 的都是比率
type Features2 struct {
DebugInfo string // 调试时帮助定位的信息,比如:时间
QPM int64 // 当前的QPM
QPMvsYesterday float64 // 日环比 比率
QPMvsYesterdayMax float64 // 当前QPM比前日Max QPM的百分比 比率
QPMvsWeek float64 // 周同比 比率
QPMvsMonth float64 // 月同比 比率
QPMvsPrevMinute float64 // QPM 当前分钟 vs 前一分钟 比率
QPMvsLast20AvgFluctuation float64 // QPM 当前分钟 vs 前20分钟的平均 比率
AVGIncrease int64 // 比前一分钟平均耗时增加的毫秒数
AVGLast20Increase float64 // 比前20分钟平均耗时增加的毫秒数
AVGvsPrevMinute float64 // 平均耗时 当前分钟 vs 前一分钟 比率
AVGvsLast20AvgFluctuation float64 // 平均耗时 当前分钟 vs 前20分钟的平均 比率
ThroughputvsPrevMinute float64 // 吞吐量 当前分钟 vs 前一分钟 比率
ThroughputvsLast20AvgFluctuation float64 // 吞吐量 当前分钟 vs 前20分钟的平均 比率
ErrorNum int // 错误数
ErrorvsPrevMinute float64 // 错误 当前分钟 vs 前一分钟
CPUBusyMax float64 // cpu.busy 最大值
CPUBusyOverThreshold int // cpu.busy 超过阈值的数量 阈值 > 80%
JVMFullgcCountMax float64 // jvm.fullgc.count 最大值
JVMFullgcCountOverThreshold int // jvm.fullgc.count 超过阈值的数量 阈值:> 0
JVMThreadBlockedCountMax float64 // jvm.thread.blocked.count 最大值
JVMThreadBlockedCountOverThreshold int // jvm.thread.blocked.count 超过阈值的数量 阈值 > 3
MEMUsedPercentMax float64 // mem.memused.percent 最大值
MEMUsedPercentOverThreshold int // mem.memused.percent 超过阈值的数量 阈值 > 80%
MEMSwapusedCountMax float64 // mem.swapused.percent 最大值
MEMSwapusedCountOverThreshold int // mem.swapused.percent 超过阈值的数量 阈值 > 80%
NumberOfMachines int // 机器数, 有host数据的机器数
}
func GetCSVHeader(debug bool) string {
doc := strings.Builder{}
if debug {
doc.WriteString("debug,")
}
doc.WriteString("label,")
doc.WriteString("QPM,")
doc.WriteString("QPMvsYesterday,")
doc.WriteString("QPMvsYesterdayMax,")
doc.WriteString("QPMvsWeek,")
doc.WriteString("QPMvsMonth,")
doc.WriteString("QPMvsPrevMinute,")
doc.WriteString("QPMvsLast20AvgFluctuation,")
doc.WriteString("AVGIncrease,")
doc.WriteString("AVGLast20Increase,")
doc.WriteString("AVGvsPrevMinute,")
doc.WriteString("AVGvsLast20AvgFluctuation,")
doc.WriteString("ThroughputvsPrevMinute,")
doc.WriteString("ThroughputvsLast20AvgFluctuation,")
doc.WriteString("ErrorNum,")
doc.WriteString("ErrorvsPrevMinute,")
doc.WriteString("CPUBusyMax,")
doc.WriteString("CPUBusyOverThreshold,")
doc.WriteString("JVMFullgcCountMax,")
doc.WriteString("JVMFullgcCountOverThreshold,")
doc.WriteString("JVMThreadBlockedCountMax,")
doc.WriteString("JVMThreadBlockedCountOverThreshold,")
doc.WriteString("MEMUsedPercentMax,")
doc.WriteString("MEMUsedPercentOverThreshold,")
doc.WriteString("MEMSwapusedCountMax,")
doc.WriteString("MEMSwapusedCountOverThreshold,")
doc.WriteString("NumberOfMachines")
doc.WriteString("\n")
return doc.String()
}
// 生成 csv 行
func (f *Features2) CSV(label int, debug bool) string {
doc := strings.Builder{}
doc.WriteString(fmt.Sprintf("%d,", label))
// if debug {
// doc.WriteString(f.DebugInfo)
// doc.WriteString(",")
// }
if f.QPM > 0 {
doc.WriteString(fmt.Sprintf("%d,", f.QPM))
} else {
doc.WriteString("0,")
}
if f.QPMvsYesterday > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.QPMvsYesterday))
} else {
doc.WriteString("0,")
}
if f.QPMvsYesterdayMax > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.QPMvsYesterdayMax))
} else {
doc.WriteString("0,")
}
if f.QPMvsWeek > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.QPMvsWeek))
} else {
doc.WriteString("0,")
}
if f.QPMvsMonth > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.QPMvsMonth))
} else {
doc.WriteString("0,")
}
if f.QPMvsPrevMinute > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.QPMvsPrevMinute))
} else {
doc.WriteString("0,")
}
if f.QPMvsLast20AvgFluctuation > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.QPMvsLast20AvgFluctuation))
} else {
doc.WriteString("0,")
}
doc.WriteString(fmt.Sprintf("%d,", f.AVGIncrease))
if f.AVGLast20Increase > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.AVGLast20Increase))
} else {
doc.WriteString("0,")
}
if f.AVGvsPrevMinute > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.AVGvsPrevMinute))
} else {
doc.WriteString("0,")
}
if f.AVGvsLast20AvgFluctuation > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.AVGvsLast20AvgFluctuation))
} else {
doc.WriteString("0,")
}
if f.ThroughputvsPrevMinute > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.ThroughputvsPrevMinute))
} else {
doc.WriteString("0,")
}
if f.ThroughputvsLast20AvgFluctuation > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.ThroughputvsLast20AvgFluctuation))
} else {
doc.WriteString("0,")
}
if f.ErrorNum > 0 {
doc.WriteString(fmt.Sprintf("%d,", f.ErrorNum))
} else {
doc.WriteString("0,")
}
if f.ErrorvsPrevMinute > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.ErrorvsPrevMinute))
} else {
doc.WriteString("0,")
}
if f.CPUBusyMax > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.CPUBusyMax))
} else {
doc.WriteString("0,")
}
doc.WriteString(fmt.Sprintf("%d,", f.CPUBusyOverThreshold))
if f.JVMFullgcCountMax > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.JVMFullgcCountMax))
} else {
doc.WriteString("0,")
}
doc.WriteString(fmt.Sprintf("%d,", f.JVMFullgcCountOverThreshold))
if f.JVMThreadBlockedCountMax > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.JVMThreadBlockedCountMax))
} else {
doc.WriteString("0,")
}
doc.WriteString(fmt.Sprintf("%d,", f.JVMThreadBlockedCountOverThreshold))
if f.MEMUsedPercentMax > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.MEMUsedPercentMax))
} else {
doc.WriteString("0,")
}
doc.WriteString(fmt.Sprintf("%d,", f.MEMUsedPercentOverThreshold))
if f.MEMSwapusedCountMax > float64(0.000001) {
doc.WriteString(fmt.Sprintf("%.6f,", f.MEMSwapusedCountMax))
} else {
doc.WriteString("0,")
}
doc.WriteString(fmt.Sprintf("%d,", f.MEMSwapusedCountOverThreshold))
doc.WriteString(fmt.Sprintf("%d", f.NumberOfMachines))
doc.WriteString("\n")
return doc.String()
}
// 产生一行 LibSVM 格式的数据
// 格式规范看
// https://blog.csdn.net/yangshaojun1992/article/details/87861767
// label 0 没有问题 1 有问题
func (f *Features2) LibSVM(label int, debug bool) string {
doc := bytes.NewBufferString(fmt.Sprintf("%d", label))
if debug {
doc.WriteString(fmt.Sprintf(" %s", f.DebugInfo))
}
if f.QPM > 0 {
if debug {
doc.WriteString(fmt.Sprintf(" 1-QPM:%d", f.QPM))
} else {
doc.WriteString(fmt.Sprintf(" 1:%d", f.QPM))
}
} else {
doc.WriteString(" 1:0")
}
if f.QPMvsYesterday > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 2-QPMvsYesterday:%.6f", f.QPMvsYesterday))
} else {
doc.WriteString(fmt.Sprintf(" 2:%.6f", f.QPMvsYesterday))
}
} else {
doc.WriteString(" 2:0")
}
if f.QPMvsYesterdayMax > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 3-QPMvsYesterdayMax:%.6f", f.QPMvsYesterdayMax))
} else {
doc.WriteString(fmt.Sprintf(" 3:%.6f", f.QPMvsYesterdayMax))
}
} else {
doc.WriteString(" 3:0")
}
if f.QPMvsWeek > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 4-QPMvsWeek:%.6f", f.QPMvsWeek))
} else {
doc.WriteString(fmt.Sprintf(" 4:%.6f", f.QPMvsWeek))
}
} else {
doc.WriteString(" 4:0")
}
if f.QPMvsMonth > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 5-QPMvsMonth:%.6f", f.QPMvsMonth))
} else {
doc.WriteString(fmt.Sprintf(" 5:%.6f", f.QPMvsMonth))
}
} else {
doc.WriteString(" 5:0")
}
if f.QPMvsPrevMinute > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 6-QPMvsPrevMinute:%.6f", f.QPMvsPrevMinute))
} else {
doc.WriteString(fmt.Sprintf(" 6:%.6f", f.QPMvsPrevMinute))
}
} else {
doc.WriteString(" 6:0")
}
if f.QPMvsLast20AvgFluctuation > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 7-QPMvsLast20AvgFluctuation:%.6f", f.QPMvsLast20AvgFluctuation))
} else {
doc.WriteString(fmt.Sprintf(" 7:%.6f", f.QPMvsLast20AvgFluctuation))
}
} else {
doc.WriteString(" 7:0")
}
if debug {
doc.WriteString(fmt.Sprintf(" 8-AVGIncrease:%d", f.AVGIncrease))
} else {
doc.WriteString(fmt.Sprintf(" 8:%d", f.AVGIncrease))
}
if f.AVGLast20Increase > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 9-AVGLast20Increase:%.6f", f.AVGLast20Increase))
} else {
doc.WriteString(fmt.Sprintf(" 9:%.6f", f.AVGLast20Increase))
}
} else {
doc.WriteString(" 9:0")
}
if f.AVGvsPrevMinute > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 10-AVGvsPrevMinute:%.6f", f.AVGvsPrevMinute))
} else {
doc.WriteString(fmt.Sprintf(" 10:%.6f", f.AVGvsPrevMinute))
}
} else {
doc.WriteString(" 10:0")
}
if f.AVGvsLast20AvgFluctuation > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 11-AVGvsLast20AvgFluctuation:%.6f", f.AVGvsLast20AvgFluctuation))
} else {
doc.WriteString(fmt.Sprintf(" 11:%.6f", f.AVGvsLast20AvgFluctuation))
}
} else {
doc.WriteString(" 11:0")
}
if f.ThroughputvsPrevMinute > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 12-ThroughputvsPrevMinute:%.6f", f.ThroughputvsPrevMinute))
} else {
doc.WriteString(fmt.Sprintf(" 12:%.6f", f.ThroughputvsPrevMinute))
}
} else {
doc.WriteString(" 12:0")
}
if f.ThroughputvsLast20AvgFluctuation > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 13-ThroughputvsLast20AvgFluctuation:%.6f", f.ThroughputvsLast20AvgFluctuation))
} else {
doc.WriteString(fmt.Sprintf(" 13:%.6f", f.ThroughputvsLast20AvgFluctuation))
}
} else {
doc.WriteString(" 13:0")
}
if f.ErrorNum > 0 {
if debug {
doc.WriteString(fmt.Sprintf(" 14-ErrorNum:%d", f.ErrorNum))
} else {
doc.WriteString(fmt.Sprintf(" 14:%d", f.ErrorNum))
}
} else {
doc.WriteString(" 14:0")
}
if f.ErrorvsPrevMinute > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 15-ErrorvsPrevMinute:%.6f", f.ErrorvsPrevMinute))
} else {
doc.WriteString(fmt.Sprintf(" 15:%.6f", f.ErrorvsPrevMinute))
}
} else {
doc.WriteString(" 15:0")
}
if f.CPUBusyMax > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 16-CPUBusyMax:%.6f", f.CPUBusyMax))
} else {
doc.WriteString(fmt.Sprintf(" 16:%.6f", f.CPUBusyMax))
}
} else {
doc.WriteString(" 16:0")
}
if debug {
doc.WriteString(fmt.Sprintf(" 17-CPUBusyOverThreshold:%d", f.CPUBusyOverThreshold))
} else {
doc.WriteString(fmt.Sprintf(" 17:%d", f.CPUBusyOverThreshold))
}
if f.JVMFullgcCountMax > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 18-JVMFullgcCountMax:%.6f", f.JVMFullgcCountMax))
} else {
doc.WriteString(fmt.Sprintf(" 18:%.6f", f.JVMFullgcCountMax))
}
} else {
doc.WriteString(" 18:0")
}
if debug {
doc.WriteString(fmt.Sprintf(" 19-JVMFullgcCountOverThreshold:%d", f.JVMFullgcCountOverThreshold))
} else {
doc.WriteString(fmt.Sprintf(" 19:%d", f.JVMFullgcCountOverThreshold))
}
if f.JVMThreadBlockedCountMax > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 20-JVMThreadBlockedCountMax:%.6f", f.JVMThreadBlockedCountMax))
} else {
doc.WriteString(fmt.Sprintf(" 20:%.6f", f.JVMThreadBlockedCountMax))
}
} else {
doc.WriteString(" 20:0")
}
if debug {
doc.WriteString(fmt.Sprintf(" 21-JVMThreadBlockedCountOverThreshold:%d", f.JVMThreadBlockedCountOverThreshold))
} else {
doc.WriteString(fmt.Sprintf(" 21:%d", f.JVMThreadBlockedCountOverThreshold))
}
if f.MEMUsedPercentMax > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 22-MEMUsedPercentMax:%.6f", f.MEMUsedPercentMax))
} else {
doc.WriteString(fmt.Sprintf(" 22:%.6f", f.MEMUsedPercentMax))
}
} else {
doc.WriteString(" 22:0")
}
if debug {
doc.WriteString(fmt.Sprintf(" 23-MEMUsedPercentOverThreshold:%d", f.MEMUsedPercentOverThreshold))
} else {
doc.WriteString(fmt.Sprintf(" 23:%d", f.MEMUsedPercentOverThreshold))
}
if f.MEMSwapusedCountMax > float64(0.000001) {
if debug {
doc.WriteString(fmt.Sprintf(" 24-MEMSwapusedCountMax:%.6f", f.MEMSwapusedCountMax))
} else {
doc.WriteString(fmt.Sprintf(" 24:%.6f", f.MEMSwapusedCountMax))
}
} else {
doc.WriteString(" 24:0")
}
if debug {
doc.WriteString(fmt.Sprintf(" 25-MEMSwapusedCountOverThreshold:%d", f.MEMSwapusedCountOverThreshold))
} else {
doc.WriteString(fmt.Sprintf(" 25:%d", f.MEMSwapusedCountOverThreshold))
}
if debug {
doc.WriteString(fmt.Sprintf(" 26-NumberOfMachines:%d", f.NumberOfMachines))
} else {
doc.WriteString(fmt.Sprintf(" 26:%d", f.NumberOfMachines))
}
doc.WriteString("\n")
return doc.String()
}
// 通过机器学习预测判断
func (f *Features2) MLPredict() bool {
fvals := make([]float64, 64)
fvals[0] = float64(f.QPM)
fvals[1] = f.QPMvsYesterday
fvals[2] = f.QPMvsYesterdayMax
fvals[3] = f.QPMvsWeek
fvals[4] = f.QPMvsMonth
fvals[5] = f.QPMvsPrevMinute
fvals[6] = f.QPMvsLast20AvgFluctuation
fvals[7] = float64(f.AVGIncrease)
fvals[8] = f.AVGLast20Increase
fvals[9] = f.AVGvsPrevMinute
fvals[10] = f.AVGvsLast20AvgFluctuation
fvals[11] = f.ThroughputvsPrevMinute
fvals[12] = f.ThroughputvsLast20AvgFluctuation
fvals[13] = float64(f.ErrorNum)
fvals[14] = f.ErrorvsPrevMinute
fvals[15] = f.CPUBusyMax
fvals[16] = float64(f.CPUBusyOverThreshold)
fvals[17] = f.JVMFullgcCountMax
fvals[18] = float64(f.JVMFullgcCountOverThreshold)
fvals[19] = f.JVMThreadBlockedCountMax
fvals[20] = float64(f.JVMThreadBlockedCountOverThreshold)
fvals[21] = f.MEMUsedPercentMax
fvals[22] = float64(f.MEMUsedPercentOverThreshold)
fvals[23] = f.MEMSwapusedCountMax
fvals[24] = float64(f.MEMSwapusedCountOverThreshold)
fvals[25] = float64(f.NumberOfMachines)
return ml.Predict(fvals)
}
// 基于规则的风险判断
func (f *Features2) RiskByRule() (risk bool, ruleInfo string, targetArr []string) {
if f == nil {
return false, "", []string{}
}
// 超过10%的机器出现 cpu.busy
if f.CPUBusyOverThreshold > 0 && float64(f.CPUBusyOverThreshold)/float64(f.NumberOfMachines) > 0.1 {
return true, fmt.Sprintf("f.CPUBusyOverThreshold(%d) > 0 && float64(f.CPUBusyOverThreshold(%d))/float64(f.NumberOfMachines(%d)) > 0.1", f.CPUBusyOverThreshold, f.CPUBusyOverThreshold, f.NumberOfMachines), []string{"cpu.busy"}
}
// 高峰期GC才有问题
if f.JVMFullgcCountOverThreshold > 1 && f.QPMvsYesterdayMax > 0.7 {
return true, fmt.Sprintf("f.JVMFullgcCountOverThreshold(%d) > 1 && f.QPMvsYesterdayMax(%f) > 0.7", f.JVMFullgcCountOverThreshold, f.QPMvsYesterdayMax), []string{"jvm.fullgc.count", "qpm"}
}
// 日志记录会block线程, 只要不是高峰期的block就没有风险
// 超过10%的机器有block线程问题,属于有风险
if f.JVMThreadBlockedCountOverThreshold > int(float64(f.NumberOfMachines)*0.1) && f.QPMvsYesterdayMax > 0.6 {
return true, fmt.Sprintf("f.JVMThreadBlockedCountOverThreshold(%d) > int(float64(f.NumberOfMachines(%d))*0.1) && f.QPMvsYesterdayMax(%f) > 0.6 ", f.JVMThreadBlockedCountOverThreshold, f.NumberOfMachines, f.QPMvsYesterdayMax), []string{"jvm.thread.blocked.count"}
}
if f.MEMUsedPercentOverThreshold > 0 {
return true, fmt.Sprintf("f.MEMUsedPercentOverThreshold(%d) > 0", f.MEMUsedPercentOverThreshold), []string{"mem.memused.percent"}
}
if f.MEMSwapusedCountOverThreshold > 0 {
return true, fmt.Sprintf("f.MEMSwapusedCountOverThreshold(%d) > 0", f.MEMSwapusedCountOverThreshold), []string{"mem.swapused.percent"}
}
// 错误占比大
if f.ErrorNum > 1 && f.ErrorvsPrevMinute > 2.0 && float64(f.ErrorNum)/float64(f.QPM) > 0.001 {
return true, fmt.Sprintf("f.ErrorNum(%d) > 1 && f.ErrorvsPrevMinute(%f) > 2.0 && float64(f.ErrorNum(%d))/float64(f.QPM(%d))(%f) > 0.001", f.ErrorNum, f.ErrorvsPrevMinute, f.ErrorNum, f.QPM, float64(f.ErrorNum)/float64(f.QPM)), []string{"error", "qpm"}
}
// 错误量级多
if f.ErrorNum > 100 && f.ErrorvsPrevMinute > 2.0 {
return true, fmt.Sprintf("f.ErrorNum(%d) > 100 && f.ErrorvsPrevMinute(%.3f) > 2.0", f.ErrorNum, f.ErrorvsPrevMinute), []string{"error"}
}
// 流量突增, 看耗时又没增加?
// 20211108 上面的case, 有突增,但是耗时、服务指标各项正常, 不属于风险隐患
if f.QPMvsPrevMinute > 1.4 && f.QPMvsYesterdayMax > 0.5 && f.AVGvsPrevMinute > 1.2 && (f.AVGvsLast20AvgFluctuation > 1.2 || f.CPUBusyOverThreshold > 1 || f.JVMFullgcCountOverThreshold > 1 || f.ErrorNum > 1) {
return true, fmt.Sprintf("f.QPMvsPrevMinute(%f) > 1.4 && f.QPMvsYesterdayMax(%f) > 0.5 &&f.AVGvsPrevMinute(%f) > 1.2 && (f.AVGvsLast20AvgFluctuation(%f) > 1.2 || f.CPUBusyOverThreshold(%d) > 1 || f.JVMFullgcCountOverThreshold(%d) > 1 || f.ErrorNum(%d) > 1) ", f.QPMvsPrevMinute, f.QPMvsYesterdayMax, f.AVGvsPrevMinute, f.AVGvsLast20AvgFluctuation, f.CPUBusyOverThreshold, f.JVMFullgcCountOverThreshold, f.ErrorNum), []string{"qpm", "error", "avg", "cpu.busy", "jvm.fullgc.count"}
}
// 20211108 增加判断条件
if f.QPMvsPrevMinute > 1.5 && f.QPMvsLast20AvgFluctuation > 1.3 && f.QPM > 1000 && (f.AVGvsLast20AvgFluctuation > 1.2 || f.CPUBusyOverThreshold > 1 || f.JVMFullgcCountOverThreshold > 1 || f.ErrorNum > 1) {
return true, fmt.Sprintf("f.QPMvsPrevMinute(%f) > 1.5 && f.QPMvsLast20AvgFluctuation(%f) > 1.3 && f.QPM(%d) > 1000 && (f.AVGvsLast20AvgFluctuation(%f) > 1.2 || f.CPUBusyOverThreshold(%d) > 1 || f.JVMFullgcCountOverThreshold(%d) > 1 || f.ErrorNum(%d) > 1) ", f.QPMvsPrevMinute, f.QPMvsLast20AvgFluctuation, f.QPM, f.AVGvsLast20AvgFluctuation, f.CPUBusyOverThreshold, f.JVMFullgcCountOverThreshold, f.ErrorNum), []string{"qpm", "error", "avg", "cpu.busy", "jvm.fullgc.count"}
}
if f.AVGvsPrevMinute > 1.5 && f.AVGvsLast20AvgFluctuation > 1.3 && f.AVGIncrease > 50 {
return true, fmt.Sprintf("f.AVGvsPrevMinute(%f) > 1.5 && f.AVGvsLast20AvgFluctuation(%f) > 1.3 && f.AVGIncrease(%d) > 50", f.AVGvsPrevMinute, f.AVGvsLast20AvgFluctuation, f.AVGIncrease), []string{"avg"}
}
if f.AVGvsPrevMinute > 1.5 && f.AVGvsLast20AvgFluctuation > 1.3 && f.AVGLast20Increase > 100 {
return true, fmt.Sprintf("f.AVGvsPrevMinute(%f) > 1.5 && f.AVGvsLast20AvgFluctuation(%f) > 1.3 && f.AVGLast20Increase(%f) > 100", f.AVGvsPrevMinute, f.AVGvsLast20AvgFluctuation, f.AVGLast20Increase), []string{"avg"}
}
if f.ThroughputvsPrevMinute > 1.5 && f.ThroughputvsLast20AvgFluctuation > 1.3 && f.QPMvsYesterdayMax > 0.8 {
return true, fmt.Sprintf("f.ThroughputvsPrevMinute(%f) > 1.5 && f.ThroughputvsLast20AvgFluctuation(%f) > 1.3 && f.QPMvsYesterdayMax(%f) > 0.8", f.ThroughputvsPrevMinute, f.ThroughputvsLast20AvgFluctuation, f.QPMvsYesterdayMax), []string{"avg", "qpm"}
}
// 解决这个问题
// 分钟级大范围上下波动,但是持续的都是这样的,属于无风险
if f.QPMvsLast20AvgFluctuation < 1.3 {
return false, fmt.Sprintf("f.QPMvsLast20AvgFluctuation(%f) < 1.3 ", f.QPMvsLast20AvgFluctuation), []string{}
}
// 20211106 流量比昨天和上周小的前提是没有错误,没有饱和度问题。
// 所以这个放在最后
if f.QPMvsYesterday < 1.1 || f.QPMvsWeek < 1.1 {
return false, fmt.Sprintf("f.QPMvsYesterday(%f) < 1.1 || f.QPMvsWeek(%f) < 1.1", f.QPMvsYesterday, f.QPMvsWeek), []string{}
}
return false, "", []string{}
}
// 在已有数据基础上,伪造出一定有问题的负样本数据
// 这些问题不是边界问题,是必定有问题的。
func (f *Features2) Forge() {
r := rand.New(rand.NewSource(time.Now().UnixNano())) // 随机数
switch r.Intn(6) {
case 0: // 超过10%的机器出现 cpu.busy
f.CPUBusyMax = 80 + r.Float64()*20
f.CPUBusyOverThreshold = int(float64(f.NumberOfMachines) * (0.3 + 0.7*r.Float64()))
case 1: // 高峰期GC有问题
f.QPMvsYesterdayMax = 80 + r.Float64()*20
f.JVMFullgcCountMax = float64(f.NumberOfMachines) * (0.3 + 0.7*r.Float64())
f.JVMFullgcCountOverThreshold = int(float64(f.NumberOfMachines) * (0.3 + 0.7*r.Float64()))
case 2: // 超过10%的机器有block线程问题,属于有风险
f.QPMvsYesterdayMax = 80 + r.Float64()*20
f.JVMThreadBlockedCountMax = 20
f.JVMThreadBlockedCountOverThreshold = int(float64(f.NumberOfMachines) * (0.3 + 0.7*r.Float64()))
case 3: // 错误量级多
f.ErrorNum = 100 + int(float64(f.QPM)*0.01*r.Float64())
f.ErrorvsPrevMinute = float64(f.ErrorNum)
case 4: // 流量突增, 耗时增加
f.QPMvsPrevMinute = 2.0 + r.Float64()
f.QPMvsYesterdayMax = 0.6 + 0.4*r.Float64()
f.AVGvsLast20AvgFluctuation = 1.3 + r.Float64()
f.AVGIncrease = int64(100 + r.Intn(1000))
default: // 不伪造数据,直接返回
}
}