123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- package logger
- import (
- "fmt"
- "net/http"
- "os"
- "time"
- "golang-fave/engine/consts"
- "golang-fave/engine/domains"
- "golang-fave/engine/utils"
- )
- type logMsg struct {
- host string
- message string
- isError bool
- }
- type Logger struct {
- wwwDir string
- cdata chan logMsg
- cclose chan bool
- }
- func (this *Logger) console(msg *logMsg) {
- if consts.ParamDebug {
- if !msg.isError {
- if consts.IS_WIN {
- fmt.Fprintln(os.Stdout, "[ACCESS] "+msg.message)
- } else {
- fmt.Fprintln(os.Stdout, "\033[0;32m[ACCESS] "+msg.message+"\033[0m")
- }
- } else {
- if consts.IS_WIN {
- fmt.Fprintln(os.Stdout, "[ERROR] "+msg.message)
- } else {
- fmt.Fprintln(os.Stdout, "\033[0;31m[ERROR] "+msg.message+"\033[0m")
- }
- }
- return
- }
- if !msg.isError {
- fmt.Fprintln(os.Stdout, msg.message)
- } else {
- fmt.Fprintln(os.Stderr, msg.message)
- }
- }
- func (this *Logger) write(msg *logMsg) {
- // Ignore file if debug
- if consts.ParamDebug {
- this.console(msg)
- return
- }
- // Ignore file if host not set
- if msg.host == "" {
- this.console(msg)
- return
- }
- // Ignore file if www dir is not exists
- if !utils.IsDirExists(this.wwwDir) {
- this.console(msg)
- return
- }
- // Extract host
- host, _ := utils.ExtractHostPort(msg.host, false)
- // --- TODO: optimize this later
- curr_host := host
- doms := domains.New(this.wwwDir)
- if mhost := doms.GetHost(host); mhost != "" {
- curr_host = mhost
- }
- // ---
- logs_dir := this.wwwDir + string(os.PathSeparator) + curr_host + string(os.PathSeparator) + "logs"
- // Try use localhost folder for logs
- if !utils.IsDirExists(logs_dir) {
- logs_dir = this.wwwDir + string(os.PathSeparator) + "localhost" + string(os.PathSeparator) + "logs"
- }
- // Ignore file if logs dir is not exists
- if !utils.IsDirExists(logs_dir) {
- this.console(msg)
- return
- }
- // Detect which log file
- log_file := logs_dir + string(os.PathSeparator) + "access.log"
- if msg.isError {
- log_file = logs_dir + string(os.PathSeparator) + "error.log"
- }
- // Try write to file
- f, err := os.OpenFile(log_file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
- if err == nil {
- defer f.Close()
- fmt.Fprintln(f, msg.message)
- return
- }
- // By default
- this.console(msg)
- }
- func New() *Logger {
- // Logs channel
- cdata := make(chan logMsg)
- // Close channel
- cclose := make(chan bool)
- // Init logger pointer
- lg := Logger{cdata: cdata, cclose: cclose}
- // Write log string in background
- go func() {
- for {
- select {
- case msg := <-cdata:
- lg.write(&msg)
- case <-cclose:
- cclose <- true
- return
- }
- }
- }()
- return &lg
- }
- func (this *Logger) Log(msg string, r *http.Request, isError bool, vars ...interface{}) {
- var host string = ""
- if r != nil {
- host = r.Host
- }
- if len(vars) > 0 {
- msg = fmt.Sprintf(msg, vars...)
- }
- select {
- case <-r.Context().Done():
- return
- case this.cdata <- logMsg{host, msg, isError}:
- return
- case <-time.After(1 * time.Second):
- fmt.Printf("Logger, can't send msg (overflow): %s, %s, %v\n", host, msg, isError)
- return
- }
- }
- func (this *Logger) SetWwwDir(dir string) {
- this.wwwDir = dir
- }
- func (this *Logger) Handler(h http.Handler) http.Handler {
- return handler{
- h: h,
- w: os.Stdout,
- c: this.cdata,
- }
- }
- func (this *Logger) Close() {
- this.cclose <- true
- <-this.cclose
- }
|