add file configuration support for logger in ghttp.Server

This commit is contained in:
John Guo
2021-06-26 11:18:44 +08:00
parent 4cd7e4e5a0
commit 237f172ae5
9 changed files with 90 additions and 46 deletions

View File

@ -24,17 +24,30 @@ func Server(name ...interface{}) *ghttp.Server {
s := ghttp.GetServer(name...)
// To avoid file no found error while it's not necessary.
if Config().Available() {
var m map[string]interface{}
var (
serverConfigMap map[string]interface{}
serverLoggerConfigMap map[string]interface{}
)
nodeKey, _ := gutil.MapPossibleItemByKey(Config().GetMap("."), configNodeNameServer)
if nodeKey == "" {
nodeKey = configNodeNameServer
}
m = Config().GetMap(fmt.Sprintf(`%s.%s`, nodeKey, s.GetName()))
if len(m) == 0 {
m = Config().GetMap(nodeKey)
// Server configuration.
serverConfigMap = Config().GetMap(fmt.Sprintf(`%s.%s`, nodeKey, s.GetName()))
if len(serverConfigMap) == 0 {
serverConfigMap = Config().GetMap(nodeKey)
}
if len(m) > 0 {
if err := s.SetConfigWithMap(m); err != nil {
if len(serverConfigMap) > 0 {
if err := s.SetConfigWithMap(serverConfigMap); err != nil {
panic(err)
}
}
// Server logger configuration.
serverLoggerConfigMap = Config().GetMap(
fmt.Sprintf(`%s.%s.%s`, nodeKey, s.GetName(), configNodeNameLogger),
)
if len(serverLoggerConfigMap) > 0 {
if err := s.Logger().SetConfigWithMap(serverLoggerConfigMap); err != nil {
panic(err)
}
}

View File

@ -19,11 +19,11 @@ import (
)
type (
// Server wraps the http.Server and provides more feature.
// Server wraps the http.Server and provides more rich features.
Server struct {
name string // Unique name for instance management.
config ServerConfig // Configuration.
plugins []Plugin // Plugin array.
plugins []Plugin // Plugin array to extends server functionality.
servers []*gracefulServer // Underlying http.Server array.
serverCount *gtype.Int // Underlying http.Server count.
closeChan chan struct{} // Used for underlying server closing event notification.
@ -44,7 +44,7 @@ type (
Priority int // Just for reference.
}
// Router item just for route dumps.
// RouterItem is just for route dumps.
RouterItem struct {
Server string // Server name.
Address string // Listening address.
@ -98,7 +98,7 @@ type (
Stack() string
}
// Request handler function.
// HandlerFunc is request handler function.
HandlerFunc = func(r *Request)
// Listening file descriptor mapping.
@ -107,10 +107,6 @@ type (
)
const (
HOOK_BEFORE_SERVE = "HOOK_BEFORE_SERVE" // Deprecated, use HookBeforeServe instead.
HOOK_AFTER_SERVE = "HOOK_AFTER_SERVE" // Deprecated, use HookAfterServe instead.
HOOK_BEFORE_OUTPUT = "HOOK_BEFORE_OUTPUT" // Deprecated, use HookBeforeOutput instead.
HOOK_AFTER_OUTPUT = "HOOK_AFTER_OUTPUT" // Deprecated, use HookAfterOutput instead.
HookBeforeServe = "HOOK_BEFORE_SERVE"
HookAfterServe = "HOOK_AFTER_SERVE"
HookBeforeOutput = "HOOK_BEFORE_OUTPUT"

View File

@ -195,7 +195,7 @@ func (s *Server) Start() error {
if gproc.IsChild() {
gtimer.SetTimeout(time.Duration(s.config.GracefulTimeout)*time.Second, func() {
if err := gproc.Send(gproc.PPid(), []byte("exit"), adminGProcCommGroup); err != nil {
//glog.Error("server error in process communication:", err)
intlog.Error("server error in process communication:", err)
}
})
}

View File

@ -223,13 +223,14 @@ type ServerConfig struct {
GracefulTimeout uint8 `json:"gracefulTimeout"`
}
// Config creates and returns a ServerConfig object with default configurations.
// Deprecated. Use NewConfig instead.
func Config() ServerConfig {
return NewConfig()
}
// NewConfig creates and returns a ServerConfig object with default configurations.
// Note that, do not define this default configuration to local package variable, as there're
// Note that, do not define this default configuration to local package variable, as there are
// some pointer attributes that may be shared in different servers.
func NewConfig() ServerConfig {
return ServerConfig{
@ -331,7 +332,9 @@ func (s *Server) SetConfig(c ServerConfig) error {
return err
}
}
s.config.Logger.SetLevelStr(s.config.LogLevel)
if err := s.config.Logger.SetLevelStr(s.config.LogLevel); err != nil {
intlog.Error(err)
}
SetGraceful(c.Graceful)
intlog.Printf("SetConfig: %+v", s.config)

View File

@ -6,6 +6,8 @@
package ghttp
import "github.com/gogf/gf/os/glog"
// SetLogPath sets the log path for server.
// It logs content to file only if the log path is set.
func (s *Server) SetLogPath(path string) error {
@ -23,6 +25,17 @@ func (s *Server) SetLogPath(path string) error {
return nil
}
// SetLogger sets the logger for logging responsibility.
// Note that it cannot be set in runtime as there may be concurrent safety issue.
func (s *Server) SetLogger(logger *glog.Logger) {
s.config.Logger = logger
}
// Logger is alias of GetLogger.
func (s *Server) Logger() *glog.Logger {
return s.config.Logger
}
// SetLogLevel sets logging level by level string.
func (s *Server) SetLogLevel(level string) {
s.config.LogLevel = level

View File

@ -7,6 +7,7 @@
package ghttp
import (
"github.com/gogf/gf/internal/intlog"
"net/http"
"os"
"sort"
@ -80,9 +81,15 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Close the request and response body
// to release the file descriptor in time.
_ = request.Request.Body.Close()
err := request.Request.Body.Close()
if err != nil {
intlog.Error(err)
}
if request.Request.Response != nil {
_ = request.Request.Response.Body.Close()
err = request.Request.Response.Body.Close()
if err != nil {
intlog.Error(err)
}
}
}()
@ -188,9 +195,11 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// searchStaticFile searches the file with given URI.
// It returns a file struct specifying the file information.
func (s *Server) searchStaticFile(uri string) *staticFile {
var file *gres.File
var path string
var dir bool
var (
file *gres.File
path string
dir bool
)
// Firstly search the StaticPaths mapping.
if len(s.config.StaticPaths) > 0 {
for _, item := range s.config.StaticPaths {

View File

@ -9,14 +9,8 @@ package ghttp
import (
"fmt"
"github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/os/glog"
)
// Logger returns the logger of the server.
func (s *Server) Logger() *glog.Logger {
return s.config.Logger
}
// handleAccessLog handles the access logging for server.
func (s *Server) handleAccessLog(r *Request) {
if !s.IsAccessLogEnabled() {
@ -26,7 +20,7 @@ func (s *Server) handleAccessLog(r *Request) {
if r.TLS != nil {
scheme = "https"
}
s.Logger().File(s.config.AccessLogPattern).
s.Logger().Ctx(r.Context()).File(s.config.AccessLogPattern).
Stdout(s.config.LogStdout).
Printf(
`%d "%s %s %s %s %s" %.3f, %s, "%s", "%s"`,
@ -63,7 +57,7 @@ func (s *Server) handleErrorLog(err error, r *Request) {
} else {
content += ", " + err.Error()
}
s.config.Logger.
s.Logger().Ctx(r.Context()).
File(s.config.ErrorLogPattern).
Stdout(s.config.LogStdout).
Print(content)

View File

@ -102,9 +102,9 @@ func (l *Logger) print(ctx context.Context, level int, values ...interface{}) {
if p.parent != nil {
p = p.parent
}
if !p.init.Val() && p.init.Cas(false, true) {
// It just initializes once for each logger.
if p.config.RotateSize > 0 || p.config.RotateExpire > 0 {
// It just initializes once for each logger.
if p.config.RotateSize > 0 || p.config.RotateExpire > 0 {
if !p.init.Val() && p.init.Cas(false, true) {
gtimer.AddOnce(p.config.RotateCheckInterval, p.rotateChecksTimely)
intlog.Printf("logger rotation initialized: every %s", p.config.RotateCheckInterval.String())
}

View File

@ -19,6 +19,10 @@ import (
"time"
)
const (
memoryLockPrefixForRotating = "glog.rotateChecksTimely:"
)
// rotateFileBySize rotates the current logging file according to the
// configured rotation size.
func (l *Logger) rotateFileBySize(now time.Time) {
@ -91,6 +95,7 @@ func (l *Logger) doRotateFile(filePath string) error {
// rotateChecksTimely timely checks the backups expiration and the compression.
func (l *Logger) rotateChecksTimely() {
defer gtimer.AddOnce(l.config.RotateCheckInterval, l.rotateChecksTimely)
// Checks whether file rotation not enabled.
if l.config.RotateSize <= 0 && l.config.RotateExpire == 0 {
intlog.Printf(
@ -101,17 +106,20 @@ func (l *Logger) rotateChecksTimely() {
}
// It here uses memory lock to guarantee the concurrent safety.
memoryLockKey := "glog.rotateChecksTimely:" + l.config.Path
memoryLockKey := memoryLockPrefixForRotating + l.config.Path
if !gmlock.TryLock(memoryLockKey) {
return
}
defer gmlock.Unlock(memoryLockKey)
var (
now = time.Now()
pattern = "*.log, *.gz"
files, _ = gfile.ScanDirFile(l.config.Path, pattern, true)
now = time.Now()
pattern = "*.log, *.gz"
files, err = gfile.ScanDirFile(l.config.Path, pattern, true)
)
if err != nil {
intlog.Error(err)
}
intlog.Printf("logging rotation start checks: %+v", files)
// =============================================================
// Rotation of expired file checks.
@ -141,7 +149,10 @@ func (l *Logger) rotateChecksTimely() {
}
if expireRotated {
// Update the files array.
files, _ = gfile.ScanDirFile(l.config.Path, pattern, true)
files, err = gfile.ScanDirFile(l.config.Path, pattern, true)
if err != nil {
intlog.Error(err)
}
}
}
@ -175,7 +186,10 @@ func (l *Logger) rotateChecksTimely() {
return true
})
// Update the files array.
files, _ = gfile.ScanDirFile(l.config.Path, pattern, true)
files, err = gfile.ScanDirFile(l.config.Path, pattern, true)
if err != nil {
intlog.Error(err)
}
}
}
@ -192,10 +206,12 @@ func (l *Logger) rotateChecksTimely() {
if backupFilesMap[originalLoggingFilePath] == nil {
backupFilesMap[originalLoggingFilePath] = garray.NewSortedArray(func(a, b interface{}) int {
// Sorted by rotated/backup file mtime.
// The old rotated/backup file is put in the head of array.
file1 := a.(string)
file2 := b.(string)
result := gfile.MTimestampMilli(file1) - gfile.MTimestampMilli(file2)
// The older rotated/backup file is put in the head of array.
var (
file1 = a.(string)
file2 = b.(string)
result = gfile.MTimestampMilli(file1) - gfile.MTimestampMilli(file2)
)
if result <= 0 {
return -1
}
@ -214,11 +230,11 @@ func (l *Logger) rotateChecksTimely() {
path, _ := array.PopLeft()
intlog.Printf(`remove exceeded backup limit file: %s`, path)
if err := gfile.Remove(path.(string)); err != nil {
intlog.Print(err)
intlog.Error(err)
}
}
}
// Backup expiration checks.
// Backups expiration checking.
if l.config.RotateBackupExpire > 0 {
var (
mtime time.Time
@ -235,7 +251,7 @@ func (l *Logger) rotateChecksTimely() {
now, mtime, subDuration, l.config.RotateBackupExpire, path,
)
if err := gfile.Remove(path); err != nil {
intlog.Print(err)
intlog.Error(err)
}
return true
} else {