|
9 | 9 | beego的日志设计部署思路来自于seelog,根据不同的level来记录日志,但是beego设计的日志系统比较轻量级,采用了系统的log.Logger接口,默认输出到os.Stdout,用户可以实现这个接口然后通过beego.SetLogger设置自定义的输出,详细的实现如下所示:
|
10 | 10 |
|
11 | 11 | ```Go
|
12 |
| - |
13 |
| - // Log levels to control the logging output. |
14 |
| - const ( |
15 |
| - LevelTrace = iota |
16 |
| - LevelDebug |
17 |
| - LevelInfo |
18 |
| - LevelWarning |
19 |
| - LevelError |
20 |
| - LevelCritical |
21 |
| - ) |
22 |
| - |
23 |
| - // logLevel controls the global log level used by the logger. |
24 |
| - var level = LevelTrace |
25 |
| - |
26 |
| - // LogLevel returns the global log level and can be used in |
27 |
| - // own implementations of the logger interface. |
28 |
| - func Level() int { |
29 |
| - return level |
30 |
| - } |
31 |
| - |
32 |
| - // SetLogLevel sets the global log level used by the simple |
33 |
| - // logger. |
34 |
| - func SetLevel(l int) { |
35 |
| - level = l |
36 |
| - } |
| 12 | + |
| 13 | +// Log levels to control the logging output. |
| 14 | +const ( |
| 15 | + LevelTrace = iota |
| 16 | + LevelDebug |
| 17 | + LevelInfo |
| 18 | + LevelWarning |
| 19 | + LevelError |
| 20 | + LevelCritical |
| 21 | +) |
| 22 | + |
| 23 | +// logLevel controls the global log level used by the logger. |
| 24 | +var level = LevelTrace |
| 25 | + |
| 26 | +// LogLevel returns the global log level and can be used in |
| 27 | +// own implementations of the logger interface. |
| 28 | +func Level() int { |
| 29 | + return level |
| 30 | +} |
| 31 | + |
| 32 | +// SetLogLevel sets the global log level used by the simple |
| 33 | +// logger. |
| 34 | +func SetLevel(l int) { |
| 35 | + level = l |
| 36 | +} |
37 | 37 | ```
|
38 | 38 | 上面这一段实现了日志系统的日志分级,默认的级别是Trace,用户通过SetLevel可以设置不同的分级。
|
39 | 39 | ```Go
|
40 | 40 |
|
41 |
| - // logger references the used application logger. |
42 |
| - var BeeLogger = log.New(os.Stdout, "", log.Ldate|log.Ltime) |
43 |
| - |
44 |
| - // SetLogger sets a new logger. |
45 |
| - func SetLogger(l *log.Logger) { |
46 |
| - BeeLogger = l |
47 |
| - } |
48 |
| - |
49 |
| - // Trace logs a message at trace level. |
50 |
| - func Trace(v ...interface{}) { |
51 |
| - if level <= LevelTrace { |
52 |
| - BeeLogger.Printf("[T] %v\n", v) |
53 |
| - } |
| 41 | +// logger references the used application logger. |
| 42 | +var BeeLogger = log.New(os.Stdout, "", log.Ldate|log.Ltime) |
| 43 | + |
| 44 | +// SetLogger sets a new logger. |
| 45 | +func SetLogger(l *log.Logger) { |
| 46 | + BeeLogger = l |
| 47 | +} |
| 48 | + |
| 49 | +// Trace logs a message at trace level. |
| 50 | +func Trace(v ...interface{}) { |
| 51 | + if level <= LevelTrace { |
| 52 | + BeeLogger.Printf("[T] %v\n", v) |
54 | 53 | }
|
55 |
| - |
56 |
| - // Debug logs a message at debug level. |
57 |
| - func Debug(v ...interface{}) { |
58 |
| - if level <= LevelDebug { |
59 |
| - BeeLogger.Printf("[D] %v\n", v) |
60 |
| - } |
| 54 | +} |
| 55 | + |
| 56 | +// Debug logs a message at debug level. |
| 57 | +func Debug(v ...interface{}) { |
| 58 | + if level <= LevelDebug { |
| 59 | + BeeLogger.Printf("[D] %v\n", v) |
61 | 60 | }
|
62 |
| - |
63 |
| - // Info logs a message at info level. |
64 |
| - func Info(v ...interface{}) { |
65 |
| - if level <= LevelInfo { |
66 |
| - BeeLogger.Printf("[I] %v\n", v) |
67 |
| - } |
| 61 | +} |
| 62 | + |
| 63 | +// Info logs a message at info level. |
| 64 | +func Info(v ...interface{}) { |
| 65 | + if level <= LevelInfo { |
| 66 | + BeeLogger.Printf("[I] %v\n", v) |
68 | 67 | }
|
69 |
| - |
70 |
| - // Warning logs a message at warning level. |
71 |
| - func Warn(v ...interface{}) { |
72 |
| - if level <= LevelWarning { |
73 |
| - BeeLogger.Printf("[W] %v\n", v) |
74 |
| - } |
| 68 | +} |
| 69 | + |
| 70 | +// Warning logs a message at warning level. |
| 71 | +func Warn(v ...interface{}) { |
| 72 | + if level <= LevelWarning { |
| 73 | + BeeLogger.Printf("[W] %v\n", v) |
75 | 74 | }
|
76 |
| - |
77 |
| - // Error logs a message at error level. |
78 |
| - func Error(v ...interface{}) { |
79 |
| - if level <= LevelError { |
80 |
| - BeeLogger.Printf("[E] %v\n", v) |
81 |
| - } |
| 75 | +} |
| 76 | + |
| 77 | +// Error logs a message at error level. |
| 78 | +func Error(v ...interface{}) { |
| 79 | + if level <= LevelError { |
| 80 | + BeeLogger.Printf("[E] %v\n", v) |
82 | 81 | }
|
83 |
| - |
84 |
| - // Critical logs a message at critical level. |
85 |
| - func Critical(v ...interface{}) { |
86 |
| - if level <= LevelCritical { |
87 |
| - BeeLogger.Printf("[C] %v\n", v) |
88 |
| - } |
| 82 | +} |
| 83 | + |
| 84 | +// Critical logs a message at critical level. |
| 85 | +func Critical(v ...interface{}) { |
| 86 | + if level <= LevelCritical { |
| 87 | + BeeLogger.Printf("[C] %v\n", v) |
89 | 88 | }
|
| 89 | +} |
90 | 90 | ```
|
91 | 91 | 上面这一段代码默认初始化了一个BeeLogger对象,默认输出到os.Stdout,用户可以通过beego.SetLogger来设置实现了logger的接口输出。这里面实现了六个函数:
|
92 | 92 |
|
@@ -121,134 +121,134 @@ beego的日志设计部署思路来自于seelog,根据不同的level来记录
|
121 | 121 | 首先定义了一些ini配置文件的一些全局性常量 :
|
122 | 122 | ```Go
|
123 | 123 |
|
124 |
| - var ( |
125 |
| - bComment = []byte{'#'} |
126 |
| - bEmpty = []byte{} |
127 |
| - bEqual = []byte{'='} |
128 |
| - bDQuote = []byte{'"'} |
129 |
| - ) |
| 124 | +var ( |
| 125 | + bComment = []byte{'#'} |
| 126 | + bEmpty = []byte{} |
| 127 | + bEqual = []byte{'='} |
| 128 | + bDQuote = []byte{'"'} |
| 129 | +) |
130 | 130 | ```
|
131 | 131 | 定义了配置文件的格式:
|
132 | 132 | ```Go
|
133 | 133 |
|
134 |
| - // A Config represents the configuration. |
135 |
| - type Config struct { |
136 |
| - filename string |
137 |
| - comment map[int][]string // id: []{comment, key...}; id 1 is for main comment. |
138 |
| - data map[string]string // key: value |
139 |
| - offset map[string]int64 // key: offset; for editing. |
140 |
| - sync.RWMutex |
141 |
| - } |
| 134 | +// A Config represents the configuration. |
| 135 | +type Config struct { |
| 136 | + filename string |
| 137 | + comment map[int][]string // id: []{comment, key...}; id 1 is for main comment. |
| 138 | + data map[string]string // key: value |
| 139 | + offset map[string]int64 // key: offset; for editing. |
| 140 | + sync.RWMutex |
| 141 | +} |
142 | 142 | ```
|
143 | 143 | 定义了解析文件的函数,解析文件的过程是打开文件,然后一行一行的读取,解析注释、空行和key=value数据:
|
144 | 144 | ```Go
|
145 | 145 |
|
146 |
| - // ParseFile creates a new Config and parses the file configuration from the |
147 |
| - // named file. |
148 |
| - func LoadConfig(name string) (*Config, error) { |
149 |
| - file, err := os.Open(name) |
150 |
| - if err != nil { |
151 |
| - return nil, err |
| 146 | +// ParseFile creates a new Config and parses the file configuration from the |
| 147 | +// named file. |
| 148 | +func LoadConfig(name string) (*Config, error) { |
| 149 | + file, err := os.Open(name) |
| 150 | + if err != nil { |
| 151 | + return nil, err |
| 152 | + } |
| 153 | + |
| 154 | + cfg := &Config{ |
| 155 | + file.Name(), |
| 156 | + make(map[int][]string), |
| 157 | + make(map[string]string), |
| 158 | + make(map[string]int64), |
| 159 | + sync.RWMutex{}, |
| 160 | + } |
| 161 | + cfg.Lock() |
| 162 | + defer cfg.Unlock() |
| 163 | + defer file.Close() |
| 164 | + |
| 165 | + var comment bytes.Buffer |
| 166 | + buf := bufio.NewReader(file) |
| 167 | + |
| 168 | + for nComment, off := 0, int64(1); ; { |
| 169 | + line, _, err := buf.ReadLine() |
| 170 | + if err == io.EOF { |
| 171 | + break |
152 | 172 | }
|
153 |
| - |
154 |
| - cfg := &Config{ |
155 |
| - file.Name(), |
156 |
| - make(map[int][]string), |
157 |
| - make(map[string]string), |
158 |
| - make(map[string]int64), |
159 |
| - sync.RWMutex{}, |
| 173 | + if bytes.Equal(line, bEmpty) { |
| 174 | + continue |
160 | 175 | }
|
161 |
| - cfg.Lock() |
162 |
| - defer cfg.Unlock() |
163 |
| - defer file.Close() |
164 |
| - |
165 |
| - var comment bytes.Buffer |
166 |
| - buf := bufio.NewReader(file) |
167 |
| - |
168 |
| - for nComment, off := 0, int64(1); ; { |
169 |
| - line, _, err := buf.ReadLine() |
170 |
| - if err == io.EOF { |
171 |
| - break |
172 |
| - } |
173 |
| - if bytes.Equal(line, bEmpty) { |
174 |
| - continue |
175 |
| - } |
176 |
| - |
177 |
| - off += int64(len(line)) |
178 |
| - |
179 |
| - if bytes.HasPrefix(line, bComment) { |
180 |
| - line = bytes.TrimLeft(line, "#") |
181 |
| - line = bytes.TrimLeftFunc(line, unicode.IsSpace) |
182 |
| - comment.Write(line) |
183 |
| - comment.WriteByte('\n') |
184 |
| - continue |
185 |
| - } |
186 |
| - if comment.Len() != 0 { |
187 |
| - cfg.comment[nComment] = []string{comment.String()} |
188 |
| - comment.Reset() |
189 |
| - nComment++ |
190 |
| - } |
191 |
| - |
192 |
| - val := bytes.SplitN(line, bEqual, 2) |
193 |
| - if bytes.HasPrefix(val[1], bDQuote) { |
194 |
| - val[1] = bytes.Trim(val[1], `"`) |
195 |
| - } |
196 |
| - |
197 |
| - key := strings.TrimSpace(string(val[0])) |
198 |
| - cfg.comment[nComment-1] = append(cfg.comment[nComment-1], key) |
199 |
| - cfg.data[key] = strings.TrimSpace(string(val[1])) |
200 |
| - cfg.offset[key] = off |
| 176 | + |
| 177 | + off += int64(len(line)) |
| 178 | + |
| 179 | + if bytes.HasPrefix(line, bComment) { |
| 180 | + line = bytes.TrimLeft(line, "#") |
| 181 | + line = bytes.TrimLeftFunc(line, unicode.IsSpace) |
| 182 | + comment.Write(line) |
| 183 | + comment.WriteByte('\n') |
| 184 | + continue |
201 | 185 | }
|
202 |
| - return cfg, nil |
| 186 | + if comment.Len() != 0 { |
| 187 | + cfg.comment[nComment] = []string{comment.String()} |
| 188 | + comment.Reset() |
| 189 | + nComment++ |
| 190 | + } |
| 191 | + |
| 192 | + val := bytes.SplitN(line, bEqual, 2) |
| 193 | + if bytes.HasPrefix(val[1], bDQuote) { |
| 194 | + val[1] = bytes.Trim(val[1], `"`) |
| 195 | + } |
| 196 | + |
| 197 | + key := strings.TrimSpace(string(val[0])) |
| 198 | + cfg.comment[nComment-1] = append(cfg.comment[nComment-1], key) |
| 199 | + cfg.data[key] = strings.TrimSpace(string(val[1])) |
| 200 | + cfg.offset[key] = off |
203 | 201 | }
|
| 202 | + return cfg, nil |
| 203 | +} |
204 | 204 | ```
|
205 | 205 | 下面实现了一些读取配置文件的函数,返回的值确定为bool、int、float64或string:
|
206 | 206 | ```Go
|
207 | 207 |
|
208 |
| - // Bool returns the boolean value for a given key. |
209 |
| - func (c *Config) Bool(key string) (bool, error) { |
210 |
| - return strconv.ParseBool(c.data[key]) |
211 |
| - } |
212 |
| - |
213 |
| - // Int returns the integer value for a given key. |
214 |
| - func (c *Config) Int(key string) (int, error) { |
215 |
| - return strconv.Atoi(c.data[key]) |
216 |
| - } |
217 |
| - |
218 |
| - // Float returns the float value for a given key. |
219 |
| - func (c *Config) Float(key string) (float64, error) { |
220 |
| - return strconv.ParseFloat(c.data[key], 64) |
221 |
| - } |
222 |
| - |
223 |
| - // String returns the string value for a given key. |
224 |
| - func (c *Config) String(key string) string { |
225 |
| - return c.data[key] |
226 |
| - } |
| 208 | +// Bool returns the boolean value for a given key. |
| 209 | +func (c *Config) Bool(key string) (bool, error) { |
| 210 | + return strconv.ParseBool(c.data[key]) |
| 211 | +} |
| 212 | + |
| 213 | +// Int returns the integer value for a given key. |
| 214 | +func (c *Config) Int(key string) (int, error) { |
| 215 | + return strconv.Atoi(c.data[key]) |
| 216 | +} |
| 217 | + |
| 218 | +// Float returns the float value for a given key. |
| 219 | +func (c *Config) Float(key string) (float64, error) { |
| 220 | + return strconv.ParseFloat(c.data[key], 64) |
| 221 | +} |
| 222 | + |
| 223 | +// String returns the string value for a given key. |
| 224 | +func (c *Config) String(key string) string { |
| 225 | + return c.data[key] |
| 226 | +} |
227 | 227 | ```
|
228 | 228 | ## 应用指南
|
229 | 229 | 下面这个函数是我一个应用中的例子,用来获取远程url地址的json数据,实现如下:
|
230 | 230 | ```Go
|
231 | 231 |
|
232 |
| - func GetJson() { |
233 |
| - resp, err := http.Get(beego.AppConfig.String("url")) |
234 |
| - if err != nil { |
235 |
| - beego.Critical("http get info error") |
236 |
| - return |
237 |
| - } |
238 |
| - defer resp.Body.Close() |
239 |
| - body, err := ioutil.ReadAll(resp.Body) |
240 |
| - err = json.Unmarshal(body, &AllInfo) |
241 |
| - if err != nil { |
242 |
| - beego.Critical("error:", err) |
243 |
| - } |
| 232 | +func GetJson() { |
| 233 | + resp, err := http.Get(beego.AppConfig.String("url")) |
| 234 | + if err != nil { |
| 235 | + beego.Critical("http get info error") |
| 236 | + return |
244 | 237 | }
|
| 238 | + defer resp.Body.Close() |
| 239 | + body, err := ioutil.ReadAll(resp.Body) |
| 240 | + err = json.Unmarshal(body, &AllInfo) |
| 241 | + if err != nil { |
| 242 | + beego.Critical("error:", err) |
| 243 | + } |
| 244 | +} |
245 | 245 | ```
|
246 | 246 | 函数中调用了框架的日志函数`beego.Critical`函数用来报错,调用了`beego.AppConfig.String("url")`用来获取配置文件中的信息,配置文件的信息如下(app.conf):
|
247 | 247 | ```Go
|
248 | 248 |
|
249 |
| - appname = hs |
250 |
| - url ="http://www.api.com/api.html" |
251 |
| - |
| 249 | +appname = hs |
| 250 | +url ="http://www.api.com/api.html" |
| 251 | + |
252 | 252 | ```
|
253 | 253 | ## links
|
254 | 254 | * [目录](<preface.md>)
|
|
0 commit comments