When logging in Revel you should use the controller.LogIf you have services running in the background you should use the revel.AppLog

Internally Revel uses log15 to do the core work, moreinformation about the log handlers can be found there.

Below is the logger interface.

  1. MultiLoggerinterface{// New returns a new Logger that has this logger's context plus the given contextNew(ctx...interface{})MultiLogger// SetHandler updates the logger to write records to the specified handler.SetHandler(hLogHandler)Debug(msgstring,ctx...interface{})Debugf(msgstring,params...interface{})Info(msgstring,ctx...interface{})Infof(msgstring,params...interface{})Warn(msgstring,ctx...interface{})Warnf(msgstring,params...interface{})Error(msgstring,ctx...interface{})Errorf(msgstring,params...interface{})Crit(msgstring,ctx...interface{})Critf(msgstring,params...interface{})//// Logs a message as an Crit and exitsFatal(msgstring,ctx...interface{})Fatalf(msgstring,params...interface{})//// Logs a message as an Crit and panicsPanic(msgstring,ctx...interface{})Panicf(msgstring,params...interface{})}

Usage

Log Contexts

Logging using these Debug,Info,Warn,Error,Crit methods will expect the message values in key value pairs. For example revel.AppLog.Debug("Hi there") is fine revel.AppLog.Debug("Hi there", 25) will panic (only passed one argument for the context). revel.AppLog.Debug("Hi there","age",25,"sex","yes","state",254) is fine. This will produce a log message that includes the context age,sex,state like .

  1. INFO2017/08/0222:31:41test.go:168:HiThereage=25sex=yesstate=254

or in json like

  1. {"caller":"test.go:168","lvl":3,"t":"2017-08-02T22:34:08.303112145-07:00","age":25,"sex":"yes","state":254}

If you want you can fork a new log from the control logger to continue using in your code or to pass to the model - consider this

  1. func(c*FooController)Edit(idint)revel.Result{log:=c.Log.New("id",id)log.Debug("Reading the output")output,err:=model.Load(log,id)iferr!=nil{log.Errorf("Failed to load :%s",err.Error())}...}

Could produce the following output (if an error occurred)

  1. INFO 22:31:41 app test.go:168: Reading the output id=25
  2. ERROR 22:31:41 app test.go:168: Failed to load: Not Found id=25

Log formats

Logging using these Debugf,Infof,Warnf,Errorf,Critf methods allows you to output a formatted string for the message. likerevel.AppLog.Debugf("Hi %s ", "Grace"). Only existing contexts will be applied to them. For example look at the log.Errorf below

  1. func(c*FooController)Edit(idint)revel.Result{log:=c.Log.New("id",id)log.Debug("Reading the output")output,err:=model.Load(log,id)iferr!=nil{log.Errorf("Failed to load :%s",err.Error())}...}

Could produce the following output (if an error occurred)

  1. INFO 22:31:41 app test.go:168: Reading the output id=25
  2. ERROR 22:31:41 app test.go:168: Failed to load: Not Found id=25

App.conf

Configuration examples1) All log messages that match the filter module=app to stdout, all messages that are error messages send to stderr. Order is significant here, the second statement log.error.output = stderr replaces the error handler specified by the log.all of the first line.

  1. log.all.filter.module.app = stdout # Log all loggers for the application to the stdout
  2. log.error.output = stderr # Log all loggers for Revel errors to the stderr

2) Existing configurations will work as well, you can even expand on them

  1. log.debug.output = stdout # Outputs to the stdout
  2. log.info.output = myloghandler # Outputs to the function in LogFunctionMap
  3. log.warn.output = stderr # Outputs to the stderr
  4. log.request.output = myloghandler
  5. log.error.output = somefile/log.json # Outputs to the file specified file using JSON format
  6. log.error.filter.module.revel = stdout # Filters based on context module.revel, outputs to stdout
  7. log.error.filter.module.revel.context.route = stdout # Filters based on context module.revel, context route outputs to stdout
  8. log.critical.output = stderr # Outputs to the stderr

To summarize the log output can be a named function contained in logger.LogFunctionMap. If that function does not exist then it is assumed to be a file name, the file name extension will choose the output format. The stderr and stdout are two predefined functions which may be overriden if desired

Filtered logging

A log filter can specify a series of key, values that will only be logged to if ALL the keys and values match a context in the log. For example the following will log at level errorto the stdout if the log message contains the context module=revel

  1. log.error.filter.module.revel = stdout

Filters are additive, they do not replace existing error handlers - for example in the following error messages that are logged with the context of module=revel will be sent to thestdout and to the json file

  1. log.all.output = stdout
  2. log.error.filter.module.revel = /var/log/revel/revel.json

