alog is a dependency free, zero/minimum memory allocation JSON logger with extensions

Overview

Alog

(c) 2020-2021 Gon Y Yi. https://gonyyi.com.
MIT License

Version 1.0.0

codecov Go Reference License

Alog Screen Shot 1

Intro

Alog was built with a very simple goal in mind:

  • Support Tagging (and also level)
  • No memory allocation (or minimum allocation)
  • Customizable (see alog/ext for example)

If you find any issues, please create an issue.

^Top

Example Usage

Create logger

al := alog.New(os.Stderr)

Hello World

// always has to end with "Write(string)", otherwise, it won't log, and will cause memory allocations.
// output example: 
//   {"date":20210308,"time":203337,"level":"info","tag":[],"message":"Hello World"}
al.Info().Writes("Hello World") // Writes takes a string argument
al.Info().Write() // Write does not take any argument

New Tag

// Create a tag "Disk"
// Create a tag "DB"
tagDisk := al.NewTag("Disk") 
tagDB := al.NewTag("DB") 

al.Info(tagDisk).Str("action", "reading disk").Write()
al.Info(tagDB).Str("id", "myID").Str("pwd", "myPasswd").Writes("Login") // Anything in `Write(string)` will be printed as `message`.
al.Info(tagDisk,tagDB).Int("status", 200).Writes("Login")
al.Info(tagDisk|tagDB).Int("status", 200).Writes("Logout") // tags can be used as `tagDisk|tagDB` or `tagDisk,tagDB` format

// Output:
// {"date":20210308,"time":203835,"level":"info","tag":["Disk"],"action":"reading disk"}
// {"date":20210308,"time":203835,"level":"info","tag":["DB"],"message":"Login","id":"myID","pwd":"myPasswd"}
// {"date":20210308,"time":203835,"level":"info","tag":["Disk","DB"],"message":"Login","status":200}
// {"date":20210308,"time":203835,"level":"info","tag":["Disk","DB"],"message":"Logout","status":200}

Change Format

Alog Screen Shot 2

package main
 
import (
    "github.com/gonyyi/alog"
    "github.com/gonyyi/alog/ext"
    "os"
)

func main() {
  al := alog.New(os.Stderr)
  tagDisk := al.NewTag("Disk")
  tagDB := al.NewTag("DB")
  
  // To color text format
  // Note: Use this after setting tag, flag, etc.
  al = al.Ext(ext.LogFmt.TextColor())
  
  al.Info(tagDisk).Str("action", "reading disk").Write()
  al.Warn(tagDB).Str("id", "myID").Str("pwd", "myPasswd").Write()
  al.Error(tagDisk, tagDB).Int("status", 200).Writes("Login")
  al.Fatal(tagDisk|tagDB).Int("status", 200).Writes("Logout")
}

More example

package main

import (
  "github.com/gonyyi/alog"
  "github.com/gonyyi/alog/ext"
  "os"
)

