go-logr / zapr Goto Github PK
View Code? Open in Web Editor NEWA logr implementation using Zap
License: Apache License 2.0
A logr implementation using Zap
License: Apache License 2.0
In k8s it's common to use relatively high V(2, 4, 6, 9) etc.
l // zap logger at debug level
zaprLogger := zapr.NewLogger(l)
log.SetLogger(zaprLogger)
fs := flag.NewFlagSet("dummy", flag.ContinueOnError)
klog.InitFlags(fs)
if err := fs.Lookup("v").Value.Set("9"); err != nil {
panic(err)
}
klog.SetLogger(zaprLogger.WithName("klog"))
klog.V(0).Infof("v: 0")
klog.V(2).Infof("v: 2")
klog.V(4).Infof("v: 4")
klog.V(9).Infof("v: 9")
The only thing outputed is:
2021-08-04T20:40:00.933+0200 INFO klog v: 0
However I see kubernetes logs being outputted with the right V() all being info level:
2021-08-04T20:40:01.909+0200 INFO klog GET https://82281D6D2F9D29E40D559B8DC3DFAD76.gr7.us-east-1.eks.amazonaws.com/api?timeout=32s 200 OK in 972 milliseconds
2021-08-04T20:40:02.037+0200 INFO klog GET https://82281D6D2F9D29E40D559B8DC3DFAD76.gr7.us-east-1.eks.amazonaws.com/apis?timeout=32s 200 OK in 127 milliseconds
2021-08-04T20:40:02.166+0200 INFO klog GET https://82281D6D2F9D29E40D559B8DC3DFAD76.gr7.us-east-1.eks.amazonaws.com/apis/apps/v1?timeout=32s 200 OK in 127 milliseconds
2021-08-04T20:40:02.167+0200 INFO klog GET https://82281D6D2F9D29E40D559B8DC3DFAD76.gr7.us-east-1.eks.amazonaws.com/apis/coordination.k8s.io/v1?timeout=32s 200 OK in 128 milliseconds
2021-08-04T20:40:02.167+0200 INFO klog GET https://82281D6D2F9D29E40D559B8DC3DFAD76.gr7.us-east-1.eks.amazonaws.com/apis/apiregistration.k8s.io/v1beta1?timeout=32s 200 OK in 128 milliseconds
(I'm not entirely sure what's happening within that code).
What I'd like to have custom function/mapping how V(...) map to zap log levels, and even have filtering capabilities from provided function.
klog.InfoS and klog.ErrorS warn about invalid parameters:
"odd number of arguments passed as key-value pairs for logging","ignored key":"akey2"
It might make sense to add that also to zapr, for the sake of consistency.
This is relevant for WithValues
, Info
, Error
.
I have a zapr logger working, but it appears the logger is not respecting the DisableCaller
config value that is being set. Here is the code sample:
func init() {
// Build a zap logger.
cfg := zap.NewDevelopmentConfig()
// Stop annotating logs with the calling function's file name.
cfg.DisableCaller = false
fmt.Printf("DisableCaller=%v\n", cfg.DisableCaller)
zapLog, err := cfg.Build()
if err != nil {
panic(fmt.Sprintf("error building logger: %v", err))
}
defer zapLog.Sync()
// zapr defines an implementation of the Logger
// interface built on top of Zap (go.uber.org/zap).
Logger = zapr.NewLogger(zapLog)
Logger.Info("started zapr logger")
}
As you can see from the logs, the calling function's file name and line number still appear.
DisableCaller=false
2019-02-20T22:26:23.561-0800 INFO zapr/zapr.go:69 started zapr logger
Some Background:
I've been trying to create a top level logger for an application using zap, and zapr.
The api I am aiming for is something along the lines of this:
log.Debug(msg, "key 1", "value 1")
log.Info(msg, "key 2", "value 2")
odd number of arguments passed as key-value pairs for logging
Code to reproduce error
Here's some sample code to reproduce the error:
package main
import (
"github.com/go-logr/logr"
"github.com/go-logr/zapr"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"os"
)
func NewZaprLogger() logr.Logger {
consoleWriterSyncer := zapcore.AddSync(os.Stderr)
logConsoleEnc := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
levelSelector := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl >= zapcore.DebugLevel
})
logCore := zapcore.NewTee(zapcore.NewCore(logConsoleEnc, consoleWriterSyncer, levelSelector))
zapLog := zap.New(logCore)
logLocal := zapr.NewLogger(zapLog)
return logLocal
}
func Debug(msg string, keysAndValues ...interface{}) {
logger := NewZaprLogger()
if keysAndValues != nil {
logger.V(1).Info(msg, keysAndValues)
} else {
logger.V(1).Info(msg)
}
}
func main() {
Debug("this is a message", "key 1", "value 1")
}
Here's the output I get:
2021-07-21T10:25:27.128-0400 DPANIC odd number of arguments passed as key-value pairs for logging {"ignored key": ["key 1","value 1"]}
2021-07-21T10:25:27.128-0400 DEBUG this is a message
Questions:
I recognize that it's possible that my use case is not one supported by Zapr, but I wanted to ask before I changed my approach.
Any insights on this is greatly appreciated.
Thanks!
With the changes to fix #6 now creating loggers using WithName or WithValues now skips to many levels of callstack
e.g.
log = zapr.NewLogger(zapLog).WithValues("version", Version).WithName("test")
log.V(0).Info("Initializing")
now prints
{"level":"info","ts":1576782453.943943,"logger":"test","caller":"runtime/asm_amd64.s:1357","msg":"Initializing","version":""}```
AddCallerSkip should only skip a level on a "root" logger
Team,
I found a new release a few days and totally agreed on pin zap to v.19.0.
However, the latest v1.0.0+1
release tag doesn't support semver spec.
Actually, This release tag replaced v1.0.1-0.20210809170106-a3325063a237
, pkg.go.dev can't handle +1
verb. See below:
Is it intended?
This is related with this issue.
When trying to use other log levels smaller than -1 (e.g. V(2)) with cfg := zap.NewProductionConfig()
(with development config works fine) I've got the following panic error:
panic: runtime error: index out of range
goroutine 1 [running]:
github.com/presslabs/mysql-operator/vendor/go.uber.org/zap/zapcore.(*counters).get(0xc0001d2000, 0xc000151cfe, 0xbb762a, 0xc, 0xc000151be0)
/home/x/go/src/github.com/presslabs/mysql-operator/vendor/go.uber.org/zap/zapcore/sampler.go:48 +0x79
github.com/presslabs/mysql-operator/vendor/go.uber.org/zap/zapcore.(*sampler).Check(0xc00018f560, 0xfe, 0xbee5907d06b7cfd4, 0x2a36d55, 0x11b62a0, 0xbb4baf, 0x7, 0xbb762a, 0xc, 0x0, ...)
/home/x/go/src/github.com/presslabs/mysql-operator/vendor/go.uber.org/zap/zapcore/sampler.go:128 +0x9d
github.com/presslabs/mysql-operator/vendor/go.uber.org/zap.(*Logger).check(0xc0000a91a0, 0x40bffe, 0xbb762a, 0xc, 0xc00010e501)
/home/x/go/src/github.com/presslabs/mysql-operator/vendor/go.uber.org/zap/logger.go:269 +0x137
github.com/presslabs/mysql-operator/vendor/go.uber.org/zap.(*Logger).Check(0xc0000a91a0, 0xb2a0fe, 0xbb762a, 0xc, 0xfffffffffffffffe)
/home/x/go/src/github.com/presslabs/mysql-operator/vendor/go.uber.org/zap/logger.go:172 +0x48
github.com/presslabs/mysql-operator/vendor/github.com/go-logr/zapr.(*infoLogger).Info(0xc0000bba40, 0xbb762a, 0xc, 0x0, 0x0, 0x0)
/home/x/go/src/github.com/presslabs/mysql-operator/vendor/github.com/go-logr/zapr/zapr.go:69 +0x4e
main.main()
/home/x/go/src/github.com/presslabs/mysql-operator/cmd/mysql-operator-sidecar/main.go:119 +0x62f
Everything is fine when running on Go 1.20 but when I go vet
on Go 1.21 issues are found.
$ go version
go version go1.20.14 linux/amd64
go vet ./operator/...
$ go version
go version go1.21.8 linux/amd64
$ go vet ./operator/...
# github.com/go-logr/zapr
../../../../pkg/mod/github.com/go-logr/[email protected]/slogzapr.go:61:31: undefined: zap.Inline
../../../../pkg/mod/github.com/go-logr/[email protected]/slogzapr.go:169:3: unknown field Function in struct literal of type zapcore.EntryCaller
../../../../pkg/mod/github.com/go-logr/[email protected]/slogzapr.go:175:37: undefined: zap.Inline
../../../../pkg/mod/github.com/go-logr/[email protected]/zapr_slog.go:42:14: undefined: zap.Inline
Originally found in this PR
Running the example program from the README prints this line:
2019-08-08T11:36:25.528-0400 INFO zapr/zapr.go:69 Logr in action! {"the answer": 42}
I would expect it to print the file and line of the program, rather than a line within zapr.go.
While looking at zapr again while adding slog support, I noticed that we unnecessarily build up a []zap.Field in WithValues and while handling Info and Error. What we can do instead is zap.Inline and there directly encode all parameters, without additional allocations.
When the value in a key/value pair is logged, it gets passed through zap.Any
which uses certain interfaces (like Stringer
) if available to serialize the value.
When that same value is contained in something else like a slice or a struct, it gets handled differently by zap.Reflect
: those interfaces are ignored.
This is why []klog.ObjectRef
worked as intended (logged as array of structs) whereas kobj.ObjectRef
didn't (logged as string).
I'm not sure whether this is a problem, but it seems inconsistent.
Code importing this is confusing because the import path is github.com/go-logr/zapr
but the imported package iszaplogr
. See kubernetes-sigs/controller-runtime#71 (comment).
Hi,
I'm trying to understand how I can use Logr to set the log levels for logging verbosity. I'm pretty new to this library and Zap in general, so I'll probably ask some pretty fundamental questions here.
My requirement is that I want to be able to show/hide logs depending on verbosity. For example, I want to set a setting in the logger to only show V(2) or above (in this case it is Warning and above for Zap).
The problem is that with using the Logr
interface, the V()
function only applies non-negative values. According to this StackOverflow post, all the levels from Logr are inverted in Zap. This means to use the Warning level in Zap, I must pass in V(-2)
. However, this is not possible given that the function implementation applies all negative values as 0: https://github.com/go-logr/logr/blob/master/logr.go#L282-L292
Is it correct my understanding of the mapping is this:
Logr | Zap |
---|---|
1 | -1 (Debug) |
0 | 0 (Info) |
-1 | 1 (Warning) |
-2 | 2 (Error) |
and so on...
How can I set negative verbosity levels if I am restricted to only using the Logr interface?
Thanks
golang.org/x/crypto/ v0.0.0-20191011191535-87dc89f01550
A nil pointer dereference in the golang.org/x/crypto/ss h component through v0.0. 0-20201203163018-be40 0aefbc4c for Go allows rem ote attackers to cause a de nial of service against SSH servers.
can you upgrade the package golang.org/x/crypto/ to v0.0.0-20220829220503-c86fa9a7ed90
Hi! I'm using v1.2.3 with zap v1.19.0 and it seems like there's a data race in WithName() method. Here's the Go's data race detector output:
==================
WARNING: DATA RACE
Read at 0x00c0006a0180 by goroutine 21:
runtime.racereadrange()
<autogenerated>:1 +0x1b
github.com/go-logr/zapr.(*zapLogger).WithName()
/Users/pachanga/go/pkg/mod/github.com/go-logr/[email protected]/zapr.go:228 +0xc6
github.com/go-logr/logr.Logger.WithName()
...
Previous write at 0x00c0006a0180 by goroutine 19:
go.uber.org/zap.(*Logger).clone()
/Users/pachanga/go/pkg/mod/go.uber.org/[email protected]/logger.go:257 +0x7d
go.uber.org/zap.(*Logger).Named()
/Users/pachanga/go/pkg/mod/go.uber.org/[email protected]/logger.go:143 +0x49
github.com/go-logr/zapr.(*zapLogger).WithName()
/Users/pachanga/go/pkg/mod/github.com/go-logr/[email protected]/zapr.go:228 +0xc6
github.com/go-logr/logr.Logger.WithName()
...
The logr recommendation is to not use spaces in keys:
https://github.com/go-logr/logr/blob/622c97b4eb90a99cc628f4773662eb0015ce0f2a/logr.go#L128
zapr violates that recommendation with zap field
, ignored key
, invalid key
in its panic messages in `handleFields.
WithName and WithValues methods don't preserve the parent log level - they always create a new logger with zap.InfoLevel
(V-level 0)
package main
import (
"github.com/go-logr/zapr"
"go.uber.org/zap"
)
func main() {
zl, _ := zap.NewProduction()
l := zapr.NewLogger(zl)
l.V(0).Info("level 0 should be logged")
l.V(1).Info("level 1 should not be logged")
l.V(1).WithValues("key", "value").Info("level 1 with values should not be logged")
l.V(1).WithName("debugName").Info("level 1 with name should not be logged")
}
output:
{"level":"info","ts":1601586159.5837796,"caller":".local/run.go:11","msg":"level 0 should be logged"}
{"level":"info","ts":1601586159.583864,"caller":".local/run.go:13","msg":"level 1 with values should not be logged","key":"value"}
{"level":"info","ts":1601586159.5838814,"logger":"debugName","caller":".local/run.go:14","msg":"level 1 with name should not be logged"}
Team,
We have been facing this error while deploying OPA-Gatekeeper policies, Please feel free to close this issue if you think it is not related to this project.
resource","metaKind":"upgrade","name":"allow-only-ecr-registry","namespace":"","error":"Operation cannot be fulfilled on k8sallowedrepos.constraints.gatekeeper.sh "allow-only-ecr-registry": the object has been modified; please apply your changes to the latest version and try again","stacktrace":"github.com/go-logr/zapr.(*zapLogger).Error
uber-go/zap#975 is in so we'll need to pick something > 1.18.1, when it is ready.
Just came here to report #6 but notice it's been fixed, just the change hasn't been release under a new tag.
Go Modules will by default install v0.1.1 which doesn't have these changes.
Workaround for now is to go get github.com/go-logr/zapr@master
, but many people won't do this by default.
Could v0.1.2 be created?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.