| 686 | } |
| 687 | |
| 688 | func PprofInfo(ctx context.Context, client *codersdk.Client, log slog.Logger) *PprofCollection { |
| 689 | if client == nil { |
| 690 | return nil |
| 691 | } |
| 692 | |
| 693 | var ( |
| 694 | p PprofCollection |
| 695 | eg errgroup.Group |
| 696 | ) |
| 697 | |
| 698 | if client.URL != nil { |
| 699 | if u, err := client.URL.Parse("/api/v2/debug/pprof"); err == nil { |
| 700 | p.EndpointURL = u.String() |
| 701 | } |
| 702 | } |
| 703 | if p.EndpointURL == "" { |
| 704 | p.EndpointURL = "/api/v2/debug/pprof" |
| 705 | } |
| 706 | p.CollectedAt = time.Now() |
| 707 | |
| 708 | const basePath = "/api/v2/debug/pprof" |
| 709 | endpoints := map[string]func([]byte){ |
| 710 | "/allocs": func(data []byte) { |
| 711 | p.Allocs = compressData(data) |
| 712 | }, |
| 713 | "/heap": func(data []byte) { |
| 714 | p.Heap = compressData(data) |
| 715 | }, |
| 716 | "/profile?seconds=30": func(data []byte) { |
| 717 | p.Profile = compressData(data) |
| 718 | }, |
| 719 | "/block": func(data []byte) { |
| 720 | p.Block = compressData(data) |
| 721 | }, |
| 722 | "/mutex": func(data []byte) { |
| 723 | p.Mutex = compressData(data) |
| 724 | }, |
| 725 | "/goroutine": func(data []byte) { |
| 726 | p.Goroutine = compressData(data) |
| 727 | }, |
| 728 | "/threadcreate": func(data []byte) { |
| 729 | p.Threadcreate = compressData(data) |
| 730 | }, |
| 731 | "/trace?seconds=30": func(data []byte) { |
| 732 | p.Trace = compressData(data) |
| 733 | }, |
| 734 | "/cmdline": func(data []byte) { |
| 735 | p.Cmdline = string(data) |
| 736 | }, |
| 737 | "/symbol": func(data []byte) { |
| 738 | p.Symbol = string(data) |
| 739 | }, |
| 740 | } |
| 741 | |
| 742 | for endpoint, setter := range endpoints { |
| 743 | eg.Go(func() error { |
| 744 | timeout := 10 * time.Second |
| 745 | if strings.Contains(endpoint, "seconds=30") { |