327 lines
7.9 KiB
Go
327 lines
7.9 KiB
Go
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
|
|
}
|