github.com/matrixorigin/matrixone@v1.2.0/pkg/util/debug/goroutine/parser.go (about)

     1  // Copyright 2023 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package goroutine
    16  
    17  import (
    18  	"bufio"
    19  	"bytes"
    20  	"strings"
    21  
    22  	"github.com/fagongzi/util/format"
    23  )
    24  
    25  var (
    26  	goroutineTokenLen      = len("goroutine")
    27  	blockedMinutesTokenLen = len(" minutes]:")
    28  )
    29  
    30  func parse(data []byte) []Goroutine {
    31  	var gs []Goroutine
    32  	var g Goroutine
    33  	scanner := bufio.NewScanner(bytes.NewReader(data))
    34  	for scanner.Scan() {
    35  		line := strings.TrimSpace(scanner.Text())
    36  		if strings.HasPrefix(line, "goroutine") {
    37  			if !g.IsEmpty() {
    38  				gs = append(gs, g)
    39  			}
    40  			g = Goroutine{}
    41  			readGoroutineLine(line, &g)
    42  		} else if line == "" {
    43  			continue
    44  		} else if strings.Contains(line, ":") {
    45  			g.files = append(g.files, line)
    46  		} else {
    47  			g.methods = append(g.methods, line)
    48  		}
    49  	}
    50  	if !g.IsEmpty() {
    51  		gs = append(gs, g)
    52  	}
    53  	return gs
    54  }
    55  
    56  // format: goroutine 628 [IO wait, 8 minutes]:
    57  func readGoroutineLine(
    58  	line string,
    59  	g *Goroutine) {
    60  	g.rawState = line
    61  
    62  	// goroutine 628 [IO wait, 8 minutes]:
    63  	//           ^ offset
    64  	offset := goroutineTokenLen + 1
    65  
    66  	idx := strings.Index(line[offset:], " ")
    67  	g.ID = format.MustParseStringInt(line[offset : offset+idx])
    68  
    69  	// goroutine 628 [IO wait, 8 minutes]:
    70  	//                ^ offset
    71  	offset += idx + 2
    72  	idx = strings.Index(line[offset:], ",")
    73  	if idx == -1 {
    74  		g.State = line[offset : len(line)-2]
    75  		return
    76  	}
    77  
    78  	g.State = line[offset : offset+idx]
    79  
    80  	// goroutine 628 [IO wait, 8 minutes]:
    81  	//                         ^ offset
    82  	offset += idx + 2
    83  	g.BlockedMinutes = format.MustParseStringInt(line[offset : len(line)-blockedMinutesTokenLen])
    84  }