func configPluginRoutes() { http.HandleFunc("/plugin/update", func(w http.ResponseWriter, r *http.Request) { if !g.Config().Plugin.Enabled { w.Write([]byte("plugin not enabled")) return } dir := g.Config().Plugin.Dir parentDir := file.Dir(dir) file.InsureDir(parentDir) if file.IsExist(dir) { // git pull cmd := exec.Command("git", "pull") cmd.Dir = dir err := cmd.Run() if err != nil { w.Write([]byte(fmt.Sprintf("git pull in dir:%s fail. error: %s", dir, err))) return } } else { // git clone cmd := exec.Command("git", "clone", g.Config().Plugin.Git, file.Basename(dir)) cmd.Dir = parentDir err := cmd.Run() if err != nil { w.Write([]byte(fmt.Sprintf("git clone in dir:%s fail. error: %s", parentDir, err))) return } } w.Write([]byte("success")) }) http.HandleFunc("/plugin/reset", func(w http.ResponseWriter, r *http.Request) { if !g.Config().Plugin.Enabled { w.Write([]byte("plugin not enabled")) return } dir := g.Config().Plugin.Dir if file.IsExist(dir) { cmd := exec.Command("git", "reset", "--hard") cmd.Dir = dir err := cmd.Run() if err != nil { w.Write([]byte(fmt.Sprintf("git reset --hard in dir:%s fail. error: %s", dir, err))) return } } w.Write([]byte("success")) }) http.HandleFunc("/plugins", func(w http.ResponseWriter, r *http.Request) { //TODO: not thread safe RenderDataJson(w, plugins.Plugins) }) }
func Collect() { if !g.Config().Transfer.Enabled { return } if g.Config().Transfer.Addr == "" { return } for _, v := range funcs.Mappers { go collect(int64(v.Interval), v.Fs) } }
func SyncMinePlugins() { if !g.Config().Plugin.Enabled { return } if !g.Config().Heartbeat.Enabled { return } if g.Config().Heartbeat.Addr == "" { return } go syncMinePlugins() }
func configAdminRoutes() { http.HandleFunc("/exit", func(w http.ResponseWriter, r *http.Request) { if g.IsTrustable(r.RemoteAddr) { w.Write([]byte("exiting...")) go func() { time.Sleep(time.Second) os.Exit(0) }() } else { w.Write([]byte("no privilege")) } }) http.HandleFunc("/config/reload", func(w http.ResponseWriter, r *http.Request) { if g.IsTrustable(r.RemoteAddr) { g.ParseConfig(g.ConfigFile) RenderDataJson(w, g.Config()) } else { w.Write([]byte("no privilege")) } }) http.HandleFunc("/workdir", func(w http.ResponseWriter, r *http.Request) { RenderDataJson(w, file.SelfDir()) }) http.HandleFunc("/ips", func(w http.ResponseWriter, r *http.Request) { RenderDataJson(w, g.TrustableIps()) }) }
func InitDataHistory() { for { //如果有数据需要两次调用才能采集的,需要在这里提前初始化一次 funcs.UpdateIfStat() time.Sleep(time.Duration(g.Config().Transfer.Interval) * time.Second) } }
func Start() { if !g.Config().Http.Enabled { return } addr := g.Config().Http.Listen if addr == "" { return } s := &http.Server{ Addr: addr, MaxHeaderBytes: 1 << 30, } log.Println("listening", addr) log.Fatalln(s.ListenAndServe()) }
func NetMetrics() (L []*model.MetricValue) { interval := g.Config().Transfer.Interval for i := 0; i < len(ifStatHistory); i++ { tags := fmt.Sprintf("iface=%s", ifStatHistory[i].Name) L = append(L, GaugeValue("win.net.if.in.bytes", (ifStatCurrent[i].BytesReceivedPersec-ifStatHistory[i].BytesReceivedPersec)/interval, tags)) L = append(L, GaugeValue("win.net.if.out.bytes", (ifStatCurrent[i].BytesSentPersec-ifStatHistory[i].BytesSentPersec)/interval, tags)) L = append(L, GaugeValue("win.net.if.total.bytes", (ifStatCurrent[i].BytesTotalPersec-ifStatHistory[i].BytesTotalPersec)/interval, tags)) L = append(L, GaugeValue("win.net.if.in.packets", (ifStatCurrent[i].PacketsReceivedPersec-ifStatHistory[i].PacketsReceivedPersec)/interval, tags)) L = append(L, GaugeValue("win.net.if.out.packets", (ifStatCurrent[i].PacketsSentPersec-ifStatHistory[i].PacketsSentPersec)/interval, tags)) L = append(L, GaugeValue("win.net.if.total.packets", (ifStatCurrent[i].PacketsPersec-ifStatHistory[i].PacketsPersec)/interval, tags)) L = append(L, GaugeValue("win.net.if.bandwidth", ifStatHistory[i].CurrentBandwidth, tags)) } return }
func BuildMappers() { interval := g.Config().Transfer.Interval Mappers = []FuncsAndInterval{ FuncsAndInterval{ Fs: []func() []*model.MetricValue{ AgentMetrics, CpuMetrics, NetMetrics, MemMetrics, DiskIOMetrics, DeviceMetrics, ProcMetrics, }, Interval: interval, }, } }
func syncTrustableIps() { duration := time.Duration(g.Config().Heartbeat.Interval) * time.Second for { REST: time.Sleep(duration) var ips string err := g.HbsClient.Call("Agent.TrustableIps", model.NullRpcRequest{}, &ips) if err != nil { log.Println("ERROR: call Agent.TrustableIps fail", err) goto REST } g.SetTrustableIps(ips) } }
func collect(sec int64, fns []func() []*model.MetricValue) { for { REST: time.Sleep(time.Duration(sec) * time.Second) hostname, err := g.Hostname() if err != nil { goto REST } mvs := []*model.MetricValue{} ignoreMetrics := g.Config().IgnoreMetrics for _, fn := range fns { items := fn() if items == nil { continue } if len(items) == 0 { continue } for _, mv := range items { if b, ok := ignoreMetrics[mv.Metric]; ok && b { continue } else { mvs = append(mvs, mv) } } } now := time.Now().Unix() for j := 0; j < len(mvs); j++ { mvs[j].Step = sec mvs[j].Endpoint = hostname mvs[j].Timestamp = now } g.SendToTransfer(mvs) } }
func PluginRun(plugin *Plugin) { timeout := plugin.Cycle*1000 - 500 fpath := filepath.Join(g.Config().Plugin.Dir, plugin.FilePath) if !file.IsExist(fpath) { log.Println("no such plugin:", fpath) return } debug := g.Config().Debug if debug { log.Println(fpath, "running...") } cmd := exec.Command(fpath) var stdout bytes.Buffer cmd.Stdout = &stdout var stderr bytes.Buffer cmd.Stderr = &stderr cmd.Start() err, isTimeout := sys.CmdRunWithTimeout(cmd, time.Duration(timeout)*time.Millisecond) errStr := stderr.String() if errStr != "" { logFile := filepath.Join(g.Config().Plugin.LogDir, plugin.FilePath+".stderr.log") if _, err = file.WriteString(logFile, errStr); err != nil { log.Printf("[ERROR] write log to %s fail, error: %s\n", logFile, err) } } if isTimeout { // has be killed if err == nil && debug { log.Println("[INFO] timeout and kill process", fpath, "successfully") } if err != nil { log.Println("[ERROR] kill process", fpath, "occur error:", err) } return } if err != nil { log.Println("[ERROR] exec plugin", fpath, "fail. error:", err) return } // exec successfully data := stdout.Bytes() if len(data) == 0 { if debug { log.Println("[DEBUG] stdout of", fpath, "is blank") } return } var metrics []*model.MetricValue err = json.Unmarshal(data, &metrics) if err != nil { log.Printf("[ERROR] json.Unmarshal stdout of %s fail. error:%s stdout: \n%s\n", fpath, err, stdout.String()) return } g.SendToTransfer(metrics) }
func syncMinePlugins() { var ( checksum string = "nil" timestamp int64 = -1 pluginDirs []string ) duration := time.Duration(g.Config().Heartbeat.Interval) * time.Second for { REST: time.Sleep(duration) hostname, err := g.Hostname() if err != nil { goto REST } req := model.AgentHeartbeatRequest{ Hostname: hostname, Checksum: checksum, } var resp model.AgentPluginsResponse err = g.HbsClient.Call("Agent.MinePlugins", req, &resp) if err != nil { log.Println("ERROR:", err) goto REST } if resp.Timestamp <= timestamp { goto REST } if resp.Checksum == checksum { goto REST } pluginDirs = resp.Plugins timestamp = resp.Timestamp checksum = resp.Checksum if g.Config().Debug { log.Println(&resp) } if len(pluginDirs) == 0 { plugins.ClearAllPlugins() } desiredAll := make(map[string]*plugins.Plugin) for _, p := range pluginDirs { underOneDir := plugins.ListPlugins(strings.Trim(p, "/")) for k, v := range underOneDir { desiredAll[k] = v } } plugins.DelNoUsePlugins(desiredAll) plugins.AddNewPlugins(desiredAll) } }
func ReportAgentStatus() { if g.Config().Heartbeat.Enabled && g.Config().Heartbeat.Addr != "" { go reportAgentStatus(time.Duration(g.Config().Heartbeat.Interval) * time.Second) } }
func SyncTrustableIps() { if g.Config().Heartbeat.Enabled && g.Config().Heartbeat.Addr != "" { go syncTrustableIps() } }
func syncBuiltinMetrics() { var timestamp int64 = -1 var checksum string = "nil" duration := time.Duration(g.Config().Heartbeat.Interval) * time.Second for { REST: time.Sleep(duration) var ports = []int64{} var procs = make(map[string]map[int]string) hostname, err := g.Hostname() if err != nil { goto REST } req := model.AgentHeartbeatRequest{ Hostname: hostname, Checksum: checksum, } var resp model.BuiltinMetricResponse err = g.HbsClient.Call("Agent.BuiltinMetrics", req, &resp) if err != nil { log.Println("ERROR:", err) goto REST } if resp.Timestamp <= timestamp { goto REST } if resp.Checksum == checksum { goto REST } timestamp = resp.Timestamp checksum = resp.Checksum for _, metric := range resp.Metrics { if metric.Metric == "net.port.listen" { if !strings.Contains(metric.Tags, "=") { // illegal continue } if port, err := strconv.ParseInt(metric.Tags[5:], 10, 64); err == nil { ports = append(ports, port) } continue } if metric.Metric == "proc.num" { arr := strings.Split(metric.Tags, ",") tmpMap := make(map[int]string) for i := 0; i < len(arr); i++ { if strings.HasPrefix(arr[i], "name=") { tmpMap[1] = arr[i][5:] } else if strings.HasPrefix(arr[i], "cmdline=") { tmpMap[2] = arr[i][8:] } } procs[metric.Tags] = tmpMap } } g.SetReportPorts(ports) g.SetReportProcs(procs) } }
func SyncBuiltinMetrics() { if g.Config().Heartbeat.Enabled && g.Config().Heartbeat.Addr != "" { go syncBuiltinMetrics() } }