1package hclog
2
3import (
4	"bytes"
5	"strings"
6)
7
8// Provides a io.Writer to shim the data out of *log.Logger
9// and back into our Logger. This is basically the only way to
10// build upon *log.Logger.
11type stdlogAdapter struct {
12	log         Logger
13	inferLevels bool
14	forceLevel  Level
15}
16
17// Take the data, infer the levels if configured, and send it through
18// a regular Logger.
19func (s *stdlogAdapter) Write(data []byte) (int, error) {
20	str := string(bytes.TrimRight(data, " \t\n"))
21
22	if s.forceLevel != NoLevel {
23		// Use pickLevel to strip log levels included in the line since we are
24		// forcing the level
25		_, str := s.pickLevel(str)
26
27		// Log at the forced level
28		switch s.forceLevel {
29		case Trace:
30			s.log.Trace(str)
31		case Debug:
32			s.log.Debug(str)
33		case Info:
34			s.log.Info(str)
35		case Warn:
36			s.log.Warn(str)
37		case Error:
38			s.log.Error(str)
39		default:
40			s.log.Info(str)
41		}
42	} else if s.inferLevels {
43		level, str := s.pickLevel(str)
44		switch level {
45		case Trace:
46			s.log.Trace(str)
47		case Debug:
48			s.log.Debug(str)
49		case Info:
50			s.log.Info(str)
51		case Warn:
52			s.log.Warn(str)
53		case Error:
54			s.log.Error(str)
55		default:
56			s.log.Info(str)
57		}
58	} else {
59		s.log.Info(str)
60	}
61
62	return len(data), nil
63}
64
65// Detect, based on conventions, what log level this is.
66func (s *stdlogAdapter) pickLevel(str string) (Level, string) {
67	switch {
68	case strings.HasPrefix(str, "[DEBUG]"):
69		return Debug, strings.TrimSpace(str[7:])
70	case strings.HasPrefix(str, "[TRACE]"):
71		return Trace, strings.TrimSpace(str[7:])
72	case strings.HasPrefix(str, "[INFO]"):
73		return Info, strings.TrimSpace(str[6:])
74	case strings.HasPrefix(str, "[WARN]"):
75		return Warn, strings.TrimSpace(str[7:])
76	case strings.HasPrefix(str, "[ERROR]"):
77		return Error, strings.TrimSpace(str[7:])
78	case strings.HasPrefix(str, "[ERR]"):
79		return Error, strings.TrimSpace(str[5:])
80	default:
81		return Info, str
82	}
83}
84