• Kirill Smelkov's avatar
    tracing: Part 1 - runtime · 3cf17be3
    Kirill Smelkov authored
    Package tracing will provide usage and runtime support for Linux-style
    traceevents/tracepoints for Go.
    
    This patch comes with the runtime support to attach/detach probes to/from
    trace-events and stop/restart the world so that attaching/detaching can
    be done safely while nothing else is running. Having attach/detach under
    STW allows regular probe list iteration to be done without locks.
    
    The next patch will add gotrace utility which automatically turns
    //trace:event in-source comments into proper trace-event definitions.
    
    Below is excerpt from tracing usage. Please refer to tracing.go for full
    text.
    
    ---- 8< ----
    Package tracing provides usage and runtime support for Go tracing facilities.
    
    Trace events
    
    A Go package can define several events of interest to trace via special
    comments. With such definition a tracing event becomes associated with trace
    function that is used to signal when the event happens. For example:
    
    	package hello
    
    	//trace:event traceHelloPre(who string)
    	//trace:event traceHello(who string)
    
    	func SayHello(who string) {
    		traceHelloPre(who)
    		fmt.Println("Hello, %s", who)
    		traceHello(who)
    	}
    
    By default trace function does nothing and has very small overhead.
    
    Probes
    
    However it is possible to attach probing functions to events. A probe, once
    attached, is called whenever event is signalled in the context which triggered
    the event and pauses original code execution until the probe is finished. It is
    possible to attach several probing functions to the same event and dynamically
    detach/(re-)attach them at runtime. Attaching/detaching probes must be done
    under tracing.Lock. For example:
    
    	type saidHelloT struct {
    		who  string
    		when time.Time
    	}
    	saidHello := make(chan saidHelloT)
    
    	tracing.Lock()
    	p := traceHello_Attach(nil, func(who string) {
    		saidHello <- saidHelloT{who, time.Now()}
    	})
    	tracing.Unlock()
    
    	go func() {
    		for hello := range saidHello {
    			fmt.Printf("Said hello to %v @ %v\n", hello.who, hello.when)
    		}
    	}()
    
    	SayHello("JP")
    	SayHello("Kirr")
    	SayHello("Varya")
    
    	tracing.Lock()
    	p.Detach()
    	tracing.Unlock()
    
    	close(saidHello)
    
    For convenience it is possible to keep group of attached probes and detach them
    all at once using ProbeGroup:
    
    	pg := &tracing.ProbeGroup{}
    
    	tracing.Lock()
    	traceHelloPre_Attach(pg, func(who string) { ... })
    	traceHello_Attach(pg, func(who string) { ... })
    	tracing.Unlock()
    
    	// some activity
    
    	// when probes needs to be detached (no explicit tracing.Lock needed):
    	pg.Done()
    
    Probes is general mechanism which allows various kinds of trace events usage.
    Three ways particularly are well-understood and handy:
    
    	- recording events stream
    	- profiling
    	- synchronous tracing
    
    ...
    3cf17be3
runtime.go 1.81 KB