Compare commits

...

7 Commits

25 changed files with 1048 additions and 32 deletions

View File

@@ -0,0 +1,138 @@
## 更新到 golangci-lint@v1.52.2
run:
timeout: 1m
build-tags: [ ]
skip-dirs: [ ]
skip-files: [ ]
linters:
disable-all: true
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- cyclop
- dupl
- durationcheck
- errname
- errorlint
- exhaustive
- exportloopref
- funlen
- gocheckcompilerdirectives
- gochecknoinits
- goconst
- gocritic
- gocyclo
- goimports
- gomnd
- goprintffuncname
- gosec
- lll
- loggercheck
- makezero
- nakedret
- nestif
- nilnil
- noctx
- nolintlint
- nosprintfhostport
- prealloc
- predeclared
- promlinter
- reassign
- revive
- stylecheck
- tenv
- testableexamples
- testpackage
- tparallel
- unconvert
- unparam
- usestdlibvars
- wastedassign
- whitespace
linters-settings:
errcheck:
check-type-assertions: true
exclude-functions: [ ]
govet:
enable-all: true
disable: [ ]
cyclop:
max-complexity: 10
package-average: 0.0
dupl:
threshold: 150
exhaustive:
check:
- switch
- map
funlen:
lines: 100
statements: 60
gocritic:
disabled-checks:
- commentFormatting
settings:
captLocal:
paramsOnly: false
underef:
skipRecvDeref: false
gocyclo:
min-complexity: 20
gomnd:
ignored-functions:
- os.Chmod
- os.Mkdir
- os.MkdirAll
- os.OpenFile
- os.WriteFile
- prometheus.ExponentialBuckets
- prometheus.ExponentialBucketsRange
- prometheus.LinearBuckets
lll:
line-length: 240
nakedret:
max-func-lines: 10
nestif:
min-complexity: 5
predeclared:
ignore: ""
q: false
reassign:
patterns:
- ".*"
tenv:
all: true
usestdlibvars:
time-month: true
time-layout: true
crypto-hash: true
default-rpc-path: true
os-dev-null: true
sql-isolation-level: true
tls-signature-scheme: true
constant-kind: true
syslog-priority: true
issues:
max-same-issues: 10
exclude-rules:
- source: "//noinspection"
linters: [ gocritic ]
- path: "_test\\.go"
linters:
- bodyclose
- dupl
- funlen
- goconst
- gosec
- noctx

View File

@@ -0,0 +1,138 @@
## 更新到 golangci-lint@v1.52.2
run:
timeout: 1m
build-tags: [ ]
skip-dirs: [ ]
skip-files: [ ]
linters:
disable-all: true
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- cyclop
- dupl
- durationcheck
- errname
- errorlint
- exhaustive
- exportloopref
- funlen
- gocheckcompilerdirectives
- gochecknoinits
- goconst
- gocritic
- gocyclo
- goimports
- gomnd
- goprintffuncname
- gosec
- lll
- loggercheck
- makezero
- nakedret
- nestif
- nilnil
- noctx
- nolintlint
- nosprintfhostport
- prealloc
- predeclared
- promlinter
- reassign
- revive
- stylecheck
- tenv
- testableexamples
- testpackage
- tparallel
- unconvert
- unparam
- usestdlibvars
- wastedassign
- whitespace
linters-settings:
errcheck:
check-type-assertions: true
exclude-functions: [ ]
govet:
enable-all: true
disable: [ ]
cyclop:
max-complexity: 10
package-average: 0.0
dupl:
threshold: 150
exhaustive:
check:
- switch
- map
funlen:
lines: 100
statements: 60
gocritic:
disabled-checks:
- commentFormatting
settings:
captLocal:
paramsOnly: false
underef:
skipRecvDeref: false
gocyclo:
min-complexity: 20
gomnd:
ignored-functions:
- os.Chmod
- os.Mkdir
- os.MkdirAll
- os.OpenFile
- os.WriteFile
- prometheus.ExponentialBuckets
- prometheus.ExponentialBucketsRange
- prometheus.LinearBuckets
lll:
line-length: 240
nakedret:
max-func-lines: 10
nestif:
min-complexity: 5
predeclared:
ignore: ""
q: false
reassign:
patterns:
- ".*"
tenv:
all: true
usestdlibvars:
time-month: true
time-layout: true
crypto-hash: true
default-rpc-path: true
os-dev-null: true
sql-isolation-level: true
tls-signature-scheme: true
constant-kind: true
syslog-priority: true
issues:
max-same-issues: 10
exclude-rules:
- source: "//noinspection"
linters: [ gocritic ]
- path: "_test\\.go"
linters:
- bodyclose
- dupl
- funlen
- goconst
- gosec
- noctx

