A Go (golang) package providing high-performance asynchronous logging, message filtering by severity and category, and multiple message targets.

Overview

ozzo-log

GoDoc Build Status Coverage Status Go Report

Other languages

简体中文 Русский

Description

ozzo-log is a Go package providing enhanced logging support for Go programs. It has the following features:

  • High performance through asynchronous logging;
  • Recording message severity levels;
  • Recording message categories;
  • Recording message call stacks;
  • Filtering via severity levels and categories;
  • Customizable message format;
  • Configurable and pluggable message handling through log targets;
  • Included console, file, network, and email log targets.

Requirements

Go 1.2 or above.

Installation

Run the following command to install the package:

go get github.com/go-ozzo/ozzo-log

Getting Started

The following code snippet shows how you can use this package.

package main

import (
	"github.com/go-ozzo/ozzo-log"
)

func main() {
    // creates the root logger
	logger := log.NewLogger()

	// adds a console target and a file target
	t1 := log.NewConsoleTarget()
	t2 := log.NewFileTarget()
	t2.FileName = "app.log"
	t2.MaxLevel = log.LevelError
	logger.Targets = append(logger.Targets, t1, t2)

	logger.Open()
	defer logger.Close()

	// calls log methods to log various log messages
	logger.Error("plain text error")
	logger.Error("error with format: %v", true)
	logger.Debug("some debug info")

	// customizes log category
	l := logger.GetLogger("app.services")
	l.Info("some info")
	l.Warning("some warning")

	...
}

Loggers and Targets

A logger provides various log methods that can be called by application code to record messages of various severity levels.

A target filters log messages by their severity levels and message categories and processes the filtered messages in various ways, such as saving them in files, sending them in emails, etc.

A logger can be equipped with multiple targets each with different filtering conditions.

The following targets are included in the ozzo-log package.

  • ConsoleTarget: displays filtered messages to console window
  • FileTarget: saves filtered messages in a file (supporting file rotating)
  • NetworkTarget: sends filtered messages to an address on a network
  • MailTarget: sends filtered messages in emails

You can create a logger, configure its targets, and start to use logger with the following code:

// creates the root logger
logger := log.NewLogger()
logger.Targets = append(logger.Targets, target1, target2, ...)
logger.Open()
...calling log methods...
logger.Close()

Severity Levels

You can log a message of a particular severity level (following the RFC5424 standard) by calling one of the following methods of the Logger struct:

  • Emergency(): the system is unusable.
  • Alert(): action must be taken immediately.
  • Critical(): critical conditions.
  • Error(): error conditions.
  • Warning(): warning conditions.
  • Notice(): normal but significant conditions.
  • Info(): informational purpose.
  • Debug(): debugging purpose.

Message Categories

Each log message is associated with a category which can be used to group messages. For example, you may use the same category for messages logged by the same Go package. This will allow you to selectively send messages to different targets.

When you call log.NewLogger(), a root logger is returned which logs messages using the category named as app. To log messages with a different category, call the GetLogger() method of the root logger or a parent logger to get a child logger and then call its log methods:

logger := log.NewLogger()
// the message is of category "app"
logger.Error("...")

l1 := logger.GetLogger("system")
// the message is of category "system"
l1.Error("...")

l2 := l1.GetLogger("app.models")
// the message is of category "app.models"
l2.Error("...")

Message Formatting

By default, each log message takes this format when being sent to different targets:

2015-10-22T08:39:28-04:00 [Error][app.models] something is wrong
...call stack (if enabled)...

You may customize the message format by specifying your own message formatter when calling Logger.GetLogger(). For example,

logger := log.NewLogger()
logger = logger.GetLogger("app", func (l *Logger, e *Entry) string {
    return fmt.Sprintf("%v [%v][%v] %v%v", e.Time.Format(time.RFC822Z), e.Level, e.Category, e.Message, e.CallStack)
})

Logging Call Stacks

