yaegi icon indicating copy to clipboard operation
yaegi copied to clipboard

import "go.uber.org/zap" fails

Open mpl opened this issue 4 years ago • 9 comments

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

mpl avatar Jul 06 '21 15:07 mpl

@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.

mpl avatar Jul 06 '21 16:07 mpl

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

darkweak avatar Jul 06 '21 16:07 darkweak

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 avatar Jul 07 '21 11:07 ldez

@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.

darkweak avatar Jul 07 '21 12:07 darkweak

you can follow #1173 and #1174

ldez avatar Jul 07 '21 12:07 ldez

@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.

mpl avatar Jul 08 '21 14:07 mpl

Thank you, and many thanks to @mvertes for his incredible work 🚀

darkweak avatar Jul 08 '21 14:07 darkweak

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?

jptosso avatar Sep 06 '21 21:09 jptosso

I'm seeing a couple of similar issues following the rework on types, under investigation right now. No need for a new issue, thanks.

mvertes avatar Sep 06 '21 22:09 mvertes

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

taliesins avatar Oct 26 '22 09:10 taliesins

#1485 is required for zap to work

taliesins avatar Oct 31 '22 23:10 taliesins