mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
add file configuration support for logger in ghttp.Server
This commit is contained in:
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user