View File

@@ -8,6 +8,7 @@ func WithNoCancel(ctx context.Context) context.Context {
return &noCancelCtx{Context: ctx} return &noCancelCtx{Context: ctx}
} }
//nolint:containedctx
type noCancelCtx struct { type noCancelCtx struct {
context.Context context.Context
} }

141
exegroup/.golangci.yaml Normal file
View File

@@ -0,0 +1,141 @@
## 基于 golangci-lint@v1.52.2
run:
timeout: 1m
build-tags: [ ]
skip-dirs: [ ]
skip-files: [ ]
linters:
disable-all: true
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- cyclop
- dupl
- durationcheck
- errname
- errorlint
- exhaustive
- exportloopref
- funlen
- gocheckcompilerdirectives
- gochecknoinits
- goconst
- gocritic
- gocyclo
- goimports
- gomnd
- goprintffuncname
- gosec
- lll
- loggercheck
- makezero
- nakedret
- nestif
- nilnil
- noctx
- nolintlint
- prealloc
- predeclared
- promlinter
- reassign
- revive
- rowserrcheck
- stylecheck
- tenv
- testableexamples
- testpackage
- tparallel
- unconvert
- unparam
- usestdlibvars
- wastedassign
- whitespace
linters-settings:
errcheck:
check-type-assertions: true
exclude-functions: [ ]
govet:
enable-all: true
disable: [ ]
cyclop:
max-complexity: 10
package-average: 0.0
dupl:
threshold: 150
exhaustive:
check:
- switch
- map
funlen:
lines: 100
statements: 60
gocritic:
disabled-checks:
- commentFormatting
settings:
captLocal:
paramsOnly: false
underef:
skipRecvDeref: false
gocyclo:
min-complexity: 20
gomnd:
ignored-functions:
- os.Chmod
- os.Mkdir
- os.MkdirAll
- os.OpenFile
- os.WriteFile
- prometheus.ExponentialBuckets
- prometheus.ExponentialBucketsRange
- prometheus.LinearBuckets
lll:
line-length: 240
nakedret:
max-func-lines: 10
nestif:
min-complexity: 5
predeclared:
ignore: ""
q: false
reassign:
patterns:
- ".*"
rowserrcheck:
packages:
- github.com/jmoiron/sqlx
tenv:
all: true
usestdlibvars:
time-month: true
time-layout: true
crypto-hash: true
default-rpc-path: true
os-dev-null: true
sql-isolation-level: true
tls-signature-scheme: true
constant-kind: true
syslog-priority: true
issues:
max-same-issues: 10
exclude-rules:
- source: "//noinspection"
linters: [ gocritic ]
- path: "_test\\.go"
linters:
- bodyclose
- dupl
- funlen
- goconst
- gosec
- noctx

View File

@@ -123,8 +123,8 @@ func (g *Group) start(ctx context.Context, c chan error) {
} }
} }
func (g *Group) wait(c chan error, cancel context.CancelFunc) (err error) { func (g *Group) wait(c chan error, cancel context.CancelFunc) error {
err = <-c err := <-c
cancel() cancel()
ctx := context.Background() ctx := context.Background()
if g.cfg.stopTimeout > 0 { if g.cfg.stopTimeout > 0 {
@@ -144,10 +144,10 @@ func (g *Group) wait(c chan error, cancel context.CancelFunc) (err error) {
select { select {
case <-c: case <-c:
case <-ctx.Done(): case <-ctx.Done():
return return err
} }
} }
return return err
} }
type config struct { type config struct {

View File

@@ -14,4 +14,5 @@ func Example_defaultGroup() {
return ctx.Err() return ctx.Err()
}) })
log.Println("exit:", g.Run(context.Background())) log.Println("exit:", g.Run(context.Background()))
// Output:
} }

