upgrade to latest dependencies (#1120)

Signed-off-by: Knative Automation <automation@knative.team>
This commit is contained in:
knative-automation 2020-11-17 06:32:52 -08:00 committed by GitHub
parent dca9561993
commit 10128901aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 107 additions and 1068 deletions

10
go.mod
View File

@ -22,11 +22,11 @@ require (
k8s.io/cli-runtime v0.18.8
k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible
k8s.io/code-generator v0.18.8
knative.dev/eventing v0.19.0
knative.dev/hack v0.0.0-20201103151104-3d5abc3a0075
knative.dev/networking v0.0.0-20201103163404-b9f80f4537af
knative.dev/pkg v0.0.0-20201103163404-5514ab0c1fdf
knative.dev/serving v0.19.0
knative.dev/eventing v0.19.1-0.20201117061051-47ee6e3586ca
knative.dev/hack v0.0.0-20201112185459-01a34c573bd8
knative.dev/networking v0.0.0-20201117131851-29d71950ee3d
knative.dev/pkg v0.0.0-20201117020252-ab1a398f669c
knative.dev/serving v0.19.1-0.20201117120351-3e2a380308b2
sigs.k8s.io/yaml v1.2.0
)

30
go.sum
View File

@ -202,7 +202,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0yf/KaRKURN6nyi7A9IZydMivZEm9oQLWNjfKDc=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@ -1182,11 +1181,9 @@ honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75
honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.18.8 h1:aIKUzJPb96f3fKec2lxtY7acZC9gQNDLVhfSGpxBAC4=
k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY=
k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio=
k8s.io/apiextensions-apiserver v0.18.8/go.mod h1:7f4ySEkkvifIr4+BRrRWriKKIJjPyg9mb/p63dJKnlM=
k8s.io/apimachinery v0.18.8 h1:jimPrycCqgx2QPearX3to1JePz7wSbVLq+7PdBTTwQ0=
k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig=
k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8=
k8s.io/apiserver v0.18.8/go.mod h1:12u5FuGql8Cc497ORNj79rhPdiXQC4bf53X/skR/1YM=
k8s.io/cli-runtime v0.18.8 h1:ycmbN3hs7CfkJIYxJAOB10iW7BVPmXGXkfEyiV9NJ+k=
k8s.io/cli-runtime v0.18.8/go.mod h1:7EzWiDbS9PFd0hamHHVoCY4GrokSTPSL32MA4rzIu0M=
@ -1195,7 +1192,6 @@ k8s.io/client-go v0.18.8/go.mod h1:HqFqMllQ5NnQJNwjro9k5zMyfhZlOwpuTLVrxjkYSxU=
k8s.io/cloud-provider v0.18.8/go.mod h1:cn9AlzMPVIXA4HHLVbgGUigaQlZyHSZ7WAwDEFNrQSs=
k8s.io/code-generator v0.18.8 h1:lgO1P1wjikEtzNvj7ia+x1VC4svJ28a/r0wnOLhhOTU=
k8s.io/code-generator v0.18.8/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
k8s.io/component-base v0.18.4/go.mod h1:7jr/Ef5PGmKwQhyAz/pjByxJbC58mhKAhiaDu0vXfPk=
k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU=
k8s.io/csi-translation-lib v0.18.8/go.mod h1:6cA6Btlzxy9s3QrS4BCZzQqclIWnTLr6Jx3H2ctAzY4=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
@ -1215,20 +1211,22 @@ k8s.io/legacy-cloud-providers v0.18.8/go.mod h1:tgp4xYf6lvjrWnjQwTOPvWQE9IVqSBGP
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
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.19.0 h1:9TdB1E4mwGYnuAJxSbNoljVsZRM+HUKEgsWiBXUIZEc=
knative.dev/eventing v0.19.0/go.mod h1:jwhDgDvoscWE4jWF8cXh7yHfxJcK0mTawVKVfrSjnvg=
knative.dev/hack v0.0.0-20201102193445-9349aeeb6701 h1:at6mUfi8gHWlBRd/qNM66JvUQ4C964cOpsy9hzac+7c=
knative.dev/hack v0.0.0-20201102193445-9349aeeb6701/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
knative.dev/caching v0.0.0-20201113182901-ee88f744543c/go.mod h1:gGr7clElRu3BOrGHex96ZjEPIM7+5dDd5XHeIRle4vE=
knative.dev/eventing v0.19.1-0.20201117061051-47ee6e3586ca h1:WFTkuMRlPvcLaNBdbM5y5xOxVDzzETOhBEBkznVPV5I=
knative.dev/eventing v0.19.1-0.20201117061051-47ee6e3586ca/go.mod h1:I5ysDZ5GyEut5p+jVHfuBKk33agLfqKJaF4kQpwvS2M=
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/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/serving v0.19.0 h1:aXJs15J7FKocVFxB+PTS2Yned2+8fvrgxMQH2sV/DWM=
knative.dev/serving v0.19.0/go.mod h1:G5FVEbwcHKLvf8XTr6XEVqLd3tn31JX8vGFEI8kdYlk=
knative.dev/hack v0.0.0-20201112185459-01a34c573bd8 h1:RNbZsAjhswBPtl4C5C5gEFX5/GfWIOZQxfYD9DhkHdY=
knative.dev/hack v0.0.0-20201112185459-01a34c573bd8/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
knative.dev/networking v0.0.0-20201116165202-57530ee4cbfc/go.mod h1:DCZ5pdCpaPkgvwSvgFzDXSDjZ2dByl+tMIHlXV4wvws=
knative.dev/networking v0.0.0-20201117131851-29d71950ee3d h1:MLhF77IJoVjMKTK6cNht+X4G9L1r5dJHGfLv5w07K94=
knative.dev/networking v0.0.0-20201117131851-29d71950ee3d/go.mod h1:/+3beeK3eK+igEo/0GHtqGlUXJDhSScMI4/pnHojIUc=
knative.dev/pkg v0.0.0-20201112201059-93fedf141385/go.mod h1:5vNHKNtZtzlNeNrcDoUtZIn+dma/8DjmpjfdHiwoQyM=
knative.dev/pkg v0.0.0-20201116214403-188df22c59ac/go.mod h1:4kXxEyYWdNk3pUR6/cx/ToMKG/dAJvEpDYUfV5RYHeU=
knative.dev/pkg v0.0.0-20201117020252-ab1a398f669c h1:dMBwabvusJrldjzIj4lces/96SnVgFXV7Kpv9z9fiCI=
knative.dev/pkg v0.0.0-20201117020252-ab1a398f669c/go.mod h1:4kXxEyYWdNk3pUR6/cx/ToMKG/dAJvEpDYUfV5RYHeU=
knative.dev/serving v0.19.1-0.20201117120351-3e2a380308b2 h1:D3+uDOvUfrAvlVGqqzN+nlpWub22xX/9QkbhpKTRZ9A=
knative.dev/serving v0.19.1-0.20201117120351-3e2a380308b2/go.mod h1:/Y2mRdW1VwRW0K3yqLGKZbakSK+4ihWHbs08NAO9ppE=
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=

View File

@ -124,8 +124,7 @@ func (sb *SinkBinding) Do(ctx context.Context, ps *duckv1.WithPod) {
spec.InitContainers[i].Env = append(spec.InitContainers[i].Env, corev1.EnvVar{
Name: "K_SINK",
Value: uri.String(),
})
spec.InitContainers[i].Env = append(spec.InitContainers[i].Env, corev1.EnvVar{
}, corev1.EnvVar{
Name: "K_CE_OVERRIDES",
Value: ceOverrides,
})
@ -134,8 +133,7 @@ func (sb *SinkBinding) Do(ctx context.Context, ps *duckv1.WithPod) {
spec.Containers[i].Env = append(spec.Containers[i].Env, corev1.EnvVar{
Name: "K_SINK",
Value: uri.String(),
})
spec.Containers[i].Env = append(spec.Containers[i].Env, corev1.EnvVar{
}, corev1.EnvVar{
Name: "K_CE_OVERRIDES",
Value: ceOverrides,
})

View File

@ -220,7 +220,7 @@ benchmarking jobs for each repo. To use it:
- `SERVICE_ACCOUNT_NAME`: Service account name for controlling GKE clusters
and interacting with [Mako](https://github.com/google/mako) server. It MUST
have `Kubernetes Engine Admin` and `Storage Admin` role, and be
[whitelisted](https://github.com/google/mako/blob/master/docs/ACCESS.md) by
[allowed](https://github.com/google/mako/blob/master/docs/ACCESS.md) by
Mako admin. Defaults to `mako-job`.
1. [optional] Customize root path of the benchmarks. This root folder should

View File

@ -353,13 +353,10 @@ function report_go_test() {
report="$(mktemp)"
local xml
xml="$(mktemp_with_extension "${ARTIFACTS}"/junit_XXXXXXXX xml)"
local json
json="$(mktemp_with_extension "${ARTIFACTS}"/json_XXXXXXXX json)"
echo "Running go test with args: ${go_test_args[*]}"
# TODO(chizhg): change to `--format testname`?
capture_output "${report}" gotestsum --format "${GO_TEST_VERBOSITY:-standard-verbose}" \
--junitfile "${xml}" --junitfile-testsuite-name relative --junitfile-testcase-classname relative \
--jsonfile "${json}" \
-- "${go_test_args[@]}"
local failed=$?
echo "Finished run, return code is ${failed}"
@ -517,7 +514,7 @@ function go_update_deps() {
echo "=== Update Deps for Golang"
local UPGRADE=0
local VERSION="master"
local VERSION="v9000.1" # release v9000 is so far in the future, it will always pick the default branch.
local DOMAIN="knative.dev"
while [[ $# -ne 0 ]]; do
parameter=$1

View File

@ -65,7 +65,10 @@ func NewLogger(configJSON string, levelOverride string, opts ...zap.Option) (*za
if err2 != nil {
panic(err2)
}
return enrichLoggerWithCommitID(logger.Named(fallbackLoggerName)), loggingCfg.Level
slogger := enrichLoggerWithCommitID(logger.Named(fallbackLoggerName))
slogger.Warnw("Failed to parse logging config - using default zap production config", zap.Error(err))
return slogger, loggingCfg.Level
}
func enrichLoggerWithCommitID(logger *zap.Logger) *zap.SugaredLogger {

View File

@ -60,7 +60,9 @@ const (
defaultPrometheusPort = 9090
maxPrometheusPort = 65535
minPrometheusPort = 1024
defaultPrometheusHost = "0.0.0.0"
prometheusPortEnvName = "METRICS_PROMETHEUS_PORT"
prometheusHostEnvName = "METRICS_PROMETHEUS_HOST"
)
// Metrics backend "enum".
@ -105,6 +107,10 @@ 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.
@ -240,6 +246,7 @@ 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
@ -341,6 +348,17 @@ 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

View File

@ -66,10 +66,15 @@ 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. If is ignored if metrics backend is not
// using the default 9090 value. It 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.

View File

@ -17,8 +17,8 @@ limitations under the License.
package metrics
import (
"fmt"
"net/http"
"strconv"
"sync"
prom "contrib.go.opencensus.io/exporter/prometheus"
@ -41,6 +41,7 @@ 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 {
@ -50,7 +51,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.prometheusPort)
srv := startNewPromSrv(e, config.prometheusHost, config.prometheusPort)
srv.ListenAndServe()
}()
return e,
@ -73,7 +74,7 @@ func resetCurPromSrv() {
}
}
func startNewPromSrv(e *prom.Exporter, port int) *http.Server {
func startNewPromSrv(e *prom.Exporter, host string, port int) *http.Server {
sm := http.NewServeMux()
sm.Handle("/metrics", e)
curPromSrvMux.Lock()
@ -82,7 +83,7 @@ func startNewPromSrv(e *prom.Exporter, port int) *http.Server {
curPromSrv.Close()
}
curPromSrv = &http.Server{
Addr: fmt.Sprint(":", port),
Addr: host + ":" + strconv.Itoa(port),
Handler: sm,
}
return curPromSrv

View File

@ -17,6 +17,7 @@ limitations under the License.
package network
import (
"fmt"
"net/http"
"strings"
"time"
@ -54,6 +55,16 @@ const (
// included in request metrics.
ProbeHeaderName = "K-Network-Probe"
// ProbeHeaderValue is the value of a header that can be added to
// requests to probe the knative networking layer. Requests
// with `K-Network-Probe` this value will not be passed to the user
// container or included in request metrics.
ProbeHeaderValue = "probe"
// HashHeaderName is the name of an internal header that Ingress controller
// uses to find out which version of the networking config is deployed.
HashHeaderName = "K-Network-Hash"
// Since K8s 1.8, prober requests have
// User-Agent = "kube-probe/{major-version}.{minor-version}".
KubeProbeUAPrefix = "kube-probe/"
@ -68,3 +79,19 @@ func IsKubeletProbe(r *http.Request) bool {
return strings.HasPrefix(r.Header.Get("User-Agent"), KubeProbeUAPrefix) ||
r.Header.Get(KubeletProbeHeaderName) != ""
}
// IsKProbe returns true if the request is a knatvie probe.
func IsKProbe(r *http.Request) bool {
return r.Header.Get(ProbeHeaderName) == ProbeHeaderValue
}
// ServeKProbe serve KProbe requests.
func ServeKProbe(w http.ResponseWriter, r *http.Request) {
hh := r.Header.Get(HashHeaderName)
if hh == "" {
http.Error(w, fmt.Sprintf("a probe request must contain a non-empty %q header", HashHeaderName), http.StatusBadRequest)
return
}
w.Header().Set(HashHeaderName, hh)
w.WriteHeader(http.StatusOK)
}

View File

@ -1 +0,0 @@
memory_encoder.go coverage-excluded=true

View File

@ -1,49 +0,0 @@
/*
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

View File

@ -1,90 +0,0 @@
/*
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}
}

View File

@ -1,76 +0,0 @@
// 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
}

View File

@ -1,74 +0,0 @@
// 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) }

View File

@ -1,196 +0,0 @@
// 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')
}
}

View File

@ -1,114 +0,0 @@
// 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
}

View File

@ -1,372 +0,0 @@
/*
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))
}
}
})
}
}

View File

@ -1,47 +0,0 @@
// 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)...)
}
}

View File

@ -216,9 +216,18 @@ func isExpired(expiry time.Time) bool {
// OnChanged implements Interface.
func (i *impl) OnChanged(obj interface{}) {
observers := i.GetObservers(obj)
for _, observer := range observers {
i.cb(observer)
}
}
// GetObservers implements Interface.
func (i *impl) GetObservers(obj interface{}) []types.NamespacedName {
item, err := kmeta.DeletionHandlingAccessor(obj)
if err != nil {
return
return nil
}
or := kmeta.ObjectReference(item)
@ -229,14 +238,9 @@ func (i *impl) OnChanged(obj interface{}) {
Name: or.Name,
}
i.m.Lock()
// Call the callbacks without the lock held.
var keys []types.NamespacedName
defer func(cb func(types.NamespacedName)) {
for _, key := range keys {
cb(key)
}
}(i.cb) // read i.cb with the lock held
i.m.Lock()
defer i.m.Unlock()
// Handle exact matches.
@ -274,6 +278,8 @@ func (i *impl) OnChanged(obj interface{}) {
delete(i.exact, ref)
}
}
return keys
}
// OnChanged implements Interface.

View File

@ -23,6 +23,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation"
"knative.dev/pkg/apis"
@ -71,6 +72,10 @@ type Interface interface {
// so that we are notified for appropriate object changes.
OnChanged(obj interface{})
// GetObservers returns the names of all observers for the given
// object.
GetObservers(obj interface{}) []types.NamespacedName
// OnDeletedObserver is a callback to register with the InformerFactory
// so that we are notified for deletions of a watching parent to
// remove the respective tracking.

10
vendor/modules.txt vendored
View File

@ -823,7 +823,7 @@ k8s.io/kube-openapi/pkg/util/sets
k8s.io/utils/buffer
k8s.io/utils/integer
k8s.io/utils/trace
# knative.dev/eventing v0.19.0
# knative.dev/eventing v0.19.1-0.20201117061051-47ee6e3586ca
## explicit
knative.dev/eventing/pkg/apis/config
knative.dev/eventing/pkg/apis/configs
@ -852,15 +852,15 @@ knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta1/fake
knative.dev/eventing/pkg/client/clientset/versioned/typed/messaging/v1beta1
knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1alpha2
knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1alpha2/fake
# knative.dev/hack v0.0.0-20201103151104-3d5abc3a0075
# knative.dev/hack v0.0.0-20201112185459-01a34c573bd8
## explicit
knative.dev/hack
# knative.dev/networking v0.0.0-20201103163404-b9f80f4537af
# knative.dev/networking v0.0.0-20201117131851-29d71950ee3d
## explicit
knative.dev/networking/pkg
knative.dev/networking/pkg/apis/networking
knative.dev/networking/pkg/apis/networking/v1alpha1
# knative.dev/pkg v0.0.0-20201103163404-5514ab0c1fdf
# knative.dev/pkg v0.0.0-20201117020252-ab1a398f669c
## explicit
knative.dev/pkg/apis
knative.dev/pkg/apis/duck
@ -900,7 +900,7 @@ knative.dev/pkg/tracing/config
knative.dev/pkg/tracing/propagation
knative.dev/pkg/tracing/propagation/tracecontextb3
knative.dev/pkg/tracker
# knative.dev/serving v0.19.0
# knative.dev/serving v0.19.1-0.20201117120351-3e2a380308b2
## explicit
knative.dev/serving/pkg/apis/autoscaling
knative.dev/serving/pkg/apis/autoscaling/v1alpha1