aah Logging
aah provides simple, flexible logger for real world application needs. It supports context, fields, console
, file
receivers, unified logger, child logger and drop-in replacement for standard logger.
- Understanding aah Logging
- Context, Fields, Child Logger Since v0.9
- Human Readable and Machine Parsable Logging
- Unified Logging
- Send Log to Centralized Logging System
- Drop-in replacement for Go Standard Logger
- Log Configuration
Reference to Server Access Log, Server Dump Log.
Understanding aah Logging
aah initializes the application default logger based on configured values from log { ... }
with context of Application Name and Application Instance Name. You can simple import log
module anywhere you need and log it. All the log entries are sent to configured receiver.
import "aahframework.org/log.v0"
// simply log it
log.Info("Welcome ", "to ", "aah ", "logger")
log.Infof("This is %s application logger", "example")
Composable Log Pattern
aah provides composable log pattern as follows. Note: log pattern is not applicable of JSON log format.
Since v0.9 appname
, insname
, reqid
, principal
flags supported.
Pro Tip:
Application instance name (flag insname
) is a key information when you have aah application cluster setup.
FmtFlags is the list of log format flags supported by aah log library
Usage of flag order is up to format composition.
level - outputs ERROR, WARN, FATAL, PANIC, INFO, DEBUG, TRACE
appname - outputs Application Name
insname - outputs Application Instance Name
reqid - outputs Request ID from HTTP header
principal - outputs Logged-In subject primary principal value
time - outputs local time as per format supplied
utctime - outputs UTC time as per format supplied
longfile - outputs full file name: /a/b/c/d.go
shortfile - outputs final file name element: d.go
line - outputs file line number: L23
message - outputs given message along supplied arguments if they present
fields - outputs field values into log entry
custom - outputs string as-is into log entry
aah Application Default Log Pattern
%time:2006-01-02 15:04:05.000 %level:-5 %appname %insname %reqid %principal %message %fields
Sample: Text log format
2017-10-01 23:41:05.983 INFO aahwebsite sfo-aahweb-01 aah go server running on :8080 2017-10-01 23:41:10.337 DEBUG aahwebsite sfo-aahweb-01 59d1df869bf2340ffaab2e28 Calling interceptor: DocController.Before 2017-10-01 23:41:10.338 DEBUG aahwebsite sfo-aahweb-01 59d1df869bf2340ffaab2e28 Calling controller: DocController.ShowDoc ... ... 2017-10-01 23:41:26.845 WARN aahwebsite sfo-aahweb-01 Interrupt signal received 2017-10-01 23:41:26.846 DEBUG aahwebsite sfo-aahweb-01 Event [OnShutdown] publishing in synchronous mode 2017-10-01 23:41:26.846 INFO aahwebsite sfo-aahweb-01 aah application shutdown successful
Sample: JSON log format
{"level":"INFO","timestamp":"2017-10-01T23:41:52-07:00","app_name":"aahwebsite","instance_name":"sfo-aahweb-01","message":"aah go server running on :8080"} {"level":"DEBUG","timestamp":"2017-10-01T23:42:00-07:00","app_name":"aahwebsite","instance_name":"sfo-aahweb-01","request_id":"59d1dfb89bf234103a1b35c2","message":"Calling interceptor: DocController.Before"} {"level":"DEBUG","timestamp":"2017-10-01T23:42:00-07:00","app_name":"aahwebsite","instance_name":"sfo-aahweb-01","request_id":"59d1dfb89bf234103a1b35c2","message":"Calling controller: DocController.ShowDoc"} ... ... {"level":"WARN","timestamp":"2017-10-01T23:42:50-07:00","app_name":"aahwebsite","instance_name":"sfo-aahweb-01","message":"Interrupt signal received"} {"level":"DEBUG","timestamp":"2017-10-01T23:42:50-07:00","app_name":"aahwebsite","instance_name":"sfo-aahweb-01","message":"Event [OnShutdown] publishing in synchronous mode"} {"level":"INFO","timestamp":"2017-10-01T23:42:50-07:00","app_name":"aahwebsite","instance_name":"sfo-aahweb-01","message":"aah application shutdown successful"}
Supported Log levels
- ERROR
- WARN
- FATAL
- PANIC
- INFO
- DEBUG
- TRACE
Pro Tip:
In aah
you could conditionally perform extra logging on certain log level. It could reduce your processing time for some use case. For example: Do extra processing and log only on level DEBUG
using IsLevelDebug()
; that particular block for DEBUG level only.
Context, Fields, Child Logger
Since v0.9 context, fields and child logger supported.
- Context: In aah, you can create logger with context, which is
log.Fields
values. Those values gets logged with every log entry. For example: aah application creates the default logger with application name and application instance name.- Use
ctx.Log().*
for logging in the controller and further to get context based logging which includes log entry with Request ID and Primary Principal value.
- Use
- Fields:
WithFields
andWithField
is used to log fields and values with current log entry. - Child Logger: You can create child logger from aah logger instance. Upon creation it inherits parent logger context values once.
- After creation, any changes to context value on parent or child does not affect each other.
- All the log entries made by child logger; logged in parent receiver.
- Child logger is handy when you want have logger per functionality/package/file, etc. For example: you could create new application child logger via
aah.NewChildLogger(fields)
.
Human Readable and Machine Parsable Logging
aah supports both human readable and machine parseable log format.
Human Readable: This is default log format called text
.
Machine Parsable: This log format is called json
. Per log entry is in JSON format per line. For example: You can use Telegraf
tool from InfluxDB to send log entry to InfluxDB. Also refer to section Send Log to Centralized Logging System
Unified Logging
Surely you will be using many libraries with aah framework. Those might provide standard Go logger for logging. This is where unified logging shines.
Use log.ToGoLogger()
to bind that logger with aah logger then you get unified logging at one place.
Send Log to Centralized Logging System
Even though aah provides out-of-the-box JSON log format. You might need further extensibility to send your log entries to centralized logging system such as Kibana, Loggly, Splunk, etc.
Use Hook
capability to register your hooks. Hooks are executed in goroutine and each hook receives log entry.
For example: Adding hook into aah application default logger.
// Create your logger Hook as type of `log.HookFunc`
func kibanaHook(e log.Entry) {
// Your logger hook logic goes here.
}
func registerLoggerHooks(_ *aah.Event) {
aah.AddLoggerHook("kibana", kibanaHook)
// so on ...
}
func init() {
aah.OnStart(registerLoggerHooks)
}
Drop-in replacement for Go Standard Logger
aah provides drop-in replacement for Go standard Logger. You just import aahframework.org/log.v0
it.