mirror of
https://github.com/nabbar/golib.git
synced 2025-11-01 03:22:34 +08:00
Package Logger :
Add function to log minimalist information and access log (latency, size remote info, ...)
Add option to transform (exclusif) logger as access logger
fix errors & optimize
Package Router :
Update methode to start gin engine with access / error logger from package logger
fix error into middleware logger
use specif middleware for starttime and request path
optimize
Package ioutils :
fix tools : missing control path still existing to prevent truncate destination file
fix tools : ignore chmod error (not mandatory if file can be create/append)
Package Prometheus :
use generic starttime into context if available
Bump Dependencies
This commit is contained in:
committed by
Nicolas JUHEL
parent
609eaa68e1
commit
c9db0074bc
3
.github/workflows/go.yml
vendored
3
.github/workflows/go.yml
vendored
@@ -58,7 +58,6 @@ jobs:
|
||||
env:
|
||||
GOOS: linux
|
||||
GOARCH: amd64
|
||||
GOAMD64: v4
|
||||
CGO_ENABLED: 0
|
||||
|
||||
- name: Check goSecu + snyk.io
|
||||
@@ -67,7 +66,6 @@ jobs:
|
||||
env:
|
||||
GOOS: linux
|
||||
GOARCH: amd64
|
||||
GOAMD64: v4
|
||||
CGO_ENABLED: 0
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
|
||||
@@ -89,7 +87,6 @@ jobs:
|
||||
env:
|
||||
GOOS: linux
|
||||
GOARCH: amd64
|
||||
GOAMD64: v4
|
||||
CGO_ENABLED: 0
|
||||
|
||||
- name: Add ming-w32 (x86 + win64)
|
||||
|
||||
@@ -28,6 +28,7 @@ package archive
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
arcmod "github.com/nabbar/golib/archive/archive"
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
)
|
||||
|
||||
148
go.mod
148
go.mod
@@ -4,14 +4,14 @@ go 1.19
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.16
|
||||
github.com/aws/aws-sdk-go-v2/config v1.17.7
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.20
|
||||
github.com/aws/aws-sdk-go-v2/service/iam v1.18.19
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.11
|
||||
github.com/aws/aws-sdk-go-v2/config v1.17.8
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.21
|
||||
github.com/aws/aws-sdk-go-v2/service/iam v1.18.20
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.28.0
|
||||
github.com/bits-and-blooms/bitset v1.3.3
|
||||
github.com/c-bata/go-prompt v0.2.6
|
||||
github.com/fatih/color v1.13.0
|
||||
github.com/fsnotify/fsnotify v1.5.4
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
github.com/fxamacker/cbor/v2 v2.4.0
|
||||
github.com/gin-gonic/gin v1.8.1
|
||||
github.com/go-ldap/ldap/v3 v3.4.4
|
||||
@@ -27,16 +27,16 @@ require (
|
||||
github.com/mattn/go-colorable v0.1.13
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/nats-io/jwt/v2 v2.3.0
|
||||
github.com/nats-io/nats-server/v2 v2.9.1
|
||||
github.com/nats-io/nats.go v1.17.0
|
||||
github.com/onsi/ginkgo/v2 v2.2.0
|
||||
github.com/onsi/gomega v1.20.2
|
||||
github.com/nats-io/nats-server/v2 v2.9.3
|
||||
github.com/nats-io/nats.go v1.18.0
|
||||
github.com/onsi/ginkgo/v2 v2.3.1
|
||||
github.com/onsi/gomega v1.22.1
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.13.0
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/spf13/cobra v1.6.0
|
||||
github.com/spf13/jwalterweatherman v1.1.0
|
||||
github.com/spf13/viper v1.13.0
|
||||
github.com/vbauerster/mpb/v5 v5.4.0
|
||||
@@ -44,33 +44,36 @@ require (
|
||||
github.com/xhit/go-simple-mail v2.2.2+incompatible
|
||||
github.com/xujiajun/nutsdb v0.10.0
|
||||
github.com/xujiajun/utils v0.0.0-20220904132955-5f7c5b914235
|
||||
golang.org/x/exp v0.0.0-20220921164117-439092de6870
|
||||
golang.org/x/net v0.0.0-20220926192436-02166a98028e
|
||||
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1
|
||||
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7
|
||||
golang.org/x/sys v0.0.0-20220926163933-8cfa568d3c25
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
golang.org/x/exp v0.0.0-20221019170559-20944726eadf
|
||||
golang.org/x/net v0.1.0
|
||||
golang.org/x/oauth2 v0.1.0
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/sys v0.1.0
|
||||
golang.org/x/term v0.1.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/driver/clickhouse v0.4.2
|
||||
gorm.io/driver/mysql v1.3.6
|
||||
gorm.io/driver/postgres v1.3.10
|
||||
gorm.io/driver/sqlite v1.3.6
|
||||
gorm.io/driver/sqlserver v1.3.2
|
||||
gorm.io/gorm v1.23.10
|
||||
gorm.io/driver/clickhouse v0.5.0
|
||||
gorm.io/driver/mysql v1.4.3
|
||||
gorm.io/driver/postgres v1.4.4
|
||||
gorm.io/driver/sqlite v1.4.3
|
||||
gorm.io/driver/sqlserver v1.4.1
|
||||
gorm.io/gorm v1.24.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.2.0 // indirect
|
||||
github.com/Masterminds/semver v1.4.2 // indirect
|
||||
github.com/Masterminds/sprig v2.16.0+incompatible // indirect
|
||||
github.com/PuerkitoBio/goquery v1.5.0 // indirect
|
||||
github.com/VictoriaMetrics/metrics v1.6.2 // indirect
|
||||
github.com/VividCortex/ewma v1.1.1 // indirect
|
||||
github.com/ClickHouse/ch-go v0.48.0 // indirect
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.3.0 // indirect
|
||||
github.com/DataDog/zstd v1.5.2 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||
github.com/PuerkitoBio/goquery v1.8.0 // indirect
|
||||
github.com/VictoriaMetrics/metrics v1.22.2 // indirect
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
|
||||
github.com/andybalholm/cascadia v1.0.0 // indirect
|
||||
github.com/aokoli/goutils v1.0.1 // indirect
|
||||
github.com/armon/go-metrics v0.3.10 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.1 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 // indirect
|
||||
@@ -82,7 +85,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 // indirect
|
||||
github.com/aws/smithy-go v1.13.3 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
@@ -93,36 +96,38 @@ require (
|
||||
github.com/cockroachdb/pebble v0.0.0-20210331181633-27fc006b8bfb // indirect
|
||||
github.com/cockroachdb/redact v1.0.6 // indirect
|
||||
github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 // indirect
|
||||
github.com/denisenkom/go-mssqldb v0.12.0 // indirect
|
||||
github.com/getsentry/sentry-go v0.14.0 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
|
||||
github.com/go-faster/city v1.0.1 // indirect
|
||||
github.com/go-faster/errors v0.6.1 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-playground/locales v0.14.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
github.com/goccy/go-json v0.9.11 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
|
||||
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3 // indirect
|
||||
github.com/google/btree v1.0.0 // indirect
|
||||
github.com/google/go-cmp v0.5.8 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/css v1.0.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-msgpack v0.5.3 // indirect
|
||||
github.com/hashicorp/go-msgpack v1.1.5 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.0 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/memberlist v0.2.2 // indirect
|
||||
github.com/huandu/xstrings v1.2.0 // indirect
|
||||
github.com/imdario/mergo v0.3.6 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/hashicorp/memberlist v0.5.0 // indirect
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/imdario/mergo v0.3.13 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||
github.com/jackc/pgconn v1.13.0 // indirect
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
@@ -131,59 +136,66 @@ require (
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
|
||||
github.com/jackc/pgtype v1.12.0 // indirect
|
||||
github.com/jackc/pgx/v4 v4.17.2 // indirect
|
||||
github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0 // indirect
|
||||
github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/juju/ratelimit v1.0.2-0.20191002062651-f60b32039441 // indirect
|
||||
github.com/klauspost/compress v1.15.10 // indirect
|
||||
github.com/kr/pretty v0.3.0 // indirect
|
||||
github.com/juju/ratelimit v1.0.2 // indirect
|
||||
github.com/klauspost/compress v1.15.11 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/lni/goutils v1.3.0 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.12 // indirect
|
||||
github.com/mattn/go-tty v0.0.3 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/miekg/dns v1.1.26 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.15 // indirect
|
||||
github.com/mattn/go-tty v0.0.4 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
|
||||
github.com/microsoft/go-mssqldb v0.17.0 // indirect
|
||||
github.com/miekg/dns v1.1.50 // indirect
|
||||
github.com/minio/highwayhash v1.0.2 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/nats-io/nkeys v0.3.0 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.1 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/paulmach/orb v0.7.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.15 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.17 // indirect
|
||||
github.com/pkg/term v1.2.0-beta.2 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.37.0 // indirect
|
||||
github.com/prometheus/procfs v0.8.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.8.0 // indirect
|
||||
github.com/rivo/uniseg v0.4.2 // indirect
|
||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/spf13/afero v1.8.2 // indirect
|
||||
github.com/spf13/afero v1.9.2 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.7 // indirect
|
||||
github.com/valyala/fastrand v1.0.0 // indirect
|
||||
github.com/valyala/histogram v1.0.1 // indirect
|
||||
github.com/vanng822/css v0.0.0-20190504095207-a21e860bcd04 // indirect
|
||||
github.com/vanng822/go-premailer v0.0.0-20191214114701-be27abe028fe // indirect
|
||||
github.com/valyala/fastrand v1.1.0 // indirect
|
||||
github.com/valyala/histogram v1.2.0 // indirect
|
||||
github.com/vanng822/css v1.0.1 // indirect
|
||||
github.com/vanng822/go-premailer v1.20.1 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xujiajun/mmap-go v1.0.1 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
go.opentelemetry.io/otel v1.7.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.7.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20220920022843-2ce7c2934d45 // indirect
|
||||
go.opentelemetry.io/otel v1.11.1 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.11.1 // indirect
|
||||
golang.org/x/crypto v0.1.0 // indirect
|
||||
golang.org/x/mod v0.6.0 // indirect
|
||||
golang.org/x/text v0.4.0 // indirect
|
||||
golang.org/x/time v0.1.0 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
|
||||
@@ -36,6 +36,9 @@ import (
|
||||
func PathCheckCreate(isFile bool, path string, permFile os.FileMode, permDir os.FileMode) error {
|
||||
if _, err := os.Stat(path); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
} else if err == nil {
|
||||
_ = os.Chmod(path, permFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !isFile {
|
||||
@@ -48,5 +51,6 @@ func PathCheckCreate(isFile bool, path string, permFile os.FileMode, permDir os.
|
||||
_ = hf.Close()
|
||||
}
|
||||
|
||||
return os.Chmod(path, permFile)
|
||||
_ = os.Chmod(path, permFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ const (
|
||||
type Entry struct {
|
||||
log func() *logrus.Logger
|
||||
gin *gin.Context
|
||||
clean bool
|
||||
|
||||
//Time is the time of the event (can be empty time if disabled timestamp)
|
||||
Time time.Time `json:"time"`
|
||||
@@ -166,7 +167,26 @@ func (e *Entry) Check(lvlNoErr Level) bool {
|
||||
return found
|
||||
}
|
||||
|
||||
func (e *Entry) _logClean() {
|
||||
var (
|
||||
log *logrus.Logger
|
||||
)
|
||||
|
||||
if e.log == nil {
|
||||
return
|
||||
} else if log = e.log(); log == nil {
|
||||
return
|
||||
} else {
|
||||
log.Info(e.Message)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Entry) Log() {
|
||||
if e.clean {
|
||||
e._logClean()
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
ent *logrus.Entry
|
||||
tag = NewFields().Add(FieldLevel, e.Level.String())
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/nabbar/golib/ioutils"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -43,12 +44,21 @@ type HookFile interface {
|
||||
}
|
||||
|
||||
type _HookFile struct {
|
||||
f *os.File
|
||||
r logrus.Formatter
|
||||
l []logrus.Level
|
||||
s bool
|
||||
d bool
|
||||
t bool
|
||||
a bool
|
||||
o _HookFileOptions
|
||||
}
|
||||
|
||||
type _HookFileOptions struct {
|
||||
Create bool
|
||||
FilePath string
|
||||
Flags int
|
||||
ModeFile os.FileMode
|
||||
ModePath os.FileMode
|
||||
}
|
||||
|
||||
func NewHookFile(opt OptionsFile, format logrus.Formatter) (HookFile, error) {
|
||||
@@ -57,32 +67,10 @@ func NewHookFile(opt OptionsFile, format logrus.Formatter) (HookFile, error) {
|
||||
}
|
||||
|
||||
var (
|
||||
flags = os.O_WRONLY | os.O_APPEND
|
||||
LVLs = make([]logrus.Level, 0)
|
||||
hdl *os.File
|
||||
err error
|
||||
flags = os.O_WRONLY | os.O_APPEND
|
||||
)
|
||||
|
||||
if opt.FileMode == 0 {
|
||||
opt.FileMode = 0644
|
||||
}
|
||||
|
||||
if opt.PathMode == 0 {
|
||||
opt.PathMode = 0755
|
||||
}
|
||||
|
||||
if opt.CreatePath {
|
||||
if err = ioutils.PathCheckCreate(true, opt.Filepath, opt.FileMode, opt.PathMode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if opt.Create {
|
||||
flags = os.O_CREATE | flags
|
||||
}
|
||||
|
||||
if hdl, err = os.OpenFile(opt.Filepath, flags, opt.FileMode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(opt.LogLevel) > 0 {
|
||||
for _, ls := range opt.LogLevel {
|
||||
LVLs = append(LVLs, GetLevelString(ls).Logrus())
|
||||
@@ -91,14 +79,59 @@ func NewHookFile(opt OptionsFile, format logrus.Formatter) (HookFile, error) {
|
||||
LVLs = logrus.AllLevels
|
||||
}
|
||||
|
||||
return &_HookFile{
|
||||
f: hdl,
|
||||
if opt.Create {
|
||||
flags = os.O_CREATE | flags
|
||||
}
|
||||
|
||||
if opt.FileMode == 0 {
|
||||
opt.FileMode = 0644
|
||||
}
|
||||
|
||||
if opt.PathMode == 0 {
|
||||
opt.PathMode = 0755
|
||||
}
|
||||
|
||||
obj := &_HookFile{
|
||||
r: format,
|
||||
l: LVLs,
|
||||
s: opt.DisableStack,
|
||||
d: opt.DisableTimestamp,
|
||||
t: opt.EnableTrace,
|
||||
}, nil
|
||||
a: opt.EnableAccessLog,
|
||||
o: _HookFileOptions{
|
||||
Create: opt.CreatePath,
|
||||
FilePath: opt.Filepath,
|
||||
Flags: flags,
|
||||
ModeFile: opt.FileMode,
|
||||
ModePath: opt.PathMode,
|
||||
},
|
||||
}
|
||||
|
||||
if h, e := obj.openCreate(); e != nil {
|
||||
return nil, e
|
||||
} else {
|
||||
_ = h.Close()
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (o *_HookFile) openCreate() (*os.File, error) {
|
||||
var err error
|
||||
|
||||
if o.o.Create {
|
||||
if err = ioutils.PathCheckCreate(true, o.o.FilePath, o.o.ModeFile, o.o.ModePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if h, e := os.OpenFile(o.o.FilePath, o.o.Flags, o.o.ModeFile); e != nil {
|
||||
return nil, e
|
||||
} else if _, e = h.Seek(0, io.SeekEnd); e != nil {
|
||||
return nil, e
|
||||
} else {
|
||||
return h, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (o *_HookFile) RegisterHook(log *logrus.Logger) {
|
||||
@@ -127,27 +160,55 @@ func (o *_HookFile) Fire(entry *logrus.Entry) error {
|
||||
ent.Data = o.filterKey(ent.Data, FieldLine)
|
||||
}
|
||||
|
||||
if p, err := o.r.Format(ent); err != nil {
|
||||
return err
|
||||
} else if _, err = o.Write(p); err != nil {
|
||||
return err
|
||||
var (
|
||||
p []byte
|
||||
e error
|
||||
)
|
||||
|
||||
if o.a {
|
||||
if len(entry.Message) > 0 {
|
||||
if !strings.HasSuffix(entry.Message, "\n") {
|
||||
entry.Message += "\n"
|
||||
}
|
||||
p = []byte(entry.Message)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
if len(ent.Data) < 1 {
|
||||
return nil
|
||||
} else if p, e = ent.Bytes(); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
if _, e = o.Write(p); e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *_HookFile) Write(p []byte) (n int, err error) {
|
||||
if o.f == nil {
|
||||
return 0, fmt.Errorf("logrus.hookfile: file not setup")
|
||||
}
|
||||
h, e := o.openCreate()
|
||||
|
||||
return o.f.Write(p)
|
||||
defer func() {
|
||||
if h != nil {
|
||||
_ = h.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
if e != nil {
|
||||
return 0, fmt.Errorf("logrus.hookfile: cannot open '%s'", o.o.FilePath)
|
||||
} else if n, e = h.Write(p); e != nil {
|
||||
return n, e
|
||||
} else {
|
||||
return n, h.Sync()
|
||||
}
|
||||
}
|
||||
|
||||
func (o *_HookFile) Close() error {
|
||||
err := o.f.Close()
|
||||
o.f = nil
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *_HookFile) filterKey(f logrus.Fields, key string) logrus.Fields {
|
||||
@@ -155,6 +216,13 @@ func (o *_HookFile) filterKey(f logrus.Fields, key string) logrus.Fields {
|
||||
return f
|
||||
}
|
||||
|
||||
if _, ok := f[key]; !ok {
|
||||
return f
|
||||
} else {
|
||||
delete(f, key)
|
||||
return f
|
||||
}
|
||||
/*
|
||||
var res = make(map[string]interface{}, 0)
|
||||
|
||||
for k, v := range f {
|
||||
@@ -165,4 +233,5 @@ func (o *_HookFile) filterKey(f logrus.Fields, key string) logrus.Fields {
|
||||
}
|
||||
|
||||
return res
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/mattn/go-colorable"
|
||||
|
||||
@@ -56,9 +57,10 @@ type _HookStd struct {
|
||||
s bool // Disable Stack
|
||||
d bool // Disable Timestamp
|
||||
t bool // Disable Trace
|
||||
a bool // Enable AccessLog
|
||||
}
|
||||
|
||||
func NewHookStandard(opt Options, s StdWriter, lvls []logrus.Level) HookFile {
|
||||
func NewHookStandard(opt Options, s StdWriter, lvls []logrus.Level) HookStandard {
|
||||
if len(lvls) < 1 {
|
||||
lvls = logrus.AllLevels
|
||||
}
|
||||
@@ -87,6 +89,7 @@ func NewHookStandard(opt Options, s StdWriter, lvls []logrus.Level) HookFile {
|
||||
s: opt.DisableStack,
|
||||
d: opt.DisableTimestamp,
|
||||
t: opt.EnableTrace,
|
||||
a: opt.EnableAccessLog,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,10 +119,30 @@ func (o *_HookStd) Fire(entry *logrus.Entry) error {
|
||||
ent.Data = o.filterKey(ent.Data, FieldLine)
|
||||
}
|
||||
|
||||
if p, err := ent.Bytes(); err != nil {
|
||||
return err
|
||||
} else if _, err = o.Write(p); err != nil {
|
||||
return err
|
||||
var (
|
||||
p []byte
|
||||
e error
|
||||
)
|
||||
|
||||
if o.a {
|
||||
if len(entry.Message) > 0 {
|
||||
if !strings.HasSuffix(entry.Message, "\n") {
|
||||
entry.Message += "\n"
|
||||
}
|
||||
p = []byte(entry.Message)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
if len(ent.Data) < 1 {
|
||||
return nil
|
||||
} else if p, e = ent.Bytes(); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
if _, e = o.Write(p); e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -142,6 +165,13 @@ func (o *_HookStd) filterKey(f logrus.Fields, key string) logrus.Fields {
|
||||
return f
|
||||
}
|
||||
|
||||
if _, ok := f[key]; !ok {
|
||||
return f
|
||||
} else {
|
||||
delete(f, key)
|
||||
return f
|
||||
}
|
||||
/*
|
||||
var res = make(map[string]interface{}, 0)
|
||||
|
||||
for k, v := range f {
|
||||
@@ -152,4 +182,5 @@ func (o *_HookStd) filterKey(f logrus.Fields, key string) logrus.Fields {
|
||||
}
|
||||
|
||||
return res
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ package logger
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -60,6 +61,7 @@ type _HookSyslog struct {
|
||||
s bool
|
||||
d bool
|
||||
t bool
|
||||
a bool
|
||||
}
|
||||
|
||||
func NewHookSyslog(opt OptionsSyslog, format logrus.Formatter) (HookSyslog, error) {
|
||||
@@ -88,6 +90,7 @@ func NewHookSyslog(opt OptionsSyslog, format logrus.Formatter) (HookSyslog, erro
|
||||
s: opt.DisableStack,
|
||||
d: opt.DisableTimestamp,
|
||||
t: opt.EnableTrace,
|
||||
a: opt.EnableAccessLog,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -117,28 +120,46 @@ func (o *_HookSyslog) Fire(entry *logrus.Entry) error {
|
||||
ent.Data = o.filterKey(ent.Data, FieldLine)
|
||||
}
|
||||
|
||||
if p, err := o.f.Format(ent); err != nil {
|
||||
return err
|
||||
var (
|
||||
p []byte
|
||||
e error
|
||||
)
|
||||
|
||||
if o.a {
|
||||
if len(entry.Message) > 0 {
|
||||
if !strings.HasSuffix(entry.Message, "\n") {
|
||||
entry.Message += "\n"
|
||||
}
|
||||
p = []byte(entry.Message)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
if len(ent.Data) < 1 {
|
||||
return nil
|
||||
} else if p, e = ent.Bytes(); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
switch ent.Level {
|
||||
case logrus.PanicLevel:
|
||||
_, err = o.w.Panic(p)
|
||||
_, e = o.w.Panic(p)
|
||||
case logrus.FatalLevel:
|
||||
_, err = o.w.Fatal(p)
|
||||
_, e = o.w.Fatal(p)
|
||||
case logrus.ErrorLevel:
|
||||
_, err = o.w.Error(p)
|
||||
_, e = o.w.Error(p)
|
||||
case logrus.WarnLevel:
|
||||
_, err = o.w.Warning(p)
|
||||
_, e = o.w.Warning(p)
|
||||
case logrus.InfoLevel:
|
||||
_, err = o.w.Info(p)
|
||||
_, e = o.w.Info(p)
|
||||
case logrus.DebugLevel:
|
||||
_, err = o.w.Debug(p)
|
||||
_, e = o.w.Debug(p)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (o *_HookSyslog) Write(p []byte) (n int, err error) {
|
||||
@@ -160,6 +181,13 @@ func (o *_HookSyslog) filterKey(f logrus.Fields, key string) logrus.Fields {
|
||||
return f
|
||||
}
|
||||
|
||||
if _, ok := f[key]; !ok {
|
||||
return f
|
||||
} else {
|
||||
delete(f, key)
|
||||
return f
|
||||
}
|
||||
/*
|
||||
var res = make(map[string]interface{}, 0)
|
||||
|
||||
for k, v := range f {
|
||||
@@ -170,4 +198,5 @@ func (o *_HookSyslog) filterKey(f logrus.Fields, key string) logrus.Fields {
|
||||
}
|
||||
|
||||
return res
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import (
|
||||
"log"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
|
||||
@@ -117,6 +118,9 @@ type Logger interface {
|
||||
|
||||
//Entry will return an entry struct to manage it (set gin context, add fields, log the entry...)
|
||||
Entry(lvl Level, message string, args ...interface{}) *Entry
|
||||
|
||||
//Access will return an entry struct to store info level access log message
|
||||
Access(remoteAddr, remoteUser string, localtime time.Time, latency time.Duration, method, request, proto string, status int, size int64) *Entry
|
||||
}
|
||||
|
||||
// New return a new logger interface pointer
|
||||
|
||||
@@ -26,11 +26,25 @@
|
||||
package logger_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/nabbar/golib/logger"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func getLogFileTemp() string {
|
||||
fsp, err := GetTempFile()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
defer func() {
|
||||
err = DelTempFile(fsp)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}()
|
||||
|
||||
return filepath.Base(fsp)
|
||||
}
|
||||
|
||||
var _ = Describe("Logger", func() {
|
||||
Context("Create New Logger with Default Config", func() {
|
||||
It("Must succeed", func() {
|
||||
@@ -86,8 +100,8 @@ var _ = Describe("Logger", func() {
|
||||
Filepath: fsp,
|
||||
Create: true,
|
||||
CreatePath: true,
|
||||
FileMode: 0644,
|
||||
PathMode: 0755,
|
||||
//FileMode: 0644,
|
||||
//PathMode: 0755,
|
||||
DisableStack: false,
|
||||
DisableTimestamp: false,
|
||||
EnableTrace: true,
|
||||
@@ -122,8 +136,8 @@ var _ = Describe("Logger", func() {
|
||||
Filepath: fsp,
|
||||
Create: true,
|
||||
CreatePath: true,
|
||||
FileMode: 0644,
|
||||
PathMode: 0755,
|
||||
//FileMode: 0644,
|
||||
//PathMode: 0755,
|
||||
DisableStack: false,
|
||||
DisableTimestamp: false,
|
||||
EnableTrace: true,
|
||||
|
||||
@@ -63,28 +63,29 @@ func GetLevelListString() []string {
|
||||
}
|
||||
}
|
||||
|
||||
// GetLevelString return a valid Level Type matching the given string parameter. If the given parameter don't represent a valid level, the InfoLevel will be return.
|
||||
// GetLevelString return a valid Level Type matching the given string parameter.
|
||||
// If the given parameter don't represent a valid level, the InfoLevel will be return.
|
||||
/*
|
||||
level the string representation of a Level type
|
||||
*/
|
||||
func GetLevelString(l string) Level {
|
||||
switch {
|
||||
case strings.Contains(strings.ToLower(PanicLevel.String()), strings.ToLower(l)):
|
||||
case strings.EqualFold(PanicLevel.String(), l):
|
||||
return PanicLevel
|
||||
|
||||
case strings.Contains(strings.ToLower(FatalLevel.String()), strings.ToLower(l)):
|
||||
case strings.EqualFold(FatalLevel.String(), l):
|
||||
return FatalLevel
|
||||
|
||||
case strings.Contains(strings.ToLower(ErrorLevel.String()), strings.ToLower(l)):
|
||||
case strings.EqualFold(ErrorLevel.String(), l):
|
||||
return ErrorLevel
|
||||
|
||||
case strings.Contains(strings.ToLower(WarnLevel.String()), strings.ToLower(l)):
|
||||
case strings.EqualFold(WarnLevel.String(), l):
|
||||
return WarnLevel
|
||||
|
||||
case strings.Contains(strings.ToLower(InfoLevel.String()), strings.ToLower(l)):
|
||||
case strings.EqualFold(InfoLevel.String(), l):
|
||||
return InfoLevel
|
||||
|
||||
case strings.Contains(strings.ToLower(DebugLevel.String()), strings.ToLower(l)):
|
||||
case strings.EqualFold(DebugLevel.String(), l):
|
||||
return DebugLevel
|
||||
}
|
||||
|
||||
@@ -109,9 +110,9 @@ func (l Level) String() string {
|
||||
case ErrorLevel:
|
||||
return "Error"
|
||||
case FatalLevel:
|
||||
return "Fatal Error"
|
||||
return "Fatal"
|
||||
case PanicLevel:
|
||||
return "Critical Error"
|
||||
return "Critical"
|
||||
case NilLevel:
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -69,6 +69,10 @@ func (l *logger) Entry(lvl Level, message string, args ...interface{}) *Entry {
|
||||
return l.newEntry(lvl, fmt.Sprintf(message, args...), nil, nil, nil)
|
||||
}
|
||||
|
||||
func (l *logger) Access(remoteAddr, remoteUser string, localtime time.Time, latency time.Duration, method, request, proto string, status int, size int64) *Entry {
|
||||
return l.newEntryClean(fmt.Sprintf("%s - %s [%s] [%s] \"%s %s %s\" %d %d", remoteAddr, remoteUser, localtime.Format(time.RFC1123Z), latency.String(), method, request, proto, status, size))
|
||||
}
|
||||
|
||||
func (l *logger) newEntry(lvl Level, message string, err []error, fields Fields, data interface{}) *Entry {
|
||||
opt := l.GetOptions()
|
||||
cLv := l.GetLevel()
|
||||
@@ -79,6 +83,7 @@ func (l *logger) newEntry(lvl Level, message string, err []error, fields Fields,
|
||||
|
||||
var ent = &Entry{
|
||||
log: l.getLog,
|
||||
clean: false,
|
||||
Time: time.Time{},
|
||||
Level: lvl,
|
||||
Stack: 0,
|
||||
@@ -117,3 +122,13 @@ func (l *logger) newEntry(lvl Level, message string, err []error, fields Fields,
|
||||
|
||||
return ent
|
||||
}
|
||||
|
||||
func (l *logger) newEntryClean(message string) *Entry {
|
||||
var ent = &Entry{
|
||||
log: l.getLog,
|
||||
clean: true,
|
||||
Message: message,
|
||||
}
|
||||
|
||||
return ent
|
||||
}
|
||||
|
||||
@@ -94,6 +94,9 @@ type OptionsFile struct {
|
||||
|
||||
// EnableTrace allow to add the origin caller/file/line of each message.
|
||||
EnableTrace bool `json:"enableTrace,omitempty" yaml:"enableTrace,omitempty" toml:"enableTrace,omitempty" mapstructure:"enableTrace,omitempty"`
|
||||
|
||||
// EnableAccessLog allow to add all message from api router for access log and error log.
|
||||
EnableAccessLog bool `json:"enableAccessLog,omitempty" yaml:"enableAccessLog,omitempty" toml:"enableAccessLog,omitempty" mapstructure:"enableAccessLog,omitempty"`
|
||||
}
|
||||
|
||||
type OptionsSyslog struct {
|
||||
@@ -125,6 +128,9 @@ type OptionsSyslog struct {
|
||||
|
||||
// EnableTrace allow to add the origin caller/file/line of each message.
|
||||
EnableTrace bool `json:"enableTrace,omitempty" yaml:"enableTrace,omitempty" toml:"enableTrace,omitempty" mapstructure:"enableTrace,omitempty"`
|
||||
|
||||
// EnableAccessLog allow to add all message from api router for access log and error log.
|
||||
EnableAccessLog bool `json:"enableAccessLog,omitempty" yaml:"enableAccessLog,omitempty" toml:"enableAccessLog,omitempty" mapstructure:"enableAccessLog,omitempty"`
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
@@ -147,6 +153,9 @@ type Options struct {
|
||||
// If the running process is not a tty, no color will be used.
|
||||
DisableColor bool `json:"disableColor,omitempty" yaml:"disableColor,omitempty" toml:"disableColor,omitempty" mapstructure:"disableColor,omitempty"`
|
||||
|
||||
// EnableAccessLog allow to add all message from api router for access log and error log.
|
||||
EnableAccessLog bool `json:"enableAccessLog,omitempty" yaml:"enableAccessLog,omitempty" toml:"enableAccessLog,omitempty" mapstructure:"enableAccessLog,omitempty"`
|
||||
|
||||
// LogFile define a list of log file configuration to allow log to files.
|
||||
LogFile []OptionsFile `json:"logFile,omitempty" yaml:"logFile,omitempty" toml:"logFile,omitempty" mapstructure:"logFile,omitempty"`
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
librtr "github.com/nabbar/golib/router"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@@ -58,7 +60,19 @@ func (m *monitor) Expose(c *gin.Context) {
|
||||
|
||||
// MiddleWare as gin monitor middleware.
|
||||
func (m *monitor) MiddleWare(c *gin.Context) {
|
||||
startTime := time.Now()
|
||||
startTime := c.GetInt64(librtr.GinContextStartUnixNanoTime)
|
||||
|
||||
if startTime == 0 {
|
||||
startTime = time.Now().UnixNano()
|
||||
}
|
||||
|
||||
path := c.GetString(librtr.GinContextRequestPath)
|
||||
if path == "" {
|
||||
path = c.Request.URL.Path
|
||||
if raw := c.Request.URL.RawQuery; len(raw) > 0 {
|
||||
path += "?" + raw
|
||||
}
|
||||
}
|
||||
|
||||
if len(m.exclude) > 0 {
|
||||
r := c.Request.URL.Path
|
||||
@@ -76,7 +90,7 @@ func (m *monitor) MiddleWare(c *gin.Context) {
|
||||
c.Next()
|
||||
|
||||
// after request
|
||||
m.CollectMetrics(c, startTime)
|
||||
m.CollectMetrics(c, time.Unix(0, startTime))
|
||||
}
|
||||
|
||||
func (m *monitor) CollectMetrics(c *gin.Context, start time.Time) {
|
||||
|
||||
@@ -26,15 +26,157 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
)
|
||||
|
||||
const EmptyHandlerGroup = "<nil>"
|
||||
const (
|
||||
EmptyHandlerGroup = "<nil>"
|
||||
GinContextStartUnixNanoTime = "gin-ctx-start-unix-nano-time"
|
||||
GinContextRequestPath = "gin-ctx-request-path"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultRouters = NewRouterList(DefaultGinInit)
|
||||
)
|
||||
|
||||
func GinEngine(trustedPlatform string, trustyProxy ...string) (*gin.Engine, error) {
|
||||
var err error
|
||||
|
||||
engine := gin.New()
|
||||
if len(trustyProxy) > 0 {
|
||||
err = engine.SetTrustedProxies(trustyProxy)
|
||||
}
|
||||
if len(trustedPlatform) > 0 {
|
||||
engine.TrustedPlatform = trustedPlatform
|
||||
}
|
||||
|
||||
return engine, err
|
||||
}
|
||||
|
||||
func GinAddGlobalMiddleware(eng *gin.Engine, middleware ...gin.HandlerFunc) *gin.Engine {
|
||||
eng.Use(middleware...)
|
||||
return eng
|
||||
}
|
||||
|
||||
func GinLatencyContext(c *gin.Context) {
|
||||
// Start timer
|
||||
c.Set(GinContextStartUnixNanoTime, time.Now().UnixNano())
|
||||
|
||||
// Process request
|
||||
c.Next()
|
||||
}
|
||||
|
||||
func GinRequestContext(c *gin.Context) {
|
||||
// Set Path
|
||||
path := c.Request.URL.Path
|
||||
|
||||
if raw := c.Request.URL.RawQuery; len(raw) > 0 {
|
||||
path += "?" + raw
|
||||
}
|
||||
|
||||
c.Set(GinContextRequestPath, path)
|
||||
|
||||
// Process request
|
||||
c.Next()
|
||||
}
|
||||
|
||||
func GinAccessLog(log liblog.FuncLog) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// Process request
|
||||
c.Next()
|
||||
|
||||
// Log only when path is not being skipped
|
||||
if log == nil {
|
||||
return
|
||||
} else if l := log(); l == nil {
|
||||
return
|
||||
} else {
|
||||
sttm := time.Unix(0, c.GetInt64(GinContextStartUnixNanoTime))
|
||||
path := c.GetString(GinContextRequestPath)
|
||||
|
||||
ent := l.Access(
|
||||
c.ClientIP(),
|
||||
c.Request.URL.User.Username(),
|
||||
time.Now(),
|
||||
time.Now().Sub(sttm),
|
||||
c.Request.Method,
|
||||
path,
|
||||
c.Request.Proto,
|
||||
c.Writer.Status(),
|
||||
int64(c.Writer.Size()),
|
||||
)
|
||||
ent.Log()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GinErrorLog(log liblog.FuncLog) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
defer func() {
|
||||
var rec error
|
||||
|
||||
if err := recover(); err != nil {
|
||||
// Check for a broken connection, as it is not really a
|
||||
// condition that warrants a panic stack trace.
|
||||
var brokenPipe bool
|
||||
if ne, ok := err.(*net.OpError); ok {
|
||||
var se *os.SyscallError
|
||||
if errors.As(ne, &se) {
|
||||
if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
|
||||
brokenPipe = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if brokenPipe {
|
||||
rec = fmt.Errorf("[Recovery] connection error: %s", err)
|
||||
} else {
|
||||
rec = fmt.Errorf("[Recovery] panic recovered: %s", err)
|
||||
}
|
||||
|
||||
if brokenPipe {
|
||||
// If the connection is dead, we can't write a status to it.
|
||||
c.Abort()
|
||||
} else {
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
path := c.GetString(GinContextRequestPath)
|
||||
|
||||
// Log only when path is not being skipped
|
||||
if log == nil {
|
||||
return
|
||||
} else if l := log(); l == nil {
|
||||
return
|
||||
} else {
|
||||
if len(c.Errors) > 0 {
|
||||
for _, e := range c.Errors {
|
||||
ent := l.Entry(liblog.ErrorLevel, "error on request \"%s %s %s\"", c.Request.Method, path, c.Request.Proto)
|
||||
ent.ErrorAdd(true, e)
|
||||
ent.Check(liblog.NilLevel)
|
||||
}
|
||||
}
|
||||
if rec != nil {
|
||||
ent := l.Entry(liblog.ErrorLevel, "error on request \"%s %s %s\"", c.Request.Method, path, c.Request.Proto)
|
||||
ent.ErrorAdd(true, rec)
|
||||
ent.Check(liblog.NilLevel)
|
||||
}
|
||||
}
|
||||
}()
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func DefaultGinInit() *gin.Engine {
|
||||
engine := gin.New()
|
||||
engine.Use(gin.Logger(), gin.Recovery())
|
||||
|
||||
Reference in New Issue
Block a user