mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 10:47:27 +08:00 
			
		
		
		
	terminal: add ability to print goroutine labels (#1879)
This commit is contained in:
		 Alessandro Arzilli
					Alessandro Arzilli
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							ade20a4d4d
						
					
				
				
					commit
					186786235f
				
			| @ -274,7 +274,8 @@ Print out info for every goroutine. The flag controls what information is shown | |||||||
| 	-r	displays location of topmost stackframe (including frames inside private runtime functions) | 	-r	displays location of topmost stackframe (including frames inside private runtime functions) | ||||||
| 	-g	displays location of go instruction that created the goroutine | 	-g	displays location of go instruction that created the goroutine | ||||||
| 	-s	displays location of the start function | 	-s	displays location of the start function | ||||||
| 	-t	displays stack trace of goroutine | 	-t	displays goroutine's stacktrace | ||||||
|  | 	-l	displays goroutine's labels | ||||||
|  |  | ||||||
| If no flag is specified the default is -u. | If no flag is specified the default is -u. | ||||||
|  |  | ||||||
|  | |||||||
| @ -189,7 +189,8 @@ Print out info for every goroutine. The flag controls what information is shown | |||||||
| 	-r	displays location of topmost stackframe (including frames inside private runtime functions) | 	-r	displays location of topmost stackframe (including frames inside private runtime functions) | ||||||
| 	-g	displays location of go instruction that created the goroutine | 	-g	displays location of go instruction that created the goroutine | ||||||
| 	-s	displays location of the start function | 	-s	displays location of the start function | ||||||
| 	-t	displays stack trace of goroutine | 	-t	displays goroutine's stacktrace | ||||||
|  | 	-l	displays goroutine's labels | ||||||
|  |  | ||||||
| If no flag is specified the default is -u.`}, | If no flag is specified the default is -u.`}, | ||||||
| 		{aliases: []string{"goroutine", "gr"}, allowedPrefixes: onPrefix, cmdFn: c.goroutine, helpMsg: `Shows or changes current goroutine | 		{aliases: []string{"goroutine", "gr"}, allowedPrefixes: onPrefix, cmdFn: c.goroutine, helpMsg: `Shows or changes current goroutine | ||||||
| @ -612,14 +613,24 @@ func (a byGoroutineID) Less(i, j int) bool { return a[i].ID < a[j].ID } | |||||||
| // The number of goroutines we're going to request on each RPC call | // The number of goroutines we're going to request on each RPC call | ||||||
| const goroutineBatchSize = 10000 | const goroutineBatchSize = 10000 | ||||||
|  |  | ||||||
| func printGoroutines(t *Term, gs []*api.Goroutine, fgl formatGoroutineLoc, bPrintStack bool, state *api.DebuggerState) error { | type printGoroutinesFlags uint8 | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	printGoroutinesStack printGoroutinesFlags = 1 << iota | ||||||
|  | 	printGoroutinesLabels | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func printGoroutines(t *Term, gs []*api.Goroutine, fgl formatGoroutineLoc, flags printGoroutinesFlags, state *api.DebuggerState) error { | ||||||
| 	for _, g := range gs { | 	for _, g := range gs { | ||||||
| 		prefix := "  " | 		prefix := "  " | ||||||
| 		if state.SelectedGoroutine != nil && g.ID == state.SelectedGoroutine.ID { | 		if state.SelectedGoroutine != nil && g.ID == state.SelectedGoroutine.ID { | ||||||
| 			prefix = "* " | 			prefix = "* " | ||||||
| 		} | 		} | ||||||
| 		fmt.Printf("%sGoroutine %s\n", prefix, formatGoroutine(g, fgl)) | 		fmt.Printf("%sGoroutine %s\n", prefix, formatGoroutine(g, fgl)) | ||||||
| 		if bPrintStack { | 		if flags&printGoroutinesLabels != 0 { | ||||||
|  | 			writeGoroutineLabels(os.Stdout, g, "\t") | ||||||
|  | 		} | ||||||
|  | 		if flags&printGoroutinesStack != 0 { | ||||||
| 			stack, err := t.client.Stacktrace(g.ID, 10, 0, nil) | 			stack, err := t.client.Stacktrace(g.ID, 10, 0, nil) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return err | 				return err | ||||||
| @ -633,7 +644,7 @@ func printGoroutines(t *Term, gs []*api.Goroutine, fgl formatGoroutineLoc, bPrin | |||||||
| func goroutines(t *Term, ctx callContext, argstr string) error { | func goroutines(t *Term, ctx callContext, argstr string) error { | ||||||
| 	args := strings.Split(argstr, " ") | 	args := strings.Split(argstr, " ") | ||||||
| 	var fgl = fglUserCurrent | 	var fgl = fglUserCurrent | ||||||
| 	bPrintStack := false | 	var flags printGoroutinesFlags | ||||||
|  |  | ||||||
| 	switch len(args) { | 	switch len(args) { | ||||||
| 	case 0: | 	case 0: | ||||||
| @ -650,7 +661,9 @@ func goroutines(t *Term, ctx callContext, argstr string) error { | |||||||
| 			case "-s": | 			case "-s": | ||||||
| 				fgl = fglStart | 				fgl = fglStart | ||||||
| 			case "-t": | 			case "-t": | ||||||
| 				bPrintStack = true | 				flags |= printGoroutinesStack | ||||||
|  | 			case "-l": | ||||||
|  | 				flags |= printGoroutinesLabels | ||||||
| 			case "": | 			case "": | ||||||
| 				// nothing to do | 				// nothing to do | ||||||
| 			default: | 			default: | ||||||
| @ -675,7 +688,7 @@ func goroutines(t *Term, ctx callContext, argstr string) error { | |||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		sort.Sort(byGoroutineID(gs)) | 		sort.Sort(byGoroutineID(gs)) | ||||||
| 		err = printGoroutines(t, gs, fgl, bPrintStack, state) | 		err = printGoroutines(t, gs, fgl, flags, state) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| @ -877,6 +890,36 @@ func writeGoroutineLong(w io.Writer, g *api.Goroutine, prefix string) { | |||||||
| 		prefix, formatLocation(g.UserCurrentLoc), | 		prefix, formatLocation(g.UserCurrentLoc), | ||||||
| 		prefix, formatLocation(g.GoStatementLoc), | 		prefix, formatLocation(g.GoStatementLoc), | ||||||
| 		prefix, formatLocation(g.StartLoc)) | 		prefix, formatLocation(g.StartLoc)) | ||||||
|  | 	writeGoroutineLabels(w, g, prefix+"\t") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func writeGoroutineLabels(w io.Writer, g *api.Goroutine, prefix string) { | ||||||
|  | 	const maxNumberOfGoroutineLabels = 5 | ||||||
|  |  | ||||||
|  | 	if len(g.Labels) <= 0 { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	keys := make([]string, 0, len(g.Labels)) | ||||||
|  | 	for k := range g.Labels { | ||||||
|  | 		keys = append(keys, k) | ||||||
|  | 	} | ||||||
|  | 	sort.Strings(keys) | ||||||
|  | 	more := false | ||||||
|  | 	if len(keys) > maxNumberOfGoroutineLabels { | ||||||
|  | 		more = true | ||||||
|  | 		keys = keys[:maxNumberOfGoroutineLabels] | ||||||
|  | 	} | ||||||
|  | 	fmt.Fprintf(w, "%sLabels: ", prefix) | ||||||
|  | 	for i, k := range keys { | ||||||
|  | 		fmt.Fprintf(w, "%q:%q", k, g.Labels[k]) | ||||||
|  | 		if i != len(keys)-1 { | ||||||
|  | 			fmt.Fprintf(w, ", ") | ||||||
|  | 		} else if more { | ||||||
|  | 			fmt.Fprintf(w, "... (%d more)", len(g.Labels)-maxNumberOfGoroutineLabels) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	fmt.Fprintf(w, "\n") | ||||||
| } | } | ||||||
|  |  | ||||||
| func restart(t *Term, ctx callContext, args string) error { | func restart(t *Term, ctx callContext, args string) error { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user