Commit 4a71d182 authored by Sameer Ajmani's avatar Sameer Ajmani

net/trace: add event logs.

An event log is typically associated with a long-lived object, like an
RPC connection.  Printf calls record events; Errorf calls record
events marked as errors.  The HTTP endpoint /debug/events organizes
event logs by family (usually the Go type name) and by
time-since-last-error.  The expanded view shows recent events in the
log and the call stack where the event log was created.

Change-Id: I3461e0d63f39ce6495e16300299048e572b3aa19
Reviewed-on: https://go-review.googlesource.com/12025Reviewed-by: 's avatarDavid Symonds <dsymonds@golang.org>
parent 1bc07200
This diff is collapsed.
......@@ -3,12 +3,14 @@
// license that can be found in the LICENSE file.
/*
Package trace implements tracing of requests.
It exports an HTTP interface on /debug/requests.
Package trace implements tracing of requests and long-lived objects.
It exports HTTP interfaces on /debug/requests and /debug/events.
A trace.Trace provides tracing for short-lived objects, usually requests.
A request handler might be implemented like this:
func myHandler(w http.ResponseWriter, req *http.Request) {
tr := trace.New("Received", req.URL.Path)
func fooHandler(w http.ResponseWriter, req *http.Request) {
tr := trace.New("mypkg.Foo", req.URL.Path)
defer tr.Finish()
...
tr.LazyPrintf("some event %q happened", str)
......@@ -18,6 +20,44 @@ A request handler might be implemented like this:
tr.SetError()
}
}
The /debug/requests HTTP endpoint organizes the traces by family,
errors, and duration. It also provides histogram of request duration
for each family.
A trace.EventLog provides tracing for long-lived objects, such as RPC
connections.
// A Fetcher fetches URL paths for a single domain.
type Fetcher struct {
domain string
events *trace.EventLog
}
func NewFetcher(domain string) *Fetcher {
return &Fetcher{
domain,
trace.NewEventLog("mypkg.Fetcher", domain),
}
}
func (f *Fetcher) Fetch(path string) (string, error) {
resp, err := http.Get("http://"+domain+"/"+path)
if err != nil {
f.events.Errorf("Get(%q) = %v", path, err)
return
}
f.events.Printf("Get(%q) = %s", path, resp.Code)
...
}
func (f *Fetcher) Close() error {
f.events.Finish()
}
The /debug/events HTTP endpoint organizes the event logs by family and
by time since the last error. The expanded view displays recent log
entries and the log's call stack.
*/
package trace // import "golang.org/x/net/trace"
......@@ -72,6 +112,14 @@ func init() {
}
render(w, req, sensitive)
})
http.HandleFunc("/debug/events", func(w http.ResponseWriter, req *http.Request) {
any, sensitive := AuthRequest(req)
if !any {
http.Error(w, "not allowed", http.StatusUnauthorized)
return
}
renderEvents(w, req, sensitive)
})
}
// render renders the HTML page.
......
......@@ -30,3 +30,17 @@ func TestReset(t *testing.T) {
t.Errorf("reset didn't clear all fields: %+v", tr)
}
}
// TestResetLog checks whether all the fields are zeroed after reset.
func TestResetLog(t *testing.T) {
el := NewEventLog("foo", "bar")
el.Printf("message")
el.Errorf("error")
el.Finish()
el.(*eventLog).reset()
if !reflect.DeepEqual(el, new(eventLog)) {
t.Errorf("reset didn't clear all fields: %+v", el)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment