Source file src/internal/trace/raw/writer.go

     1  // Copyright 2023 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  
     5  package raw
     6  
     7  import (
     8  	"encoding/binary"
     9  	"fmt"
    10  	"io"
    11  
    12  	"internal/trace/event"
    13  	"internal/trace/version"
    14  )
    15  
    16  // Writer emits the wire format of a trace.
    17  //
    18  // It may not produce a byte-for-byte compatible trace from what is
    19  // produced by the runtime, because it may be missing extra padding
    20  // in the LEB128 encoding that the runtime adds but isn't necessary
    21  // when you know the data up-front.
    22  type Writer struct {
    23  	w     io.Writer
    24  	buf   []byte
    25  	v     version.Version
    26  	specs []event.Spec
    27  }
    28  
    29  // NewWriter creates a new byte format writer.
    30  func NewWriter(w io.Writer, v version.Version) (*Writer, error) {
    31  	_, err := version.WriteHeader(w, v)
    32  	return &Writer{w: w, v: v, specs: v.Specs()}, err
    33  }
    34  
    35  // WriteEvent writes a single event to the trace wire format stream.
    36  func (w *Writer) WriteEvent(e Event) error {
    37  	// Check version.
    38  	if e.Version != w.v {
    39  		return fmt.Errorf("mismatched version between writer (go 1.%d) and event (go 1.%d)", w.v, e.Version)
    40  	}
    41  
    42  	// Write event header byte.
    43  	w.buf = append(w.buf, uint8(e.Ev))
    44  
    45  	// Write out all arguments.
    46  	spec := w.specs[e.Ev]
    47  	for _, arg := range e.Args[:len(spec.Args)] {
    48  		w.buf = binary.AppendUvarint(w.buf, arg)
    49  	}
    50  	if spec.IsStack {
    51  		frameArgs := e.Args[len(spec.Args):]
    52  		for i := 0; i < len(frameArgs); i++ {
    53  			w.buf = binary.AppendUvarint(w.buf, frameArgs[i])
    54  		}
    55  	}
    56  
    57  	// Write out the length of the data.
    58  	if spec.HasData {
    59  		w.buf = binary.AppendUvarint(w.buf, uint64(len(e.Data)))
    60  	}
    61  
    62  	// Write out varint events.
    63  	_, err := w.w.Write(w.buf)
    64  	w.buf = w.buf[:0]
    65  	if err != nil {
    66  		return err
    67  	}
    68  
    69  	// Write out data.
    70  	if spec.HasData {
    71  		_, err := w.w.Write(e.Data)
    72  		return err
    73  	}
    74  	return nil
    75  }
    76  

View as plain text