diff --git a/internal/telemetry/event/log.go b/internal/telemetry/event/log.go index 568aa1b923..8d0a046e78 100644 --- a/internal/telemetry/event/log.go +++ b/internal/telemetry/event/log.go @@ -7,6 +7,7 @@ package event import ( "context" "errors" + "fmt" ) // Log sends a log event with the supplied tag list to the exporter. @@ -57,3 +58,11 @@ func Error(ctx context.Context, message string, err error, tags ...Tag) { } dispatch(ctx, makeEvent(LogType, sTags{Msg.Of(message), Err.Of(err)}, tags)) } + +// Debugf sends a log event with the supplied message to the exporter. +// This is intended only for temporary debugging lines, and usage should not +// normally be checked in, preffering structured log events for things +// that have to be used in production. +func Debugf(ctx context.Context, message string, args ...interface{}) { + dispatch(ctx, makeEvent(LogType, sTags{Msg.Of(fmt.Sprintf(message, args...))}, nil)) +} diff --git a/internal/telemetry/export/eventtest/eventtest.go b/internal/telemetry/export/eventtest/eventtest.go new file mode 100644 index 0000000000..ae92166d7a --- /dev/null +++ b/internal/telemetry/export/eventtest/eventtest.go @@ -0,0 +1,62 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package eventtest supports logging events to a test. +// You can use NewContext to create a context that knows how to deliver +// telemetry events back to the test. +// You must use this context or a derived one anywhere you want telemetry to be +// correctly routed back to the test it was constructed with. +// Any events delivered to a background context will be dropped. +// +// Importing this package will cause it to register a new global telemetry +// exporter that understands the special contexts returned by NewContext. +// This means you should not import this package if you are not going to call +// NewContext. +package eventtest + +import ( + "bytes" + "context" + "sync" + "testing" + + "golang.org/x/tools/internal/telemetry/event" + "golang.org/x/tools/internal/telemetry/export" +) + +func init() { + e := &testExporter{buffer: &bytes.Buffer{}} + e.logger = export.LogWriter(e.buffer, false) + + event.SetExporter(export.Spans(e.processEvent)) +} + +type testingKeyType int + +const testingKey = testingKeyType(0) + +// NewContext returns a context you should use for the active test. +func NewContext(ctx context.Context, t testing.TB) context.Context { + return context.WithValue(ctx, testingKey, t) +} + +type testExporter struct { + mu sync.Mutex + buffer *bytes.Buffer + logger event.Exporter +} + +func (w *testExporter) processEvent(ctx context.Context, ev event.Event, tagMap event.TagMap) context.Context { + w.mu.Lock() + defer w.mu.Unlock() + // build our log message in buffer + result := w.logger(ctx, ev, tagMap) + v := ctx.Value(testingKey) + // get the testing.TB + if w.buffer.Len() > 0 && v != nil { + v.(testing.TB).Log(w.buffer) + } + w.buffer.Truncate(0) + return result +}