Skip to content

Commit

Permalink
Merge pull request #2 from nohupped/nohupped/use_pointers
Browse files Browse the repository at this point in the history
use pointers to store loglevel
  • Loading branch information
nohupped authored Jan 4, 2020
2 parents ef78151 + f486d75 commit ca61064
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 90 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
language: go
154 changes: 115 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,88 @@
# glog
# glog [![Build Status](https://travis-ci.org/nohupped/glog.svg?branch=master)](https://travis-ci.org/nohupped/glog)

Go's modified log package with an option to set a loglevel, which will filter the output of logs based on that.
(This is the modified code from GO's original `log` package at https://github.com/golang/go/tree/master/src/log (version 1.6.2)), and the logic borrowed from https://github.com/Sirupsen/logrus package.
(This is a lame attempt to modify GO's original [`log` package](https://github.com/golang/go/tree/master/src/log) (version 1.6.2)), and the logic borrowed from [Sirupsen](https://github.com/Sirupsen/logrus) package.

## Why

##### Why!
I was trying to find a way to log `filename` and `line number` using logrus for obvious debugging purpose, but I failed to get a workaround. I am not using advanced features of `logrus` like `SetFormatter` or `hooks`. `Go`'s native `log` package already provides a feature to log filename and line numbers but it lacks setting a loglevel for filtering logs. I just borrowed and incorporated the idea of using a `loglevel`.
Newly added methods for `*Logger` like `(Error|Warn|Info|Debug)ln(), (Error|Warn|Info|Debug)f() and (Error|Warn|Info|Debug)()` will only output logs based on the configured loglevel with the helper function `SetLogLevel()`. Accepted log levels are `ErrorLevel, WarnLevel, InfoLevel and DebugLevel` which are of values `int 0, 1, 2, 3` respectively.

Default value of `loglevel` at the time of initing the `*Logger` is set to the lowest level, which is `ErrorLevel`.

##### Reference when setting loglevel:
## Breaking change because of using pointer to loglevel

Use

```bash
require github.com/nohupped/glog v0.0.0-20200102070319-ef78151f855d
```

in the go.mod file to continue using the older version that uses `int` as `loglevel` instead of `*uint`.

* why? To have the convenience of using this logger in `init()` functions and have a global variable that can be modified without calling the `SetStandardLogLevel` or similar functions in every importing sub-packages.

Eg: Package `foo/blah`

```golang
package blah
import (
// "flag"
log "github.com/nohupped/glog"
)

// Loglevel is the logging handler
var Loglevel *uint

func init() {
// loglevel := flag.Uint("loglevel", uint(glog.InfoLevel), "Loglevel.")
// flag.Parse()
// Don't do the above 2 lines in init functions. This will mess with go's testing because of https://github.com/golang/go/issues/33774.
// flag.Parse() and init() functions doesn't go well.
if Loglevel == nil {
l := log.ErrorLevel
Loglevel = &l
}
log.SetFlags(log.Lshortfile | log.Ldate | log.Ltime)
log.SetStandardLogLevel(Loglevel)
log.Infof("Setting loglevel to %d", log.InfoLevel)
}

```

and in package foo,

```golang
package main

import(
"foo/blah"
)
func main(){
loglevel := flag.Uint("loglevel", log.InfoLevel, "Loglevel.")
flag.Parse()
*blah.Loglevel = *loglevel // Dereference and modify the pointer value to update the loglevel globally on all the packages that imports foo/blah.
}
```

Now, for another sub-package `foo/extreme_computation`,

```golang
package extreme_computation
import(
_ "foo/blah"
log "github.com/nohupped/glog"
)

func PvsNP() {

}

```

it will see the updated loglevel from the `main` although the initial loglevel was set in `blah`, and this is because of the `var Loglevel *uint`

### Reference when setting loglevel

`logger.SetLogLevel(log.ErrorLevel)` will log only Errors using the method `log.Error*()`. Any calls to `log.Warn*()`, `log.Info*()` and `log.Debug*()` will not be logged unless the `loglevel` is changed.

Expand All @@ -20,47 +94,49 @@ Default value of `loglevel` at the time of initing the `*Logger` is set to the l

Note: To disable logging line numbers and file names, set the logger's flag similar to `logger := log.New(&buf, "logger: ", log.Ldate)` instead of `log.Lshortfile` or similar flags.

##### Example:
#### Example

```
```golang
package main

import (
"bytes"
"fmt"
log "github.com/nohupped/glog"
"bytes"
"fmt"
log "github.com/nohupped/glog"
)

func main() {
var buf bytes.Buffer
logger := log.New(&buf, "logger: ", log.Lshortfile)
// Below two lines to set logging to file
//file, _ := os.OpenFile("/tmp/testlog.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
//logger.SetOutput(file)
strfn := "Errorf()!"
logger.Errorf("Hello, this is %d Error from %s", 1, strfn)
logger.Error("Hello, this is 1 Error from Error()!")
logger.Warnln("Hello, This is from Warnln!") // This will not print because the default loglevel when initiating logger is set to ErrorLevel.
logger.SetLogLevel(log.InfoLevel)
logger.Errorln("Hello, This is Error from Errorln!")
logger.Warnln("Hello, This is Warn from Warnln!")
logger.Infoln("Hello, This is Info from Infoln!")
logger.Debugln("Hello, This is Debug from Debugln!") // This will not print because loglevel is set to InfoLevel
log.SetStandardLogLevel(log.DebugLevel) // set std loglevel. This will NOT set the *Logger struct's loglevel.
log.SetFlags(log.Lshortfile) // set flags to log. This will add short filename and line number.
log.Debugf("This is from %s", strfn)
log.Printf("%d error from %s", 1, "Error function")
log.Warnf("%d error from %s", 1, "Error function")
fmt.Println(&buf)
fmt.Print(&buf)
// Output:
// logger: main.go:19: ERROR: Hello, this is 1 Error from Errorf()!
// logger: main.go:20: ERROR: Hello, this is 1 Error from Error()!
// logger: main.go:23: ERROR: Hello, This is Error from Errorln!
// logger: main.go:24: WARN: Hello, This is Warn from Warnln!
// logger: main.go:25: INFO: Hello, This is Info from Infoln!
var buf bytes.Buffer
logger := log.New(&buf, "logger: ", log.Lshortfile)
// Below two lines to set logging to file
//file, _ := os.OpenFile("/tmp/testlog.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
//logger.SetOutput(file)
strfn := "Errorf()!"
logger.Errorf("Hello, this is %d Error from %s", 1, strfn)
logger.Error("Hello, this is 1 Error from Error()!")
logger.Warnln("Hello, This is from Warnln!") // This will not print because the default loglevel when initiating logger is set to ErrorLevel.
il := log.InfoLevel
logger.SetLogLevel(&iL)
logger.Errorln("Hello, This is Error from Errorln!")
logger.Warnln("Hello, This is Warn from Warnln!")
logger.Infoln("Hello, This is Info from Infoln!")
logger.Debugln("Hello, This is Debug from Debugln!") // This will not print because loglevel is set to InfoLevel
dl := log.DebugLevel
log.SetStandardLogLevel(&dl) // set std loglevel. This will NOT set the *Logger struct's loglevel.
log.SetFlags(log.Lshortfile) // set flags to log. This will add short filename and line number.
log.Debugf("This is from %s", strfn)
log.Printf("%d error from %s", 1, "Error function")
log.Warnf("%d error from %s", 1, "Error function")
fmt.Println(&buf)

fmt.Print(&buf)

// Output:
// logger: main.go:19: ERROR: Hello, this is 1 Error from Errorf()!
// logger: main.go:20: ERROR: Hello, this is 1 Error from Error()!
// logger: main.go:23: ERROR: Hello, This is Error from Errorln!
// logger: main.go:24: WARN: Hello, This is Warn from Warnln!
// logger: main.go:25: INFO: Hello, This is Info from Infoln!

```
`* Line numbers may vary.`
Loading

0 comments on commit ca61064

Please sign in to comment.