]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/trace: merge testdata debugging tools into the trace tool
authorMichael Anthony Knyszek <mknyszek@google.com>
Fri, 21 Jun 2024 15:32:29 +0000 (15:32 +0000)
committerGopher Robot <gobot@golang.org>
Tue, 23 Jul 2024 14:57:42 +0000 (14:57 +0000)
Currently internal/trace/testdata contains three debugging tools which
were written early in the trace rewrite for debugging. Two of these are
completely redundant with go tool trace -d=1 and go tool trace -d=2. The
only remaining one landed in the last cycle and could easily also be
another debug mode.

This change thus merges gotraceeventstats into go tool trace as a new
debug mode, and updates the debug mode flag (-d) to accept a string,
giving each mode a more descriptive name.

Change-Id: I170f30440691b81de846b4e247deb3d0982fc205
Reviewed-on: https://go-review.googlesource.com/c/go/+/593975
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>

src/cmd/trace/main.go
src/internal/trace/raw/event.go
src/internal/trace/testdata/cmd/gotraceeventstats/main.go [deleted file]
src/internal/trace/testdata/cmd/gotraceraw/main.go [deleted file]
src/internal/trace/testdata/cmd/gotracevalidate/main.go [deleted file]

index d51ee5816456bf9a1e120e653b987b17e9f9bda8..075212eacb1490ef656ed04deb3ef276ba376d67 100644 (file)
@@ -7,9 +7,11 @@ package main
 import (
        "cmd/internal/browser"
        "cmd/internal/telemetry/counter"
+       "cmp"
        "flag"
        "fmt"
        "internal/trace"
+       "internal/trace/event"
        "internal/trace/raw"
        "internal/trace/traceviewer"
        "io"
@@ -18,7 +20,9 @@ import (
        "net/http"
        _ "net/http/pprof" // Required to use pprof
        "os"
+       "slices"
        "sync/atomic"
+       "text/tabwriter"
        "time"
 )
 
@@ -45,7 +49,7 @@ Supported profile types are:
 Flags:
        -http=addr: HTTP service address (e.g., ':6060')
        -pprof=type: print a pprof-like profile instead
-       -d=int: print debug info such as parsed events (1 for high-level, 2 for low-level)
+       -d=mode: print debug info and exit (modes: wire, parsed, footprint)
 
 Note that while the various profiles available when launching
 'go tool trace' work on every browser, the trace viewer itself
@@ -56,7 +60,7 @@ and is only actively tested on that browser.
 var (
        httpFlag  = flag.String("http", "localhost:0", "HTTP service address (e.g., ':6060')")
        pprofFlag = flag.String("pprof", "", "print a pprof-like profile instead")
-       debugFlag = flag.Int("d", 0, "print debug information (1 for basic debug info, 2 for lower-level info)")
+       debugFlag = flag.String("d", "", "print debug info and exit (modes: wire, parsed, footprint)")
 
        // The binary file name, left here for serveSVGProfile.
        programBinary string
@@ -128,11 +132,17 @@ func main() {
        }
 
        // Debug flags.
-       switch *debugFlag {
-       case 1:
-               logAndDie(debugProcessedEvents(tracef))
-       case 2:
-               logAndDie(debugRawEvents(tracef))
+       if *debugFlag != "" {
+               switch *debugFlag {
+               case "parsed":
+                       logAndDie(debugProcessedEvents(tracef))
+               case "wire":
+                       logAndDie(debugRawEvents(tracef))
+               case "footprint":
+                       logAndDie(debugEventsFootprint(tracef))
+               default:
+                       logAndDie(fmt.Errorf("invalid debug mode %s, want one of: parsed, wire, footprint", *debugFlag))
+               }
        }
 
        ln, err := net.Listen("tcp", *httpFlag)
@@ -355,6 +365,58 @@ func debugRawEvents(trc io.Reader) error {
        }
 }
 
+func debugEventsFootprint(trc io.Reader) error {
+       cr := countingReader{r: trc}
+       tr, err := raw.NewReader(&cr)
+       if err != nil {
+               return err
+       }
+       type eventStats struct {
+               typ   event.Type
+               count int
+               bytes int
+       }
+       var stats [256]eventStats
+       for i := range stats {
+               stats[i].typ = event.Type(i)
+       }
+       eventsRead := 0
+       for {
+               e, err := tr.ReadEvent()
+               if err == io.EOF {
+                       break
+               }
+               if err != nil {
+                       return err
+               }
+               s := &stats[e.Ev]
+               s.count++
+               s.bytes += e.EncodedSize()
+               eventsRead++
+       }
+       slices.SortFunc(stats[:], func(a, b eventStats) int {
+               return cmp.Compare(b.bytes, a.bytes)
+       })
+       specs := tr.Version().Specs()
+       w := tabwriter.NewWriter(os.Stdout, 3, 8, 2, ' ', 0)
+       fmt.Fprintf(w, "Event\tBytes\t%%\tCount\t%%\n")
+       fmt.Fprintf(w, "-\t-\t-\t-\t-\n")
+       for i := range stats {
+               stat := &stats[i]
+               name := ""
+               if int(stat.typ) >= len(specs) {
+                       name = fmt.Sprintf("<unknown (%d)>", stat.typ)
+               } else {
+                       name = specs[stat.typ].Name
+               }
+               bytesPct := float64(stat.bytes) / float64(cr.bytesRead.Load()) * 100
+               countPct := float64(stat.count) / float64(eventsRead) * 100
+               fmt.Fprintf(w, "%s\t%d\t%.2f%%\t%d\t%.2f%%\n", name, stat.bytes, bytesPct, stat.count, countPct)
+       }
+       w.Flush()
+       return nil
+}
+
 type countingReader struct {
        r         io.Reader
        bytesRead atomic.Int64
index 4766fbe563de90ac01cc1d46be87bf3c670782fb..e163a2c6ef820b546e86e9b2de427b7469339d97 100644 (file)
@@ -5,6 +5,7 @@
 package raw
 
 import (
+       "encoding/binary"
        "strconv"
        "strings"
 
@@ -58,3 +59,18 @@ func (e *Event) String() string {
        }
        return s.String()
 }
+
+// EncodedSize returns the canonical encoded size of an event.
+func (e *Event) EncodedSize() int {
+       size := 1
+       var buf [binary.MaxVarintLen64]byte
+       for _, arg := range e.Args {
+               size += binary.PutUvarint(buf[:], arg)
+       }
+       spec := e.Version.Specs()[e.Ev]
+       if spec.HasData {
+               size += binary.PutUvarint(buf[:], uint64(len(e.Data)))
+               size += len(e.Data)
+       }
+       return size
+}
diff --git a/src/internal/trace/testdata/cmd/gotraceeventstats/main.go b/src/internal/trace/testdata/cmd/gotraceeventstats/main.go
deleted file mode 100644 (file)
index d2379da..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2023 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 main
-
-import (
-       "cmp"
-       "encoding/binary"
-       "flag"
-       "fmt"
-       "io"
-       "log"
-       "os"
-       "slices"
-       "text/tabwriter"
-
-       "internal/trace/event"
-       "internal/trace/raw"
-)
-
-func init() {
-       flag.Usage = func() {
-               fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [mode]\n", os.Args[0])
-               fmt.Fprintf(flag.CommandLine.Output(), "\n")
-               fmt.Fprintf(flag.CommandLine.Output(), "Accepts a trace at stdin.\n")
-               fmt.Fprintf(flag.CommandLine.Output(), "\n")
-               fmt.Fprintf(flag.CommandLine.Output(), "Supported modes:")
-               fmt.Fprintf(flag.CommandLine.Output(), "\n")
-               fmt.Fprintf(flag.CommandLine.Output(), "* size  - dumps size stats\n")
-               fmt.Fprintf(flag.CommandLine.Output(), "\n")
-               flag.PrintDefaults()
-       }
-       log.SetFlags(0)
-}
-
-func main() {
-       log.SetPrefix("")
-       flag.Parse()
-
-       if flag.NArg() != 1 {
-               log.Print("missing mode argument")
-               flag.Usage()
-               os.Exit(1)
-       }
-       var err error
-       switch mode := flag.Arg(0); mode {
-       case "size":
-               err = printSizeStats(os.Stdin)
-       default:
-               log.Printf("unknown mode %q", mode)
-               flag.Usage()
-               os.Exit(1)
-       }
-       if err != nil {
-               log.Fatalf("error: %v", err)
-               os.Exit(1)
-       }
-}
-
-func printSizeStats(r io.Reader) error {
-       cr := countingReader{Reader: r}
-       tr, err := raw.NewReader(&cr)
-       if err != nil {
-               return err
-       }
-       type eventStats struct {
-               typ   event.Type
-               count int
-               bytes int
-       }
-       var stats [256]eventStats
-       for i := range stats {
-               stats[i].typ = event.Type(i)
-       }
-       eventsRead := 0
-       for {
-               e, err := tr.ReadEvent()
-               if err == io.EOF {
-                       break
-               }
-               if err != nil {
-                       return err
-               }
-               s := &stats[e.Ev]
-               s.count++
-               s.bytes += encodedSize(&e)
-               eventsRead++
-       }
-       slices.SortFunc(stats[:], func(a, b eventStats) int {
-               return cmp.Compare(b.bytes, a.bytes)
-       })
-       specs := tr.Version().Specs()
-       w := tabwriter.NewWriter(os.Stdout, 3, 8, 2, ' ', 0)
-       fmt.Fprintf(w, "Event\tBytes\t%%\tCount\t%%\n")
-       fmt.Fprintf(w, "-\t-\t-\t-\t-\n")
-       for i := range stats {
-               stat := &stats[i]
-               name := ""
-               if int(stat.typ) >= len(specs) {
-                       name = fmt.Sprintf("<unknown (%d)>", stat.typ)
-               } else {
-                       name = specs[stat.typ].Name
-               }
-               bytesPct := float64(stat.bytes) / float64(cr.bytesRead) * 100
-               countPct := float64(stat.count) / float64(eventsRead) * 100
-               fmt.Fprintf(w, "%s\t%d\t%.2f%%\t%d\t%.2f%%\n", name, stat.bytes, bytesPct, stat.count, countPct)
-       }
-       w.Flush()
-       return nil
-}
-
-func encodedSize(e *raw.Event) int {
-       size := 1
-       var buf [binary.MaxVarintLen64]byte
-       for _, arg := range e.Args {
-               size += binary.PutUvarint(buf[:], arg)
-       }
-       spec := e.Version.Specs()[e.Ev]
-       if spec.HasData {
-               size += binary.PutUvarint(buf[:], uint64(len(e.Data)))
-               size += len(e.Data)
-       }
-       return size
-}
-
-type countingReader struct {
-       io.Reader
-       bytesRead int
-}
-
-func (r *countingReader) Read(b []byte) (int, error) {
-       n, err := r.Reader.Read(b)
-       r.bytesRead += n
-       return n, err
-}
diff --git a/src/internal/trace/testdata/cmd/gotraceraw/main.go b/src/internal/trace/testdata/cmd/gotraceraw/main.go
deleted file mode 100644 (file)
index ec4ebf2..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2023 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 main
-
-import (
-       "flag"
-       "fmt"
-       "io"
-       "log"
-       "os"
-
-       "internal/trace/raw"
-       "internal/trace/version"
-)
-
-func init() {
-       flag.Usage = func() {
-               fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [mode]\n", os.Args[0])
-               fmt.Fprintf(flag.CommandLine.Output(), "\n")
-               fmt.Fprintf(flag.CommandLine.Output(), "Supported modes:")
-               fmt.Fprintf(flag.CommandLine.Output(), "\n")
-               fmt.Fprintf(flag.CommandLine.Output(), "* text2bytes - converts a text format trace to bytes\n")
-               fmt.Fprintf(flag.CommandLine.Output(), "* bytes2text - converts a byte format trace to text\n")
-               fmt.Fprintf(flag.CommandLine.Output(), "\n")
-               flag.PrintDefaults()
-       }
-       log.SetFlags(0)
-}
-
-func main() {
-       flag.Parse()
-       if narg := flag.NArg(); narg != 1 {
-               log.Fatal("expected exactly one positional argument: the mode to operate in; see -h output")
-       }
-
-       r := os.Stdin
-       w := os.Stdout
-
-       var tr traceReader
-       var tw traceWriter
-       var err error
-
-       switch flag.Arg(0) {
-       case "text2bytes":
-               tr, err = raw.NewTextReader(r)
-               if err != nil {
-                       log.Fatal(err)
-               }
-               tw, err = raw.NewWriter(w, tr.Version())
-               if err != nil {
-                       log.Fatal(err)
-               }
-       case "bytes2text":
-               tr, err = raw.NewReader(r)
-               if err != nil {
-                       log.Fatal(err)
-               }
-               tw, err = raw.NewTextWriter(w, tr.Version())
-               if err != nil {
-                       log.Fatal(err)
-               }
-       }
-       for {
-               ev, err := tr.ReadEvent()
-               if err == io.EOF {
-                       break
-               }
-               if err != nil {
-                       log.Fatal(err)
-               }
-               if err := tw.WriteEvent(ev); err != nil {
-                       log.Fatal(err)
-               }
-       }
-}
-
-type traceReader interface {
-       Version() version.Version
-       ReadEvent() (raw.Event, error)
-}
-
-type traceWriter interface {
-       WriteEvent(raw.Event) error
-}
diff --git a/src/internal/trace/testdata/cmd/gotracevalidate/main.go b/src/internal/trace/testdata/cmd/gotracevalidate/main.go
deleted file mode 100644 (file)
index 6c681df..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2023 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 main
-
-import (
-       "flag"
-       "fmt"
-       "io"
-       "log"
-       "os"
-
-       "internal/trace"
-       "internal/trace/testtrace"
-)
-
-func init() {
-       flag.Usage = func() {
-               fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s\n", os.Args[0])
-               fmt.Fprintf(flag.CommandLine.Output(), "\n")
-               fmt.Fprintf(flag.CommandLine.Output(), "Accepts a trace at stdin and validates it.\n")
-               flag.PrintDefaults()
-       }
-       log.SetFlags(0)
-}
-
-var logEvents = flag.Bool("log-events", false, "whether to log events")
-
-func main() {
-       flag.Parse()
-
-       r, err := trace.NewReader(os.Stdin)
-       if err != nil {
-               log.Fatal(err)
-       }
-       v := testtrace.NewValidator()
-       for {
-               ev, err := r.ReadEvent()
-               if err == io.EOF {
-                       break
-               }
-               if err != nil {
-                       log.Fatal(err)
-               }
-               if *logEvents {
-                       log.Println(ev.String())
-               }
-               if err := v.Event(ev); err != nil {
-                       log.Fatal(err)
-               }
-       }
-}