diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index a0f1510..0506a70 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -12,7 +12,7 @@ jobs: uses: golangci/golangci-lint-action@v2 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.59 + version: v1.63.4 # Optional: working directory, useful for monorepos # working-directory: somedir diff --git a/.golangci.yml b/.golangci.yml index 183c6ec..ecf1ba8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -20,6 +20,7 @@ linters-settings: excludes: - G108 - G114 + - G115 revive: rules: - name: unused-parameter @@ -33,7 +34,6 @@ linters-settings: - github.com/getsentry/sentry-go - github.com/gin-gonic/gin - github.com/nikandfor/assert - - github.com/nikandfor/hacked - github.com/opentracing/opentracing-go - github.com/prometheus/client_golang - github.com/prometheus/client_model @@ -41,8 +41,10 @@ linters-settings: - github.com/stretchr/testify/require - go.opentelemetry.io/otel - golang.org/x + - nikand.dev/go/cbor - nikand.dev/go/cli - nikand.dev/go/graceful + - nikand.dev/go/hacked - tlog.app/go/eazy - tlog.app/go/errors - tlog.app/go/loc @@ -74,6 +76,8 @@ linters: enable-all: true disable: - cyclop + - dogsled + - err113 - exhaustive - exhaustivestruct - exhaustruct @@ -86,15 +90,16 @@ linters: - goconst - gocyclo - godox - - err113 - golint - gomnd - - mnd + - gosmopolitan - ifshort + - inamedparam - ireturn - lll - maintidx - maligned + - mnd - nakedret - nestif - nlreturn @@ -103,6 +108,9 @@ linters: - paralleltest - prealloc - predeclared + - recvcheck + - tagalign + - testifylint - testpackage - thelper - typecheck diff --git a/agent/agent.go b/agent/agent.go index 360d8d2..fc1929b 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -30,7 +30,7 @@ type ( subs []sub streams []*stream - files []*file + // files []*file // end of mu @@ -202,7 +202,7 @@ func (a *Agent) writeFile(s *stream, f *file, p []byte, ts int64) (n int, err er tlog.Printw("write message", "i", geti(p)) s.zbuf = s.zbuf[:0] - n, err = s.z.Write(p) + _, err = s.z.Write(p) if err != nil { return 0, errors.Wrap(err, "eazy") } @@ -248,7 +248,7 @@ func (a *Agent) writeFile(s *stream, f *file, p []byte, ts int64) (n int, err er if s.boff == 0 { s.zbuf = s.zbuf[:0] - n, err = s.z.Write(p) + _, err = s.z.Write(p) if err != nil { return 0, errors.Wrap(err, "eazy") } @@ -307,13 +307,13 @@ func (a *Agent) newFile(s *stream, part, ts int64) (*file, error) { } func (a *Agent) padFile(s *stream, f *file) error { - if f.off%int64(a.BlockSize) == 0 { + if f.off%a.BlockSize == 0 { s.boff = 0 return nil } - off := f.off + int64(a.BlockSize) - f.off%int64(a.BlockSize) + off := f.off + a.BlockSize - f.off%a.BlockSize if s, ok := f.w.(interface { Truncate(int64) error diff --git a/console.go b/console.go index a0ada2e..ceab316 100644 --- a/console.go +++ b/console.go @@ -726,14 +726,15 @@ func (w *ConsoleWriter) ConvertValue(b, p []byte, st, ff int) (_ []byte, i int) } } - if quote && haveQuotes && !haveBackQuotes && w.QuoteUseBackQuotes { + switch { + case quote && haveQuotes && !haveBackQuotes && w.QuoteUseBackQuotes: b = append(b, '`') b = append(b, s...) b = append(b, '`') - } else if quote { + case quote: ss := tlow.UnsafeBytesToString(s) b = strconv.AppendQuote(b, ss) - } else { + default: b = append(b, s...) } @@ -918,6 +919,7 @@ func (w *ConsoleWriter) AppendDuration(b []byte, d time.Duration) []byte { d = add(d, time.Hour, 'h') d = add(d, time.Minute, 'm') d = add(d, time.Second, 's') + _ = d return append(b, buf[:i]...) } diff --git a/convert/json.go b/convert/json.go index f3ebad9..4ca49ec 100644 --- a/convert/json.go +++ b/convert/json.go @@ -253,26 +253,7 @@ func (w *JSON) ConvertValue(b, p []byte, st int) (_ []byte, i int) { id.FormatTo(b, bst, 'u') case tlwire.Caller: - var pc loc.PC - var pcs loc.PCs - pc, pcs, i = w.d.Callers(p, st) - - if pcs != nil { - b = append(b, '[') - for i, pc := range pcs { - if i != 0 { - b = append(b, ',') - } - - _, file, line := pc.NameFileLine() - b = fmt.Appendf(b, `"%v:%d"`, filepath.Base(file), line) - } - b = append(b, ']') - } else { - _, file, line := pc.NameFileLine() - - b = fmt.Appendf(b, `"%v:%d"`, filepath.Base(file), line) - } + b, i = appendCallers(b, p, st, w.d) default: b, i = w.ConvertValue(b, p, i) } @@ -337,3 +318,28 @@ func (r SimpleRenamer) fallback(b, p, k []byte, i int) ([]byte, bool) { return r.Fallback(b, p, k, i) } + +func appendCallers(b, p []byte, st int, d tlwire.Decoder) ([]byte, int) { + var pc loc.PC + var pcs loc.PCs + pc, pcs, i := d.Callers(p, st) + + if pcs != nil { + b = append(b, '[') + for i, pc := range pcs { + if i != 0 { + b = append(b, ',') + } + + _, file, line := pc.NameFileLine() + b = fmt.Appendf(b, `"%v:%d"`, filepath.Base(file), line) + } + b = append(b, ']') + } else { + _, file, line := pc.NameFileLine() + + b = fmt.Appendf(b, `"%v:%d"`, filepath.Base(file), line) + } + + return b, i +} diff --git a/convert/logfmt.go b/convert/logfmt.go index dca9eb4..d3da8f1 100644 --- a/convert/logfmt.go +++ b/convert/logfmt.go @@ -4,13 +4,11 @@ import ( "errors" "fmt" "io" - "path/filepath" "strconv" "time" "golang.org/x/term" "nikand.dev/go/hacked/low" - "tlog.app/go/loc" "tlog.app/go/tlog" tlow "tlog.app/go/tlog/low" @@ -259,26 +257,7 @@ func (w *Logfmt) ConvertValue(b, p, k []byte, st int) (_ []byte, i int) { id.FormatTo(b, bst, 'u') case tlwire.Caller: - var pc loc.PC - var pcs loc.PCs - pc, pcs, i = w.d.Callers(p, st) - - if pcs != nil { - b = append(b, '[') - for i, pc := range pcs { - if i != 0 { - b = append(b, ',') - } - - _, file, line := pc.NameFileLine() - b = fmt.Appendf(b, `"%v:%d"`, filepath.Base(file), line) - } - b = append(b, ']') - } else { - _, file, line := pc.NameFileLine() - - b = fmt.Appendf(b, `"%v:%d"`, filepath.Base(file), line) - } + b, i = appendCallers(b, p, st, w.d) default: b, i = w.ConvertValue(b, p, k, i) } diff --git a/convert/logfmt_test.go b/convert/logfmt_test.go index c7d0dd6..21a191a 100644 --- a/convert/logfmt_test.go +++ b/convert/logfmt_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" - "nikand.dev/go/hacked/low" "github.com/stretchr/testify/assert" + "nikand.dev/go/hacked/low" "tlog.app/go/tlog" "tlog.app/go/tlog/tlwire" diff --git a/convert/web.go b/convert/web.go index 5e8ac88..b143c15 100644 --- a/convert/web.go +++ b/convert/web.go @@ -25,12 +25,9 @@ type ( PickMessage bool d tlwire.Decoder - l Logfmt - j JSON c *tlog.ConsoleWriter s []tlog.ID - m []byte time, last []byte diff --git a/ext/tlflag/flag_test.go b/ext/tlflag/flag_test.go index 50c8e1b..e86ba7c 100644 --- a/ext/tlflag/flag_test.go +++ b/ext/tlflag/flag_test.go @@ -113,8 +113,6 @@ func TestURLWriter(t *testing.T) { //nolint:dupl func TestRotatedWriter(t *testing.T) { OpenFileWriter = TestingFileOpener - const CompressorBlockSize = 1 * eazy.MiB - with := func(f *rotating.File, wrap func(*rotating.File)) *rotating.File { wrap(f) diff --git a/id_test.go b/id_test.go index 4188f0d..223cae2 100644 --- a/id_test.go +++ b/id_test.go @@ -42,7 +42,7 @@ func TestIDJSON(t *testing.T) { data, err := json.Marshal(id) assert.NoError(t, err) - t.Logf("json encoded id: %s (% x)", data, []byte(id[:])) + t.Logf("json encoded id: %s (% x)", data, id[:]) var back ID err = json.Unmarshal(data, &back) diff --git a/rotating/ctime_darwin.go b/rotating/ctime_darwin.go index c0794c5..97ff418 100644 --- a/rotating/ctime_darwin.go +++ b/rotating/ctime_darwin.go @@ -6,15 +6,6 @@ import ( "time" ) -func fileCtime(fstat func(string) (fs.FileInfo, error), name string, now time.Time) time.Time { - inf, err := fstat(name) - if err != nil { - return now - } - - return ctime(inf, now) -} - func ctime(inf fs.FileInfo, now time.Time) time.Time { stat, ok := inf.Sys().(*syscall.Stat_t) if !ok { diff --git a/rotating/ctime_linux.go b/rotating/ctime_linux.go index 87fabe1..57ca8df 100644 --- a/rotating/ctime_linux.go +++ b/rotating/ctime_linux.go @@ -6,15 +6,6 @@ import ( "time" ) -func fileCtime(fstat func(string) (fs.FileInfo, error), name string, now time.Time) time.Time { - inf, err := fstat(name) - if err != nil { - return now - } - - return ctime(inf, now) -} - func ctime(inf fs.FileInfo, now time.Time) time.Time { stat, ok := inf.Sys().(*syscall.Stat_t) if !ok { diff --git a/rotating/ctime_windows.go b/rotating/ctime_windows.go index 6cdfe4f..93e39ab 100644 --- a/rotating/ctime_windows.go +++ b/rotating/ctime_windows.go @@ -6,15 +6,6 @@ import ( "time" ) -func fileCtime(fstat func(string) (fs.FileInfo, error), name string, now time.Time) time.Time { - inf, err := fstat(name) - if err != nil { - return now - } - - return ctime(inf, now) -} - func ctime(inf fs.FileInfo, now time.Time) time.Time { stat, ok := inf.Sys().(*syscall.Win32FileAttributeData) if !ok { diff --git a/rotating/file.go b/rotating/file.go index 6014198..46b859e 100644 --- a/rotating/file.go +++ b/rotating/file.go @@ -110,7 +110,7 @@ func (f *File) Write(p []byte) (n int, err error) { if f.w == nil || f.size != 0 && (f.MaxFileSize != 0 && f.size+int64(len(p)) > f.MaxFileSize || - f.MaxFileAge != 0 && time.Since(f.start) > f.MaxFileAge) { + f.MaxFileAge != 0 && time.Since(f.start) > f.MaxFileAge) { //nolint:whitespace err = f.rotate() if err != nil { @@ -163,7 +163,6 @@ func (f *File) rotate() (err error) { f.current = fname f.size = 0 f.start = now - // f.start = fileCtime(f.fstat, fname, now) if f.symlink != nil { link := filepath.Join(f.dir, f.pref+"LATEST"+f.suff) @@ -173,7 +172,9 @@ func (f *File) rotate() (err error) { } if f.MaxTotalSize != 0 || f.MaxTotalAge != 0 || f.MaxTotalFiles != 0 { - go f.removeOld(f.dir, base, f.pref, f.suff, f.format, f.start) + go func(start time.Time) { + _ = f.removeOld(f.dir, base, f.pref, f.suff, f.format, start) + }(f.start) } return diff --git a/tlio/writers.go b/tlio/writers.go index f259e43..17fd853 100644 --- a/tlio/writers.go +++ b/tlio/writers.go @@ -63,7 +63,7 @@ type ( WriterFunc func(p []byte) (int, error) - // base interfaces + // Base interfaces. Flusher interface { Flush() error diff --git a/tlog.go b/tlog.go index d2f71f6..2bad424 100644 --- a/tlog.go +++ b/tlog.go @@ -441,7 +441,7 @@ func (s Span) IOWriter(d int) io.Writer { } func (l *Logger) DumpWriter(d int, msg, key string) io.Writer { - return dumpWrapper{ + return &dumpWrapper{ Span: Span{ Logger: l, }, @@ -453,7 +453,7 @@ func (l *Logger) DumpWriter(d int, msg, key string) io.Writer { } func (s Span) DumpWriter(d int, msg, key string) io.Writer { - return dumpWrapper{ + return &dumpWrapper{ Span: s, loc: loc.Caller(1 + d), @@ -468,7 +468,7 @@ func (w writeWrapper) Write(p []byte) (int, error) { return len(p), nil } -func (w dumpWrapper) Write(p []byte) (int, error) { +func (w *dumpWrapper) Write(p []byte) (int, error) { message(w.Logger, w.ID, -1, w.msg, []any{KeyCaller, w.loc, w.key, p}) return len(p), nil diff --git a/tlwire/encoder_value.go b/tlwire/encoder_value.go index c82f582..fc6d4cb 100644 --- a/tlwire/encoder_value.go +++ b/tlwire/encoder_value.go @@ -29,13 +29,6 @@ type ( ptr unsafe.Pointer } - //nolint:structcheck - reflectValue struct { - typ unsafe.Pointer - ptr unsafe.Pointer - flag uintptr - } - encoders map[unsafe.Pointer]ValueEncoder ) @@ -164,8 +157,7 @@ func (e *Encoder) appendRaw(b []byte, r reflect.Value, visited ptrSet) []byte { return enc(e, b, v) } - switch v := v.(type) { - case TlogAppender: + if v, ok := v.(TlogAppender); ok { return v.TlogAppend(b) } @@ -316,36 +308,6 @@ func (e *Encoder) appendStructFields(b []byte, t reflect.Type, r reflect.Value, return b } -func value(v reflect.Value) reflectValue { - return *(*reflectValue)(unsafe.Pointer(&v)) -} - -func valueInterface(r reflect.Value) interface{} { - v := value(r) - - if r.Kind() == reflect.Interface { - // Special case: return the element inside the interface. - // Empty interface has one layout, all interfaces with - // methods have a second layout. - if r.NumMethod() == 0 { - return *(*interface{})(v.ptr) - } - return *(*interface { - M() - })(v.ptr) - } - - const flagAddr = 1 << 8 - - v.flag &^= flagAddr - - return *(*interface{})(unsafe.Pointer(&v)) - // return reflect_packEface(v) -} - -//go:linkname reflect_packEface reflect.packEface -func reflect_packEface(reflectValue) interface{} - func raweface(x interface{}) eface { return *(*eface)(unsafe.Pointer(&x)) } diff --git a/web/server.go b/web/server.go index 102edc9..3d6ea8f 100644 --- a/web/server.go +++ b/web/server.go @@ -15,6 +15,7 @@ import ( "time" "nikand.dev/go/hacked/hnet" + "nikand.dev/go/hacked/little" "tlog.app/go/eazy" "tlog.app/go/errors" @@ -45,12 +46,10 @@ type ( Proto func(context.Context, net.Conn) error ) -var ( - //go:embed index.html - //go:embed manifest.json - //go:embed static - static embed.FS -) +//go:embed index.html +//go:embed manifest.json +//go:embed static +var static embed.FS func New(a Agent) (*Server, error) { return &Server{ @@ -166,7 +165,7 @@ func (s *Server) HandleRequest(ctx context.Context, rw http.ResponseWriter, req w = convert.NewLogfmt(w) case ".html": ww := convert.NewWeb(w) - defer closeWrap(ww, "close Web", &err) + defer little.Closer(ww, &err, "close Web") w = ww default: @@ -179,10 +178,10 @@ func (s *Server) HandleRequest(ctx context.Context, rw http.ResponseWriter, req } return errors.Wrap(err, "process query") + default: + http.FileServer(s.FS).ServeHTTP(rw, req) } - http.FileServer(s.FS).ServeHTTP(rw, req) - return nil } @@ -224,13 +223,6 @@ func (r *response) Write(p []byte) (n int, err error) { return } -func closeWrap(c io.Closer, msg string, errp *error) { - e := c.Close() - if *errp == nil { - *errp = errors.Wrap(e, msg) - } -} - func pathExt(name string) string { last := len(name)