Browse Source

Better logs system

Vova Tkach 6 years ago
parent
commit
a5c6095de9
3 changed files with 94 additions and 8 deletions
  1. 16 4
      logger/handler.go
  2. 64 1
      logger/logger.go
  3. 14 3
      main.go

+ 16 - 4
logger/handler.go

@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"io"
 	"net/http"
-	"os"
 	"strconv"
 	"strings"
 	"time"
@@ -13,10 +12,11 @@ import (
 type handler struct {
 	h http.Handler
 	w io.Writer
+	c chan string
 }
 
-func (this handler) logRequest(w *writer, r *http.Request) {
-	fmt.Fprintln(os.Stdout, strings.Join([]string{
+func (this handler) log(w *writer, r *http.Request) {
+	str := fmt.Sprint(strings.Join([]string{
 		r.Host,
 		r.RemoteAddr,
 		"-",
@@ -26,11 +26,23 @@ func (this handler) logRequest(w *writer, r *http.Request) {
 		r.Proto + `"`,
 		strconv.Itoa(w.status),
 		strconv.Itoa(w.size),
+		fmt.Sprintf("%.3f ms", time.Now().Sub(w.s).Seconds()/1e6),
 	}, " "))
+
+	// Do not wait
+	go func() {
+		select {
+		case this.c <- str:
+			return
+		case <-time.After(1 * time.Second):
+			fmt.Println("Logger error, log channel is overflowed (2)")
+			return
+		}
+	}()
 }
 
 func (this handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	wrt := &writer{w: w, s: time.Now()}
 	this.h.ServeHTTP(wrt, r)
-	this.logRequest(wrt, r)
+	this.log(wrt, r)
 }

+ 64 - 1
logger/logger.go

@@ -1,13 +1,76 @@
 package logger
 
 import (
+	"fmt"
 	"net/http"
 	"os"
+	"time"
 )
 
-func New(h http.Handler) http.Handler {
+type Logger struct {
+	wwwDir string
+	cdata  chan string
+	cclose chan bool
+}
+
+func (this *Logger) write(str string) {
+	// TODO: write to console or to file
+	// If www and host home dir are exists
+	fmt.Fprintln(os.Stdout, str)
+}
+
+func New() *Logger {
+	// Logs channel
+	cdata := make(chan string)
+
+	// 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 str := <-cdata:
+				lg.write(str)
+			case <-cclose:
+				cclose <- true
+				return
+			}
+		}
+	}()
+
+	return &lg
+}
+
+func (this *Logger) Log(str string) {
+	// Do not wait
+	go func() {
+		select {
+		case this.cdata <- str:
+			return
+		case <-time.After(1 * time.Second):
+			fmt.Println("Logger error, log channel is overflowed (1)")
+			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
+}

+ 14 - 3
main.go

@@ -31,13 +31,21 @@ func init() {
 }
 
 func main() {
+	// Init logger
+	lg := logger.New()
+	defer lg.Close()
+
+	// Check www dir
 	ParamWwwDir = utils.FixPath(ParamWwwDir)
 	if !utils.IsHostDirExists(ParamWwwDir) {
-		fmt.Println("Virtual hosts directory is not exists")
-		fmt.Println("Example: ./fave -host 127.0.0.1 -port 80 -dir ./hosts")
+		lg.Log("Virtual hosts directory is not exists")
+		lg.Log("Example: ./fave -host 127.0.0.1 -port 80 -dir ./hosts")
 		return
 	}
 
+	// Attach www dir to logger
+	lg.SetWwwDir(ParamWwwDir)
+
 	// Init mounted resources
 	res := resource.New()
 	res.Add(consts.AssetsCpScriptsJs, "application/javascript; charset=utf-8", assets.CpScriptsJs)
@@ -52,7 +60,7 @@ func main() {
 	stat := static.New(consts.DirIndexFile)
 
 	// Init and start web server
-	bootstrap.Start(logger.New, fmt.Sprintf("%s:%d", ParamHost, ParamPort), 30, consts.AssetsPath, func(w http.ResponseWriter, r *http.Request) {
+	bootstrap.Start(lg.Handler, fmt.Sprintf("%s:%d", ParamHost, ParamPort), 30, consts.AssetsPath, func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Server", "fave.pro/"+consts.ServerVersion)
 	}, func(w http.ResponseWriter, r *http.Request) {
 		// Mounted assets
@@ -114,6 +122,9 @@ func main() {
 		utils.SystemErrorPage404(w)
 	})
 
+	// Close logger
+	//lg.Close()
+
 	// TODO: call it in background time by time
 	// Delete expired session files
 	// session.Clean("./tmp")