refactor: create logx package (#584)
This commit is contained in:
256
logx/log.go
Normal file
256
logx/log.go
Normal file
@@ -0,0 +1,256 @@
|
||||
package logx
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/appleboy/gorush/core"
|
||||
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
green = string([]byte{27, 91, 57, 55, 59, 52, 50, 109})
|
||||
white = string([]byte{27, 91, 57, 48, 59, 52, 55, 109})
|
||||
yellow = string([]byte{27, 91, 57, 55, 59, 52, 51, 109})
|
||||
red = string([]byte{27, 91, 57, 55, 59, 52, 49, 109})
|
||||
blue = string([]byte{27, 91, 57, 55, 59, 52, 52, 109})
|
||||
magenta = string([]byte{27, 91, 57, 55, 59, 52, 53, 109})
|
||||
cyan = string([]byte{27, 91, 57, 55, 59, 52, 54, 109})
|
||||
reset = string([]byte{27, 91, 48, 109})
|
||||
)
|
||||
|
||||
// LogPushEntry is push response log
|
||||
type LogPushEntry struct {
|
||||
ID string `json:"notif_id,omitempty"`
|
||||
Type string `json:"type"`
|
||||
Platform string `json:"platform"`
|
||||
Token string `json:"token"`
|
||||
Message string `json:"message"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
var isTerm bool
|
||||
|
||||
func init() {
|
||||
isTerm = isatty.IsTerminal(os.Stdout.Fd())
|
||||
}
|
||||
|
||||
var (
|
||||
// LogAccess is log server request log
|
||||
LogAccess *logrus.Logger
|
||||
// LogError is log server error log
|
||||
LogError *logrus.Logger
|
||||
)
|
||||
|
||||
// InitLog use for initial log module
|
||||
func InitLog(accessLevel, accessLog, errorLevel, errorLog string) error {
|
||||
var err error
|
||||
|
||||
// init logger
|
||||
LogAccess = logrus.New()
|
||||
LogError = logrus.New()
|
||||
|
||||
if !isTerm {
|
||||
LogAccess.SetFormatter(&logrus.JSONFormatter{})
|
||||
LogError.SetFormatter(&logrus.JSONFormatter{})
|
||||
} else {
|
||||
LogAccess.Formatter = &logrus.TextFormatter{
|
||||
TimestampFormat: "2006/01/02 - 15:04:05",
|
||||
FullTimestamp: true,
|
||||
}
|
||||
|
||||
LogError.Formatter = &logrus.TextFormatter{
|
||||
TimestampFormat: "2006/01/02 - 15:04:05",
|
||||
FullTimestamp: true,
|
||||
}
|
||||
}
|
||||
|
||||
// set logger
|
||||
if err = SetLogLevel(LogAccess, accessLevel); err != nil {
|
||||
return errors.New("Set access log level error: " + err.Error())
|
||||
}
|
||||
|
||||
if err = SetLogLevel(LogError, errorLevel); err != nil {
|
||||
return errors.New("Set error log level error: " + err.Error())
|
||||
}
|
||||
|
||||
if err = SetLogOut(LogAccess, accessLog); err != nil {
|
||||
return errors.New("Set access log path error: " + err.Error())
|
||||
}
|
||||
|
||||
if err = SetLogOut(LogError, errorLog); err != nil {
|
||||
return errors.New("Set error log path error: " + err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetLogOut provide log stdout and stderr output
|
||||
func SetLogOut(log *logrus.Logger, outString string) error {
|
||||
switch outString {
|
||||
case "stdout":
|
||||
log.Out = os.Stdout
|
||||
case "stderr":
|
||||
log.Out = os.Stderr
|
||||
default:
|
||||
f, err := os.OpenFile(outString, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Out = f
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetLogLevel is define log level what you want
|
||||
// log level: panic, fatal, error, warn, info and debug
|
||||
func SetLogLevel(log *logrus.Logger, levelString string) error {
|
||||
level, err := logrus.ParseLevel(levelString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Level = level
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func colorForPlatForm(platform int) string {
|
||||
switch platform {
|
||||
case core.PlatFormIos:
|
||||
return blue
|
||||
case core.PlatFormAndroid:
|
||||
return yellow
|
||||
case core.PlatFormHuawei:
|
||||
return green
|
||||
default:
|
||||
return reset
|
||||
}
|
||||
}
|
||||
|
||||
func typeForPlatForm(platform int) string {
|
||||
switch platform {
|
||||
case core.PlatFormIos:
|
||||
return "ios"
|
||||
case core.PlatFormAndroid:
|
||||
return "android"
|
||||
case core.PlatFormHuawei:
|
||||
return "huawei"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func hideToken(token string, markLen int) string {
|
||||
if token == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
if len(token) < markLen*2 {
|
||||
return strings.Repeat("*", len(token))
|
||||
}
|
||||
|
||||
start := token[len(token)-markLen:]
|
||||
end := token[0:markLen]
|
||||
|
||||
result := strings.Replace(token, start, strings.Repeat("*", markLen), -1)
|
||||
result = strings.Replace(result, end, strings.Repeat("*", markLen), -1)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// GetLogPushEntry get push data into log structure
|
||||
func GetLogPushEntry(input *InputLog) LogPushEntry {
|
||||
var errMsg string
|
||||
var token string
|
||||
|
||||
plat := typeForPlatForm(input.Platform)
|
||||
|
||||
if input.Error != nil {
|
||||
errMsg = input.Error.Error()
|
||||
}
|
||||
|
||||
if input.HideToken {
|
||||
token = hideToken(input.Token, 10)
|
||||
}
|
||||
|
||||
return LogPushEntry{
|
||||
ID: input.ID,
|
||||
Type: input.Status,
|
||||
Platform: plat,
|
||||
Token: token,
|
||||
Message: input.Message,
|
||||
Error: errMsg,
|
||||
}
|
||||
}
|
||||
|
||||
// InputLog log request
|
||||
type InputLog struct {
|
||||
ID string
|
||||
Status string
|
||||
Token string
|
||||
Message string
|
||||
Platform int
|
||||
Error error
|
||||
HideToken bool
|
||||
Format string
|
||||
}
|
||||
|
||||
// LogPush record user push request and server response.
|
||||
func LogPush(input *InputLog) {
|
||||
var platColor, resetColor, output string
|
||||
|
||||
if isTerm {
|
||||
platColor = colorForPlatForm(input.Platform)
|
||||
resetColor = reset
|
||||
}
|
||||
|
||||
log := GetLogPushEntry(input)
|
||||
|
||||
if input.Format == "json" {
|
||||
logJSON, _ := json.Marshal(log)
|
||||
|
||||
output = string(logJSON)
|
||||
} else {
|
||||
var typeColor string
|
||||
switch input.Status {
|
||||
case core.SucceededPush:
|
||||
if isTerm {
|
||||
typeColor = green
|
||||
}
|
||||
|
||||
output = fmt.Sprintf("|%s %s %s| %s%s%s [%s] %s",
|
||||
typeColor, log.Type, resetColor,
|
||||
platColor, log.Platform, resetColor,
|
||||
log.Token,
|
||||
log.Message,
|
||||
)
|
||||
case core.FailedPush:
|
||||
if isTerm {
|
||||
typeColor = red
|
||||
}
|
||||
|
||||
output = fmt.Sprintf("|%s %s %s| %s%s%s [%s] | %s | Error Message: %s",
|
||||
typeColor, log.Type, resetColor,
|
||||
platColor, log.Platform, resetColor,
|
||||
log.Token,
|
||||
log.Message,
|
||||
log.Error,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
switch input.Status {
|
||||
case core.SucceededPush:
|
||||
LogAccess.Info(output)
|
||||
case core.FailedPush:
|
||||
LogError.Error(output)
|
||||
}
|
||||
}
|
||||
0
logx/log/.gitkeep
Normal file
0
logx/log/.gitkeep
Normal file
0
logx/log/access.log
Normal file
0
logx/log/access.log
Normal file
129
logx/log_test.go
Normal file
129
logx/log_test.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package logx
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/appleboy/gorush/config"
|
||||
"github.com/appleboy/gorush/core"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSetLogLevel(t *testing.T) {
|
||||
log := logrus.New()
|
||||
|
||||
err := SetLogLevel(log, "debug")
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = SetLogLevel(log, "invalid")
|
||||
assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
|
||||
}
|
||||
|
||||
func TestSetLogOut(t *testing.T) {
|
||||
log := logrus.New()
|
||||
|
||||
err := SetLogOut(log, "stdout")
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = SetLogOut(log, "stderr")
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = SetLogOut(log, "log/access.log")
|
||||
assert.Nil(t, err)
|
||||
|
||||
// missing create logs folder.
|
||||
err = SetLogOut(log, "logs/access.log")
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestInitDefaultLog(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
|
||||
// no errors on default config
|
||||
assert.Nil(t, InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
))
|
||||
|
||||
PushConf.Log.AccessLevel = "invalid"
|
||||
|
||||
assert.NotNil(t, InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
))
|
||||
}
|
||||
|
||||
func TestAccessLevel(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
|
||||
PushConf.Log.AccessLevel = "invalid"
|
||||
|
||||
assert.NotNil(t, InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
))
|
||||
}
|
||||
|
||||
func TestErrorLevel(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
|
||||
PushConf.Log.ErrorLevel = "invalid"
|
||||
|
||||
assert.NotNil(t, InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
))
|
||||
}
|
||||
|
||||
func TestAccessLogPath(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
|
||||
PushConf.Log.AccessLog = "logs/access.log"
|
||||
|
||||
assert.NotNil(t, InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
))
|
||||
}
|
||||
|
||||
func TestErrorLogPath(t *testing.T) {
|
||||
PushConf, _ := config.LoadConf("")
|
||||
|
||||
PushConf.Log.ErrorLog = "logs/error.log"
|
||||
|
||||
assert.NotNil(t, InitLog(
|
||||
PushConf.Log.AccessLevel,
|
||||
PushConf.Log.AccessLog,
|
||||
PushConf.Log.ErrorLevel,
|
||||
PushConf.Log.ErrorLog,
|
||||
))
|
||||
}
|
||||
|
||||
func TestPlatFormType(t *testing.T) {
|
||||
assert.Equal(t, "ios", typeForPlatForm(core.PlatFormIos))
|
||||
assert.Equal(t, "android", typeForPlatForm(core.PlatFormAndroid))
|
||||
assert.Equal(t, "", typeForPlatForm(10000))
|
||||
}
|
||||
|
||||
func TestPlatFormColor(t *testing.T) {
|
||||
assert.Equal(t, blue, colorForPlatForm(core.PlatFormIos))
|
||||
assert.Equal(t, yellow, colorForPlatForm(core.PlatFormAndroid))
|
||||
assert.Equal(t, reset, colorForPlatForm(1000000))
|
||||
}
|
||||
|
||||
func TestHideToken(t *testing.T) {
|
||||
assert.Equal(t, "", hideToken("", 2))
|
||||
assert.Equal(t, "**345678**", hideToken("1234567890", 2))
|
||||
assert.Equal(t, "*****", hideToken("12345", 10))
|
||||
}
|
||||
Reference in New Issue
Block a user