mirror of
https://github.com/nabbar/golib.git
synced 2025-11-02 19:54:14 +08:00
# Add package : - config server, cluster, logger, user & permission - config client & builder - interface for managing server, cluster and client - test for nats cluster / client producer & subscriber # Update packages : - pkg errors : constant to add package nats - pkg logger : add function to read options - pkg ioutils : add function to check / create file & path # Dependancies : - Bump dependancies - Add dependancies : - github.com/nats-io/nats-server/v2 - github.com/nats-io/nats.go
224 lines
6.1 KiB
Go
224 lines
6.1 KiB
Go
/*
|
|
MIT License
|
|
|
|
Copyright (c) 2019 Nicolas JUHEL
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
*/
|
|
|
|
package logger
|
|
|
|
import (
|
|
"bytes"
|
|
"log"
|
|
"path"
|
|
"reflect"
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
const (
|
|
tagStack = "stack"
|
|
tagTime = "time"
|
|
tagCaller = "func"
|
|
tagFile = "file"
|
|
tagLine = "line"
|
|
tagMsg = "message"
|
|
tagErr = "error"
|
|
tagData = "data"
|
|
)
|
|
|
|
var (
|
|
currPkgs = path.Base(reflect.TypeOf(IOWriter{}).PkgPath())
|
|
filterPkg = path.Clean(reflect.TypeOf(IOWriter{}).PkgPath())
|
|
modeColor = true
|
|
timestamp = true
|
|
filetrace = false
|
|
enableGID = false
|
|
enableVPR = true
|
|
)
|
|
|
|
func init() {
|
|
if i := strings.LastIndex(filterPkg, "/vendor/"); i != -1 {
|
|
filterPkg = filterPkg[:i+1]
|
|
}
|
|
}
|
|
|
|
// GetLogger return a golang log.logger instance linked with this main logger.
|
|
// This function is useful to keep the format, mode, color, output... same as current config.
|
|
// - msgPrefixPattern a pattern prefix to identify or comment all message passed throw this log.logger instance.
|
|
// - msgPrefixArgs a list of interface to apply on pattern with a fmt function.
|
|
func GetLogger(lvl Level, logFlags int, msgPrefixPattern string, msgPrefixArgs ...interface{}) *log.Logger {
|
|
return log.New(GetIOWriter(lvl, msgPrefixPattern, msgPrefixArgs...), "", logFlags)
|
|
}
|
|
|
|
// SetStdLogger force the default golang log.logger instance linked with this main logger.
|
|
// This function is useful to keep the format, mode, color, output... same as current config.
|
|
// - msgPrefixPattern a pattern prefix to identify or comment all message passed throw this log.logger instance.
|
|
// - msgPrefixArgs a list of interface to apply on pattern with a fmt function.
|
|
func SetStdLogger(lvl Level, logFlags int, msgPrefixPattern string, msgPrefixArgs ...interface{}) {
|
|
log.SetOutput(GetIOWriter(lvl, msgPrefixPattern, msgPrefixArgs...))
|
|
log.SetPrefix("")
|
|
log.SetFlags(logFlags)
|
|
}
|
|
|
|
// AddGID Reconfigure the current logger to add or not the thread GID before each message.
|
|
func AddGID(enable bool) {
|
|
enableGID = enable
|
|
}
|
|
|
|
// Timestamp Reconfigure the current logger to add or not the timestamp before each message.
|
|
func Timestamp(enable bool) {
|
|
timestamp = enable
|
|
}
|
|
|
|
// IsTimeStamp will return true if timestamp is added or not on log message
|
|
func IsTimeStamp() bool {
|
|
return timestamp
|
|
}
|
|
|
|
// FileTrace Reconfigure the current logger to add or not the origin file/line of each message.
|
|
// This option is apply for all message except info message.
|
|
func FileTrace(enable bool) {
|
|
filetrace = enable
|
|
setViperLogTrace()
|
|
}
|
|
|
|
// IsFileTrace will return true if trace is added or not on log message
|
|
func IsFileTrace() bool {
|
|
return filetrace
|
|
}
|
|
|
|
// ModeColor will reconfigure the current logger to use or not color in messages format.
|
|
// This apply only for next message and only for TextFormat.
|
|
func ModeColor(enable bool) {
|
|
modeColor = enable
|
|
updateFormatter(nilFormat)
|
|
}
|
|
|
|
// IsModeColor will return true if color is configured on log message
|
|
func IsModeColor() bool {
|
|
return modeColor
|
|
}
|
|
|
|
// EnableColor Reconfigure the current logger to use color in messages format.
|
|
// This apply only for next message and only for TextFormat.
|
|
// @deprecated use ModeColor(true)
|
|
func EnableColor() {
|
|
ModeColor(true)
|
|
}
|
|
|
|
// DisableColor Reconfigure the current logger to not use color in messages format.
|
|
// This apply only for next message and only for TextFormat.
|
|
// @deprecated use Color(false)
|
|
func DisableColor() {
|
|
ModeColor(false)
|
|
}
|
|
|
|
// EnableViperLog enable or not the Gin Logger configuration.
|
|
func EnableViperLog(enable bool) {
|
|
enableVPR = enable
|
|
setViperLogTrace()
|
|
}
|
|
|
|
// SetTracePathFilter customize the filter apply to filepath on trace.
|
|
func SetTracePathFilter(path string) {
|
|
filterPkg = path
|
|
}
|
|
|
|
func getFrame() runtime.Frame {
|
|
// Set size to targetFrameIndex+2 to ensure we have room for one more caller than we need.
|
|
programCounters := make([]uintptr, 10, 255)
|
|
n := runtime.Callers(1, programCounters)
|
|
|
|
if n > 0 {
|
|
frames := runtime.CallersFrames(programCounters[:n])
|
|
more := true
|
|
|
|
for more {
|
|
var (
|
|
frame runtime.Frame
|
|
)
|
|
|
|
frame, more = frames.Next()
|
|
|
|
if strings.Contains(frame.Function, currPkgs) {
|
|
continue
|
|
}
|
|
|
|
return frame
|
|
}
|
|
}
|
|
|
|
return runtime.Frame{Function: "unknown", File: "unknown", Line: 0}
|
|
}
|
|
|
|
func getGID() uint64 {
|
|
b := make([]byte, 64)
|
|
|
|
b = b[:runtime.Stack(b, false)]
|
|
b = bytes.TrimPrefix(b, []byte("goroutine "))
|
|
b = b[:bytes.IndexByte(b, ' ')]
|
|
|
|
//nolint #nosec
|
|
/* #nosec */
|
|
n, _ := strconv.ParseUint(string(b), 10, 64)
|
|
|
|
return n
|
|
}
|
|
|
|
func ginTonicAddError(c *gin.Context, err error) {
|
|
if c != nil && err != nil {
|
|
_ = c.Error(err)
|
|
}
|
|
}
|
|
|
|
func proceed(lvl Level) bool {
|
|
return lvl != NilLevel && lvl <= GetCurrentLevel()
|
|
}
|
|
|
|
func filterPath(pathname string) string {
|
|
var (
|
|
filterMod = "/pkg/mod/"
|
|
filterVendor = "/vendor/"
|
|
)
|
|
|
|
if i := strings.LastIndex(pathname, filterMod); i != -1 {
|
|
i = i + len(filterMod)
|
|
pathname = pathname[i:]
|
|
}
|
|
|
|
if i := strings.LastIndex(pathname, filterPkg); i != -1 {
|
|
i = i + len(filterPkg)
|
|
pathname = pathname[i:]
|
|
}
|
|
|
|
if i := strings.LastIndex(pathname, filterVendor); i != -1 {
|
|
i = i + len(filterVendor)
|
|
pathname = pathname[i:]
|
|
}
|
|
|
|
pathname = path.Clean(pathname)
|
|
|
|
return strings.Trim(pathname, "/")
|
|
}
|