feat(log): 实现带颜色的日志输出功能

- 添加了 ANSI 颜色代码常量定义
- 创建了正则表达式用于去除颜色码
- 实现了自定义 logWriter 结构体用于分离控制台和文件输出
- 控制台输出保留颜色,文件输出自动去除颜色码
- 更新了日志格式包含时间戳和颜色标识
- 修改了 Info、Error、Warn、Debug 函数的前缀格式
main v1.0.1015
black1552 2026-03-06 10:18:31 +08:00
parent de8348e424
commit 5affb5e653
2 changed files with 67 additions and 124 deletions

View File

@ -101,13 +101,6 @@
</set>
</value>
</entry>
<entry key="News">
<value>
<set>
<option value="file://$PROJECT_DIR$/../gin_test/model/news.go" />
</set>
</value>
</entry>
<entry key="Paginate">
<value>
<set>
@ -157,10 +150,11 @@
</set>
</value>
</entry>
<entry key="User">
<entry key="logWriter">
<value>
<set>
<option value="file://$PROJECT_DIR$/../gin_test/model/user.go" />
<option value="file://$PROJECT_DIR$/log/log.go" />
<option value="file://$PROJECT_DIR$/../yingji/api-gateway/internal/utils/log.go" />
</set>
</value>
</entry>
@ -178,34 +172,6 @@
</set>
</value>
</entry>
<entry key="sNewsDao">
<value>
<set>
<option value="file://$PROJECT_DIR$/../gin_test/model/dao/newsDao.go" />
</set>
</value>
</entry>
<entry key="sNewsDb">
<value>
<set>
<option value="file://$PROJECT_DIR$/../gin_test/service/news.go" />
</set>
</value>
</entry>
<entry key="sUser">
<value>
<set>
<option value="file://$PROJECT_DIR$/../gin_test/service/user.go" />
</set>
</value>
</entry>
<entry key="sUserDao">
<value>
<set>
<option value="file://$PROJECT_DIR$/../gin_test/model/dao/userDao.go" />
</set>
</value>
</entry>
</map>
</option>
<option name="scannedPathMapping">
@ -283,7 +249,12 @@
<entry key="file://$PROJECT_DIR$/log/log.go">
<value>
<ScannedPath>
<option name="lastModified" value="1772420020488" />
<option name="lastModified" value="1772763464061" />
<option name="schema">
<list>
<option value="logWriter" />
</list>
</option>
</ScannedPath>
</value>
</entry>
@ -462,87 +433,20 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/../gin_test/controller/home/index.go">
<entry key="file://$PROJECT_DIR$/../yingji/api-gateway/internal/cmd/cmd.go">
<value>
<ScannedPath>
<option name="lastModified" value="1772608689818" />
<option name="lastModified" value="1772762475609" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/../gin_test/migrate/migrate.go">
<entry key="file://$PROJECT_DIR$/../yingji/api-gateway/internal/utils/log.go">
<value>
<ScannedPath>
<option name="lastModified" value="1772607808155" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/../gin_test/model/dao/newsDao.go">
<value>
<ScannedPath>
<option name="lastModified" value="1772605092268" />
<option name="lastModified" value="1772763430097" />
<option name="schema">
<list>
<option value="sNewsDao" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/../gin_test/model/dao/userDao.go">
<value>
<ScannedPath>
<option name="lastModified" value="1772605102821" />
<option name="schema">
<list>
<option value="sUserDao" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/../gin_test/model/news.go">
<value>
<ScannedPath>
<option name="lastModified" value="1772607773437" />
<option name="schema">
<list>
<option value="News" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/../gin_test/model/user.go">
<value>
<ScannedPath>
<option name="lastModified" value="1772606080031" />
<option name="schema">
<list>
<option value="User" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/../gin_test/service/news.go">
<value>
<ScannedPath>
<option name="lastModified" value="1772593137875" />
<option name="schema">
<list>
<option value="sNewsDb" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/../gin_test/service/user.go">
<value>
<ScannedPath>
<option name="lastModified" value="1772593163860" />
<option name="schema">
<list>
<option value="sUser" />
<option value="logWriter" />
</list>
</option>
</ScannedPath>
@ -564,25 +468,20 @@
<entry key="data_base_config" value="DataBaseConfig" />
<entry key="jwt_claims" value="JWTClaims" />
<entry key="jwt_config" value="JwtConfig" />
<entry key="log_writer" value="logWriter" />
<entry key="manager" value="Manager" />
<entry key="msg" value="Msg" />
<entry key="news" value="News" />
<entry key="paginate" value="Paginate" />
<entry key="res_file" value="resFile" />
<entry key="response" value="response" />
<entry key="s_news_dao" value="sNewsDao" />
<entry key="s_news_db" value="sNewsDb" />
<entry key="s_user" value="sUser" />
<entry key="s_user_dao" value="sUserDao" />
<entry key="server_config" value="ServerConfig" />
<entry key="sq_lite_pool" value="SQLitePool" />
<entry key="tcp_connection" value="TcpConnection" />
<entry key="tcp_message" value="TcpMessage" />
<entry key="tcp_pool_config" value="TcpPoolConfig" />
<entry key="tcp_server" value="TCPServer" />
<entry key="user" value="User" />
</map>
</option>
<option name="lastTimeChecked" value="1772592078880" />
<option name="lastTimeChecked" value="1772761874263" />
</component>
</project>