Filters may be empty so that you can make use the additive feature, the following sends all errors to both stdout and all-errors.json

  1. log.all.output = stdout
  2. log.error.filter = /var/log/revel/all-errors.json

Inverse filters can be applied by using nfilter for example, consider the following

  1. log.all.filter.module.app = stdout # Log all loggers for the application to the stdout
  2. log.error.output = stderr # Log all errors to stderr

In this case any application error would end up logging to both stdout and stderr - which in some cases (like output to a file) would be useful but if you do not want to send duplicate messages to the console you can do the following

  1. log.all.filter.module.app = stdout # Log all loggers for the application to the stdout
  2. log.error.nfilter.module.app = stderr # Everything else that logs an error to stderr

The log.error.nfilter.module.app is the inversion of the first filter, with the type of error.

File logging

For file logging revel uses lumberjack.Logger to stream the output to file. The following configuration options can be set

  1. log.compressBackups = true # Compress the backups after rotation default true
  2. log.maxsize = 1024 # The max file size before rotation in MB degault 10G
  3. log.maxagelog.maxage= 14 # The max age of the file before rotation occurs default 14 days
  4. log.maxbackups = 14 # The max number of old log files to keep default 14

These are global options, you can however apply unique options by Customizing Log Handling

More configuration options
  1. log.colorize = true # Turns off colorization for console output
  2. log.smallDate = true # Outputs just the time for the terminal output
Customizing Log Handling

The following code adds a new output called stdoutjson

  1. logger.LogFunctionMap["stdoutjson"]=func(c*logger.CompositeMultiHandler,options*logger.LogOptions){// Set the json formatter to os.Stdout, replace any existing handlers for the level specifiedc.SetJson(os.Stdout,options)}logger.LogFunctionMap["longtermstorage"]=func(c*logger.CompositeMultiHandler,options*logger.LogOptions){options.SetExtendedOptions("maxAgeDays",30,"maxSizeMB",1024*10,"maxBackups",50)c.SetJsonFile("/var/log/revel/longterm.json",options)}

This setting in app.conf would activate the above logger for all log messages of level Warnand error messages from the module=revel

  1. log.warn.output = stdoutjson
  2. log.error.filter.module.revel = longtermstorage

It is important to note that your logger function may be called with a nil options.Ctx (this is the revel.Config).

The special cases
  • log.request.output assigns a handler for messages which are on the info channel and have the section=requestlog assigned to them. If log.request.output is not specified then messages willbe logged directly to the same handler handling the info log level.

  • log.trace usage in initialization files is deprecated and replace by log.debug

  • If log.critical is not specified and log.error has been. Then the error handler will receive the critical messages as well

    Deprecated Logs

The following loggers are deprecated, the will continue to function but will output something like this INFO 22:16:10 app harness.go:190: LOG DEPRECATED Listening on :9000 module=app section=deprecated

  1. revel.TRACErevel.INFOrevel.WARNrevel.ERROR

Internal structure

Revel provides a single root logger called revel.RootLog. The logger is forked into the following loggers

  • revel.RevelLog Contains context of module=revel
  • revel.AppLog Contains context of module=app
  • module.Log on Startup of revel, it contains the context of module=modulename.
    revel.AppLog is forked to create a logger for

  • controller.Log A new instance is created on every request, and contains context information like, the source ip, request path and request method. If the controller handling the response is from a module it will be forked from module.Log

    Request logger

Sample format: terminal format

  1. log.request.output = stdout

be logged directly to the same handler handling the info log level.

  1. INFO 2017/08/02 22:31:41 server-engine.go:168: Request Stats ip=::1 path=/public/img/favicon.png method=GET action=Static.Serve namespace=static\\ start=2017/08/02 22:31:41 status=200 duration_seconds=0.0007656

JSON Format

  1. log.request.output = /var/log/revel/requestlog.json
  1. {"action":"Static.Serve","caller":"server-engine.go:168","duration_seconds":0.00058336,"ip":"::1","lvl":3,
  2. "method":"GET","msg":"Request Stats","namespace":"static\\","path":"/public/img/favicon.png",
  3. "start":"2017-08-02T22:34:08-0700","status":200,"t":"2017-08-02T22:34:08.303112145-07:00"}

  • Issues tagged with log

    Module Logs

To fetch a logger initialized for a module you can use the revel.RegisterModuleInit like below

  1. varmoduleLoggerlogger.MultiLoggerfuncinit(){revel.RegisterModuleInit(func(module*revel.Module){moduleLogger=module.LogmoduleLogger.Debug("Assigned Logger")})}

The callback registered in the revel.RegisterModuleInit is called before the revel.OnAppStartfunctions are.

GoDoc Reference
GitHub Labels

原文: https://revel.github.io/manual/logging.html