finclip-app-manager/infrastructure/logger/log.go

327 lines
7.9 KiB
Go
Raw Permalink Normal View History

2023-10-31 14:07:26 +08:00
package logger
import (
"encoding/json"
"fmt"
"log"
"os"
"runtime"
"strconv"
"strings"
"time"
"finclip-app-manager/infrastructure/config"
"github.com/Shopify/sarama"
)
var logProducer sarama.AsyncProducer
type LogContent struct {
LogName string `json:"logger_name"`
LogLevel string `json:"loglevel"`
Message string `json:"message"`
Class string `json:"class"`
Host string `json:"host"`
File string `json:"file"`
Method string `json:"method"`
LineNumber string `json:"line_number"`
ThreadName string `json:"thread_name"`
AppName string `json:"Appname"`
ProjectName string `json:"projectname"`
Timestamp string `json:"timestamp"`
}
func init() {
if config.GetConfig().OpenKafkaLog {
kafkaConfig := sarama.NewConfig()
kafkaConfig.Producer.RequiredAcks = sarama.WaitForLocal
kafkaConfig.Producer.Compression = sarama.CompressionSnappy
kafkaConfig.Producer.Flush.Frequency = 500 * time.Millisecond
var err error
addrs := strings.Split(config.GetConfig().KafkaAddr, ",")
logProducer, err = sarama.NewAsyncProducer(addrs, kafkaConfig)
if err != nil {
panic(err)
}
fmt.Println("log kafka init succ ...")
}
}
func getLogInfo() (string, string, string) {
_, file, line, ok := runtime.Caller(3)
if !ok {
file = "???"
line = 0
} else {
short := file
for i := len(file) - 1; i > 0; i-- {
if file[i] == '/' {
short = file[i+1:]
break
}
}
file = short
}
pc := make([]uintptr, 1)
runtime.Callers(4, pc)
f := runtime.FuncForPC(pc[0])
return file, f.Name(), strconv.Itoa(line)
}
func getLogUtcTime() string {
t := time.Now().Format("2006-01-02 15:04:05")
loc, _ := time.ParseInLocation("2006-01-02 15:04:05", t, time.Local)
return loc.UTC().Format("2006-01-02T15:04:05.000Z")
}
func pullLogToKafka(logStr, logLevel string) error {
if config.GetConfig().OpenKafkaLog {
file, function, line := getLogInfo()
content := LogContent{}
content.LogName = config.GetConfig().ServerName + ".log"
content.LogLevel = logLevel
content.Message = logStr
content.Class = "test_class"
content.Host = "127.0.0.1"
content.File = file
content.Method = function
content.LineNumber = line
content.ThreadName = "test_thread_name"
content.AppName = config.GetConfig().ServerName
content.ProjectName = config.GetConfig().ServerName
content.Timestamp = getLogUtcTime()
valueByte, _ := json.Marshal(content)
logProducer.Input() <- &sarama.ProducerMessage{
Topic: config.GetConfig().LogTopic,
Value: sarama.ByteEncoder(string(valueByte)),
}
}
return nil
}
// Logger is the server logger
type Logger struct {
logger *log.Logger
debug bool
trace bool
file bool
infoLabel string
errorLabel string
fatalLabel string
debugLabel string
traceLabel string
}
// NewStdLogger creates a logger with output directed to Stderr
func NewStdLogger(time, file, debug, trace, colors, pid bool) *Logger {
flags := 0
if time {
flags = log.LstdFlags | log.Lmicroseconds
}
pre := ""
if pid {
pre = pidPrefix()
}
l := &Logger{
logger: log.New(os.Stdout, pre, flags),
debug: debug,
trace: trace,
file: file,
}
if colors {
setColoredLabelFormats(l)
} else {
setPlainLabelFormats(l)
}
return l
}
// NewFileLogger creates a logger with output directed to a file
func NewFileLogger(filename string, time, file, debug, trace, pid bool) *Logger {
fileflags := os.O_WRONLY | os.O_APPEND | os.O_CREATE
f, err := os.OpenFile(filename, fileflags, 0660)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
flags := 0
if time {
flags = log.LstdFlags | log.Lmicroseconds
}
pre := ""
if pid {
pre = pidPrefix()
}
l := &Logger{
logger: log.New(f, pre, flags),
debug: debug,
trace: trace,
file: file,
}
setPlainLabelFormats(l)
return l
}
// Generate the pid prefix string
func pidPrefix() string {
return fmt.Sprintf("[%d] ", os.Getpid())
}
func setPlainLabelFormats(l *Logger) {
l.infoLabel = "[INF]"
l.debugLabel = "[DBG]"
l.errorLabel = "[ERR]"
l.fatalLabel = "[FTL]"
l.traceLabel = "[TRC]"
}
func setColoredLabelFormats(l *Logger) {
colorFormat := "[\x1b[%dm%s\x1b[0m]"
l.infoLabel = fmt.Sprintf(colorFormat, 32, "INF")
l.debugLabel = fmt.Sprintf(colorFormat, 36, "DBG")
l.errorLabel = fmt.Sprintf(colorFormat, 31, "ERR")
l.fatalLabel = fmt.Sprintf(colorFormat, 31, "FTL")
l.traceLabel = fmt.Sprintf(colorFormat, 33, "TRC")
}
// copy from go/src/log/log.go and modify by guojuntao, 2017/09/21
// Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.
func itoa(i int, wid int) string {
// Assemble decimal in reverse order.
var b [20]byte
bp := len(b) - 1
for i >= 10 || wid > 1 {
wid--
q := i / 10
b[bp] = byte('0' + i - q*10)
bp--
i = q
}
// i < 10
b[bp] = byte('0' + i)
return string(b[bp:])
}
func (l *Logger) getFileLineFormat(calldepth int) string {
if l.file {
_, file, line, ok := runtime.Caller(calldepth)
if !ok {
file = "???"
line = 0
}
short := file
for i := len(file) - 1; i > 0; i-- {
if file[i] == '/' {
short = file[i+1:]
break
}
}
file = short
return " " + file + ":" + itoa(line, -1) + ":"
}
return ""
}
// Noticef logs a notice statement
func (l *Logger) Noticef(format string, v ...interface{}) {
pullLogToKafka(fmt.Sprintf(format, v...), "NOTICE")
l.logger.Printf(l.infoLabel+l.getFileLineFormat(2)+" "+format, v...)
}
func (l *Logger) Noticeln(v ...interface{}) {
pullLogToKafka(fmt.Sprint(v...), "NOTICE")
l.logger.Println(append([]interface{}{l.infoLabel + l.getFileLineFormat(2)}, v...)...)
}
// Warf logs an error statement
func (l *Logger) Warf(format string, v ...interface{}) {
pullLogToKafka(fmt.Sprintf(format, v...), "WARNING")
l.logger.Printf(l.errorLabel+l.getFileLineFormat(2)+" "+format, v...)
}
// Errorf logs an error statement
func (l *Logger) Errorf(format string, v ...interface{}) {
pullLogToKafka(fmt.Sprintf(format, v...), "ERROR")
l.logger.Printf(l.errorLabel+l.getFileLineFormat(2)+" "+format, v...)
}
func (l *Logger) Errorln(v ...interface{}) {
pullLogToKafka(fmt.Sprint(v...), "ERROR")
l.logger.Println(append([]interface{}{l.errorLabel + l.getFileLineFormat(2)}, v...)...)
}
// Fatalf logs a fatal error
func (l *Logger) Fatalf(format string, v ...interface{}) {
pullLogToKafka(fmt.Sprintf(format, v...), "FATAL")
l.logger.Fatalf(l.fatalLabel+l.getFileLineFormat(2)+" "+format, v...)
}
func (l *Logger) Fatalln(v ...interface{}) {
pullLogToKafka(fmt.Sprint(v...), "FATAL")
l.logger.Fatalln(append([]interface{}{l.fatalLabel + l.getFileLineFormat(2)}, v...)...)
}
// Debugf logs a debug statement
func (l *Logger) Debugf(format string, v ...interface{}) {
if l.debug {
pullLogToKafka(fmt.Sprintf(format, v...), "DEBUG")
l.logger.Printf(l.debugLabel+l.getFileLineFormat(2)+" "+format, v...)
}
}
func (l *Logger) Debugln(v ...interface{}) {
if l.debug {
pullLogToKafka(fmt.Sprint(v...), "DEBUG")
l.logger.Println(append([]interface{}{l.debugLabel + l.getFileLineFormat(2)}, v...)...)
}
}
// Infof logs a debug statement
func (l *Logger) Infof(format string, v ...interface{}) {
if l.debug {
pullLogToKafka(fmt.Sprintf(format, v...), "INFO")
l.logger.Printf(l.debugLabel+l.getFileLineFormat(2)+" "+format, v...)
}
}
func (l *Logger) Infoln(v ...interface{}) {
if l.debug {
pullLogToKafka(fmt.Sprint(v...), "INFO")
l.logger.Println(append([]interface{}{l.debugLabel + l.getFileLineFormat(2)}, v...)...)
}
}
// Tracef logs a trace statement
func (l *Logger) Tracef(format string, v ...interface{}) {
if l.trace {
pullLogToKafka(fmt.Sprintf(format, v...), "TRACE")
l.logger.Printf(l.traceLabel+l.getFileLineFormat(2)+" "+format, v...)
}
}
func (l *Logger) Traceln(v ...interface{}) {
if l.trace {
pullLogToKafka(fmt.Sprint(v...), "TRACE")
l.logger.Println(append([]interface{}{l.traceLabel + l.getFileLineFormat(2)}, v...)...)
}
}
func (l *Logger) IsDebugEnabled() bool {
return l.debug
}
func (l *Logger) IsTraceEnabled() bool {
return l.trace
}