volcano.sh/volcano@v1.9.0/pkg/scheduler/cache/dumper.go (about) 1 /* 2 Copyright 2023 The Volcano Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package cache 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "os" 23 "os/signal" 24 "path" 25 "runtime" 26 "strings" 27 "syscall" 28 "time" 29 30 "k8s.io/klog/v2" 31 32 "volcano.sh/volcano/pkg/scheduler/api" 33 ) 34 35 // Dumper writes some information from the scheduler cache to the scheduler logs 36 // for debugging purposes. Usage: run `kill -s USR2 <pid>` in the shell, where <pid> 37 // is the process id of the scheduler process. 38 type Dumper struct { 39 Cache Cache 40 RootDir string // target directory for the dumped json file 41 } 42 43 // dumpToJSONFile marsh scheduler cache snapshot to json file 44 func (d *Dumper) dumpToJSONFile() { 45 snapshot := d.Cache.Snapshot() 46 name := fmt.Sprintf("snapshot-%d.json", time.Now().Unix()) 47 fName := path.Join(d.RootDir, name) 48 file, err := os.OpenFile(fName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) 49 if err != nil { 50 klog.Errorf("error creating snapshot because of error creating file: %v", err) 51 return 52 } 53 defer file.Close() 54 klog.Infoln("Starting to dump info in scheduler cache to file", fName) 55 if err = json.NewEncoder(file).Encode(snapshot.Nodes); err != nil { 56 klog.Errorf("Failed to dump info in scheduler cache, json encode error: %v", err) 57 return 58 } 59 60 klog.Infoln("Successfully dump info in scheduler cache to file", fName) 61 } 62 63 // dumpAll prints all information to log 64 func (d *Dumper) dumpAll() { 65 snapshot := d.Cache.Snapshot() 66 klog.Info("Dump of nodes info in scheduler cache") 67 for _, nodeInfo := range snapshot.Nodes { 68 klog.Info(d.printNodeInfo(nodeInfo)) 69 } 70 71 klog.Info("Dump of jobs info in scheduler cache") 72 for _, jobInfo := range snapshot.Jobs { 73 klog.Info(d.printJobInfo(jobInfo)) 74 } 75 76 d.displaySchedulerMemStats() 77 } 78 79 func (d *Dumper) displaySchedulerMemStats() { 80 var m runtime.MemStats 81 runtime.ReadMemStats(&m) 82 klog.Infof("volcano scheduler memory stat: %+v\n", m) 83 } 84 85 func (d *Dumper) printNodeInfo(node *api.NodeInfo) string { 86 var data strings.Builder 87 data.WriteString("\n") 88 data.WriteString(node.String()) 89 data.WriteString("\n") 90 return data.String() 91 } 92 93 func (d *Dumper) printJobInfo(jobInfo *api.JobInfo) string { 94 var data strings.Builder 95 data.WriteString("\n") 96 data.WriteString(jobInfo.String()) 97 data.WriteString("\n") 98 return data.String() 99 } 100 101 // ListenForSignal starts a goroutine that will respond when process 102 // receives SIGUSER1/SIGUSER2 signal. 103 func (d *Dumper) ListenForSignal(stopCh <-chan struct{}) { 104 ch1 := make(chan os.Signal, 1) 105 ch2 := make(chan os.Signal, 1) 106 signal.Notify(ch1, syscall.SIGUSR1) 107 signal.Notify(ch2, syscall.SIGUSR2) 108 go func() { 109 for { 110 select { 111 case <-stopCh: 112 return 113 case <-ch1: 114 d.dumpToJSONFile() 115 case <-ch2: 116 d.dumpAll() 117 } 118 } 119 }() 120 }