func main() {
  // When creating, if nil is given for io.Writer, 
  // alog.Discard will be used. (same as io.Discard)
  al := alog.New(os.Stderr) 
  
  // Level + Optional Tag + Write(Message)  
  al.Info().Writes("info level log message")
  // Output:
  // {"date":20210304,"time":175516,"level":"info","tag":[],"message":"info level log message"}

  // Creating tags
  // Note: if same name of tags are created, it will return same tag value.
  //   eg. DB1 := al.NewTag("DB")
  //       DB2 := al.NewTag("DB") // DB1 == DB2 (true)
  IO := al.NewTag("IO")
  DB := al.NewTag("DB")
  SYS := al.NewTag("SYS")
  NET := al.NewTag("NET")
  TEST := al.NewTag("TEST")

  // Write warning log with id = 1.
  // Note: If more than one string given, Alog will take the first one.
  // Output: {"date":20210304,"time":180012,"level":"warn","tag":[],"id":1}
  al.Warn().Int("id", 1).Write()
  

  // Create a warning log with IO tag, and value of id = 2, message = "this will print IO in the tag"
  // Output: {"date":20210304,"time":180012,"level":"warn","tag":["IO"],"message":"this will print IO in the tag","id":2}
  al.Warn(IO).Int("id", 2).Writes("this will print IO in the tag")
  

  // Create a warning log with IO/DB/SYS/NET tag, id = 3, message = "this will print IO/DB/SYS/NET to tag"
  // Tags can be listed with with pipe as well instead of comma: 
  //   `al.Warn(IO|DB|SYS|NET).Int("id", 3).Write("this will print IO/DB/SYS/NET to tag")`
  // Output: {"date":20210304,"time":180012,"level":"warn","tag":["IO","DB","SYS","NET"],"message":"this will print IO/DB/SYS/NET to tag","id":3}
  al.Warn(IO,DB,SYS,NET).Int("id", 3).Writes("this will print IO/DB/SYS/NET to tag")
  
  
  // Change logging level to Fatal. (highest logging level)
  al.Control.Level = alog.FatalLevel 


  // No output as below Fatal level
  al.Info(IO|SYS).Int("id", 4).Writes("this will not print")
  al.Info(IO).Int("id", 5).Writes("this will not print")
  al.Error(DB).Int("id", 6).Writes("this will not print")


  // This will print because it's a Fatal level log entry
  // Output: {"date":20210304,"time":180150,"level":"fatal","tag":["NET"],"message":"this will print","id":7}
  al.Fatal(NET).Int("id", 7).Writes("this will print")
  

  // By adding Tags to control, any log entries with Fatal level or above (as set above),
  // OR any log entries that contains IO tag will show.
  al.Control.Tags = IO 
  

  // Tag contains tag IO; will be printed
  // Output: {"date":20210304,"time":180942,"level":"info","tag":["IO","SYS"],"id":4,"attempt":2}
  al.Info(IO|SYS). 
    Int("id", 4).
    Int("attempt", 2).
    Write()

  // Tag is IO; will be printed  
  // Output: {"date":20210304,"time":180942,"level":"info","tag":["IO"],"id":5,"attempt":2}
  al.Info(IO). 
    Int("id", 5).
    Int("attempt", 2).
    Write()

  // Tag IO isn't used. And level is below Fatal. Will NOT be printed.
  al.Error(DB). 
    Int("id", 6).
    Int("attempt", 2).
    Write()

  // Tag is not matching, but Level is, so will be printed.
  // Output: {"date":20210304,"time":180942,"level":"fatal","tag":["NET"],"id":7,"attempt":2}
  al.Fatal(NET). 
    Int("id", 7).
    Int("attempt", 2).
    Write()


  // EXTENSIONS: Formatter Extension <github.com/gonyyi/alog/ext>
  // revert logging level to INFO level (from fatal)
  al.Control.Level = alog.InfoLevel 


  // Use color formatter extension
  // This will output the log with ANSI colored text format.
  // Output (in Color): 
  //   2021-0304 18:13:38  INF  [TEST] testType="colorText"
  al = al.Ext(ext.LogFmt.TextColor()) 
  al.Info(TEST).Str("testType", "colorText").Write()
  

  // Use text formatter extension
  // This will output the log with ANSI colored text format.
  // Output: 
  //   2021-0304 18:14:24 INF [TEST] testType="normalText"
  al = al.Ext(ext.LogFmt.Text())
  al.Info(TEST).Str("testType", "normalText").Write()
  

  // Use default formatter (JSON)
  // This will output the log with default JSON format.
  // Output: 
  //   {"date":20210304,"time":181615,"level":"info","tag":["TEST"],"testType":"backToJSON"}
  al = al.Ext(ext.LogFmt.None())
  al.Info(TEST).Str("testType", "backToJSON").Write()
  

  // EXTENSION: Custom Log Entry
  // A user can create a custom log entry function.
  // Example below takes a name and set name; also add two additional values
  // of string "testStr" with "myStr", and integer "testInt" with 123.
  myEntry := func(s string) alog.EntryFn {
      return func(entry *alog.Entry) *alog.Entry {
          return entry.Str("name", s).Str("testStr", "myStr").Int("testInt", 123)
      }
  }

  // When using custom log entry function, use Ext() method from the *Entry.
  // Output: {"date":20210305,"time":81210,"level":"info","tag":[],"message":"ok","name":"GON","testStr":"myStr","testInt":123}
  al.Info().Ext(myEntry("GON")).Writes("ok")
  
  
  // EXTENSION: Macro Type <github.com/gonyyi/alog/ext>
  // Currently there are 3 log modes: LogMode.Prod(), LogMode.Dev(), and LogMode.Test().
  // - Prod Mode: to a file, buffered writer, JSON
  // - Dev Mode:  to a file, writer, JSON
  // - Test Mode: stderr, TextColor
  // All three modes take same arguments, but for Test mode, the argument (filename)
  // will be ignored. The reason it is still required for Test() is for users to quickly
  // switch between different modes.
  al = al.Ext(ext.LogMode.Prod("output.log")) 
  al.Info(IO).Str("testType", "PROD").Write()

  // `*Logger.Close() error` will close io.Writer if Close() method is available. 
  // It is not required for testing, but when saved to a file, especially buffered
  // file, it is important to call Close() method.
  al.Close() 
}

