mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-07-07 09:55:41 +02:00
feat: add a EXCLUSION
to the logger (#8212)
Some checks are pending
/ release (push) Waiting to run
testing-integration / test-unit (push) Waiting to run
testing-integration / test-sqlite (push) Waiting to run
testing / backend-checks (push) Waiting to run
testing / frontend-checks (push) Waiting to run
testing / test-unit (push) Blocked by required conditions
testing / test-e2e (push) Blocked by required conditions
testing / test-remote-cacher (redis) (push) Blocked by required conditions
testing / test-remote-cacher (valkey) (push) Blocked by required conditions
testing / test-remote-cacher (garnet) (push) Blocked by required conditions
testing / test-remote-cacher (redict) (push) Blocked by required conditions
testing / test-mysql (push) Blocked by required conditions
testing / test-pgsql (push) Blocked by required conditions
testing / test-sqlite (push) Blocked by required conditions
testing / security-check (push) Blocked by required conditions
Some checks are pending
/ release (push) Waiting to run
testing-integration / test-unit (push) Waiting to run
testing-integration / test-sqlite (push) Waiting to run
testing / backend-checks (push) Waiting to run
testing / frontend-checks (push) Waiting to run
testing / test-unit (push) Blocked by required conditions
testing / test-e2e (push) Blocked by required conditions
testing / test-remote-cacher (redis) (push) Blocked by required conditions
testing / test-remote-cacher (valkey) (push) Blocked by required conditions
testing / test-remote-cacher (garnet) (push) Blocked by required conditions
testing / test-remote-cacher (redict) (push) Blocked by required conditions
testing / test-mysql (push) Blocked by required conditions
testing / test-pgsql (push) Blocked by required conditions
testing / test-sqlite (push) Blocked by required conditions
testing / security-check (push) Blocked by required conditions
This feature is intended to help reduce noisy logs generated by routine Kubernetes probes and Prometheus scraping. While logs are essential, these specific requests (e.g., to /metrics and /api/healthz) generally don't provide useful information and tend to clutter the output. The goal is to introduce functionality that effectively acts as the inverse of the existing EXPRESSION mode—allowing logging to be excluded based on a condition, rather than included. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8212 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Co-authored-by: zokki <zokki.softwareschmiede@gmail.com> Co-committed-by: zokki <zokki.softwareschmiede@gmail.com>
This commit is contained in:
parent
b669564f39
commit
72620db8df
9 changed files with 100 additions and 0 deletions
|
@ -44,6 +44,11 @@ func defaultLoggingFlags() []cli.Flag {
|
||||||
Aliases: []string{"e"},
|
Aliases: []string{"e"},
|
||||||
Usage: "Matching expression for the logger",
|
Usage: "Matching expression for the logger",
|
||||||
},
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "exclusion",
|
||||||
|
Aliases: []string{"x"},
|
||||||
|
Usage: "Exclusion for the logger",
|
||||||
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "prefix",
|
Name: "prefix",
|
||||||
Aliases: []string{"p"},
|
Aliases: []string{"p"},
|
||||||
|
@ -286,6 +291,9 @@ func commonAddLogger(ctx context.Context, c *cli.Command, mode string, vals map[
|
||||||
if len(c.String("expression")) > 0 {
|
if len(c.String("expression")) > 0 {
|
||||||
vals["expression"] = c.String("expression")
|
vals["expression"] = c.String("expression")
|
||||||
}
|
}
|
||||||
|
if len(c.String("exclusion")) > 0 {
|
||||||
|
vals["exclusion"] = c.String("exclusion")
|
||||||
|
}
|
||||||
if len(c.String("prefix")) > 0 {
|
if len(c.String("prefix")) > 0 {
|
||||||
vals["prefix"] = c.String("prefix")
|
vals["prefix"] = c.String("prefix")
|
||||||
}
|
}
|
||||||
|
|
|
@ -631,6 +631,7 @@ LEVEL = Info
|
||||||
;LEVEL=
|
;LEVEL=
|
||||||
;FLAGS = stdflags or journald
|
;FLAGS = stdflags or journald
|
||||||
;EXPRESSION =
|
;EXPRESSION =
|
||||||
|
;EXCLUSION =
|
||||||
;PREFIX =
|
;PREFIX =
|
||||||
;COLORIZE = false
|
;COLORIZE = false
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -26,6 +26,7 @@ type WriterMode struct {
|
||||||
Flags Flags
|
Flags Flags
|
||||||
|
|
||||||
Expression string
|
Expression string
|
||||||
|
Exclusion string
|
||||||
|
|
||||||
StacktraceLevel Level
|
StacktraceLevel Level
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,14 @@ func (b *EventWriterBaseImpl) Run(ctx context.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var exclusionRegexp *regexp.Regexp
|
||||||
|
if b.Mode.Exclusion != "" {
|
||||||
|
var err error
|
||||||
|
if exclusionRegexp, err = regexp.Compile(b.Mode.Exclusion); err != nil {
|
||||||
|
FallbackErrorf("unable to compile exclusion %q for writer %q: %v", b.Mode.Exclusion, b.Name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handlePaused := func() {
|
handlePaused := func() {
|
||||||
if pause := b.GetPauseChan(); pause != nil {
|
if pause := b.GetPauseChan(); pause != nil {
|
||||||
select {
|
select {
|
||||||
|
@ -95,6 +103,13 @@ func (b *EventWriterBaseImpl) Run(ctx context.Context) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if exclusionRegexp != nil {
|
||||||
|
fileLineCaller := fmt.Sprintf("%s:%d:%s", event.Origin.Filename, event.Origin.Line, event.Origin.Caller)
|
||||||
|
matched := exclusionRegexp.MatchString(fileLineCaller) || exclusionRegexp.MatchString(event.Origin.MsgSimpleText)
|
||||||
|
if matched {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
switch msg := event.Msg.(type) {
|
switch msg := event.Msg.(type) {
|
||||||
|
|
|
@ -31,3 +31,49 @@ func TestBufferLogger(t *testing.T) {
|
||||||
logger.Close()
|
logger.Close()
|
||||||
assert.Contains(t, bufferWriter.Buffer.String(), expected)
|
assert.Contains(t, bufferWriter.Buffer.String(), expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBufferLoggerWithExclusion(t *testing.T) {
|
||||||
|
prefix := "ExclusionPrefix "
|
||||||
|
level := log.INFO
|
||||||
|
message := "something"
|
||||||
|
|
||||||
|
bufferWriter := log.NewEventWriterBuffer("test-buffer", log.WriterMode{
|
||||||
|
Level: level,
|
||||||
|
Prefix: prefix,
|
||||||
|
Exclusion: message,
|
||||||
|
})
|
||||||
|
|
||||||
|
logger := log.NewLoggerWithWriters(t.Context(), "test", bufferWriter)
|
||||||
|
|
||||||
|
logger.SendLogEvent(&log.Event{
|
||||||
|
Level: log.INFO,
|
||||||
|
MsgSimpleText: message,
|
||||||
|
})
|
||||||
|
logger.Close()
|
||||||
|
assert.NotContains(t, bufferWriter.Buffer.String(), message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBufferLoggerWithExpressionAndExclusion(t *testing.T) {
|
||||||
|
prefix := "BothPrefix "
|
||||||
|
level := log.INFO
|
||||||
|
expression := ".*foo.*"
|
||||||
|
exclusion := ".*bar.*"
|
||||||
|
|
||||||
|
bufferWriter := log.NewEventWriterBuffer("test-buffer", log.WriterMode{
|
||||||
|
Level: level,
|
||||||
|
Prefix: prefix,
|
||||||
|
Expression: expression,
|
||||||
|
Exclusion: exclusion,
|
||||||
|
})
|
||||||
|
|
||||||
|
logger := log.NewLoggerWithWriters(t.Context(), "test", bufferWriter)
|
||||||
|
|
||||||
|
logger.SendLogEvent(&log.Event{Level: log.INFO, MsgSimpleText: "foo expression"})
|
||||||
|
logger.SendLogEvent(&log.Event{Level: log.INFO, MsgSimpleText: "bar exclusion"})
|
||||||
|
logger.SendLogEvent(&log.Event{Level: log.INFO, MsgSimpleText: "foo bar both"})
|
||||||
|
logger.SendLogEvent(&log.Event{Level: log.INFO, MsgSimpleText: "none"})
|
||||||
|
logger.Close()
|
||||||
|
|
||||||
|
assert.Contains(t, bufferWriter.Buffer.String(), "foo expression")
|
||||||
|
assert.NotContains(t, bufferWriter.Buffer.String(), "bar")
|
||||||
|
}
|
||||||
|
|
|
@ -143,3 +143,19 @@ func TestLoggerExpressionFilter(t *testing.T) {
|
||||||
|
|
||||||
assert.Equal(t, []string{"foo\n", "foo bar\n", "by filename\n"}, w1.GetLogs())
|
assert.Equal(t, []string{"foo\n", "foo bar\n", "by filename\n"}, w1.GetLogs())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoggerExclusionFilter(t *testing.T) {
|
||||||
|
logger := NewLoggerWithWriters(t.Context(), "test")
|
||||||
|
|
||||||
|
w1 := newDummyWriter("dummy-1", DEBUG, 0)
|
||||||
|
w1.Mode.Exclusion = "foo.*"
|
||||||
|
logger.AddWriters(w1)
|
||||||
|
|
||||||
|
logger.Info("foo")
|
||||||
|
logger.Info("bar")
|
||||||
|
logger.Info("foo bar")
|
||||||
|
logger.SendLogEvent(&Event{Level: INFO, Filename: "foo.go", MsgSimpleText: "by filename"})
|
||||||
|
logger.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, []string{"bar\n"}, w1.GetLogs())
|
||||||
|
}
|
||||||
|
|
|
@ -133,6 +133,7 @@ func loadLogModeByName(rootCfg ConfigProvider, loggerName, modeName string) (wri
|
||||||
writerMode.StacktraceLevel = log.LevelFromString(ConfigInheritedKeyString(sec, "STACKTRACE_LEVEL", Log.StacktraceLogLevel.String()))
|
writerMode.StacktraceLevel = log.LevelFromString(ConfigInheritedKeyString(sec, "STACKTRACE_LEVEL", Log.StacktraceLogLevel.String()))
|
||||||
writerMode.Prefix = ConfigInheritedKeyString(sec, "PREFIX")
|
writerMode.Prefix = ConfigInheritedKeyString(sec, "PREFIX")
|
||||||
writerMode.Expression = ConfigInheritedKeyString(sec, "EXPRESSION")
|
writerMode.Expression = ConfigInheritedKeyString(sec, "EXPRESSION")
|
||||||
|
writerMode.Exclusion = ConfigInheritedKeyString(sec, "EXCLUSION")
|
||||||
// flags are updated and set below
|
// flags are updated and set below
|
||||||
|
|
||||||
switch writerType {
|
switch writerType {
|
||||||
|
|
|
@ -44,6 +44,7 @@ func TestLogConfigDefault(t *testing.T) {
|
||||||
"BufferLen": 10000,
|
"BufferLen": 10000,
|
||||||
"Colorize": false,
|
"Colorize": false,
|
||||||
"Expression": "",
|
"Expression": "",
|
||||||
|
"Exclusion": "",
|
||||||
"Flags": "stdflags",
|
"Flags": "stdflags",
|
||||||
"Level": "info",
|
"Level": "info",
|
||||||
"Prefix": "",
|
"Prefix": "",
|
||||||
|
@ -83,6 +84,7 @@ logger.xorm.MODE =
|
||||||
"BufferLen": 10000,
|
"BufferLen": 10000,
|
||||||
"Colorize": false,
|
"Colorize": false,
|
||||||
"Expression": "",
|
"Expression": "",
|
||||||
|
"Exclusion": "",
|
||||||
"Flags": "stdflags",
|
"Flags": "stdflags",
|
||||||
"Level": "info",
|
"Level": "info",
|
||||||
"Prefix": "",
|
"Prefix": "",
|
||||||
|
@ -121,6 +123,7 @@ MODE = console
|
||||||
"BufferLen": 10000,
|
"BufferLen": 10000,
|
||||||
"Colorize": false,
|
"Colorize": false,
|
||||||
"Expression": "",
|
"Expression": "",
|
||||||
|
"Exclusion": "",
|
||||||
"Flags": "stdflags",
|
"Flags": "stdflags",
|
||||||
"Level": "info",
|
"Level": "info",
|
||||||
"Prefix": "",
|
"Prefix": "",
|
||||||
|
@ -168,6 +171,7 @@ ACCESS = file
|
||||||
"BufferLen": 10000,
|
"BufferLen": 10000,
|
||||||
"Colorize": false,
|
"Colorize": false,
|
||||||
"Expression": "",
|
"Expression": "",
|
||||||
|
"Exclusion": "",
|
||||||
"Flags": "stdflags",
|
"Flags": "stdflags",
|
||||||
"Level": "info",
|
"Level": "info",
|
||||||
"Prefix": "",
|
"Prefix": "",
|
||||||
|
@ -191,6 +195,7 @@ ACCESS = file
|
||||||
"BufferLen": 10000,
|
"BufferLen": 10000,
|
||||||
"Colorize": false,
|
"Colorize": false,
|
||||||
"Expression": "",
|
"Expression": "",
|
||||||
|
"Exclusion": "",
|
||||||
"Flags": "none",
|
"Flags": "none",
|
||||||
"Level": "info",
|
"Level": "info",
|
||||||
"Prefix": "",
|
"Prefix": "",
|
||||||
|
@ -257,6 +262,7 @@ STDERR = true
|
||||||
"BufferLen": 10000,
|
"BufferLen": 10000,
|
||||||
"Colorize": false,
|
"Colorize": false,
|
||||||
"Expression": "",
|
"Expression": "",
|
||||||
|
"Exclusion": "",
|
||||||
"Flags": "stdflags",
|
"Flags": "stdflags",
|
||||||
"Level": "warn",
|
"Level": "warn",
|
||||||
"Prefix": "",
|
"Prefix": "",
|
||||||
|
@ -270,6 +276,7 @@ STDERR = true
|
||||||
"BufferLen": 10000,
|
"BufferLen": 10000,
|
||||||
"Colorize": false,
|
"Colorize": false,
|
||||||
"Expression": "",
|
"Expression": "",
|
||||||
|
"Exclusion": "",
|
||||||
"Flags": "stdflags",
|
"Flags": "stdflags",
|
||||||
"Level": "error",
|
"Level": "error",
|
||||||
"Prefix": "",
|
"Prefix": "",
|
||||||
|
@ -287,6 +294,7 @@ STDERR = true
|
||||||
"BufferLen": 10000,
|
"BufferLen": 10000,
|
||||||
"Colorize": false,
|
"Colorize": false,
|
||||||
"Expression": "",
|
"Expression": "",
|
||||||
|
"Exclusion": "",
|
||||||
"Flags": "none",
|
"Flags": "none",
|
||||||
"Level": "warn",
|
"Level": "warn",
|
||||||
"Prefix": "",
|
"Prefix": "",
|
||||||
|
@ -323,6 +331,7 @@ MODE = file
|
||||||
LEVEL = error
|
LEVEL = error
|
||||||
STACKTRACE_LEVEL = fatal
|
STACKTRACE_LEVEL = fatal
|
||||||
EXPRESSION = filter
|
EXPRESSION = filter
|
||||||
|
EXCLUSION = not
|
||||||
FLAGS = medfile
|
FLAGS = medfile
|
||||||
PREFIX = "[Prefix] "
|
PREFIX = "[Prefix] "
|
||||||
FILE_NAME = file-xxx.log
|
FILE_NAME = file-xxx.log
|
||||||
|
@ -341,6 +350,7 @@ COMPRESSION_LEVEL = 4
|
||||||
"BufferLen": 10,
|
"BufferLen": 10,
|
||||||
"Colorize": false,
|
"Colorize": false,
|
||||||
"Expression": "",
|
"Expression": "",
|
||||||
|
"Exclusion": "",
|
||||||
"Flags": "stdflags",
|
"Flags": "stdflags",
|
||||||
"Level": "info",
|
"Level": "info",
|
||||||
"Prefix": "",
|
"Prefix": "",
|
||||||
|
@ -360,6 +370,7 @@ COMPRESSION_LEVEL = 4
|
||||||
"BufferLen": 10,
|
"BufferLen": 10,
|
||||||
"Colorize": false,
|
"Colorize": false,
|
||||||
"Expression": "filter",
|
"Expression": "filter",
|
||||||
|
"Exclusion": "not",
|
||||||
"Flags": "medfile",
|
"Flags": "medfile",
|
||||||
"Level": "error",
|
"Level": "error",
|
||||||
"Prefix": "[Prefix] ",
|
"Prefix": "[Prefix] ",
|
||||||
|
|
|
@ -145,6 +145,7 @@ func AddLogger(ctx *context.PrivateContext) {
|
||||||
|
|
||||||
writerMode.Prefix, _ = opts.Config["prefix"].(string)
|
writerMode.Prefix, _ = opts.Config["prefix"].(string)
|
||||||
writerMode.Expression, _ = opts.Config["expression"].(string)
|
writerMode.Expression, _ = opts.Config["expression"].(string)
|
||||||
|
writerMode.Exclusion, _ = opts.Config["exclusion"].(string)
|
||||||
|
|
||||||
switch writerType {
|
switch writerType {
|
||||||
case "console":
|
case "console":
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue