Documentation
¶
Overview ¶
Package trace allows debugging programs via trace statements inserted in code. Sometimes you need to see the sequence in which functions are called, and stepping through each manually with a debugger is not the appropriate answer. If you've ever sprinkled "Printf" statements throughout your code to get insight into what's happenning, this package is strictly better: in addition to printing the messages you specify, it denotes the structure of the stack by appropriately indenting them (and indenting the names of the callers), and printing time stamps of when the trace calls occurred.
Tracing is as simple as inserting a Trace statements where you want to do the tracing. These statements will print all the currrent stack frames to the most recent previously traced stack frame that is on the current stack.
trace.Trace()
You may also pass Printf-style arguments to Trace to display interesting state of your program:
trace("Label: my var=%v", myvar)
You should turn on tracing before the point in your program where you want to trace. If you want to trace a package init() function, turn it on there. This function call is idempotent. It is merely a shorthand for setting Global.On:
trace.On(true)
You may also turn off tracing at any point you wish:
trace.On(false)
In fact, you may change many of the seetings of an active Tracer object by modifying them directly. For example, to make global tracer only trace the last reported goroutine, use
trace.Global.LockGoRoutine = true
While in most cases you'll want to use the trace.Global logger (accessible directly and through the trace.Trace function), you can also create custom Tracer objects and use them via Tracer.Trace().
Tracer is concurrency-safe. When Trace() is called from a different goroutine than its previous call, it prints a warning about a goroutine switch. Optionally, it can print just the current goroutine stack frame including frames recorded earlier (if OnGoroutineSwitchPrintCurrentStack is set; default is false in Global), or print the entire history of the stack for this goroutine (if OnGoroutineSwitchPrintStackHistory is set; default is true in Global).
Example ¶
package main import ( "time" "trace" ) func a(n string) { trace.Trace("Alice: [%s]", n) } func b(n string) { trace.Trace("Barb! [%s]", n) for i := 1; i < 5; i++ { time.Sleep(10 * time.Millisecond) a("barb " + n) } trace.Trace("Bob! [%s]", n) for i := 1; i < 5; i++ { time.Sleep(10 * time.Millisecond) a("bob " + n) } trace.Trace("Blaise! [%s]", n) } func d(n string) { trace.Trace("Dely! [%s]", n) for i := 1; i < 5; i++ { trace.Trace() } trace.Trace("Dan! [%s]", n) } func c(n string) { trace.Trace("Carol before [%s]", n) time.Sleep(50 * time.Millisecond) a("carol " + n) trace.Trace("Carol after [%s]", n) } func main() { trace.Global.On = true trace.Trace("Start") c("one") if true { go a("two") go c("three") go b("four") go b("five") } else { a("six") c("seven") b("eight") b("nine") } a("ten") d("eleven") trace.Trace("The end!") time.Sleep(5 * time.Second) }
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GoroutineID ¶
func GoroutineID() int
GoroutineID returns the numerical ID of the currently running goroutine.
func On ¶
func On(on bool)
On turns tracing with the global debugger on or off. It's nothing more than a shorthand for setting Global.On manually.
func Trace ¶
func Trace(args ...interface{})
Trace prints out the call stack of the current goroutine. The top stack frame is annotated with `args`, which are interpreted as parameters to fmt.Printf().
Example ¶
package main import ( "trace" ) func main() { trace.On(true) trace.Trace("First") func() { trace.Trace("Third") }() trace.Trace("Second") }
func TruncateError ¶
TruncateError returns the string representation of `err` truncated to `max` characters.
Types ¶
type FrameInfo ¶
type FrameInfo struct { runtime.Frame // The time at which this stack frame was recorded. Note that // parent functions up the stack (until the previous call to // Trace()) will have the same TimeRecorded because they were // recorded at the same time, even though they were actually // entered at different times. TimeRecorded time.Time }
type GoroutineInfo ¶
type GoroutineInfo struct { // ID holds the numerical ID of this subroutine. ID int // Frames is a list of the current stack frames, with the top // of the stack being the 0th element. Frames []*FrameInfo // TopMessage is the message, if any, logged on the last call // to Trace() on this goroutine. // // Note that only the top frame in the current stack at any // moment could possibly have a message. All the previous // stack frames are by necessity from a function call site, // not from a Trace() call site, so they cannot have any // messages in them. As a result, we store the topMessage once // per goroutine rather than having mostly empty fields in // frames TopMessage string // History holds all the logging entries ever written for this // goroutine. History []string }
func (*GoroutineInfo) Copy ¶
func (gi *GoroutineInfo) Copy() *GoroutineInfo
Copy returns a deep copy of `gi`.
type Logger ¶
type Logger interface { Printf(format string, v ...interface{}) Println(v ...interface{}) }
Logger defines the output functionality needed by Tracer. Note that log.Logger satisfies this interface.
type Tracer ¶
type Tracer struct { // On determines whether the Tracer is active or not. On bool // Out receives the output of the Trace() calls. Out Logger // Capacity holds the maximum stack size we can accomodate. Capacity int // SourceLength holds the maxium displayed length, // right-justified, of the string specifying the source code // file name and line number. The SourceLength int // LockGoroutine causes Trace() to only record and emit output // for the current (ie last invoking) goroutine. LockGoroutine bool // OmitTime causes Tracer to not output date/time info. This // might be useful to shorten output lines if the Logger // specified in Out already displays time info. However, it is // recommended to leave this set to false so that accurate // time stamps are displayed when printing previously recorded // frames (if enabled via the OnGoroutinePrint* options). OmitTime bool // ClockFn is the function that will return the time used to // record when Trace() calls were invoked. If not specified, // time.Now will be used. ClockFn func() time.Time // OnGoroutineSwitchPrintCurrentStack prints out the current // state of the call stack when switching to a different // goroutine. Note that this does NOT print the whole History // of the stack for this goroutine. OnGoroutineSwitchPrintCurrentStack bool // OnGoroutineSwitchPrintStackHistory prints out the entire // history of the current call stack when switching to a // different goroutine. OnGoroutineSwitchPrintStackHistory bool // contains filtered or unexported fields }
Tracer records and echoes the call stack when Trace() is invoked. The public parameters configure how Tracer operates, and may be changed at run time, in which case they take effect on the next call to Trace().
var Global *Tracer
Global is the global instance of Tracer, which can be easily accessed by the trace.Trace() function. The public parameters of Global may be changed dynamically and affect subsequent calls to Trace(). Refer to this module's init() function for more details.
func (*Tracer) Goroutines ¶
func (tr *Tracer) Goroutines() map[int]*GoroutineInfo
Goroutines returns a map of goroutine IDs to GoroutineInfo objects reflecting the current state of `tr`. The returned map is a deep copy of the internal state of `tr`.
func (*Tracer) Trace ¶
Trace records and echoes the state of the current goroutine's stack since the last time it was recorded. Those "new" entries are printed with a "+" marker. Previous entries on the call stack may be printed depending on the values of OnGoroutineSwitchPrintCurrentStack and OnGoroutineSwitchPrintStackHistory; those previous entries will NOT have a "+" marker.
Note that the output cannot distinguish between to consecutive calls to Trace from the same stack frame, vs two consecutive calls to Trace from sibling stack frames.
The parameter `skip` denotes the number of stack frames to skip in processing; a value of 0 denotes to start processing with the caller of this function as the top of the stack.