zhangshu
10 months ago
10 changed files with 361 additions and 12 deletions
@ -0,0 +1,214 @@ |
|||||
|
package utils |
||||
|
|
||||
|
import ( |
||||
|
"bytes" |
||||
|
"fmt" |
||||
|
"io" |
||||
|
"os" |
||||
|
"path" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/gin-gonic/gin" |
||||
|
rotatelogs "github.com/lestrrat-go/file-rotatelogs" |
||||
|
"github.com/logrusorgru/aurora" |
||||
|
"github.com/rifflock/lfshook" |
||||
|
"github.com/sirupsen/logrus" |
||||
|
) |
||||
|
|
||||
|
var Logger *logrus.Logger |
||||
|
var isInit bool |
||||
|
|
||||
|
func CheckInitLog() bool { |
||||
|
return isInit |
||||
|
} |
||||
|
func init() { |
||||
|
isInit = false |
||||
|
} |
||||
|
|
||||
|
const ( |
||||
|
maxAgeHour = 168 |
||||
|
rotationHour = 24 |
||||
|
) |
||||
|
|
||||
|
type SaveFormatter struct { |
||||
|
} |
||||
|
|
||||
|
func (m *SaveFormatter) Format(entry *logrus.Entry) ([]byte, error) { |
||||
|
var b *bytes.Buffer |
||||
|
if entry.Buffer != nil { |
||||
|
b = entry.Buffer |
||||
|
} else { |
||||
|
b = &bytes.Buffer{} |
||||
|
} |
||||
|
timestamp := entry.Time.Format("2006-01-02 15:04:05") |
||||
|
var newLog string |
||||
|
newLog = fmt.Sprintf("[%s] [%s:%d] [%s] %s \n", timestamp, path.Base(entry.Caller.File), entry.Caller.Line, entry.Level, entry.Message) |
||||
|
b.WriteString(newLog) |
||||
|
return b.Bytes(), nil |
||||
|
} |
||||
|
|
||||
|
type ConsoleFormatter struct { |
||||
|
} |
||||
|
|
||||
|
func (m *ConsoleFormatter) Format(entry *logrus.Entry) ([]byte, error) { |
||||
|
var b *bytes.Buffer |
||||
|
if entry.Buffer != nil { |
||||
|
b = entry.Buffer |
||||
|
} else { |
||||
|
b = &bytes.Buffer{} |
||||
|
} |
||||
|
timestamp := entry.Time.Format("2006-01-02 15:04:05") |
||||
|
var newLog string |
||||
|
var levelString aurora.Value |
||||
|
switch entry.Level.String() { |
||||
|
case "info": |
||||
|
levelString = aurora.Green(entry.Level) |
||||
|
case "warning": |
||||
|
levelString = aurora.Yellow(entry.Level) |
||||
|
case "debug": |
||||
|
levelString = aurora.Gray(16-1, entry.Level) |
||||
|
case "error": |
||||
|
levelString = aurora.Red(entry.Level) |
||||
|
case "fatal": |
||||
|
levelString = aurora.Red(entry.Level) |
||||
|
case "panic": |
||||
|
levelString = aurora.Red(entry.Level) |
||||
|
} |
||||
|
newLog = fmt.Sprintf("[%s] [%s:%d] [%s] %s \n", timestamp, path.Base(entry.Caller.File), entry.Caller.Line, levelString, entry.Message) |
||||
|
b.WriteString(newLog) |
||||
|
return b.Bytes(), nil |
||||
|
} |
||||
|
|
||||
|
func InitLogger(env string, logPath string) *logrus.Logger { |
||||
|
logFilePath := "" |
||||
|
errFilePath := "" |
||||
|
if dir, err := os.Getwd(); err == nil { |
||||
|
logFilePath = dir + "/logs/" + logPath + "/all.log" |
||||
|
errFilePath = dir + "/logs/" + logPath + "/error.log" |
||||
|
} |
||||
|
|
||||
|
accessWriter, err := rotatelogs.New( |
||||
|
logFilePath+".%Y-%m-%d", |
||||
|
rotatelogs.WithLinkName(logFilePath), |
||||
|
rotatelogs.WithRotationTime(time.Hour*rotationHour), |
||||
|
rotatelogs.WithMaxAge(time.Hour*maxAgeHour), |
||||
|
) |
||||
|
if err != nil { |
||||
|
panic(err) |
||||
|
} |
||||
|
errorWriter, err := rotatelogs.New( |
||||
|
errFilePath+".%Y-%m-%d", |
||||
|
rotatelogs.WithLinkName(errFilePath), |
||||
|
rotatelogs.WithRotationTime(time.Hour*rotationHour), |
||||
|
rotatelogs.WithMaxAge(time.Hour*maxAgeHour), |
||||
|
) |
||||
|
if err != nil { |
||||
|
panic(err) |
||||
|
} |
||||
|
allWriter := io.MultiWriter(accessWriter, errorWriter) |
||||
|
//实例化
|
||||
|
logger := logrus.New() |
||||
|
logger.Out = os.Stdout |
||||
|
//设置日志格式
|
||||
|
logger.SetFormatter(&ConsoleFormatter{}) |
||||
|
logger.SetReportCaller(true) |
||||
|
//设置输出
|
||||
|
if env != "dev" { |
||||
|
logger.AddHook(lfshook.NewHook( |
||||
|
lfshook.WriterMap{ |
||||
|
logrus.DebugLevel: accessWriter, |
||||
|
logrus.InfoLevel: accessWriter, |
||||
|
logrus.ErrorLevel: allWriter, |
||||
|
logrus.PanicLevel: allWriter, |
||||
|
}, |
||||
|
&SaveFormatter{}, |
||||
|
)) |
||||
|
} |
||||
|
//设置日志级别
|
||||
|
logger.SetLevel(logrus.DebugLevel) |
||||
|
Logger = logger |
||||
|
isInit = true |
||||
|
return logger |
||||
|
} |
||||
|
|
||||
|
func InitReqLogger(env string, logPath string) *logrus.Logger { |
||||
|
logFilePath := "" |
||||
|
errFilePath := "" |
||||
|
if dir, err := os.Getwd(); err == nil { |
||||
|
logFilePath = dir + "/logs/" + logPath + "/req.log" |
||||
|
errFilePath = dir + "/logs/" + logPath + "/req-error.log" |
||||
|
} |
||||
|
|
||||
|
accessWriter, err := rotatelogs.New( |
||||
|
logFilePath+".%Y-%m-%d", |
||||
|
rotatelogs.WithLinkName(logFilePath), |
||||
|
rotatelogs.WithRotationTime(time.Hour*rotationHour), |
||||
|
rotatelogs.WithMaxAge(time.Hour*maxAgeHour), |
||||
|
) |
||||
|
if err != nil { |
||||
|
panic(err) |
||||
|
} |
||||
|
errorWriter, err := rotatelogs.New( |
||||
|
errFilePath+".%Y-%m-%d", |
||||
|
rotatelogs.WithLinkName(errFilePath), |
||||
|
rotatelogs.WithRotationTime(time.Hour*rotationHour), |
||||
|
rotatelogs.WithMaxAge(time.Hour*maxAgeHour), |
||||
|
) |
||||
|
if err != nil { |
||||
|
panic(err) |
||||
|
} |
||||
|
allWriter := io.MultiWriter(accessWriter, errorWriter) |
||||
|
//实例化
|
||||
|
logger := logrus.New() |
||||
|
logger.Out = os.Stdout |
||||
|
//设置日志格式
|
||||
|
logger.SetFormatter(&ConsoleFormatter{}) |
||||
|
logger.SetReportCaller(true) |
||||
|
//设置输出
|
||||
|
if env != "dev" { |
||||
|
logger.AddHook(lfshook.NewHook( |
||||
|
lfshook.WriterMap{ |
||||
|
logrus.DebugLevel: accessWriter, |
||||
|
logrus.InfoLevel: accessWriter, |
||||
|
logrus.ErrorLevel: allWriter, |
||||
|
logrus.PanicLevel: allWriter, |
||||
|
}, |
||||
|
&SaveFormatter{}, |
||||
|
)) |
||||
|
} |
||||
|
//设置日志级别
|
||||
|
logger.SetLevel(logrus.DebugLevel) |
||||
|
Logger = logger |
||||
|
isInit = true |
||||
|
return logger |
||||
|
} |
||||
|
|
||||
|
func LoggerToFile(env string, logPath string) gin.HandlerFunc { |
||||
|
logger := InitReqLogger(env, logPath) |
||||
|
return func(c *gin.Context) { |
||||
|
// 开始时间
|
||||
|
startTime := time.Now() |
||||
|
// 处理请求
|
||||
|
c.Next() |
||||
|
// 结束时间
|
||||
|
endTime := time.Now() |
||||
|
// 执行时间
|
||||
|
latencyTime := endTime.Sub(startTime) |
||||
|
// 请求方式
|
||||
|
reqMethod := c.Request.Method |
||||
|
// 请求路由
|
||||
|
reqUri := c.Request.RequestURI |
||||
|
// 状态码
|
||||
|
statusCode := c.Writer.Status() |
||||
|
// 请求IP
|
||||
|
clientIP := c.ClientIP() |
||||
|
//日志格式
|
||||
|
logger.Infof("|%3d|%13v|%15s|%s|%s|", |
||||
|
statusCode, |
||||
|
latencyTime, |
||||
|
clientIP, |
||||
|
reqMethod, |
||||
|
reqUri, |
||||
|
) |
||||
|
} |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
server: |
||||
|
ip: 127.0.0.1 |
||||
|
port: 9999 |
||||
|
log: |
||||
|
logenv: test |
||||
|
logpath: server |
@ -0,0 +1,16 @@ |
|||||
|
package config |
||||
|
|
||||
|
type EnvConfig struct { |
||||
|
Server ServerEntity |
||||
|
Log LogEntity |
||||
|
} |
||||
|
|
||||
|
type ServerEntity struct { |
||||
|
Ip string |
||||
|
Port int |
||||
|
} |
||||
|
|
||||
|
type LogEntity struct { |
||||
|
LogEnv string |
||||
|
LogPath string |
||||
|
} |
@ -0,0 +1,34 @@ |
|||||
|
package config |
||||
|
|
||||
|
import ( |
||||
|
"flag" |
||||
|
"fmt" |
||||
|
"io/ioutil" |
||||
|
|
||||
|
utils "youtube_collection_server/Utils" |
||||
|
|
||||
|
"github.com/sirupsen/logrus" |
||||
|
"gopkg.in/yaml.v2" |
||||
|
) |
||||
|
|
||||
|
var configFile string |
||||
|
var MyEnv EnvConfig |
||||
|
var Logger *logrus.Logger |
||||
|
|
||||
|
func init() { |
||||
|
flag.StringVar(&configFile, "cf", "config.yml", "配置文件名") |
||||
|
} |
||||
|
|
||||
|
func InitConfig() { |
||||
|
flag.Parse() |
||||
|
//读取配置文件
|
||||
|
data, _ := ioutil.ReadFile(configFile) |
||||
|
err := yaml.Unmarshal(data, &MyEnv) |
||||
|
if err != nil { |
||||
|
fmt.Println("读取配置文件错误...") |
||||
|
return |
||||
|
} |
||||
|
//初始化日志
|
||||
|
Logger = utils.InitLogger(MyEnv.Log.LogEnv, MyEnv.Log.LogPath) |
||||
|
Logger.Info("初始化Logger成功...") |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
package controller |
||||
|
|
||||
|
import "github.com/gin-gonic/gin" |
||||
|
|
||||
|
type userController struct { |
||||
|
} |
||||
|
|
||||
|
var UserController userController |
||||
|
|
||||
|
func (m *userController) Test(c *gin.Context) { |
||||
|
c.JSON(200, gin.H{ |
||||
|
"username": "name1", |
||||
|
"data": "data1", |
||||
|
}) |
||||
|
} |
@ -1,20 +1,34 @@ |
|||||
package main |
package main |
||||
|
|
||||
import ( |
import ( |
||||
|
"fmt" |
||||
|
utils "youtube_collection_server/Utils" |
||||
|
. "youtube_collection_server/config" |
||||
|
"youtube_collection_server/controller" |
||||
|
"youtube_collection_server/middle" |
||||
|
|
||||
"github.com/gin-gonic/gin" |
"github.com/gin-gonic/gin" |
||||
) |
) |
||||
|
|
||||
func main() { |
func main() { |
||||
|
InitConfig() |
||||
// 创建一个默认的路由引擎
|
// 创建一个默认的路由引擎
|
||||
r := gin.Default() |
router := gin.Default() |
||||
// 配置路由
|
//初始化路由
|
||||
f := func(c *gin.Context) { |
initRouter(router) |
||||
c.JSON(200, gin.H{ |
Logger.Infof("服务器启动成功...端口:%d", MyEnv.Server.Port) |
||||
"username": "name1", |
router.Use(middle.Cors()) |
||||
"data": "data1", |
err := router.Run(fmt.Sprintf(":"+"%d", MyEnv.Server.Port)) |
||||
}) |
if err != nil { |
||||
|
Logger.Error("服务器启动失败") |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func initRouter(router *gin.Engine) { |
||||
|
router.Use(utils.LoggerToFile(MyEnv.Log.LogEnv, MyEnv.Log.LogPath)) |
||||
|
noAuth := router.Group("") |
||||
|
{ |
||||
|
noAuth.GET("/test", controller.UserController.Test) |
||||
} |
} |
||||
r.GET("/", f) |
|
||||
// 启动 HTTP 服务,默认在 0.0.0.0:8080 启动服务
|
|
||||
r.Run() |
|
||||
} |
} |
||||
|
@ -0,0 +1,22 @@ |
|||||
|
package middle |
||||
|
|
||||
|
import ( |
||||
|
"net/http" |
||||
|
|
||||
|
"github.com/gin-gonic/gin" |
||||
|
) |
||||
|
|
||||
|
func Cors() gin.HandlerFunc { |
||||
|
return func(context *gin.Context) { |
||||
|
method := context.Request.Method |
||||
|
context.Header("Access-Control-Allow-Origin", "*") |
||||
|
context.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token") |
||||
|
context.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS") |
||||
|
context.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type") |
||||
|
context.Header("Access-Control-Allow-Credentials", "true") |
||||
|
if method == "OPTIONS" { |
||||
|
context.AbortWithStatus(http.StatusNoContent) |
||||
|
} |
||||
|
context.Next() |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue