summaryrefslogtreecommitdiff
path: root/mapr/logformat
diff options
context:
space:
mode:
authorPaul Bütow <pbuetow@mimecast.com>2020-01-09 20:30:15 +0000
committerPaul Bütow <pbuetow@mimecast.com>2020-01-09 20:30:15 +0000
commit3755a9911ecb05886577095f2b8cc8b9e4066a3a (patch)
tree86e24bc466986cb5c9c6d167a918e6064defeafc /mapr/logformat
Release of DTail v1.0.0v1.0.0
Diffstat (limited to 'mapr/logformat')
-rw-r--r--mapr/logformat/default.go23
-rw-r--r--mapr/logformat/default_test.go35
-rw-r--r--mapr/logformat/parser.go75
3 files changed, 133 insertions, 0 deletions
diff --git a/mapr/logformat/default.go b/mapr/logformat/default.go
new file mode 100644
index 0000000..f0df5bc
--- /dev/null
+++ b/mapr/logformat/default.go
@@ -0,0 +1,23 @@
+package logformat
+
+import (
+ "errors"
+ "strings"
+)
+
+// MakeFieldsDEFAULT is the default log file mapreduce parser.
+func (p *Parser) MakeFieldsDEFAULT(maprLine string) (map[string]string, error) {
+ fields := make(map[string]string, 20)
+ splitted := strings.Split(maprLine, "|")
+
+ fields["$hostname"] = p.hostname
+
+ for _, kv := range splitted {
+ keyAndValue := strings.SplitN(kv, "=", 2)
+ if len(keyAndValue) != 2 {
+ return fields, errors.New("Error parsing mapr token: " + kv)
+ }
+ fields[strings.ToLower(keyAndValue[0])] = keyAndValue[1]
+ }
+ return fields, nil
+}
diff --git a/mapr/logformat/default_test.go b/mapr/logformat/default_test.go
new file mode 100644
index 0000000..a3c47fb
--- /dev/null
+++ b/mapr/logformat/default_test.go
@@ -0,0 +1,35 @@
+package logformat
+
+import (
+ "testing"
+)
+
+func TestDefaultLogFormat(t *testing.T) {
+ parser, err := NewParser("default")
+ if err != nil {
+ t.Errorf("Unable to create parser: %s", err.Error())
+ }
+
+ fields, err := parser.MakeFields("foo=bar|baz=bay")
+
+ if err != nil {
+ t.Errorf("Unable to parse: %s", err.Error())
+ }
+
+ if bar, ok := fields["foo"]; !ok {
+ t.Errorf("Expected field 'foo', but no such field there\n")
+ } else if bar != "bar" {
+ t.Errorf("Expected 'bar' stored in field 'foo', but got '%s'\n", bar)
+ }
+
+ if bay, ok := fields["baz"]; !ok {
+ t.Errorf("Expected field 'baz', but no such field there\n")
+ } else if bay != "bay" {
+ t.Errorf("Expected 'bay' stored in field 'baz', but got '%s'\n", bay)
+ }
+
+ fields, err = parser.MakeFields("foo=bar|bazbay")
+ if err == nil {
+ t.Errorf("Expected error but didn't: %s", err.Error())
+ }
+}
diff --git a/mapr/logformat/parser.go b/mapr/logformat/parser.go
new file mode 100644
index 0000000..b7c8c5c
--- /dev/null
+++ b/mapr/logformat/parser.go
@@ -0,0 +1,75 @@
+package logformat
+
+import (
+ "dtail/logger"
+ "errors"
+ "fmt"
+ "os"
+ "reflect"
+ "strings"
+)
+
+// Parser is used to parse the mapreduce information from the server log files.
+type Parser struct {
+ hostname string
+ logFormatName string
+ makeFieldsFunc reflect.Value
+ makeFieldsReceiver reflect.Value
+}
+
+// NewParser returns a new log parser.
+func NewParser(logFormatName string) (*Parser, error) {
+ hostname, err := os.Hostname()
+
+ if err != nil {
+ return nil, err
+ }
+
+ p := Parser{
+ hostname: hostname,
+ }
+
+ err = p.reflectLogFormat(logFormatName)
+ if err != nil {
+ return nil, err
+ }
+
+ return &p, nil
+}
+
+// The aim of this is that everyone can plug in their own mapr log format
+// parsing method to DTail. Just add a method MakeFieldsMODULENAME to type
+// Parser. Whereas MODULENAME must be a upeprcase string.
+func (p *Parser) reflectLogFormat(logFormatName string) error {
+ methodName := fmt.Sprintf("MakeFields%s", strings.ToUpper(logFormatName))
+
+ rt := reflect.TypeOf(p)
+ method, ok := rt.MethodByName(methodName)
+ if !ok {
+ return errors.New("No such mapr log format module: " + methodName)
+ }
+
+ p.makeFieldsFunc = method.Func
+ p.makeFieldsReceiver = reflect.ValueOf(p)
+
+ return nil
+}
+
+// MakeFields is for returning the fields from a given log line.
+func (p *Parser) MakeFields(maprLine string) (fields map[string]string, err error) {
+ inputValues := []reflect.Value{p.makeFieldsReceiver, reflect.ValueOf(maprLine)}
+ returnValues := p.makeFieldsFunc.Call(inputValues)
+
+ errInterface := returnValues[1].Interface()
+
+ if errInterface == nil {
+ fields, err = returnValues[0].Interface().(map[string]string), nil
+ logger.Trace("parser.MakeFields", fields, err)
+ return
+ }
+
+ fields, err = returnValues[0].Interface().(map[string]string), errInterface.(error)
+ logger.Trace("parser.MakeFields", fields, err)
+
+ return
+}