go/src/internal/trace/version/version.go
Michael Anthony Knyszek 4a7fde922f internal/trace: add end-of-generation signal to trace
This change takes the EvEndOfGeneration event and promotes it to a real
event that appears in the trace.

This allows the trace parser to unambiguously identify truncated traces
vs. broken traces. It also makes a lot of the logic around parsing
simpler, because there's no more batch spilling necessary.

Fixes #73904.

Change-Id: I37c359b32b6b5f894825aafc02921adeaacf2595
Reviewed-on: https://go-review.googlesource.com/c/go/+/693398
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-08-15 14:01:30 -07:00

87 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 version
import (
"fmt"
"io"
"internal/trace/tracev2"
)
// Version represents the version of a trace file.
type Version uint32
const (
Go111 Version = 11 // v1
Go119 Version = 19 // v1
Go121 Version = 21 // v1
Go122 Version = 22 // v2
Go123 Version = 23 // v2
Go125 Version = 25 // v2
Go126 Version = 26 // v2
Current = Go126
)
var versions = map[Version][]tracev2.EventSpec{
// Go 1.111.21 use a different parser and are only set here for the sake of
// Version.Valid.
Go111: nil,
Go119: nil,
Go121: nil,
Go122: tracev2.Specs()[:tracev2.EvUserLog+1], // All events after are Go 1.23+.
Go123: tracev2.Specs()[:tracev2.EvExperimentalBatch+1], // All events after are Go 1.25+.
Go125: tracev2.Specs()[:tracev2.EvClockSnapshot+1], // All events after are Go 1.26+.
Go126: tracev2.Specs(),
}
// Specs returns the set of event.Specs for this version.
func (v Version) Specs() []tracev2.EventSpec {
return versions[v]
}
// EventName returns a string name of a wire format event
// for a particular trace version.
func (v Version) EventName(typ tracev2.EventType) string {
if !v.Valid() {
return "<invalid trace version>"
}
s := v.Specs()
if len(s) == 0 {
return "<v1 trace event type>"
}
if int(typ) < len(s) && s[typ].Name != "" {
return s[typ].Name
}
return fmt.Sprintf("Invalid(%d)", typ)
}
func (v Version) Valid() bool {
_, ok := versions[v]
return ok
}
// headerFmt is the format of the header of all Go execution traces.
const headerFmt = "go 1.%d trace\x00\x00\x00"
// ReadHeader reads the version of the trace out of the trace file's
// header, whose prefix must be present in v.
func ReadHeader(r io.Reader) (Version, error) {
var v Version
_, err := fmt.Fscanf(r, headerFmt, &v)
if err != nil {
return v, fmt.Errorf("bad file format: not a Go execution trace?")
}
if !v.Valid() {
return v, fmt.Errorf("unknown or unsupported trace version go 1.%d", v)
}
return v, nil
}
// WriteHeader writes a header for a trace version v to w.
func WriteHeader(w io.Writer, v Version) (int, error) {
return fmt.Fprintf(w, headerFmt, v)
}