FAQ
I am looking for an idiomatic way to do logging.

Assume I am writing
a) Packages intended as libraries for applications, that incorporate packages that also log
b) Applications that incorporate packages that also log.

The incorporated packages will not in the majority case be mine.

What I'd like to do is use the same logging library.

Here's what I'd like to be able to do:

* Specify different log levels, and have these passed to syslog and/or filtered in program dependent on application config file / command line

* Find some way of filtering by package or file etc. as well, so if I turn debug logging on in foo, it doesn't turn debug logging on in baz, just because foo imports bar which imports baz; again this filtering would be controlled by an application config file / command line

Sadly the standard "log" package does not define and export an interface which it implements. Therefore there is no 'standard logger', and (as far as I can see) no way of intercepting logs done in imported packages (that themselves just 'import "log"'), other than log.SetOutput(), and post-processing the log output. That's relatively disgusting a if I want to filter the log lines by package, I now need to parse log strings. It would have been nice if the log implementation passed semantic data (e.g. stack frame, prefix, priority) to an intermediate LogWriter, which in turn wrote those to an IOWriter, but that's not the case either. As it is, I can't see much way of rescuing existing packages besides parsing their log output. Ideas?

That leaves the choice of how to implement logging in my libraries and application. There appear to be a hundred existing packages to 'help', but no standard, and again sadly no interface, so (given log statements end up dotted around the source code) no easy way of swapping between any two, making the decision permanent--ish. Are there any common solutions here? Or (better) emerging standards?

--
Alex Bligh




