Documentation ¶
Overview ¶
Package instrument provides support for instrumenting complex applications to trace their operation and communication behaviour across multiple goroutines and contexts.
The underlying data structure used for the trace related instrumentation tools is a combination of a linked list of trace records where each individual record in that linked list can itself host any number linked lists of trace records. This mimics a linear execution which can spawn concurrent traces from any point, that is, a linear execution which spawns goroutines. The various uses of this underlying structure offer a 'Go' method to be used in conjunction with goroutines to allow the traces to span multiple goroutines.
Functions are provided to register and retrieve traces from context.Context instances and thus to pass them through multiple API boundaries.
Index ¶
- func CopyCallTrace(from, to context.Context) context.Context
- func CopyMessageTrace(from, to context.Context) context.Context
- func WithCallTrace(ctx context.Context) context.Context
- func WithMessageTrace(ctx context.Context) context.Context
- func WriteFrames(out io.Writer, prefix string, frames []runtime.Frame)
- type CallRecord
- type CallTrace
- func (ct *CallTrace) GoLog(skip int, args ...interface{}) *CallTrace
- func (ct *CallTrace) GoLogf(skip int, format string, args ...interface{}) *CallTrace
- func (ct *CallTrace) ID() int64
- func (ct *CallTrace) Log(skip int, args ...interface{})
- func (ct *CallTrace) Logf(skip int, format string, args ...interface{})
- func (ct *CallTrace) Print(out io.Writer, callers, relative bool)
- func (ct *CallTrace) ReleaseArguments()
- func (ct *CallTrace) RootID() int64
- func (ct *CallTrace) String() string
- func (ct *CallTrace) Walk(fn func(cr CallRecord))
- type MessagePrimitive
- type MessageRecord
- type MessageRecords
- type MessageTrace
- func (mt *MessageTrace) Flatten(tag string) MessageRecords
- func (mt *MessageTrace) GoLog(skip int, args ...interface{}) *MessageTrace
- func (mt *MessageTrace) GoLogf(skip int, format string, args ...interface{}) *MessageTrace
- func (mt *MessageTrace) ID() int64
- func (mt *MessageTrace) Log(skip int, status MessagePrimitive, local, remote net.Addr, args ...interface{})
- func (mt *MessageTrace) Logf(skip int, status MessagePrimitive, local, remote net.Addr, format string, ...)
- func (mt *MessageTrace) Print(out io.Writer, callers, relative bool)
- func (mt *MessageTrace) ReleaseArguments()
- func (mt *MessageTrace) RootID() int64
- func (mt *MessageTrace) String() string
- func (mt *MessageTrace) Walk(fn func(mr MessageRecord))
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CopyCallTrace ¶
CopyCallTrace will copy a call trace from one context to another.
func CopyMessageTrace ¶
CopyMessageTrace will copy a call trace from one context to another.
func WithCallTrace ¶
WithCallTrace returns a context.Context that is guaranteed to contain a call trace. If the context already had a trace then it is left in place and the same context is returned, otherwise a new context is returneed with an empty trace.
func WithMessageTrace ¶
WithMesageTrace returns a context.Context that is guaranteed to contain a message trace. If the context already had a trace then it is left in place and the same context is returned, otherwise a new context is returneed with an empty trace.
Types ¶
type CallRecord ¶
type CallRecord struct {
// ID is the id of the current trace, and RootID the ID of the
// trace that created this one via a GoLog or GoLogf call.
ID, RootID int64
// Level is the number of GoLog or GoLogf calls that preceded
// the creation of this record. It is used to generate relative
// relative stack traces when printing traces.
Level int
// Time is the time that the record was created at.
Time time.Time
// GoCall is true if this record was generated by a GoLo or GoLogf
// call.
GoCall bool
// Full is the full stack frame of recorded location, whereas Relative
// is relative to the previous recorded location.
Full, Relative []runtime.Frame
// GoCaller is the full stack frame of the call to GoLog or GoLogf
// that created this sub-trace.
GoCaller []runtime.Frame
// Arguments is either the formatted string for Logf or a slice
// containing the arguments to Log.
Arguments interface{}
}
CallRecord represents a recorded trace location.
type CallTrace ¶
type CallTrace struct {
// contains filtered or unexported fields
}
CallTrace provides the ability to log specific points in a linear execution (Log, Logf) as well as to span the creation of goroutines and points in their execution (GoLog, GoLogf). A log record consists of the parameters to the logging function and the location of the call (ie. caller stackframes).
Example ¶
package main import ( "fmt" "os" "sync" "cloudeng.io/debug/instrument" ) func main() { ct := &instrument.CallTrace{} ct.Logf(1, "a") ct.Logf(1, "b") var wg sync.WaitGroup n := 2 wg.Add(n) for i := 0; i < n; i++ { ct := ct.GoLogf(1, "goroutine launch") go func(i int) { ct.Logf(1, fmt.Sprintf("inside goroutine %v", i)) wg.Done() ct.Logf(1, fmt.Sprintf("inside goroutine %v", i)) }(i) } wg.Wait() // Print the call trace without stack frames. fmt.Println(ct.String()) // Print the call trace with relative stack frames. ct.Print(os.Stdout, true, true) }
Output:
func CallTraceFrom ¶
CallTraceFrom extracts a CallTrace from the supplied context. It returns an empty, unused trace (i.e. its ID() method will return 0) if no trace is found.
func (*CallTrace) GoLog ¶
GoLog logs the current call site and returns a new CallTrace, that is a child of the existing one, to be used in a goroutine started from the current one. Skip is the number of callers to skip, as per runtime.Callers.
func (*CallTrace) GoLogf ¶
GoLogf logs the current call site and returns a new CallTrace, that is a child of the existing one, to be used in a goroutine started from the current one. Skip is the number of callers to skip, as per runtime.Callers.
func (*CallTrace) ID ¶
ID returns the id of this call trace. All traces are allocated a unique id on first use, otherwise their id is zero.
func (*CallTrace) Log ¶
Log logs the current call site and its arguments. The supplied arguments are stored in a slice and retained until ReleaseArguments is called. Skip is the number of callers to skip, as per runtime.Callers.
func (*CallTrace) Logf ¶
Logf logs the current call site with its arguments being immediately used to create a string (using fmt.Sprintf) that is stored within the trace. Skip is the number of callers to skip, as per runtime.Callers.
func (*CallTrace) Print ¶
Print will print the trace to the supplied io.Writer, if callers is set then the stack frame will be printed and if relative is set each displayed stack frame will be relative to the previous one for
func (*CallTrace) ReleaseArguments ¶
func (ct *CallTrace) ReleaseArguments()
ReleaseArguments releases all stored arguments from previous calls to Log or Logf.
func (*CallTrace) RootID ¶
RootID returns the root id of this call trace, ie. the id that was allocated to the first record in this call trace hierarchy.
func (*CallTrace) Walk ¶
func (ct *CallTrace) Walk(fn func(cr CallRecord))
Walk traverses the call trace calling the supplied function for each record.
type MessagePrimitive ¶
type MessagePrimitive int
MessagePrimitive represents the supported message operations.
const ( MessageWait MessagePrimitive = iota + 1 MessageAcceptWait MessageAccepted MessageSent MessageReceived )
The above are the defined communication primitives. They are defined in order of preference when sorting by MergeMessageTraces.
func (MessagePrimitive) String ¶
func (m MessagePrimitive) String() string
String implements fmt.Stringer.
type MessageRecord ¶
type MessageRecord struct { CallRecord Tag string // Tag assigned to this message trace by Flatten. Status MessagePrimitive // The status of the message. Local, Remote net.Addr // The local and remote addresses for the message. }
MessageRecord represents the metadata for a recorded message.
func (MessageRecord) String ¶
func (mr MessageRecord) String() string
String implements fmt.Stringer.
type MessageRecords ¶
type MessageRecords []MessageRecord
func MergeMessageTraces ¶
func MergeMessageTraces(traces ...MessageRecords) MessageRecords
func (MessageRecords) String ¶
func (ms MessageRecords) String() string
type MessageTrace ¶
type MessageTrace struct {
// contains filtered or unexported fields
}
MessageTrace provides the ability to log various communication primitives (e.g. message sent, received etc) and their location in a linear execution (Log, Logf) as well as to span the creation of goroutines and the execution of said primitives in their linear execution (GoLog, GoLogf). A log record consists of the parameters to the logging function and the location of the call (ie. caller stackframes).
Example ¶
package main import ( "fmt" "net" "os" "cloudeng.io/debug/instrument" ) var localAddr, remoteAddr *net.IPAddr func main() { mt := &instrument.MessageTrace{} mt.Log(1, instrument.MessageSent, localAddr, remoteAddr, "some detail") mt.Log(1, instrument.MessageReceived, localAddr, remoteAddr, "some detail") fmt.Println(mt.String()) mt.Print(os.Stdout, true, true) }
Output:
func MessageTraceFrom ¶
func MessageTraceFrom(ctx context.Context) *MessageTrace
MessageTraceFrom extracts a MessageTrace from the supplied context. It returns an empty, unused trace (i.e. its ID() method will return 0) if no trace is found.
func (*MessageTrace) Flatten ¶
func (mt *MessageTrace) Flatten(tag string) MessageRecords
Flatten returns a slice of MessageRecords sorted by level, rootID, ID, time and finally by message status (in order of Waiting, Sent and Received).
func (*MessageTrace) GoLog ¶
func (mt *MessageTrace) GoLog(skip int, args ...interface{}) *MessageTrace
GoLog logs the current call site and returns a new MessageTrace, that is a child of the existing one, to be used in a goroutine started from the current one. Skip is the number of callers to skip, as per runtime.Callers.
func (*MessageTrace) GoLogf ¶
func (mt *MessageTrace) GoLogf(skip int, format string, args ...interface{}) *MessageTrace
GoLogf logs the current call site and returns a new MessageTrace, that is a child of the existing one, to be used in a goroutine started from the current one. Skip is the number of callers to skip, as per runtime.Callers.
func (*MessageTrace) ID ¶
func (mt *MessageTrace) ID() int64
ID returns the id of this message trace. All traces are allocated a unique id on first use, otherwise their id is zero.
func (*MessageTrace) Log ¶
func (mt *MessageTrace) Log(skip int, status MessagePrimitive, local, remote net.Addr, args ...interface{})
Log logs the current call site and its arguments. The supplied arguments are stored in a slice and retained until ReleaseArguments is called. Skip is the number of callers to skip, as per runtime.Callers.
func (*MessageTrace) Logf ¶
func (mt *MessageTrace) Logf(skip int, status MessagePrimitive, local, remote net.Addr, format string, args ...interface{})
Logf logs the current call site with its arguments being immediately used to create a string (using fmt.Sprintf) that is stored within the trace. Skip is the number of callers to skip, as per runtime.Callers.
func (*MessageTrace) Print ¶
func (mt *MessageTrace) Print(out io.Writer, callers, relative bool)
Print will print the trace to the supplied io.Writer, if callers is set then the stack frame will be printed and if relative is set each displayed stack frame will be relative to the previous one for
func (*MessageTrace) ReleaseArguments ¶
func (mt *MessageTrace) ReleaseArguments()
ReleaseArguments releases all stored arguments from previous calls to Log or Logf.
func (*MessageTrace) RootID ¶
func (mt *MessageTrace) RootID() int64
RootID returns the root id of this message trace, that is the id that is allocated to the first MessageTrace record in this call trace.
func (*MessageTrace) String ¶
func (mt *MessageTrace) String() string
String implements fmt.Stringer.
func (*MessageTrace) Walk ¶
func (mt *MessageTrace) Walk(fn func(mr MessageRecord))
Walk traverses the call trace calling the supplied function for each record.