GithubHelp home page GithubHelp logo

go-logging's Introduction

Golang logging library

godoc build

Package logging implements a logging infrastructure for Go. Its output format is customizable and supports different logging backends like syslog, file and memory. Multiple backends can be utilized with different log levels per backend and logger.

NOTE: backwards compatibility promise have been dropped for master. Please vendor this package or use gopkg.in/op/go-logging.v1 for previous version. See changelog for details.

Example

Let's have a look at an example which demonstrates most of the features found in this library.

Example Output

package main

import (
	"os"

	"github.com/op/go-logging"
)

var log = logging.MustGetLogger("example")

// Example format string. Everything except the message has a custom color
// which is dependent on the log level. Many fields have a custom output
// formatting too, eg. the time returns the hour down to the milli second.
var format = logging.MustStringFormatter(
	`%{color}%{time:15:04:05.000} %{shortfunc} ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}`,
)

// Password is just an example type implementing the Redactor interface. Any
// time this is logged, the Redacted() function will be called.
type Password string

func (p Password) Redacted() interface{} {
	return logging.Redact(string(p))
}

func main() {
	// For demo purposes, create two backend for os.Stderr.
	backend1 := logging.NewLogBackend(os.Stderr, "", 0)
	backend2 := logging.NewLogBackend(os.Stderr, "", 0)

	// For messages written to backend2 we want to add some additional
	// information to the output, including the used log level and the name of
	// the function.
	backend2Formatter := logging.NewBackendFormatter(backend2, format)

	// Only errors and more severe messages should be sent to backend1
	backend1Leveled := logging.AddModuleLevel(backend1)
	backend1Leveled.SetLevel(logging.ERROR, "")

	// Set the backends to be used.
	logging.SetBackend(backend1Leveled, backend2Formatter)

	log.Debugf("debug %s", Password("secret"))
	log.Info("info")
	log.Notice("notice")
	log.Warning("warning")
	log.Error("err")
	log.Critical("crit")
}

Installing

Using go get

$ go get github.com/op/go-logging

After this command go-logging is ready to use. Its source will be in:

$GOPATH/src/pkg/github.com/op/go-logging

You can use go get -u to update the package.

Documentation

For docs, see http://godoc.org/github.com/op/go-logging or run:

$ godoc github.com/op/go-logging

Additional resources

  • wslog -- exposes log messages through a WebSocket.

go-logging's People

Contributors

aheuermann avatar alecthomas avatar babo avatar cryptix avatar divan avatar giftig avatar gogolok avatar guilhem avatar lk4d4 avatar nemosupremo avatar nplanel avatar nvx avatar op avatar phedoreanu avatar pjvds avatar selverob avatar zanderz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-logging's Issues

unformatted code

The library need to be gofmted. Using something like godep is very sensitive about that. When I format my project Godeps/ will be formatted to. When I want to run godep update I got an error. Godep is right! The hash doesn't match the code base, because the codebase changed, caused by formatting. Would be really cool to format the logging library.

godep: dirty working tree: /home/vagrant/project/.gobuild/src/github.com/op/go-logging

All the best, Tim 🍰

Control/Observe exit code based on logging level?

Hi Örjan,

I observe that if my application (which uses op/go-logging) ever issues a log message at level WARNING or higher, then when the application exits it exits with a non-zero exit code. So far I have not been able to figure out how this happens. Is this behavior controllable? Can it be observed? By that I mean if my main() is about to return (exit) how can I check if any part of the application has logged at WARNING or above and the program will return a on-0 code?

Thanks - Bishop Brock

suppress or comment files in "examples"

Hi,