^Top

Example - Quick Start

github.com/gonyyi/alog/log (see /log suffix), Alog can be used right away.

Default format is *Logger.LEVEL(...TAG).TYPE(KEY, VALUE)...Write(MSG)

  • LEVEL: Trace, Debug, Info, Warn, Error, Fatal
  • TAG: defined by user. Can be used with comma or pipe.
  • TYPE: Int, Int64, Str, Bool, Err, Float, Ext
  • KEY: string of key
  • VALUE: values depend on type.
  • MSG: optional message. Only first will be used.

Example 1.

// Create an info level log with "MyTag",
// city = "Gonway", zip = "12345"
// name = "Gon", age = 50,
// isMarried = false, height = 5.8
log.Info(MyTag).
Str("city", "Gonway").Str("zip", "12345").
Str("name", "Gon").Int("age", 50).
Bool("isMarried", false).
Float("height", 5.8).Write() // Make sure all log entries must end with Write(string)

Example 2.

package main

import (
  "github.com/gonyyi/alog"
  "github.com/gonyyi/alog/log" // quick start
)

func main() {
  // Alog format is
  //    *Logger.`LOGLEVEL(TAG)`.`Str/Int/Int64/Float/Bool/Err(key, value)`.Write(`MSG`)
  log.Info().Str("name", "Alog").Int("buildNo", 6).Int("testID", 1).Writes("Starting")

  // Tag can be created by `NewTag(name string)`
  tagDB := log.NewTag("DB")
  tagHTTP := log.NewTag("HTTP")
  tagREQ := log.NewTag("REQ")
  tagRES := log.NewTag("RES")

  // Below Debug will not be printed, because default log level is INFO or higher.
  // Final message in Write(string) is required.
  log.Debug(tagDB).Str("status", "started").Int("buildNo", 6).Int("testID", 2).Write()

  // Set level and tag. Since it is set to DebugLevel (and above) and/or tagHTTP,
  // log entriees with DebugLevel or higher AND also log entries containing tagHTTP will show up.
  log.Control(alog.DebugLevel, tagHTTP)

  log.Debug(tagHTTP|tagREQ).Str("requestFrom", "123.0.1.100").Int("testID", 3).Writes("will show")
  log.Trace(tagDB).Int("status", 200).Str("dest", "123.0.1.100").Int("testID", 4).Writes("will not show")
  log.Trace(tagHTTP|tagRES).Int("status", 200).Str("dest", "123.0.1.100").Int("testID", 5).Writes("will show")

  // Output:
  // {"date":20210304,"time":173510,"level":"info","tag":[],"message":"Starting","name":"Alog","buildNo":6,"testID":1}
  // {"date":20210304,"time":173510,"level":"debug","tag":["HTTP","REQ"],"message":"will show","requestFrom":"123.0.1.100","testID":3}
  // {"date":20210304,"time":173510,"level":"trace","tag":["HTTP","RES"],"message":"will show","status":200,"dest":"123.0.1.100","testID":5}
}

