[chore] ensure consistent caller name fetching regardless of compiler inlining (#3323)

* move logging levels into log package itself

* ensure inconsistent inlining doesn't mess with log calling function name

* remove unused global variable

* fix log level
This commit is contained in:
kim 2024-09-20 13:30:33 +00:00 committed by GitHub
parent 747c251df6
commit 77b095a8c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 292 additions and 204 deletions

View File

@ -24,7 +24,6 @@
"os/signal" "os/signal"
"syscall" "syscall"
"codeberg.org/gruf/go-logger/v2/level"
"codeberg.org/gruf/go-storage/memory" "codeberg.org/gruf/go-storage/memory"
"github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb" "github.com/superseriousbusiness/gotosocial/internal/db/bundb"
@ -41,7 +40,7 @@ func main() {
ctx, cncl := signal.NotifyContext(ctx, syscall.SIGTERM, syscall.SIGINT) ctx, cncl := signal.NotifyContext(ctx, syscall.SIGTERM, syscall.SIGINT)
defer cncl() defer cncl()
log.SetLevel(level.INFO) log.SetLevel(log.INFO)
if len(os.Args) != 3 { if len(os.Args) != 3 {
log.Panic(ctx, "Usage: go run ./cmd/process-emoji <input-file> <output-static>") log.Panic(ctx, "Usage: go run ./cmd/process-emoji <input-file> <output-static>")

View File

@ -24,7 +24,6 @@
"os/signal" "os/signal"
"syscall" "syscall"
"codeberg.org/gruf/go-logger/v2/level"
"codeberg.org/gruf/go-storage/memory" "codeberg.org/gruf/go-storage/memory"
"github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb" "github.com/superseriousbusiness/gotosocial/internal/db/bundb"
@ -40,7 +39,7 @@ func main() {
ctx, cncl := signal.NotifyContext(ctx, syscall.SIGTERM, syscall.SIGINT) ctx, cncl := signal.NotifyContext(ctx, syscall.SIGTERM, syscall.SIGINT)
defer cncl() defer cncl()
log.SetLevel(level.INFO) log.SetLevel(log.INFO)
if len(os.Args) != 4 { if len(os.Args) != 4 {
log.Panic(ctx, "Usage: go run ./cmd/process-media <input-file> <output-processed> <output-thumbnail>") log.Panic(ctx, "Usage: go run ./cmd/process-media <input-file> <output-processed> <output-thumbnail>")

1
go.mod
View File

@ -16,7 +16,6 @@ require (
codeberg.org/gruf/go-iotools v0.0.0-20240710125620-934ae9c654cf codeberg.org/gruf/go-iotools v0.0.0-20240710125620-934ae9c654cf
codeberg.org/gruf/go-kv v1.6.4 codeberg.org/gruf/go-kv v1.6.4
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f
codeberg.org/gruf/go-logger/v2 v2.2.1
codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760 codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760
codeberg.org/gruf/go-mimetypes v1.2.0 codeberg.org/gruf/go-mimetypes v1.2.0
codeberg.org/gruf/go-mutexes v1.5.1 codeberg.org/gruf/go-mutexes v1.5.1

2
go.sum
View File

@ -60,8 +60,6 @@ codeberg.org/gruf/go-kv v1.6.4 h1:3NZiW8HVdBM3kpOiLb7XfRiihnzZWMAixdCznguhILk=
codeberg.org/gruf/go-kv v1.6.4/go.mod h1:O/YkSvKiS9XsRolM3rqCd9YJmND7dAXu9z+PrlYO4bc= codeberg.org/gruf/go-kv v1.6.4/go.mod h1:O/YkSvKiS9XsRolM3rqCd9YJmND7dAXu9z+PrlYO4bc=
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f h1:Ss6Z+vygy+jOGhj96d/GwsYYDd22QmIcH74zM7/nQkw= codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f h1:Ss6Z+vygy+jOGhj96d/GwsYYDd22QmIcH74zM7/nQkw=
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f/go.mod h1:F9pl4h34iuVN7kucKam9fLwsItTc+9mmaKt7pNXRd/4= codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f/go.mod h1:F9pl4h34iuVN7kucKam9fLwsItTc+9mmaKt7pNXRd/4=
codeberg.org/gruf/go-logger/v2 v2.2.1 h1:RP2u059EQKTBFV3cN8X6xDxNk2RkzqdgXGKflKqB7Oc=
codeberg.org/gruf/go-logger/v2 v2.2.1/go.mod h1:m/vBfG5jNUmYXI8Hg9aVSk7Pn8YgEBITQB/B/CzdRss=
codeberg.org/gruf/go-loosy v0.0.0-20231007123304-bb910d1ab5c4 h1:IXwfoU7f2whT6+JKIKskNl/hBlmWmnF1vZd84Eb3cyA= codeberg.org/gruf/go-loosy v0.0.0-20231007123304-bb910d1ab5c4 h1:IXwfoU7f2whT6+JKIKskNl/hBlmWmnF1vZd84Eb3cyA=
codeberg.org/gruf/go-loosy v0.0.0-20231007123304-bb910d1ab5c4/go.mod h1:fiO8HE1wjZCephcYmRRsVnNI/i0+mhy44Z5dQalS0rM= codeberg.org/gruf/go-loosy v0.0.0-20231007123304-bb910d1ab5c4/go.mod h1:fiO8HE1wjZCephcYmRRsVnNI/i0+mhy44Z5dQalS0rM=
codeberg.org/gruf/go-mangler v1.4.1 h1:Dv58jFfy9On49L11ji6tpADUknwoJA46iaiZvnNXecs= codeberg.org/gruf/go-mangler v1.4.1 h1:Dv58jFfy9On49L11ji6tpADUknwoJA46iaiZvnNXecs=

View File

@ -22,7 +22,6 @@
"time" "time"
"codeberg.org/gruf/go-kv" "codeberg.org/gruf/go-kv"
"codeberg.org/gruf/go-logger/v2/level"
"github.com/superseriousbusiness/gotosocial/internal/log" "github.com/superseriousbusiness/gotosocial/internal/log"
"github.com/uptrace/bun" "github.com/uptrace/bun"
) )
@ -50,7 +49,7 @@ func (queryHook) AfterQuery(ctx context.Context, event *bun.QueryEvent) {
// On trace, we log query information, // On trace, we log query information,
// manually crafting so DB query not escaped. // manually crafting so DB query not escaped.
case log.Level() >= level.TRACE: case log.Level() >= log.TRACE:
log.Printf("level=TRACE duration=%s query=%s", dur, event.Query) log.Printf("level=TRACE duration=%s query=%s", dur, event.Query)
} }
} }

View File

@ -23,11 +23,13 @@
) )
// Caller fetches the calling function name, skipping 'depth'. // Caller fetches the calling function name, skipping 'depth'.
//
//go:noinline
func Caller(depth int) string { func Caller(depth int) string {
var pcs [1]uintptr pcs := make([]uintptr, 1)
// Fetch calling function using calldepth // Fetch calling func using depth.
_ = runtime.Callers(depth, pcs[:]) _ = runtime.Callers(depth, pcs)
fn := runtime.FuncForPC(pcs[0]) fn := runtime.FuncForPC(pcs[0])
if fn == nil { if fn == nil {
@ -37,14 +39,14 @@ func Caller(depth int) string {
// Get func name. // Get func name.
name := fn.Name() name := fn.Name()
// Drop all but the package name and function name, no mod path // Drop all but package and function name, no path.
if idx := strings.LastIndex(name, "/"); idx >= 0 { if idx := strings.LastIndex(name, "/"); idx >= 0 {
name = name[idx+1:] name = name[idx+1:]
} }
const params = `[...]` const params = `[...]`
// Drop any generic type parameter markers // Drop any function generic type parameter markers.
if idx := strings.Index(name, params); idx >= 0 { if idx := strings.Index(name, params); idx >= 0 {
name = name[:idx] + name[idx+len(params):] name = name[:idx] + name[idx+len(params):]
} }

View File

@ -20,10 +20,8 @@
import ( import (
"context" "context"
"fmt" "fmt"
"syscall"
"codeberg.org/gruf/go-kv" "codeberg.org/gruf/go-kv"
"codeberg.org/gruf/go-logger/v2/level"
) )
type Entry struct { type Entry struct {
@ -31,93 +29,136 @@ type Entry struct {
kvs []kv.Field kvs []kv.Field
} }
// WithContext updates Entry{} value context.
func (e Entry) WithContext(ctx context.Context) Entry { func (e Entry) WithContext(ctx context.Context) Entry {
e.ctx = ctx e.ctx = ctx
return e return e
} }
// WithField appends key-value field to Entry{}.
func (e Entry) WithField(key string, value interface{}) Entry { func (e Entry) WithField(key string, value interface{}) Entry {
e.kvs = append(e.kvs, kv.Field{K: key, V: value}) e.kvs = append(e.kvs, kv.Field{K: key, V: value})
return e return e
} }
// WithFields appends key-value fields to Entry{}.
func (e Entry) WithFields(kvs ...kv.Field) Entry { func (e Entry) WithFields(kvs ...kv.Field) Entry {
e.kvs = append(e.kvs, kvs...) e.kvs = append(e.kvs, kvs...)
return e return e
} }
// Trace will log formatted args as 'msg' field to the log at TRACE level.
//
//go:noinline
func (e Entry) Trace(a ...interface{}) { func (e Entry) Trace(a ...interface{}) {
logf(e.ctx, 3, level.TRACE, e.kvs, args(len(a)), a...) logf(e.ctx, 3, TRACE, e.kvs, args(len(a)), a...)
} }
// Tracef will log format string as 'msg' field to the log at TRACE level.
//
//go:noinline
func (e Entry) Tracef(s string, a ...interface{}) { func (e Entry) Tracef(s string, a ...interface{}) {
logf(e.ctx, 3, level.TRACE, e.kvs, s, a...) logf(e.ctx, 3, TRACE, e.kvs, s, a...)
} }
// Debug will log formatted args as 'msg' field to the log at DEBUG level.
//
//go:noinline
func (e Entry) Debug(a ...interface{}) { func (e Entry) Debug(a ...interface{}) {
logf(e.ctx, 3, level.DEBUG, e.kvs, args(len(a)), a...) logf(e.ctx, 3, DEBUG, e.kvs, args(len(a)), a...)
} }
// Debugf will log format string as 'msg' field to the log at DEBUG level.
//
//go:noinline
func (e Entry) Debugf(s string, a ...interface{}) { func (e Entry) Debugf(s string, a ...interface{}) {
logf(e.ctx, 3, level.DEBUG, e.kvs, s, a...) logf(e.ctx, 3, DEBUG, e.kvs, s, a...)
} }
// Info will log formatted args as 'msg' field to the log at INFO level.
//
//go:noinline
func (e Entry) Info(a ...interface{}) { func (e Entry) Info(a ...interface{}) {
logf(e.ctx, 3, level.INFO, e.kvs, args(len(a)), a...) logf(e.ctx, 3, INFO, e.kvs, args(len(a)), a...)
} }
// Infof will log format string as 'msg' field to the log at INFO level.
//
//go:noinline
func (e Entry) Infof(s string, a ...interface{}) { func (e Entry) Infof(s string, a ...interface{}) {
logf(e.ctx, 3, level.INFO, e.kvs, s, a...) logf(e.ctx, 3, INFO, e.kvs, s, a...)
} }
// Warn will log formatted args as 'msg' field to the log at WARN level.
//
//go:noinline
func (e Entry) Warn(a ...interface{}) { func (e Entry) Warn(a ...interface{}) {
logf(e.ctx, 3, level.WARN, e.kvs, args(len(a)), a...) logf(e.ctx, 3, WARN, e.kvs, args(len(a)), a...)
} }
// Warnf will log format string as 'msg' field to the log at WARN level.
//
//go:noinline
func (e Entry) Warnf(s string, a ...interface{}) { func (e Entry) Warnf(s string, a ...interface{}) {
logf(e.ctx, 3, level.WARN, e.kvs, s, a...) logf(e.ctx, 3, WARN, e.kvs, s, a...)
} }
// Error will log formatted args as 'msg' field to the log at ERROR level.
//
//go:noinline
func (e Entry) Error(a ...interface{}) { func (e Entry) Error(a ...interface{}) {
logf(e.ctx, 3, level.ERROR, e.kvs, args(len(a)), a...) logf(e.ctx, 3, ERROR, e.kvs, args(len(a)), a...)
} }
// Errorf will log format string as 'msg' field to the log at ERROR level.
//
//go:noinline
func (e Entry) Errorf(s string, a ...interface{}) { func (e Entry) Errorf(s string, a ...interface{}) {
logf(e.ctx, 3, level.ERROR, e.kvs, s, a...) logf(e.ctx, 3, ERROR, e.kvs, s, a...)
}
func (e Entry) Fatal(a ...interface{}) {
defer syscall.Exit(1)
logf(e.ctx, 3, level.FATAL, e.kvs, args(len(a)), a...)
}
func (e Entry) Fatalf(s string, a ...interface{}) {
defer syscall.Exit(1)
logf(e.ctx, 3, level.FATAL, e.kvs, s, a...)
} }
// Panic will log formatted args as 'msg' field to the log at PANIC level.
// This will then call panic causing the application to crash.
//
//go:noinline
func (e Entry) Panic(a ...interface{}) { func (e Entry) Panic(a ...interface{}) {
defer panic(fmt.Sprint(a...)) defer panic(fmt.Sprint(a...))
logf(e.ctx, 3, level.PANIC, e.kvs, args(len(a)), a...) logf(e.ctx, 3, PANIC, e.kvs, args(len(a)), a...)
} }
// Panicf will log format string as 'msg' field to the log at PANIC level.
// This will then call panic causing the application to crash.
//
//go:noinline
func (e Entry) Panicf(s string, a ...interface{}) { func (e Entry) Panicf(s string, a ...interface{}) {
defer panic(fmt.Sprintf(s, a...)) defer panic(fmt.Sprintf(s, a...))
logf(e.ctx, 3, level.PANIC, e.kvs, s, a...) logf(e.ctx, 3, PANIC, e.kvs, s, a...)
} }
func (e Entry) Log(lvl level.LEVEL, a ...interface{}) { // Log will log formatted args as 'msg' field to the log at given level.
//
//go:noinline
func (e Entry) Log(lvl LEVEL, a ...interface{}) {
logf(e.ctx, 3, lvl, e.kvs, args(len(a)), a...) logf(e.ctx, 3, lvl, e.kvs, args(len(a)), a...)
} }
func (e Entry) Logf(lvl level.LEVEL, s string, a ...interface{}) { // Logf will log format string as 'msg' field to the log at given level.
//
//go:noinline
func (e Entry) Logf(lvl LEVEL, s string, a ...interface{}) {
logf(e.ctx, 3, lvl, e.kvs, s, a...) logf(e.ctx, 3, lvl, e.kvs, s, a...)
} }
// Print will log formatted args to the stdout log output.
//
//go:noinline
func (e Entry) Print(a ...interface{}) { func (e Entry) Print(a ...interface{}) {
printf(3, e.kvs, args(len(a)), a...) printf(3, e.kvs, args(len(a)), a...)
} }
// Printf will log format string to the stdout log output.
//
//go:noinline
func (e Entry) Printf(s string, a ...interface{}) { func (e Entry) Printf(s string, a ...interface{}) {
printf(3, e.kvs, s, a...) printf(3, e.kvs, s, a...)
} }

View File

@ -21,25 +21,23 @@
"fmt" "fmt"
"log/syslog" "log/syslog"
"strings" "strings"
"codeberg.org/gruf/go-logger/v2/level"
) )
// ParseLevel will parse the log level from given string and set to appropriate level. // ParseLevel will parse the log level from given string and set to appropriate LEVEL.
func ParseLevel(str string) error { func ParseLevel(str string) error {
switch strings.ToLower(str) { switch strings.ToLower(str) {
case "trace": case "trace":
SetLevel(level.TRACE) SetLevel(TRACE)
case "debug": case "debug":
SetLevel(level.DEBUG) SetLevel(DEBUG)
case "", "info": case "", "info":
SetLevel(level.INFO) SetLevel(INFO)
case "warn": case "warn":
SetLevel(level.WARN) SetLevel(WARN)
case "error": case "error":
SetLevel(level.ERROR) SetLevel(ERROR)
case "fatal": case "fatal", "panic":
SetLevel(level.FATAL) SetLevel(PANIC)
default: default:
return fmt.Errorf("unknown log level: %q", str) return fmt.Errorf("unknown log level: %q", str)
} }

38
internal/log/level.go Normal file
View File

@ -0,0 +1,38 @@
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package log
// LEVEL defines a level of logging.
type LEVEL uint8
// Default levels of logging.
const (
UNSET LEVEL = 0
PANIC LEVEL = 1
ERROR LEVEL = 100
WARN LEVEL = 150
INFO LEVEL = 200
DEBUG LEVEL = 250
TRACE LEVEL = 254
ALL LEVEL = ^LEVEL(0)
)
// CanLog returns whether an incoming log of 'lvl' can be logged against receiving level.
func (loglvl LEVEL) CanLog(lvl LEVEL) bool {
return loglvl > lvl
}

View File

@ -24,19 +24,26 @@
"os" "os"
"slices" "slices"
"strings" "strings"
"syscall"
"time" "time"
"codeberg.org/gruf/go-kv" "codeberg.org/gruf/go-kv"
"codeberg.org/gruf/go-logger/v2/level"
) )
var ( var (
// loglvl is the currently set logging level. // loglvl is the currently
loglvl level.LEVEL // set logging output
loglvl LEVEL
// lvlstrs is the lookup table of log levels to strings. // lvlstrs is the lookup table
lvlstrs = level.Default() // of all log levels to strings.
lvlstrs = [int(ALL) + 1]string{
TRACE: "TRACE",
DEBUG: "DEBUG",
INFO: "INFO",
WARN: "WARN",
ERROR: "ERROR",
PANIC: "PANIC",
}
// syslog output, only set if enabled. // syslog output, only set if enabled.
sysout *syslog.Writer sysout *syslog.Writer
@ -54,13 +61,13 @@ func Hook(hook func(ctx context.Context, kvs []kv.Field) []kv.Field) {
ctxhooks = append(ctxhooks, hook) ctxhooks = append(ctxhooks, hook)
} }
// Level returns the currently set log level. // Level returns the currently set log
func Level() level.LEVEL { func Level() LEVEL {
return loglvl return loglvl
} }
// SetLevel sets the max logging level. // SetLevel sets the max logging
func SetLevel(lvl level.LEVEL) { func SetLevel(lvl LEVEL) {
loglvl = lvl loglvl = lvl
} }
@ -83,174 +90,259 @@ func New() Entry {
return Entry{} return Entry{}
} }
// WithContext returns a new prepared Entry{} with context.
func WithContext(ctx context.Context) Entry { func WithContext(ctx context.Context) Entry {
return Entry{ctx: ctx} return Entry{ctx: ctx}
} }
// WithField returns a new prepared Entry{} with key-value field.
func WithField(key string, value interface{}) Entry { func WithField(key string, value interface{}) Entry {
return New().WithField(key, value) return Entry{kvs: []kv.Field{{K: key, V: value}}}
} }
// WithFields returns a new prepared Entry{} with key-value fields.
func WithFields(fields ...kv.Field) Entry { func WithFields(fields ...kv.Field) Entry {
return New().WithFields(fields...) return Entry{kvs: fields}
} }
// Note that most of the below logging
// functions we specifically do NOT allow
// the Go buildchain to inline, to ensure
// expected behaviour in caller fetching.
// Trace will log formatted args as 'msg' field to the log at TRACE level.
//
//go:noinline
func Trace(ctx context.Context, a ...interface{}) { func Trace(ctx context.Context, a ...interface{}) {
logf(ctx, 3, level.TRACE, nil, args(len(a)), a...) logf(ctx, 3, TRACE, nil, args(len(a)), a...)
} }
// Tracef will log format string as 'msg' field to the log at TRACE level.
//
//go:noinline
func Tracef(ctx context.Context, s string, a ...interface{}) { func Tracef(ctx context.Context, s string, a ...interface{}) {
logf(ctx, 3, level.TRACE, nil, s, a...) logf(ctx, 3, TRACE, nil, s, a...)
} }
// TraceKV will log the one key-value field to the log at TRACE level.
//
//go:noinline
func TraceKV(ctx context.Context, key string, value interface{}) { func TraceKV(ctx context.Context, key string, value interface{}) {
logf(ctx, 3, level.TRACE, []kv.Field{{K: key, V: value}}, "") logf(ctx, 3, TRACE, []kv.Field{{K: key, V: value}}, "")
} }
// TraceKVs will log key-value fields to the log at TRACE level.
//
//go:noinline
func TraceKVs(ctx context.Context, kvs ...kv.Field) { func TraceKVs(ctx context.Context, kvs ...kv.Field) {
logf(ctx, 3, level.TRACE, kvs, "") logf(ctx, 3, TRACE, kvs, "")
} }
// Debug will log formatted args as 'msg' field to the log at DEBUG level.
//
//go:noinline
func Debug(ctx context.Context, a ...interface{}) { func Debug(ctx context.Context, a ...interface{}) {
logf(ctx, 3, level.DEBUG, nil, args(len(a)), a...) logf(ctx, 3, DEBUG, nil, args(len(a)), a...)
} }
// Debugf will log format string as 'msg' field to the log at DEBUG level.
//
//go:noinline
func Debugf(ctx context.Context, s string, a ...interface{}) { func Debugf(ctx context.Context, s string, a ...interface{}) {
logf(ctx, 3, level.DEBUG, nil, s, a...) logf(ctx, 3, DEBUG, nil, s, a...)
} }
// DebugKV will log the one key-value field to the log at DEBUG level.
//
//go:noinline
func DebugKV(ctx context.Context, key string, value interface{}) { func DebugKV(ctx context.Context, key string, value interface{}) {
logf(ctx, 3, level.DEBUG, []kv.Field{{K: key, V: value}}, "") logf(ctx, 3, DEBUG, []kv.Field{{K: key, V: value}}, "")
} }
// DebugKVs will log key-value fields to the log at DEBUG level.
//
//go:noinline
func DebugKVs(ctx context.Context, kvs ...kv.Field) { func DebugKVs(ctx context.Context, kvs ...kv.Field) {
logf(ctx, 3, level.DEBUG, kvs, "") logf(ctx, 3, DEBUG, kvs, "")
} }
// Info will log formatted args as 'msg' field to the log at INFO level.
//
//go:noinline
func Info(ctx context.Context, a ...interface{}) { func Info(ctx context.Context, a ...interface{}) {
logf(ctx, 3, level.INFO, nil, args(len(a)), a...) logf(ctx, 3, INFO, nil, args(len(a)), a...)
} }
// Infof will log format string as 'msg' field to the log at INFO level.
//
//go:noinline
func Infof(ctx context.Context, s string, a ...interface{}) { func Infof(ctx context.Context, s string, a ...interface{}) {
logf(ctx, 3, level.INFO, nil, s, a...) logf(ctx, 3, INFO, nil, s, a...)
} }
// InfoKV will log the one key-value field to the log at INFO level.
//
//go:noinline
func InfoKV(ctx context.Context, key string, value interface{}) { func InfoKV(ctx context.Context, key string, value interface{}) {
logf(ctx, 3, level.INFO, []kv.Field{{K: key, V: value}}, "") logf(ctx, 3, INFO, []kv.Field{{K: key, V: value}}, "")
} }
// InfoKVs will log key-value fields to the log at INFO level.
//
//go:noinline
func InfoKVs(ctx context.Context, kvs ...kv.Field) { func InfoKVs(ctx context.Context, kvs ...kv.Field) {
logf(ctx, 3, level.INFO, kvs, "") logf(ctx, 3, INFO, kvs, "")
} }
// Warn will log formatted args as 'msg' field to the log at WARN level.
//
//go:noinline
func Warn(ctx context.Context, a ...interface{}) { func Warn(ctx context.Context, a ...interface{}) {
logf(ctx, 3, level.WARN, nil, args(len(a)), a...) logf(ctx, 3, WARN, nil, args(len(a)), a...)
} }
// Warnf will log format string as 'msg' field to the log at WARN level.
//
//go:noinline
func Warnf(ctx context.Context, s string, a ...interface{}) { func Warnf(ctx context.Context, s string, a ...interface{}) {
logf(ctx, 3, level.WARN, nil, s, a...) logf(ctx, 3, WARN, nil, s, a...)
} }
// WarnKV will log the one key-value field to the log at WARN level.
//
//go:noinline
func WarnKV(ctx context.Context, key string, value interface{}) { func WarnKV(ctx context.Context, key string, value interface{}) {
logf(ctx, 3, level.WARN, []kv.Field{{K: key, V: value}}, "") logf(ctx, 3, WARN, []kv.Field{{K: key, V: value}}, "")
} }
// WarnKVs will log key-value fields to the log at WARN level.
//
//go:noinline
func WarnKVs(ctx context.Context, kvs ...kv.Field) { func WarnKVs(ctx context.Context, kvs ...kv.Field) {
logf(ctx, 3, level.WARN, kvs, "") logf(ctx, 3, WARN, kvs, "")
} }
// Error will log formatted args as 'msg' field to the log at ERROR level.
//
//go:noinline
func Error(ctx context.Context, a ...interface{}) { func Error(ctx context.Context, a ...interface{}) {
logf(ctx, 3, level.ERROR, nil, args(len(a)), a...) logf(ctx, 3, ERROR, nil, args(len(a)), a...)
} }
// Errorf will log format string as 'msg' field to the log at ERROR level.
//
//go:noinline
func Errorf(ctx context.Context, s string, a ...interface{}) { func Errorf(ctx context.Context, s string, a ...interface{}) {
logf(ctx, 3, level.ERROR, nil, s, a...) logf(ctx, 3, ERROR, nil, s, a...)
} }
// ErrorKV will log the one key-value field to the log at ERROR level.
//
//go:noinline
func ErrorKV(ctx context.Context, key string, value interface{}) { func ErrorKV(ctx context.Context, key string, value interface{}) {
logf(ctx, 3, level.ERROR, []kv.Field{{K: key, V: value}}, "") logf(ctx, 3, ERROR, []kv.Field{{K: key, V: value}}, "")
} }
// ErrorKVs will log key-value fields to the log at ERROR level.
//
//go:noinline
func ErrorKVs(ctx context.Context, kvs ...kv.Field) { func ErrorKVs(ctx context.Context, kvs ...kv.Field) {
logf(ctx, 3, level.WARN, kvs, "") logf(ctx, 3, ERROR, kvs, "")
}
func Fatal(ctx context.Context, a ...interface{}) {
defer syscall.Exit(1)
logf(ctx, 3, level.FATAL, nil, args(len(a)), a...)
}
func Fatalf(ctx context.Context, s string, a ...interface{}) {
defer syscall.Exit(1)
logf(ctx, 3, level.FATAL, nil, s, a...)
}
func FatalKV(ctx context.Context, key string, value interface{}) {
logf(ctx, 3, level.FATAL, []kv.Field{{K: key, V: value}}, "")
}
func FatalKVs(ctx context.Context, kvs ...kv.Field) {
logf(ctx, 3, level.FATAL, kvs, "")
} }
// Panic will log formatted args as 'msg' field to the log at PANIC level.
// This will then call panic causing the application to crash.
//
//go:noinline
func Panic(ctx context.Context, a ...interface{}) { func Panic(ctx context.Context, a ...interface{}) {
defer panic(fmt.Sprint(a...)) defer panic(fmt.Sprint(a...))
logf(ctx, 3, level.PANIC, nil, args(len(a)), a...) logf(ctx, 3, PANIC, nil, args(len(a)), a...)
} }
// Panicf will log format string as 'msg' field to the log at PANIC level.
// This will then call panic causing the application to crash.
//
//go:noinline
func Panicf(ctx context.Context, s string, a ...interface{}) { func Panicf(ctx context.Context, s string, a ...interface{}) {
defer panic(fmt.Sprintf(s, a...)) defer panic(fmt.Sprintf(s, a...))
logf(ctx, 3, level.PANIC, nil, s, a...) logf(ctx, 3, PANIC, nil, s, a...)
} }
// PanicKV will log the one key-value field to the log at PANIC level.
// This will then call panic causing the application to crash.
//
//go:noinline
func PanicKV(ctx context.Context, key string, value interface{}) { func PanicKV(ctx context.Context, key string, value interface{}) {
logf(ctx, 3, level.PANIC, []kv.Field{{K: key, V: value}}, "") defer panic(kv.Field{K: key, V: value}.String())
logf(ctx, 3, PANIC, []kv.Field{{K: key, V: value}}, "")
} }
// PanicKVs will log key-value fields to the log at PANIC level.
// This will then call panic causing the application to crash.
//
//go:noinline
func PanicKVs(ctx context.Context, kvs ...kv.Field) { func PanicKVs(ctx context.Context, kvs ...kv.Field) {
logf(ctx, 3, level.PANIC, kvs, "") defer panic(kv.Fields(kvs).String())
logf(ctx, 3, PANIC, kvs, "")
} }
// Log will log formatted args as 'msg' field to the log at given level. // Log will log formatted args as 'msg' field to the log at given level.
func Log(ctx context.Context, lvl level.LEVEL, a ...interface{}) { //
//go:noinline
func Log(ctx context.Context, lvl LEVEL, a ...interface{}) {
logf(ctx, 3, lvl, nil, args(len(a)), a...) logf(ctx, 3, lvl, nil, args(len(a)), a...)
} }
// Logf will log format string as 'msg' field to the log at given level. // Logf will log format string as 'msg' field to the log at given level.
func Logf(ctx context.Context, lvl level.LEVEL, s string, a ...interface{}) { //
//go:noinline
func Logf(ctx context.Context, lvl LEVEL, s string, a ...interface{}) {
logf(ctx, 3, lvl, nil, s, a...) logf(ctx, 3, lvl, nil, s, a...)
} }
// LogKV will log the one key-value field to the log at given level. // LogKV will log the one key-value field to the log at given level.
func LogKV(ctx context.Context, lvl level.LEVEL, key string, value interface{}) { //nolint:revive //
logf(ctx, 3, level.DEBUG, []kv.Field{{K: key, V: value}}, "") //go:noinline
func LogKV(ctx context.Context, lvl LEVEL, key string, value interface{}) { //nolint:revive
logf(ctx, 3, lvl, []kv.Field{{K: key, V: value}}, "")
} }
// LogKVs will log key-value fields to the log at given level. // LogKVs will log key-value fields to the log at given level.
func LogKVs(ctx context.Context, lvl level.LEVEL, kvs ...kv.Field) { //nolint:revive //
//go:noinline
func LogKVs(ctx context.Context, lvl LEVEL, kvs ...kv.Field) { //nolint:revive
logf(ctx, 3, lvl, kvs, "") logf(ctx, 3, lvl, kvs, "")
} }
// Print will log formatted args to the stdout log output. // Print will log formatted args to the stdout log output.
//
//go:noinline
func Print(a ...interface{}) { func Print(a ...interface{}) {
printf(3, nil, args(len(a)), a...) printf(3, nil, args(len(a)), a...)
} }
// Printf will log format string to the stdout log output. // Printf will log format string to the stdout log output.
//
//go:noinline
func Printf(s string, a ...interface{}) { func Printf(s string, a ...interface{}) {
printf(3, nil, s, a...) printf(3, nil, s, a...)
} }
// PrintKVs will log the one key-value field to the stdout log output. // PrintKVs will log the one key-value field to the stdout log output.
//
//go:noinline
func PrintKV(key string, value interface{}) { func PrintKV(key string, value interface{}) {
printf(3, []kv.Field{{K: key, V: value}}, "") printf(3, []kv.Field{{K: key, V: value}}, "")
} }
// PrintKVs will log key-value fields to the stdout log output. // PrintKVs will log key-value fields to the stdout log output.
//
//go:noinline
func PrintKVs(kvs ...kv.Field) { func PrintKVs(kvs ...kv.Field) {
printf(3, kvs, "") printf(3, kvs, "")
} }
//go:noinline
func printf(depth int, fields []kv.Field, s string, a ...interface{}) { func printf(depth int, fields []kv.Field, s string, a ...interface{}) {
// Acquire buffer // Acquire buffer
buf := getBuf() buf := getBuf()
@ -279,7 +371,7 @@ func printf(depth int, fields []kv.Field, s string, a ...interface{}) {
if sysout != nil { if sysout != nil {
// Write log entry to syslog // Write log entry to syslog
logsys(level.INFO, buf.String()) logsys(INFO, buf.String())
} }
// Write to log and release // Write to log and release
@ -287,17 +379,18 @@ func printf(depth int, fields []kv.Field, s string, a ...interface{}) {
putBuf(buf) putBuf(buf)
} }
func logf(ctx context.Context, depth int, lvl level.LEVEL, fields []kv.Field, s string, a ...interface{}) { //go:noinline
func logf(ctx context.Context, depth int, lvl LEVEL, fields []kv.Field, s string, a ...interface{}) {
var out *os.File var out *os.File
// Check if enabled. // Check if enabled.
if lvl > Level() { if lvl > loglvl {
return return
} }
// Split errors to stderr, // Split errors to stderr,
// all else goes to stdout. // all else goes to stdout.
if lvl <= level.ERROR { if lvl <= ERROR {
out = os.Stderr out = os.Stderr
} else { } else {
out = os.Stdout out = os.Stdout
@ -354,21 +447,21 @@ func logf(ctx context.Context, depth int, lvl level.LEVEL, fields []kv.Field, s
// logsys will log given msg at given severity to the syslog. // logsys will log given msg at given severity to the syslog.
// Max length: https://www.rfc-editor.org/rfc/rfc5424.html#section-6.1 // Max length: https://www.rfc-editor.org/rfc/rfc5424.html#section-6.1
func logsys(lvl level.LEVEL, msg string) { func logsys(lvl LEVEL, msg string) {
if max := 2048; len(msg) > max { if max := 2048; len(msg) > max {
// Truncate up to max // Truncate up to max
msg = msg[:max] msg = msg[:max]
} }
switch lvl { switch lvl {
case level.TRACE, level.DEBUG: case TRACE, DEBUG:
_ = sysout.Debug(msg) _ = sysout.Debug(msg)
case level.INFO: case INFO:
_ = sysout.Info(msg) _ = sysout.Info(msg)
case level.WARN: case WARN:
_ = sysout.Warning(msg) _ = sysout.Warning(msg)
case level.ERROR: case ERROR:
_ = sysout.Err(msg) _ = sysout.Err(msg)
case level.FATAL, level.PANIC: case PANIC:
_ = sysout.Crit(msg) _ = sysout.Crit(msg)
} }
} }

View File

@ -26,7 +26,6 @@
"codeberg.org/gruf/go-bytesize" "codeberg.org/gruf/go-bytesize"
"codeberg.org/gruf/go-errors/v2" "codeberg.org/gruf/go-errors/v2"
"codeberg.org/gruf/go-kv" "codeberg.org/gruf/go-kv"
"codeberg.org/gruf/go-logger/v2/level"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/internal/gtscontext" "github.com/superseriousbusiness/gotosocial/internal/gtscontext"
"github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtserror"
@ -99,11 +98,11 @@ func Logger(logClientIP bool) gin.HandlerFunc {
l = l.WithFields(fields...) l = l.WithFields(fields...)
// Default is info // Default is info
lvl := level.INFO lvl := log.INFO
if code >= 500 { if code >= 500 {
// Actual server error. // Actual error.
lvl = level.ERROR lvl = log.ERROR
} }
if len(c.Errors) > 0 { if len(c.Errors) > 0 {

View File

@ -23,7 +23,6 @@
"time" "time"
"codeberg.org/gruf/go-kv" "codeberg.org/gruf/go-kv"
"codeberg.org/gruf/go-logger/v2/level"
"github.com/superseriousbusiness/gotosocial/internal/ap" "github.com/superseriousbusiness/gotosocial/internal/ap"
"github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtscontext" "github.com/superseriousbusiness/gotosocial/internal/gtscontext"
@ -62,7 +61,7 @@ func (p *Processor) ProcessFromClientAPI(ctx context.Context, cMsg *messages.Fro
// Include GTSModel in logs if appropriate. // Include GTSModel in logs if appropriate.
if cMsg.GTSModel != nil && if cMsg.GTSModel != nil &&
log.Level() >= level.DEBUG { log.Level() >= log.DEBUG {
fields = append(fields, kv.Field{ fields = append(fields, kv.Field{
"model", cMsg.GTSModel, "model", cMsg.GTSModel,
}) })

View File

@ -23,7 +23,6 @@
"time" "time"
"codeberg.org/gruf/go-kv" "codeberg.org/gruf/go-kv"
"codeberg.org/gruf/go-logger/v2/level"
"github.com/superseriousbusiness/gotosocial/internal/ap" "github.com/superseriousbusiness/gotosocial/internal/ap"
"github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/federation/dereferencing" "github.com/superseriousbusiness/gotosocial/internal/federation/dereferencing"
@ -69,7 +68,7 @@ func (p *Processor) ProcessFromFediAPI(ctx context.Context, fMsg *messages.FromF
// Include GTSModel in logs if appropriate. // Include GTSModel in logs if appropriate.
if fMsg.GTSModel != nil && if fMsg.GTSModel != nil &&
log.Level() >= level.DEBUG { log.Level() >= log.DEBUG {
fields = append(fields, kv.Field{ fields = append(fields, kv.Field{
"model", fMsg.GTSModel, "model", fMsg.GTSModel,
}) })

View File

@ -176,7 +176,7 @@ func (r *Router) Start() error {
go func() { go func() {
log.Infof(nil, "listening on %s", r.srv.Addr) log.Infof(nil, "listening on %s", r.srv.Addr)
if err := listen(); err != nil && err != http.ErrServerClosed { if err := listen(); err != nil && err != http.ErrServerClosed {
log.Fatalf(nil, "listen: %s", err) log.Panicf(nil, "listen: %v", err)
} }
}() }()
@ -273,7 +273,7 @@ func (r *Router) letsEncryptTLS() (func() error, error) {
log.Infof(nil, "letsencrypt listening on %s", leSrv.Addr) log.Infof(nil, "letsencrypt listening on %s", leSrv.Addr)
if err := leSrv.ListenAndServe(); err != nil && if err := leSrv.ListenAndServe(); err != nil &&
err != http.ErrServerClosed { err != http.ErrServerClosed {
log.Fatalf(nil, "letsencrypt: listen: %s", err) log.Panicf(nil, "letsencrypt: listen: %v", err)
} }
}() }()

View File

@ -1,9 +0,0 @@
MIT License
Copyright (c) 2022 gruf
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,63 +0,0 @@
package level
import (
"fmt"
"strings"
)
// LEVEL defines a level of logging.
type LEVEL uint8
// Default levels of logging.
const (
UNSET LEVEL = 0
PANIC LEVEL = 1
FATAL LEVEL = 50
ERROR LEVEL = 100
WARN LEVEL = 150
INFO LEVEL = 200
DEBUG LEVEL = 250
TRACE LEVEL = 254
ALL LEVEL = ^LEVEL(0)
)
// CanLog returns whether an incoming log of 'lvl' can be logged against receiving level.
func (loglvl LEVEL) CanLog(lvl LEVEL) bool {
return loglvl > lvl
}
// Levels defines a mapping of log LEVELs to formatted level strings.
type Levels [int(ALL) + 1]string
// Default returns the default set of log levels.
func Default() Levels {
return Levels{
TRACE: "TRACE",
DEBUG: "DEBUG",
INFO: "INFO",
WARN: "WARN",
ERROR: "ERROR",
FATAL: "FATAL",
PANIC: "PANIC",
}
}
// Get fetches the level string for the provided value.
func (l Levels) Get(lvl LEVEL) string {
return l[int(lvl)]
}
// Parse will attempt to decode a LEVEL from given string, checking (case insensitive) against strings in Levels.
func (l Levels) Parse(s string) (LEVEL, error) {
// Ensure consistent casing
s = strings.ToUpper(s)
for lvl := LEVEL(0); int(lvl) < len(l); lvl++ {
// Compare to eqach known level
if strings.ToUpper(l[lvl]) == s {
return lvl, nil
}
}
return 0, fmt.Errorf("unrecognized log level: %s", s)
}

3
vendor/modules.txt vendored
View File

@ -44,9 +44,6 @@ codeberg.org/gruf/go-kv/format
# codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f # codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f
## explicit; go 1.21.3 ## explicit; go 1.21.3
codeberg.org/gruf/go-list codeberg.org/gruf/go-list
# codeberg.org/gruf/go-logger/v2 v2.2.1
## explicit; go 1.19
codeberg.org/gruf/go-logger/v2/level
# codeberg.org/gruf/go-mangler v1.4.1 # codeberg.org/gruf/go-mangler v1.4.1
## explicit; go 1.19 ## explicit; go 1.19
codeberg.org/gruf/go-mangler codeberg.org/gruf/go-mangler