Add API Framework Revel Source Files
[iec.git] / src / foundation / api / revel / logger / revel_logger.go
1 package logger
2
3 import (
4         "fmt"
5         "github.com/revel/log15"
6         "log"
7         "os"
8 )
9
10 // This type implements the MultiLogger
11 type RevelLogger struct {
12         log15.Logger
13 }
14
15 // Set the systems default logger
16 // Default logs will be captured and handled by revel at level info
17 func SetDefaultLog(fromLog MultiLogger) {
18         log.SetOutput(loggerRewrite{Logger: fromLog, Level: log15.LvlInfo, hideDeprecated: true})
19         // No need to show date and time, that will be logged with revel
20         log.SetFlags(0)
21 }
22
23 func (rl *RevelLogger) Debugf(msg string, param ...interface{}) {
24         rl.Debug(fmt.Sprintf(msg, param...))
25 }
26
27 // Print a formatted info message
28 func (rl *RevelLogger) Infof(msg string, param ...interface{}) {
29         rl.Info(fmt.Sprintf(msg, param...))
30 }
31
32 // Print a formatted warn message
33 func (rl *RevelLogger) Warnf(msg string, param ...interface{}) {
34         rl.Warn(fmt.Sprintf(msg, param...))
35 }
36
37 // Print a formatted error message
38 func (rl *RevelLogger) Errorf(msg string, param ...interface{}) {
39         rl.Error(fmt.Sprintf(msg, param...))
40 }
41
42 // Print a formatted critical message
43 func (rl *RevelLogger) Critf(msg string, param ...interface{}) {
44         rl.Crit(fmt.Sprintf(msg, param...))
45 }
46
47 // Print a formatted fatal message
48 func (rl *RevelLogger) Fatalf(msg string, param ...interface{}) {
49         rl.Fatal(fmt.Sprintf(msg, param...))
50 }
51
52 // Print a formatted panic message
53 func (rl *RevelLogger) Panicf(msg string, param ...interface{}) {
54         rl.Panic(fmt.Sprintf(msg, param...))
55 }
56
57 // Print a critical message and call os.Exit(1)
58 func (rl *RevelLogger) Fatal(msg string, ctx ...interface{}) {
59         rl.Crit(msg, ctx...)
60         os.Exit(1)
61 }
62
63 // Print a critical message and panic
64 func (rl *RevelLogger) Panic(msg string, ctx ...interface{}) {
65         rl.Crit(msg, ctx...)
66         panic(msg)
67 }
68
69 // Override log15 method
70 func (rl *RevelLogger) New(ctx ...interface{}) MultiLogger {
71         old := &RevelLogger{Logger: rl.Logger.New(ctx...)}
72         return old
73 }
74
75 // Set the stack level to check for the caller
76 func (rl *RevelLogger) SetStackDepth(amount int) MultiLogger {
77         rl.Logger.SetStackDepth(amount) // Ignore the logger returned
78         return rl
79 }
80
81 // Create a new logger
82 func New(ctx ...interface{}) MultiLogger {
83         r := &RevelLogger{Logger: log15.New(ctx...)}
84         r.SetStackDepth(1)
85         return r
86 }
87
88 // Set the handler in the Logger
89 func (rl *RevelLogger) SetHandler(h LogHandler) {
90         rl.Logger.SetHandler(callHandler(h.Log))
91 }
92
93 // The function wrapper to implement the callback
94 type callHandler func(r *Record) error
95
96 // Log implementation, reads the record and extracts the details from the log record
97 // Hiding the implementation.
98 func (c callHandler) Log(log *log15.Record) error {
99         ctx := log.Ctx
100         var ctxMap ContextMap
101         if len(ctx) > 0 {
102                 ctxMap = make(ContextMap, len(ctx)/2)
103
104                 for i := 0; i < len(ctx); i += 2 {
105                         v := ctx[i]
106                         key, ok := v.(string)
107                         if !ok {
108                                 key = fmt.Sprintf("LOGGER_INVALID_KEY %v", v)
109                         }
110                         var value interface{}
111                         if len(ctx) > i+1 {
112                                 value = ctx[i+1]
113                         } else {
114                                 value = "LOGGER_VALUE_MISSING"
115                         }
116                         ctxMap[key] = value
117                 }
118         } else {
119                 ctxMap = make(ContextMap, 0)
120         }
121         r := &Record{Message: log.Msg, Context: ctxMap, Time: log.Time, Level: LogLevel(log.Lvl), Call: CallStack(log.Call)}
122         return c(r)
123 }
124
125 // Internally used contextMap, allows conversion of map to map[string]string
126 type ContextMap map[string]interface{}
127
128 // Convert the context map to be string only values, any non string values are ignored
129 func (m ContextMap) StringMap() (newMap map[string]string) {
130         if m != nil {
131                 newMap = map[string]string{}
132                 for key, value := range m {
133                         if svalue, isstring := value.(string); isstring {
134                                 newMap[key] = svalue
135                         }
136                 }
137         }
138         return
139 }
140 func (m ContextMap) Add(key string, value interface{}) {
141         m[key] = value
142 }