First of all, thank you for your work :)
I just created a software in go ( https://github.com/optiflows/bapteme ) and I use your library.

In a way to distribute this software, I create deb package for any library I use, yours is here:
https://launchpad.net/golang-logging (project)
https://launchpad.net/~golang-logging ("team" to manage code and repositories)
https://code.launchpad.net/~golang-logging/+recipe/golang-logging-daily (script to create new packages daily)
https://code.launchpad.net/~golang-logging/+archive/daily (a deb repository for ubuntu updated daily)

Today, when I create package, your library work great... but your file "multi.go" in example create a binary file who is put in bin path.

I don't know if it's a good things to compile an example file every time someone take your library...
I'm quite a newbie in Go, so I don't have any solution to propose...
maybe put this code to README.md can work (it's not a too long file).

Let me know what you think about it :)

thanks

Very strange bug.

I tried your example code. It works for your your line but not by additional line:

(customer is just a struct -> DOES NOT PRINT IN COLOR)

log := logging.MustGetLogger("example")
format := logging.MustStringFormatter("%{color}%{time:15:04:05.000000} %{shortfunc} ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}")

backend1 := logging.NewLogBackend(os.Stderr, "", 0)
backend2 := logging.NewLogBackend(os.Stderr, "", 0)

// For messages written to backend2 we want to add some additional
// information to the output, including the used log level and the name of
// the function.
backend2Formatter := logging.NewBackendFormatter(backend2, format)

// Only errors and more severe messages should be sent to backend1
backend1Leveled := logging.AddModuleLevel(backend1)
backend1Leveled.SetLevel(logging.ERROR, "")

// Set the backends to be used.
logging.SetBackend(backend1Leveled, backend2Formatter)

log.Info("info") // WORKS
log.Notice("notice") //WORKS
log.Info("CustomeR: %+v", customer) // <-- DOES NOT PRINT IN COLOR

Don't leak the redacted string's length

In here, the to-be-redacted string is replaced by * of the same length, thus leaking the redacted string's length. Especially when redacting passwords from logs, this is not nice.

How about changing the default to a secure REDACTED or another fixed-length-string?

Logger as interface, not struct?

Hello guys!
I'm just wondering if you're considering to make Logger interface instead of struct. This can allow to switch between logger implementations.

Even PHP-world decided to develop convenient logger interface :)

RFC: Fine, Finer, Finest?

log4j and log4go both provide these extra levels below Debug. It adds nice granularity to debugging logs, as opposed to the single Debug all -or-nothing. I personally like it, and would write a patch for it, but not if you're not interested in merging.

Global logger

hello,

Sorry if this is a somewhat stupid question, but I am trying to define a global logger which I would use it multiple fils within my project. The structure is pretty simple:

src/
    tlookup.go  # main()
    papi.go      # rest 
    utils.go      # utils

the problem i am having is that if I define it in the main then I cant seem to reference the logger in methods in my other files. Any pointers you could git would be great. Thanks !

Thanks

-John

global SetLevel

We've multiple loggers, but would be nice to set the level of all of them in one place (e.g. normally all are at Error, but can bump one down specifically to debug that portion.

logging.SetLevel(logging.ERROR, "") // or "*"

Log using UTC time

I have a simple logger setup:

import logging "github.com/op/go-logging"

func main() {
    ...

    log := logging.MustGetLogger(name)

    // Setup the logger
    logBackend := logging.NewLogBackend(os.Stdout, "", 0)
    var format = logging.MustStringFormatter(
        `%{time:2006-01-02 15:04:05.000} : %{level:-6.6s} : %{message}`,
    )
    logging.timeNow = timeNow
    logBackendFormatter := logging.NewBackendFormatter(logBackend, format)
    logging.SetBackend(logBackendFormatter)
}

and I am trying to get it to output timestamps in UTC time, but I do not see a way to do this. I think setting logging.timeNow would work, but this isn't possible because it is not exported. Is there a way to do this? If not, could we support using custom time functions? I'd like to use something like:

func UtcTimeNow() time.Time {
    return time.Now().UTC()
}

Thanks!

Color property has no effect on log output

