I could write everything into a file with #805 post.
Related to this, how could it be possible to write error into a separate log?
--
I assume to use gin.DefaultErrorWriter, but it seems that log.SetOuput is only possible with a single file.
Current output (everything into a single file)
[GIN] 2018/05/30 - 19:21:17 | 404 | 114.656碌s | ::1 | GET /comment/view/99999
Error #01: th size of input parameter is not 40
[GIN] 2018/05/30 - 19:21:20 | 200 | 1.82468ms | ::1 | GET /comment/view/00001
Current code
logfile, err := os.OpenFile(c.GinLogPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalln("Failed to create request log file:", err)
}
errlogfile, err := os.OpenFile(c.GinErrorLogPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalln("Failed to create request log file:", err)
}
// set request logging
gin.DefaultWriter = io.MultiWriter(logfile)
gin.DefaultErrorWriter = io.MultiWriter(errlogfile)
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
log.SetOutput(gin.DefaultWriter)
logfile, _ := os.Create("request.log")
gin.DefaultWriter = io.MultiWriter(logfile)errlogfile, _ := os.Create("error.log")
gin.DefaultErrorWriter = io.MultiWriter(errlogfile)
En. Maybe You have a misconception about issues 805
1. The request log will be fomartted and logged by gin.DefaultWriter or gin.DefaultErrorWriter (the logger.go of gin , not the the log package of go ).So you needn't to care about log(removing it).
2. If just want everything into a single file, it is unnecessary to use io.MultiWriter
Based on the above two points
// set request logging
gin.DefaultWriter = logfile
gin.DefaultErrorWriter = errlogfile
is enough
Hi, Thanks for your reply!
I removed log.Setflags and log.Setoutput.
However, the error log is still empty.
Just log.Println(err) doesn't make records in the error log.
This might be very basic, but could you give me any advice about howto write to error log (gin.DefaultErrorWriter)?
--
I tried c.AbortWithError(http.StatusNotFound, err) and c.Error(err) in my handler function.
still got nothing in error log (only gin.DefaultWriter log).
- project<dir>
--- main.go <- gin.DefaultWriter, gin.DefaultErrorWriter setting is here.
--- handlers<dir>
----- view_handler.go <- c.AbortWithError is here.
--- ...
// Recovery returns a middleware that recovers from any panics and writes a 500 if there was one.
func Recovery() HandlerFunc {
return RecoveryWithWriter(DefaultErrorWriter)
}
Because gin.DefaultErrorWriter are used to do this, this mean only log panic
c.Error(err) you reference does not belong to this situation, and so only gin.DefaultWriter log.
--
Actually, you can use gin.DefaultErrorWriter and add some log what you want into error log.
package main
import (
"github.com/gin-gonic/gin"
"os"
)
func main() {
r := gin.Default()
errlogfile, _ := os.Create("error.log")
gin.DefaultErrorWriter = errlogfile
r.GET("t", func(c *gin.Context) {
errLogger := gin.DefaultErrorWriter
errLogger.Write([]byte("[DIY ERROR] HELLO ERROR!\n"))
c.JSON(200, gin.H{"hello": "world"})
})
r.Run(":8080")
}
But it depend on you(developer).
Thanks.
So, recovery from panic is the case to use DefaultErrorWriter.
(A) If so, appropriate approach is to define logger for error in handler function and use it.
I'll take this approach.
(B) I suppose another approach could be to use fmt.Fprinln(gin.DefaultErrorWriter, "some error message") directly, and confirmed this would write error to error log.
--
(C) I confirmed I could write with your suggestion(I used gin.DefaultErrorWriter.Write(...) directly in handler) successfuly.
In summary (A), (B), or (C) could be solution.
@chainhelen thanks again!!
--
I am not sure if this would help others but I'll write the detail of my approach to write separate logs for handler functions.
detail of (A):
(a) for default request log: set gin.DefaultWriter (in main())
(b) for other log (which includes errors, and is separate from (a)): as follows
in handlers.go
var (
Debug *log.Logger
Info *log.Logger
Warning *log.Logger
Error *log.Logger
)
...
func init() {
...
// set package-internal logger
Info = log.New(logfile, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
Warning = log.New(logfile, "WARN: ", log.Ldate|log.Ltime|log.Lshortfile)
Error = log.New(logfile, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
}
in each xxx_handler.go (functions called from main route.GET(xxxx))
if someobjects, err := somedbfunction(); err == nil {
c.JSON ...
} else {
Error.Println(err)
c.AbortWithStatus(http.StatusNotFound)
}
the structure of directory is
- project<dir>
--- main.go <- gin.DefaultWriter, gin.DefaultErrorWriter setting is here.
--- handlers<dir>
----- handlers.go <- define package internal logger (var Error or Info or Warn ... )
----- view_handler.go <- use logger here like Error.Println, Info.Println, Warn.Println...
--- ...
@chainhelen All Right
@nowissan
Gin does not provide log level type, you can add other golang package on your project simply.
https://github.com/avelino/awesome-go#logging
@syssam
thanks! this is helpful.
I thought about using zap or zerolog from performance reason.
they could be options for structured.
replace gin log, reference
https://github.com/szuecs/gin-glog/blob/master/ginglog.go
Most helpful comment
En. Maybe You have a misconception about issues 805
1. The request log will be fomartted and logged by
gin.DefaultWriter or gin.DefaultErrorWriter(the logger.go of gin, not thethe log package of go).So you needn't to care aboutlog(removing it).2. If just want
everything into a single file, it is unnecessary to useio.MultiWriterBased on the above two points
is enough