如何从 “sigs.k8s.io/controller-runtime” 中模拟 zap logger?

huangapple go评论95阅读模式
英文:

How to mock zap logger from ctrl "sigs.k8s.io/controller-runtime"?

问题

你可以使用zap包中的New函数创建一个新的Logger实例,并将其输出重定向到缓冲区。然后,你可以将这个新的Logger实例传递给testLog,以便将日志输出到缓冲区。

以下是修改后的代码示例:

package logger

import (
	"bytes"
	"github.com/onsi/ginkgo"
	"github.com/onsi/gomega"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/log/zap"
)

var _ = Describe("Logger", func() {
	It("Test Default Log Level", func() {
		buf := &bytes.Buffer{}
		testLog := ctrl.Log.WithName("setup")
		testLog.Info("This is a test")

		Expect(buf.String()).To(Equal("This is a test"))
	})
})

func SetLogger() {
	opts := zap.Options{
		Development:     developmentFlag,
		StacktraceLevel: stacktraceLevel,
		Level:           isLevelEnabler,
		Encoder:         logFmtEncoder,
	}

	buf := &bytes.Buffer{}
	logger := zap.New(zap.UseFlagOptions(&opts), zap.Output(zap.AddSync(buf)))
	ctrl.SetLogger(logger)
}

SetLogger函数中,我们创建了一个新的Logger实例logger,并将其输出重定向到缓冲区buf。然后,我们将这个新的Logger实例传递给ctrl.SetLogger,以便将日志输出到缓冲区。

这样,当你调用testLog.Info时,日志将被写入缓冲区buf中。你可以通过检查buf.String()来获取缓冲区中的日志内容。

英文:
package logger

import (
	"bytes"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	ctrl "sigs.k8s.io/controller-runtime"
)
var _ = Describe("Logger", func() {
	It("Test Default Log Level", func() {
		buf := &bytes.Buffer{}
		testLog := ctrl.Log.WithName("setup")
        SetLogger()
		

		testLog.Info("This is a test")
		Expect(buf.String(),"This is a test")
	})
})

And this is the SetLogger function, which is used also in production:

package logger

import (
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/log/zap"
    ...
)

func SetLogger() {
	opts := zap.Options{
		Development:     developmentFlag,
		StacktraceLevel: stacktraceLevel,
		Level:           isLevelEnabler,
		Encoder:         logFmtEncoder,
	}
  ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
}

How I can change the output of the testLog.Info to buffer?

答案1

得分: 1

如果你只对测试日志消息感兴趣,可以使用一个钩子(hook)。

具体来说,zap.Hooks 函数可以从多个钩子构造一个 zap.Option。钩子只是一个 func(entry zapcore.Entry) error,你可以使用它来拦截日志条目并将其消息写入缓冲区。

要将这个 zap.Option 设置到你的 sigs.k8s.io 日志记录器中,你需要将它设置为 ZapOpts 字段:

opts := k8szap.Options{
    // ...
    ZapOpts: []zap.Option{
        zap.Hooks(func(entry zapcore.Entry) error {
            buf.WriteString(entry.Message)
            return nil
        }),
    },
}

因此,由于你需要访问缓冲区,你可以将它作为参数传递给 SetLogger 函数:

func SetLogger(buf *bytes.Buffer) {
    opts := zap.Options{
        Development:     developmentFlag,
        StacktraceLevel: stacktraceLevel,
        Level:           isLevelEnabler,
        Encoder:         logFmtEncoder,

        // 这里的 'zap' 选择器是 'go.uber.org/zap'
        ZapOpts: []zap.Option{
            zap.Hooks(func(entry zapcore.Entry) error {
                buf.WriteString(entry.Message)
                return nil
            }),
        },
    }
    // 这里我调用 'k8szap' 选择器的包是 'sigs.k8s.io/controller-runtime/pkg/log/zap'
    ctrl.SetLogger(k8szap.New(k8szap.UseFlagOptions(&opts)))
}

然后在你的测试函数中:

It("Test Default Log Level", func() {
    buf := &bytes.Buffer{}
    testLog := ctrl.Log.WithName("setup")

    // 将缓冲区传递给 SetLogger
    SetLogger(buf)

    testLog.Info("This is a test")
    Expect(buf.String(), "This is a test")
})

最简化的示例(在 playground 中下载包可能会超时):https://play.golang.org/p/oBN3SHFKVC8

英文:

If you are only interested in testing the log message, you can use a hook.

In particular zap.Hooks function constructs a zap.Option from a variable number of hooks. A hook is just a func(entry zapcore.Entry) error which you can use to intercept the entry and write its message to the buffer.

To set this zap.Option into your sigs.k8s.io logger, you set it to the ZapOpts field:

	opts := k8szap.Options{
		// ...
		ZapOpts: []zap.Option{
			zap.Hooks(func(entry zapcore.Entry) error {
				buf.WriteString(entry.Message)
				return nil
			}),
		},
	}

So since you need access to the buffer, you can pass it as argument to the SetLogger function:

func SetLogger(buf *bytes.Buffer) {
    opts := zap.Options{
        Development:     developmentFlag,
        StacktraceLevel: stacktraceLevel,
        Level:           isLevelEnabler,
        Encoder:         logFmtEncoder,

        // here 'zap' selector is 'go.uber.org/zap'
        ZapOpts: []zap.Option{
			zap.Hooks(func(entry zapcore.Entry) error {
				buf.WriteString(entry.Message)
				return nil
			}),
		},
    }
    // here I call 'k8szap' selector the package 'sigs.k8s.io/controller-runtime/pkg/log/zap'
    ctrl.SetLogger(k8szap.New(k8szap.UseFlagOptions(&opts)))
}

And then in your test function:

    It("Test Default Log Level", func() {
        buf := &bytes.Buffer{}
        testLog := ctrl.Log.WithName("setup")

        // pass buffer to SetLogger
        SetLogger(buf)
        

        testLog.Info("This is a test")
        Expect(buf.String(), "This is a test")
    })

Minimal example (it may timeout when downloading the packages in the playground): https://play.golang.org/p/oBN3SHFKVC8

huangapple
  • 本文由 发表于 2021年10月28日 20:15:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/69753926.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定