提交 197c1656 编写于 作者: F Florin Patan 提交者: Derek Parker

proc/breakpoint Add breakpoint statistics

This adds support for breakpoints statistics

Fixes #247
上级 f35d4b92
......@@ -17,14 +17,16 @@ type Breakpoint struct {
Temp bool // Whether this is a temp breakpoint (for next'ing).
// Breakpoint information
Tracepoint bool // Tracepoint flag
Stacktrace int // Number of stack frames to retrieve
Goroutine bool // Retrieve goroutine information
Variables []string // Variables to evaluate
Tracepoint bool // Tracepoint flag
Stacktrace int // Number of stack frames to retrieve
Goroutine bool // Retrieve goroutine information
Variables []string // Variables to evaluate
HitCount map[int]uint64 // Number of times a breakpoint has been reached in a certain goroutine
TotalHitCount uint64 // Number of times a breakpoint has been reached
}
func (bp *Breakpoint) String() string {
return fmt.Sprintf("Breakpoint %d at %#v %s:%d", bp.ID, bp.Addr, bp.File, bp.Line)
return fmt.Sprintf("Breakpoint %d at %#v %s:%d (%d)", bp.ID, bp.Addr, bp.File, bp.Line, bp.TotalHitCount)
}
// Clear this breakpoint appropriately depending on whether it is a
......@@ -74,6 +76,7 @@ func (dbp *Process) setBreakpoint(tid int, addr uint64, temp bool) (*Breakpoint,
Line: l,
Addr: addr,
Temp: temp,
HitCount: map[int]uint64{},
}
if temp {
......
......@@ -646,6 +646,10 @@ func (dbp *Process) handleBreakpointOnThread(id int) (*Thread, error) {
if err = thread.SetPC(bp.Addr); err != nil {
return nil, err
}
if g, err := thread.GetG(); err == nil {
thread.CurrentBreakpoint.HitCount[g.Id]++
}
thread.CurrentBreakpoint.TotalHitCount++
return thread, nil
}
if dbp.halt {
......
......@@ -178,6 +178,10 @@ func TestBreakpoint(t *testing.T) {
t.Fatal(err)
}
if bp.TotalHitCount != 1 {
t.Fatalf("Breakpoint should be hit once, got %d\n", bp.TotalHitCount)
}
if pc-1 != bp.Addr && pc != bp.Addr {
f, l, _ := p.goSymTable.PCToLine(pc)
t.Fatalf("Break not respected:\nPC:%#v %s:%d\nFN:%#v \n", pc, f, l, bp.Addr)
......
......@@ -2,23 +2,32 @@ package api
import (
"debug/gosym"
"strconv"
"github.com/derekparker/delve/proc"
)
// convertBreakpoint converts an internal breakpoint to an API Breakpoint.
func ConvertBreakpoint(bp *proc.Breakpoint) *Breakpoint {
return &Breakpoint{
ID: bp.ID,
FunctionName: bp.FunctionName,
File: bp.File,
Line: bp.Line,
Addr: bp.Addr,
Tracepoint: bp.Tracepoint,
Stacktrace: bp.Stacktrace,
Goroutine: bp.Goroutine,
Variables: bp.Variables,
b := &Breakpoint{
ID: bp.ID,
FunctionName: bp.FunctionName,
File: bp.File,
Line: bp.Line,
Addr: bp.Addr,
Tracepoint: bp.Tracepoint,
Stacktrace: bp.Stacktrace,
Goroutine: bp.Goroutine,
Variables: bp.Variables,
TotalHitCount: bp.TotalHitCount,
}
b.HitCount = map[string]uint64{}
for idx := range bp.HitCount {
b.HitCount[strconv.Itoa(idx)] = bp.HitCount[idx]
}
return b
}
// convertThread converts an internal thread to an API Thread.
......
......@@ -42,6 +42,10 @@ type Breakpoint struct {
Goroutine bool `json:"goroutine"`
// variables to evaluate
Variables []string `json:"variables,omitempty"`
// number of times a breakpoint has been reached in a certain goroutine
HitCount map[string]uint64 `json:"hitCount"`
// number of times a breakpoint has been reached
TotalHitCount uint64 `json:"totalHitCount"`
}
// Thread is a thread within the debugged process.
......
......@@ -481,7 +481,7 @@ func breakpoints(t *Term, args ...string) error {
if bp.Tracepoint {
thing = "Tracepoint"
}
fmt.Printf("%s %d at %#v %s:%d\n", thing, bp.ID, bp.Addr, shortenFilePath(bp.File), bp.Line)
fmt.Printf("%s %d at %#v %s:%d (%d)\n", thing, bp.ID, bp.Addr, shortenFilePath(bp.File), bp.Line, bp.TotalHitCount)
var attrs []string
if bp.Stacktrace > 0 {
......@@ -767,12 +767,34 @@ func printcontext(t *Term, state *api.DebuggerState) error {
if state.CurrentThread.Function != nil {
fn = state.CurrentThread.Function
}
if state.Breakpoint != nil && state.Breakpoint.Tracepoint {
var args []string
for _, arg := range state.CurrentThread.Function.Args {
args = append(args, arg.Value)
if state.Breakpoint != nil {
args := ""
if state.Breakpoint.Tracepoint {
var arg []string
for _, ar := range state.CurrentThread.Function.Args {
arg = append(arg, ar.Value)
}
args = strings.Join(arg, ", ")
}
if hitCount, ok := state.Breakpoint.HitCount[strconv.Itoa(state.SelectedGoroutine.ID)]; ok {
fmt.Printf("> %s(%s) %s:%d (hits goroutine(%d):%d total:%d)\n",
fn.Name,
args,
shortenFilePath(state.CurrentThread.File),
state.CurrentThread.Line,
state.SelectedGoroutine.ID,
hitCount,
state.Breakpoint.TotalHitCount)
} else {
fmt.Printf("> %s(%s) %s:%d (hits total:%d)\n",
fn.Name,
args,
shortenFilePath(state.CurrentThread.File),
state.CurrentThread.Line,
state.Breakpoint.TotalHitCount)
}
fmt.Printf("> %s(%s) %s:%d\n", fn.Name, strings.Join(args, ", "), shortenFilePath(state.CurrentThread.File), state.CurrentThread.Line)
} else {
fmt.Printf("> %s() %s:%d\n", fn.Name, shortenFilePath(state.CurrentThread.File), state.CurrentThread.Line)
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册