--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Peter Mogensen at Mar 9, 2016 at 7:33 am

    On 2016-03-09 08:26, Alex Bligh wrote:
    I am looking for an idiomatic way to do logging.

    Assume I am writing
    a) Packages intended as libraries for applications, that incorporate packages that also log
    b) Applications that incorporate packages that also log. ...
    Here's what I'd like to be able to do:

    * Specify different log levels, and have these passed to syslog and/or filtered in program dependent on application config file / command line

    * Find some way of filtering by package or file etc. as well, so if I turn debug logging on in foo, it doesn't turn debug logging on in baz, just because foo imports bar which imports baz; again this filtering would be controlled by an application config file / command line
    I tried to solve this with:


    https://github.com/One-com/gonelog

    It works well for us. Your last item is done the same way as the python
    "logging" library - a hierarchy of named loggers.


    /Peter

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Konstantin Shaposhnikov at Mar 9, 2016 at 11:22 am
    Are there any common solutions here? Or (better) emerging standards?
    I hope that the emerging standard will be not to use logging frameworks in
    packages.

    In rare cases if a package needs to log something it should provide a way
    to inject logging function or interface. This way an application has full
    control on logging package to use (if any) on logging levels for different
    packages, etc. The following article explains this idea in more details -
    https://0value.com/about-Go-logging.

    I find it ironic that in Java land DI frameworks like Spring are very
    popular however they are totally ignored when it comes to logging. SLF4J
    became de-factor standard despite java.util.logging availabe in the
    standard library since Java 1.4. Still configuring logging in an
    application with many dependencies can be painful experience. Go is in a
    better position as it appeared later and can learn from Java mistakes.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Alex Bligh at Mar 9, 2016 at 1:10 pm

    On 9 Mar 2016, at 11:22, Konstantin Shaposhnikov wrote:

    Are there any common solutions here? Or (better) emerging standards?

    I hope that the emerging standard will be not to use logging frameworks in packages.
    Well, that's fine if you don't want your packages to log. However, often either (i) you do, or (ii) the package author thinks you do (or might). In both cases, I'd like to be able to control it and its destination.
    In rare cases if a package needs to log something it should provide a way to inject logging function or interface. This way an application has full control on logging package to use (if any) on logging levels for different packages, etc. The following article explains this idea in more details - https://0value.com/about-Go-logging.
    Thanks for the useful blog.

    What I was thinking of (which I think accords with what you are suggesting) is some form of LoggerInterface interface (or similar). This would be implemented trivially by a NullLogger (which simply discards everything).

    Packages would do something like

        var Log LoggerInterface = Log.NewNullLogger()

    And then call

        Log.Print()

    or equivalent. The default action would thus be 'discard' which is I think what you are seeking.

    Logging could be redirected by:
        myPackage.Log = myfancylog.NewFancyLogger()

    Equally packages could have different loggers per instance / section etc.

    For (https://golang.org/pkg/log/'s) Logger to implement LoggerInterface would require some (back compatible) modification by adding of new methods if LoggerInterface is also to support debug levels.

    It would (according to your article anyway) be relatively easy to make https://godoc.org/github.com/golang/glog implement this interface, and perhaps some of the other loggers, as well as provide an equivalent to glog's CopyStandardLogTo (copy normal logger output to glog).

    --
    Alex Bligh




    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Konstantin Shaposhnikov at Mar 9, 2016 at 1:38 pm

    On Wednesday, 9 March 2016 21:11:06 UTC+8, Alex Bligh wrote:

    On 9 Mar 2016, at 11:22, Konstantin Shaposhnikov <k.shapo...@gmail.com
    <javascript:>> wrote:
    Are there any common solutions here? Or (better) emerging standards?

    I hope that the emerging standard will be not to use logging frameworks
    in packages.

    Well, that's fine if you don't want your packages to log. However, often
    either (i) you do, or (ii) the package author thinks you do (or might). In
    both cases, I'd like to be able to control it and its destination.
    In rare cases if a package needs to log something it should provide a
    way to inject logging function or interface. This way an application has
    full control on logging package to use (if any) on logging levels for
    different packages, etc. The following article explains this idea in more
    details - https://0value.com/about-Go-logging.

    Thanks for the useful blog.

    What I was thinking of (which I think accords with what you are
    suggesting) is some form of LoggerInterface interface (or similar). This
    would be implemented trivially by a NullLogger (which simply discards
    everything).

    Packages would do something like

    var Log LoggerInterface = Log.NewNullLogger()

    And then call

    Log.Print()

    or equivalent. The default action would thus be 'discard' which is I think
    what you are seeking.

    Logging could be redirected by:
    myPackage.Log = myfancylog.NewFancyLogger()

    Equally packages could have different loggers per instance / section etc.

    For (https://golang.org/pkg/log/'s) Logger to implement LoggerInterface
    would require some (back compatible) modification by adding of new methods
    if LoggerInterface is also to support debug levels.
    I think in practice debug levels are needed even less often than logging
    from a package. The simplest solution for such packages to define *var
    Debug bool*. Defining Logger interface with Info and Debug methods is
    slightly more flexible but IMHO unnecessary.


    It would (according to your article anyway) be relatively easy to make
    https://godoc.org/github.com/golang/glog implement this interface, and
    perhaps some of the other loggers, as well as provide an equivalent to
    glog's CopyStandardLogTo (copy normal logger output to glog).
    While it would be nice for all logging packages to conform to the same
    interface it is not strictly necessary. An application can "connect" all
    packages to the chosen logging framework via few adapter functions and/or
    structs.


    --
    Alex Bligh



    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tamás Gulácsi at Mar 9, 2016 at 2:38 pm
    var Debugf, Infof... func(pat string, args interface...)

    And assign blackhole functions in the lib.
    This way the user can choose the leveling filtering, destination... Everything.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Manlio Perillo at Mar 9, 2016 at 3:47 pm
    Il giorno mercoledì 9 marzo 2016 15:37:31 UTC+1, Tamás Gulácsi ha scritto:
    var Debugf, Infof... func(pat string, args interface...)

    And assign blackhole functions in the lib.
    This way the user can choose the leveling filtering, destination...
    Everything.
    Better (IMHO):
       var DebugOutput func (calldepth int, s string) error
    or, even better,
       func SetDebugOutput(func (calldepth int, s string) error)

    so that you can use log.Output function.

    Personally, I'm using log *only* for error messages. When I will need
    debug messages I will use a different log.Logger instance.
    Info, warning, fatal, trace does not exists, for me.


    Manlio

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedMar 9, '16 at 7:27a
activeMar 9, '16 at 3:47p
posts7
users5
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase