mirror of https://github.com/minio/minio.git
Browse Source
Add a script to filter goroutines waiting for a given number of minutes (#17204)
pull/17222/head
Add a script to filter goroutines waiting for a given number of minutes (#17204)
pull/17222/head

committed by
GitHub

No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 140 additions and 0 deletions
@ -0,0 +1,140 @@ |
|||
// Copyright (c) 2015-2023 MinIO, Inc.
|
|||
//
|
|||
// This file is part of MinIO Object Storage stack
|
|||
//
|
|||
// This program is free software: you can redistribute it and/or modify
|
|||
// it under the terms of the GNU Affero General Public License as published by
|
|||
// the Free Software Foundation, either version 3 of the License, or
|
|||
// (at your option) any later version.
|
|||
//
|
|||
// This program is distributed in the hope that it will be useful
|
|||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||
// GNU Affero General Public License for more details.
|
|||
//
|
|||
// You should have received a copy of the GNU Affero General Public License
|
|||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
|||
package main |
|||
|
|||
import ( |
|||
"bufio" |
|||
"bytes" |
|||
"flag" |
|||
"fmt" |
|||
"log" |
|||
"math" |
|||
"os" |
|||
"path" |
|||
"regexp" |
|||
"strconv" |
|||
"strings" |
|||
"time" |
|||
) |
|||
|
|||
var ( |
|||
re *regexp.Regexp |
|||
goTime, margin time.Duration |
|||
) |
|||
|
|||
func init() { |
|||
re = regexp.MustCompile(`^goroutine [0-9]+ \[[^,]+(, ([0-9]+) minutes)?\]:$`) |
|||
|
|||
flag.DurationVar(&goTime, "time", 0, "goroutine block age") |
|||
flag.DurationVar(&margin, "margin", 0, "margin time") |
|||
} |
|||
|
|||
func parseGoroutineType2(path string) (map[time.Duration][]string, error) { |
|||
f, err := os.Open(path) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
bf := bytes.Buffer{} |
|||
|
|||
save := func(s string) { |
|||
bf.WriteString(s + "\n") |
|||
} |
|||
reset := func() { |
|||
bf.Reset() |
|||
} |
|||
|
|||
ret := make(map[time.Duration][]string) |
|||
|
|||
s := bufio.NewScanner(f) |
|||
s.Split(bufio.ScanLines) |
|||
|
|||
var ( |
|||
t time.Duration |
|||
skip, record bool |
|||
) |
|||
|
|||
for s.Scan() { |
|||
line := s.Text() |
|||
switch { |
|||
case skip && line != "": |
|||
case skip && line == "": |
|||
skip = false |
|||
case record && line == "": |
|||
record = false |
|||
ret[t] = append(ret[t], bf.String()) |
|||
reset() |
|||
case record: |
|||
save(line) |
|||
default: |
|||
z := re.FindStringSubmatch(line) |
|||
if len(z) == 3 { |
|||
if z[2] != "" { |
|||
a, _ := strconv.Atoi(z[2]) |
|||
t = time.Duration(a) * time.Minute |
|||
save(line) |
|||
record = true |
|||
} else { |
|||
skip = true |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return ret, nil |
|||
} |
|||
|
|||
const helpUsage = ` |
|||
|
|||
At least one argument is required to run this tool. |
|||
|
|||
EXAMPLE: |
|||
./pprofgoparser --time 50m --margin 1m /path/to/*-goroutines-before,debug=2.txt |
|||
` |
|||
|
|||
func main() { |
|||
flag.Parse() |
|||
|
|||
if len(flag.Args()) == 0 { |
|||
log.Fatal(helpUsage) |
|||
} |
|||
|
|||
for _, arg := range flag.Args() { |
|||
if !strings.HasSuffix(arg, "-goroutines-before,debug=2.txt") { |
|||
continue |
|||
} |
|||
r, err := parseGoroutineType2(arg) |
|||
if err != nil { |
|||
log.Fatal(err) |
|||
} |
|||
|
|||
profFName := path.Base(arg) |
|||
fmt.Println(strings.Repeat("=", len(profFName))) |
|||
fmt.Println(profFName) |
|||
fmt.Println(strings.Repeat("=", len(profFName))) |
|||
fmt.Println("") |
|||
|
|||
for t, stacks := range r { |
|||
if goTime == 0 || math.Abs(float64(t)-float64(goTime)) <= float64(margin) { |
|||
for _, stack := range stacks { |
|||
fmt.Println(stack) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue