1// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package export
6
7import (
8	"context"
9	"fmt"
10	"io"
11	"sync"
12
13	"golang.org/x/tools/internal/event"
14	"golang.org/x/tools/internal/event/core"
15	"golang.org/x/tools/internal/event/label"
16)
17
18// LogWriter returns an Exporter that logs events to the supplied writer.
19// If onlyErrors is true it does not log any event that did not have an
20// associated error.
21// It ignores all telemetry other than log events.
22func LogWriter(w io.Writer, onlyErrors bool) event.Exporter {
23	lw := &logWriter{writer: w, onlyErrors: onlyErrors}
24	return lw.ProcessEvent
25}
26
27type logWriter struct {
28	mu         sync.Mutex
29	printer    Printer
30	writer     io.Writer
31	onlyErrors bool
32}
33
34func (w *logWriter) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context {
35	switch {
36	case event.IsLog(ev):
37		if w.onlyErrors && !event.IsError(ev) {
38			return ctx
39		}
40		w.mu.Lock()
41		defer w.mu.Unlock()
42		w.printer.WriteEvent(w.writer, ev, lm)
43
44	case event.IsStart(ev):
45		if span := GetSpan(ctx); span != nil {
46			fmt.Fprintf(w.writer, "start: %v %v", span.Name, span.ID)
47			if span.ParentID.IsValid() {
48				fmt.Fprintf(w.writer, "[%v]", span.ParentID)
49			}
50		}
51	case event.IsEnd(ev):
52		if span := GetSpan(ctx); span != nil {
53			fmt.Fprintf(w.writer, "finish: %v %v", span.Name, span.ID)
54		}
55	}
56	return ctx
57}
58