Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2a80c63 authored by Liz Kammer's avatar Liz Kammer
Browse files

Add non-zero exit + error message to soong metrics

Improves some error messages that would have given little/no information

Bug: 254650145
Test: relevant unit tests
Test: Induce errors and check metrics proto
Change-Id: Ife6116af74af6e62c2f8ae8774e53c28178fb8d0
parent 706d35fe
Loading
Loading
Loading
Loading
+10 −10
Original line number Original line Diff line number Diff line
@@ -132,8 +132,13 @@ func main() {
		build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"),
		build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"),
		build.OsEnvironment().IsEnvTrue("SOONG_UI_ANSI_OUTPUT"))
		build.OsEnvironment().IsEnvTrue("SOONG_UI_ANSI_OUTPUT"))


	// Create and start a new metric record.
	met := metrics.New()
	met.SetBuildDateTime(buildStarted)
	met.SetBuildCommand(os.Args)

	// Attach a new logger instance to the terminal output.
	// Attach a new logger instance to the terminal output.
	log := logger.New(output)
	log := logger.NewWithMetrics(output, met)
	defer log.Cleanup()
	defer log.Cleanup()


	// Create a context to simplify the program termination process.
	// Create a context to simplify the program termination process.
@@ -144,11 +149,6 @@ func main() {
	trace := tracer.New(log)
	trace := tracer.New(log)
	defer trace.Close()
	defer trace.Close()


	// Create and start a new metric record.
	met := metrics.New()
	met.SetBuildDateTime(buildStarted)
	met.SetBuildCommand(os.Args)

	// Create a new Status instance, which manages action counts and event output channels.
	// Create a new Status instance, which manages action counts and event output channels.
	stat := &status.Status{}
	stat := &status.Status{}
	defer stat.Finish()
	defer stat.Finish()
@@ -281,7 +281,7 @@ func dumpVar(ctx build.Context, config build.Config, args []string, _ string) {


	if flags.NArg() != 1 {
	if flags.NArg() != 1 {
		flags.Usage()
		flags.Usage()
		os.Exit(1)
		ctx.Fatalf("Invalid usage")
	}
	}


	varName := flags.Arg(0)
	varName := flags.Arg(0)
@@ -341,7 +341,7 @@ func dumpVars(ctx build.Context, config build.Config, args []string, _ string) {


	if flags.NArg() != 0 {
	if flags.NArg() != 0 {
		flags.Usage()
		flags.Usage()
		os.Exit(1)
		ctx.Fatalf("Invalid usage")
	}
	}


	vars := strings.Fields(*varsStr)
	vars := strings.Fields(*varsStr)
@@ -502,7 +502,7 @@ func runMake(ctx build.Context, config build.Config, _ []string, logsDir string)
		fmt.Fprintln(writer, "!")
		fmt.Fprintln(writer, "!")
		fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
		fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
		fmt.Fprintln(writer, "")
		fmt.Fprintln(writer, "")
		ctx.Fatal("done")
		ctx.Fatal("Invalid argument")
	}
	}


	if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
	if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
@@ -513,7 +513,7 @@ func runMake(ctx build.Context, config build.Config, _ []string, logsDir string)
		fmt.Fprintln(writer, "!")
		fmt.Fprintln(writer, "!")
		fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
		fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
		fmt.Fprintln(writer, "")
		fmt.Fprintln(writer, "")
		ctx.Fatal("done")
		ctx.Fatal("Invalid environment")
	}
	}


	build.Build(ctx, config)
	build.Build(ctx, config)
+2 −2
Original line number Original line Diff line number Diff line
@@ -48,7 +48,7 @@ func (c ContextImpl) BeginTrace(name, desc string) {
		c.Tracer.Begin(desc, c.Thread)
		c.Tracer.Begin(desc, c.Thread)
	}
	}
	if c.Metrics != nil {
	if c.Metrics != nil {
		c.Metrics.EventTracer.Begin(name, desc, c.Thread)
		c.Metrics.EventTracer.Begin(name, desc)
	}
	}
}
}


@@ -58,7 +58,7 @@ func (c ContextImpl) EndTrace() {
		c.Tracer.End(c.Thread)
		c.Tracer.End(c.Thread)
	}
	}
	if c.Metrics != nil {
	if c.Metrics != nil {
		c.Metrics.SetTimeMetrics(c.Metrics.EventTracer.End(c.Thread))
		c.Metrics.SetTimeMetrics(c.Metrics.EventTracer.End())
	}
	}
}
}


+3 −0
Original line number Original line Diff line number Diff line
@@ -25,4 +25,7 @@ bootstrap_go_package {
    testSrcs: [
    testSrcs: [
        "logger_test.go",
        "logger_test.go",
    ],
    ],
    deps: [
        "soong-ui-metrics",
    ],
}
}
+44 −21
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@
package logger
package logger


