package esLogUtil import ( "fmt" "sync" "time" "github.com/elastic/go-elasticsearch/v8" "goutil/logUtil" "goutil/stringUtil" ) var ( serverModuleName = "esLog" esClient *elasticsearch.Client indexName string //Index名 strServerGroupId string //区服 isStop bool logChan = make(chan EsLog, 2048) warnCount = 2000 closedChan = make(chan struct{}) logPool = sync.Pool{ New: func() interface{} { return &EsLog{} }, } ) // 启动ES日志系统 // 参数: // // esUrls:ES地址(多个地址使用,分割) // name:IndexName // serverGroupId:服务器组Id // // 返回值: // // 结果状态 func Start(esUrls string, name string, serverGroupId int32) { if stringUtil.IsEmpty(esUrls) { return } //构造Es客户端 var err error esClient, err = elasticsearch.NewClient(elasticsearch.Config{ Addresses: stringUtil.Split(esUrls, []string{","}), // Retry on 429 TooManyRequests statuses // RetryOnStatus: []int{502, 503, 504, 429}, // A simple incremental backoff function // RetryBackoff: func(i int) time.Duration { return time.Duration(i) * 100 * time.Millisecond }, // Retry up to 5 attempts // MaxRetries: 5, }) if err != nil { panic(fmt.Sprintf("构造es对象出错,err:%s", err.Error())) } indexName = name strServerGroupId = fmt.Sprintf("%d", serverGroupId) //初始化ES newIndexer(getIndexName()) timedReindex() startSendProcessor() guardProcessor() return } // 停止服务 func Stop() { //停止接受日志 isStop = true if indexer == nil { return } if len(logChan) == 0 { close(logChan) } <-closedChan } //#region 内部方法 func guardProcessor() { go func() { defer func() { if r := recover(); r != nil { logUtil.LogUnknownError(r) time.Sleep(1 * time.Second) guardProcessor() } }() for { time.Sleep(5 * time.Second) count := len(logChan) if count < warnCount { continue } logUtil.NormalLog(fmt.Sprintf("ES日志通道中当前有%d条消息待消费。", count), logUtil.Warn) } }() } func startSendProcessor() { go func() { defer func() { if r := recover(); r != nil { logUtil.LogUnknownError(r) time.Sleep(1 * time.Second) startSendProcessor() } }() for { select { case logObj, ok := <-logChan: if ok { bulkSendHandler(logObj) // 执行刷新 } if len(logChan) == 0 && isStop { // is closed closeIndex() closedChan <- struct{}{} return } } } }() } func getIndexName() string { //获取当天日期 return fmt.Sprintf("%s_%s", indexName, time.Now().Format("20060102")) } // 写入在线日志 // 参数: // // 日志信息对象 // // 返回值: // // 无 func writeLog(logObj *EsLog) { if isStop || indexer == nil { return } logChan <- *logObj } // 组装ES日志对象 // 参数: // // logType 日志类型 // format 日志格式 // args 参数列表 // // 返回值: // // 结果状态 func buildLog(logType, format string, args ...interface{}) (newLogObj *EsLog) { msg := format if len(args) > 0 { msg = fmt.Sprintf(format, args...) } //构造新的日志对象 newLogObj = new(logType, msg, strServerGroupId) return } //#endregion //#region 外部方法 // 日志记录 // // format:日志格式 // logType:日志类型 // args:参数列表 // // 返回值 // // 无 func NormalLog(format string, logType logUtil.LogType, args ...interface{}) { writeLog(buildLog(logType.String(), format, args...)) } // 消息日志记录 // // format:日志格式 // args:参数列表 // // 返回值 // // 无 func InfoLog(format string, args ...interface{}) { writeLog(buildLog("Info", format, args...)) } // 警告日志记录 // // format:日志格式 // args:参数列表 // // 返回值 // // 无 func WarnLog(format string, args ...interface{}) { writeLog(buildLog("Warn", format, args...)) } // 调试日志记录 // // format:日志格式 // args:参数列表 // // 返回值 // // 无 func DebugLog(format string, args ...interface{}) { writeLog(buildLog("Debug", format, args...)) } // 错误日志记录 // // format:日志格式 // args:参数列表 // // 返回值 // // 无 func ErrorLog(format string, args ...interface{}) { writeLog(buildLog("Error", format, args...)) } // 致命错误日志记录 // // format:日志格式 // args:参数列表 // // 返回值 // // 无 func FatalLog(format string, args ...interface{}) { writeLog(buildLog("Fatal", format, args...)) } //#endregion