By setting Logger.CallStackDepth as a positive number, it is possible to record call stack information for each log method call. You may further configure Logger.CallStackFilter so that only call stack frames containing the specified substring will be recorded. For example,

logger := log.NewLogger()
// record call stacks containing "myapp/src" up to 5 frames per log message
logger.CallStackDepth = 5
logger.CallStackFilter = "myapp/src"

Message Filtering

By default, messages of all severity levels will be recorded. You may customize Logger.MaxLevel to change this behavior. For example,

logger := log.NewLogger()
// only record messages between Emergency and Warning levels
logger.MaxLevel = log.LevelWarning

Besides filtering messages at the logger level, a finer grained message filtering can be done at target level. For each target, you can specify its MaxLevel similar to that with the logger; you can also specify which categories of the messages the target should handle. For example,

target := log.NewConsoleTarget()
// handle messages between Emergency and Info levels
target.MaxLevel = log.LevelInfo
// handle messages of categories which start with "system.db." or "app."
target.Categories = []string{"system.db.*", "app.*"}

Configuring Logger

When an application is deployed for production, a common need is to allow changing the logging configuration of the application without recompiling its source code. ozzo-log is designed with this in mind.

For example, you can use a JSON file to specify how the application and its logger should be configured:

{
    "Logger": {
        "Targets": [
            {
                "type": "ConsoleTarget",
            },
            {
                "type": "FileTarget",
                "FileName": "app.log",
                "MaxLevel": 4   // Warning or above
            }
        ]
    }
}

Assuming the JSON file is app.json, in your application code you can use the ozzo-config package to load the JSON file and configure the logger used by the application:

package main

import (
	"github.com/go-ozzo/ozzo-config"
    "github.com/go-ozzo/ozzo-log"
)

func main() {
    c := config.New()
    c.Load("app.json")
    // register the target types to allow configuring Logger.Targets.
    c.Register("ConsoleTarget", log.NewConsoleTarget)
    c.Register("FileTarget", log.NewFileTarget)

    logger := log.NewLogger()
    if err := c.Configure(logger, "Logger"); err != nil {
        panic(err)
    }
}

To change the logger configuration, simply modify the JSON file without recompiling the Go source files.

