yaegi
yaegi copied to clipboard
import "go.uber.org/zap" fails
The following program sample.go triggers an unexpected result
package main
import (
"time"
"go.uber.org/zap"
)
func main() {
logger, _ := zap.NewProduction()
// defer logger.Sync() // flushes buffer, if any
sugar := logger.Sugar()
sugar.Infow("failed to fetch URL",
// Structured context as loosely typed key-value pairs.
"url", "blabla",
"attempt", 3,
"backoff", time.Second,
)
sugar.Infof("Failed to fetch URL: %s", "blabla")
}
Expected result
{"level":"info","ts":1625585709.656375,"caller":"yaegi/foo.go:15","msg":"failed to fetch URL","url":"blabla","attempt":3,"backoff":1}
{"level":"info","ts":1625585709.656471,"caller":"yaegi/foo.go:21","msg":"Failed to fetch URL: blabla"}
Got
% yaegi run -unrestricted -unsafe ./sample.go
run: ./foo.go:8:2: import "go.uber.org/zap" error: /Users/mpl/src/go.uber.org/zap/array.go:26:2: import "go.uber.org/zap/zapcore" error: /Users/mpl/src/go.uber.org/zap/zapcore/entry.go:31:2: import "go.uber.org/zap/internal/exit" error: /Users/mpl/src/go.uber.org/zap/internal/exit/exit.go:32:2: not enough arguments in call to real
Yaegi Version
devel
Additional Notes
Hints at: https://github.com/uber-go/zap/blob/master/internal/exit/exit.go#L27
@Darkweak fyi, I was able to get past your issue by changing all func() signatures to func(i int) , so that they would match the os.Exit signature. Not a real fix of course, but that allowed us to see that there's other problems waiting behind. So it's going to be several fixes before you can use that package in yaegi.
So, what's next ? Is there another way to make plugins for træfik instead of using yaegi while you're trying to fix this bug ? @mpl
The plugin's system inside Traefik is based on Yaegi, then there is no other way.
You have to wait for the Yaegi fix or fork go.uber.org/zap to fix the problem with the real function.
@ldez I don't think fork the zap project and patch by myself is a good and viable solution. When does the fix would be available ? As rc or concrete release idc, that's just for testing purpose and be able to prepare the release of this plugin.
you can follow #1173 and #1174
@Darkweak FYI, with #1174, #1176, #1178, and #1180 now merged , the example above goes much further, but we're now hitting problems in sync/pool, so there's more work (potentially trickier, yet to be determined) to be done.
Thank you, and many thanks to @mvertes for his incredible work 🚀
I want to add something to this issue (I'm using 4653d87):
scope.go:225: nil reflect type
panic: nil reflect type [recovered]
panic: /Users/jptosso/go/src/github.com/jptosso/coraza-waf/vendor/go.uber.org/zap/logger.go:309:2: CFG post-order panic: nil reflect type
goroutine 1 [running]:
github.com/traefik/yaegi/interp.(*Interpreter).cfg.func2.1(0xc0015ed8c0)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/cfg.go:467 +0xb7
panic(0x1a212c0, 0xc000f08b00)
/usr/local/Cellar/go/1.16.5/libexec/src/runtime/panic.go:965 +0x1b9
log.Panic(0xc0009120b0, 0x1, 0x1)
/usr/local/Cellar/go/1.16.5/libexec/src/log/log.go:354 +0xae
github.com/traefik/yaegi/interp.(*scope).add(0xc000fc01b0, 0xc0004962d0, 0x1)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/scope.go:225 +0x175
github.com/traefik/yaegi/interp.(*Interpreter).cfg.func2(0xc0015ed8c0)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/cfg.go:1672 +0x2226
github.com/traefik/yaegi/interp.(*node).Walk(0xc0015ed8c0, 0xc000912e10, 0xc000912dd8)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:288 +0xa6
github.com/traefik/yaegi/interp.(*node).Walk(0xc0015ed7a0, 0xc000912e10, 0xc000912dd8)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:285 +0x67
github.com/traefik/yaegi/interp.(*node).Walk(0xc0015e17a0, 0xc000912e10, 0xc000912dd8)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:285 +0x67
github.com/traefik/yaegi/interp.(*node).Walk(0xc0015dfd40, 0xc000912e10, 0xc000912dd8)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:285 +0x67
github.com/traefik/yaegi/interp.(*node).Walk(0xc0014e5560, 0xc000912e10, 0xc000912dd8)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:285 +0x67
github.com/traefik/yaegi/interp.(*Interpreter).cfg(0xc00033e200, 0xc0014e5560, 0xc0000de2e9, 0xf, 0xc00056970d, 0x3, 0x0, 0x0, 0x0, 0x0, ...)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/cfg.go:60 +0x2a7
github.com/traefik/yaegi/interp.(*Interpreter).importSrc(0xc00033e200, 0xc000042810, 0x24, 0xc0000de2e9, 0xf, 0xc000640c01, 0xc0000c2610, 0x5, 0x0, 0xf)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/src.go:117 +0x68f
github.com/traefik/yaegi/interp.(*Interpreter).gta.func1(0xc00063d7a0, 0xc00054bb98)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/gta.go:226 +0x1390
github.com/traefik/yaegi/interp.(*node).Walk(0xc00063d7a0, 0xc000913b98, 0x0)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:281 +0xb6
github.com/traefik/yaegi/interp.(*node).Walk(0xc00063d440, 0xc000913b98, 0x0)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:285 +0x67
github.com/traefik/yaegi/interp.(*node).Walk(0xc00063d200, 0xc000913b98, 0x0)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:285 +0x67
github.com/traefik/yaegi/interp.(*Interpreter).gta(0xc00033e200, 0xc00063d200, 0xc0000427e0, 0x2d, 0xc0000c42a1, 0x2d, 0xc00060f4c0, 0xf, 0xc00063d200, 0x0, ...)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/gta.go:20 +0x258
github.com/traefik/yaegi/interp.(*Interpreter).importSrc(0xc00033e200, 0xc0001986c0, 0x1d, 0xc0000c42a1, 0x2d, 0xc000171301, 0xc00033e200, 0xc00054c078, 0xc00054c078, 0x6)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/src.go:100 +0xfe5
github.com/traefik/yaegi/interp.(*Interpreter).gta.func1(0xc0005ff9e0, 0xc00054c948)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/gta.go:226 +0x1390
github.com/traefik/yaegi/interp.(*node).Walk(0xc0005ff9e0, 0xc000914948, 0x0)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:281 +0xb6
github.com/traefik/yaegi/interp.(*node).Walk(0xc0005ff680, 0xc000914948, 0x0)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:285 +0x67
github.com/traefik/yaegi/interp.(*node).Walk(0xc0005ff440, 0xc000914948, 0x0)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:285 +0x67
github.com/traefik/yaegi/interp.(*Interpreter).gta(0xc00033e200, 0xc0005ff440, 0xc0001986c0, 0x1d, 0xc00050c041, 0x1d, 0xc000203f58, 0x6, 0xc0005ff440, 0x0, ...)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/gta.go:20 +0x258
github.com/traefik/yaegi/interp.(*Interpreter).importSrc(0xc00033e200, 0xc000203d7a, 0x1, 0xc00050c041, 0x1d, 0xc00020c401, 0x0, 0x1, 0x2343f18, 0x6)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/src.go:100 +0xfe5
github.com/traefik/yaegi/interp.(*Interpreter).gta.func1(0xc0003eb440, 0xc0001cf6f8)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/gta.go:226 +0x1390
github.com/traefik/yaegi/interp.(*node).Walk(0xc0003eb440, 0xc0009156f8, 0x0)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:281 +0xb6
github.com/traefik/yaegi/interp.(*node).Walk(0xc0003eaa20, 0xc0009156f8, 0x0)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:285 +0x67
github.com/traefik/yaegi/interp.(*node).Walk(0xc0003ea7e0, 0xc0009156f8, 0x0)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:285 +0x67
github.com/traefik/yaegi/interp.(*Interpreter).gta(0xc00033e200, 0xc0003ea7e0, 0xc000203d7a, 0x1, 0xc0002039ac, 0x2, 0xc000203a90, 0x6, 0xc0003ea7e0, 0x0, ...)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/gta.go:20 +0x258
github.com/traefik/yaegi/interp.(*Interpreter).importSrc(0xc00033e200, 0x1cd9d58, 0x1, 0xc0002039ac, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/src.go:100 +0xfe5
github.com/traefik/yaegi/interp.(*Interpreter).EvalTest(...)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/interp/interp.go:509
main.test(0xc0000ca000, 0x0, 0x0, 0xc000094101, 0xc00008a480)
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/cmd/yaegi/test.go:151 +0x106a
main.main()
/Users/jptosso/go/pkg/mod/github.com/traefik/[email protected]/cmd/yaegi/yaegi.go:135 +0x505
code:
ce.ErrorOutput = log.errorOutput
Should I create a new issue?
I'm seeing a couple of similar issues following the rework on types, under investigation right now. No need for a new issue, thanks.
I have copied the zap source code into my project (messed around with namespaces too) but I eventually got a minimal logging example to work. I had to use go 1.9 so that I could use the native sync/atomic package so that I could drop the uber atomic packaged which uses unsafe.
Quite a lot of the fixes relate to helping yeagi understand the type
Example 1
Broken:
func AddSync(w io.Writer) WriteSyncer {
switch w := w.(type) {
case WriteSyncer:
return w
default:
return writerWrapper{w}
}
}
To:
func AddSync(w io.Writer) WriteSyncer {
switch w := w.(type) {
case WriteSyncer:
return w
default:
var wrapper WriteSyncer
wrapper = writerWrapper{w}
return wrapper
}
}
Example 2 Broken
func (c *ioCore) Write(ent Entry, fields []Field) error {
buf, err := c.enc.EncodeEntry(ent, fields)
if err != nil {
return err
}
_, err = c.out.Write(buf.Bytes())
buf.Free()
if err != nil {
return err
}
if ent.Level > level.ErrorLevel {
// Since we may be crashing the program, sync the output. Ignore Sync
// errors, pending a clean solution to issue #370.
c.Sync()
}
return nil
}
to
func (c *ioCore) Write(ent Entry, fields []Field) error {
buf, err := c.enc.EncodeEntry(ent, fields)
if err != nil {
return err
}
if c.out != nil {
var ioWriter io.Writer
ioWriter = c.out
_, err = ioWriter.Write(buf.Bytes())
}
buf.Free()
if err != nil {
return err
}
if ent.Level > level.ErrorLevel {
// Since we may be crashing the program, sync the output. Ignore Sync
// errors, pending a clean solution to issue #370.
c.Sync()
}
return nil
}
func (c *ioCore) Sync() error {
if c.out == nil {
return nil
}
return c.out.Sync()
}
https://github.com/taliesins/traefik-plugin-oidc/tree/initial/log
#1485 is required for zap to work