mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-05-05 03:23:49 +08:00
local log hook
This commit is contained in:
parent
2156b6083b
commit
360f7188e1
152
global/log_hook.go
Normal file
152
global/log_hook.go
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
package global
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LocalHook struct {
|
||||||
|
lock *sync.Mutex
|
||||||
|
levels []logrus.Level // hook级别
|
||||||
|
formatter logrus.Formatter // 格式
|
||||||
|
path string // 写入path
|
||||||
|
writer io.Writer // io
|
||||||
|
}
|
||||||
|
|
||||||
|
// ref: logrus/hooks.go. impl Hook interface
|
||||||
|
func (hook *LocalHook) Levels() []logrus.Level {
|
||||||
|
if len(hook.levels) == 0 {
|
||||||
|
return logrus.AllLevels
|
||||||
|
}
|
||||||
|
return hook.levels
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *LocalHook) ioWrite(entry *logrus.Entry) error {
|
||||||
|
log, err := hook.formatter.Format(entry)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = hook.writer.Write(log)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *LocalHook) pathWrite(entry *logrus.Entry) error {
|
||||||
|
dir := filepath.Dir(hook.path)
|
||||||
|
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fd, err := os.OpenFile(hook.path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fd.Close()
|
||||||
|
|
||||||
|
log, err := hook.formatter.Format(entry)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = fd.Write(log)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *LocalHook) Fire(entry *logrus.Entry) error {
|
||||||
|
hook.lock.Lock()
|
||||||
|
defer hook.lock.Unlock()
|
||||||
|
|
||||||
|
if hook.writer != nil {
|
||||||
|
return hook.ioWrite(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
if hook.path != "" {
|
||||||
|
return hook.pathWrite(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *LocalHook) SetFormatter(formatter logrus.Formatter) {
|
||||||
|
hook.lock.Lock()
|
||||||
|
defer hook.lock.Unlock()
|
||||||
|
|
||||||
|
if formatter == nil {
|
||||||
|
// 用默认的
|
||||||
|
formatter = &logrus.TextFormatter{DisableColors: true}
|
||||||
|
} else {
|
||||||
|
switch formatter.(type) {
|
||||||
|
case *logrus.TextFormatter:
|
||||||
|
textFormatter := formatter.(*logrus.TextFormatter)
|
||||||
|
textFormatter.DisableColors = true
|
||||||
|
default:
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hook.formatter = formatter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *LocalHook) SetWriter(writer io.Writer) {
|
||||||
|
hook.lock.Lock()
|
||||||
|
defer hook.lock.Unlock()
|
||||||
|
hook.writer = writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hook *LocalHook) SetPath(path string) {
|
||||||
|
hook.lock.Lock()
|
||||||
|
defer hook.lock.Unlock()
|
||||||
|
hook.path = path
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLocalHook(args interface{}, formatter logrus.Formatter, levels ...logrus.Level) *LocalHook {
|
||||||
|
hook := &LocalHook{
|
||||||
|
lock: new(sync.Mutex),
|
||||||
|
}
|
||||||
|
hook.SetFormatter(formatter)
|
||||||
|
hook.levels = append(hook.levels, levels...)
|
||||||
|
|
||||||
|
switch args.(type) {
|
||||||
|
case string:
|
||||||
|
hook.SetPath(args.(string))
|
||||||
|
case io.Writer:
|
||||||
|
hook.SetWriter(args.(io.Writer))
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unsupported type: %v", reflect.TypeOf(args)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return hook
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLogLevel(level string) []logrus.Level {
|
||||||
|
switch level {
|
||||||
|
case "trace":
|
||||||
|
return []logrus.Level{logrus.TraceLevel, logrus.DebugLevel,
|
||||||
|
logrus.InfoLevel, logrus.WarnLevel, logrus.ErrorLevel,
|
||||||
|
logrus.FatalLevel, logrus.PanicLevel}
|
||||||
|
case "debug":
|
||||||
|
return []logrus.Level{logrus.DebugLevel, logrus.InfoLevel,
|
||||||
|
logrus.WarnLevel, logrus.ErrorLevel,
|
||||||
|
logrus.FatalLevel, logrus.PanicLevel}
|
||||||
|
case "info":
|
||||||
|
return []logrus.Level{logrus.InfoLevel, logrus.WarnLevel,
|
||||||
|
logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel}
|
||||||
|
case "warn":
|
||||||
|
return []logrus.Level{logrus.WarnLevel, logrus.ErrorLevel,
|
||||||
|
logrus.FatalLevel, logrus.PanicLevel}
|
||||||
|
case "error":
|
||||||
|
return []logrus.Level{logrus.ErrorLevel, logrus.FatalLevel,
|
||||||
|
logrus.PanicLevel}
|
||||||
|
default:
|
||||||
|
return logrus.AllLevels
|
||||||
|
}
|
||||||
|
}
|
195
main.go
195
main.go
@ -29,42 +29,14 @@ import (
|
|||||||
"github.com/Mrs4s/go-cqhttp/global"
|
"github.com/Mrs4s/go-cqhttp/global"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
|
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
|
||||||
"github.com/rifflock/lfshook"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
easy "github.com/t-tomalak/logrus-easy-formatter"
|
easy "github.com/t-tomalak/logrus-easy-formatter"
|
||||||
)
|
)
|
||||||
|
|
||||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
var conf *global.JsonConfig
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
log.SetFormatter(&easy.Formatter{
|
|
||||||
TimestampFormat: "2006-01-02 15:04:05",
|
|
||||||
LogFormat: "[%time%] [%lvl%]: %msg% \n",
|
|
||||||
})
|
|
||||||
w, err := rotatelogs.New(path.Join("logs", "%Y-%m-%d.log"), rotatelogs.WithRotationTime(time.Hour*24))
|
|
||||||
if err == nil {
|
|
||||||
log.SetOutput(io.MultiWriter(os.Stderr, w))
|
|
||||||
}
|
|
||||||
if !global.PathExists(global.IMAGE_PATH) {
|
|
||||||
if err := os.MkdirAll(global.IMAGE_PATH, 0755); err != nil {
|
|
||||||
log.Fatalf("创建图片缓存文件夹失败: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !global.PathExists(global.VOICE_PATH) {
|
|
||||||
if err := os.MkdirAll(global.VOICE_PATH, 0755); err != nil {
|
|
||||||
log.Fatalf("创建语音缓存文件夹失败: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !global.PathExists(global.VIDEO_PATH) {
|
|
||||||
if err := os.MkdirAll(global.VIDEO_PATH, 0755); err != nil {
|
|
||||||
log.Fatalf("创建视频缓存文件夹失败: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !global.PathExists(global.CACHE_PATH) {
|
|
||||||
if err := os.MkdirAll(global.CACHE_PATH, 0755); err != nil {
|
|
||||||
log.Fatalf("创建发送图片缓存文件夹失败: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if global.PathExists("cqhttp.json") {
|
if global.PathExists("cqhttp.json") {
|
||||||
log.Info("发现 cqhttp.json 将在五秒后尝试导入配置,按 Ctrl+C 取消.")
|
log.Info("发现 cqhttp.json 将在五秒后尝试导入配置,按 Ctrl+C 取消.")
|
||||||
log.Warn("警告: 该操作会删除 cqhttp.json 并覆盖 config.hjson 文件.")
|
log.Warn("警告: 该操作会删除 cqhttp.json 并覆盖 config.hjson 文件.")
|
||||||
@ -94,6 +66,44 @@ func init() {
|
|||||||
}
|
}
|
||||||
_ = os.Remove("cqhttp.json")
|
_ = os.Remove("cqhttp.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conf = getConfig()
|
||||||
|
if conf == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logFormatter := &easy.Formatter{
|
||||||
|
TimestampFormat: "2006-01-02 15:04:05",
|
||||||
|
LogFormat: "[%time%] [%lvl%]: %msg% \n",
|
||||||
|
}
|
||||||
|
w, err := rotatelogs.New(path.Join("logs", "%Y-%m-%d.log"), rotatelogs.WithRotationTime(time.Hour*24))
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("rotatelogs init err: %v", err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.AddHook(global.NewLocalHook(w, logFormatter, global.GetLogLevel(conf.LogLevel)...))
|
||||||
|
|
||||||
|
if !global.PathExists(global.IMAGE_PATH) {
|
||||||
|
if err := os.MkdirAll(global.IMAGE_PATH, 0755); err != nil {
|
||||||
|
log.Fatalf("创建图片缓存文件夹失败: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !global.PathExists(global.VOICE_PATH) {
|
||||||
|
if err := os.MkdirAll(global.VOICE_PATH, 0755); err != nil {
|
||||||
|
log.Fatalf("创建语音缓存文件夹失败: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !global.PathExists(global.VIDEO_PATH) {
|
||||||
|
if err := os.MkdirAll(global.VIDEO_PATH, 0755); err != nil {
|
||||||
|
log.Fatalf("创建视频缓存文件夹失败: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !global.PathExists(global.CACHE_PATH) {
|
||||||
|
if err := os.MkdirAll(global.CACHE_PATH, 0755); err != nil {
|
||||||
|
log.Fatalf("创建发送图片缓存文件夹失败: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -120,93 +130,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var conf *global.JsonConfig
|
|
||||||
if global.PathExists("config.json") {
|
|
||||||
conf = global.Load("config.json")
|
|
||||||
_ = conf.Save("config.hjson")
|
|
||||||
_ = os.Remove("config.json")
|
|
||||||
} else if os.Getenv("UIN") != "" {
|
|
||||||
log.Infof("将从环境变量加载配置.")
|
|
||||||
uin, _ := strconv.ParseInt(os.Getenv("UIN"), 10, 64)
|
|
||||||
pwd := os.Getenv("PASS")
|
|
||||||
post := os.Getenv("HTTP_POST")
|
|
||||||
conf = &global.JsonConfig{
|
|
||||||
Uin: uin,
|
|
||||||
Password: pwd,
|
|
||||||
HttpConfig: &global.GoCQHttpConfig{
|
|
||||||
Enabled: true,
|
|
||||||
Host: "0.0.0.0",
|
|
||||||
Port: 5700,
|
|
||||||
PostUrls: map[string]string{},
|
|
||||||
},
|
|
||||||
WSConfig: &global.GoCQWebsocketConfig{
|
|
||||||
Enabled: true,
|
|
||||||
Host: "0.0.0.0",
|
|
||||||
Port: 6700,
|
|
||||||
},
|
|
||||||
PostMessageFormat: "string",
|
|
||||||
Debug: os.Getenv("DEBUG") == "true",
|
|
||||||
}
|
|
||||||
if post != "" {
|
|
||||||
conf.HttpConfig.PostUrls[post] = os.Getenv("HTTP_SECRET")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
conf = global.Load("config.hjson")
|
|
||||||
}
|
|
||||||
if conf == nil {
|
|
||||||
err := global.WriteAllText("config.hjson", global.DefaultConfigWithComments)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("创建默认配置文件时出现错误: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Infof("默认配置文件已生成, 请编辑 config.hjson 后重启程序.")
|
|
||||||
time.Sleep(time.Second * 5)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if conf.Uin == 0 || (conf.Password == "" && conf.PasswordEncrypted == "") {
|
if conf.Uin == 0 || (conf.Password == "" && conf.PasswordEncrypted == "") {
|
||||||
log.Warnf("请修改 config.hjson 以添加账号密码.")
|
log.Warnf("请修改 config.hjson 以添加账号密码.")
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// log classified by level
|
|
||||||
// Collect all records up to the specified level (default level: warn)
|
|
||||||
logLevel := conf.LogLevel
|
|
||||||
if logLevel != "" {
|
|
||||||
date := time.Now().Format("2006-01-02")
|
|
||||||
var logPathMap lfshook.PathMap
|
|
||||||
switch conf.LogLevel {
|
|
||||||
case "warn":
|
|
||||||
logPathMap = lfshook.PathMap{
|
|
||||||
log.WarnLevel: path.Join("logs", date+"-warn.log"),
|
|
||||||
log.ErrorLevel: path.Join("logs", date+"-warn.log"),
|
|
||||||
log.FatalLevel: path.Join("logs", date+"-warn.log"),
|
|
||||||
log.PanicLevel: path.Join("logs", date+"-warn.log"),
|
|
||||||
}
|
|
||||||
case "error":
|
|
||||||
logPathMap = lfshook.PathMap{
|
|
||||||
log.ErrorLevel: path.Join("logs", date+"-error.log"),
|
|
||||||
log.FatalLevel: path.Join("logs", date+"-error.log"),
|
|
||||||
log.PanicLevel: path.Join("logs", date+"-error.log"),
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
logPathMap = lfshook.PathMap{
|
|
||||||
log.WarnLevel: path.Join("logs", date+"-warn.log"),
|
|
||||||
log.ErrorLevel: path.Join("logs", date+"-warn.log"),
|
|
||||||
log.FatalLevel: path.Join("logs", date+"-warn.log"),
|
|
||||||
log.PanicLevel: path.Join("logs", date+"-warn.log"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.AddHook(lfshook.NewHook(
|
|
||||||
logPathMap,
|
|
||||||
&easy.Formatter{
|
|
||||||
TimestampFormat: "2006-01-02 15:04:05",
|
|
||||||
LogFormat: "[%time%] [%lvl%]: %msg% \n",
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info("当前版本:", coolq.Version)
|
log.Info("当前版本:", coolq.Version)
|
||||||
if conf.Debug {
|
if conf.Debug {
|
||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
@ -487,3 +416,49 @@ func restart(Args []string) {
|
|||||||
}
|
}
|
||||||
cmd.Start()
|
cmd.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getConfig() *global.JsonConfig {
|
||||||
|
if global.PathExists("config.json") {
|
||||||
|
conf = global.Load("config.json")
|
||||||
|
_ = conf.Save("config.hjson")
|
||||||
|
_ = os.Remove("config.json")
|
||||||
|
} else if os.Getenv("UIN") != "" {
|
||||||
|
log.Infof("将从环境变量加载配置.")
|
||||||
|
uin, _ := strconv.ParseInt(os.Getenv("UIN"), 10, 64)
|
||||||
|
pwd := os.Getenv("PASS")
|
||||||
|
post := os.Getenv("HTTP_POST")
|
||||||
|
conf = &global.JsonConfig{
|
||||||
|
Uin: uin,
|
||||||
|
Password: pwd,
|
||||||
|
HttpConfig: &global.GoCQHttpConfig{
|
||||||
|
Enabled: true,
|
||||||
|
Host: "0.0.0.0",
|
||||||
|
Port: 5700,
|
||||||
|
PostUrls: map[string]string{},
|
||||||
|
},
|
||||||
|
WSConfig: &global.GoCQWebsocketConfig{
|
||||||
|
Enabled: true,
|
||||||
|
Host: "0.0.0.0",
|
||||||
|
Port: 6700,
|
||||||
|
},
|
||||||
|
PostMessageFormat: "string",
|
||||||
|
Debug: os.Getenv("DEBUG") == "true",
|
||||||
|
}
|
||||||
|
if post != "" {
|
||||||
|
conf.HttpConfig.PostUrls[post] = os.Getenv("HTTP_SECRET")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
conf = global.Load("config.hjson")
|
||||||
|
}
|
||||||
|
if conf == nil {
|
||||||
|
err := global.WriteAllText("config.hjson", global.DefaultConfigWithComments)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("创建默认配置文件时出现错误: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Infof("默认配置文件已生成, 请编辑 config.hjson 后重启程序.")
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return conf
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user