View File

@@ -2,14 +2,20 @@ package exegroup
import ( import (
"context" "context"
"fmt" "net"
"net/http" "net/http"
"strconv"
"sync/atomic" "sync/atomic"
"time"
) )
// HttpListenAndServe 提供 [http.Server] 的启动和停止函数; // HTTPListenAndServe 提供 [http.Server] 的启动和停止函数;
func HttpListenAndServe(port int, handler http.Handler) (func(ctx context.Context) error, func(ctx context.Context)) { func HTTPListenAndServe(port int, handler http.Handler) (func(ctx context.Context) error, func(ctx context.Context)) {
server := &http.Server{Addr: fmt.Sprintf(":%d", port), Handler: handler} server := &http.Server{
Addr: net.JoinHostPort("", strconv.Itoa(port)),
Handler: handler,
ReadHeaderTimeout: time.Second,
}
inShutdown := &atomic.Bool{} inShutdown := &atomic.Bool{}
c := make(chan error, 1) c := make(chan error, 1)
goFunc := func(_ context.Context) error { goFunc := func(_ context.Context) error {

141
log/.golangci.yaml Normal file
View File

@@ -0,0 +1,141 @@
## 基于 golangci-lint@v1.52.2
run:
timeout: 1m
build-tags: [ ]
skip-dirs: [ ]
skip-files: [ ]
linters:
disable-all: true
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- cyclop
- dupl
- durationcheck
- errname
- errorlint
- exhaustive
- exportloopref
- funlen
- gocheckcompilerdirectives
- gochecknoinits
- goconst
- gocritic
- gocyclo
- goimports
- gomnd
- goprintffuncname
- gosec
- lll
- loggercheck
- makezero
- nakedret
- nestif
- nilnil
- noctx
- nolintlint
- prealloc
- predeclared
- promlinter
- reassign
- revive
- rowserrcheck
- stylecheck
- tenv
- testableexamples
- testpackage
- tparallel
- unconvert
- unparam
- usestdlibvars
- wastedassign
- whitespace
linters-settings:
errcheck:
check-type-assertions: true
exclude-functions: [ ]
govet:
enable-all: true
disable: [ ]
cyclop:
max-complexity: 10
package-average: 0.0
dupl:
threshold: 150
exhaustive:
check:
- switch
- map
funlen:
lines: 100
statements: 60
gocritic:
disabled-checks:
- commentFormatting
settings:
captLocal:
paramsOnly: false
underef:
skipRecvDeref: false
gocyclo:
min-complexity: 20
gomnd:
ignored-functions:
- os.Chmod
- os.Mkdir
- os.MkdirAll
- os.OpenFile
- os.WriteFile
- prometheus.ExponentialBuckets
- prometheus.ExponentialBucketsRange
- prometheus.LinearBuckets
lll:
line-length: 240
nakedret:
max-func-lines: 10
nestif:
min-complexity: 5
predeclared:
ignore: ""
q: false
reassign:
patterns:
- ".*"
rowserrcheck:
packages:
- github.com/jmoiron/sqlx
tenv:
all: true
usestdlibvars:
time-month: true
time-layout: true
crypto-hash: true
default-rpc-path: true
os-dev-null: true
sql-isolation-level: true
tls-signature-scheme: true
constant-kind: true
syslog-priority: true
issues:
max-same-issues: 10
exclude-rules:
- source: "//noinspection"
linters: [ gocritic ]
- path: "_test\\.go"
linters:
- bodyclose
- dupl
- funlen
- goconst
- gosec
- noctx

View File

@@ -37,7 +37,7 @@ func (entry Entry) AddCallerSkip(n int) Entry {
// WithField 增加1组键值对 // WithField 增加1组键值对
func (entry Entry) WithField(key string, value any) Entry { func (entry Entry) WithField(key string, value any) Entry {
return entry.WithFields(KV{Key: key, Value: value}) return entry.WithFields(Field(key, value))
} }
// WithFields 增加键值对 // WithFields 增加键值对
@@ -198,7 +198,7 @@ func (entry Entry) log(ctx context.Context, level Level, message string) {
readonlyEntry.Caller = getCaller(newEntry.callerSkip) readonlyEntry.Caller = getCaller(newEntry.callerSkip)
} }
if newEntry.GetReportStack() || level <= newEntry.logger.GetReportStackLevel() { if newEntry.GetReportStack() || level <= newEntry.logger.GetReportStackLevel() {
readonlyEntry.Stack = getStack(newEntry.callerSkip, 32) readonlyEntry.Stack = getStack(newEntry.callerSkip, maximumFrames)
} }
for _, processor := range newEntry.logger.getLevelProcessors(level) { for _, processor := range newEntry.logger.getLevelProcessors(level) {
processor.Process(ctx, readonlyEntry) processor.Process(ctx, readonlyEntry)

View File

@@ -3,13 +3,15 @@ package logsdk
// Field 返回键值对 // Field 返回键值对
func Field(key string, value any) KV { func Field(key string, value any) KV {
return KV{ return KV{
Value: value,
Key: key, Key: key,
Value: value,
} }
} }
// KV 是日志记录中的键值对 // KV 是日志记录中的键值对
//
//nolint:govet
type KV struct { type KV struct {
Value any `json:"v"`
Key string `json:"k"` Key string `json:"k"`
Value any `json:"v"`
} }

View File

@@ -28,6 +28,8 @@ func (level Level) MarshalText() ([]byte, error) {
return []byte(LevelDebugValue), nil return []byte(LevelDebugValue), nil
case LevelTrace: case LevelTrace:
return []byte(LevelTraceValue), nil return []byte(LevelTraceValue), nil
case LevelDisabled:
return []byte(levelDisabledValue), nil
} }
return nil, fmt.Errorf("not a valid log level %d", level) return nil, fmt.Errorf("not a valid log level %d", level)
} }
@@ -61,6 +63,8 @@ const (
LevelInfoValue = "info" LevelInfoValue = "info"
LevelDebugValue = "debug" LevelDebugValue = "debug"
LevelTraceValue = "trace" LevelTraceValue = "trace"
levelDisabledValue = "disabled"
) )
var AllLevels = []Level{ var AllLevels = []Level{

View File

@@ -111,11 +111,12 @@ func (logger *Logger) Reset() {
// Exit 退出程序, 执行的具体过程可以通过 SetExit 指定 // Exit 退出程序, 执行的具体过程可以通过 SetExit 指定
func (logger *Logger) Exit(code int) { func (logger *Logger) Exit(code int) {
logger.lock.RLock() logger.lock.RLock()
defer logger.lock.RUnlock() exit := logger.exit
if logger.exit == nil { logger.lock.RUnlock()
if exit == nil {
os.Exit(code) os.Exit(code)
} }
logger.exit(code) exit(code)
} }
// SetExit 指定退出程序时执行的函数 // SetExit 指定退出程序时执行的函数
@@ -134,7 +135,7 @@ func (logger *Logger) getLevelProcessors(level Level) []EntryProcessor {
func (logger *Logger) newEntry() Entry { func (logger *Logger) newEntry() Entry {
return Entry{ return Entry{
logger: logger, logger: logger,
callerSkip: logger.GetCallerSkip() + 2, callerSkip: logger.GetCallerSkip() + entrySkipOffset,
reportCaller: logger.GetReportCaller(), reportCaller: logger.GetReportCaller(),
reportStack: logger.GetReportStack(), reportStack: logger.GetReportStack(),
initialized: true, initialized: true,

View File

@@ -60,7 +60,7 @@ func newConfig(opts ...Option) *config {
opt.apply(cfg) opt.apply(cfg)
} }
if !cfg.hasPool { if !cfg.hasPool {
cfg.bytesBufferPool = NewBytesBufferPool(512, 4096) cfg.bytesBufferPool = NewBytesBufferPool(bytesBufferInitialSize, bytesBufferMaximumSize)
} }
if cfg.output == nil { if cfg.output == nil {
cfg.output = NewSyncWriter(os.Stderr) cfg.output = NewSyncWriter(os.Stderr)

View File

@@ -5,6 +5,11 @@ import (
"sync" "sync"
) )
const (
bytesBufferInitialSize = 512
bytesBufferMaximumSize = 4096
)
type BytesBufferPool interface { type BytesBufferPool interface {
Get() *bytes.Buffer Get() *bytes.Buffer
Put(buffer *bytes.Buffer) Put(buffer *bytes.Buffer)

View File

@@ -18,7 +18,7 @@ type syncWriter struct {
lock sync.Mutex lock sync.Mutex
} }
func (w *syncWriter) Write(p []byte) (n int, err error) { func (w *syncWriter) Write(p []byte) (int, error) {
w.lock.Lock() w.lock.Lock()
defer w.lock.Unlock() defer w.lock.Unlock()
return w.writer.Write(p) return w.writer.Write(p)

View File

@@ -4,6 +4,12 @@ import (
"runtime" "runtime"
) )
const (
maximumFrames = 32
getCallerSkipOffset = 2
entrySkipOffset = 2
)
// Frame 调用相关信息 // Frame 调用相关信息
type Frame struct { type Frame struct {
Function string `json:"func"` Function string `json:"func"`
@@ -18,7 +24,7 @@ func (frame Frame) IsValid() bool {
func getCaller(skip int) Frame { func getCaller(skip int) Frame {
pc := make([]uintptr, 1) pc := make([]uintptr, 1)
n := runtime.Callers(skip+2, pc) n := runtime.Callers(skip+getCallerSkipOffset, pc)
frame, _ := runtime.CallersFrames(pc[:n]).Next() frame, _ := runtime.CallersFrames(pc[:n]).Next()
if frame.PC == 0 { if frame.PC == 0 {
return Frame{} return Frame{}
@@ -32,7 +38,7 @@ func getCaller(skip int) Frame {
func getStack(skip, maximumFrames int) []Frame { func getStack(skip, maximumFrames int) []Frame {
pc := make([]uintptr, maximumFrames) pc := make([]uintptr, maximumFrames)
n := runtime.Callers(skip+2, pc) n := runtime.Callers(skip+getCallerSkipOffset, pc)
stack := make([]Frame, 0, n) stack := make([]Frame, 0, n)
frames := runtime.CallersFrames(pc[:n]) frames := runtime.CallersFrames(pc[:n])
for { for {

141
logotel/.golangci.yaml Normal file
View File

@@ -0,0 +1,141 @@
## 基于 golangci-lint@v1.52.2
run:
timeout: 1m
build-tags: [ ]
skip-dirs: [ ]
skip-files: [ ]
linters:
disable-all: true
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- cyclop
- dupl
- durationcheck
- errname
- errorlint
- exhaustive
- exportloopref
- funlen
- gocheckcompilerdirectives
- gochecknoinits
- goconst
- gocritic
- gocyclo
- goimports
- gomnd
- goprintffuncname
- gosec
- lll
- loggercheck
- makezero
- nakedret
- nestif
- nilnil
- noctx
- nolintlint
- prealloc
- predeclared
- promlinter
- reassign
- revive
- rowserrcheck
- stylecheck
- tenv
- testableexamples
- testpackage
- tparallel
- unconvert
- unparam
- usestdlibvars
- wastedassign
- whitespace
linters-settings:
errcheck:
check-type-assertions: true
exclude-functions: [ ]
govet:
enable-all: true
disable: [ ]
cyclop:
max-complexity: 10
package-average: 0.0
dupl:
threshold: 150
exhaustive:
check:
- switch
- map
funlen:
lines: 100
statements: 60
gocritic:
disabled-checks:
- commentFormatting
settings:
captLocal:
paramsOnly: false
underef:
skipRecvDeref: false
gocyclo:
min-complexity: 20
gomnd:
ignored-functions:
- os.Chmod
- os.Mkdir
- os.MkdirAll
- os.OpenFile
- os.WriteFile
- prometheus.ExponentialBuckets
- prometheus.ExponentialBucketsRange
- prometheus.LinearBuckets
lll:
line-length: 240
nakedret:
max-func-lines: 10
nestif:
min-complexity: 5
predeclared:
ignore: ""
q: false
reassign:
patterns:
- ".*"
rowserrcheck:
packages:
- github.com/jmoiron/sqlx
tenv:
all: true
usestdlibvars:
time-month: true
time-layout: true
crypto-hash: true
default-rpc-path: true
os-dev-null: true
sql-isolation-level: true
tls-signature-scheme: true
constant-kind: true
syslog-priority: true
issues:
max-same-issues: 10
exclude-rules:
- source: "//noinspection"
linters: [ gocritic ]
- path: "_test\\.go"
linters:
- bodyclose
- dupl
- funlen
- goconst
- gosec
- noctx

View File

@@ -3,7 +3,7 @@ module git.blauwelle.com/go/crate/logotel
go 1.20 go 1.20
require ( require (
git.blauwelle.com/go/crate/log v0.8.0 git.blauwelle.com/go/crate/log v0.9.0
go.opentelemetry.io/otel v1.13.0 go.opentelemetry.io/otel v1.13.0
go.opentelemetry.io/otel/trace v1.13.0 go.opentelemetry.io/otel/trace v1.13.0
) )

View File

@@ -1,5 +1,5 @@
git.blauwelle.com/go/crate/log v0.8.0 h1:TINzuFo330MZIagzdULouwBoLCcLIB4yjI/G1IH0I+0= git.blauwelle.com/go/crate/log v0.9.0 h1:H01AQIKcYybeCZGdReBzMoWhkXPQJAoY1t+K0J1asEk=
git.blauwelle.com/go/crate/log v0.8.0/go.mod h1:jfVfpRODZTA70A8IkApVeGsS1zfLk1D77sLWZM/w+L0= git.blauwelle.com/go/crate/log v0.9.0/go.mod h1:jfVfpRODZTA70A8IkApVeGsS1zfLk1D77sLWZM/w+L0=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

View File

@@ -4,13 +4,18 @@ import (
"git.blauwelle.com/go/crate/log/logsdk/logjson" "git.blauwelle.com/go/crate/log/logsdk/logjson"
) )
const (
bytesBufferInitialSize = 512
bytesBufferMaximumSize = 4096
)
func newConfig(opts ...Option) *config { func newConfig(opts ...Option) *config {
cfg := defaultConfig() cfg := defaultConfig()
for _, opt := range opts { for _, opt := range opts {
opt.apply(cfg) opt.apply(cfg)
} }
if !cfg.hasPool { if !cfg.hasPool {
cfg.bytesBufferPool = logjson.NewBytesBufferPool(512, 4096) cfg.bytesBufferPool = logjson.NewBytesBufferPool(bytesBufferInitialSize, bytesBufferMaximumSize)
} }
return cfg return cfg
} }

View File

@@ -36,7 +36,8 @@ func (processor *Processor) Process(ctx context.Context, entry logsdk.ReadonlyEn
return return
} }
attrs := make([]attribute.KeyValue, 0, len(entry.Fields)+6) const entryInitSize = 6
attrs := make([]attribute.KeyValue, 0, len(entry.Fields)+entryInitSize)
attrs = append(attrs, attribute.String("log.severity", entry.Level.String())) attrs = append(attrs, attribute.String("log.severity", entry.Level.String()))
attrs = append(attrs, attribute.String("log.message", entry.Message)) attrs = append(attrs, attribute.String("log.message", entry.Message))
if entry.Caller.IsValid() { if entry.Caller.IsValid() {

138
mapset/.golangci.yaml Normal file
View File

@@ -0,0 +1,138 @@
## 更新到 golangci-lint@v1.52.2
run:
timeout: 1m
build-tags: [ ]
skip-dirs: [ ]
skip-files: [ ]
linters:
disable-all: true
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- cyclop
- dupl
- durationcheck
- errname
- errorlint
- exhaustive
- exportloopref
- funlen
- gocheckcompilerdirectives
- gochecknoinits
- goconst
- gocritic
- gocyclo
- goimports
- gomnd
- goprintffuncname
- gosec
- lll
- loggercheck
- makezero
- nakedret
- nestif
- nilnil
- noctx
- nolintlint
- nosprintfhostport
- prealloc
- predeclared
- promlinter
- reassign
- revive
- stylecheck
- tenv
- testableexamples
- testpackage
- tparallel
- unconvert
- unparam
- usestdlibvars
- wastedassign
- whitespace
linters-settings:
errcheck:
check-type-assertions: true
exclude-functions: [ ]
govet:
enable-all: true
disable: [ ]
cyclop:
max-complexity: 10
package-average: 0.0
dupl:
threshold: 150
exhaustive:
check:
- switch
- map
funlen:
lines: 100
statements: 60
gocritic:
disabled-checks:
- commentFormatting
settings:
captLocal:
paramsOnly: false
underef:
skipRecvDeref: false
gocyclo:
min-complexity: 20
gomnd:
ignored-functions:
- os.Chmod
- os.Mkdir
- os.MkdirAll
- os.OpenFile
- os.WriteFile
- prometheus.ExponentialBuckets
- prometheus.ExponentialBucketsRange
- prometheus.LinearBuckets
lll:
line-length: 240
nakedret:
max-func-lines: 10
nestif:
min-complexity: 5
predeclared:
ignore: ""
q: false
reassign:
patterns:
- ".*"
tenv:
all: true
usestdlibvars:
time-month: true
time-layout: true
crypto-hash: true
default-rpc-path: true
os-dev-null: true
sql-isolation-level: true
tls-signature-scheme: true
constant-kind: true
syslog-priority: true
issues:
max-same-issues: 10
exclude-rules:
- source: "//noinspection"
linters: [ gocritic ]
- path: "_test\\.go"
linters:
- bodyclose
- dupl
- funlen
- goconst
- gosec
- noctx

View File

@@ -7,6 +7,10 @@ import (
"strings" "strings"
) )
const (
maximumItemToPrint = 64
)
// New 返回 [MapSet] // New 返回 [MapSet]
func New[T comparable](keys ...T) MapSet[T] { func New[T comparable](keys ...T) MapSet[T] {
s := make(MapSet[T], len(keys)) s := make(MapSet[T], len(keys))
@@ -267,8 +271,8 @@ func (s *MapSet[T]) UnmarshalJSON(b []byte) error {
func (s MapSet[T]) String() string { func (s MapSet[T]) String() string {
size := s.Cardinality() size := s.Cardinality()
if size > 64 { if size > maximumItemToPrint {
size = 64 size = maximumItemToPrint
} }
keys := make([]string, 0, size) keys := make([]string, 0, size)
for key := range s { for key := range s {

View File

@@ -0,0 +1,138 @@
## 更新到 golangci-lint@v1.52.2
run:
timeout: 1m
build-tags: [ ]
skip-dirs: [ ]
skip-files: [ ]
linters:
disable-all: true
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- cyclop
- dupl
- durationcheck
- errname
- errorlint
- exhaustive
- exportloopref
- funlen
- gocheckcompilerdirectives
- gochecknoinits
- goconst
- gocritic
- gocyclo
- goimports
- gomnd
- goprintffuncname
- gosec
- lll
- loggercheck
- makezero
- nakedret
- nestif
- nilnil
- noctx
- nolintlint
- nosprintfhostport
- prealloc
- predeclared
- promlinter
- reassign
- revive
- stylecheck
- tenv
- testableexamples
- testpackage
- tparallel
- unconvert
- unparam
- usestdlibvars
- wastedassign
- whitespace
linters-settings:
errcheck:
check-type-assertions: true
exclude-functions: [ ]
govet:
enable-all: true
disable: [ ]
cyclop:
max-complexity: 10
package-average: 0.0
dupl:
threshold: 150
exhaustive:
check:
- switch
- map
funlen:
lines: 100
statements: 60
gocritic:
disabled-checks:
- commentFormatting
settings:
captLocal:
paramsOnly: false
underef:
skipRecvDeref: false
gocyclo:
min-complexity: 20
gomnd:
ignored-functions:
- os.Chmod
- os.Mkdir
- os.MkdirAll
- os.OpenFile
- os.WriteFile
- prometheus.ExponentialBuckets
- prometheus.ExponentialBucketsRange
- prometheus.LinearBuckets
lll:
line-length: 240
nakedret:
max-func-lines: 10
nestif:
min-complexity: 5
predeclared:
ignore: ""
q: false
reassign:
patterns:
- ".*"
tenv:
all: true
usestdlibvars:
time-month: true
time-layout: true
crypto-hash: true
default-rpc-path: true
os-dev-null: true
sql-isolation-level: true
tls-signature-scheme: true
constant-kind: true
syslog-priority: true
issues:
max-same-issues: 10
exclude-rules:
- source: "//noinspection"
linters: [ gocritic ]
- path: "_test\\.go"
linters:
- bodyclose
- dupl
- funlen
- goconst
- gosec
- noctx

View File

@@ -6,6 +6,11 @@ import (
"runtime" "runtime"
) )
const (
callerSkipOffset = 2
maximumFrames = 32
)
// Frame 调用相关信息 // Frame 调用相关信息
type Frame struct { type Frame struct {
Function string `json:"func"` Function string `json:"func"`
@@ -38,7 +43,7 @@ func (frame Frame) SplitFunction() (string, string) {
// skip=0 表示调用 Caller 处. // skip=0 表示调用 Caller 处.
func Caller(skip int) Frame { func Caller(skip int) Frame {
pc := make([]uintptr, 1) pc := make([]uintptr, 1)
n := runtime.Callers(skip+2, pc) n := runtime.Callers(skip+callerSkipOffset, pc)
frame, _ := runtime.CallersFrames(pc[:n]).Next() frame, _ := runtime.CallersFrames(pc[:n]).Next()
if frame.PC == 0 { if frame.PC == 0 {
return Frame{} return Frame{}
@@ -54,7 +59,7 @@ func Caller(skip int) Frame {
// skip=0 表示调用 Stack 处. // skip=0 表示调用 Stack 处.
func Stack(skip, maximumFrames int) []Frame { func Stack(skip, maximumFrames int) []Frame {
pc := make([]uintptr, maximumFrames) pc := make([]uintptr, maximumFrames)
n := runtime.Callers(skip+2, pc) n := runtime.Callers(skip+callerSkipOffset, pc)
stack := make([]Frame, 0, n) stack := make([]Frame, 0, n)
frames := runtime.CallersFrames(pc[:n]) frames := runtime.CallersFrames(pc[:n])
for { for {
@@ -82,7 +87,7 @@ func Stack(skip, maximumFrames int) []Frame {
// 可以使用 [runtime.Frame.PC] != 0 判断 runtime.Frame 有效 // 可以使用 [runtime.Frame.PC] != 0 判断 runtime.Frame 有效
func CallerFrame(skip int) runtime.Frame { func CallerFrame(skip int) runtime.Frame {
pc := make([]uintptr, 1) pc := make([]uintptr, 1)
n := runtime.Callers(skip+2, pc) n := runtime.Callers(skip+callerSkipOffset, pc)
frame, _ := runtime.CallersFrames(pc[:n]).Next() frame, _ := runtime.CallersFrames(pc[:n]).Next()
return frame return frame
} }
@@ -95,14 +100,14 @@ func CallerFrame(skip int) runtime.Frame {
// - 0: 调用 CallersFrames 处 // - 0: 调用 CallersFrames 处
func CallersFrames(skip, maximumFrames int) *runtime.Frames { func CallersFrames(skip, maximumFrames int) *runtime.Frames {
pc := make([]uintptr, maximumFrames) pc := make([]uintptr, maximumFrames)
n := runtime.Callers(skip+2, pc) n := runtime.Callers(skip+callerSkipOffset, pc)
return runtime.CallersFrames(pc[:n]) return runtime.CallersFrames(pc[:n])
} }
// PrintCallersFrames 打印函数调用栈, // PrintCallersFrames 打印函数调用栈,
// 从调用 PrintCallersFrames 的地方开始打印 // 从调用 PrintCallersFrames 的地方开始打印
func PrintCallersFrames() { func PrintCallersFrames() {
frames := CallersFrames(3, 32) frames := CallersFrames(callerSkipOffset+1, maximumFrames)
for { for {
frame, more := frames.Next() frame, more := frames.Next()
if frame.PC != 0 { if frame.PC != 0 {