Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ require (
github.com/spf13/pflag v1.0.6
github.com/tsenart/vegeta/v12 v12.12.0
go.opencensus.io v0.24.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0
go.opentelemetry.io/contrib/instrumentation/runtime v0.62.0
go.opentelemetry.io/otel v1.37.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.37.0
Expand Down Expand Up @@ -61,6 +62,7 @@ require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lSh
github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
Expand Down Expand Up @@ -363,6 +365,8 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
go.opentelemetry.io/contrib/instrumentation/runtime v0.62.0 h1:ZIt0ya9/y4WyRIzfLC8hQRRsWg0J9M9GyaGtIMiElZI=
go.opentelemetry.io/contrib/instrumentation/runtime v0.62.0/go.mod h1:F1aJ9VuiKWOlWwKdTYDUp1aoS0HzQxg38/VLxKmhm5U=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
Expand Down
66 changes: 5 additions & 61 deletions test/logging/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,66 +24,29 @@ import (
"flag"
"os"
"strconv"
"strings"
"sync"
"time"

"github.com/davecgh/go-spew/spew"
"go.opencensus.io/stats/view"
"go.opencensus.io/trace"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"k8s.io/klog/v2"
)

const (
// 1 second was chosen arbitrarily
metricViewReportingPeriod = 1 * time.Second

// prefix attached to metric name that indicates to the
// ExportSpan method that span needs to be emitted.
emitableSpanNamePrefix = "emitspan-"
)
var tracer = otel.GetTracerProvider().Tracer("knative.dev/pkg/test/logging")

// FormatLogger is a printf style function for logging in tests.
type FormatLogger func(template string, args ...interface{})

var exporter *zapMetricExporter

// zapMetricExporter is a stats and trace exporter that logs the
// exported data to the provided (probably test specific) zap logger.
// It conforms to the view.Exporter and trace.Exporter interfaces.
type zapMetricExporter struct {
logger *zap.SugaredLogger
}

// ExportView will emit the view data vd (i.e. the stats that have been
// recorded) to the zap logger.
func (e *zapMetricExporter) ExportView(vd *view.Data) {
// We are not currently consuming these metrics, so for now we'll juse
// dump the view.Data object as is.
e.logger.Debug(spew.Sprint(vd))
}

// GetEmitableSpan starts and returns a trace.Span with a name that
// is used by the ExportSpan method to emit the span.
//
//nolint:spancheck
func GetEmitableSpan(ctx context.Context, metricName string) *trace.Span {
_, span := trace.StartSpan(ctx, emitableSpanNamePrefix+metricName)
func GetEmitableSpan(ctx context.Context, metricName string) trace.Span {
_, span := tracer.Start(ctx, metricName)
return span
}

// ExportSpan will emit the trace data to the zap logger. The span is emitted
// only if the metric name is prefix with emitableSpanNamePrefix constant.
func (e *zapMetricExporter) ExportSpan(vd *trace.SpanData) {
if strings.HasPrefix(vd.Name, emitableSpanNamePrefix) {
duration := vd.EndTime.Sub(vd.StartTime)
// We will start the log entry with `metric` to identify it as a metric for parsing
e.logger.Infof("metric %s %d %d %s", vd.Name[len(emitableSpanNamePrefix):], vd.StartTime.UnixNano(), vd.EndTime.UnixNano(), duration)
}
}

const (
logrZapDebugLevel = 3
)
Expand All @@ -103,25 +66,6 @@ func zapLevelFromLogrLevel(logrLevel int) zapcore.Level {
return l
}

// InitializeMetricExporter initializes the metric exporter logger
func InitializeMetricExporter(context string) {
// If there was a previously registered exporter, unregister it so we only emit
// the metrics in the current context.
if exporter != nil {
view.UnregisterExporter(exporter)
trace.UnregisterExporter(exporter)
}

l := logger.Named(context).Sugar()

exporter = &zapMetricExporter{logger: l}
view.RegisterExporter(exporter)
trace.RegisterExporter(exporter)

view.SetReportingPeriod(metricViewReportingPeriod)
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
}

func printFlags() {
var flagList []interface{}
flag.CommandLine.VisitAll(func(f *flag.Flag) {
Expand Down
50 changes: 12 additions & 38 deletions test/spoof/spoof.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,18 @@ import (
"k8s.io/client-go/kubernetes"
"knative.dev/pkg/test/ingress"
"knative.dev/pkg/test/logging"
"knative.dev/pkg/test/zipkin"
"knative.dev/pkg/tracing/propagation/tracecontextb3"

"go.opencensus.io/plugin/ochttp"
"go.opencensus.io/trace"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
)

var tracer trace.Tracer

func init() {
tracer = otel.GetTracerProvider().Tracer("knative.dev/pkg/test/spoof")
}

// Response is a stripped down subset of http.Response. The is primarily useful
// for ResponseCheckers to inspect the response body without consuming it.
// Notably, Body is a byte slice instead of an io.ReadCloser.
Expand Down Expand Up @@ -125,11 +130,7 @@ func New(
transport = opt(transport)
}

// Enable Zipkin tracing
roundTripper := &ochttp.Transport{
Base: transport,
Propagation: tracecontextb3.TraceContextB3Egress,
}
roundTripper := otelhttp.NewTransport(transport)

sc := &SpoofingClient{
Client: &http.Client{Transport: roundTripper},
Expand All @@ -154,7 +155,7 @@ func ResolveEndpoint(ctx context.Context, kubeClientset kubernetes.Interface, do

// Do dispatches to the underlying http.Client.Do, spoofing domains as needed
// and transforming the http.Response into a spoof.Response.
// Each response is augmented with "ZipkinTraceID" header that identifies the zipkin trace corresponding to the request.
// Each response is augmented with "X-Trace-Id" header that identifies the trace corresponding to the request.
func (sc *SpoofingClient) Do(req *http.Request, errorRetryCheckers ...interface{}) (*Response, error) {
return sc.Poll(req, func(*Response) (bool, error) { return true, nil }, errorRetryCheckers...)
}
Expand All @@ -170,7 +171,7 @@ func (sc *SpoofingClient) Poll(req *http.Request, inState ResponseChecker, check
var resp *Response
err := wait.PollUntilContextTimeout(context.Background(), sc.RequestInterval, sc.RequestTimeout, true, func(ctx context.Context) (bool, error) {
// Starting span to capture zipkin trace.
traceContext, span := trace.StartSpan(req.Context(), "SpoofingClient-Trace")
traceContext, span := tracer.Start(req.Context(), "SpoofingClient-Trace")
defer span.End()
rawResp, err := sc.Client.Do(req.WithContext(traceContext))
if err != nil {
Expand All @@ -192,7 +193,6 @@ func (sc *SpoofingClient) Poll(req *http.Request, inState ResponseChecker, check
if err != nil {
return true, err
}
rawResp.Header.Add(zipkin.ZipkinTraceIDHeader, span.SpanContext().TraceID.String())

resp = &Response{
Status: rawResp.Status,
Expand All @@ -216,11 +216,6 @@ func (sc *SpoofingClient) Poll(req *http.Request, inState ResponseChecker, check

return inState(resp)
})

if resp != nil {
sc.logZipkinTrace(resp)
}

if err != nil {
return resp, fmt.Errorf("response: %s did not pass checks: %w", resp, err)
}
Expand Down Expand Up @@ -263,27 +258,6 @@ func DefaultResponseRetryChecker(resp *Response) (bool, error) {
return false, nil
}

// logZipkinTrace provides support to log Zipkin Trace for param: spoofResponse
// We only log Zipkin trace for HTTP server errors i.e for HTTP status codes between 500 to 600
func (sc *SpoofingClient) logZipkinTrace(spoofResp *Response) {
if !zipkin.IsTracingEnabled() || spoofResp.StatusCode < http.StatusInternalServerError || spoofResp.StatusCode >= 600 {
return
}

traceID := spoofResp.Header.Get(zipkin.ZipkinTraceIDHeader)
sc.Logf("Logging Zipkin Trace for: %s", traceID)

json, err := zipkin.JSONTrace(traceID /* We don't know the expected number of spans */, -1, 5*time.Second)
if err != nil {
var errTimeout *zipkin.TimeoutError
if !errors.As(err, &errTimeout) {
sc.Logf("Error getting zipkin trace: %v", err)
}
}

sc.Logf("%s", json)
}

func (sc *SpoofingClient) WaitForEndpointState(
ctx context.Context,
url *url.URL,
Expand Down
Empty file.
19 changes: 19 additions & 0 deletions vendor/github.com/felixge/httpsnoop/LICENSE.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions vendor/github.com/felixge/httpsnoop/Makefile

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

95 changes: 95 additions & 0 deletions vendor/github.com/felixge/httpsnoop/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading