eef056f83c0b2ab03ca69e7f2e78486b392c9b33

Author
TheEdgeOfRage <git@theedgeofrage.com>
Committer
TheEdgeOfRage <git@theedgeofrage.com>
Date

Message

Add exclude fields flag

Diff

  1diff --git a/README.md b/README.md
  2index fad24f692ca9c155e88d19eb5055bec2c8ead75d..20bfca7aae996bf0771cda8a1b52dce9d0763705 100644
  3--- a/README.md
  4+++ b/README.md
  5@@ -1,6 +1,6 @@
  6 # logfmt CLI
  7 
  8-This is a (very) simple logfmt CLI tool to make reading logfmt logs on your terminal easier.
  9+This is a (very) simple CLI tool to make reading and parsing logfmt logs from your terminal easier.
 10 It supports colorized output, output field selection, and log level and key value filtering.
 11 
 12 ## What is logfmt?
 13@@ -32,11 +32,12 @@ go install github.com/TheEdgeOfRage/logfmt
 14 
 15 ```
 16 Usage:
 17-  main [OPTIONS]
 18+  logfmt [OPTIONS]
 19 
 20 Application Options:
 21   -l, --level=       Log level filter. One of DEBUG, INFO, WARN, ERROR, FATAL (default: INFO)
 22   -o, --output=      Output field selector (comma separated)
 23+  -e, --exclude=     Exclude field selector (comma separated)
 24   -f, --filter=      Filter fields (key=value comma separated)
 25   -n, --no-color     Disable color output
 26   -c, --force-color  Force color output, even when outputting to a pipe
 27@@ -69,6 +70,12 @@ show up.
 28 You can pass in a comma separated list of fields to the `-o` flag that you want it to print to the output. The timestamp
 29 and level are always printed, so this only applies to additional fields.
 30 
 31+#### Excluding fields
 32+
 33+If you want to exclude some fields from the output, you can pass in a comma separated list of fields to the `-e` flag.
 34+This can be useful in cases where you don't know what fields are going to be present in the logs, but want to exclude
 35+some verbose ones.
 36+
 37 #### Filtering by values
 38 
 39 If you want to only select records that have a specific value on a key, you can pass one or more comma separated filters
 40diff --git a/config/config.go b/config/config.go
 41index 0ab3ee2877aff3aa1115430c562ad28fe8d77cde..da4c70069c5499cfbaa212095ef524700bcccc77 100644
 42--- a/config/config.go
 43+++ b/config/config.go
 44@@ -19,18 +19,21 @@ const (
 45 type Config struct {
 46 	// LogLevel is the level filter for the log output
 47 	LogLevel int
 48-	// LogFormat is a list of fields to include on the log output
 49+	// OutputFields is a list of fields to include on the log output
 50 	OutputFields []string
 51+	// ExcludeFields is a list of fields to exclude from the log output
 52+	ExcludeFields []string
 53 	// Filter is a map of fields and values which are used to filter the log output
 54 	Filter map[string]string
 55 }
 56 
 57 type rawConfig struct {
 58-	LogLevel     string `long:"level" short:"l" description:"Log level filter. One of DEBUG, INFO, WARN, ERROR, FATAL" default:"INFO"` // nolint:lll
 59-	OutputFields string `long:"output" short:"o" description:"Output field selector (comma separated)"`
 60-	Filter       string `long:"filter" short:"f" description:"Filter fields (key=value comma separated)"`
 61-	NoColor      bool   `long:"no-color" short:"n" description:"Disable color output"`
 62-	ForceColor   bool   `long:"force-color" short:"c" description:"Force color output, even when outputting to a pipe"`
 63+	LogLevel      string `long:"level" short:"l" description:"Log level filter. One of DEBUG, INFO, WARN, ERROR, FATAL" default:"INFO"` // nolint:lll
 64+	OutputFields  string `long:"output" short:"o" description:"Output field selector (comma separated)"`
 65+	ExcludeFields string `long:"exclude" short:"e" description:"Exclude field selector (comma separated)"`
 66+	Filter        string `long:"filter" short:"f" description:"Filter fields (key=value comma separated)"`
 67+	NoColor       bool   `long:"no-color" short:"n" description:"Disable color output"`
 68+	ForceColor    bool   `long:"force-color" short:"c" description:"Force color output, even when outputting to a pipe"`
 69 }
 70 
 71 func Parse() (*Config, error) {
 72@@ -42,8 +45,10 @@ func Parse() (*Config, error) {
 73 		return nil, err
 74 	}
 75 
 76-	cfg := Config{}
 77-	cfg.setOutputFields(raw.OutputFields)
 78+	cfg := Config{
 79+		OutputFields:  parseFieldList(raw.OutputFields),
 80+		ExcludeFields: parseFieldList(raw.ExcludeFields),
 81+	}
 82 	err = cfg.setFilter(raw.Filter)
 83 	if err != nil {
 84 		return nil, err
 85@@ -83,12 +88,12 @@ func (c *Config) setLevel(level string) error {
 86 	return nil
 87 }
 88 
 89-func (c *Config) setOutputFields(fields string) {
 90+func parseFieldList(fields string) []string {
 91 	fields = strings.Trim(fields, " ")
 92 	if fields == "" {
 93-		return
 94+		return nil
 95 	}
 96-	c.OutputFields = strings.Split(fields, ",")
 97+	return strings.Split(fields, ",")
 98 }
 99 
100 func (c *Config) setFilter(filter string) error {
101diff --git a/parser/parser.go b/parser/parser.go
102index ff76b7045abd78f6a5cff198efd7ccafbb872ab5..909d5fd0eb88ebf298832733711e81a2f830102b 100644
103--- a/parser/parser.go
104+++ b/parser/parser.go
105@@ -37,7 +37,7 @@ func (p *Parser) Start() error {
106 			continue
107 		}
108 
109-		_, err = fmt.Fprintf(p.output, "%s\n", record.String(p.cfg.OutputFields))
110+		_, err = fmt.Fprintf(p.output, "%s\n", record.String(p.cfg.OutputFields, p.cfg.ExcludeFields))
111 		if err != nil {
112 			return fmt.Errorf("failed to print log to output: %w", err)
113 		}
114diff --git a/parser/record.go b/parser/record.go
115index fcc34e805523b304f7857b1a797e84dddc4bccae..d2c630a90fdd06872fd80ac524e7dab65792374a 100644
116--- a/parser/record.go
117+++ b/parser/record.go
118@@ -140,12 +140,15 @@ func (r *Record) MatchesFilter(filter map[string]string) bool {
119 }
120 
121 // String returns a formatted string representation of the Record
122-func (r *Record) String(outputFields []string) string {
123+func (r *Record) String(outputFields []string, excludeFields []string) string {
124 	line := ""
125 	for _, key := range r.fieldOrder {
126 		if len(outputFields) > 0 && !slices.Contains(outputFields, key) {
127 			continue
128 		}
129+		if len(excludeFields) > 0 && slices.Contains(excludeFields, key) {
130+			continue
131+		}
132 		value := r.fields[key]
133 		key = color.HiBlueString(key)
134 		line += fmt.Sprintf("%s=%s ", key, getFormattedValue(value))