Comments
  • Logger is not working

    Logger is not working

    Hi! I try to use Logger as shown in example. The application builds without errors. The file is created, but it is always empty ( And In console nothing to.

    bug 
    opened by kolkov 11
  • Add Chinese Translation

    Add Chinese Translation

    Hi Xue Qiang, please have a look and do not merge it at this moment. As in I am about to polish it and remove all the original English words in a while.

    opened by qiansen1386 4
  • 持续运行几个小时后日志调用会阻塞。

    持续运行几个小时后日志调用会阻塞。

    我英语不太好,事情比较复杂,还是写中文吧。

    环境是 windows 10 和 ubuntu x32 1404 , 语言版本:go version go1.6.2 windows/amd64

    程序创建了一个模块来配置日志共享给其他模块,相关代码:

    
    package logger
    
    import (
        "github.com/go-ozzo/ozzo-log"
    )
    
    var logger = log.NewLogger()
    
    // main 函数调用这个函数初始化 log
    func Open(fileName string) {
        ct := log.NewConsoleTarget()
        ct.MaxLevel = log.LevelDebug
    
        ft := log.NewFileTarget()
        ft.FileName = fileName
        ft.MaxLevel = log.LevelInfo
        ft.MaxBytes = 1 * 1024 * 1024 //2M
        ft.BackupCount = 10
        ft.Rotate = true //自动切割旋转日志文件
    
        logger.Targets = append(logger.Targets, ct, ft)
    
        logger.Open()
    
        logger.Debug("日志完成初始化...")
    }
    
    // 其他模块调用这个函数获得自己的 Logger 并使用
    func GetLogger(category string, formatter ...log.Formatter) *log.Logger {
        return logger.GetLogger(category, formatter...)
    }
    
    func Close() {
        logger.Close()
    }
    
    

    日志被设置为控制台输出DEBUG日志,文件记录INFO以上级别的日志。1M文件自动切割。

    故障现象是:

    持续运行几个小时(最近这次是2个小时)后,日志调用阻塞,任何涉及到日志的流程全部阻塞,同时控制台、日志文件不会再输出新内容。 完全没有调用 ozzo 的代码能正常运行:我同时使用了 xorm ,打开了打印sql语句功能。有一个定时调用正常时不会调用 ozzo 打印日志, ozzo 完全阻塞后能看到这个流程还在继续运行,能够看到 xorm 定时打印到控制台的sql语句。

    故障时控制台最后的日志输出:

    2016-06-30T15:50:02+08:00 [Debug][yfforward] .......
    2016-06-30T15:50:02+08:00 [Info][yfforward] .......
    2016-06-30T15:50:03+08:00 [Info][yfforward] ......
    2016-06-30T15:50:03+08:00 [Debug][yfforward] ......
    2016-06-30T15:50:03+08:00 [Info][yfforward] ......
    2016-06-30T15:50:04+08:00 [Info][yfforward] ......
    [xorm] [info]  2016/06/30 15:50:19.176599 [sql] SELECT........
    [xorm] [info]  2016/06/30 15:50:19.177598 [sql] UPDATE.......
    [xorm] [info]  2016/06/30 15:50:40.648707 [sql] SELECT ........
    

    日志文件最后的内容:

    2016-06-30T15:50:00+08:00 [Info][yfforward] .....
    2016-06-30T15:50:01+08:00 [Info][yfforward] ........
    2016-06-30T15:50:01+08:00 [Info][yfforward] ......
    2016-06-30T15:50:02+08:00 [Info][yfforward] ......
    2016-06-30T15:50:02+08:00 [Info][yfforward] .....
    2016-06-30T15:50:03+08:00 [Info][yfforward] ......
    2016-06-30T15:50:03+08:00 [Info][yfforward] ........
    

    猜测可能是多线程竟态问题,但是使用 tace 选项编译的程序运行中并没有报任何错误...

    为了确认故障位置,针对 http api 服务 handle 函数增加了 fmt.Print ,代码如下:

        fmt.Printf("fmt.Print [ping] %v %v ping %v", r.RemoteAddr, rtype, raddr)
        log.Info("[ping] %v %v ping %v", r.RemoteAddr, rtype, raddr)
        fmt.Println("fmt.Print end")
    

    然后访问这个 api,控制台输出如下:

    ··· [xorm] [info] 2016/06/30 15:58:57.089083 [sql] UPDATEXXXXXXXXXXXXXX fmt.Print [ping] 127.0.0.1:52080 TCP ping www.163.com:80[xorm] [info] 2016/06/30 15:59:07.088631 [sql] SELECT XXXXXXXXXXXXXXXXXXXXXXX [xorm] [info] XXXXXXXXXXXXXXXXXXXXXX [xorm] [info] 2016/06/30 15:59:17.104377 XXXXXXXXXXXXXXXXXXXXXXXXX ···

    可以看到是ozzo日志调用阻塞了。xorm 的输出是上面那个不涉及 ozzo 的定时调用的输出。

    目前正在想办法确定更具体的位置,挂载调试器的程序还未故障,稍故障后设置断点确定更准确的位置。

    还有一个地方比较奇怪,日志切割设置并没有生效,故障时查看日志文件已经1.39M了,但是并没有执行切割,不知道是不是和这个有关。

    opened by GameXG 3
  • Catching standard panics

    Catching standard panics

    Hello.

    Sorry for a newbie question, but how could I catch standard panics with this? For example I got this panic from Go:

    2016/02/17 11:22:29 http: panic serving [::1]:58256: runtime error: index out of rang
    e
    goroutine 17 [running]:
    net/http.(*conn).serve.func1(0xc0820b2000, 0x14110f8, 0xc0820ac018)
            c:/go/src/net/http/server.go:1287 +0xbc
    main.whoisHandler(0x1411278, 0xc0820b20b0, 0xc0820b01c0)
            C:/Projects/test/main.go:121 +0xeb7
    net/http.HandlerFunc.ServeHTTP(0x7d1de0, 0x1411278, 0xc0820b20b0, 0xc0820b01c0)
            c:/go/src/net/http/server.go:1422 +0x41
    net/http.(*ServeMux).ServeHTTP(0xc08205a3f0, 0x1411278, 0xc0820b20b0, 0xc0820b01c0)
            c:/go/src/net/http/server.go:1699 +0x184
    net/http.serverHandler.ServeHTTP(0xc0820a8000, 0x1411278, 0xc0820b20b0, 0xc0820b01c0)
    
            c:/go/src/net/http/server.go:1862 +0x1a5
    net/http.(*conn).serve(0xc0820b2000)
            c:/go/src/net/http/server.go:1361 +0xbf5
    created by net/http.(*Server).Serve
            c:/go/src/net/http/server.go:1910 +0x3fd
    

    How could I log it properly and possibly redirect the output as well? Using the standard log library it's as simple as setting the log.SetOutput(logFile).

    P.S. I know this has to be a bad error handling, but what if I missed something and such a panic arises.

    opened by importnil 3
  • Debugging ozzo-config.Config

    Debugging ozzo-config.Config

    I builded a windows version of dalve and plugin that support it. But when I debugging my App, i don't see any values loaded into this struct...

    func LoadConfig() *config.Config{
        // Load config
        c := config.New()
        c.Load("conf/config.json")
        return c
    }
    
    {
      "Version": "1.0",
      "StaticServer": {
        "Path": "./static"
      },
      "WebServer": {
        "PortHTTP": "8080",
        "PortHTTPS": "8088",
        "Domain": "localhost"
      },
      "Logger": {
        "Filename": "app.log",
        "Email": "****@gmail.com"
      },
      "Db":{
        "Type": "mysql",
        "Host": "localhost",
        "DbName": "inframe",
        "Login": "root",
        "Password": ""
      }
    }
    

    image Are you see the same in Linux or more?

    opened by kolkov 0
  • Error of wrong Target

    Error of wrong Target

            target := log.NewFileTarget()
    	target.FileName = "\"qweqw\""
    
    	l.logger.Targets = append(l.logger.Targets, target)
    	l.logger.Open()
            err = logger.Open()
    	if err != nil {
    	     panic(err)
    	}
            // run my code
    

    After running this code I get the message only:

    Failed to open target: FileTarget was unable to create a log file: open "qweqw": The filename, directory name, or volume label syntax is incorrect.

    And the code is executed further silent! (no panic)

    IMHO it's wrong behavior

    opened by githubjeka 0
  • create directories from config file

    create directories from config file

    I want to ask to add it creating folders from config file if it is not exist. for example: "type": "FileTarget", "FileName": "c:/sed/1.log" the library creates c:\sed

    To rewrite localy the library is bad decision.

    opened by annakozyreva1 0
Owner
Ozzo Framework
Ozzo is a Go (golang) framework consisting of fully decoupled packages supporting rapid Web application development.
Ozzo Framework
Tiny structured logging abstraction or facade for various logging libraries, allowing the end user to plug in the desired logging library in main.go

Tiny structured logging abstraction or facade for various logging libraries, allowing the end user to plug in the desired logging library in main.go.

Jacek Olszak 14 Dec 7, 2022
Gomol is a library for structured, multiple-output logging for Go with extensible logging outputs

gomol Gomol (Go Multi-Output Logger) is an MIT-licensed structured logging library for Go. Gomol grew from a desire to have a structured logging libra

Kristin Davidson 19 Sep 26, 2022
Fully asynchronous, structured, pluggable logging for Go.

logr Logr is a fully asynchronous, contextual logger for Go. It is very much inspired by Logrus but addresses two issues: Logr is fully asynchronous,

Mattermost 16 Dec 28, 2022
Package logging implements a logging infrastructure for Go

Golang logging library Package logging implements a logging infrastructure for Go. Its output format is customizable and supports different logging ba

Luke Zhang 0 Nov 10, 2021
a lightweight, high-performance, out-of-the-box logging library that relies solely on the Go standard library

English | 中文 olog olog is a lightweight, high-performance, out-of-the-box logging library that relies solely on the Go standard library. Support outpu

null 6 Apr 12, 2023
A simple logging module for go, with a rotating file feature and console logging.

A simple logging module for go, with a rotating file feature and console logging. Installation go get github.com/jbrodriguez/mlog Usage Sample usage W

Juan B. Rodriguez 30 Dec 14, 2022
FactorLog is a logging infrastructure for Go that provides numerous logging functions for whatever your style may be

FactorLog FactorLog is a fast logging infrastructure for Go that provides numerous logging functions for whatever your style may be. It could easily b

Kevin Darlington 55 Aug 3, 2022
Logger - Go language is interface-oriented to implement an asynchronous log writing program

logger日志库 1、安装 go get github.com/staryjie/logger@latest 2、使用 示例: package main import ( "github.com/staryjie/logger" "time" ) func initLogger(name,

StaryJie 0 Jan 4, 2022
This package enables json output, level logging and so on to standard go logger.

logplug This package enables json output, level logging and so on to standard logger. Usage log.SetOutput(logplug.NewJSONPlug(os.Stderr, logplug.LogF

Koumei Mikuni 0 Dec 27, 2021
Structured logging package for Go.

Package log implements a simple structured logging API inspired by Logrus, designed with centralization in mind. Read more on Medium. Handlers apexlog

Apex 1.3k Dec 24, 2022
Package for easy logging to logstash http input from microservices

Micro Logger package for easy logging to logstash http input from microservices

null 0 Dec 28, 2021
Nightingale - A Distributed and High-Performance Monitoring System. Prometheus enterprise edition

Introduction ?? A Distributed and High-Performance Monitoring System. Prometheus

taotao 1 Jan 7, 2022
The AlfheimDB's high performance write-ahead log.

The AlfheimDB's high performance write-ahead log.

chunming.dong 5 Jul 18, 2022
Simple and blazing fast lockfree logging library for golang

glg is simple golang logging library Requirement Go 1.11 Installation go get github.com/kpango/glg Example package main import ( "net/http" "time"

Yusuke Kato 175 Nov 28, 2022
Parametrized JSON logging library in Golang which lets you obfuscate sensitive data and marshal any kind of content.

Noodlog Summary Noodlog is a Golang JSON parametrized and highly configurable logging library. It allows you to: print go structs as JSON messages; pr

Gyoza Tech 42 Oct 27, 2022
Logging library for Golang

GLO Logging library for Golang Inspired by Monolog for PHP, severity levels are identical Install go get github.com/lajosbencz/glo Severity levels Deb

Lajos Bencz 15 Sep 26, 2022
LogVoyage - logging SaaS written in GoLang

No longer maintained, sorry. Completely rewritten v2 is going to be released soon. Please follow http://github.com/logvoyage LogVoyage - fast and simp

null 93 Sep 26, 2022
Utilities for slightly better logging in Go (Golang).

logutils logutils is a Go package that augments the standard library "log" package to make logging a bit more modern, without fragmenting the Go ecosy

HashiCorp 334 Dec 16, 2022
Golang logging library

Golang logging library Package logging implements a logging infrastructure for Go. Its output format is customizable and supports different logging ba

Örjan Fors 1.8k Dec 27, 2022