//获取linux环境下崩溃栈(可以根据文件最后修改时间，知悉崩溃时间)
//pprof memory(cpu) need graphviz
//go tool pprof --pdf/web/svg http://10.105.57.151:8101/debug/pprof/heap(profile) >one.pdf

package util

import (
	"dsbqj-admin/pkg/logger"
	"fmt"
	"log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/exec"
	"syscall"
)

func init() {
	os.MkdirAll("logs", 0660)
	logFile, err := os.OpenFile("logs/sysdebug.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0660)
	if err != nil {
		log.Println("open sysdebug err:", err.Error())
		return
	}
	// 将进程标准出错重定向至文件，进程崩溃时运行时将向该文件记录协程调用栈信息
	syscall.Dup2(int(logFile.Fd()), int(os.Stderr.Fd()))
	log.Println("program runtime...")
	//监控pprof
	ListenPprof()
}

// 端口号是否正在被使用
func PortInUse(port int) bool {
	checkStatement := fmt.Sprintf("lsof -i:%d ", port)
	output, _ := exec.Command("sh", "-c", checkStatement).CombinedOutput()
	if len(output) > 0 {
		return true
	}
	return false
}

// 监控pprof
func ListenPprof() {
	go func() {
		port := 6060
		for i := 0; i < 1000; i++ { //从6060开始，找一个空闲的端口号
			if PortInUse(port) {
				port++
			} else {
				break
			}
		}
		logger.Info("start listen pprof: %d", port)
		err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
		if err != nil {
			logger.Error("pprof listen err: %s", err.Error())
		}
	}()
}

// 发送警告
func SendAlarm(group string, content string) {
	if group == "" {
		return
	}
	command := fmt.Sprint("cagent_tools alarm  '《指挥官》", content, "' ", group)
	cmd := exec.Command("/bin/bash", "-c", command)

	output, err := cmd.Output()
	if err != nil {
		log.Printf("Execute Shell:%s failed with error:%s", command, err.Error())
		return
	}
	log.Printf("Execute Shell:%s finished with output:\n%s", command, string(output))

}
