Global Registration (via packages)

I spent a lot of time searching and reading messages on this subject, but have not yet managed to fully answer my question - or maybe I just need more clarification on the existing answers.

I read this post, which has the same title as mine, but it is related to logging in via go, not packages.

What I'm trying to solve is to enter the main application and any packages it uses. I need a logger that can register in several places (which can be done with io.MultiWriter) and can do things like log.Error () and log.Debug ()

I know that there are packages that do this, and I know how to implement these things on my own.

That I cannot figure out how to use it correctly with my packages.

One way, of course, is to create a log in the main one, and then transfer it to all functions that require logging. But it seems uncomfortable.

My ideal solution would be to have a registrar, as a built-in global registrar, from a log package, but with added functionality, as mentioned above.

Basically I want this for additional debugging logging inside packages, so I can enable this in the production version if necessary.

What is the right way to do this?

+7
source share
4 answers

The right path is what you consider ideal. Just create a package (preferably following the Go conventions https://golang.org/doc/code.html ) and make your journal global:

package mylog // Define your custom logger type. type logger struct { /* Whatever you want */ } // Optionally make it a interface. type Logger interface { /* Your functions */ } // And just go global. var defaultLogger *Logger func init(){ defaultLogger = new(logger) } func Debug(params ...string){ // Have some fun. } // ... 

I would also recommend describing in the documentation that your project uses this logging feature.

+5
source

@ The answer to CedmundoMartinez fluttered my head to come up with (very simple and pretty obvious, now that I can use the rearview mirrors).

I am posting my answer here for those interested in a similar solution.

What I did was make a copy of the standard log package (src / log / log.go) and expand it. It could not be easier to get a global logger that already does everything that a standard logger does, and all you want! In this case, record alignment is supported.

The only changes I had to make:

 type Logger struct { mu sync.Mutex // ensures atomic writes; protects the following fields prefix string // prefix to write at beginning of each line flag int // properties out io.Writer // destination for output buf []byte // for accumulating text to write level int // One of DEBUG, ERROR, INFO } 

Only the last line is added. The log package sets the global variable std , which can then be used to access string fields from any function in the package.

Then I added constants for different levels of the log:

 const ( DEBUG = 1 << iota INFO ERROR ) 

Next, I added my functions:

(Note: ct is a package https://github.com/seago/go-colortext that allows console color text on windows, so all errors here are printed in red)

 func Error(v ...interface{}) { if std.level <= ERROR { ct.ChangeColor(ct.Red, true, ct.None, false) s := fmt.Sprintf("ERROR: %v", v...) std.Output(2, s) ct.ResetColor() } } func Info(format string, v ...interface{}) { if std.level <= INFO { s := fmt.Sprintf("INFO: "+format, v...) std.Output(2, s) } } func Debug(v ...interface{}) { if std.level <= DEBUG { s := fmt.Sprintf("DEBUG: %v", v...) std.Output(2, s) } } func SetLogLevel(lvl int) { std.level = lvl } 

And this! With this, I can now use it by simply importing the modified package instead of the standard log package and open it:

 import ( "errors" "tryme/log" ) func main() { log.SetLogLevel(log.INFO) log.Info("This is a test Info") err := errors.New("This is a test error!!!") log.Error(err) log.Debug("Testing debugging") // won't be printed with log.INFO } 

This, of course, is just a demo version, and it can be easily expanded with more log levels, output formatting, etc.

You can use all the functions that the standard log package provides, for example, SetOutput for writing to a file or MultiWriter for writing to a file and console, etc.

+3
source

To add, if you want to register multiple Go applications, you can use RPC and create a logging service. This application will work independently, providing services to other applications. Golang has his own package for him.

+1
source

I post the solution worked for me! I just created my own package and used the init function.

 package logging import ( "io" logging "log" "os" "github.com/Sirupsen/logrus" ) var ( log *logrus.Logger ) func init() { f, err := os.OpenFile("logs/application.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { logging.Fatalf("error opening file: %v", err) } log = logrus.New() //log.Formatter = &logrus.JSONFormatter{} log.SetReportCaller(true) mw := io.MultiWriter(os.Stdout, f) log.SetOutput(mw) } // Info ... func Info(format string, v ...interface{}) { log.Infof(format, v...) } // Warn ... func Warn(format string, v ...interface{}) { log.Warnf(format, v...) } // Error ... func Error(format string, v ...interface{}) { log.Errorf(format, v...) } var ( // ConfigError ... ConfigError = "%v type=config.error" // HTTPError ... HTTPError = "%v type=http.error" // HTTPWarn ... HTTPWarn = "%v type=http.warn" // HTTPInfo ... HTTPInfo = "%v type=http.info" ) 

And in any package, just import my package and I execute the function (Info, Warn, Error)

 package main import ( log "logging" ) func main() { log.Error(log.ConfigError, "Testing the error") } 

The log entry will be saved on the screen and saved in a file.

0
source

All Articles