mirror of
https://github.com/SigNoz/signoz.git
synced 2026-02-13 04:42:54 +00:00
Compare commits
5 Commits
test/uplot
...
chore/igno
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef88766b81 | ||
|
|
16ef88521c | ||
|
|
feff1c1267 | ||
|
|
57db8b9e23 | ||
|
|
9650d7ee24 |
2
.github/workflows/goci.yaml
vendored
2
.github/workflows/goci.yaml
vendored
@@ -88,4 +88,4 @@ jobs:
|
||||
- name: generate-openapi
|
||||
run: |
|
||||
go run cmd/enterprise/*.go generate openapi
|
||||
git diff --compact-summary --exit-code || (echo; echo "Unexpected difference in openapi spec. Run go run cmd/enterprise/*.go generate openapi locally and commit."; exit 1)
|
||||
git diff --compact-summary --exit-code || (echo; echo 'Unexpected difference in openapi spec. Run `go run cmd/enterprise/*.go generate openapi` locally and commit.'; exit 1)
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
type zapToSlogConverter struct{}
|
||||
|
||||
func NewLogger(config Config, wrappers ...loghandler.Wrapper) *slog.Logger {
|
||||
wrappers = append([]loghandler.Wrapper{loghandler.NewFilter()}, wrappers...)
|
||||
|
||||
logger := slog.New(
|
||||
loghandler.New(
|
||||
slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: config.Logs.Level, AddSource: true, ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
type correlation struct{}
|
||||
|
||||
func NewCorrelation() *correlation {
|
||||
func NewCorrelation() Wrapper {
|
||||
return &correlation{}
|
||||
}
|
||||
|
||||
|
||||
54
pkg/instrumentation/loghandler/filter.go
Normal file
54
pkg/instrumentation/loghandler/filter.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package loghandler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
)
|
||||
|
||||
// filter wraps a LogHandler to filter out log entries based on a custom logic
|
||||
type filter struct{}
|
||||
|
||||
// NewFilter creates a new filtering wrapper
|
||||
func NewFilter() Wrapper {
|
||||
return &filter{}
|
||||
}
|
||||
|
||||
// Wrap implements the Wrapper interface.
|
||||
// It returns a LogHandler that filters log records based on a custom logic
|
||||
func (f *filter) Wrap(next LogHandler) LogHandler {
|
||||
return LogHandlerFunc(func(ctx context.Context, record slog.Record) error {
|
||||
dropEntry := false
|
||||
record.Attrs(func(attr slog.Attr) bool {
|
||||
if shouldDropEntry(attr) {
|
||||
dropEntry = true
|
||||
return false // stop iteration
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// Skip logging this entry
|
||||
if dropEntry {
|
||||
return nil
|
||||
}
|
||||
|
||||
return next.Handle(ctx, record)
|
||||
})
|
||||
}
|
||||
|
||||
// shouldDropEntry determines whether a log entry should be written based on
|
||||
// its fields.
|
||||
// Returns false if the entry should be suppressed, true otherwise.
|
||||
//
|
||||
// Current filters:
|
||||
// - context.Canceled: These are expected errors from cancelled operations,
|
||||
// and create noise in logs.
|
||||
func shouldDropEntry(attr slog.Attr) bool {
|
||||
if (attr.Key == "error" || attr.Key == "err") && attr.Value.Kind() == slog.KindAny {
|
||||
if loggedErr, ok := attr.Value.Any().(error); ok && loggedErr != nil {
|
||||
return errors.Is(loggedErr, context.Canceled)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
68
pkg/instrumentation/loghandler/filter_test.go
Normal file
68
pkg/instrumentation/loghandler/filter_test.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package loghandler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFilter_ContextCanceled(t *testing.T) {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
logger := slog.New(&handler{
|
||||
base: slog.NewJSONHandler(buf, &slog.HandlerOptions{Level: slog.LevelDebug}),
|
||||
wrappers: []Wrapper{NewFilter()},
|
||||
})
|
||||
|
||||
logger.WarnContext(context.Background(), "ignore_message", "error", context.Canceled)
|
||||
|
||||
// Buffer should be empty since the log should be filtered out
|
||||
assert.Empty(t, buf.Bytes(), "context.Canceled error should be filtered out")
|
||||
}
|
||||
|
||||
func TestFilter_OtherErrors(t *testing.T) {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
logger := slog.New(&handler{
|
||||
base: slog.NewJSONHandler(buf, &slog.HandlerOptions{Level: slog.LevelDebug}),
|
||||
wrappers: []Wrapper{NewFilter()},
|
||||
})
|
||||
|
||||
// Log with different error - should NOT be filtered
|
||||
logger.WarnContext(context.Background(), "log_message", "error", context.DeadlineExceeded)
|
||||
|
||||
// Buffer should contain the log entry
|
||||
require.NotEmpty(t, buf.Bytes(), "other errors should be logged")
|
||||
|
||||
m := make(map[string]any)
|
||||
err := json.Unmarshal(buf.Bytes(), &m)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "log_message", m["msg"])
|
||||
assert.Equal(t, "WARN", m["level"])
|
||||
assert.Equal(t, "context deadline exceeded", m["error"])
|
||||
}
|
||||
|
||||
func TestFilter_NoError(t *testing.T) {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
logger := slog.New(&handler{
|
||||
base: slog.NewJSONHandler(buf, &slog.HandlerOptions{Level: slog.LevelDebug}),
|
||||
wrappers: []Wrapper{NewFilter()},
|
||||
})
|
||||
|
||||
// Log without error - should be logged normally
|
||||
logger.InfoContext(context.Background(), "normal_message", "key", "value")
|
||||
|
||||
// Buffer should contain the log entry
|
||||
require.NotEmpty(t, buf.Bytes(), "logs without errors should be logged")
|
||||
|
||||
m := make(map[string]any)
|
||||
err := json.Unmarshal(buf.Bytes(), &m)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "normal_message", m["msg"])
|
||||
assert.Equal(t, "value", m["key"])
|
||||
}
|
||||
Reference in New Issue
Block a user