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:
Nicolas JUHEL
2022-10-17 14:32:29 +02:00
committed by Nicolas JUHEL
parent 609eaa68e1
commit c9db0074bc
15 changed files with 546 additions and 184 deletions

View File

@@ -58,7 +58,6 @@ jobs:
env: env:
GOOS: linux GOOS: linux
GOARCH: amd64 GOARCH: amd64
GOAMD64: v4
CGO_ENABLED: 0 CGO_ENABLED: 0
- name: Check goSecu + snyk.io - name: Check goSecu + snyk.io
@@ -67,7 +66,6 @@ jobs:
env: env:
GOOS: linux GOOS: linux
GOARCH: amd64 GOARCH: amd64
GOAMD64: v4
CGO_ENABLED: 0 CGO_ENABLED: 0
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
@@ -89,7 +87,6 @@ jobs:
env: env:
GOOS: linux GOOS: linux
GOARCH: amd64 GOARCH: amd64
GOAMD64: v4
CGO_ENABLED: 0 CGO_ENABLED: 0
- name: Add ming-w32 (x86 + win64) - name: Add ming-w32 (x86 + win64)

View File

@@ -28,6 +28,7 @@ package archive
import ( import (
"fmt" "fmt"
arcmod "github.com/nabbar/golib/archive/archive" arcmod "github.com/nabbar/golib/archive/archive"
liberr "github.com/nabbar/golib/errors" liberr "github.com/nabbar/golib/errors"
) )

148
go.mod
View File

@@ -4,14 +4,14 @@ go 1.19
require ( require (
github.com/aws/aws-sdk-go-v2 v1.16.16 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/config v1.17.8
github.com/aws/aws-sdk-go-v2/credentials v1.12.20 github.com/aws/aws-sdk-go-v2/credentials v1.12.21
github.com/aws/aws-sdk-go-v2/service/iam v1.18.19 github.com/aws/aws-sdk-go-v2/service/iam v1.18.20
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.11 github.com/aws/aws-sdk-go-v2/service/s3 v1.28.0
github.com/bits-and-blooms/bitset v1.3.3 github.com/bits-and-blooms/bitset v1.3.3
github.com/c-bata/go-prompt v0.2.6 github.com/c-bata/go-prompt v0.2.6
github.com/fatih/color v1.13.0 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/fxamacker/cbor/v2 v2.4.0
github.com/gin-gonic/gin v1.8.1 github.com/gin-gonic/gin v1.8.1
github.com/go-ldap/ldap/v3 v3.4.4 github.com/go-ldap/ldap/v3 v3.4.4
@@ -27,16 +27,16 @@ require (
github.com/mattn/go-colorable v0.1.13 github.com/mattn/go-colorable v0.1.13
github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-homedir v1.1.0
github.com/nats-io/jwt/v2 v2.3.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-server/v2 v2.9.3
github.com/nats-io/nats.go v1.17.0 github.com/nats-io/nats.go v1.18.0
github.com/onsi/ginkgo/v2 v2.2.0 github.com/onsi/ginkgo/v2 v2.3.1
github.com/onsi/gomega v1.20.2 github.com/onsi/gomega v1.22.1
github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml v1.9.5
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.13.0 github.com/prometheus/client_golang v1.13.0
github.com/shirou/gopsutil v3.21.11+incompatible github.com/shirou/gopsutil v3.21.11+incompatible
github.com/sirupsen/logrus v1.9.0 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/jwalterweatherman v1.1.0
github.com/spf13/viper v1.13.0 github.com/spf13/viper v1.13.0
github.com/vbauerster/mpb/v5 v5.4.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/xhit/go-simple-mail v2.2.2+incompatible
github.com/xujiajun/nutsdb v0.10.0 github.com/xujiajun/nutsdb v0.10.0
github.com/xujiajun/utils v0.0.0-20220904132955-5f7c5b914235 github.com/xujiajun/utils v0.0.0-20220904132955-5f7c5b914235
golang.org/x/exp v0.0.0-20220921164117-439092de6870 golang.org/x/exp v0.0.0-20221019170559-20944726eadf
golang.org/x/net v0.0.0-20220926192436-02166a98028e golang.org/x/net v0.1.0
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 golang.org/x/oauth2 v0.1.0
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7 golang.org/x/sync v0.1.0
golang.org/x/sys v0.0.0-20220926163933-8cfa568d3c25 golang.org/x/sys v0.1.0
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 golang.org/x/term v0.1.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/clickhouse v0.4.2 gorm.io/driver/clickhouse v0.5.0
gorm.io/driver/mysql v1.3.6 gorm.io/driver/mysql v1.4.3
gorm.io/driver/postgres v1.3.10 gorm.io/driver/postgres v1.4.4
gorm.io/driver/sqlite v1.3.6 gorm.io/driver/sqlite v1.4.3
gorm.io/driver/sqlserver v1.3.2 gorm.io/driver/sqlserver v1.4.1
gorm.io/gorm v1.23.10 gorm.io/gorm v1.24.0
) )
require ( require (
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.2.0 // indirect github.com/ClickHouse/ch-go v0.48.0 // indirect
github.com/Masterminds/semver v1.4.2 // indirect github.com/ClickHouse/clickhouse-go/v2 v2.3.0 // indirect
github.com/Masterminds/sprig v2.16.0+incompatible // indirect github.com/DataDog/zstd v1.5.2 // indirect
github.com/PuerkitoBio/goquery v1.5.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect
github.com/VictoriaMetrics/metrics v1.6.2 // indirect github.com/Masterminds/semver v1.5.0 // indirect
github.com/VividCortex/ewma v1.1.1 // 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/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/andybalholm/cascadia v1.0.0 // indirect github.com/andybalholm/brotli v1.0.4 // indirect
github.com/aokoli/goutils v1.0.1 // indirect github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/armon/go-metrics v0.3.10 // 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/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/feature/ec2/imds v1.12.17 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 // 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/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/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/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/aws-sdk-go-v2/service/sts v1.16.19 // indirect
github.com/aws/smithy-go v1.13.3 // indirect github.com/aws/smithy-go v1.13.3 // indirect
github.com/beorn7/perks v1.0.1 // 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/pebble v0.0.0-20210331181633-27fc006b8bfb // indirect
github.com/cockroachdb/redact v1.0.6 // indirect github.com/cockroachdb/redact v1.0.6 // indirect
github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 // 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/gin-contrib/sse v0.1.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // 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-ole/go-ole v1.2.6 // indirect
github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/goccy/go-json v0.9.11 // indirect github.com/goccy/go-json v0.9.11 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.0.0 // indirect github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.5.8 // indirect github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/css v1.0.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-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // 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-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/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/memberlist v0.2.2 // indirect github.com/hashicorp/memberlist v0.5.0 // indirect
github.com/huandu/xstrings v1.2.0 // indirect github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.6 // indirect github.com/imdario/mergo v0.3.13 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.13.0 // indirect github.com/jackc/pgconn v1.13.0 // indirect
github.com/jackc/pgio v1.0.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/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgtype v1.12.0 // indirect github.com/jackc/pgtype v1.12.0 // indirect
github.com/jackc/pgx/v4 v4.17.2 // 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/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/juju/ratelimit v1.0.2-0.20191002062651-f60b32039441 // indirect github.com/juju/ratelimit v1.0.2 // indirect
github.com/klauspost/compress v1.15.10 // indirect github.com/klauspost/compress v1.15.11 // indirect
github.com/kr/pretty v0.3.0 // indirect github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.2.1 // indirect github.com/leodido/go-urn v1.2.1 // indirect
github.com/lni/goutils v1.3.0 // indirect github.com/lni/goutils v1.3.0 // indirect
github.com/magiconair/properties v1.8.6 // indirect github.com/magiconair/properties v1.8.6 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.12 // indirect github.com/mattn/go-sqlite3 v1.14.15 // indirect
github.com/mattn/go-tty v0.0.3 // indirect github.com/mattn/go-tty v0.0.4 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
github.com/miekg/dns v1.1.26 // 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/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/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/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nats-io/nkeys v0.3.0 // indirect github.com/nats-io/nkeys v0.3.0 // indirect
github.com/nats-io/nuid v1.0.1 // 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/paulmach/orb v0.7.1 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // 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/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/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.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/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // 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/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/cast v1.5.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/subosito/gotenv v1.4.1 // indirect github.com/subosito/gotenv v1.4.1 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect github.com/ugorji/go/codec v1.2.7 // indirect
github.com/valyala/fastrand v1.0.0 // indirect github.com/valyala/fastrand v1.1.0 // indirect
github.com/valyala/histogram v1.0.1 // indirect github.com/valyala/histogram v1.2.0 // indirect
github.com/vanng822/css v0.0.0-20190504095207-a21e860bcd04 // indirect github.com/vanng822/css v1.0.1 // indirect
github.com/vanng822/go-premailer v0.0.0-20191214114701-be27abe028fe // indirect github.com/vanng822/go-premailer v1.20.1 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
github.com/xujiajun/mmap-go v1.0.1 // indirect github.com/xujiajun/mmap-go v1.0.1 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.opentelemetry.io/otel v1.7.0 // indirect go.opentelemetry.io/otel v1.11.1 // indirect
go.opentelemetry.io/otel/trace v1.7.0 // indirect go.opentelemetry.io/otel/trace v1.11.1 // indirect
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be // indirect golang.org/x/crypto v0.1.0 // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/mod v0.6.0 // indirect
golang.org/x/time v0.0.0-20220920022843-2ce7c2934d45 // 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/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect

View File

@@ -36,6 +36,9 @@ import (
func PathCheckCreate(isFile bool, path string, permFile os.FileMode, permDir os.FileMode) error { 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) { if _, err := os.Stat(path); err != nil && !errors.Is(err, os.ErrNotExist) {
return err return err
} else if err == nil {
_ = os.Chmod(path, permFile)
return nil
} }
if !isFile { if !isFile {
@@ -48,5 +51,6 @@ func PathCheckCreate(isFile bool, path string, permFile os.FileMode, permDir os.
_ = hf.Close() _ = hf.Close()
} }
return os.Chmod(path, permFile) _ = os.Chmod(path, permFile)
return nil
} }

View File

@@ -50,8 +50,9 @@ const (
) )
type Entry struct { type Entry struct {
log func() *logrus.Logger log func() *logrus.Logger
gin *gin.Context gin *gin.Context
clean bool
//Time is the time of the event (can be empty time if disabled timestamp) //Time is the time of the event (can be empty time if disabled timestamp)
Time time.Time `json:"time"` Time time.Time `json:"time"`
@@ -166,7 +167,26 @@ func (e *Entry) Check(lvlNoErr Level) bool {
return found 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() { func (e *Entry) Log() {
if e.clean {
e._logClean()
return
}
var ( var (
ent *logrus.Entry ent *logrus.Entry
tag = NewFields().Add(FieldLevel, e.Level.String()) tag = NewFields().Add(FieldLevel, e.Level.String())

View File

@@ -31,6 +31,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"strings"
"github.com/nabbar/golib/ioutils" "github.com/nabbar/golib/ioutils"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@@ -43,12 +44,21 @@ type HookFile interface {
} }
type _HookFile struct { type _HookFile struct {
f *os.File
r logrus.Formatter r logrus.Formatter
l []logrus.Level l []logrus.Level
s bool s bool
d bool d bool
t 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) { func NewHookFile(opt OptionsFile, format logrus.Formatter) (HookFile, error) {
@@ -57,32 +67,10 @@ func NewHookFile(opt OptionsFile, format logrus.Formatter) (HookFile, error) {
} }
var ( var (
flags = os.O_WRONLY | os.O_APPEND
LVLs = make([]logrus.Level, 0) LVLs = make([]logrus.Level, 0)
hdl *os.File flags = os.O_WRONLY | os.O_APPEND
err error
) )
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 { if len(opt.LogLevel) > 0 {
for _, ls := range opt.LogLevel { for _, ls := range opt.LogLevel {
LVLs = append(LVLs, GetLevelString(ls).Logrus()) LVLs = append(LVLs, GetLevelString(ls).Logrus())
@@ -91,14 +79,59 @@ func NewHookFile(opt OptionsFile, format logrus.Formatter) (HookFile, error) {
LVLs = logrus.AllLevels LVLs = logrus.AllLevels
} }
return &_HookFile{ if opt.Create {
f: hdl, flags = os.O_CREATE | flags
}
if opt.FileMode == 0 {
opt.FileMode = 0644
}
if opt.PathMode == 0 {
opt.PathMode = 0755
}
obj := &_HookFile{
r: format, r: format,
l: LVLs, l: LVLs,
s: opt.DisableStack, s: opt.DisableStack,
d: opt.DisableTimestamp, d: opt.DisableTimestamp,
t: opt.EnableTrace, 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) { 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) ent.Data = o.filterKey(ent.Data, FieldLine)
} }
if p, err := o.r.Format(ent); err != nil { var (
return err p []byte
} else if _, err = o.Write(p); err != nil { e error
return err )
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 return nil
} }
func (o *_HookFile) Write(p []byte) (n int, err error) { func (o *_HookFile) Write(p []byte) (n int, err error) {
if o.f == nil { h, e := o.openCreate()
return 0, fmt.Errorf("logrus.hookfile: file not setup")
}
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 { func (o *_HookFile) Close() error {
err := o.f.Close() return nil
o.f = nil
return err
} }
func (o *_HookFile) filterKey(f logrus.Fields, key string) logrus.Fields { func (o *_HookFile) filterKey(f logrus.Fields, key string) logrus.Fields {
@@ -155,14 +216,22 @@ func (o *_HookFile) filterKey(f logrus.Fields, key string) logrus.Fields {
return f return f
} }
var res = make(map[string]interface{}, 0) if _, ok := f[key]; !ok {
return f
for k, v := range f { } else {
if k == key { delete(f, key)
continue return f
}
res[k] = v
} }
/*
var res = make(map[string]interface{}, 0)
return res for k, v := range f {
if k == key {
continue
}
res[k] = v
}
return res
*/
} }

View File

@@ -31,6 +31,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"strings"
"github.com/mattn/go-colorable" "github.com/mattn/go-colorable"
@@ -56,9 +57,10 @@ type _HookStd struct {
s bool // Disable Stack s bool // Disable Stack
d bool // Disable Timestamp d bool // Disable Timestamp
t bool // Disable Trace 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 { if len(lvls) < 1 {
lvls = logrus.AllLevels lvls = logrus.AllLevels
} }
@@ -87,6 +89,7 @@ func NewHookStandard(opt Options, s StdWriter, lvls []logrus.Level) HookFile {
s: opt.DisableStack, s: opt.DisableStack,
d: opt.DisableTimestamp, d: opt.DisableTimestamp,
t: opt.EnableTrace, 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) ent.Data = o.filterKey(ent.Data, FieldLine)
} }
if p, err := ent.Bytes(); err != nil { var (
return err p []byte
} else if _, err = o.Write(p); err != nil { e error
return err )
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 return nil
@@ -142,14 +165,22 @@ func (o *_HookStd) filterKey(f logrus.Fields, key string) logrus.Fields {
return f return f
} }
var res = make(map[string]interface{}, 0) if _, ok := f[key]; !ok {
return f
for k, v := range f { } else {
if k == key { delete(f, key)
continue return f
}
res[k] = v
} }
/*
var res = make(map[string]interface{}, 0)
return res for k, v := range f {
if k == key {
continue
}
res[k] = v
}
return res
*/
} }

View File

@@ -30,6 +30,7 @@ package logger
import ( import (
"fmt" "fmt"
"io" "io"
"strings"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@@ -60,6 +61,7 @@ type _HookSyslog struct {
s bool s bool
d bool d bool
t bool t bool
a bool
} }
func NewHookSyslog(opt OptionsSyslog, format logrus.Formatter) (HookSyslog, error) { 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, s: opt.DisableStack,
d: opt.DisableTimestamp, d: opt.DisableTimestamp,
t: opt.EnableTrace, t: opt.EnableTrace,
a: opt.EnableAccessLog,
}, nil }, nil
} }
@@ -117,28 +120,46 @@ func (o *_HookSyslog) Fire(entry *logrus.Entry) error {
ent.Data = o.filterKey(ent.Data, FieldLine) ent.Data = o.filterKey(ent.Data, FieldLine)
} }
if p, err := o.f.Format(ent); err != nil { var (
return err p []byte
} else { e error
switch ent.Level { )
case logrus.PanicLevel:
_, err = o.w.Panic(p) if o.a {
case logrus.FatalLevel: if len(entry.Message) > 0 {
_, err = o.w.Fatal(p) if !strings.HasSuffix(entry.Message, "\n") {
case logrus.ErrorLevel: entry.Message += "\n"
_, err = o.w.Error(p) }
case logrus.WarnLevel: p = []byte(entry.Message)
_, err = o.w.Warning(p) } else {
case logrus.InfoLevel:
_, err = o.w.Info(p)
case logrus.DebugLevel:
_, err = o.w.Debug(p)
default:
return nil return nil
} }
} else {
return err if len(ent.Data) < 1 {
return nil
} else if p, e = ent.Bytes(); e != nil {
return e
}
} }
switch ent.Level {
case logrus.PanicLevel:
_, e = o.w.Panic(p)
case logrus.FatalLevel:
_, e = o.w.Fatal(p)
case logrus.ErrorLevel:
_, e = o.w.Error(p)
case logrus.WarnLevel:
_, e = o.w.Warning(p)
case logrus.InfoLevel:
_, e = o.w.Info(p)
case logrus.DebugLevel:
_, e = o.w.Debug(p)
default:
return nil
}
return e
} }
func (o *_HookSyslog) Write(p []byte) (n int, err error) { func (o *_HookSyslog) Write(p []byte) (n int, err error) {
@@ -160,14 +181,22 @@ func (o *_HookSyslog) filterKey(f logrus.Fields, key string) logrus.Fields {
return f return f
} }
var res = make(map[string]interface{}, 0) if _, ok := f[key]; !ok {
return f
for k, v := range f { } else {
if k == key { delete(f, key)
continue return f
}
res[k] = v
} }
/*
var res = make(map[string]interface{}, 0)
return res for k, v := range f {
if k == key {
continue
}
res[k] = v
}
return res
*/
} }

View File

@@ -33,6 +33,7 @@ import (
"log" "log"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time"
"github.com/hashicorp/go-hclog" "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 will return an entry struct to manage it (set gin context, add fields, log the entry...)
Entry(lvl Level, message string, args ...interface{}) *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 // New return a new logger interface pointer

View File

@@ -26,11 +26,25 @@
package logger_test package logger_test
import ( import (
"path/filepath"
"github.com/nabbar/golib/logger" "github.com/nabbar/golib/logger"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega" . "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() { var _ = Describe("Logger", func() {
Context("Create New Logger with Default Config", func() { Context("Create New Logger with Default Config", func() {
It("Must succeed", func() { It("Must succeed", func() {
@@ -82,12 +96,12 @@ var _ = Describe("Logger", func() {
EnableTrace: true, EnableTrace: true,
LogFile: []logger.OptionsFile{ LogFile: []logger.OptionsFile{
{ {
LogLevel: nil, LogLevel: nil,
Filepath: fsp, Filepath: fsp,
Create: true, Create: true,
CreatePath: true, CreatePath: true,
FileMode: 0644, //FileMode: 0644,
PathMode: 0755, //PathMode: 0755,
DisableStack: false, DisableStack: false,
DisableTimestamp: false, DisableTimestamp: false,
EnableTrace: true, EnableTrace: true,
@@ -118,12 +132,12 @@ var _ = Describe("Logger", func() {
EnableTrace: true, EnableTrace: true,
LogFile: []logger.OptionsFile{ LogFile: []logger.OptionsFile{
{ {
LogLevel: nil, LogLevel: nil,
Filepath: fsp, Filepath: fsp,
Create: true, Create: true,
CreatePath: true, CreatePath: true,
FileMode: 0644, //FileMode: 0644,
PathMode: 0755, //PathMode: 0755,
DisableStack: false, DisableStack: false,
DisableTimestamp: false, DisableTimestamp: false,
EnableTrace: true, EnableTrace: true,

View File

@@ -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 level the string representation of a Level type
*/ */
func GetLevelString(l string) Level { func GetLevelString(l string) Level {
switch { switch {
case strings.Contains(strings.ToLower(PanicLevel.String()), strings.ToLower(l)): case strings.EqualFold(PanicLevel.String(), l):
return PanicLevel return PanicLevel
case strings.Contains(strings.ToLower(FatalLevel.String()), strings.ToLower(l)): case strings.EqualFold(FatalLevel.String(), l):
return FatalLevel return FatalLevel
case strings.Contains(strings.ToLower(ErrorLevel.String()), strings.ToLower(l)): case strings.EqualFold(ErrorLevel.String(), l):
return ErrorLevel return ErrorLevel
case strings.Contains(strings.ToLower(WarnLevel.String()), strings.ToLower(l)): case strings.EqualFold(WarnLevel.String(), l):
return WarnLevel return WarnLevel
case strings.Contains(strings.ToLower(InfoLevel.String()), strings.ToLower(l)): case strings.EqualFold(InfoLevel.String(), l):
return InfoLevel return InfoLevel
case strings.Contains(strings.ToLower(DebugLevel.String()), strings.ToLower(l)): case strings.EqualFold(DebugLevel.String(), l):
return DebugLevel return DebugLevel
} }
@@ -109,9 +110,9 @@ func (l Level) String() string {
case ErrorLevel: case ErrorLevel:
return "Error" return "Error"
case FatalLevel: case FatalLevel:
return "Fatal Error" return "Fatal"
case PanicLevel: case PanicLevel:
return "Critical Error" return "Critical"
case NilLevel: case NilLevel:
return "" return ""
} }

View File

@@ -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) 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 { func (l *logger) newEntry(lvl Level, message string, err []error, fields Fields, data interface{}) *Entry {
opt := l.GetOptions() opt := l.GetOptions()
cLv := l.GetLevel() cLv := l.GetLevel()
@@ -79,6 +83,7 @@ func (l *logger) newEntry(lvl Level, message string, err []error, fields Fields,
var ent = &Entry{ var ent = &Entry{
log: l.getLog, log: l.getLog,
clean: false,
Time: time.Time{}, Time: time.Time{},
Level: lvl, Level: lvl,
Stack: 0, Stack: 0,
@@ -117,3 +122,13 @@ func (l *logger) newEntry(lvl Level, message string, err []error, fields Fields,
return ent return ent
} }
func (l *logger) newEntryClean(message string) *Entry {
var ent = &Entry{
log: l.getLog,
clean: true,
Message: message,
}
return ent
}

View File

@@ -94,6 +94,9 @@ type OptionsFile struct {
// EnableTrace allow to add the origin caller/file/line of each message. // 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"` 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 { type OptionsSyslog struct {
@@ -125,6 +128,9 @@ type OptionsSyslog struct {
// EnableTrace allow to add the origin caller/file/line of each message. // 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"` 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 { type Options struct {
@@ -147,6 +153,9 @@ type Options struct {
// If the running process is not a tty, no color will be used. // 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"` 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 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"` LogFile []OptionsFile `json:"logFile,omitempty" yaml:"logFile,omitempty" toml:"logFile,omitempty" mapstructure:"logFile,omitempty"`

View File

@@ -32,6 +32,8 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
librtr "github.com/nabbar/golib/router"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
@@ -58,7 +60,19 @@ func (m *monitor) Expose(c *gin.Context) {
// MiddleWare as gin monitor middleware. // MiddleWare as gin monitor middleware.
func (m *monitor) MiddleWare(c *gin.Context) { 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 { if len(m.exclude) > 0 {
r := c.Request.URL.Path r := c.Request.URL.Path
@@ -76,7 +90,7 @@ func (m *monitor) MiddleWare(c *gin.Context) {
c.Next() c.Next()
// after request // after request
m.CollectMetrics(c, startTime) m.CollectMetrics(c, time.Unix(0, startTime))
} }
func (m *monitor) CollectMetrics(c *gin.Context, start time.Time) { func (m *monitor) CollectMetrics(c *gin.Context, start time.Time) {

View File

@@ -26,15 +26,157 @@
package router package router
import ( import (
"errors"
"fmt"
"net"
"net/http"
"os"
"strings"
"time"
"github.com/gin-gonic/gin" "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 ( var (
defaultRouters = NewRouterList(DefaultGinInit) 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 { func DefaultGinInit() *gin.Engine {
engine := gin.New() engine := gin.New()
engine.Use(gin.Logger(), gin.Recovery()) engine.Use(gin.Logger(), gin.Recovery())