^Top

Level and Tag

Alog supports both leveled logging and tagging. Tagging allows minimize total number of logging, hence can boost the performance, save disk space needed. Tagging and level can be carefully controlled by control function as well as simply using level and tags alone.

ControlFn can be used by *Logger.Control.Fn = myControlFunc

ControlFn is func(Level, Tag) bool. This function directs true (log) or false (not log) with given Level and Tag. Please, note that, when control function is set, it will supersedes *Logger.Control.Level and *Logger.Control.Tag.

^Top

Extension

Extensions are for users to customize alog. Few examples are written in ext folder (github.com/gonyyi/alog/ext). Current examples are as below:

  • Custom Log Entry
    • Usage: alog.Info().Ext(ext.EntryHTTP.ReqRx(h)).Write(string)
  • Custom Formatter
    • Usage
      • Color Text: al = alog.New(nil).Ext(ext.LogFmt.TextColor())
      • Text: al = alog.New(nil).Ext(ext.LogFmt.Text())
      • None: al = alog.New(nil).Ext(ext.LogFmt.None())
  • Custom Mode
    • Usage
      • PROD: al = alog.New(nil).Ext(ext.LogMode.Prod("mylog.log"))
      • DEV: al = alog.New(nil).Ext(ext.LogMode.Dev("mylog.log"))
      • TEST: al = alog.New(nil).Ext(ext.LogMode.Test("mylog.log"))

^Top

Limitation and Benchmark

TL;DR:

  • Alog does not support fancy features supported by Zerolog.
  • Alog's performance drops significantly when string escape is needed.

Alog has been optimized for simple leveled and tag-based logging with zero memory allocation. To get the performance, Alog does not check duplicate keys.

Alog was designed expecting keys and string values aren't needed for string escapes. Alog does check for this, however, and if found escapes are needed, it will run strconv.Quote(). This part has not been optimized and will slower the performance when happens.

Running a benchmark is very tricky. Depend on which system the benchmark is performed, the output can be vary and potentially misleading. Please note that this benchmark can be very differ than your own.

Please note that, this benchmark test is done based on very limited cases and can be misleading.

Benchmark 1

Type Zerolog Alog Diffs
Single 117.4 ns/op 95.54 ns/op 18.6% faster
Parallel 24.21 ns/op 19.21 ns/op 20.6% faster
Check 1.581 ns/op 1.357 ns/op 14.1% faster
  • Tested on Mac Mini (M1, 8GB, 2020)
  • Both Zerolog and Alog reported zero memory allocation (0 B/op, 0 allocs/op)
  • Zerolog version: v1.20.0
  • Alog version: v0.7.3

Benchmark 2

Type Zerolog Alog Diffs
Single 145.5 ns/op 142.2 ns/op 2.2% faster
Parallel 31.5 ns/op 25.5 ns/op 19.0% faster
Check 2.10 ns/op 1.67 ns/op 20.4% faster
  • Tested on Intel Macbook Pro 15" (i9-8950HK, 32GB, 2018)
  • Both Zerolog and Alog reported zero memory allocation (0 B/op, 0 allocs/op)
  • Zerolog version: v1.20.0
  • Alog version: v0.7.3

Benchmark Code

See github.com/gonyyi/alog/_tmp for benchmark used.

al.Info(0).
  Str("name", "gonal").
  Int("count", i).
  Str("block", dataComp.StrSlice[i%5]).
  Write(dataComp.Msg)

zl.Info().
  Str("name", "gonzl").
  Int("count", i).
  Str("block", dataComp.StrSlice[i%5]).
  Msg(dataComp.Msg)

^Top

EOF