View File

@ -5,8 +5,10 @@ import (
"io"
"log"
"os"
"regexp"
"runtime/debug"
"strings"
"time"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gtime"
@ -18,6 +20,45 @@ var (
sysLog *log.Logger
)
const (
Reset = "\033[0m"
Red = "\033[31m"
Green = "\033[32m"
Yellow = "\033[33m"
Blue = "\033[34m"
Purple = "\033[35m"
Cyan = "\033[36m"
)
// 正则表达式匹配 ANSI 颜色码
var ansiColorRegex = regexp.MustCompile(`\x1b\[[0-9;]*m`)
// stripAnsiColors 去除字符串中的 ANSI 颜色码
func stripAnsiColors(s string) string {
return ansiColorRegex.ReplaceAllString(s, "")
}
// logWriter 自定义 writer用于分别处理控制台和文件输出
type logWriter struct {
console io.Writer
file io.Writer
}
func (w *logWriter) Write(p []byte) (n int, err error) {
// 控制台输出保留颜色
_, err = w.console.Write(p)
if err != nil {
return 0, err
}
// 文件输出去除颜色码
colorless := stripAnsiColors(string(p))
_, err = w.file.Write([]byte(colorless))
if err != nil {
return 0, err
}
return len(p), nil
}
func init() {
logPath = gfile.Join(gfile.Pwd(), "logs")
filePath := gfile.Join(logPath, fmt.Sprintf("log-%s.log", gtime.Date()))
@ -28,25 +69,28 @@ func init() {
MaxAge: 30, // 保留 30 天
Compress: false, // 启用压缩
}
// 创建 MultiWriter 实现同时输出到文件和终端
multiWriter := io.MultiWriter(fileLogger, os.Stdout)
sysLog = log.New(multiWriter, "", log.LstdFlags)
// 使用自定义 writer 实现控制台带颜色、文件无颜色的输出
multiWriter := &logWriter{
console: os.Stdout,
file: fileLogger,
}
sysLog = log.New(multiWriter, "", 0)
}
func Info(v ...any) {
sysLog.SetPrefix("[INFO] ")
sysLog.SetPrefix(fmt.Sprintf("[%s] %s[INFO]%s ", time.Now().Format("2006-01-02 15:04:05"), Green, Reset))
sysLog.Println(fmt.Sprint(v...))
}
func Error(v ...any) {
sysLog.SetPrefix("[ERROR] ")
sysLog.SetPrefix(fmt.Sprintf("[%s] %s[ERROR]%s ", time.Now().Format("2006-01-02 15:04:05"), Red, Reset))
msg := fmt.Sprint(v...)
sysLog.Println(msg, strings.TrimSpace(string(debug.Stack())))
}
func Warn(v ...any) {
sysLog.SetPrefix("[WARN] ")
sysLog.SetPrefix(fmt.Sprintf("[%s] %s[WARN]%s ", time.Now().Format("2006-01-02 15:04:05"), Yellow, Reset))
sysLog.Println(fmt.Sprint(v...))
}
func Debug(v ...any) {
sysLog.SetPrefix("[DEBUG] ")
sysLog.SetPrefix(fmt.Sprintf("[%s] %s[DEBUG]%s ", time.Now().Format("2006-01-02 15:04:05"), Blue, Reset))
sysLog.Println(fmt.Sprint(v...))
}