-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
00359b6
commit d3524e1
Showing
1 changed file
with
78 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,110 +1,144 @@ | ||
package parser | ||
|
||
import ( | ||
"bytes" | ||
"os" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/mattn/go-isatty" | ||
) | ||
|
||
const size = 2024 | ||
|
||
// JSONLineHandler serializes log lines into JSON (NDJSON) format. It keywords the line number if specified. | ||
// Labels and values are combined into key-value pairs, and the result is a single JSON object. | ||
func JSONLineHandler(labels []string, values []string, _ bool) (string, error) { | ||
b := &strings.Builder{} | ||
b.WriteString("{") | ||
func JSONLineHandler(labels, values []string, _ bool) (string, error) { | ||
buf := &bytes.Buffer{} | ||
buf.Grow(size) | ||
buf.WriteByte('{') | ||
for i, value := range values { | ||
if i < len(labels) { | ||
if i > 0 { | ||
b.WriteString(",") | ||
buf.WriteByte(',') | ||
} | ||
b.WriteString("\"") | ||
b.WriteString(labels[i]) | ||
b.WriteString("\":") | ||
b.WriteString(strconv.Quote(value)) | ||
buf.WriteByte('"') | ||
buf.WriteString(labels[i]) | ||
buf.WriteString("\":") | ||
buf.WriteByte('"') | ||
writeEscapedString(buf, value) | ||
buf.WriteByte('"') | ||
} | ||
} | ||
b.WriteString("}") | ||
return b.String(), nil | ||
buf.WriteByte('}') | ||
return buf.String(), nil | ||
} | ||
|
||
// PrettyJSONLineHandler enhances JSONLineHandler by formatting the output for readability. It uses indentation and new lines. | ||
func PrettyJSONLineHandler(labels []string, values []string, _ bool) (string, error) { | ||
b := &strings.Builder{} | ||
b.WriteString("{\n") | ||
func PrettyJSONLineHandler(labels, values []string, _ bool) (string, error) { | ||
buf := &bytes.Buffer{} | ||
buf.Grow(size) | ||
buf.WriteString("{\n") | ||
for i, value := range values { | ||
if i < len(labels) { | ||
if i > 0 { | ||
b.WriteString(",\n") | ||
buf.WriteString(",\n") | ||
} | ||
b.WriteString(" \"") | ||
b.WriteString(labels[i]) | ||
b.WriteString("\": ") | ||
b.WriteString(strconv.Quote(value)) | ||
buf.WriteString(" \"") | ||
buf.WriteString(labels[i]) | ||
buf.WriteString("\": ") | ||
buf.WriteByte('"') | ||
writeEscapedString(buf, value) | ||
buf.WriteByte('"') | ||
} | ||
} | ||
b.WriteString("\n}") | ||
return b.String(), nil | ||
buf.WriteString("\n}") | ||
return buf.String(), nil | ||
} | ||
|
||
// KeyValuePairLineHandler converts log lines into a space-separated string of key-value pairs. | ||
func KeyValuePairLineHandler(labels []string, values []string, _ bool) (string, error) { | ||
b := &strings.Builder{} | ||
func KeyValuePairLineHandler(labels, values []string, _ bool) (string, error) { | ||
buf := &bytes.Buffer{} | ||
buf.Grow(size) | ||
for i, value := range values { | ||
if i < len(labels) { | ||
if i > 0 { | ||
b.WriteString(" ") | ||
buf.WriteByte(' ') | ||
} | ||
b.WriteString(labels[i]) | ||
b.WriteString("=") | ||
b.WriteString(strconv.Quote(value)) | ||
buf.WriteString(labels[i]) | ||
buf.WriteByte('=') | ||
buf.WriteByte('"') | ||
writeEscapedString(buf, value) | ||
buf.WriteByte('"') | ||
} | ||
} | ||
return b.String(), nil | ||
return buf.String(), nil | ||
} | ||
|
||
// LTSVLineHandler formats log lines as LTSV (Labeled Tab-separated Values). | ||
func LTSVLineHandler(labels []string, values []string, _ bool) (string, error) { | ||
b := &strings.Builder{} | ||
func LTSVLineHandler(labels, values []string, _ bool) (string, error) { | ||
buf := &bytes.Buffer{} | ||
buf.Grow(size) | ||
for i, value := range values { | ||
if i < len(labels) { | ||
if i > 0 { | ||
b.WriteString("\t") | ||
buf.WriteByte('\t') | ||
} | ||
b.WriteString(labels[i]) | ||
b.WriteString(":") | ||
buf.WriteString(labels[i]) | ||
buf.WriteByte(':') | ||
if value == "" { | ||
b.WriteString("-") | ||
buf.WriteByte('-') | ||
} else { | ||
b.WriteString(value) | ||
buf.WriteString(value) | ||
} | ||
} | ||
} | ||
return b.String(), nil | ||
return buf.String(), nil | ||
} | ||
|
||
// TSVLineHandler formats log lines as TSV (Tab-separated Values). | ||
func TSVLineHandler(labels []string, values []string, isFirst bool) (string, error) { | ||
b := &strings.Builder{} | ||
func TSVLineHandler(labels, values []string, isFirst bool) (string, error) { | ||
buf := &bytes.Buffer{} | ||
buf.Grow(size) | ||
if isFirst { | ||
header := strings.Join(labels, "\t") | ||
if isatty.IsTerminal(os.Stdout.Fd()) { | ||
header = "\033[1;37m" + header + "\033[0m" | ||
} | ||
b.WriteString(header) | ||
b.WriteString("\n") | ||
buf.WriteString(header) | ||
buf.WriteByte('\n') | ||
} | ||
for i, value := range values { | ||
if i < len(labels) { | ||
if i > 0 { | ||
b.WriteString("\t") | ||
buf.WriteByte('\t') | ||
} | ||
if value == "" { | ||
b.WriteString("-") | ||
buf.WriteByte('-') | ||
} else { | ||
b.WriteString(value) | ||
buf.WriteString(value) | ||
} | ||
} | ||
} | ||
return b.String(), nil | ||
return buf.String(), nil | ||
} | ||
|
||
// EscapedString writes the string s to the given bytes.Buffer while properly escaping | ||
// special characters (backslash, double quote, newline, carriage return, tab). | ||
func writeEscapedString(buf *bytes.Buffer, s string) { | ||
for _, r := range s { | ||
switch r { | ||
case '\\': | ||
buf.WriteString("\\\\") | ||
case '"': | ||
buf.WriteString("\\\"") | ||
case '\n': | ||
buf.WriteString("\\n") | ||
case '\r': | ||
buf.WriteString("\\r") | ||
case '\t': | ||
buf.WriteString("\\t") | ||
default: | ||
buf.WriteRune(r) | ||
} | ||
} | ||
} |