diff options
| author | Paul Bütow <pbuetow@mimecast.com> | 2020-01-09 20:30:15 +0000 |
|---|---|---|
| committer | Paul Bütow <pbuetow@mimecast.com> | 2020-01-09 20:30:15 +0000 |
| commit | 3755a9911ecb05886577095f2b8cc8b9e4066a3a (patch) | |
| tree | 86e24bc466986cb5c9c6d167a918e6064defeafc /mapr/logformat | |
Release of DTail v1.0.0v1.0.0
Diffstat (limited to 'mapr/logformat')
| -rw-r--r-- | mapr/logformat/default.go | 23 | ||||
| -rw-r--r-- | mapr/logformat/default_test.go | 35 | ||||
| -rw-r--r-- | mapr/logformat/parser.go | 75 |
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 +} |
