Skip to content

Commit

Permalink
feat(log): Adding colored output for error or warning level
Browse files Browse the repository at this point in the history
Signed-off-by: Vincent Boutour <[email protected]>
  • Loading branch information
ViBiOh committed Oct 24, 2022
1 parent 1e1068e commit 20a74e2
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,10 @@ Flags:
-d, --dry-run Dry-run, print only pods
-g, --grep string Regexp to filter log
-h, --help help for log
--levelKey string Key for level in JSON (default "level")
-l, --selector stringToString Labels to filter pods (default [])
-s, --since duration Display logs since given duration (default 1h0m0s)
--statusCodeKey string Key for HTTP Status code in JSON (default "statusCode")
```
### `port-forward`
Expand Down
16 changes: 13 additions & 3 deletions cmd/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ var (
containersName []string
containersRegexp []*regexp.Regexp

levelKey string
statusCodeKey string

logFilter string
logFilterRegexp *regexp.Regexp
)
Expand Down Expand Up @@ -165,6 +168,8 @@ func initLog() {
flags.BoolVarP(&dryRun, "dry-run", "d", false, "Dry-run, print only pods")
flags.StringToStringVarP(&labelsSelector, "selector", "l", nil, "Labels to filter pods")
flags.StringVarP(&logFilter, "grep", "g", "", "Regexp to filter log")
flags.StringVar(&levelKey, "levelKey", "level", "Key for level in JSON")
flags.StringVar(&statusCodeKey, "statusCodeKey", "statusCode", "Key for HTTP Status code in JSON")
}

func handleLogPod(ctx context.Context, activeStreams *sync.Map, streaming *concurrent.Simple, kube client.Kube, pod v1.Pod) {
Expand Down Expand Up @@ -238,13 +243,18 @@ func outputLog(reader io.Reader, kube client.Kube, name, container string) {
streamScanner.Split(bufio.ScanLines)

for streamScanner.Scan() {
text := streamScanner.Text()

if colorOutputter := getColorFromJSON(strings.NewReader(text), levelKey, statusCodeKey); colorOutputter != nil {
text = colorOutputter(text)
}

if logFilterRegexp == nil {
outputter.Std(streamScanner.Text())
outputter.Std(text)

continue
}

text := streamScanner.Text()

if !logFilterRegexp.MatchString(text) {
continue
}
Expand Down
90 changes: 90 additions & 0 deletions cmd/log_color.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package cmd

import (
"encoding/json"
"fmt"
"io"
"net/http"
"strings"

"github.com/ViBiOh/kmux/pkg/output"
)

type Formatter func(a ...interface{}) string

func getColorFromJSON(stream io.Reader, keys ...string) Formatter {
decoder := json.NewDecoder(stream)

if err := moveDecoderToKey(decoder, keys...); err != nil {
return nil
}

token, err := decoder.Token()
if err != nil {
return nil
}

switch value := token.(type) {
case string:
switch strings.ToLower(value) {
case "warn", "warning":
return output.Yellow
case "error", "critical", "fatal":
return output.Red
case "trace", "debug":
return output.Green
default:
return nil
}
case float64:
switch {
case value >= http.StatusInternalServerError:
return output.Red
case value >= http.StatusBadRequest:
return output.Yellow
case value >= http.StatusMultipleChoices:
return output.Green
default:
return nil
}
default:
return nil
}
}

func moveDecoderToKey(decoder *json.Decoder, keys ...string) error {
var token json.Token
var nested uint64
var err error

for {
token, err = decoder.Token()
if err != nil {
return fmt.Errorf("decode token: %w", err)
}

if nested == 1 {
tokenStr := fmt.Sprintf("%s", token)
var found bool

for _, key := range keys {
if strings.EqualFold(tokenStr, key) {
found = true
break
}
}

if found {
break
}
}

if strToken := fmt.Sprintf("%s", token); strToken == "{" {
nested++
} else if strToken == "}" {
nested--
}
}

return nil
}

0 comments on commit 20a74e2

Please sign in to comment.