open-nomad/client/driver/logcollector/parser.go

162 lines
3.6 KiB
Go
Raw Normal View History

2016-02-13 00:20:04 +00:00
// +build !windows
package logcollector
2016-02-10 15:52:15 +00:00
import (
"bufio"
2016-02-10 20:09:07 +00:00
"fmt"
2016-02-10 15:52:15 +00:00
"log"
2016-02-10 20:09:07 +00:00
"log/syslog"
"strconv"
2016-02-10 15:52:15 +00:00
"time"
"github.com/jeromer/syslogparser"
)
2016-02-10 23:23:25 +00:00
// Errors related to parsing priority
2016-02-10 20:09:07 +00:00
var (
ErrPriorityNoStart = fmt.Errorf("No start char found for priority")
ErrPriorityEmpty = fmt.Errorf("Priority field empty")
ErrPriorityNoEnd = fmt.Errorf("No end char found for priority")
ErrPriorityTooShort = fmt.Errorf("Priority field too short")
ErrPriorityTooLong = fmt.Errorf("Priority field too long")
ErrPriorityNonDigit = fmt.Errorf("Non digit found in priority")
)
2016-02-10 23:23:25 +00:00
// Priority header and ending characters
2016-02-10 20:09:07 +00:00
const (
PRI_PART_START = '<'
PRI_PART_END = '>'
)
2016-02-10 23:23:25 +00:00
// Priority holds all the priority bits in a syslog log line
2016-02-10 20:09:07 +00:00
type Priority struct {
Pri int
Facility syslog.Priority
Severity syslog.Priority
2016-02-10 20:09:07 +00:00
}
2016-02-10 23:23:25 +00:00
// DockerLogParser parses a line of log message that the docker daemon ships
2016-02-10 15:52:15 +00:00
type DockerLogParser struct {
2016-02-10 23:23:25 +00:00
line []byte
content []byte
severity Priority
2016-02-10 15:52:15 +00:00
log *log.Logger
}
2016-02-10 23:23:25 +00:00
// NewDockerLogParser creates a new DockerLogParser
2016-02-10 15:52:15 +00:00
func NewDockerLogParser(line []byte) *DockerLogParser {
return &DockerLogParser{line: line}
}
2016-02-10 23:23:25 +00:00
// Parse parses a syslog log line
2016-02-10 15:52:15 +00:00
func (d *DockerLogParser) Parse() error {
2016-02-10 23:23:25 +00:00
severity, _, _ := d.parsePriority(d.line)
msgIdx := d.logContentIndex(d.line)
d.severity = severity
d.content = d.line[msgIdx:]
2016-02-10 15:52:15 +00:00
return nil
}
2016-02-10 23:23:25 +00:00
// Dump creates a map of the parsed log line and severity
2016-02-10 15:52:15 +00:00
func (d *DockerLogParser) Dump() syslogparser.LogParts {
return map[string]interface{}{
2016-02-10 23:23:25 +00:00
"content": d.content,
"severity": d.severity,
2016-02-10 20:09:07 +00:00
}
}
2016-02-10 23:23:25 +00:00
// logContentIndex finds out the index of the start index of the content in a
// syslog line
func (d *DockerLogParser) logContentIndex(line []byte) int {
cursor := 0
numSpace := 0
for i := 0; i < len(line); i++ {
if line[i] == ' ' {
numSpace += 1
if numSpace == 1 {
cursor = i
break
}
}
}
for i := cursor; i < len(line); i++ {
if line[i] == ':' {
cursor = i
break
}
}
return cursor + 1
}
2016-02-10 23:23:25 +00:00
// parsePriority parses the priority in a syslog message
2016-02-10 20:09:07 +00:00
func (d *DockerLogParser) parsePriority(line []byte) (Priority, int, error) {
cursor := 0
pri := d.newPriority(0)
if len(line) <= 0 {
return pri, cursor, ErrPriorityEmpty
}
if line[cursor] != PRI_PART_START {
return pri, cursor, ErrPriorityNoStart
}
i := 1
priDigit := 0
for i < len(line) {
if i >= 5 {
return pri, cursor, ErrPriorityTooLong
}
c := line[i]
if c == PRI_PART_END {
if i == 1 {
return pri, cursor, ErrPriorityTooShort
}
cursor = i + 1
return d.newPriority(priDigit), cursor, nil
}
if d.isDigit(c) {
v, e := strconv.Atoi(string(c))
if e != nil {
return pri, cursor, e
}
priDigit = (priDigit * 10) + v
} else {
return pri, cursor, ErrPriorityNonDigit
}
i++
}
return pri, cursor, ErrPriorityNoEnd
}
2016-02-10 23:23:25 +00:00
// isDigit checks if a byte is a numeric char
2016-02-10 20:09:07 +00:00
func (d *DockerLogParser) isDigit(c byte) bool {
return c >= '0' && c <= '9'
}
2016-02-10 23:23:25 +00:00
// newPriority creates a new default priority
2016-02-10 20:09:07 +00:00
func (d *DockerLogParser) newPriority(p int) Priority {
// The Priority value is calculated by first multiplying the Facility
// number by 8 and then adding the numerical value of the Severity.
return Priority{
Pri: p,
Facility: syslog.Priority(p / 8),
Severity: syslog.Priority(p % 8),
2016-02-10 15:52:15 +00:00
}
}
func (d *DockerLogParser) Location(location *time.Location) {
}
2016-02-10 23:23:25 +00:00
// CustomParser is a parser to parse docker syslog lines
2016-02-10 15:52:15 +00:00
type CustomParser struct {
logger *log.Logger
}
func (c *CustomParser) GetParser(line []byte) syslogparser.LogParser {
return NewDockerLogParser(line)
}
func (c *CustomParser) GetSplitFunc() bufio.SplitFunc {
return nil
}