[client] add profiling dumps to debug package (#3517)

enhances debugging capabilities by adding support for goroutine, mutex, and block profiling while updating state dump tracking and refining test and release settings.

- Adds pprof-based profiling for goroutine, mutex, and block profiles in the debug bundle.
- Updates state dump functionality by incorporating new status and key fields.
- Adjusts test validations and default flag/retention settings.
This commit is contained in:
Maycon Santos
2025-03-23 13:46:09 +01:00
committed by GitHub
parent 051a5a4adc
commit bd8f0c1ef3
8 changed files with 71 additions and 14 deletions

View File

@ -17,6 +17,7 @@ import (
"os"
"path/filepath"
"runtime"
"runtime/pprof"
"sort"
"strings"
"time"
@ -46,6 +47,9 @@ nftables.txt: Anonymized nftables rules with packet counters, if --system-info f
config.txt: Anonymized configuration information of the NetBird client.
network_map.json: Anonymized network map containing peer configurations, routes, DNS settings, and firewall rules.
state.json: Anonymized client state dump containing netbird states.
mutex.prof: Mutex profiling information.
goroutine.prof: Goroutine profiling information.
block.prof: Block profiling information.
Anonymization Process
@ -88,6 +92,14 @@ The state file follows the same anonymization rules as other files:
- Domain names are consistently anonymized
- Technical identifiers and non-sensitive data remain unchanged
Mutex, Goroutines, and Block Profiling Files
The goroutine, block, and mutex profiling files contains process information that might help the NetBird team diagnose performance issues. The information in these files don't contain personal data.
You can check each using the following go command:
go tool pprof -http=:8088 mutex.prof
This will open a web browser tab with the profiling information.
Routes
For anonymized routes, the IP addresses are replaced as described above. The prefix length remains unchanged. Note that for prefixes, the anonymized IP might not be a network address, but the prefix length is still correct.
@ -188,6 +200,10 @@ func (s *Server) createArchive(bundlePath *os.File, req *proto.DebugBundleReques
s.addSystemInfo(req, anonymizer, archive)
}
if err := s.addProf(req, anonymizer, archive); err != nil {
log.Errorf("Failed to add goroutines rules to debug bundle: %v", err)
}
if err := s.addNetworkMap(req, anonymizer, archive); err != nil {
return fmt.Errorf("add network map: %w", err)
}
@ -310,6 +326,29 @@ func (s *Server) addCommonConfigFields(configContent *strings.Builder) {
configContent.WriteString(fmt.Sprintf("BlockLANAccess: %v\n", s.config.BlockLANAccess))
}
func (s *Server) addProf(req *proto.DebugBundleRequest, anonymizer *anonymize.Anonymizer, archive *zip.Writer) error {
runtime.SetBlockProfileRate(1)
_ = runtime.SetMutexProfileFraction(1)
defer runtime.SetBlockProfileRate(0)
defer runtime.SetMutexProfileFraction(0)
time.Sleep(5 * time.Second)
for _, profile := range []string{"goroutine", "block", "mutex"} {
var buff []byte
myBuff := bytes.NewBuffer(buff)
err := pprof.Lookup(profile).WriteTo(myBuff, 0)
if err != nil {
return fmt.Errorf("write %s profile: %w", profile, err)
}
if err := addFileToZip(archive, myBuff, profile+".prof"); err != nil {
return fmt.Errorf("add %s file to zip: %w", profile, err)
}
}
return nil
}
func (s *Server) addRoutes(req *proto.DebugBundleRequest, anonymizer *anonymize.Anonymizer, archive *zip.Writer) error {
routes, err := systemops.GetRoutesFromTable()
if err != nil {