|
| 1 | +--- |
| 2 | +date: "2019-04-02T17:06:00+01:00" |
| 3 | +title: "Advanced: Logging Configuration" |
| 4 | +slug: "logging-configuration" |
| 5 | +weight: 55 |
| 6 | +toc: true |
| 7 | +draft: false |
| 8 | +menu: |
| 9 | + sidebar: |
| 10 | + parent: "advanced" |
| 11 | + name: "Logging Configuration" |
| 12 | + weight: 55 |
| 13 | + identifier: "logging-configuration" |
| 14 | +--- |
| 15 | + |
| 16 | +# Logging Configuration |
| 17 | + |
| 18 | +The logging framework has been revamped in Gitea 1.9.0. |
| 19 | + |
| 20 | +## Log Groups |
| 21 | + |
| 22 | +The fundamental thing to be aware of in Gitea is that there are several |
| 23 | +log groups: |
| 24 | + |
| 25 | +* The "Default" logger |
| 26 | +* The Macaron logger |
| 27 | +* The Router logger |
| 28 | +* The Access logger |
| 29 | +* The XORM logger |
| 30 | +* A logger called the `GitLogger` which is used during hooks. |
| 31 | + |
| 32 | +There is also the go log logger. |
| 33 | + |
| 34 | +### The go log logger |
| 35 | + |
| 36 | +Go provides its own extremely basic logger in the `log` package, |
| 37 | +however, this is not sufficient for our purposes as it does not provide |
| 38 | +a way of logging at multiple levels, nor does it provide a good way of |
| 39 | +controlling where these logs are logged except through setting of a |
| 40 | +writer. |
| 41 | + |
| 42 | +We have therefore redirected this logger to our Default logger, and we |
| 43 | +will log anything that is logged using the go logger at the INFO level. |
| 44 | + |
| 45 | +### The "Default" logger |
| 46 | + |
| 47 | +Calls to `log.Info`, `log.Debug`, `log.Error` etc. from the `code.gitea.io/gitea/modules/log` package will log to this logger. |
| 48 | + |
| 49 | +You can configure the outputs of this logger by setting the `MODE` |
| 50 | +value in the `[log]` section of the configuration. |
| 51 | + |
| 52 | +Each output sublogger is configured in a separate `[log.sublogger]` |
| 53 | +section, but there are certain default values. These will not be inherited from the `[log]` section: |
| 54 | + |
| 55 | +* `FLAGS` is `stdflags` (Equal to |
| 56 | +`date,time,medfile,shortfuncname,levelinitial`) |
| 57 | +* `FILE_NAME` will default to `%(ROOT_PATH)/gitea.log` |
| 58 | +* `EXPRESSION` will default to `""` |
| 59 | +* `PREFIX` will default to `""` |
| 60 | + |
| 61 | +The provider type of the sublogger can be set using the `MODE` value in |
| 62 | +its subsection, but will default to the name. This allows you to have |
| 63 | +multiple subloggers that will log to files. |
| 64 | + |
| 65 | +### The "Macaron" logger |
| 66 | + |
| 67 | +By default Macaron will log to its own go `log` instance. This writes |
| 68 | +to `os.Stdout`. You can redirect this log to a Gitea configurable logger |
| 69 | +through setting the `ENABLE_MACARON_REDIRECT` setting in the `[log]` |
| 70 | +section which you can configure the outputs of by setting the `MACARON` |
| 71 | +value in the `[log]` section of the configuration. `MACARON` defaults |
| 72 | +to `file` if unset. |
| 73 | + |
| 74 | +Each output sublogger for this logger is configured in |
| 75 | +`[log.sublogger.macaron]` sections. There are certain default values |
| 76 | +which will not be inherited from the `[log]` or relevant |
| 77 | +`[log.sublogger]` sections: |
| 78 | + |
| 79 | +* `FLAGS` is `stdflags` (Equal to |
| 80 | +`date,time,medfile,shortfuncname,levelinitial`) |
| 81 | +* `FILE_NAME` will default to `%(ROOT_PATH)/macaron.log` |
| 82 | +* `EXPRESSION` will default to `""` |
| 83 | +* `PREFIX` will default to `""` |
| 84 | + |
| 85 | +NB: You can redirect the macaron logger to send its events to the gitea |
| 86 | +log using the value: `MACARON = ,` |
| 87 | + |
| 88 | +### The "Router" logger |
| 89 | + |
| 90 | +There are two types of Router log. By default Macaron send its own |
| 91 | +router log which will be directed to Macaron's go `log`, however if you |
| 92 | +`ENABLE_MACARON_REDIRECT` you will enable Gitea's router log. You can |
| 93 | +disable both types of Router log by setting `DISABLE_ROUTER_LOG`. |
| 94 | + |
| 95 | +If you enable the redirect, you can configure the outputs of this |
| 96 | +router log by setting the `ROUTER` value in the `[log]` section of the |
| 97 | +configuration. `ROUTER` will default to `console` if unset. The Gitea |
| 98 | +Router logs the same data as the Macaron log but has slightly different |
| 99 | +coloring. It logs at the `Info` level by default, but this can be |
| 100 | +changed if desired by setting the `ROUTER_LOG_LEVEL` value. |
| 101 | + |
| 102 | +Each output sublogger for this logger is configured in |
| 103 | +`[log.sublogger.router]` sections. There are certain default values |
| 104 | +which will not be inherited from the `[log]` or relevant |
| 105 | +`[log.sublogger]` sections: |
| 106 | + |
| 107 | +* `FILE_NAME` will default to `%(ROOT_PATH)/router.log` |
| 108 | +* `FLAGS` defaults to `date,time` |
| 109 | +* `EXPRESSION` will default to `""` |
| 110 | +* `PREFIX` will default to `""` |
| 111 | + |
| 112 | +NB: You can redirect the router logger to send its events to the Gitea |
| 113 | +log using the value: `ROUTER = ,` |
| 114 | + |
| 115 | +### The "Access" logger |
| 116 | + |
| 117 | +The Access logger is a new logger for version 1.9. It provides a NCSA |
| 118 | +Common Log compliant log format. It's highly configurable but caution |
| 119 | +should be taken when changing its template. The main benefit of this |
| 120 | +logger is that Gitea can now log accesses in a standard log format so |
| 121 | +standard tools may be used. |
| 122 | + |
| 123 | +You can enable this logger using `ENABLE_ACCESS_LOG`. Its outputs are |
| 124 | +configured by setting the `ACCESS` value in the `[log]` section of the |
| 125 | +configuration. `ACCESS` defaults to `file` if unset. |
| 126 | + |
| 127 | +Each output sublogger for this logger is configured in |
| 128 | +`[log.sublogger.access]` sections. There are certain default values |
| 129 | +which will not be inherited from the `[log]` or relevant |
| 130 | +`[log.sublogger]` sections: |
| 131 | + |
| 132 | +* `FILE_NAME` will default to `%(ROOT_PATH)/access.log` |
| 133 | +* `FLAGS` defaults to `` or None |
| 134 | +* `EXPRESSION` will default to `""` |
| 135 | +* `PREFIX` will default to `""` |
| 136 | + |
| 137 | +If desired the format of the Access logger can be changed by changing |
| 138 | +the value of the `ACCESS_LOG_TEMPLATE`. |
| 139 | + |
| 140 | +NB: You can redirect the access logger to send its events to the Gitea |
| 141 | +log using the value: `ACCESS = ,` |
| 142 | + |
| 143 | +#### The ACCESS_LOG_TEMPLATE |
| 144 | + |
| 145 | +This value represent a go template. It's default value is: |
| 146 | + |
| 147 | +`{{.Ctx.RemoteAddr}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}\" \"{{.Ctx.Req.UserAgent}}"` |
| 148 | + |
| 149 | +The template is passed following options: |
| 150 | + |
| 151 | +* `Ctx` is the `macaron.Context` |
| 152 | +* `Identity` is the `SignedUserName` or `"-"` if the user is not logged |
| 153 | +in |
| 154 | +* `Start` is the start time of the request |
| 155 | +* `ResponseWriter` is the `macaron.ResponseWriter` |
| 156 | + |
| 157 | +Caution must be taken when changing this template as it runs outside of |
| 158 | +the standard panic recovery trap. The template should also be as simple |
| 159 | +as it runs for every request. |
| 160 | + |
| 161 | +### The "XORM" logger |
| 162 | + |
| 163 | +The XORM logger is a long-standing logger that exists to collect XORM |
| 164 | +log events. It is enabled by default but can be switched off by setting |
| 165 | +`ENABLE_XORM_LOG` to `false` in the `[log]` section. Its outputs are |
| 166 | +configured by setting the `XORM` value in the `[log]` section of the |
| 167 | +configuration. `XORM` defaults to `,` if unset, meaning it is redirected |
| 168 | +to the main Gitea log. |
| 169 | + |
| 170 | +XORM will log SQL events by default. This can be changed by setting |
| 171 | +the `LOG_SQL` value to `false` in the `[database]` section. |
| 172 | + |
| 173 | +Each output sublogger for this logger is configured in |
| 174 | +`[log.sublogger.xorm]` sections. There are certain default values |
| 175 | +which will not be inherited from the `[log]` or relevant |
| 176 | +`[log.sublogger]` sections: |
| 177 | + |
| 178 | +* `FILE_NAME` will default to `%(ROOT_PATH)/xorm.log` |
| 179 | +* `FLAGS` defaults to `date,time` |
| 180 | +* `EXPRESSION` will default to `""` |
| 181 | +* `PREFIX` will default to `""` |
| 182 | + |
| 183 | +### The Hook and Serv "GitLoggers" |
| 184 | + |
| 185 | +These are less well defined loggers. Essentially these should only be |
| 186 | +used within Gitea's subsystems and cannot be configured at present. |
| 187 | + |
| 188 | +They will write log files in: |
| 189 | + |
| 190 | +* `%(ROOT_PATH)/hooks/pre-receive.log` |
| 191 | +* `%(ROOT_PATH)/hooks/update.log` |
| 192 | +* `%(ROOT_PATH)/hooks/post-receive.log` |
| 193 | +* `%(ROOT_PATH)/serv.log` |
| 194 | +* `%(ROOT_PATH)/http.log` |
| 195 | + |
| 196 | +In the future these logs may be rationalised. |
| 197 | + |
| 198 | +## Log outputs |
| 199 | + |
| 200 | +Gitea provides 4 possible log outputs: |
| 201 | + |
| 202 | +* `console` - Log to `os.Stdout` or `os.Stderr` |
| 203 | +* `file` - Log to a file |
| 204 | +* `conn` - Log to a keep-alive TCP connection |
| 205 | +* `smtp` - Log via email |
| 206 | + |
| 207 | +Certain configuration is common to all modes of log output: |
| 208 | + |
| 209 | +* `LEVEL` is the lowest level that this output will log. This value |
| 210 | +is inherited from `[log]` and in the case of the non-default loggers |
| 211 | +from `[log.sublogger]`. |
| 212 | +* `STACKTRACE_LEVEL` is the lowest level that this output will print |
| 213 | +a stacktrace. This value is inherited. |
| 214 | +* `MODE` is the mode of the log output. It will default to the sublogger |
| 215 | +name. Thus `[log.console.macaron]` will default to `MODE = console`. |
| 216 | +* `COLORIZE` will default to `true` for `file` and `console` as |
| 217 | +described, otherwise it will default to `false`. |
| 218 | + |
| 219 | +### Non-inherited default values |
| 220 | + |
| 221 | +There are several values which are not inherited as described above but |
| 222 | +rather default to those specific to type of logger, these are: |
| 223 | +`EXPRESSION`, `FLAGS`, `PREFIX` and `FILE_NAME`. |
| 224 | + |
| 225 | +#### `EXPRESSION` |
| 226 | + |
| 227 | +`EXPRESSION` represents a regular expression that log events must match to be logged by the sublogger. Either the log message, (with colors removed), must match or the `longfilename:linenumber:functionname` must match. NB: the whole message or string doesn't need to completely match. |
| 228 | + |
| 229 | +Please note this expression will be run in the sublogger's goroutine |
| 230 | +not the logging event subroutine. Therefore it can be complicated. |
| 231 | + |
| 232 | +#### `FLAGS` |
| 233 | + |
| 234 | +`FLAGS` represents the preceding logging context information that is |
| 235 | +printed before each message. It is a comma-separated string set. The order of values does not matter. |
| 236 | + |
| 237 | +Possible values are: |
| 238 | + |
| 239 | +* `none` or `,` - No flags. |
| 240 | +* `date` - the date in the local time zone: `2009/01/23`. |
| 241 | +* `time` - the time in the local time zone: `01:23:23`. |
| 242 | +* `microseconds` - microsecond resolution: `01:23:23.123123`. Assumes |
| 243 | +time. |
| 244 | +* `longfile` - full file name and line number: `/a/b/c/d.go:23`. |
| 245 | +* `shortfile` - final file name element and line number: `d.go:23`. |
| 246 | +* `funcname` - function name of the caller: `runtime.Caller()`. |
| 247 | +* `shortfuncname` - last part of the function name. Overrides |
| 248 | +`funcname`. |
| 249 | +* `utc` - if date or time is set, use UTC rather than the local time |
| 250 | +zone. |
| 251 | +* `levelinitial` - Initial character of the provided level in brackets eg. `[I]` for info. |
| 252 | +* `level` - Provided level in brackets `[INFO]` |
| 253 | +* `medfile` - Last 20 characters of the filename - equivalent to |
| 254 | +`shortfile,longfile`. |
| 255 | +* `stdflags` - Equivalent to `date,time,medfile,shortfuncname,levelinitial` |
| 256 | + |
| 257 | +### Console mode |
| 258 | + |
| 259 | +For loggers in console mode, `COLORIZE` will default to `true` if not |
| 260 | +on windows, or the windows terminal can be set into ANSI mode or is a |
| 261 | +cygwin or Msys pipe. |
| 262 | + |
| 263 | +If `STDERR` is set to `true` the logger will use `os.Stderr` instead of |
| 264 | +`os.Stdout`. |
| 265 | + |
| 266 | +### File mode |
| 267 | + |
| 268 | +The `FILE_NAME` defaults as described above. If set it will be relative |
| 269 | +to the provided `ROOT_PATH` in the master `[log]` section. |
| 270 | + |
| 271 | +Other values: |
| 272 | + |
| 273 | +* `LOG_ROTATE`: **true**: Rotate the log files. |
| 274 | +* `MAX_SIZE_SHIFT`: **28**: Maximum size shift of a single file, 28 represents 256Mb. |
| 275 | +* `DAILY_ROTATE`: **true**: Rotate logs daily. |
| 276 | +* `MAX_DAYS`: **7**: Delete the log file after n days |
| 277 | +* NB: `COLORIZE`: will default to `true` if not on windows. |
| 278 | +* `COMPRESS`: **true**: Compress old log files by default with gzip |
| 279 | +* `COMPRESSION_LEVEL`: **-1**: Compression level |
| 280 | + |
| 281 | +### Conn mode |
| 282 | + |
| 283 | +* `RECONNECT_ON_MSG`: **false**: Reconnect host for every single message. |
| 284 | +* `RECONNECT`: **false**: Try to reconnect when connection is lost. |
| 285 | +* `PROTOCOL`: **tcp**: Set the protocol, either "tcp", "unix" or "udp". |
| 286 | +* `ADDR`: **:7020**: Sets the address to connect to. |
| 287 | + |
| 288 | +### SMTP mode |
| 289 | + |
| 290 | +It is not recommended to use this logger to send general logging |
| 291 | +messages. However, you could perhaps set this logger to work on `FATAL`. |
| 292 | + |
| 293 | +* `USER`: User email address to send from. |
| 294 | +* `PASSWD`: Password for the smtp server. |
| 295 | +* `HOST`: **127.0.0.1:25**: The SMTP host to connect to. |
| 296 | +* `RECEIVERS`: Email addresses to send to. |
| 297 | +* `SUBJECT`: **Diagnostic message from Gitea** |
| 298 | + |
| 299 | +## Default Configuration |
| 300 | + |
| 301 | +The default empty configuration is equivalent to: |
| 302 | + |
| 303 | +```ini |
| 304 | +[log] |
| 305 | +ROOT_PATH = %(GITEA_WORK_DIR)/log |
| 306 | +MODE = console |
| 307 | +LEVEL = Info |
| 308 | +STACKTRACE_LEVEL = None |
| 309 | +REDIRECT_MACARON_LOG = false |
| 310 | +ENABLE_ACCESS_LOG = false |
| 311 | +ENABLE_XORM_LOG = true |
| 312 | +XORM = , |
| 313 | + |
| 314 | +[log.console] |
| 315 | +MODE = console |
| 316 | +LEVEL = %(LEVEL) |
| 317 | +STACKTRACE_LEVEL = %(STACKTRACE_LEVEL) |
| 318 | +FLAGS = stdflags |
| 319 | +PREFIX = |
| 320 | +COLORIZE = true # Or false if your windows terminal cannot color |
| 321 | +``` |
| 322 | + |
| 323 | +This is equivalent to sending all logs to the console, with default go log being sent to the console log too. |
| 324 | + |
| 325 | +## Log colorization |
| 326 | + |
| 327 | +Logs to the console will be colorized by default when not running on |
| 328 | +Windows. Terminal sniffing will occur on Windows and if it is |
| 329 | +determined that we are running on a terminal capable of color we will |
| 330 | +colorize. |
| 331 | + |
| 332 | +Further, on *nix it is becoming common to have file logs that are |
| 333 | +colored by default. Therefore file logs will be colorised by default |
| 334 | +when not running on Windows. |
| 335 | + |
| 336 | +You can switch on or off colorization by using the `COLORIZE` value. |
| 337 | + |
| 338 | +From a development point of view. If you write |
| 339 | +`log.Info("A %s string", "formatted")` the `formatted` part of the log |
| 340 | +message will be Bolded on colorized logs. |
| 341 | + |
| 342 | +You can change this by either rendering the formatted string yourself. |
| 343 | +Or you can wrap the value in a `log.ColoredValue` struct. |
| 344 | + |
| 345 | +The `log.ColoredValue` struct contains a pointer to value, a pointer to |
| 346 | +string of bytes which should represent a color and second set of reset |
| 347 | +bytes. Pointers were chosen to prevent copying of large numbers of |
| 348 | +values. There are several helper methods: |
| 349 | + |
| 350 | +* `log.NewColoredValue` takes a value and 0 or more color attributes |
| 351 | +that represent the color. If 0 are provided it will default to a cached |
| 352 | +bold. Note, it is recommended that color bytes constructed from |
| 353 | +attributes should be cached if this is a commonly used log message. |
| 354 | +* `log.NewColoredValuePointer` takes a pointer to a value, and |
| 355 | +0 or more color attributes that represent the color. |
| 356 | +* `log.NewColoredValueBytes` takes a value and a pointer to an array |
| 357 | +of bytes representing the color. |
| 358 | + |
| 359 | +These functions will not double wrap a `log.ColoredValue`. They will |
| 360 | +also set the ResetBytes to the cached resetBytes. |
| 361 | + |
| 362 | +Be careful not to change the contents of resetBytes or boldBytes as this |
| 363 | +will break rendering of logging elsewhere. You have been warned. |
| 364 | + |
| 365 | +## Log Spoofing protection |
| 366 | + |
| 367 | +In order to protect the logs from being spoofed with cleverly |
| 368 | +constructed messages. Newlines are now prefixed with a tab and control |
| 369 | +characters except those used in an ANSI CSI are escaped with a |
| 370 | +preceding `\` and their octal value. |
| 371 | + |
| 372 | +## Creating a new named logger group |
| 373 | + |
| 374 | +Should a developer wish to create a new named logger, `NEWONE`. It is |
| 375 | +recommended to add an `ENABLE_NEWONE_LOG` value to the `[log]` |
| 376 | +section, and to add a new `NEWONE` value for the modes. |
| 377 | + |
| 378 | +A function like `func newNewOneLogService()` is recommended to manage |
| 379 | +construction of the named logger. e.g. |
| 380 | + |
| 381 | +```go |
| 382 | +func newNewoneLogService() { |
| 383 | + EnableNewoneLog = Cfg.Section("log").Key("ENABLE_NEWONE_LOG").MustBool(false) |
| 384 | + Cfg.Section("log").Key("NEWONE").MustString("file") // or console? or "," if you want to send this to default logger by default |
| 385 | + if EnableNewoneLog { |
| 386 | + options := newDefaultLogOptions() |
| 387 | + options.filename = filepath.Join(LogRootPath, "newone.log") |
| 388 | + options.flags = "stdflags" |
| 389 | + options.bufferLength = Cfg.Section("log").Key("BUFFER_LEN").MustInt64(10000) |
| 390 | + generateNamedLogger("newone", options) |
| 391 | + } |
| 392 | +} |
| 393 | +``` |
| 394 | + |
| 395 | +You should then add `newOneLogService` to `NewServices()` in |
| 396 | +`modules/setting/setting.go` |
0 commit comments