add vendor package
[oom/registrator.git] / kube2msb / src / vendor / github.com / coreos / pkg / capnslog / logmap.go
1 // Copyright 2015 CoreOS, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package capnslog
16
17 import (
18         "errors"
19         "strings"
20         "sync"
21 )
22
23 // LogLevel is the set of all log levels.
24 type LogLevel int8
25
26 const (
27         // CRITICAL is the lowest log level; only errors which will end the program will be propagated.
28         CRITICAL LogLevel = iota - 1
29         // ERROR is for errors that are not fatal but lead to troubling behavior.
30         ERROR
31         // WARNING is for errors which are not fatal and not errors, but are unusual. Often sourced from misconfigurations.
32         WARNING
33         // NOTICE is for normal but significant conditions.
34         NOTICE
35         // INFO is a log level for common, everyday log updates.
36         INFO
37         // DEBUG is the default hidden level for more verbose updates about internal processes.
38         DEBUG
39         // TRACE is for (potentially) call by call tracing of programs.
40         TRACE
41 )
42
43 // Char returns a single-character representation of the log level.
44 func (l LogLevel) Char() string {
45         switch l {
46         case CRITICAL:
47                 return "C"
48         case ERROR:
49                 return "E"
50         case WARNING:
51                 return "W"
52         case NOTICE:
53                 return "N"
54         case INFO:
55                 return "I"
56         case DEBUG:
57                 return "D"
58         case TRACE:
59                 return "T"
60         default:
61                 panic("Unhandled loglevel")
62         }
63 }
64
65 // String returns a multi-character representation of the log level.
66 func (l LogLevel) String() string {
67         switch l {
68         case CRITICAL:
69                 return "CRITICAL"
70         case ERROR:
71                 return "ERROR"
72         case WARNING:
73                 return "WARNING"
74         case NOTICE:
75                 return "NOTICE"
76         case INFO:
77                 return "INFO"
78         case DEBUG:
79                 return "DEBUG"
80         case TRACE:
81                 return "TRACE"
82         default:
83                 panic("Unhandled loglevel")
84         }
85 }
86
87 // Update using the given string value. Fulfills the flag.Value interface.
88 func (l *LogLevel) Set(s string) error {
89         value, err := ParseLevel(s)
90         if err != nil {
91                 return err
92         }
93
94         *l = value
95         return nil
96 }
97
98 // ParseLevel translates some potential loglevel strings into their corresponding levels.
99 func ParseLevel(s string) (LogLevel, error) {
100         switch s {
101         case "CRITICAL", "C":
102                 return CRITICAL, nil
103         case "ERROR", "0", "E":
104                 return ERROR, nil
105         case "WARNING", "1", "W":
106                 return WARNING, nil
107         case "NOTICE", "2", "N":
108                 return NOTICE, nil
109         case "INFO", "3", "I":
110                 return INFO, nil
111         case "DEBUG", "4", "D":
112                 return DEBUG, nil
113         case "TRACE", "5", "T":
114                 return TRACE, nil
115         }
116         return CRITICAL, errors.New("couldn't parse log level " + s)
117 }
118
119 type RepoLogger map[string]*PackageLogger
120
121 type loggerStruct struct {
122         sync.Mutex
123         repoMap   map[string]RepoLogger
124         formatter Formatter
125 }
126
127 // logger is the global logger
128 var logger = new(loggerStruct)
129
130 // SetGlobalLogLevel sets the log level for all packages in all repositories
131 // registered with capnslog.
132 func SetGlobalLogLevel(l LogLevel) {
133         logger.Lock()
134         defer logger.Unlock()
135         for _, r := range logger.repoMap {
136                 r.setRepoLogLevelInternal(l)
137         }
138 }
139
140 // GetRepoLogger may return the handle to the repository's set of packages' loggers.
141 func GetRepoLogger(repo string) (RepoLogger, error) {
142         logger.Lock()
143         defer logger.Unlock()
144         r, ok := logger.repoMap[repo]
145         if !ok {
146                 return nil, errors.New("no packages registered for repo " + repo)
147         }
148         return r, nil
149 }
150
151 // MustRepoLogger returns the handle to the repository's packages' loggers.
152 func MustRepoLogger(repo string) RepoLogger {
153         r, err := GetRepoLogger(repo)
154         if err != nil {
155                 panic(err)
156         }
157         return r
158 }
159
160 // SetRepoLogLevel sets the log level for all packages in the repository.
161 func (r RepoLogger) SetRepoLogLevel(l LogLevel) {
162         logger.Lock()
163         defer logger.Unlock()
164         r.setRepoLogLevelInternal(l)
165 }
166
167 func (r RepoLogger) setRepoLogLevelInternal(l LogLevel) {
168         for _, v := range r {
169                 v.level = l
170         }
171 }
172
173 // ParseLogLevelConfig parses a comma-separated string of "package=loglevel", in
174 // order, and returns a map of the results, for use in SetLogLevel.
175 func (r RepoLogger) ParseLogLevelConfig(conf string) (map[string]LogLevel, error) {
176         setlist := strings.Split(conf, ",")
177         out := make(map[string]LogLevel)
178         for _, setstring := range setlist {
179                 setting := strings.Split(setstring, "=")
180                 if len(setting) != 2 {
181                         return nil, errors.New("oddly structured `pkg=level` option: " + setstring)
182                 }
183                 l, err := ParseLevel(setting[1])
184                 if err != nil {
185                         return nil, err
186                 }
187                 out[setting[0]] = l
188         }
189         return out, nil
190 }
191
192 // SetLogLevel takes a map of package names within a repository to their desired
193 // loglevel, and sets the levels appropriately. Unknown packages are ignored.
194 // "*" is a special package name that corresponds to all packages, and will be
195 // processed first.
196 func (r RepoLogger) SetLogLevel(m map[string]LogLevel) {
197         logger.Lock()
198         defer logger.Unlock()
199         if l, ok := m["*"]; ok {
200                 r.setRepoLogLevelInternal(l)
201         }
202         for k, v := range m {
203                 l, ok := r[k]
204                 if !ok {
205                         continue
206                 }
207                 l.level = v
208         }
209 }
210
211 // SetFormatter sets the formatting function for all logs.
212 func SetFormatter(f Formatter) {
213         logger.Lock()
214         defer logger.Unlock()
215         logger.formatter = f
216 }
217
218 // NewPackageLogger creates a package logger object.
219 // This should be defined as a global var in your package, referencing your repo.
220 func NewPackageLogger(repo string, pkg string) (p *PackageLogger) {
221         logger.Lock()
222         defer logger.Unlock()
223         if logger.repoMap == nil {
224                 logger.repoMap = make(map[string]RepoLogger)
225         }
226         r, rok := logger.repoMap[repo]
227         if !rok {
228                 logger.repoMap[repo] = make(RepoLogger)
229                 r = logger.repoMap[repo]
230         }
231         p, pok := r[pkg]
232         if !pok {
233                 r[pkg] = &PackageLogger{
234                         pkg:   pkg,
235                         level: INFO,
236                 }
237                 p = r[pkg]
238         }
239         return
240 }