import (
import (
	"android/soong/ui/metrics"
	"errors"
	"errors"
	"fmt"
	"fmt"
	"io"
	"io"
@@ -72,8 +73,8 @@ type Logger interface {
	Output(calldepth int, str string) error
	Output(calldepth int, str string) error
}
}


// fatalLog is the type used when Fatal[f|ln]
// fatalError is the type used when Fatal[f|ln]
type fatalLog struct {
type fatalError struct {
	error
	error
}
}


@@ -127,7 +128,7 @@ func Recover(fn func(err error)) {


	if p == nil {
	if p == nil {
		return
		return
	} else if log, ok := p.(fatalLog); ok {
	} else if log, ok := p.(fatalError); ok {
		fn(error(log))
		fn(error(log))
	} else {
	} else {
		panic(p)
		panic(p)
@@ -141,6 +142,7 @@ type stdLogger struct {
	fileLogger *log.Logger
	fileLogger *log.Logger
	mutex      sync.Mutex
	mutex      sync.Mutex
	file       *os.File
	file       *os.File
	metrics    *metrics.Metrics
}
}


var _ Logger = &stdLogger{}
var _ Logger = &stdLogger{}
@@ -149,9 +151,14 @@ var _ Logger = &stdLogger{}
// os.Stderr, but it may be a buffer for tests, or a separate log file if
// os.Stderr, but it may be a buffer for tests, or a separate log file if
// the user doesn't need to see the output.
// the user doesn't need to see the output.
func New(out io.Writer) *stdLogger {
func New(out io.Writer) *stdLogger {
	return NewWithMetrics(out, nil)
}

func NewWithMetrics(out io.Writer, m *metrics.Metrics) *stdLogger {
	return &stdLogger{
	return &stdLogger{
		stderr:     log.New(out, "", log.Ltime),
		stderr:     log.New(out, "", log.Ltime),
		fileLogger: log.New(ioutil.Discard, "", log.Ldate|log.Lmicroseconds|log.Llongfile),
		fileLogger: log.New(ioutil.Discard, "", log.Ldate|log.Lmicroseconds|log.Llongfile),
		metrics:    m,
	}
	}
}
}


@@ -201,7 +208,7 @@ func (s *stdLogger) Cleanup() {
	fatal := false
	fatal := false
	p := recover()
	p := recover()


	if _, ok := p.(fatalLog); ok {
	if _, ok := p.(fatalError); ok {
		fatal = true
		fatal = true
		p = nil
		p = nil
	} else if p != nil {
	} else if p != nil {
@@ -217,40 +224,56 @@ func (s *stdLogger) Cleanup() {
	}
	}
}
}


type verbosityLevel int

const (
	verboseLog verbosityLevel = iota
	infoLog
	fatalLog
	panicLog
)

// Output writes string to both stderr and the file log.
// Output writes string to both stderr and the file log.
func (s *stdLogger) Output(calldepth int, str string) error {
func (s *stdLogger) Output(calldepth int, str string) error {
	return s.output(calldepth, str, infoLog)
}

// output writes string to stderr, the file log, and if fatal or panic, to metrics.
func (s *stdLogger) output(calldepth int, str string, level verbosityLevel) error {
	if level != verboseLog || s.verbose {
		s.stderr.Output(calldepth+1, str)
		s.stderr.Output(calldepth+1, str)
	}
	if level >= fatalLog {
		s.metrics.SetFatalOrPanicMessage(str)
	}
	return s.fileLogger.Output(calldepth+1, str)
	return s.fileLogger.Output(calldepth+1, str)
}
}


// VerboseOutput is equivalent to Output, but only goes to the file log
// VerboseOutput is equivalent to Output, but only goes to the file log
// unless SetVerbose(true) has been called.
// unless SetVerbose(true) has been called.
func (s *stdLogger) VerboseOutput(calldepth int, str string) error {
func (s *stdLogger) VerboseOutput(calldepth int, str string) error {
	if s.verbose {
	return s.output(calldepth, str, verboseLog)
		s.stderr.Output(calldepth+1, str)
	}
	return s.fileLogger.Output(calldepth+1, str)
}
}


// Print prints to both stderr and the file log.
// Print prints to both stderr and the file log.
// Arguments are handled in the manner of fmt.Print.
// Arguments are handled in the manner of fmt.Print.
func (s *stdLogger) Print(v ...interface{}) {
func (s *stdLogger) Print(v ...interface{}) {
	output := fmt.Sprint(v...)
	output := fmt.Sprint(v...)
	s.Output(2, output)
	s.output(2, output, infoLog)
}
}


// Printf prints to both stderr and the file log.
// Printf prints to both stderr and the file log.
// Arguments are handled in the manner of fmt.Printf.
// Arguments are handled in the manner of fmt.Printf.
func (s *stdLogger) Printf(format string, v ...interface{}) {
func (s *stdLogger) Printf(format string, v ...interface{}) {
	output := fmt.Sprintf(format, v...)
	output := fmt.Sprintf(format, v...)
	s.Output(2, output)
	s.output(2, output, infoLog)
}
}


// Println prints to both stderr and the file log.
// Println prints to both stderr and the file log.
// Arguments are handled in the manner of fmt.Println.
// Arguments are handled in the manner of fmt.Println.
func (s *stdLogger) Println(v ...interface{}) {
func (s *stdLogger) Println(v ...interface{}) {
	output := fmt.Sprintln(v...)
	output := fmt.Sprintln(v...)
	s.Output(2, output)
	s.output(2, output, infoLog)
}
}


// Verbose is equivalent to Print, but only goes to the file log unless
// Verbose is equivalent to Print, but only goes to the file log unless
@@ -278,43 +301,43 @@ func (s *stdLogger) Verboseln(v ...interface{}) {
// Cleanup will convert to a os.Exit(1).
// Cleanup will convert to a os.Exit(1).
func (s *stdLogger) Fatal(v ...interface{}) {
func (s *stdLogger) Fatal(v ...interface{}) {
	output := fmt.Sprint(v...)
	output := fmt.Sprint(v...)
	s.Output(2, output)
	s.output(2, output, fatalLog)
	panic(fatalLog{errors.New(output)})
	panic(fatalError{errors.New(output)})
}
}


// Fatalf is equivalent to Printf() followed by a call to panic() that
// Fatalf is equivalent to Printf() followed by a call to panic() that
// Cleanup will convert to a os.Exit(1).
// Cleanup will convert to a os.Exit(1).
func (s *stdLogger) Fatalf(format string, v ...interface{}) {
func (s *stdLogger) Fatalf(format string, v ...interface{}) {
	output := fmt.Sprintf(format, v...)
	output := fmt.Sprintf(format, v...)
	s.Output(2, output)
	s.output(2, output, fatalLog)
	panic(fatalLog{errors.New(output)})
	panic(fatalError{errors.New(output)})
}
}


// Fatalln is equivalent to Println() followed by a call to panic() that
// Fatalln is equivalent to Println() followed by a call to panic() that
// Cleanup will convert to a os.Exit(1).
// Cleanup will convert to a os.Exit(1).
func (s *stdLogger) Fatalln(v ...interface{}) {
func (s *stdLogger) Fatalln(v ...interface{}) {
	output := fmt.Sprintln(v...)
	output := fmt.Sprintln(v...)
	s.Output(2, output)
	s.output(2, output, fatalLog)
	panic(fatalLog{errors.New(output)})
	panic(fatalError{errors.New(output)})
}
}


// Panic is equivalent to Print() followed by a call to panic().
// Panic is equivalent to Print() followed by a call to panic().
func (s *stdLogger) Panic(v ...interface{}) {
func (s *stdLogger) Panic(v ...interface{}) {
	output := fmt.Sprint(v...)
	output := fmt.Sprint(v...)
	s.Output(2, output)
	s.output(2, output, panicLog)
	panic(output)
	panic(output)
}
}


// Panicf is equivalent to Printf() followed by a call to panic().
// Panicf is equivalent to Printf() followed by a call to panic().
func (s *stdLogger) Panicf(format string, v ...interface{}) {
func (s *stdLogger) Panicf(format string, v ...interface{}) {
	output := fmt.Sprintf(format, v...)
	output := fmt.Sprintf(format, v...)
	s.Output(2, output)
	s.output(2, output, panicLog)
	panic(output)
	panic(output)
}
}


// Panicln is equivalent to Println() followed by a call to panic().
// Panicln is equivalent to Println() followed by a call to panic().
func (s *stdLogger) Panicln(v ...interface{}) {
func (s *stdLogger) Panicln(v ...interface{}) {
	output := fmt.Sprintln(v...)
	output := fmt.Sprintln(v...)
	s.Output(2, output)
	s.output(2, output, panicLog)
	panic(output)
	panic(output)
}
}
+0 −1
Original line number Original line Diff line number Diff line
@@ -25,7 +25,6 @@ bootstrap_go_package {
        "soong-ui-metrics_upload_proto",
        "soong-ui-metrics_upload_proto",
        "soong-ui-metrics_proto",
        "soong-ui-metrics_proto",
        "soong-ui-mk_metrics_proto",
        "soong-ui-mk_metrics_proto",
        "soong-ui-tracer",
        "soong-shared",
        "soong-shared",
    ],
    ],
    srcs: [
    srcs: [
Loading