Issues
  • Trigger func

    Trigger func

    something like

    Take functions that triggered by tag and level.. and should able to get log string as well.. so maybe run at the end of logging?

    This can be used like if http request comes, it can do something specific additional task. like saving it to a file.

    v0.4 
    opened by gonyyi 1
  • when only write was used

    when only write was used

    This maybe a bug for specific version, but

    s.log.Info(SYS).Write(INFO_SYS_READY_START) ==> 2021/04/02 15:56:22 INF [SYS] system ready to start // [

    (suffix // [ shouldn't be populated)

    Happens on ext.NewFormatterTerminal and ext.NewFormatterTerminalColoir.

    Bug v0.8 
    opened by gonyyi 0
  • Need a hook

    Need a hook

    From 3rd party side:

    For instance, write some mini logger thing with "io.Writer" that primarily handles "warnings" that library will not return as an error. Default to io.Discard

    Main program:

    Can use alog's hook to get those 3rd party warning info.

    opened by gonyyi 0
  • Need an option exit_on_fatal

    Need an option exit_on_fatal

    There are cases where Fatalf or Fatal should exit.. And this is normal process for other loggers. Create an option, exit_on_fatal (bool) OR do_on_fatal (func())

    opened by gonyyi 0
  • Create a

    Create a "writer" folder and add all writers there.

    Create a "writer" folder and add all writers there.

    • [ ] Alogw - log writer with rotating, gzip
    • [ ] Syslog Writer
    • [ ] Multi Writer - based on level and tag, write it to different writers
      • Eg. (using alogw + syslog)
        • To Syslog: when ERROR and ABOVE
        • To alogw: ALL
        • To terminal: when ERROR and ABOVE
        • To file - records with tag: HTTP
        • To file - records with tag: LOGIN
    NewFeature v0.8 
    opened by gonyyi 0
Releases(v1.0.0)
  • v1.0.0(Jul 19, 2021)

    This is a first 1.0.0 release.

    // Create a tag "Disk"
    // Create a tag "DB"
    tagDisk := al.NewTag("Disk") 
    tagDB := al.NewTag("DB") 
    
    al.Info(tagDisk).Str("action", "reading disk").Write()
    al.Info(tagDB).Str("id", "myID").Str("pwd", "myPasswd").Writes("Login") // Anything in `Write(string)` will be printed as `message`.
    al.Info(tagDisk,tagDB).Int("status", 200).Writes("Login")
    al.Info(tagDisk|tagDB).Int("status", 200).Writes("Logout") // tags can be used as `tagDisk|tagDB` or `tagDisk,tagDB` format
    
    // Output:
    // {"date":20210308,"time":203835,"level":"info","tag":["Disk"],"action":"reading disk"}
    // {"date":20210308,"time":203835,"level":"info","tag":["DB"],"message":"Login","id":"myID","pwd":"myPasswd"}
    // {"date":20210308,"time":203835,"level":"info","tag":["Disk","DB"],"message":"Login","status":200}
    // {"date":20210308,"time":203835,"level":"info","tag":["Disk","DB"],"message":"Logout","status":200}
    
    Source code(tar.gz)
    Source code(zip)
  • v0.8.1(Apr 6, 2021)

  • v0.8.0(Apr 5, 2021)

    • Fixed bug with ext.Formatter when Write("")
    • Added alog.Err type
    • Use Zerolog's AppendString (see appendString.go)
    • Err(string, error) now takes Err(error) and "error" will be used as a default key.
    • Write(string) now takes Write(...string) to be optional
    Source code(tar.gz)
    Source code(zip)
  • v0.7.7(Mar 9, 2021)

  • v0.7.5(Mar 9, 2021)

  • v0.4.2(Feb 9, 2021)

  • v0.3.2(Jan 12, 2021)

  • v0.3.0(Jan 3, 2021)

    v0.3.0

    1. New *alog.Do(*Logger) method.
    2. New *alog.NewTag() Tag, this replaced alog.NewCategory().
    3. New *alog.SetTags(...*alog.Tag) method. This will set tags for given pointers.
    4. New *alog.Output(lvl level, tag Tag, b []byte) method. This takes byte slice and should be used where bytes are used.
    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(Jan 3, 2021)

    New method Do(fn ...func(*Logger)) *Logger will take Do function (func(*Logger)) for custom / predefined configuration.

    An example usage of function is alog.DoColor(*Logger) which brings level labels in color when the logger is writing to os.Stderr or os.Stdout. This function will not write ANSI color code when a log is written to a file.

    Source code(tar.gz)
    Source code(zip)
  • v0.1.6(Dec 31, 2020)

    • Added a badge for a coverage
    • Any level-predefined and formatted methods such as Tracef, Debugf, ... Fatalf will evaluate if any additional arguments are present besides format string. If there is no additional argument, it will run without formatting to save processing time.
    • *.Logger.IfError(error), *.Logger.IfFatal(error) has been added. These methods are taking error (or nil) for an argument. If it's nil, it will ignore, but if actual error is given, it will log the error message.
    • *Logger.Close() method has been added back. If an io.Writer that logger uses have Close() method, it will call the Close() method of the writer.
    • Fatal, Fatalf, IfFatal will call *Logger.Close() right before the os.Exit()
    Source code(tar.gz)
    Source code(zip)
  • v0.1.5(Dec 30, 2020)

  • v0.1.4(Dec 29, 2020)

    v0.1.4

    New flag option Fnewline has been added. The default behavior is not allowing newline within the log message. However, using this option will allow newlines in the log message.

    Fix for #9

    Source code(tar.gz)
    Source code(zip)
  • v0.1.3(Dec 29, 2020)

    v0.1.3

    NewWriter and NewPrint now takes additional string argument for prefix.

    • *Logger.NewWriter(level, Category, string) *alogw
    • *Logger.NewPrint(level, Category, string) func(string)

    Benchmark

    • MacOS 10.15.7 Catalina
    • 2.9 GHz 6-Core Intel Core i9
    • 32 GB 2400 MHz DDR4
    • Radeon Pro 560X 4 GB / Intel UHD Graphics 630 1536 MB

    | Type | Name | Test | Count | Speed | Mem | Alloc | |:--------|:-------------------------------|:-------------------|:-----------|:------------|:--------|:------------| | Builtin | BenchmarkBuiltinLoggerBasic-12 | | 2969100 | 408 ns/op | 80 B/op | 2 allocs/op | | Builtin | BenchmarkBuiltinLoggerFmt-12 | | 2534346 | 477 ns/op | 88 B/op | 3 allocs/op | | Alog | BenchmarkLogger_Info | 1_eval_0_print-12 | 1000000000 | 0.420 ns/op | 0 B/op | 0 allocs/op | | Alog | BenchmarkLogger_Info | 5_eval_0_prints-12 | 651124946 | 1.89 ns/op | 0 B/op | 0 allocs/op | | Alog | BenchmarkLogger_Info | 5_eval_3_prints-12 | 1517264 | 777 ns/op | 0 B/op | 0 allocs/op | | Alog | BenchmarkLogger_Infof | 1_eval_0_print-12 | 1000000000 | 1.10 ns/op | 0 B/op | 0 allocs/op | | Alog | BenchmarkLogger_Infof | 5_eval_0_prints-12 | 227060984 | 5.48 ns/op | 0 B/op | 0 allocs/op | | Alog | BenchmarkLogger_Infof | 5_eval_3_prints-12 | 1078039 | 1112 ns/op | 0 B/op | 0 allocs/op | | Alog | BenchmarkLogger_Print | 5_eval_1_prints-12 | 4073192 | 304 ns/op | 0 B/op | 0 allocs/op | | Alog | BenchmarkLogger_Print | 5_eval_2_prints-12 | 2320356 | 478 ns/op | 0 B/op | 0 allocs/op | | Alog | BenchmarkLogger_Printf | 5_eval_1_prints-12 | 2938634 | 419 ns/op | 0 B/op | 0 allocs/op | | Alog | BenchmarkLogger_Printf | 5_eval_2_prints-12 | 1502662 | 805 ns/op | 0 B/op | 0 allocs/op | | Alog | BenchmarkLogger_NewPrint-12 | | 3516364 | 337 ns/op | 0 B/op | 0 allocs/op | | Alog | BenchmarkLogger_NewWriter-12 | | 2853715 | 409 ns/op | 0 B/op | 0 allocs/op |

    Source code(tar.gz)
    Source code(zip)
Owner
Gon
where's the headache coming from? naming and documenting things.
Gon
Dead simple, super fast, zero allocation and modular logger for Golang

Onelog Onelog is a dead simple but very efficient JSON logger. It is one of the fastest JSON logger out there. Also, it is one of the logger with the

Francois Parquet 401 Apr 5, 2022
A powerful zero-dependency json logger.

ZKits Logger Library About This package is a library of ZKits project. This is a zero-dependency standard JSON log library that supports structured JS

Qingshan Luo 15 Dec 31, 2021
Convenient Logger interface and std logger wrapper

Convenient logger interface and wrapper around std logger Interface type Logger interface { Error(err error) Debugf(format string, args ...interface

Denis Mitrofanov 1 Nov 28, 2021
Logger - Simple logger without written with std pkg

Go-Logger Simple usage is: package main

MaskedTrench 2 Jan 2, 2022
Logger - A thin wrapper of uber-go/zap logger for personal project

a thin wraper of uber-go/zap logger for personal project 0. thanks uber-go/zap B

tsingson 0 May 2, 2022
A simple Go JSON logger.

logger A simple JSON logger for Go. It uses a context.Context to store values which will then be logged along with each message. It is possible to rec

Shawn Milochik 1 Dec 20, 2021
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
A logger, for Go

Go-Log A logger, for Go! It's sort of log and code.google.com/p/log4go compatible, so in most cases can be used without any code changes. Breaking cha

Ian Kent 38 May 12, 2022
Simple logger for Go programs. Allows custom formats for messages.

go-logger A simple go logger for easy logging in your programs. Allows setting custom format for messages. Preview Install go get github.com/apsdehal/

Amanpreet Singh 275 Apr 27, 2022
Loggly Hooks for GO Logrus logger

Loggly Hooks for Logrus Usage package main import ( "github.com/sirupsen/logrus" "github.com/sebest/logrusly" ) var logglyToken string = "YOUR_LOG

Sebest 27 Jul 27, 2021
A 12-factor app logger built for performance and happy development

logxi log XI is a structured 12-factor app logger built for speed and happy development. Simpler. Sane no-configuration defaults out of the box. Faste

Mario Gutierrez 346 Apr 22, 2022
A logger for Go SQL database driver without modify existing *sql.DB stdlib usage.

SQLDB-Logger A logger for Go SQL database driver without modify existing *sql.DB stdlib usage. Colored console writer output above only for sample/dev

Sarjono Mukti Aji 217 May 22, 2022
xlog is a logger for net/context aware HTTP applications

⚠️ Check zerolog, the successor of xlog. HTTP Handler Logger xlog is a logger for net/context aware HTTP applications. Unlike most loggers, xlog will

Olivier Poitrey 135 Nov 22, 2021
Configurable Logger for Go

Timber! This is a logger implementation that supports multiple log levels, multiple output destinations with configurable formats and levels for each.

DeNA SF 67 Dec 27, 2021
A feature-rich and easy to use logger for golang

A feature-rich and easy to use logger for golang ?? Install ?? Common Logs lumber.Success() lumber.Info() lumber.Debug() lumber.Warning()

Matthew Gleich 48 May 10, 2022
A minimal and extensible structured logger

⚠️ PRE-RELEASE ⚠️ DO NOT IMPORT THIS MODULE YOUR PROJECT WILL BREAK package log package log provides a minimal interface for structured logging in ser

Go kit 93 May 5, 2022
HTTP request logger for Golang

Horus ?? Introduction Horus is a request logger and viewer for Go. It allows developers log and view http requests made to their web application. Inst

Michael Okoh 77 Apr 13, 2022
Simple Yet Powerful Logger

sypl sypl provides a Simple Yet Powerful Logger built on top of the Golang sypl. A sypl logger can have many Outputs, and each Output is responsible f

Sauce Labs 9 Apr 28, 2022
simple concurrent logger

XMUS-LOGGER pure golang logger compatible with golang io standards. USAGE : logOptions := logger.LoggerOptions{ LogLevel: 6, // read more about lo

amupxm [amir hossein mokarrami far] 5 Sep 19, 2021