From 25a856bf7bfa7f2de32ecb7b4c8d6997a2835f76 Mon Sep 17 00:00:00 2001 From: Yuhang Wei Date: Sat, 25 Nov 2023 15:18:23 +0800 Subject: [PATCH 1/2] fix(agent, proxy): transform log timestamp to human-readable format Originally, the log of controllers is timestamp which is hard to read. Now, transform the log into more human-readable format. Signed-off-by: Yuhang Wei --- cmd/operator/controllers/os_controller_test.go | 3 +-- cmd/operator/controllers/suite_test.go | 12 +++++++++++- cmd/operator/main.go | 13 +++++++++++++ cmd/proxy/controllers/suite_test.go | 11 ++++++++++- cmd/proxy/main.go | 13 +++++++++++++ go.mod | 3 ++- go.sum | 8 ++++++++ 7 files changed, 58 insertions(+), 5 deletions(-) diff --git a/cmd/operator/controllers/os_controller_test.go b/cmd/operator/controllers/os_controller_test.go index 6cc2760e..8c5d1981 100644 --- a/cmd/operator/controllers/os_controller_test.go +++ b/cmd/operator/controllers/os_controller_test.go @@ -23,7 +23,6 @@ import ( "github.com/google/uuid" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -912,7 +911,7 @@ func Test_getNodes(t *testing.T) { tests := []struct { name string args args - want []corev1.Node + want []v1.Node wantErr bool }{ { diff --git a/cmd/operator/controllers/suite_test.go b/cmd/operator/controllers/suite_test.go index aa6deeae..67fc9e71 100644 --- a/cmd/operator/controllers/suite_test.go +++ b/cmd/operator/controllers/suite_test.go @@ -16,9 +16,13 @@ import ( "context" "path/filepath" "testing" + "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + zaplogfmt "github.com/sykesm/zap-logfmt" + uzap "go.uber.org/zap" + "go.uber.org/zap/zapcore" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" @@ -46,7 +50,13 @@ func TestAPIs(t *testing.T) { } var _ = BeforeSuite(func() { - logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + configLog := uzap.NewProductionEncoderConfig() + configLog.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString(ts.UTC().Format(time.RFC3339Nano)) + } + logfmtEncoder := zaplogfmt.NewEncoder(configLog) + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true), zap.Encoder(logfmtEncoder))) + ctx, cancel = context.WithCancel(context.TODO()) By("bootstrapping test environment") diff --git a/cmd/operator/main.go b/cmd/operator/main.go index 8249ad2d..6b90b26b 100644 --- a/cmd/operator/main.go +++ b/cmd/operator/main.go @@ -14,12 +14,17 @@ package main import ( "os" + "time" + zaplogfmt "github.com/sykesm/zap-logfmt" + uzap "go.uber.org/zap" + "go.uber.org/zap/zapcore" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/log/zap" upgradev1 "openeuler.org/KubeOS/api/v1alpha1" "openeuler.org/KubeOS/cmd/operator/controllers" @@ -41,6 +46,14 @@ func init() { } func main() { + configLog := uzap.NewProductionEncoderConfig() + configLog.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString(ts.UTC().Format(time.RFC3339Nano)) + } + logfmtEncoder := zaplogfmt.NewEncoder(configLog) + logger := zap.New(zap.UseDevMode(true), zap.WriteTo(os.Stdout), zap.Encoder(logfmtEncoder)) + ctrl.SetLogger(logger) + mgr, err := common.NewControllerManager(setupLog, scheme) if err != nil { setupLog.Error(err, "unable to start manager") diff --git a/cmd/proxy/controllers/suite_test.go b/cmd/proxy/controllers/suite_test.go index 00eebbf4..767fe955 100644 --- a/cmd/proxy/controllers/suite_test.go +++ b/cmd/proxy/controllers/suite_test.go @@ -16,9 +16,13 @@ import ( "context" "path/filepath" "testing" + "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + zaplogfmt "github.com/sykesm/zap-logfmt" + uzap "go.uber.org/zap" + "go.uber.org/zap/zapcore" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" @@ -48,7 +52,12 @@ func TestAPIs(t *testing.T) { } var _ = BeforeSuite(func() { - logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + configLog := uzap.NewProductionEncoderConfig() + configLog.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString(ts.UTC().Format(time.RFC3339Nano)) + } + logfmtEncoder := zaplogfmt.NewEncoder(configLog) + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true), zap.Encoder(logfmtEncoder))) ctx, cancel = context.WithCancel(context.TODO()) By("bootstrapping test environment") diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index 3a537d90..e606083a 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -15,12 +15,17 @@ package main import ( "os" "path/filepath" + "time" + zaplogfmt "github.com/sykesm/zap-logfmt" + uzap "go.uber.org/zap" + "go.uber.org/zap/zapcore" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/log/zap" upgradev1 "openeuler.org/KubeOS/api/v1alpha1" "openeuler.org/KubeOS/cmd/agent/server" @@ -44,6 +49,14 @@ func init() { } func main() { + configLog := uzap.NewProductionEncoderConfig() + configLog.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString(ts.UTC().Format(time.RFC3339Nano)) + } + logfmtEncoder := zaplogfmt.NewEncoder(configLog) + logger := zap.New(zap.UseDevMode(true), zap.WriteTo(os.Stdout), zap.Encoder(logfmtEncoder)) + ctrl.SetLogger(logger) + var err error mgr, err := common.NewControllerManager(setupLog, scheme) if err != nil { diff --git a/go.mod b/go.mod index 057292c8..72ca9782 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,8 @@ require ( github.com/onsi/ginkgo/v2 v2.1.4 github.com/onsi/gomega v1.20.0 github.com/sirupsen/logrus v1.8.1 + github.com/sykesm/zap-logfmt v0.0.4 + go.uber.org/zap v1.19.1 google.golang.org/grpc v1.49.0 google.golang.org/protobuf v1.28.1 k8s.io/api v0.24.0 @@ -82,7 +84,6 @@ require ( go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.19.1 // indirect golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect diff --git a/go.sum b/go.sum index 6bd1ba1b..325cd88a 100644 --- a/go.sum +++ b/go.sum @@ -516,6 +516,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/sykesm/zap-logfmt v0.0.4 h1:U2WzRvmIWG1wDLCFY3sz8UeEmsdHQjHFNlIdmroVFaI= +github.com/sykesm/zap-logfmt v0.0.4/go.mod h1:AuBd9xQjAe3URrWT1BBDk2v2onAZHkZkWRMiYZXiZWA= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -559,15 +561,19 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= @@ -812,6 +818,8 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -- Gitee From e1b4b7a7008855920f866d0fa4c16d09f9341baf Mon Sep 17 00:00:00 2001 From: Yuhang Wei Date: Sat, 25 Nov 2023 15:18:36 +0800 Subject: [PATCH 2/2] build: update vendor use zapfmt to transform timestamp to human-readable format Signed-off-by: Yuhang Wei --- .../github.com/sykesm/zap-logfmt/.gitignore | 1 + .../github.com/sykesm/zap-logfmt/.travis.yml | 12 + vendor/github.com/sykesm/zap-logfmt/LICENSE | 21 + vendor/github.com/sykesm/zap-logfmt/README.md | 76 +++ .../github.com/sykesm/zap-logfmt/encoder.go | 527 ++++++++++++++++++ vendor/modules.txt | 3 + 6 files changed, 640 insertions(+) create mode 100644 vendor/github.com/sykesm/zap-logfmt/.gitignore create mode 100644 vendor/github.com/sykesm/zap-logfmt/.travis.yml create mode 100644 vendor/github.com/sykesm/zap-logfmt/LICENSE create mode 100644 vendor/github.com/sykesm/zap-logfmt/README.md create mode 100644 vendor/github.com/sykesm/zap-logfmt/encoder.go diff --git a/vendor/github.com/sykesm/zap-logfmt/.gitignore b/vendor/github.com/sykesm/zap-logfmt/.gitignore new file mode 100644 index 00000000..7a6353d6 --- /dev/null +++ b/vendor/github.com/sykesm/zap-logfmt/.gitignore @@ -0,0 +1 @@ +.envrc diff --git a/vendor/github.com/sykesm/zap-logfmt/.travis.yml b/vendor/github.com/sykesm/zap-logfmt/.travis.yml new file mode 100644 index 00000000..7ce1f7ab --- /dev/null +++ b/vendor/github.com/sykesm/zap-logfmt/.travis.yml @@ -0,0 +1,12 @@ +language: go + +matrix: + include: + - go: "1.13.x" + install: true + - go: "1.14.x" + install: true + - go: "1.15.x" + install: true + +script: go test -race ./... diff --git a/vendor/github.com/sykesm/zap-logfmt/LICENSE b/vendor/github.com/sykesm/zap-logfmt/LICENSE new file mode 100644 index 00000000..43a1c326 --- /dev/null +++ b/vendor/github.com/sykesm/zap-logfmt/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Jonathan Sternberg +Copyright (c) 2019 Matthew Sykes + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/sykesm/zap-logfmt/README.md b/vendor/github.com/sykesm/zap-logfmt/README.md new file mode 100644 index 00000000..751f2880 --- /dev/null +++ b/vendor/github.com/sykesm/zap-logfmt/README.md @@ -0,0 +1,76 @@ +# Logfmt Encoder + +This package provides a logfmt encoder for [zap][zap]. + +It is a fork of [github.com/jsternberg/zap-logfmt][jsternberg] that improves +the handling of reflected fields and encodes arrays and objects instead of +dropping them from logs. While logging simple fields is preferred for many +reasons, having ugly data is often better than missing data. + +[![Build Status](https://travis-ci.org/sykesm/zap-logfmt.svg?branch=master)](https://travis-ci.org/sykesm/zap-logfmt) +[![GoDoc](https://godoc.org/github.com/sykesm/zap-logfmt?status.svg)](https://godoc.org/github.com/sykesm/zap-logfmt) + +## Usage + +The encoder is easy to configure. Simply create a new core with an instance of +the logfmt encoder and use it with your preferred logging interface. + +```go +package main + +import ( + "os" + + "github.com/sykesm/zap-logfmt" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +func main() { + config := zap.NewProductionEncoderConfig() + logger := zap.New(zapcore.NewCore( + zaplogfmt.NewEncoder(config), + os.Stdout, + zapcore.DebugLevel, + )) + logger.Info("Hello World") +} +``` + +## Arrays, Objects, and Reflected Fields + +While it's best to avoid complex data types in log fields, there are times +when they sneak in. When complex fields are included in log records, they will +be encoded, but they won't be very pretty. + +### Arrays + +Arrays are encoded as a comma separated list of values within square brackets. +This format is very similar to JSON encoding. Arrays of simple scalars remain +quite readable but including elements that require quoting will result in very +ugly records. + +### Objects + +Objects are encoded as a space separated list of _key=value_ pairs. Because +this format includes an equals sign, the encoded object will require quoting. +If any value in the object requires quoting, the required escapes will make +the encoded field pretty difficult for humans to read. + +### Channels and Functions + +Channels and functions are encoded as their type and their address. There +aren't many meaningful ways to log channels and functions... + +### Maps and Structs + +Maps and structs are encoded as strings that contain the result of `fmt.Sprint`. + +## Namespaces + +Namespaces are supported. If a namespace is opened, all of the keys will +be prepended with the namespace name. For example, with the namespace +`foo` and the key `bar`, you would get a key of `foo.bar`. + +[zap]: https://github.com/uber-go/zap +[jsternberg]: https://github.com/jsternberg/zap-logfmt diff --git a/vendor/github.com/sykesm/zap-logfmt/encoder.go b/vendor/github.com/sykesm/zap-logfmt/encoder.go new file mode 100644 index 00000000..9e960cc5 --- /dev/null +++ b/vendor/github.com/sykesm/zap-logfmt/encoder.go @@ -0,0 +1,527 @@ +// Package zaplogfmt provides a zap encoder that formats log entries in +// "logfmt" format. +package zaplogfmt + +import ( + "bytes" + "encoding" + "encoding/base64" + "encoding/json" + "fmt" + "math" + "reflect" + "strings" + "sync" + "time" + "unicode/utf8" + + "go.uber.org/zap/buffer" + "go.uber.org/zap/zapcore" +) + +var ( + logfmtPool = sync.Pool{ + New: func() interface{} { return &logfmtEncoder{} }, + } + bufferpool = buffer.NewPool() +) + +func getEncoder() *logfmtEncoder { + return logfmtPool.Get().(*logfmtEncoder) +} + +func putEncoder(enc *logfmtEncoder) { + enc.EncoderConfig = nil + enc.buf = nil + enc.namespaces = nil + enc.arrayLiteral = false + logfmtPool.Put(enc) +} + +type logfmtEncoder struct { + *zapcore.EncoderConfig + buf *buffer.Buffer + namespaces []string + arrayLiteral bool +} + +// NewEncoder creates an encoder writes logfmt formatted log entries. +func NewEncoder(cfg zapcore.EncoderConfig) zapcore.Encoder { + return &logfmtEncoder{ + EncoderConfig: &cfg, + buf: bufferpool.Get(), + } +} + +func (enc *logfmtEncoder) AddArray(key string, arr zapcore.ArrayMarshaler) error { + enc.addKey(key) + return enc.AppendArray(arr) +} + +func (enc *logfmtEncoder) AddBinary(key string, value []byte) { + enc.AddString(key, base64.StdEncoding.EncodeToString(value)) +} + +func (enc *logfmtEncoder) AddBool(key string, value bool) { + enc.addKey(key) + enc.AppendBool(value) +} + +func (enc *logfmtEncoder) AddByteString(key string, value []byte) { + enc.addKey(key) + enc.AppendByteString(value) +} + +func (enc *logfmtEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) } +func (enc *logfmtEncoder) AddComplex128(key string, value complex128) { + enc.addKey(key) + enc.AppendComplex128(value) +} + +func (enc *logfmtEncoder) AddDuration(key string, value time.Duration) { + enc.addKey(key) + enc.AppendDuration(value) +} + +func (enc *logfmtEncoder) AddFloat32(key string, value float32) { + enc.addKey(key) + enc.AppendFloat32(value) +} + +func (enc *logfmtEncoder) AddFloat64(key string, value float64) { + enc.addKey(key) + enc.AppendFloat64(value) +} + +func (enc *logfmtEncoder) AddInt(k string, v int) { enc.AddInt64(k, int64(v)) } +func (enc *logfmtEncoder) AddInt8(k string, v int8) { enc.AddInt64(k, int64(v)) } +func (enc *logfmtEncoder) AddInt32(k string, v int32) { enc.AddInt64(k, int64(v)) } +func (enc *logfmtEncoder) AddInt16(k string, v int16) { enc.AddInt64(k, int64(v)) } +func (enc *logfmtEncoder) AddInt64(key string, value int64) { + enc.addKey(key) + enc.AppendInt64(value) +} + +func (enc *logfmtEncoder) AddObject(key string, obj zapcore.ObjectMarshaler) error { + enc.addKey(key) + return enc.AppendObject(obj) +} + +func (enc *logfmtEncoder) AddReflected(key string, value interface{}) error { + enc.addKey(key) + return enc.AppendReflected(value) +} + +func (enc *logfmtEncoder) AddString(key, value string) { + enc.addKey(key) + enc.AppendString(value) +} + +func (enc *logfmtEncoder) AddTime(key string, value time.Time) { + enc.addKey(key) + enc.AppendTime(value) +} + +func (enc *logfmtEncoder) AddUint(k string, v uint) { enc.AddUint64(k, uint64(v)) } +func (enc *logfmtEncoder) AddUint8(k string, v uint8) { enc.AddUint64(k, uint64(v)) } +func (enc *logfmtEncoder) AddUint32(k string, v uint32) { enc.AddUint64(k, uint64(v)) } +func (enc *logfmtEncoder) AddUint16(k string, v uint16) { enc.AddUint64(k, uint64(v)) } +func (enc *logfmtEncoder) AddUintptr(k string, v uintptr) { enc.AddUint64(k, uint64(v)) } +func (enc *logfmtEncoder) AddUint64(key string, value uint64) { + enc.addKey(key) + enc.AppendUint64(value) +} + +func (enc *logfmtEncoder) AppendArray(arr zapcore.ArrayMarshaler) error { + marshaler := enc.clone() + marshaler.namespaces = nil + marshaler.arrayLiteral = true + + marshaler.buf.AppendByte('[') + err := arr.MarshalLogArray(marshaler) + if err == nil { + marshaler.buf.AppendByte(']') + enc.AppendByteString(marshaler.buf.Bytes()) + } else { + enc.AppendByteString(nil) + } + marshaler.buf.Free() + putEncoder(marshaler) + return err +} + +func (enc *logfmtEncoder) AppendBool(value bool) { + if value { + enc.AppendString("true") + } else { + enc.AppendString("false") + } +} + +func (enc *logfmtEncoder) AppendByteString(value []byte) { + enc.addSeparator() + + needsQuotes := bytes.IndexFunc(value, needsQuotedValueRune) != -1 + if needsQuotes { + enc.buf.AppendByte('"') + } + enc.safeAddByteString(value) + if needsQuotes { + enc.buf.AppendByte('"') + } +} + +func (enc *logfmtEncoder) AppendComplex64(v complex64) { enc.AppendComplex128(complex128(v)) } +func (enc *logfmtEncoder) AppendComplex128(value complex128) { + enc.addSeparator() + + // Cast to a platform-independent, fixed-size type. + r, i := float64(real(value)), float64(imag(value)) + enc.buf.AppendFloat(r, 64) + enc.buf.AppendByte('+') + enc.buf.AppendFloat(i, 64) + enc.buf.AppendByte('i') +} + +func (enc *logfmtEncoder) AppendDuration(value time.Duration) { + cur := enc.buf.Len() + if enc.EncodeDuration != nil { + enc.EncodeDuration(value, enc) + } + if cur == enc.buf.Len() { + enc.AppendInt64(int64(value)) + } +} + +func (enc *logfmtEncoder) AppendFloat32(v float32) { enc.appendFloat(float64(v), 32) } +func (enc *logfmtEncoder) AppendFloat64(v float64) { enc.appendFloat(v, 64) } +func (enc *logfmtEncoder) appendFloat(val float64, bitSize int) { + enc.addSeparator() + + switch { + case math.IsNaN(val): + enc.buf.AppendString(`NaN`) + case math.IsInf(val, 1): + enc.buf.AppendString(`+Inf`) + case math.IsInf(val, -1): + enc.buf.AppendString(`-Inf`) + default: + enc.buf.AppendFloat(val, bitSize) + } +} + +func (enc *logfmtEncoder) AppendInt(v int) { enc.AppendInt64(int64(v)) } +func (enc *logfmtEncoder) AppendInt8(v int8) { enc.AppendInt64(int64(v)) } +func (enc *logfmtEncoder) AppendInt16(v int16) { enc.AppendInt64(int64(v)) } +func (enc *logfmtEncoder) AppendInt32(v int32) { enc.AppendInt64(int64(v)) } +func (enc *logfmtEncoder) AppendInt64(value int64) { + enc.addSeparator() + enc.buf.AppendInt(value) +} + +func (enc *logfmtEncoder) AppendObject(obj zapcore.ObjectMarshaler) error { + marshaler := enc.clone() + marshaler.namespaces = nil + + err := obj.MarshalLogObject(marshaler) + if err == nil { + enc.AppendByteString(marshaler.buf.Bytes()) + } else { + enc.AppendByteString(nil) + } + marshaler.buf.Free() + putEncoder(marshaler) + return err +} + +func (enc *logfmtEncoder) AppendReflected(value interface{}) error { + switch v := value.(type) { + case nil: + enc.AppendString("null") + case error: + enc.AppendString(v.Error()) + case []byte: + enc.AppendByteString(v) + case fmt.Stringer: + enc.AppendString(v.String()) + case encoding.TextMarshaler: + b, err := v.MarshalText() + if err != nil { + return err + } + enc.AppendString(string(b)) + case json.Marshaler: + b, err := v.MarshalJSON() + if err != nil { + return err + } + enc.AppendString(string(b)) + default: + rvalue := reflect.ValueOf(value) + switch rvalue.Kind() { + case reflect.Bool: + enc.AppendBool(rvalue.Bool()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + enc.AppendInt64(rvalue.Int()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + enc.AppendUint64(rvalue.Uint()) + case reflect.Float32: + enc.appendFloat(rvalue.Float(), 32) + case reflect.Float64: + enc.AppendFloat64(rvalue.Float()) + case reflect.String: + enc.AppendString(rvalue.String()) + case reflect.Complex64, reflect.Complex128: + enc.AppendComplex128(rvalue.Complex()) + case reflect.Chan, reflect.Func: + enc.AppendString(fmt.Sprintf("%T(%p)", value, value)) + case reflect.Map, reflect.Struct: + enc.AppendString(fmt.Sprint(value)) + case reflect.Array, reflect.Slice: + enc.AppendArray(zapcore.ArrayMarshalerFunc(func(ae zapcore.ArrayEncoder) error { + for i := 0; i < rvalue.Len(); i++ { + ae.AppendReflected(rvalue.Index(i).Interface()) + } + return nil + })) + case reflect.Interface, reflect.Ptr: + return enc.AppendReflected(rvalue.Elem().Interface()) + } + } + return nil +} + +func (enc *logfmtEncoder) AppendString(value string) { + enc.addSeparator() + + needsQuotes := strings.IndexFunc(value, needsQuotedValueRune) != -1 + if needsQuotes { + enc.buf.AppendByte('"') + } + enc.safeAddString(value) + if needsQuotes { + enc.buf.AppendByte('"') + } +} + +func (enc *logfmtEncoder) AppendTime(value time.Time) { + cur := enc.buf.Len() + if enc.EncodeTime != nil { + enc.EncodeTime(value, enc) + } + if cur == enc.buf.Len() { + enc.AppendInt64(value.UnixNano()) + } +} + +func (enc *logfmtEncoder) AppendUint(v uint) { enc.AppendUint64(uint64(v)) } +func (enc *logfmtEncoder) AppendUint8(v uint8) { enc.AppendUint64(uint64(v)) } +func (enc *logfmtEncoder) AppendUint16(v uint16) { enc.AppendUint64(uint64(v)) } +func (enc *logfmtEncoder) AppendUint32(v uint32) { enc.AppendUint64(uint64(v)) } +func (enc *logfmtEncoder) AppendUintptr(v uintptr) { enc.AppendUint64(uint64(v)) } +func (enc *logfmtEncoder) AppendUint64(value uint64) { + enc.addSeparator() + enc.buf.AppendUint(value) +} + +func (enc *logfmtEncoder) Clone() zapcore.Encoder { + clone := enc.clone() + clone.buf.Write(enc.buf.Bytes()) + return clone +} + +func (enc *logfmtEncoder) clone() *logfmtEncoder { + clone := getEncoder() + clone.EncoderConfig = enc.EncoderConfig + clone.buf = bufferpool.Get() + clone.namespaces = enc.namespaces + return clone +} + +func (enc *logfmtEncoder) OpenNamespace(key string) { + key = strings.Map(keyRuneFilter, key) + enc.namespaces = append(enc.namespaces, key) +} + +func (enc *logfmtEncoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) { + final := enc.clone() + if final.TimeKey != "" { + final.AddTime(final.TimeKey, ent.Time) + } + if final.LevelKey != "" { + final.addKey(final.LevelKey) + cur := final.buf.Len() + if final.EncodeLevel != nil { + final.EncodeLevel(ent.Level, final) + } + if cur == final.buf.Len() { + // User-supplied EncodeLevel was a no-op. Fall back to strings to keep + // output valid. + final.AppendString(ent.Level.String()) + } + } + if ent.LoggerName != "" && final.NameKey != "" { + final.addKey(final.NameKey) + cur := final.buf.Len() + if final.EncodeName != nil { + final.EncodeName(ent.LoggerName, final) + } + if cur == final.buf.Len() { + // User-supplied EncodeName was a no-op. Fall back to strings to + // keep output valid. + final.AppendString(ent.LoggerName) + } + } + if ent.Caller.Defined && final.CallerKey != "" { + final.addKey(final.CallerKey) + cur := final.buf.Len() + if final.EncodeCaller != nil { + final.EncodeCaller(ent.Caller, final) + } + if cur == final.buf.Len() { + // User-supplied EncodeCaller was a no-op. Fall back to strings to + // keep output valid. + final.AppendString(ent.Caller.String()) + } + } + if final.MessageKey != "" { + final.addKey(enc.MessageKey) + final.AppendString(ent.Message) + } + if enc.buf.Len() > 0 { + if final.buf.Len() > 0 { + final.buf.AppendByte(' ') + } + final.buf.Write(enc.buf.Bytes()) + } + addFields(final, fields) + if ent.Stack != "" && final.StacktraceKey != "" { + final.AddString(final.StacktraceKey, ent.Stack) + } + if final.LineEnding != "" { + final.buf.AppendString(final.LineEnding) + } else { + final.buf.AppendString(zapcore.DefaultLineEnding) + } + + ret := final.buf + putEncoder(final) + return ret, nil +} + +func (enc *logfmtEncoder) addSeparator() { + if !enc.arrayLiteral { + return + } + + last := enc.buf.Len() - 1 + if last >= 0 && enc.buf.Bytes()[last] != '[' { + enc.buf.AppendByte(',') + } +} + +func (enc *logfmtEncoder) addKey(key string) { + key = strings.Map(keyRuneFilter, key) + if enc.buf.Len() > 0 { + enc.buf.AppendByte(' ') + } + for _, ns := range enc.namespaces { + enc.safeAddString(ns) + enc.buf.AppendByte('.') + } + enc.safeAddString(key) + enc.buf.AppendByte('=') +} + +// safeAddString JSON-escapes a string and appends it to the internal buffer. +// Unlike the standard library's encoder, it doesn't attempt to protect the +// user from browser vulnerabilities or JSONP-related problems. +func (enc *logfmtEncoder) safeAddString(s string) { + for i := 0; i < len(s); { + if enc.tryAddRuneSelf(s[i]) { + i++ + continue + } + r, size := utf8.DecodeRuneInString(s[i:]) + if enc.tryAddRuneError(r, size) { + i++ + continue + } + enc.buf.AppendString(s[i : i+size]) + i += size + } +} + +// safeAddByteString is no-alloc equivalent of safeAddString(string(s)) for s []byte. +func (enc *logfmtEncoder) safeAddByteString(s []byte) { + for i := 0; i < len(s); { + if enc.tryAddRuneSelf(s[i]) { + i++ + continue + } + r, size := utf8.DecodeRune(s[i:]) + if enc.tryAddRuneError(r, size) { + i++ + continue + } + enc.buf.Write(s[i : i+size]) + i += size + } +} + +// tryAddRuneSelf appends b if it is valid UTF-8 character represented in a single byte. +func (enc *logfmtEncoder) tryAddRuneSelf(b byte) bool { + if b >= utf8.RuneSelf { + return false + } + if 0x20 <= b && b != '\\' && b != '"' { + enc.buf.AppendByte(b) + return true + } + switch b { + case '\\', '"': + enc.buf.AppendByte('\\') + enc.buf.AppendByte(b) + case '\n': + enc.buf.AppendByte('\\') + enc.buf.AppendByte('n') + case '\r': + enc.buf.AppendByte('\\') + enc.buf.AppendByte('r') + case '\t': + enc.buf.AppendByte('\\') + enc.buf.AppendByte('t') + default: + // Encode bytes < 0x20, except for the escape sequences above. + const _hex = "0123456789abcdef" + enc.buf.AppendString(`\u00`) + enc.buf.AppendByte(_hex[b>>4]) + enc.buf.AppendByte(_hex[b&0xF]) + } + return true +} + +func (enc *logfmtEncoder) tryAddRuneError(r rune, size int) bool { + if r == utf8.RuneError && size == 1 { + enc.buf.AppendString(`\ufffd`) + return true + } + return false +} + +func needsQuotedValueRune(r rune) bool { + return r <= ' ' || r == '=' || r == '"' || r == utf8.RuneError +} + +func keyRuneFilter(r rune) rune { + if needsQuotedValueRune(r) { + return -1 + } + return r +} + +func addFields(enc zapcore.ObjectEncoder, fields []zapcore.Field) { + for i := range fields { + fields[i].AddTo(enc) + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index c6048c91..67935ef8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -245,6 +245,9 @@ github.com/spf13/pflag ## explicit; go 1.13 github.com/stretchr/testify/assert github.com/stretchr/testify/require +# github.com/sykesm/zap-logfmt v0.0.4 +## explicit; go 1.13 +github.com/sykesm/zap-logfmt # github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca ## explicit github.com/xlab/treeprint -- Gitee