mirror of
https://github.com/fatedier/frp.git
synced 2026-03-21 01:09:27 +08:00
feat(client): add access messages for proxy services
feat(client): translate log messages to Chinese feat(cmd): add authentication token support for API config feat(log): implement rotating file logger with custom styles feat(banner): add banner display function fix(version): update version string for CLI
This commit is contained in:
12
pkg/util/banner/banner.go
Normal file
12
pkg/util/banner/banner.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package banner
|
||||
|
||||
import "fmt"
|
||||
|
||||
func DisplayBanner() {
|
||||
fmt.Println(" __ ___ __________ ____ ________ ____")
|
||||
fmt.Println(" / / ____ / (_)___ _/ ____/ __ \\/ __ \\ / ____/ / / _/")
|
||||
fmt.Println(" / / / __ \\/ / / __ `/ /_ / /_/ / /_/ /_____/ / / / / / ")
|
||||
fmt.Println(" / /___/ /_/ / / / /_/ / __/ / _, _/ ____/_____/ /___/ /____/ / ")
|
||||
fmt.Println("/_____/\\____/_/_/\\__,_/_/ /_/ |_/_/ \\____/_____/___/ ")
|
||||
fmt.Println(" ")
|
||||
}
|
||||
@@ -16,13 +16,18 @@ package log
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/log"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/charmbracelet/log"
|
||||
)
|
||||
|
||||
var (
|
||||
TraceLevel = log.TraceLevel
|
||||
TraceLevel = log.DebugLevel
|
||||
DebugLevel = log.DebugLevel
|
||||
InfoLevel = log.InfoLevel
|
||||
WarnLevel = log.WarnLevel
|
||||
@@ -32,39 +37,156 @@ var (
|
||||
var Logger *log.Logger
|
||||
|
||||
func init() {
|
||||
Logger = log.New(
|
||||
log.WithCaller(true),
|
||||
log.AddCallerSkip(1),
|
||||
log.WithLevel(log.InfoLevel),
|
||||
)
|
||||
Logger = log.NewWithOptions(os.Stderr, log.Options{
|
||||
ReportCaller: true,
|
||||
ReportTimestamp: true,
|
||||
TimeFormat: time.Kitchen,
|
||||
Prefix: "LoliaFRP-CLI",
|
||||
CallerOffset: 1,
|
||||
})
|
||||
// 设置自定义样式以支持 Trace 级别
|
||||
styles := log.DefaultStyles()
|
||||
styles.Levels[TraceLevel] = lipgloss.NewStyle().
|
||||
SetString("TRACE").
|
||||
Bold(true).
|
||||
MaxWidth(5).
|
||||
Foreground(lipgloss.Color("61"))
|
||||
Logger.SetStyles(styles)
|
||||
}
|
||||
|
||||
func InitLogger(logPath string, levelStr string, maxDays int, disableLogColor bool) {
|
||||
options := []log.Option{}
|
||||
var output io.Writer
|
||||
var err error
|
||||
|
||||
if logPath == "console" {
|
||||
if !disableLogColor {
|
||||
options = append(options,
|
||||
log.WithOutput(log.NewConsoleWriter(log.ConsoleConfig{
|
||||
Colorful: true,
|
||||
}, os.Stdout)),
|
||||
)
|
||||
}
|
||||
output = os.Stdout
|
||||
} else {
|
||||
writer := log.NewRotateFileWriter(log.RotateFileConfig{
|
||||
FileName: logPath,
|
||||
Mode: log.RotateFileModeDaily,
|
||||
MaxDays: maxDays,
|
||||
})
|
||||
writer.Init()
|
||||
options = append(options, log.WithOutput(writer))
|
||||
// Use rotating file writer
|
||||
output, err = NewRotateFileWriter(logPath, maxDays)
|
||||
if err != nil {
|
||||
// Fallback to console if file creation fails
|
||||
output = os.Stdout
|
||||
}
|
||||
}
|
||||
|
||||
level, err := log.ParseLevel(levelStr)
|
||||
if err != nil {
|
||||
level = log.InfoLevel
|
||||
}
|
||||
options = append(options, log.WithLevel(level))
|
||||
Logger = Logger.WithOptions(options...)
|
||||
|
||||
Logger = log.NewWithOptions(output, log.Options{
|
||||
ReportCaller: true,
|
||||
ReportTimestamp: true,
|
||||
TimeFormat: time.Kitchen,
|
||||
Prefix: "LoliaFRP-CLI",
|
||||
CallerOffset: 1,
|
||||
Level: level,
|
||||
})
|
||||
}
|
||||
|
||||
// NewRotateFileWriter creates a rotating file writer
|
||||
func NewRotateFileWriter(filePath string, maxDays int) (*RotateFileWriter, error) {
|
||||
w := &RotateFileWriter{
|
||||
filePath: filePath,
|
||||
maxDays: maxDays,
|
||||
lastRotate: time.Now(),
|
||||
currentDate: time.Now().Format("2006-01-02"),
|
||||
}
|
||||
|
||||
if err := w.openFile(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return w, nil
|
||||
}
|
||||
|
||||
// RotateFileWriter implements io.Writer with daily rotation
|
||||
type RotateFileWriter struct {
|
||||
filePath string
|
||||
maxDays int
|
||||
file *os.File
|
||||
lastRotate time.Time
|
||||
currentDate string
|
||||
}
|
||||
|
||||
func (w *RotateFileWriter) openFile() error {
|
||||
var err error
|
||||
w.file, err = os.OpenFile(w.filePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *RotateFileWriter) checkRotate() error {
|
||||
now := time.Now()
|
||||
currentDate := now.Format("2006-01-02")
|
||||
|
||||
if currentDate != w.currentDate {
|
||||
// Close current file
|
||||
if w.file != nil {
|
||||
w.file.Close()
|
||||
}
|
||||
|
||||
// Rename current file with date suffix
|
||||
oldPath := w.filePath
|
||||
newPath := w.filePath + "." + w.currentDate
|
||||
if _, err := os.Stat(oldPath); err == nil {
|
||||
os.Rename(oldPath, newPath)
|
||||
}
|
||||
|
||||
// Clean up old log files
|
||||
w.cleanupOldLogs(now)
|
||||
|
||||
// Update current date and open new file
|
||||
w.currentDate = currentDate
|
||||
w.lastRotate = now
|
||||
return w.openFile()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *RotateFileWriter) cleanupOldLogs(now time.Time) {
|
||||
if w.maxDays <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
cutoffDate := now.AddDate(0, 0, -w.maxDays)
|
||||
|
||||
// Find and remove old log files
|
||||
dir := filepath.Dir(w.filePath)
|
||||
base := filepath.Base(w.filePath)
|
||||
|
||||
files, _ := os.ReadDir(dir)
|
||||
for _, f := range files {
|
||||
if f.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
name := f.Name()
|
||||
if strings.HasPrefix(name, base+".") {
|
||||
// Extract date from filename (base.YYYY-MM-DD)
|
||||
dateStr := strings.TrimPrefix(name, base+".")
|
||||
if len(dateStr) == 10 {
|
||||
fileDate, err := time.Parse("2006-01-02", dateStr)
|
||||
if err == nil && fileDate.Before(cutoffDate) {
|
||||
os.Remove(filepath.Join(dir, name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *RotateFileWriter) Write(p []byte) (n int, err error) {
|
||||
if err := w.checkRotate(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return w.file.Write(p)
|
||||
}
|
||||
|
||||
func (w *RotateFileWriter) Close() error {
|
||||
if w.file != nil {
|
||||
return w.file.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Errorf(format string, v ...any) {
|
||||
@@ -75,6 +197,10 @@ func Warnf(format string, v ...any) {
|
||||
Logger.Warnf(format, v...)
|
||||
}
|
||||
|
||||
func Info(format string, v ...any) {
|
||||
Logger.Info(format, v...)
|
||||
}
|
||||
|
||||
func Infof(format string, v ...any) {
|
||||
Logger.Infof(format, v...)
|
||||
}
|
||||
@@ -84,11 +210,12 @@ func Debugf(format string, v ...any) {
|
||||
}
|
||||
|
||||
func Tracef(format string, v ...any) {
|
||||
Logger.Tracef(format, v...)
|
||||
Logger.Logf(TraceLevel, format, v...)
|
||||
}
|
||||
|
||||
func Logf(level log.Level, offset int, format string, v ...any) {
|
||||
Logger.Logf(level, offset, format, v...)
|
||||
// charmbracelet/log doesn't support offset, so we ignore it
|
||||
Logger.Logf(level, format, v...)
|
||||
}
|
||||
|
||||
type WriteLogger struct {
|
||||
@@ -104,6 +231,8 @@ func NewWriteLogger(level log.Level, offset int) *WriteLogger {
|
||||
}
|
||||
|
||||
func (w *WriteLogger) Write(p []byte) (n int, err error) {
|
||||
Logger.Log(w.level, w.offset, string(bytes.TrimRight(p, "\n")))
|
||||
// charmbracelet/log doesn't support offset in Log
|
||||
msg := string(bytes.TrimRight(p, "\n"))
|
||||
Logger.Log(w.level, msg)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package version
|
||||
|
||||
var version = "LoliaFRP 0.66.0"
|
||||
var version = "LoliaFRP-CLI 0.66.0"
|
||||
|
||||
func Full() string {
|
||||
return version
|
||||
|
||||
@@ -111,5 +111,5 @@ func (l *Logger) Debugf(format string, v ...any) {
|
||||
}
|
||||
|
||||
func (l *Logger) Tracef(format string, v ...any) {
|
||||
log.Logger.Tracef(l.prefixString+format, v...)
|
||||
log.Logger.Logf(log.TraceLevel, l.prefixString+format, v...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user