-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update: #243
- Loading branch information
Showing
9 changed files
with
207 additions
and
0 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
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
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 |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"severity": { | ||
"str": "Warn", | ||
"number": 13, | ||
"text": "warning" | ||
}, | ||
"body": "The group's number increased tremendously!", | ||
"timestamp": "2015-03-26T05:27:38Z", | ||
"attrs": { | ||
"number": 122, | ||
"omg": true | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"severity": { | ||
"str": "Fatal", | ||
"number": 21, | ||
"text": "fatal" | ||
}, | ||
"body": "The ice breaks!", | ||
"timestamp": "2015-03-26T05:27:38Z", | ||
"attrs": { | ||
"err": "&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!}", | ||
"number": 100, | ||
"omg": true | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"attrs": { | ||
"foo": "bar", | ||
"a": 14, | ||
"baz": "hello kitty", | ||
"cool%story": "bro", | ||
"f": true, | ||
"%^asdf": true | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1,2 @@ | ||
time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true | ||
time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err="&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!}" number=100 omg=true |
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 |
---|---|---|
@@ -0,0 +1 @@ | ||
foo=bar a=14 baz="hello kitty" cool%story=bro f %^asdf |
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 |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package logparser | ||
|
||
import ( | ||
"encoding/hex" | ||
"strings" | ||
"time" | ||
"unicode" | ||
|
||
"github.com/go-faster/jx" | ||
"github.com/google/uuid" | ||
"github.com/kr/logfmt" | ||
"go.opentelemetry.io/collector/pdata/pcommon" | ||
|
||
"github.com/go-faster/oteldb/internal/otelstorage" | ||
) | ||
|
||
// LogFmtParser parses logfmt lines. | ||
type LogFmtParser struct{} | ||
|
||
// Parse line. | ||
func (LogFmtParser) Parse(data []byte) (*Line, error) { | ||
line := &Line{} | ||
attrs := pcommon.NewMap() | ||
hf := logfmt.HandlerFunc(func(key, val []byte) error { | ||
k := string(key) | ||
v := string(val) | ||
switch k { | ||
case "msg": | ||
line.Body = v | ||
case "level", "lvl", "levelStr", "severity_text", "severity", "levelname": | ||
line.SeverityText = v | ||
line.SeverityNumber = _severityMap[unicode.ToLower(rune(v[0]))] | ||
case "span_id", "spanid", "spanID", "spanId": | ||
raw, _ := hex.DecodeString(v) | ||
if len(raw) != 8 { | ||
attrs.PutStr(k, v) | ||
return nil | ||
} | ||
var spanID otelstorage.SpanID | ||
copy(spanID[:], raw) | ||
line.SpanID = spanID | ||
case "trace_id", "traceid", "traceID", "traceId": | ||
traceID, err := otelstorage.ParseTraceID(strings.ToLower(v)) | ||
if err != nil { | ||
// Trying to parse as UUID. | ||
id, err := uuid.Parse(v) | ||
if err != nil { | ||
attrs.PutStr(k, v) | ||
return nil | ||
} | ||
traceID = otelstorage.TraceID(id) | ||
} | ||
line.TraceID = traceID | ||
case "ts", "time", "@timestamp", "timestamp": | ||
for _, layout := range []string{ | ||
time.RFC3339Nano, | ||
time.RFC3339, | ||
ISO8601Millis, | ||
} { | ||
ts, err := time.Parse(layout, v) | ||
if err != nil { | ||
continue | ||
} | ||
line.Timestamp = otelstorage.Timestamp(ts.UnixNano()) | ||
} | ||
if line.Timestamp == 0 { | ||
attrs.PutStr(k, v) | ||
} | ||
default: | ||
// Try deduct a type. | ||
if v == "" { | ||
attrs.PutBool(k, true) | ||
return nil | ||
} | ||
dec := jx.DecodeBytes(val) | ||
switch dec.Next() { | ||
case jx.Number: | ||
n, err := dec.Num() | ||
if err == nil && n.IsInt() { | ||
i, err := n.Int64() | ||
if err == nil { | ||
attrs.PutInt(k, i) | ||
return nil | ||
} | ||
} else if err == nil { | ||
f, err := n.Float64() | ||
if err == nil { | ||
attrs.PutDouble(k, f) | ||
return nil | ||
} | ||
} | ||
case jx.Bool: | ||
v, err := dec.Bool() | ||
if err == nil { | ||
attrs.PutBool(k, v) | ||
return nil | ||
} | ||
} | ||
// Fallback. | ||
attrs.PutStr(k, v) | ||
} | ||
return nil | ||
}) | ||
if err := logfmt.Unmarshal(data, hf); err != nil { | ||
return nil, err | ||
} | ||
if attrs.Len() > 0 { | ||
line.Attrs = otelstorage.Attrs(attrs) | ||
} | ||
return line, nil | ||
} | ||
|
||
// Detect if line is parsable by this parser. | ||
func (LogFmtParser) Detect(line string) bool { | ||
return jx.DecodeStr(line).Next() == jx.Object | ||
} |
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 |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package logparser | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/go-faster/sdk/gold" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestLogFmtParser_Parse(t *testing.T) { | ||
const name = "logfmt" | ||
files, err := os.ReadDir(filepath.Join("_testdata", name)) | ||
require.NoError(t, err, "read testdata") | ||
|
||
for _, file := range files { | ||
t.Run(file.Name(), func(t *testing.T) { | ||
data, err := os.ReadFile(filepath.Join("_testdata", name, file.Name())) | ||
require.NoError(t, err, "read testdata") | ||
|
||
var parser LogFmtParser | ||
|
||
scanner := bufio.NewScanner(bytes.NewReader(data)) | ||
|
||
var i int | ||
for scanner.Scan() { | ||
s := strings.TrimSpace(scanner.Text()) | ||
if s == "" { | ||
continue | ||
} | ||
i++ | ||
t.Run(fmt.Sprintf("Line%02d", i), func(t *testing.T) { | ||
t.Logf("%s", s) | ||
line, err := parser.Parse([]byte(s)) | ||
require.NoError(t, err, "parse") | ||
fileName := fmt.Sprintf("%s_%s_%02d.json", | ||
name, strings.TrimSuffix(file.Name(), filepath.Ext(file.Name())), i, | ||
) | ||
gold.Str(t, line.String(), fileName) | ||
}) | ||
} | ||
}) | ||
} | ||
} |