NewLogBackend.Color property has no effect when custom format with colors are supplied to SetFormatter. So having one backend to write to a file and colors in console in other is a no go. :(

    log_format := "%{color}[%{level:.4s}] %{time:15:04:05.000000} %{id:03x} %{shortfile} [%{longpkg}] %{longfunc} -> %{color:reset}%{message}"
    logging.SetFormatter(logging.MustStringFormatter(log_format))

If I am reading this correctly Record.Formatted and stringFormatter Format have no information about color from backend. If they would, it would be trivial to add really cool functionality like per backend formats and log details.

Make general log function public

Hello @op !
I really enjoy the library, it's been great using it!

It'd be awesome to have access to the root log function that Error, Warning, etc call, in one project we have our own logging wrapper that bundles a few different blasts out and we can't use go-logging backends. It'd be nice to be able to translate our own logging levels to go-loggingsLeveland calllog` directly rather than having to switch!

Timestamp appears two times

Hi,

Using such formatter:

 var format = logging.MustStringFormatter("%{time:20060102-15:04:05.000} %{level} %{module} %{message}")

I gets following output

2013/12/16 17:12:26 20131216-17:12:26.879 INFO mAin Get: Hello

How can I get rid of the first timestamp?

Thanks a lot.

revert Error() api change

In commit 0758a84 Error changed from
Error(format string, args ...interface{})
to
Error(args ...interface{})

So now all of Error calls in my projects print the literal formats. I am seeing stuff like:

err := fmt.Errorf("Error Message")
log.Error("Thing failed: %s", err)

now prints the format literally like:

Thing failed: %sError Message

I would say that the Error api should be no different than the other log level statements Critical, Warning, Notice, Info, Debug.

So I kindly ask you to revert the Error api change made in 0758a84.

Thanks!
-Cory

too much cpu time being spent even in loglevels below current level

hi, i have an app that does quite a bit of log traffic (potentially thousands of messages per second depending on which log level). I was troubleshooting an issue today (grafana/carbon-relay-ng#57) and noticed that we spend quite some cpu time in logging functions that are below the current log level. for example in Debug() when level is set to warning.
logging-profile
I notice that when we call (l *Logger) log it spends time creating a new record, allocating memory and increasing atomic sequence numbers.
and then in the LogBackend Log() it does a bunch more allocations and function calls, and then calls log.Logger. I didn't study all the code in detail, but why not just check the current loglevel first and bypass all the logic when we don't need it?

Color verb

Would be nice if the color verb supported other ansi colors (other than just the log color)

e.g.

var LogFormat = "%{color:gray}%{time:15:04:05.999} %{color}%{level} %{color:gray}%{shortfile}:  %{color:reset}%{message}"

You could wrap one of the ansi color libs out there

race test failed

package main

import (
        "os"
        "time"

        "github.com/op/go-logging"
)

func main() {
        go func() {
                test("test1")
        }()

        test("test2")

        time.Sleep(time.Second)
}

func test(name string) {
        backend := logging.NewLogBackend(os.Stdout, "", 0)
        leveledBackend := logging.AddModuleLevel(backend)
        leveledBackend.SetLevel(logging.DEBUG, name)
        logging.SetBackend(leveledBackend)

        logger := logging.MustGetLogger(name)
        logger.Debug("debug")
}

run go run -race main.go, DATA RACE detected:

# go run -race main.go 
debug
==================
WARNING: DATA RACE
Write by goroutine 6:
  github.com/op/go-logging.SetBackend()
      /root/godev/src/github.com/op/go-logging/backend.go:26 +0x24c
  main.test()
      /root/godev/src/logging/main.go:24 +0x522
  main.main.func1()
      /root/godev/src/logging/main.go:12 +0x39

Previous write by main goroutine:
  github.com/op/go-logging.SetBackend()
      /root/godev/src/github.com/op/go-logging/backend.go:26 +0x24c
  main.test()
      /root/godev/src/logging/main.go:24 +0x522
  main.main()
      /root/godev/src/logging/main.go:15 +0x51

Goroutine 6 (running) created at:
  main.main()
      /root/godev/src/logging/main.go:13 +0x38
==================
debug
Found 1 data race(s)
exit status 66

Stack Skip Count parameter

Hey @op !
As I mentioned in the previous issue on one project we have our own logging wrapper, as a result calling go-logging with formatting that dumps any sort of function call or file information will only product our logging wrapper. It'd be super nice to have a way to tell go-logging to skip X number of stack objects when it pulls the information.

Importing go-logging in multiple libraries reset level to default in previous imported places

This is bit of an odd bug to describe, but here goes.

I wrapped go-logging in a custom logger package that's imported by our libraries and workers. In that logger package I set the logging level to WARNING. The first time I import it, the level is WARNING, however the second I import it, the level for first one changes to DEBUG (the default level in go-logging). I know this because I'm seeing debug level logs in stdout for the first worker.

Here's the basic gist of the wrapper:

func NewGoLog(name string) *GoLogger {
    logging.SetFormatter(logging.MustStringFormatter("[%{level:.8s}] - %{message}"))

    // Send log to stdout
    var logBackend = logging.NewLogBackend(os.Stderr, "", stdlog.LstdFlags|stdlog.Lshortfile)
    logBackend.Color = true

    // Send log to syslog
    var syslogBackend, err = logging.NewSyslogBackend("")
    if err != nil {
        panic(err)
    }

    logging.SetBackend(logBackend, syslogBackend)

    loggingLevel = getLoggingLevelFromConfig(name)
    var goLog = &GoLogger{logging.MustGetLogger(name)}

    return goLog
}

GoLogger implements methods like:

Info(format string, args ...interface{})
Notice(format string, args ...interface{})

We use it like:

var log = New("tester")
log.Info("Started")

Thanks.

How could I print log both on screen and file by using go-logging

I followed the example, and I tried to use logging.MultiLogger, but it failed. could you please tell me how to resolve my problem? Thanks!!

my code as below

var format = logging.MustStringFormatter("[%{time:15:04:05.000}][%{shortfunc}][%{level:.4s}] %{message}")

beScreen := logging.NewLogBackend(os.Stdout, "", 0)

logfile := "log/test.log"
file, _ := os.OpenFile(logfile, os.O_RDWR|os.O_CREATE, 0666)
beFile := logging.NewLogBackend(file, "", 0)

beScreenFormatter := logging.NewBackendFormatter(beScreen, format)
beFileFormatter := logging.NewBackendFormatter(beFile, format)

beScreenLeveled := logging.AddModuleLevel(beScreenFormatter)
beScreenLeveled.SetLevel(logging.ERROR, "")

beFileLeveled := logging.AddModuleLevel(beFileFormatter)
beFileLeveled.SetLevel(logging.ERROR, "")

// Set 2 backends to be used.
logging.MultiLogger(beScreenLeveled, beFileLeveled)

Memory backends don't work with calldepth format verbs

Memory backend records don't properly handle formatters that use verbs that require stack inspection using calldepth.

Would the right fix be to call record.Formatted() before attempting to put the record into the linked list or channel so that the value is memoized?

Different formats for different log sinks?

So I started playing around with examples and while console output is pretty and colorful, syslog message looks like that:

Sep 19 01:43:00 hydra zeroctl[18897]: #033[33;1m2014-09-19T01:43:00.7243Z+02:00#033[0m#033[33m [W] #033[0mmain[main] Works

Is it possible to set up different format (per logger) ?

Only one backend being written to

This is almost certainly me doing something wrong. :-)

I'm setting two backends: one to stdout, one to a file. The file is successfully created and opened, but nothing is ever logged to it -- only to stdout. My simplified code looks like this:

var (
    logger                  = logging.MustGetLogger("aiab")
)

func main() {
    stdOutBackend := logging.NewLogBackend(os.Stdout, "", 0)
    logFileBaseName := "aiab-" + time.Now().Format(time.RFC3339)
    logFileName := os.Getenv("AIAB_LOGS") + "/" + logFileBaseName
    logFile, err := os.OpenFile(logFileName, os.O_APPEND|os.O_CREATE, 0664)
    if err != nil {
        panic("Could not open log file: " + err.Error())
    }
    logFileBackend := logging.NewLogBackend(logFile, "", 0)
    logging.SetBackend(stdOutBackend, logFileBackend)
    logging.SetFormatter(logging.GlogFormatter)
    logging.SetLevel(logging.DEBUG, "aiab")
}

What am I doing wrong? I've perused the various docs and I've tried some variations on the above but the same result: no error is ever reported, and the file is created successfully, but nothing is written to it, only stdout.

Thanks!

Problems with signals on log

Hi.

On the revision 970db52 the log's signals don't work well.
Example:

[INF] Module Location satisfied: %+v { 1 1 1}

The %v can't translate the object to log.

The problems happened on Go's version is 1.6.2

Cheers

any function to do a log rotation?

Is there a function to set the log rotation?
otherwise I have to write some function to:

  1. setup a new LogBackend with a new filename and replace the current Backend
  2. rename the old log file to xxx.log.$DATETIME
  3. rename the new log file to xxx.log

Add per-level formatter

Currently Formatter is usable only in backend logger. In some cases (e.g. for debug messages) is preferable to apply a different Formatter without touch the backend. So, in this case, it would be useful to apply the Formatter in level functions (e.g. log.Debug("message", formatter) )

Safe use of *LogBackend.Logger

Is it safe to write to the same *LogBackend.Logger concurrently from multiple goroutines? I ask because I am introducing a client library that requires *log.Logger and would like for the library logging to write to the same file as the application logs.

NewLogBackend signature is different on *nix and Windows

It causes errors when compiling on Win (but not on Linux\Mac).

Win: NewLogBackend(out *os.File, prefix string, flag int)
*nix: NewLogBackend(out io.Writer, prefix string, flag int)

https://github.com/op/go-logging/blob/master/log_windows.go#L54
https://github.com/op/go-logging/blob/master/log_nix.go#L40

In particular here's how we use go-logging: https://github.com/luci/luci-go/blob/master/common/logging/gologger/config.go#L30

It used to work fine, but after 03393de it compiles on Linux\Mac, but not on Windows (causing some confusion).


IMHO, public API should look identical on all platforms. Requiring os.File everywhere may be a breaking change. What do you think about using io.Writer in NewLogBackend on Win too, but try to cast it to os.File (and enabling colors only if cast succeeds)?

Date string is added to the message

package main

import (
        "github.com/op/go-logging"
)

var log = logging.MustGetLogger("main")

func main() {
    format := logging.MustStringFormatter("%{level} %{message}")
    logging.SetFormatter(format)
    log.Info("hello golang")
}

$ go run main.go
2013/11/08 18:09:02 INFO hello golang

I expected "INFO hello golang". Why date string is added to the message?

Use out of the box

Is there a way to use this 100% out of the box with default settings attached:

i.e.
var log = logging.MustGetLogger("example")
log.Info("CustomeR: %+v", customer)

and BANG it just works?

Error & Critical level logging issue

Messages used in error and critical level logging are displayed separately before log message as logged in formatted manner

Sample output:

16:50:01.581 main . DEBU 001 debug ******
16:50:01.583 main . INFO 002 info
16:50:01.584 main . NOTI 003 notice
16:50:01.584 main . WARN 004 test
this is error level logging message
16:50:01.585 main . ERRO 005 this is error level logging message
this is critical level message
16:50:01.587 main . CRIT 006 this is critical level message

code example:

package main

import (
"os"

"github.com/op/go-logging"

)

var log = logging.MustGetLogger("example")

// Example format string. Everything except the message has a custom color
// which is dependent on the log level. Many fields have a custom output
// formatting too, eg. the time returns the hour down to the milli second.
var format = logging.MustStringFormatter(
"%{color}%{time:15:04:05.000} %{shortfunc} . %{level:.4s} %{id:03x}%{color:reset} %{message}",
)

// Password is just an example type implementing the Redactor interface. Any
// time this is logged, the Redacted() function will be called.
type Password string

func (p Password) Redacted() interface{} {
return logging.Redact(string(p))
}
func main() {
//test := "there are log of error i"

// For demo purposes, create two backend for os.Stderr.
backend1 := logging.NewLogBackend(os.Stderr, "", 0)
backend2 := logging.NewLogBackend(os.Stderr, "", 0)

// For messages written to backend2 we want to add some additional
// information to the output, including the used log level and the name of
// the function.
backend2Formatter := logging.NewBackendFormatter(backend2, format)

// Only errors and more severe messages should be sent to backend1
backend1Leveled := logging.AddModuleLevel(backend1)
backend1Leveled.SetLevel(logging.ERROR, "")

// Set the backends to be used.
logging.SetBackend(backend1Leveled, backend2Formatter)

log.Debug("debug %s", Password("secret"))
log.Info("info")
log.Notice("notice")
log.Warning("test")
log.Error("this is error level logging message")

// log.Error("err")
log.Critical("this is critical level message")
}

Formatter fields

The example states:
// Example format string. Everything except the message has a custom color
// which is dependent on the log level. Many fields have a custom output
// formatting too, eg. the time returns the hour down to the milli second.

This info plus the example formatter are all I can find about the possible options. I assume there are more fields possible with each their own custom formatting. Is there a complete list of all this somewhere ?

Time is always included

Even when you call logging.SetFormatter() with a format that does not include the time verb, the time is still included in the beginning of every message. The very example in the README exhibits this behaviour. Maybe that's actually intentional, but it's not stated anywhere. If that's the case, it'd be nice if there was a way to turn it off.

experimental websocket backend

Hi,

I'm experimented a little with exposing logs over websockets. The backend exposes a net/http Handler which upgrades requests to websocket connections (it uses the gorilla ws pkg) and registers them. Records given to the backend are than broadcasted to all registered connections.

I just thought I share this for others to see how easy it is to implement your own backends. If there is interest i'd be happy to refine it and open a PR.

Possible areas of improvement:

  • Implement Leveled per ws connection and let clients control this
  • Format to JSON
  • ???

best way to initialize the logger

This is not technically a issue but a question. I'm moving my code to go-logging but met a problem. Some packages are loaded ahead of my main function, by package level init() function. Thus, some initialization code would use default log settings to output information. But I do hope to keep everything during bootstrap.

The question is, do we have a way to set global log settings before all packages? I'm thinking of configuration file, maybe.

I can live with current behavior, BTW. This logging tool is already cool enough. Thanks~

Prefix

Suppose I have a logger, and i want to prefix its output. Pseudo example:

func factorial(log prefix.Logger, i int) {
  log = log.Prefix("%d", i)
  log.Debug("enter")
  defer log.Debug("exit")

  switch {
  case i < 0:
    log.Error("is negative!")
    return 0
  case i == 0, i == 1:
    return 1
  default:
    return i * factorial(log, i - 1)
  }
}

func main() {
  n, _ := strconv.Atoi(os.Args[1])
  log := prefix.Logger("factorial")
  log = log.Prefix("factorial:")
  fmt.Printf("%d", factorial(log, n))
}
> go run main.go 4
factorial: 4 enter
factorial: 4 3 enter
factorial: 4 3 2 enter
factorial: 4 3 2 1 enter
factorial: 4 3 2 1 exit
factorial: 4 3 2 exit
factorial: 4 3 exit
factorial: 4 exit
24

> go run main.go -10
factorial: -10 enter
factorial: -10 is negative!
factorial: -10 exit
0

I implemented this: https://gist.github.com/jbenet/70ff524c460986eab6c3 which does what I want. (extracted from go-ipfs). BUT, the issue is the filename breaks, because op/go-logging assumes the runtime calldepth is at a particular place in the stack, and that its logger is not being wrapped.

So, if not wrapping, then it has to be done within a logging.Logger.

  • could wrap a Backend? can't get the logger's current backend, and the Record's fields are private.
  • could wrap the Formatter? the logger is not associated with a formatter. see backend.

Suggestions?

init() { Reset() } clobbers any previously-set custom logging levels

init() { Reset() } at the bottom of logger.go clobbers any previously-set custom logging levels.

// Reset restores the internal state of the logging library.
func Reset() {
    // TODO make a global Init() method to be less magic? or make it such that
    // if there's no backends at all configured, we could use some tricks to
    // automatically setup backends based if we have a TTY or not.
    sequenceNo = 0
    b := SetBackend(NewLogBackend(os.Stderr, "", log.LstdFlags))
    b.SetLevel(DEBUG, "")
    SetFormatter(DefaultFormatter)
    timeNow = time.Now
}

+1 for making it be less magic, would strongly prefer to explicitly invoke .Init() or .Reset() during initial logger setup/configuration.

This just cost me at 2 hours of time to track down why the custom log levels were not working, and I'd love a more elegant solution than the ugly hack of adding the following fragment around all the logging setup and configuration code:

// Wait until after logging.init() has had a chance to run.
go func() {
    time.Sleep(time.Second)
    ...
}()```

Formatting versions

@op not really sure what the right interface is -- you know best. But it strikes me that since the logging functions take formatting, maybe they should follow stdlib practice of having both Name(string) and Namef(string, ...interface{}) variants.

Random reason to lean towards the extra f: lint errors like this:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.