From 58158f373914b6b0877014b21d9cc4f391d31fca Mon Sep 17 00:00:00 2001 From: Nicolas Lopez Date: Tue, 10 Nov 2020 15:23:58 -0500 Subject: [PATCH] update prior to release 0.19 branch (#1903) --- go.mod | 8 +- go.sum | 15 +- .../eventing/test/e2e-conformance-tests.sh | 4 +- vendor/knative.dev/eventing/test/e2e-tests.sh | 4 +- vendor/knative.dev/hack/library.sh | 2 +- vendor/knative.dev/pkg/logging/config.go | 5 +- vendor/knative.dev/pkg/metrics/config.go | 18 - .../pkg/metrics/config_observability.go | 7 - vendor/knative.dev/pkg/metrics/exporter.go | 7 +- .../pkg/metrics/prometheus_exporter.go | 9 +- .../pkg/test/logging/.gitattributes | 1 + vendor/knative.dev/pkg/test/logging/doc.go | 49 +++ vendor/knative.dev/pkg/test/logging/error.go | 90 +++++ vendor/knative.dev/pkg/test/logging/logger.go | 76 ++++ .../pkg/test/logging/memory_encoder.go | 74 ++++ .../pkg/test/logging/spew_encoder.go | 196 +++++++++ vendor/knative.dev/pkg/test/logging/sugar.go | 114 ++++++ .../knative.dev/pkg/test/logging/tlogger.go | 372 ++++++++++++++++++ vendor/knative.dev/pkg/test/logging/zapr.go | 47 +++ .../pkg/apis/serving/v1/revision_lifecycle.go | 8 +- vendor/modules.txt | 8 +- 21 files changed, 1051 insertions(+), 63 deletions(-) create mode 100644 vendor/knative.dev/pkg/test/logging/.gitattributes create mode 100644 vendor/knative.dev/pkg/test/logging/doc.go create mode 100644 vendor/knative.dev/pkg/test/logging/error.go create mode 100644 vendor/knative.dev/pkg/test/logging/logger.go create mode 100644 vendor/knative.dev/pkg/test/logging/memory_encoder.go create mode 100644 vendor/knative.dev/pkg/test/logging/spew_encoder.go create mode 100644 vendor/knative.dev/pkg/test/logging/sugar.go create mode 100644 vendor/knative.dev/pkg/test/logging/tlogger.go create mode 100644 vendor/knative.dev/pkg/test/logging/zapr.go diff --git a/go.mod b/go.mod index 59f732ce7a..46b19acd3b 100644 --- a/go.mod +++ b/go.mod @@ -30,10 +30,10 @@ require ( k8s.io/api v0.18.8 k8s.io/apimachinery v0.18.8 k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible - knative.dev/eventing v0.18.1-0.20201109063108-dccb17e10b6b - knative.dev/hack v0.0.0-20201106190108-88f9ae4e6734 - knative.dev/pkg v0.0.0-20201106192907-f98befda69eb - knative.dev/serving v0.18.1-0.20201109120108-68c2e63e32ee + knative.dev/eventing v0.18.1-0.20201110185558-0f9a8c55c7b6 + knative.dev/hack v0.0.0-20201103151104-3d5abc3a0075 + knative.dev/pkg v0.0.0-20201103163404-5514ab0c1fdf + knative.dev/serving v0.18.1-0.20201110011758-db4879e0f615 sigs.k8s.io/yaml v1.2.0 ) diff --git a/go.sum b/go.sum index c98982ac82..c40699e686 100644 --- a/go.sum +++ b/go.sum @@ -523,6 +523,7 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= @@ -726,6 +727,7 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -744,6 +746,7 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -1316,22 +1319,18 @@ k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl k8s.io/utils v0.0.0-20200603063816-c1c6865ac451 h1:v8ud2Up6QK1lNOKFgiIVrZdMg7MpmSnvtrOieolJKoE= k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= knative.dev/caching v0.0.0-20201104174804-1a305923cfbe/go.mod h1:twy5Yz5LtFbmihtbBG0CcgwJzV5d8RUBoGkZFs7uRQs= -knative.dev/eventing v0.18.1-0.20201109063108-dccb17e10b6b h1:X0cLLfDZeDPLChjG2YWzWWX9YlyK44UQS96cPvvk5js= -knative.dev/eventing v0.18.1-0.20201109063108-dccb17e10b6b/go.mod h1:jwhDgDvoscWE4jWF8cXh7yHfxJcK0mTawVKVfrSjnvg= +knative.dev/eventing v0.18.1-0.20201110185558-0f9a8c55c7b6 h1:OyHSzOB5vOFRiFhL0SJmy7EtJ/LHLTlqC+ctWJvqu84= +knative.dev/eventing v0.18.1-0.20201110185558-0f9a8c55c7b6/go.mod h1:jwhDgDvoscWE4jWF8cXh7yHfxJcK0mTawVKVfrSjnvg= knative.dev/hack v0.0.0-20201102193445-9349aeeb6701/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= knative.dev/hack v0.0.0-20201103151104-3d5abc3a0075 h1:YAgWplKIy4O5e3F5vUUECmXAAyZ0M5ymo6fCt1jeZhs= knative.dev/hack v0.0.0-20201103151104-3d5abc3a0075/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= -knative.dev/hack v0.0.0-20201106190108-88f9ae4e6734 h1:AF3ZnSNQrSF6NNjJxD1EvBCr/0/WnSJt6HjCstextBU= -knative.dev/hack v0.0.0-20201106190108-88f9ae4e6734/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= knative.dev/networking v0.0.0-20201103163404-b9f80f4537af h1:xPS3bRfp30XHb69B0F9Pgv4Nc2eTfJHWR0TzVRHf1hU= knative.dev/networking v0.0.0-20201103163404-b9f80f4537af/go.mod h1:0OaR4FLbs3Xn6UjeX1zYql9RWO8sLTO/ZMJS4jDbfFE= knative.dev/pkg v0.0.0-20201103150904-7f1970af5b6f/go.mod h1:2hMxAUviPH2nl3BuODx5L6shYCdzA+7SPzQpdkcg9wc= knative.dev/pkg v0.0.0-20201103163404-5514ab0c1fdf h1:QwULgRwcv6R3Ya1GZlf/E1atcaGUNw4DKjxSQUfcR6U= knative.dev/pkg v0.0.0-20201103163404-5514ab0c1fdf/go.mod h1:cuKOgUvJvnWHIps/apCXX8wZuMlT0dyMZLqRQfsENbQ= -knative.dev/pkg v0.0.0-20201106192907-f98befda69eb h1:wdathwJYpgxe5E35+2245E7oFDfeypAsmJsIzWBPhE0= -knative.dev/pkg v0.0.0-20201106192907-f98befda69eb/go.mod h1:5vNHKNtZtzlNeNrcDoUtZIn+dma/8DjmpjfdHiwoQyM= -knative.dev/serving v0.18.1-0.20201109120108-68c2e63e32ee h1:LKuaz3yq666KfuuoQBMcFGrKoNyZojcmjRKMkfm2y/w= -knative.dev/serving v0.18.1-0.20201109120108-68c2e63e32ee/go.mod h1:G5FVEbwcHKLvf8XTr6XEVqLd3tn31JX8vGFEI8kdYlk= +knative.dev/serving v0.18.1-0.20201110011758-db4879e0f615 h1:HSJGCLfPOgXLa6gsmmDSqWY6/lg9rYaTkyc+IsJVsPQ= +knative.dev/serving v0.18.1-0.20201110011758-db4879e0f615/go.mod h1:G5FVEbwcHKLvf8XTr6XEVqLd3tn31JX8vGFEI8kdYlk= pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= diff --git a/vendor/knative.dev/eventing/test/e2e-conformance-tests.sh b/vendor/knative.dev/eventing/test/e2e-conformance-tests.sh index 13bba73ceb..a6d1da4611 100644 --- a/vendor/knative.dev/eventing/test/e2e-conformance-tests.sh +++ b/vendor/knative.dev/eventing/test/e2e-conformance-tests.sh @@ -32,7 +32,7 @@ source "$(dirname "$0")/e2e-common.sh" initialize $@ --skip-istio-addon -echo "Running tests with Multi Tenant Channel Based Broker" -go_test_e2e -timeout=30m -parallel=12 ./test/conformance -brokers=eventing.knative.dev/v1beta1:MTChannelBasedBroker -channels=messaging.knative.dev/v1beta1:Channel,messaging.knative.dev/v1beta1:InMemoryChannel,messaging.knative.dev/v1:Channel,messaging.knative.dev/v1:InMemoryChannel -sources=sources.knative.dev/v1beta1:ApiServerSource,sources.knative.dev/v1alpha2:ContainerSource,sources.knative.dev/v1beta1:PingSource || fail_test +echo "Running Conformance tests for: Multi Tenant Channel Based Broker (v1beta1), Channel (v1beta1, v1), InMemoryChannel (v1beta1, v1) , ApiServerSource (v1beta1, v1), ContainerSource (v1alpha2, v1) and PingSource (v1beta1)" +go_test_e2e -timeout=30m -parallel=12 ./test/conformance -brokers=eventing.knative.dev/v1beta1:MTChannelBasedBroker -channels=messaging.knative.dev/v1beta1:Channel,messaging.knative.dev/v1beta1:InMemoryChannel,messaging.knative.dev/v1:Channel,messaging.knative.dev/v1:InMemoryChannel -sources=sources.knative.dev/v1beta1:ApiServerSource,sources.knative.dev/v1alpha2:ContainerSource,sources.knative.dev/v1beta1:PingSource,sources.knative.dev/v1:ApiServerSource,sources.knative.dev/v1:ContainerSource || fail_test success diff --git a/vendor/knative.dev/eventing/test/e2e-tests.sh b/vendor/knative.dev/eventing/test/e2e-tests.sh index 32e2fb88cb..7693467088 100644 --- a/vendor/knative.dev/eventing/test/e2e-tests.sh +++ b/vendor/knative.dev/eventing/test/e2e-tests.sh @@ -32,7 +32,7 @@ source "$(dirname "$0")/e2e-common.sh" initialize $@ --skip-istio-addon -echo "Running tests with Multi Tenant Channel Based Broker" -go_test_e2e -timeout=30m -parallel=12 ./test/e2e -brokerclass=MTChannelBasedBroker -channels=messaging.knative.dev/v1beta1:Channel,messaging.knative.dev/v1beta1:InMemoryChannel,messaging.knative.dev/v1:Channel,messaging.knative.dev/v1:InMemoryChannel -sources=sources.knative.dev/v1alpha2:ApiServerSource,sources.knative.dev/v1alpha2:ContainerSource,sources.knative.dev/v1alpha2:PingSource || fail_test +echo "Running E2E tests for: Multi Tenant Channel Based Broker, Channel (v1beta1, v1), InMemoryChannel (v1beta1, v1) , ApiServerSource (v1beta1, v1), ContainerSource (v1alpha2, v1) and PingSource (v1beta1)" +go_test_e2e -timeout=30m -parallel=12 ./test/e2e -brokerclass=MTChannelBasedBroker -channels=messaging.knative.dev/v1beta1:Channel,messaging.knative.dev/v1beta1:InMemoryChannel,messaging.knative.dev/v1:Channel,messaging.knative.dev/v1:InMemoryChannel -sources=sources.knative.dev/v1beta1:ApiServerSource,sources.knative.dev/v1alpha2:ContainerSource,sources.knative.dev/v1beta1:PingSource,sources.knative.dev/v1:ApiServerSource,sources.knative.dev/v1:ContainerSource || fail_test success diff --git a/vendor/knative.dev/hack/library.sh b/vendor/knative.dev/hack/library.sh index 89c89d9453..020eb72061 100644 --- a/vendor/knative.dev/hack/library.sh +++ b/vendor/knative.dev/hack/library.sh @@ -517,7 +517,7 @@ function go_update_deps() { echo "=== Update Deps for Golang" local UPGRADE=0 - local VERSION="v9000.1" # release v9000 is so far in the future, it will always pick the default branch. + local VERSION="master" local DOMAIN="knative.dev" while [[ $# -ne 0 ]]; do parameter=$1 diff --git a/vendor/knative.dev/pkg/logging/config.go b/vendor/knative.dev/pkg/logging/config.go index e1480033de..2b5eb696d9 100644 --- a/vendor/knative.dev/pkg/logging/config.go +++ b/vendor/knative.dev/pkg/logging/config.go @@ -65,10 +65,7 @@ func NewLogger(configJSON string, levelOverride string, opts ...zap.Option) (*za if err2 != nil { panic(err2) } - - slogger := enrichLoggerWithCommitID(logger.Named(fallbackLoggerName)) - slogger.Warnw("Failed to parse logging config - using default zap production config", zap.Error(err)) - return slogger, loggingCfg.Level + return enrichLoggerWithCommitID(logger.Named(fallbackLoggerName)), loggingCfg.Level } func enrichLoggerWithCommitID(logger *zap.Logger) *zap.SugaredLogger { diff --git a/vendor/knative.dev/pkg/metrics/config.go b/vendor/knative.dev/pkg/metrics/config.go index d4ae24ad54..38ac02e65f 100644 --- a/vendor/knative.dev/pkg/metrics/config.go +++ b/vendor/knative.dev/pkg/metrics/config.go @@ -60,9 +60,7 @@ const ( defaultPrometheusPort = 9090 maxPrometheusPort = 65535 minPrometheusPort = 1024 - defaultPrometheusHost = "0.0.0.0" prometheusPortEnvName = "METRICS_PROMETHEUS_PORT" - prometheusHostEnvName = "METRICS_PROMETHEUS_HOST" ) // Metrics backend "enum". @@ -107,10 +105,6 @@ type metricsConfig struct { // format. It defaults to 9090. prometheusPort int - // prometheusHost is the host where the metrics are exposed in Prometheus - // format. It defaults to "0.0.0.0" - prometheusHost string - // ---- Stackdriver specific below ---- // True if backendDestination equals to "stackdriver". Store this in a variable // to reduce string comparison operations. @@ -246,7 +240,6 @@ func createMetricsConfig(ctx context.Context, ops ExporterOptions) (*metricsConf } mc.prometheusPort = pp - mc.prometheusHost = prometheusHost() case stackdriver: // If stackdriverClientConfig is not provided for stackdriver backend destination, OpenCensus will try to // use the application default credentials. If that is not available, Opencensus would fail to create the @@ -348,17 +341,6 @@ func prometheusPort() (int, error) { return int(pp), nil } -// prometheusHost returns the host configured via the environment -// for the Prometheus metrics exporter if it's set, a default value otherwise. -// No validation is done here. -func prometheusHost() string { - phStr := os.Getenv(prometheusHostEnvName) - if phStr == "" { - return defaultPrometheusHost - } - return phStr -} - // JSONToOptions converts a json string to ExporterOptions. func JSONToOptions(jsonOpts string) (*ExporterOptions, error) { var opts ExporterOptions diff --git a/vendor/knative.dev/pkg/metrics/config_observability.go b/vendor/knative.dev/pkg/metrics/config_observability.go index 18df1e9176..ae622c928d 100644 --- a/vendor/knative.dev/pkg/metrics/config_observability.go +++ b/vendor/knative.dev/pkg/metrics/config_observability.go @@ -73,12 +73,6 @@ type ObservabilityConfig struct { // the pods via an HTTP server in the format expected by the pprof visualization tool. EnableProfiling bool - // DisableQPProfiling indicates whether EnableProfiling flag applies to the QueueProxy processes. - // If false (default) — enabling or disabling profiling causes a global rolling restart of the - // Knative service pods, which might not be desirable (especially if there is no need to profile - // QP processes). - DisableQPProfiling bool - // EnableRequestLog enables activator/queue-proxy to write request logs. EnableRequestLog bool @@ -107,7 +101,6 @@ func NewObservabilityConfigFromConfigMap(configMap *corev1.ConfigMap) (*Observab cm.AsBool(EnableProbeReqLogKey, &oc.EnableProbeRequestLog), cm.AsString("metrics.request-metrics-backend-destination", &oc.RequestMetricsBackend), cm.AsBool("profiling.enable", &oc.EnableProfiling), - cm.AsBool("profiling.disable-qp", &oc.DisableQPProfiling), cm.AsString("metrics.opencensus-address", &oc.MetricsCollectorAddress), ); err != nil { return nil, err diff --git a/vendor/knative.dev/pkg/metrics/exporter.go b/vendor/knative.dev/pkg/metrics/exporter.go index 0c680106ee..a7411fccb0 100644 --- a/vendor/knative.dev/pkg/metrics/exporter.go +++ b/vendor/knative.dev/pkg/metrics/exporter.go @@ -66,15 +66,10 @@ type ExporterOptions struct { // PrometheusPort is the port to expose metrics if metrics backend is Prometheus. // It should be between maxPrometheusPort and maxPrometheusPort. 0 value means - // using the default 9090 value. It is ignored if metrics backend is not + // using the default 9090 value. If is ignored if metrics backend is not // Prometheus. PrometheusPort int - // PrometheusHost is the host to expose metrics on if metrics backend is Prometheus. - // The default value is "0.0.0.0". It is ignored if metrics backend is not - // Prometheus. - PrometheusHost string - // ConfigMap is the data from config map config-observability. Must be present. // See https://github.com/knative/serving/blob/master/config/config-observability.yaml // for details. diff --git a/vendor/knative.dev/pkg/metrics/prometheus_exporter.go b/vendor/knative.dev/pkg/metrics/prometheus_exporter.go index 784eab2e8c..7f49302cc4 100644 --- a/vendor/knative.dev/pkg/metrics/prometheus_exporter.go +++ b/vendor/knative.dev/pkg/metrics/prometheus_exporter.go @@ -17,8 +17,8 @@ limitations under the License. package metrics import ( + "fmt" "net/http" - "strconv" "sync" prom "contrib.go.opencensus.io/exporter/prometheus" @@ -41,7 +41,6 @@ func (emptyPromExporter) ExportView(viewData *view.Data) { // a signal to enrich the internal Meters with Resource information. } -//nolint: unparam // False positive of flagging the second result of this function unused. func newPrometheusExporter(config *metricsConfig, logger *zap.SugaredLogger) (view.Exporter, ResourceExporterFactory, error) { e, err := prom.NewExporter(prom.Options{Namespace: config.component}) if err != nil { @@ -51,7 +50,7 @@ func newPrometheusExporter(config *metricsConfig, logger *zap.SugaredLogger) (vi logger.Infof("Created Opencensus Prometheus exporter with config: %v. Start the server for Prometheus exporter.", config) // Start the server for Prometheus scraping go func() { - srv := startNewPromSrv(e, config.prometheusHost, config.prometheusPort) + srv := startNewPromSrv(e, config.prometheusPort) srv.ListenAndServe() }() return e, @@ -74,7 +73,7 @@ func resetCurPromSrv() { } } -func startNewPromSrv(e *prom.Exporter, host string, port int) *http.Server { +func startNewPromSrv(e *prom.Exporter, port int) *http.Server { sm := http.NewServeMux() sm.Handle("/metrics", e) curPromSrvMux.Lock() @@ -83,7 +82,7 @@ func startNewPromSrv(e *prom.Exporter, host string, port int) *http.Server { curPromSrv.Close() } curPromSrv = &http.Server{ - Addr: host + ":" + strconv.Itoa(port), + Addr: fmt.Sprint(":", port), Handler: sm, } return curPromSrv diff --git a/vendor/knative.dev/pkg/test/logging/.gitattributes b/vendor/knative.dev/pkg/test/logging/.gitattributes new file mode 100644 index 0000000000..19c29c12f6 --- /dev/null +++ b/vendor/knative.dev/pkg/test/logging/.gitattributes @@ -0,0 +1 @@ +memory_encoder.go coverage-excluded=true diff --git a/vendor/knative.dev/pkg/test/logging/doc.go b/vendor/knative.dev/pkg/test/logging/doc.go new file mode 100644 index 0000000000..e76b9cbe94 --- /dev/null +++ b/vendor/knative.dev/pkg/test/logging/doc.go @@ -0,0 +1,49 @@ +/* +Copyright 2020 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/* +Package logging assists setting up test logging and using leveled logging in tests. + +The TLogger is designed to assist the test writer in creating more useful tests and +collecting log data in multiple streams, optimizing for human readability in one and +machine readability in another. It's designed to mimic the testing.T object rather closely and +use Zap logging semantics, both things already in use in Knative, to minimize the time developers +need to spend learning the tool. + +Inspired by and uses go-logr. + +Advantages + +The TLogger enhances test design through subtle nudges and affordances: + +* It encourages only logging with .V(), giving the writer a nudge to think about how important it is, +but without requiring them to fit it in a narrowly-defined category. + +* Reduces boilerplate of carrying around context for errors in several different variables, +using .WithValues(), which results in more consistent and reusable code across the tests. + +Porting + +To port code from using testing.T to logging.TLogger, the interfaces knative.dev/pkg/test.T and +knative.dev/pkg/test.TLegacy have been created. All library functions should be refactored to use +one interface and all .Log() calls rewritten to use structured format, which works with testing and +TLogger. If a library function needs test functions not available even in test.TLegacy, +it's probably badly written. + +Then any test can be incrementally rewritten to use TLogger, as it coexists with testing.T without issue. + +*/ +package logging diff --git a/vendor/knative.dev/pkg/test/logging/error.go b/vendor/knative.dev/pkg/test/logging/error.go new file mode 100644 index 0000000000..774a606125 --- /dev/null +++ b/vendor/knative.dev/pkg/test/logging/error.go @@ -0,0 +1,90 @@ +/* +Copyright 2020 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package logging + +import ( + "fmt" + + "github.com/davecgh/go-spew/spew" +) + +// StructuredError is an error which can hold arbitrary key-value arguments. +// +// TODO(coryrc): The Structured Error is experimental and likely to be removed, but is currently in use in a refactored test. +type StructuredError interface { + error + GetValues() []interface{} + WithValues(...interface{}) StructuredError + DisableValuePrinting() + EnableValuePrinting() +} + +type structuredError struct { + msg string + keysAndValues []interface{} + print bool +} + +func keysAndValuesToSpewedMap(args ...interface{}) map[string]string { + m := make(map[string]string, len(args)/2) + for i := 0; i < len(args); i += 2 { + key, val := args[i], args[i+1] + if keyStr, ok := key.(string); ok { + m[keyStr] = spew.Sdump(val) + } + } + return m +} + +// Error implements `error` interface +func (e structuredError) Error() string { + // TODO(coryrc): accept zap.Field entries? + if e.print { + // %v for fmt.Sprintf does print keys sorted + return fmt.Sprintf("Error: %s\nContext:\n%v", e.msg, keysAndValuesToSpewedMap(e.keysAndValues...)) + } + return e.msg +} + +// GetValues gives you the structured key values in a plist +func (e structuredError) GetValues() []interface{} { + return e.keysAndValues +} + +// DisableValuePrinting disables printing out the keys and values from the Error() method +func (e *structuredError) DisableValuePrinting() { + e.print = false +} + +// EnableValuePrinting enables printing out the keys and values from the Error() method +func (e *structuredError) EnableValuePrinting() { + e.print = true +} + +// Create a StructuredError. Gives a little better logging when given to a TLogger. +// This may prove to not be useful if users use the logger's WithValues() better. +func Error(msg string, keysAndValues ...interface{}) error { + return &structuredError{msg, keysAndValues, true} +} + +// WithValues operates just like TLogger's WithValues but stores them in the error object. +func (e *structuredError) WithValues(keysAndValues ...interface{}) StructuredError { + newKAV := make([]interface{}, 0, len(keysAndValues)+len(e.keysAndValues)) + newKAV = append(newKAV, e.keysAndValues...) + newKAV = append(newKAV, keysAndValues...) + return &structuredError{e.msg, newKAV, e.print} +} diff --git a/vendor/knative.dev/pkg/test/logging/logger.go b/vendor/knative.dev/pkg/test/logging/logger.go new file mode 100644 index 0000000000..b8f3e4a716 --- /dev/null +++ b/vendor/knative.dev/pkg/test/logging/logger.go @@ -0,0 +1,76 @@ +// Copyright 2020 The Knative Authors +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +// Copying testingWriter from zaptest and allowing it to be disabled + +package logging + +import ( + "bytes" + "errors" + "testing" +) + +// testingWriter is a WriteSyncer that writes to the given testing.TB. +type testingWriter struct { + t *testing.T + + // If true, the test will be marked as failed if this testingWriter is + // ever used. + markFailed bool +} + +func newTestingWriter(t *testing.T) testingWriter { + return testingWriter{t: t} +} + +// WithMarkFailed returns a copy of this testingWriter with markFailed set to +// the provided value. +func (w testingWriter) WithMarkFailed(v bool) testingWriter { + w.markFailed = v + return w +} + +func (w testingWriter) Write(p []byte) (n int, err error) { + if w.t == nil { + return 0, errors.New("Write to buffer after test function completed") + } + n = len(p) + + // Strip trailing newline because t.Log always adds one. + p = bytes.TrimRight(p, "\n") + + // Note: t.Log is safe for concurrent use. + w.t.Logf("%s", p) + if w.markFailed { + w.t.Fail() + } + + return n, nil +} + +func (w testingWriter) Sync() error { + return nil +} + +func (w *testingWriter) Disable() { + w.t = nil +} diff --git a/vendor/knative.dev/pkg/test/logging/memory_encoder.go b/vendor/knative.dev/pkg/test/logging/memory_encoder.go new file mode 100644 index 0000000000..248046b624 --- /dev/null +++ b/vendor/knative.dev/pkg/test/logging/memory_encoder.go @@ -0,0 +1,74 @@ +// Copyright 2020 The Knative Authors +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package logging + +import ( + "time" + + "go.uber.org/zap/zapcore" +) + +// sliceArrayEncoder is an ArrayEncoder backed by a simple []interface{}. Like +// the MapObjectEncoder, it's not designed for production use. +type sliceArrayEncoder struct { + elems []interface{} +} + +func (s *sliceArrayEncoder) AppendArray(v zapcore.ArrayMarshaler) error { + enc := &sliceArrayEncoder{} + err := v.MarshalLogArray(enc) + s.elems = append(s.elems, enc.elems) + return err +} + +func (s *sliceArrayEncoder) AppendObject(v zapcore.ObjectMarshaler) error { + m := zapcore.NewMapObjectEncoder() + err := v.MarshalLogObject(m) + s.elems = append(s.elems, m.Fields) + return err +} + +func (s *sliceArrayEncoder) AppendReflected(v interface{}) error { + s.elems = append(s.elems, v) + return nil +} + +func (s *sliceArrayEncoder) AppendBool(v bool) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendByteString(v []byte) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendComplex128(v complex128) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendComplex64(v complex64) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendDuration(v time.Duration) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendFloat64(v float64) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendFloat32(v float32) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt(v int) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt64(v int64) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt32(v int32) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt16(v int16) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt8(v int8) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendString(v string) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendTime(v time.Time) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint(v uint) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint64(v uint64) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint32(v uint32) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint16(v uint16) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint8(v uint8) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUintptr(v uintptr) { s.elems = append(s.elems, v) } diff --git a/vendor/knative.dev/pkg/test/logging/spew_encoder.go b/vendor/knative.dev/pkg/test/logging/spew_encoder.go new file mode 100644 index 0000000000..38c83c8541 --- /dev/null +++ b/vendor/knative.dev/pkg/test/logging/spew_encoder.go @@ -0,0 +1,196 @@ +// Copyright 2020 The Knative Authors +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package logging + +import ( + "fmt" + "sort" + "strings" + "sync" + + "go.uber.org/zap" + "go.uber.org/zap/buffer" + "go.uber.org/zap/zapcore" +) + +var ( + _pool = buffer.NewPool() + _sliceEncoderPool = sync.Pool{ + New: func() interface{} { + return &sliceArrayEncoder{elems: make([]interface{}, 0, 2)} + }, + } +) + +func init() { + zap.RegisterEncoder("spew", func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { + return NewSpewEncoder(encoderConfig), nil + }) +} + +// NewSpewEncoder encodes logs using the spew library. +// +// The JSON encoder (also used by the console encoder) included in Zap can only print objects that +// can be serialized to JSON and doesn't print them in the most readable way. This spew encoder is +// designed to make human-readable log only and get the most information to the user on any data type. +// +// Code is mostly from console_encoder.go in zapcore. +func NewSpewEncoder(cfg zapcore.EncoderConfig) *SpewEncoder { + enc := SpewEncoder{} + enc.MapObjectEncoder = zapcore.NewMapObjectEncoder() + enc.EncoderConfig = &cfg + return &enc +} + +// SpewEncoder implements zapcore.Encoder interface +type SpewEncoder struct { + *zapcore.MapObjectEncoder + *zapcore.EncoderConfig +} + +// Implements zapcore.Encoder interface +func (enc *SpewEncoder) Clone() zapcore.Encoder { + n := NewSpewEncoder(*(enc.EncoderConfig)) + for k, v := range enc.Fields { + n.Fields[k] = v + } + return n +} + +func getSliceEncoder() *sliceArrayEncoder { + return _sliceEncoderPool.Get().(*sliceArrayEncoder) +} + +func putSliceEncoder(e *sliceArrayEncoder) { + e.elems = e.elems[:0] + _sliceEncoderPool.Put(e) +} + +// Implements zapcore.Encoder interface. +func (enc *SpewEncoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) { + line := _pool.Get() + + // Could probably rewrite this portion and remove the copied + // memory_encoder.go from this folder + arr := getSliceEncoder() + defer putSliceEncoder(arr) + + if enc.TimeKey != "" && enc.EncodeTime != nil { + enc.EncodeTime(ent.Time, arr) + } + if enc.LevelKey != "" && enc.EncodeLevel != nil { + enc.EncodeLevel(ent.Level, arr) + } + + if ent.LoggerName != "" && enc.NameKey != "" { + nameEncoder := enc.EncodeName + + if nameEncoder == nil { + // Fall back to FullNameEncoder for backward compatibility. + nameEncoder = zapcore.FullNameEncoder + } + + nameEncoder(ent.LoggerName, arr) + } + if ent.Caller.Defined && enc.CallerKey != "" && enc.EncodeCaller != nil { + enc.EncodeCaller(ent.Caller, arr) + } + for i := range arr.elems { + if i > 0 { + line.AppendByte('\t') + } + fmt.Fprint(line, arr.elems[i]) + } + + // Add the message itself. + if enc.MessageKey != "" { + enc.addTabIfNecessary(line) + line.AppendString(ent.Message) + } + + // Add any structured context. + enc.writeContext(line, fields) + + // If there's no stacktrace key, honor that; this allows users to force + // single-line output. + if ent.Stack != "" && enc.StacktraceKey != "" { + line.AppendByte('\n') + line.AppendString(ent.Stack) + } + + if enc.LineEnding != "" { + line.AppendString(enc.LineEnding) + } else { + line.AppendString(zapcore.DefaultLineEnding) + } + return line, nil +} + +func (enc *SpewEncoder) writeContext(line *buffer.Buffer, extra []zapcore.Field) { + if len(extra) == 0 && len(enc.Fields) == 0 { + return + } + + // This could probably be more efficient, but .AddTo() is convenient + + context := zapcore.NewMapObjectEncoder() + for k, v := range enc.Fields { + context.Fields[k] = v + } + for i := range extra { + extra[i].AddTo(context) + } + + enc.addTabIfNecessary(line) + line.AppendString("\nContext:\n") + keys := make([]string, 0, len(context.Fields)) + for k := range context.Fields { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + line.AppendString(k) + line.AppendString(": ") + line.AppendString(stringify(context.Fields[k])) + line.TrimNewline() + line.AppendString("\n") + } +} + +func stringify(a interface{}) string { + s, ok := a.(string) + if !ok { + s = strings.TrimSuffix(spewConfig.Sdump(a), "\n") + } + ret := strings.ReplaceAll(s, "\n", "\n ") + hasNewlines := s != ret + if hasNewlines { + return "\n " + ret + } + return s +} + +func (enc *SpewEncoder) addTabIfNecessary(line *buffer.Buffer) { + if line.Len() > 0 { + line.AppendByte('\t') + } +} diff --git a/vendor/knative.dev/pkg/test/logging/sugar.go b/vendor/knative.dev/pkg/test/logging/sugar.go new file mode 100644 index 0000000000..01fc6b29f9 --- /dev/null +++ b/vendor/knative.dev/pkg/test/logging/sugar.go @@ -0,0 +1,114 @@ +// Copyright 2020 Knative Authors +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package logging + +import ( + "github.com/davecgh/go-spew/spew" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + + "go.uber.org/multierr" +) + +const ( + _oddNumberErrMsg = "Ignored key without a value." + _nonStringKeyErrMsg = "Ignored key-value pairs with non-string keys." +) + +var spewConfig *spew.ConfigState + +func init() { + spewConfig = spew.NewDefaultConfig() + spewConfig.DisableCapacities = true + spewConfig.SortKeys = true + spewConfig.SpewKeys = true + spewConfig.ContinueOnMethod = true +} + +func (o *TLogger) handleFields(args []interface{}) []zap.Field { + if len(args) == 0 { + return nil + } + s := o.l.Sugar() + + // Allocate enough space for the worst case; if users pass only structured + // fields, we shouldn't penalize them with extra allocations. + fields := make([]zap.Field, 0, len(args)) + var invalid invalidPairs + + for i := 0; i < len(args); { + // This is a strongly-typed field. Consume it and move on. + if f, ok := args[i].(zap.Field); ok { + fields = append(fields, f) + i++ + continue + } + + // Make sure this element isn't a dangling key. + if i == len(args)-1 { + s.DPanic(_oddNumberErrMsg, zap.Any("ignored", args[i])) + break + } + + // Consume this value and the next, treating them as a key-value pair. If the + // key isn't a string, add this pair to the slice of invalid pairs. + key, val := args[i], args[i+1] + if keyStr, ok := key.(string); !ok { + // Subsequent errors are likely, so allocate once up front. + if cap(invalid) == 0 { + invalid = make(invalidPairs, 0, len(args)/2) + } + invalid = append(invalid, invalidPair{i, key, val}) + } else { + fields = append(fields, zap.Any(keyStr, val)) + } + i += 2 + } + + // If we encountered any invalid key-value pairs, log an error. + if len(invalid) > 0 { + s.DPanic(_nonStringKeyErrMsg, zap.Array("invalid", invalid), zap.String("all_input", spew.Sprintf("%#+v", args))) + } + return fields +} + +type invalidPair struct { + position int + key, value interface{} +} + +func (p invalidPair) MarshalLogObject(enc zapcore.ObjectEncoder) error { + enc.AddInt64("position", int64(p.position)) + zap.Any("key", p.key).AddTo(enc) + zap.Any("value", p.value).AddTo(enc) + return nil +} + +type invalidPairs []invalidPair + +func (ps invalidPairs) MarshalLogArray(enc zapcore.ArrayEncoder) error { + var err error + for i := range ps { + err = multierr.Append(err, enc.AppendObject(ps[i])) + } + return err +} diff --git a/vendor/knative.dev/pkg/test/logging/tlogger.go b/vendor/knative.dev/pkg/test/logging/tlogger.go new file mode 100644 index 0000000000..f6e05c5ce2 --- /dev/null +++ b/vendor/knative.dev/pkg/test/logging/tlogger.go @@ -0,0 +1,372 @@ +/* +Copyright 2020 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package logging + +import ( + "errors" + "fmt" + "testing" + + "github.com/go-logr/logr" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +// TLogger is TLogger +type TLogger struct { + l *zap.Logger + level int + t *testing.T + errs map[string][]interface{} // For Collect() + dontFail bool +} + +// V() returns an InfoLogger from go-logr. +// +// This should be the main way your tests log. +// Most frequent usage is used directly: +// t.V(2).Info("Something at regular level") +// But if something computationally difficult is to be done, can do: +// if l := t.V(8); l.Enabled() { +// x := somethingExpensive() +// l.Info("logging it", "expensiveThing", x) +// } +// +// Elsewhere in this documentation refers to a hypothetical .V(errorLevel) to simplify explanations. +// The V() function cannot write to the error level; the Error, ErrorIfErr, Fatal, and +// FatalIfErr methods are the only way to write to the error level. +func (o *TLogger) V(level int) logr.InfoLogger { + // Consider adding || (level <= logrZapDebugLevel && o.l.Core().Enabled(zapLevelFromLogrLevel(level))) + // Reason to add it is even if you ask for verbosity=1, in case of error you'll get up to verbosity=3 in the debug output + // but since zapTest uses Debug, you always get V(<=3) even when verbosity < 3 + // Probable solution is to write to t.Log at Info level? + if level <= o.level { + return &infoLogger{ + logrLevel: o.level, + t: o, + } + } + return disabledInfoLogger +} + +// WithValues() acts like Zap's With() method. +// Consistent with logr.Logger.WithValues() +// Whenever anything is logged with the returned TLogger, +// it will act as if these keys and values were passed into every logging call. +func (o *TLogger) WithValues(keysAndValues ...interface{}) *TLogger { + return o.cloneWithNewLogger(o.l.With(o.handleFields(keysAndValues)...)) +} + +// WithName() acts like Zap's Named() method. +// Consistent with logr.Logger.WithName() +// Appends the name onto the current logger +func (o *TLogger) WithName(name string) *TLogger { + return o.cloneWithNewLogger(o.l.Named(name)) +} + +// Custom additions: + +// ErrorIfErr fails the current test if the err != nil. +// Remaining arguments function as if passed to .V(errorLevel).Info() (were that a thing) +// Same signature as logr.Logger.Error() method, but as this is a test, it functions slightly differently. +func (o *TLogger) ErrorIfErr(err error, msg string, keysAndValues ...interface{}) { + if err != nil { + o.error(err, msg, keysAndValues) + o.fail() + } +} + +// FatalIfErr is just like ErrorIfErr() but test execution stops immediately +func (o *TLogger) FatalIfErr(err error, msg string, keysAndValues ...interface{}) { + if err != nil { + o.error(err, msg, keysAndValues) + o.failNow() + } +} + +// Error is essentially a .V(errorLevel).Info() followed by failing the test. +// Intended usage is Error(msg string, key-value alternating arguments) +// Same effect as testing.T.Error +// Generic definition for compatibility with test.T interface +// Implements test.T +func (o *TLogger) Error(stringThenKeysAndValues ...interface{}) { + // Using o.error to have consistent call depth for Error, FatalIfErr, Info, etc + o.error(o.errorWithRuntimeCheck(stringThenKeysAndValues...)) + o.fail() +} + +// Fatal is essentially a .V(errorLevel).Info() followed by failing and immediately stopping the test. +// Intended usage is Fatal(msg string, key-value alternating arguments) +// Same effect as testing.T.Fatal +// Generic definition for compatibility with test.TLegacy interface +// Implements test.TLegacy +func (o *TLogger) Fatal(stringThenKeysAndValues ...interface{}) { + o.error(o.errorWithRuntimeCheck(stringThenKeysAndValues...)) + o.failNow() +} + +func (o *TLogger) fail() { + if o.t != nil && !o.dontFail { + o.t.Fail() + } +} + +func (o *TLogger) failNow() { + if o.t != nil && !o.dontFail { + o.t.FailNow() + } +} + +func validateKeysAndValues(keysAndValues ...interface{}) bool { + length := len(keysAndValues) + for i := 0; i < length; { + _, isField := keysAndValues[i].(zapcore.Field) + _, isString := keysAndValues[i].(string) + if isField { + i++ + } else if isString { + if i == length-1 { + return false + } + i += 2 + } else { + return false + } + } + return true +} + +func (o *TLogger) interfacesToFields(things ...interface{}) []interface{} { + o.V(5).Info("DEPRECATED Error/Fatal usage", zap.Stack("callstack")) + fields := make([]interface{}, 2*len(things)) + for i, d := range things { + fields[i*2] = fmt.Sprintf("arg %d", i) + fields[i*2+1] = d + } + return fields +} + +func (o *TLogger) errorWithRuntimeCheck(stringThenKeysAndValues ...interface{}) (error, string, []interface{}) { //nolint // Returning the error first is okay and expected here. + if len(stringThenKeysAndValues) == 0 { + return nil, "", nil + } + s, isString := stringThenKeysAndValues[0].(string) + if isString { + // Desired case (hopefully) + remainder := stringThenKeysAndValues[1:] + if !validateKeysAndValues(remainder...) { + remainder = o.interfacesToFields(remainder...) + } + return nil, s, remainder + } + e, isError := stringThenKeysAndValues[0].(error) + if isError && len(stringThenKeysAndValues) == 1 { + return e, "", nil + } + return nil, "unstructured error", o.interfacesToFields(stringThenKeysAndValues...) +} + +// Cleanup registers a cleanup callback. +func (o *TLogger) Cleanup(c func()) { + o.t.Cleanup(c) +} + +// Run a subtest. Just like testing.T.Run but creates a TLogger. +func (o *TLogger) Run(name string, f func(t *TLogger)) { + tfunc := func(ts *testing.T) { + tl, cancel := newTLogger(ts, o.level, o.dontFail) + defer cancel() + f(tl) + } + o.t.Run(name, tfunc) +} + +// Name is just like testing.T.Name() +// Implements test.T +func (o *TLogger) Name() string { + return o.t.Name() +} + +// Helper cannot work as an indirect call, so just do nothing :( +// Implements test.T +func (o *TLogger) Helper() { +} + +// SkipNow immediately stops test execution +// Implements test.T +func (o *TLogger) SkipNow() { + o.t.SkipNow() +} + +// Log is deprecated: only existing for test.T compatibility +// Please use leveled logging via .V().Info() +// Will panic if given data incompatible with Info() function +// Implements test.T +func (o *TLogger) Log(args ...interface{}) { + // This is complicated to ensure exactly 2 levels of indirection + i := o.V(2) + iL, ok := i.(*infoLogger) + if ok { + iL.indirectWrite(args[0].(string), args[1:]...) + } +} + +// Parallel allows tests or subtests to run in parallel +// Just calls the testing.T.Parallel() under the hood +func (o *TLogger) Parallel() { + o.t.Parallel() +} + +// Logf is deprecated: only existing for test.TLegacy compatibility +// Please use leveled logging via .V().Info() +// Implements test.TLegacy +func (o *TLogger) Logf(fmtS string, args ...interface{}) { + // This is complicated to ensure exactly 2 levels of indirection + iL, ok := o.V(2).(*infoLogger) + if ok { + iL.indirectWrite(fmt.Sprintf(fmtS, args...)) + } +} + +func (o *TLogger) error(err error, msg string, keysAndValues []interface{}) { + var newKAV []interface{} + var serr StructuredError + if errors.As(err, &serr) { + serr.DisableValuePrinting() + defer serr.EnableValuePrinting() + newLen := len(keysAndValues) + len(serr.GetValues()) + newKAV = make([]interface{}, 0, newLen+2) + newKAV = append(newKAV, keysAndValues...) + newKAV = append(newKAV, serr.GetValues()...) + } + if err != nil { + if msg == "" { // This is used if just the error is given to .Error() or .Fatal() + msg = err.Error() + } else { + if newKAV == nil { + newKAV = make([]interface{}, 0, len(keysAndValues)+1) + newKAV = append(newKAV, keysAndValues...) + } + newKAV = append(newKAV, zap.Error(err)) + } + } + if newKAV != nil { + keysAndValues = newKAV + } + if checkedEntry := o.l.Check(zap.ErrorLevel, msg); checkedEntry != nil { + checkedEntry.Write(o.handleFields(keysAndValues)...) + } +} + +// Creation and Teardown + +// Create a TLogger object using the global Zap logger and the current testing.T +// `defer` a call to second return value immediately after. +func NewTLogger(t *testing.T) (*TLogger, func()) { + return newTLogger(t, verbosity, false) +} + +func newTLogger(t *testing.T, verbosity int, dontFail bool) (*TLogger, func()) { + testOptions := []zap.Option{ + zap.AddCaller(), + zap.AddCallerSkip(2), + zap.Development(), + } + writer := newTestingWriter(t) + // Based off zap.NewDevelopmentEncoderConfig() + cfg := zapcore.EncoderConfig{ + // Wanted keys can be anything except the empty string. + TimeKey: "", + LevelKey: "", + NameKey: "", + CallerKey: "C", + MessageKey: "M", + StacktraceKey: "S", + LineEnding: zapcore.DefaultLineEnding, + EncodeLevel: zapcore.CapitalLevelEncoder, + EncodeTime: zapcore.ISO8601TimeEncoder, + EncodeDuration: zapcore.StringDurationEncoder, + EncodeCaller: zapcore.ShortCallerEncoder, + } + core := zapcore.NewCore( + NewSpewEncoder(cfg), + writer, + zapcore.DebugLevel, + ) + if zapCore != nil { + core = zapcore.NewTee( + zapCore, + core, + // TODO(coryrc): Open new file (maybe creating JUnit!?) with test output? + ) + } + log := zap.New(core, testOptions...).Named(t.Name()) + tlogger := TLogger{ + l: log, + level: verbosity, + t: t, + errs: make(map[string][]interface{}), + dontFail: dontFail, + } + return &tlogger, func() { + tlogger.handleCollectedErrors() + // Sometimes goroutines exist after a test and they cause panics if they attempt to call t.Log(). + // Prevent this panic by disabling writes to the testing.T (we'll still get them everywhere else). + writer.Disable() + } +} + +func (o *TLogger) cloneWithNewLogger(l *zap.Logger) *TLogger { + t := TLogger{ + l: l, + level: o.level, + t: o.t, + errs: o.errs, + dontFail: o.dontFail, + } + return &t +} + +// Collect allows you to commingle multiple validations during one test execution. +// Under the hood, it creates a sub-test during cleanup and iterates through the collected values, printing them. +// If any are errors, it fails the subtest. +// Currently experimental and likely to be removed +func (o *TLogger) Collect(key string, value interface{}) { + list, hasKey := o.errs[key] + if hasKey { + list = append(list, value) + } else { + list = make([]interface{}, 1) + list[0] = value + } + o.errs[key] = list +} + +func (o *TLogger) handleCollectedErrors() { + for name, list := range o.errs { + o.Run(name, func(t *TLogger) { + for _, item := range list { + _, isError := item.(error) + if isError { + t.Error(item) + } else { + t.V(3).Info(spewConfig.Sprint(item)) + } + } + }) + } +} diff --git a/vendor/knative.dev/pkg/test/logging/zapr.go b/vendor/knative.dev/pkg/test/logging/zapr.go new file mode 100644 index 0000000000..c0b9f58584 --- /dev/null +++ b/vendor/knative.dev/pkg/test/logging/zapr.go @@ -0,0 +1,47 @@ +// Copyright 2020 Knative Authors +// Copyright 2018 Solly Ross +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The useful parts of this file have been preserved +// from their origin at https://github.com/go-logr/zapr/tree/8f2487342d52a33a1793e50e3ca04bc1767aa65c + +package logging + +// noopInfoLogger is a logr.InfoLogger that's always disabled, and does nothing. +type noopInfoLogger struct{} + +func (l *noopInfoLogger) Enabled() bool { return false } +func (l *noopInfoLogger) Info(_ string, _ ...interface{}) {} + +var disabledInfoLogger = &noopInfoLogger{} + +// infoLogger is a logr.InfoLogger that uses Zap to log at a particular +// level. +type infoLogger struct { + logrLevel int + t *TLogger +} + +func (i *infoLogger) Enabled() bool { return true } +func (i *infoLogger) Info(msg string, keysAndVals ...interface{}) { + i.indirectWrite(msg, keysAndVals...) +} + +// This function just exists to have consistent 2-level call depth for Zap proxying +func (i *infoLogger) indirectWrite(msg string, keysAndVals ...interface{}) { + lvl := zapLevelFromLogrLevel(i.logrLevel) + if checkedEntry := i.t.l.Check(lvl, msg); checkedEntry != nil { + checkedEntry.Write(i.t.handleFields(keysAndVals)...) + } +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_lifecycle.go index 85089e9aeb..fac3cd3592 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_lifecycle.go @@ -123,12 +123,16 @@ func (rs *RevisionStatus) MarkContainerHealthyTrue() { // MarkContainerHealthyFalse marks ContainerHealthy status on revision as False func (rs *RevisionStatus) MarkContainerHealthyFalse(reason, message string) { - revisionCondSet.Manage(rs).MarkFalse(RevisionConditionContainerHealthy, reason, message) + // We escape here, because errors sometimes contain `%` and that makes the error message + // quite poor. + revisionCondSet.Manage(rs).MarkFalse(RevisionConditionContainerHealthy, reason, "%s", message) } // MarkContainerHealthyUnknown marks ContainerHealthy status on revision as Unknown func (rs *RevisionStatus) MarkContainerHealthyUnknown(reason, message string) { - revisionCondSet.Manage(rs).MarkUnknown(RevisionConditionContainerHealthy, reason, message) + // We escape here, because errors sometimes contain `%` and that makes the error message + // quite poor. + revisionCondSet.Manage(rs).MarkUnknown(RevisionConditionContainerHealthy, reason, "%s", message) } // MarkResourcesAvailableTrue marks ResourcesAvailable status on revision as True diff --git a/vendor/modules.txt b/vendor/modules.txt index 43c821edf5..c8f48b82a4 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1001,7 +1001,7 @@ k8s.io/utils/buffer k8s.io/utils/integer k8s.io/utils/pointer k8s.io/utils/trace -# knative.dev/eventing v0.18.1-0.20201109063108-dccb17e10b6b +# knative.dev/eventing v0.18.1-0.20201110185558-0f9a8c55c7b6 ## explicit knative.dev/eventing/pkg/apis/config knative.dev/eventing/pkg/apis/configs @@ -1132,14 +1132,14 @@ knative.dev/eventing/test/upgrade/prober/wathola/fetcher knative.dev/eventing/test/upgrade/prober/wathola/forwarder knative.dev/eventing/test/upgrade/prober/wathola/receiver knative.dev/eventing/test/upgrade/prober/wathola/sender -# knative.dev/hack v0.0.0-20201106190108-88f9ae4e6734 +# knative.dev/hack v0.0.0-20201103151104-3d5abc3a0075 ## explicit knative.dev/hack # knative.dev/networking v0.0.0-20201103163404-b9f80f4537af knative.dev/networking/pkg knative.dev/networking/pkg/apis/networking knative.dev/networking/pkg/apis/networking/v1alpha1 -# knative.dev/pkg v0.0.0-20201106192907-f98befda69eb +# knative.dev/pkg v0.0.0-20201103163404-5514ab0c1fdf ## explicit knative.dev/pkg/apiextensions/storageversion knative.dev/pkg/apiextensions/storageversion/cmd/migrate @@ -1252,7 +1252,7 @@ knative.dev/pkg/webhook/resourcesemantics knative.dev/pkg/webhook/resourcesemantics/conversion knative.dev/pkg/webhook/resourcesemantics/defaulting knative.dev/pkg/webhook/resourcesemantics/validation -# knative.dev/serving v0.18.1-0.20201109120108-68c2e63e32ee +# knative.dev/serving v0.18.1-0.20201110011758-db4879e0f615 ## explicit knative.dev/serving/pkg/apis/autoscaling knative.dev/serving/pkg/apis/autoscaling/v1alpha1