mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 21:38:05 -05:00
Compare commits
1 Commits
hashtree_f
...
logs-per-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
850b7326eb |
3
changelog/bastin_per-package-visibility.md
Normal file
3
changelog/bastin_per-package-visibility.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Added
|
||||
|
||||
- Added `--log-only` and `--log-exclude` flags to the beacon chain client to allow users to filter log output.
|
||||
@@ -113,6 +113,8 @@ var appFlags = []cli.Flag{
|
||||
cmd.PubsubQueueSize,
|
||||
cmd.DataDirFlag,
|
||||
cmd.VerbosityFlag,
|
||||
cmd.LogOnlyFlag,
|
||||
cmd.LogExcludeFlag,
|
||||
cmd.EnableTracingFlag,
|
||||
cmd.TracingProcessNameFlag,
|
||||
cmd.TracingEndpointFlag,
|
||||
@@ -191,6 +193,10 @@ func before(ctx *cli.Context) error {
|
||||
formatter.FullTimestamp = true
|
||||
formatter.ForceFormatting = true
|
||||
formatter.ForceColors = true
|
||||
logOnly, logExclude := cmd.ParseLogPackageFlags(ctx)
|
||||
formatter.LogOnly = logOnly
|
||||
formatter.LogExclude = logExclude
|
||||
formatter.RespectLogFilters = true
|
||||
|
||||
logrus.AddHook(&logs.WriterHook{
|
||||
Formatter: formatter,
|
||||
|
||||
@@ -201,6 +201,8 @@ var appHelpFlagGroups = []flagGroup{
|
||||
cmd.LogFileName,
|
||||
cmd.VerbosityFlag,
|
||||
flags.DisableEphemeralLogFile,
|
||||
cmd.LogExcludeFlag,
|
||||
cmd.LogOnlyFlag,
|
||||
},
|
||||
},
|
||||
{ // Feature flags.
|
||||
|
||||
@@ -62,6 +62,9 @@ func main() {
|
||||
formatter := new(prefixed.TextFormatter)
|
||||
formatter.TimestampFormat = "2006-01-02 15:04:05.00"
|
||||
formatter.FullTimestamp = true
|
||||
logOnly, logExclude := cmd.ParseLogPackageFlags(ctx)
|
||||
formatter.LogOnly = logOnly
|
||||
formatter.LogExclude = logExclude
|
||||
// If persistent log files are written - we disable the log messages coloring because
|
||||
// the colors are ANSI codes and seen as gibberish in the log files.
|
||||
formatter.DisableColors = ctx.String(cmd.LogFileName.Name) != ""
|
||||
|
||||
29
cmd/flags.go
29
cmd/flags.go
@@ -36,6 +36,16 @@ var (
|
||||
Usage: "Logging verbosity. (trace, debug, info, warn, error, fatal, panic)",
|
||||
Value: "info",
|
||||
}
|
||||
// LogOnlyFlag specifies the packages for which logging is enabled.
|
||||
LogOnlyFlag = &cli.StringSliceFlag{
|
||||
Name: "log-only",
|
||||
Usage: "Enables logging only for the specified packages (comma-separated package paths). By default, all packages are logged.",
|
||||
}
|
||||
// LogExcludeFlag specifies the packages for which logging is disabled.
|
||||
LogExcludeFlag = &cli.StringSliceFlag{
|
||||
Name: "log-exclude",
|
||||
Usage: "Disables logging for the specified packages (comma-separated package paths).",
|
||||
}
|
||||
// DataDirFlag defines a path on disk where Prysm databases are stored.
|
||||
DataDirFlag = &cli.StringFlag{
|
||||
Name: "datadir",
|
||||
@@ -283,6 +293,25 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// ParseLogPackageFlags returns flattened lists for log-only and log-exclude flags.
|
||||
func ParseLogPackageFlags(ctx *cli.Context) (logOnly []string, logExclude []string) {
|
||||
return parseCommaSeparatedEntries(ctx.StringSlice(LogOnlyFlag.Name)), parseCommaSeparatedEntries(ctx.StringSlice(LogExcludeFlag.Name))
|
||||
}
|
||||
|
||||
func parseCommaSeparatedEntries(values []string) []string {
|
||||
entries := make([]string, 0)
|
||||
for _, value := range values {
|
||||
for entry := range strings.SplitSeq(value, ",") {
|
||||
entry = strings.TrimSpace(entry)
|
||||
entry = strings.TrimSuffix(entry, "/")
|
||||
if entry != "" {
|
||||
entries = append(entries, entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
// LoadFlagsFromConfig sets flags values from config file if ConfigFileFlag is set.
|
||||
func LoadFlagsFromConfig(cliCtx *cli.Context, flags []cli.Flag) error {
|
||||
if cliCtx.IsSet(ConfigFileFlag.Name) {
|
||||
|
||||
@@ -41,6 +41,21 @@ func TestLoadFlagsFromConfig(t *testing.T) {
|
||||
require.NoError(t, os.Remove("flags_test.yaml"))
|
||||
}
|
||||
|
||||
func TestParseLogPackageFlags(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
require.NoError(t, LogOnlyFlag.Apply(set))
|
||||
require.NoError(t, LogExcludeFlag.Apply(set))
|
||||
require.NoError(t, set.Set(LogOnlyFlag.Name, "pkg/a/,pkg/b"))
|
||||
require.NoError(t, set.Set(LogOnlyFlag.Name, "pkg/c"))
|
||||
require.NoError(t, set.Set(LogExcludeFlag.Name, " pkg/d ,pkg/e/ "))
|
||||
|
||||
ctx := cli.NewContext(&cli.App{}, set, nil)
|
||||
|
||||
logOnly, logExclude := ParseLogPackageFlags(ctx)
|
||||
require.DeepEqual(t, []string{"pkg/a", "pkg/b", "pkg/c"}, logOnly)
|
||||
require.DeepEqual(t, []string{"pkg/d", "pkg/e"}, logExclude)
|
||||
}
|
||||
|
||||
func TestValidateNoArgs(t *testing.T) {
|
||||
app := &cli.App{
|
||||
Before: ValidateNoArgs,
|
||||
|
||||
@@ -170,6 +170,9 @@ func main() {
|
||||
formatter.FullTimestamp = true
|
||||
formatter.ForceFormatting = true
|
||||
formatter.ForceColors = true
|
||||
logOnly, logExclude := cmd.ParseLogPackageFlags(ctx)
|
||||
formatter.LogOnly = logOnly
|
||||
formatter.LogExclude = logExclude
|
||||
|
||||
logrus.AddHook(&logs.WriterHook{
|
||||
Formatter: formatter,
|
||||
|
||||
@@ -104,6 +104,9 @@ type TextFormatter struct {
|
||||
// Wrap empty fields in quotes if true.
|
||||
QuoteEmptyFields bool
|
||||
|
||||
// Whether to respect the per-Package log filters.
|
||||
RespectLogFilters bool
|
||||
|
||||
sync.Once
|
||||
|
||||
// Pad msg field with spaces on the right for display.
|
||||
@@ -120,6 +123,10 @@ type TextFormatter struct {
|
||||
|
||||
// Timestamp format to use for display when a full timestamp is printed.
|
||||
TimestampFormat string
|
||||
|
||||
// Per-Package log filters parsed from CLI flags.
|
||||
LogOnly []string
|
||||
LogExclude []string
|
||||
}
|
||||
|
||||
func getCompiledColor(main string, fallback string) func(string) string {
|
||||
@@ -168,6 +175,13 @@ func (f *TextFormatter) SetColorScheme(colorScheme *ColorScheme) {
|
||||
}
|
||||
|
||||
func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) {
|
||||
// check if entry should be dropped based on package filters
|
||||
if f.RespectLogFilters {
|
||||
if shouldDrop := f.shouldDropEntry(entry); shouldDrop {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
var b *bytes.Buffer
|
||||
keys := make([]string, 0, len(entry.Data))
|
||||
for k := range entry.Data {
|
||||
@@ -403,6 +417,62 @@ func (f *TextFormatter) appendValue(b *bytes.Buffer, value any) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (f *TextFormatter) shouldDropEntry(entry *logrus.Entry) bool {
|
||||
if len(f.LogOnly) == 0 && len(f.LogExclude) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// try to get package field
|
||||
packageField, ok := entry.Data["package"]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
packageName, ok := packageField.(string)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
// get best matches. longer match means a more specific match
|
||||
lengthOfBestIncludeMatch := bestMatchLen(packageName, f.LogOnly)
|
||||
lengthOfBestExcludeMatch := bestMatchLen(packageName, f.LogExclude)
|
||||
|
||||
if len(f.LogOnly) > 0 && lengthOfBestIncludeMatch == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
if lengthOfBestExcludeMatch > 0 {
|
||||
// if we're only excluding, then drop the entry
|
||||
if len(f.LogOnly) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
// if both include and exclude have matches, compare lengths. prefers include.
|
||||
if lengthOfBestIncludeMatch >= lengthOfBestExcludeMatch {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// bestMatchLen returns the length (specificity) of the most specific path that matches package name.
|
||||
// 0 means "no match".
|
||||
func bestMatchLen(pkg string, paths []string) int {
|
||||
best := 0
|
||||
for _, r := range paths {
|
||||
if r == "" {
|
||||
continue
|
||||
}
|
||||
if r == pkg || strings.HasPrefix(pkg, r+"/") {
|
||||
if len(r) > best {
|
||||
best = len(r)
|
||||
}
|
||||
}
|
||||
}
|
||||
return best
|
||||
}
|
||||
|
||||
// This is to not silently overwrite `time`, `msg` and `level` fields when
|
||||
// dumping it. If this code wasn't there doing:
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user