mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
improve logging feature for ghttp.Server
This commit is contained in:
@ -1,12 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
replaceCharReg, err := regexp.Compile(`[\-\.\_\s]+`)
|
||||
//b := make([]byte, 10)
|
||||
r := bytes.NewBuffer(make([]byte, 1))
|
||||
|
||||
n, err := r.Write([]byte("12345"))
|
||||
|
||||
fmt.Println(n)
|
||||
fmt.Println(err)
|
||||
fmt.Println(replaceCharReg.ReplaceAllString("s--s.s.a b", ""))
|
||||
fmt.Println(r.String())
|
||||
}
|
||||
|
||||
@ -48,7 +48,6 @@ type (
|
||||
routesMap map[string][]registeredRouteItem // 已经注册的路由及对应的注册方法文件地址(用以路由重复注册判断)
|
||||
statusHandlerMap map[string]HandlerFunc // 不同状态码下的注册处理方法(例如404状态时的处理方法)
|
||||
sessionManager *gsession.Manager // Session管理器
|
||||
logger *glog.Logger // 日志管理对象
|
||||
}
|
||||
|
||||
// 路由对象
|
||||
@ -223,7 +222,6 @@ func GetServer(name ...interface{}) *Server {
|
||||
serveCache: gcache.New(),
|
||||
routesMap: make(map[string][]registeredRouteItem),
|
||||
servedCount: gtype.NewInt(),
|
||||
logger: glog.New(),
|
||||
}
|
||||
// 初始化时使用默认配置
|
||||
if err := s.SetConfig(c); err != nil {
|
||||
@ -245,14 +243,19 @@ func (s *Server) Start() error {
|
||||
|
||||
// 当前Web Server状态判断
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server is already running")
|
||||
return errors.New("[ghttp] server is already running")
|
||||
}
|
||||
|
||||
// 没有注册任何路由,且没有开启文件服务,那么提示错误
|
||||
if len(s.routesMap) == 0 && !s.config.FileServerEnabled {
|
||||
glog.Fatal("[ghttp] There's no route set or static feature enabled, did you forget import the router?")
|
||||
return errors.New(`[ghttp] there's no route set or static feature enabled, did you forget import the router?`)
|
||||
}
|
||||
// Logging.
|
||||
if s.config.LogPath != "" {
|
||||
if err := s.config.Logger.SetPath(s.config.LogPath); err != nil {
|
||||
return errors.New(fmt.Sprintf("[ghttp] set log path '%s' error: %v", s.config.LogPath, err))
|
||||
}
|
||||
}
|
||||
|
||||
// Default session storage.
|
||||
if s.config.SessionStorage == nil {
|
||||
path := ""
|
||||
@ -260,7 +263,7 @@ func (s *Server) Start() error {
|
||||
path = gfile.Join(s.config.SessionPath, s.name)
|
||||
if !gfile.Exists(path) {
|
||||
if err := gfile.Mkdir(path); err != nil {
|
||||
glog.Fatalf("mkdir failed for '%s': %v", path, err)
|
||||
return errors.New(fmt.Sprintf("[ghttp] mkdir failed for '%s': %v", path, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -421,7 +424,7 @@ func (s *Server) Run() {
|
||||
// 阻塞等待服务执行完成
|
||||
<-s.closeChan
|
||||
|
||||
glog.Printf("%d: all servers shutdown", gproc.Pid())
|
||||
glog.Printf("[ghttp] %d: all servers shutdown", gproc.Pid())
|
||||
}
|
||||
|
||||
// 阻塞等待所有Web Server停止,常用于多Web Server场景,以及需要将Web Server异步运行的场景
|
||||
@ -430,7 +433,7 @@ func Wait() {
|
||||
// 阻塞等待服务执行完成
|
||||
<-allDoneChan
|
||||
|
||||
glog.Printf("%d: all servers shutdown", gproc.Pid())
|
||||
glog.Printf("[ghttp] %d: all servers shutdown", gproc.Pid())
|
||||
}
|
||||
|
||||
// 开启底层Web Server执行
|
||||
|
||||
@ -32,9 +32,6 @@ const (
|
||||
URI_TYPE_CAMEL = 3 // 采用驼峰命名方式
|
||||
)
|
||||
|
||||
// LogHandler is the log handler function type.
|
||||
type LogHandler func(r *Request, err ...error)
|
||||
|
||||
// HTTP Server configuration.
|
||||
type ServerConfig struct {
|
||||
Address string // Server listening address like ":port", multiple addresses separated using ','
|
||||
@ -67,8 +64,8 @@ type ServerConfig struct {
|
||||
DenyIps []string // Security: 不允许访问的ip列表,支持ip前缀过滤,如: 10 将不允许10开头的ip访问
|
||||
AllowIps []string // Security: 仅允许访问的ip列表,支持ip前缀过滤,如: 10 将仅允许10开头的ip访问
|
||||
DenyRoutes []string // Security: 不允许访问的路由规则列表
|
||||
Logger *glog.Logger // Logging: Custom logger for server.
|
||||
LogPath string // Logging: 存放日志的目录路径(默认为空,表示不写文件)
|
||||
LogHandler LogHandler // Logging: 日志配置: 自定义日志处理回调方法(默认为空)
|
||||
LogStdout bool // Logging: 是否打印日志到终端(默认开启)
|
||||
ErrorStack bool // Logging: 当产生错误时打印调用链详细堆栈
|
||||
ErrorLogEnabled bool // Logging: 是否开启error log(默认开启)
|
||||
@ -106,6 +103,7 @@ var defaultServerConfig = ServerConfig{
|
||||
SessionMaxAge: time.Hour * 24,
|
||||
SessionIdName: "gfsessionid",
|
||||
SessionPath: gsession.DefaultStorageFilePath,
|
||||
Logger: glog.New(),
|
||||
LogStdout: true,
|
||||
ErrorStack: true,
|
||||
ErrorLogEnabled: true,
|
||||
@ -139,10 +137,6 @@ func (s *Server) SetConfig(c ServerConfig) error {
|
||||
c.Handler = http.HandlerFunc(s.defaultHttpHandle)
|
||||
}
|
||||
s.config = c
|
||||
// Logging.
|
||||
if c.LogPath != "" {
|
||||
return s.logger.SetPath(c.LogPath)
|
||||
}
|
||||
// HTTPS.
|
||||
if c.TLSConfig == nil && c.HTTPSCertPath != "" {
|
||||
s.EnableHTTPS(c.HTTPSCertPath, c.HTTPSKeyPath)
|
||||
|
||||
@ -7,9 +7,6 @@
|
||||
package ghttp
|
||||
|
||||
// 设置日志目录,只有在设置了日志目录的情况下才会输出日志到日志文件中。
|
||||
// 日志文件路径格式为:
|
||||
// 1. 请求日志: access/YYYY-MM-DD.log
|
||||
// 2. 错误日志: error/YYYY-MM-DD.log
|
||||
func (s *Server) SetLogPath(path string) {
|
||||
if len(path) == 0 {
|
||||
return
|
||||
@ -17,7 +14,6 @@ func (s *Server) SetLogPath(path string) {
|
||||
s.config.LogPath = path
|
||||
s.config.ErrorLogEnabled = true
|
||||
s.config.AccessLogEnabled = true
|
||||
s.logger.SetPath(path)
|
||||
}
|
||||
|
||||
// 设置日志内容是否输出到终端,默认情况下只有错误日志才会自动输出到终端。
|
||||
@ -41,16 +37,6 @@ func (s *Server) SetErrorStack(enabled bool) {
|
||||
s.config.ErrorStack = enabled
|
||||
}
|
||||
|
||||
// 设置日志写入的回调函数
|
||||
func (s *Server) SetLogHandler(handler LogHandler) {
|
||||
s.config.LogHandler = handler
|
||||
}
|
||||
|
||||
// 获取日志写入的回调函数
|
||||
func (s *Server) GetLogHandler() LogHandler {
|
||||
return s.config.LogHandler
|
||||
}
|
||||
|
||||
// 获取日志目录
|
||||
func (s *Server) GetLogPath() string {
|
||||
return s.config.LogPath
|
||||
|
||||
@ -46,7 +46,7 @@ func (s *Server) SetServerRoot(root string) {
|
||||
realPath := root
|
||||
if !gres.Contains(realPath) {
|
||||
if p, err := gfile.Search(root); err != nil {
|
||||
glog.Fatal(fmt.Sprintf(`[ghttp] SetServerRoot failed: %s`, err.Error()))
|
||||
glog.Fatal(fmt.Sprintf(`[ghttp] SetServerRoot failed: %v`, err))
|
||||
} else {
|
||||
realPath = p
|
||||
}
|
||||
@ -61,7 +61,7 @@ func (s *Server) AddSearchPath(path string) {
|
||||
realPath := path
|
||||
if !gres.Contains(realPath) {
|
||||
if p, err := gfile.Search(path); err != nil {
|
||||
glog.Fatal(fmt.Sprintf(`[ghttp] AddSearchPath failed: %s`, err.Error()))
|
||||
glog.Fatal(fmt.Sprintf(`[ghttp] AddSearchPath failed: %v`, err))
|
||||
} else {
|
||||
realPath = p
|
||||
}
|
||||
@ -75,7 +75,7 @@ func (s *Server) AddStaticPath(prefix string, path string) {
|
||||
realPath := path
|
||||
if !gres.Contains(realPath) {
|
||||
if p, err := gfile.Search(path); err != nil {
|
||||
glog.Fatal(fmt.Sprintf(`[ghttp] AddStaticPath failed: %s`, err.Error()))
|
||||
glog.Fatal(fmt.Sprintf(`[ghttp] AddStaticPath failed: %v`, err))
|
||||
} else {
|
||||
realPath = p
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ func (s *Server) newHttpServer(itemFunc string) *http.Server {
|
||||
WriteTimeout: s.config.WriteTimeout,
|
||||
IdleTimeout: s.config.IdleTimeout,
|
||||
MaxHeaderBytes: s.config.MaxHeaderBytes,
|
||||
ErrorLog: log.New(&errorLogger{logger: s.logger}, "", 0),
|
||||
ErrorLog: log.New(&errorLogger{logger: s.config.Logger}, "", 0),
|
||||
}
|
||||
server.SetKeepAlivesEnabled(s.config.KeepAlive)
|
||||
return server
|
||||
|
||||
@ -23,11 +23,6 @@ func (s *Server) handleAccessLog(r *Request) {
|
||||
if !s.IsAccessLogEnabled() {
|
||||
return
|
||||
}
|
||||
// 自定义错误处理
|
||||
if v := s.GetLogHandler(); v != nil {
|
||||
v(r)
|
||||
return
|
||||
}
|
||||
scheme := "http"
|
||||
if r.TLS != nil {
|
||||
scheme = "https"
|
||||
@ -38,7 +33,7 @@ func (s *Server) handleAccessLog(r *Request) {
|
||||
)
|
||||
content += fmt.Sprintf(` %.3f`, float64(r.LeaveTime-r.EnterTime)/1000)
|
||||
content += fmt.Sprintf(`, %s, "%s", "%s"`, r.GetClientIp(), r.Referer(), r.UserAgent())
|
||||
s.logger.File(s.config.AccessLogPattern).StackWithFilter(gPATH_FILTER_KEY).Stdout(s.config.LogStdout).Println(content)
|
||||
s.config.Logger.File(s.config.AccessLogPattern).StackWithFilter(gPATH_FILTER_KEY).Stdout(s.config.LogStdout).Println(content)
|
||||
}
|
||||
|
||||
// 处理服务错误信息,主要是panic,http请求的status由access log进行管理
|
||||
@ -48,12 +43,6 @@ func (s *Server) handleErrorLog(err error, r *Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// 自定义错误处理
|
||||
if v := s.GetLogHandler(); v != nil {
|
||||
v(r, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 错误日志信息
|
||||
scheme := "http"
|
||||
if r.TLS != nil {
|
||||
@ -71,5 +60,5 @@ func (s *Server) handleErrorLog(err error, r *Request) {
|
||||
content += "\n" + stack
|
||||
}
|
||||
}
|
||||
s.logger.File(s.config.AccessLogPattern).Stack(false).Stdout(s.config.LogStdout).Error(content)
|
||||
s.config.Logger.File(s.config.AccessLogPattern).Stack(false).Stdout(s.config.LogStdout).Error(content)
|
||||
}
|
||||
|
||||
@ -70,7 +70,6 @@ func Letters(n int) string {
|
||||
b[i] = letters[Intn(52)]
|
||||
}
|
||||
return string(b)
|
||||
|
||||
}
|
||||
|
||||
// Perm returns, as a slice of n int numbers, a pseudo-random permutation of the integers [0,n).
|
||||
|
||||
@ -9,6 +9,8 @@
|
||||
package grand_test
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/util/grand"
|
||||
@ -22,10 +24,10 @@ func Benchmark_Rand(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
//func Benchmark_Buffer(b *testing.B) {
|
||||
// for i := 0; i < b.N; i++ {
|
||||
// if _, err := rand.Read(buffer); err == nil {
|
||||
// binary.LittleEndian.Uint64(buffer)
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
func Benchmark_Buffer(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := rand.Read(buffer); err == nil {
|
||||
binary.LittleEndian.Uint64(buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
56
util/guuid/guuid_z_bench_test.go
Normal file
56
util/guuid/guuid_z_bench_test.go
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package guuid_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/util/guuid"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Benchmark_New(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
guuid.New()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_NewUUID(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
guuid.NewUUID()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_NewDCEGroup(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
guuid.NewDCEGroup()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_NewDCEPerson(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
guuid.NewDCEPerson()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_NewRandom(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
guuid.NewRandom()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_NewMD5(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
guuid.NewMD5(guuid.UUID{}, []byte(""))
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_NewSHA1(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
guuid.NewSHA1(guuid.UUID{}, []byte(""))
|
||||
}
|
||||
}
|
||||
@ -29,9 +29,6 @@ func Test_Basic(t *testing.T) {
|
||||
uuid, _ = guuid.NewRandom()
|
||||
gtest.Assert(len(uuid.String()), 36)
|
||||
|
||||
uuid, _ = guuid.NewRandom()
|
||||
gtest.Assert(len(uuid.String()), 36)
|
||||
|
||||
gtest.Assert(len(guuid.NewMD5(guuid.UUID{}, []byte("")).String()), 36)
|
||||
gtest.Assert(len(guuid.NewSHA1(guuid.UUID{}, []byte("")).String()), 36)
|
||||
})
|
||||
Reference in New Issue
Block a user