前端代碼
一. 代碼結(jié)構(gòu)
- config: 開發(fā) & 構(gòu)建配置
- proxy.config.js:代理配置
- theme.js:antd 主題配置
- webpack.config.js:webpack 開發(fā)環(huán)境補(bǔ)充配置文兑,覆蓋默認(rèn)配置
- webpack.build.config.js:webpack 構(gòu)建補(bǔ)充配置,覆蓋默認(rèn)配置
- webpack.build.config.js:webpack dll補(bǔ)充配置七扰,覆蓋默認(rèn)配置
- webpackConfigResolveAlias.js 文件路徑別名配置
- src:源代碼所在目錄
- assets:全局資源 img、css
- common: 全局配置敬尺、通用方法
- components:公共組件
- pages:路由匹配的頁(yè)面組件
- app.jsx 菜單闰围、路由配置組件
- index.html:?jiǎn)雾?yè)
- index.jsx:入口文件
- fetk.config.js 開發(fā)工具配置頁(yè)面
二. 修改內(nèi)容
1.添加接口查詢功能
2.修改頁(yè)面圖標(biāo)和公司名稱
3.添加報(bào)警提示音
三. 代碼修改記錄
- common/request.tsx
//新增
if (!data) {
return data;
}
if(data.notify_type){
return data;
}
- components/Layout/index.tsx
//新增定時(shí)任務(wù) 提示報(bào)警信息
this.timerID =self.setInterval(()=>{
request("/api/alarm").then((res: any) => {
console.log(res);
console.log("查詢");
if(res){
if(res.event.endpoint){
message.warn(res.event.sname);
var url= "http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&spd=5&text=" + encodeURI("創(chuàng)林監(jiān)控系統(tǒng)報(bào)警消恍, ip為"+res.event.endpoint+" 錯(cuò)誤為"+res.event.sname);
new Audio(url).play()
}
}
});
},60000)
- interface/index.tsx
//interface返回參數(shù)新增notify_type屬性
notify_type:any | ResponseDat,
- locales/zh.ts
//新增接口頁(yè)面屬性名
'collect.api': '接口',
'collect.api.name': '接口',
'collect.api.name.placeholder': 'http://xxx.xxxx.xxx/xxx',
'collect.api.ip': '主機(jī)ip',
'collect.api.ip.placeholder': '192.168.0.1',
- pages/Monitor
- Collect
- CollectForm
- APIForm.tsx
//整頁(yè)新增
- index.tsx
//新增頁(yè)面 export default { log: LOGForm, port: PORTForm, proc: PROCForm, plugin: PLUGINForm, api:APIForm, //新增 };
- config.tsx
//typeMap新增api接口屬性 export const typeMap: any = { log: '日志', port: '端口', proc: '進(jìn)程', plugin: '插件', api:'接口'//新增屬性 };
- CollectForm
- Dashboard
- config.tsx
//metricMap新增redis,nginx豺总,pgsql分類 nginx: { key: 'nginx', alias: 'nginx', dynamic: true, filter: { type: 'prefix', value: 'nginx.,NGINX.' }, }, pgsql: { key: 'pgsql', alias: 'pgsql', dynamic: true, filter: { type: 'prefix', value: 'pgsql.,PGSQL.' }, }, redis: { key: 'redis', alias: 'redis', dynamic: true, filter: { type: 'prefix', value: 'redis.,Redis.' }, },
- MetricSelect.tsx
//新增采集數(shù)據(jù)信息提示 title={() => { const currentMetricMeta = getCurrentMetricMeta(metric); if (currentMetricMeta) { return ( <div> <p>含義:{currentMetricMeta.meaning}</p> <p>單位:{currentMetricMeta.unit}</p> </div> ); } return ''; }}
- Collect
郵件服務(wù)
一. 代碼結(jié)構(gòu)
- mail-sender
- config //配置
- cron //發(fā)送數(shù)據(jù)
- dataobj //警報(bào)結(jié)構(gòu)體
- etc //配置文件
- redisc //redis操作方法
二. 修改內(nèi)容
1.在報(bào)警郵件發(fā)送前向Redis存儲(chǔ)報(bào)警信息
2.對(duì)外暴露一個(gè)報(bào)警信息查詢接口车伞,接口用成功后刪除當(dāng)前報(bào)警信息
三. 修改記錄
- cron/sender.go
//sendMail方法中新增
redisc.AddMessage(message)
- redisc/poper.go
//新增兩個(gè)數(shù)據(jù)
/**
添加報(bào)警數(shù)據(jù)
*/
func AddMessage(message *dataobj.Message) (string,error) {
var lst []*dataobj.Message
rc := RedisConnPool.Get()
defer rc.Close()
reply, err := redis.String(rc.Do("GET", "alarm-message"))
if err != nil {
if err != redis.ErrNil {
logger.Errorf("rpop queue:%s failed, err: %v", "alarm-message", err)
}
}
if reply == "" || reply == "nil" {
//讀取到的是空 新增alarm-message數(shù)據(jù)
lst=append(lst,message)
}else{
err = json.Unmarshal([]byte(reply), &lst)
if err != nil {
logger.Errorf("unmarshal message failed, err: %v, redis reply: %v", err, reply)
return "json轉(zhuǎn)換失敗", err
}
lst=append(lst,message)
}
jsonArr,err:=json.Marshal(lst)
if err != nil {
logger.Errorf("unmarshal message failed, err: %v, redis reply: %v", err, reply)
return "json轉(zhuǎn)換失敗", err
}
setres,err:=redis.String(rc.Do("SET","alarm-message",jsonArr))
if err != nil {
logger.Errorf("unmarshal message failed, err: %v, redis reply: %v", err, reply)
return "json轉(zhuǎn)換失敗", err
}
if(setres=="" || setres=="nil"){
logger.Errorf("返回空")
}
return "ok", nil
}
/**
查找報(bào)警數(shù)據(jù)
*/
func FindMessage() (*dataobj.Message,error){
var lst []*dataobj.Message
rc := RedisConnPool.Get()
defer rc.Close()
reply, err := redis.String(rc.Do("GET", "alarm-message"))
if err != nil {
if err != redis.ErrNil {
logger.Errorf("rpop queue:%s failed, err: %v", "alarm-message", err)
}
return nil, err
}
if reply == "" || reply == "nil" {
//讀取到的是空 新增alarm-message數(shù)據(jù)
return nil, err
} else{
err = json.Unmarshal([]byte(reply), &lst)
if err != nil {
logger.Errorf("unmarshal message failed, err: %v, redis reply: %v", err, reply)
return nil, err
}
if(len(lst)<=0){
return nil, err
}
res :=lst[0]
lst=lst[1:len(lst)]
jsonArr,err:=json.Marshal(lst)
if err != nil {
logger.Errorf("unmarshal message failed, err: %v, redis reply: %v", err, reply)
return nil, err
}
//刪除
del,err := redis.Bool(rc.Do("DEL","alarm-message"))
if err != nil {
logger.Errorf("unmarshal message failed, err: %v, redis reply: %v", err, reply)
return nil, err
}
fmt.Println(del)
//設(shè)置message
setres,err:=redis.String(rc.Do("SET","alarm-message",jsonArr))
if err != nil {
logger.Errorf("unmarshal message failed, err: %v, redis reply: %v", err, reply)
return nil, err
}
if(setres=="" || setres=="nil"){
logger.Errorf("返回空")
}
return res, nil
}
}
- main.go
//main函數(shù)下新增端口監(jiān)聽(tīng)
http.HandleFunc("/", indexHandler)
port := os.Getenv("PORT")
if port == "" {
port = "8082"
log.Printf("Defaulting to port %s", port)
}
log.Printf("Listening on port %s", port)
log.Printf("Open http://localhost:%s in the browser", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
//新增接口路由
func indexHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
_, err := fmt.Fprint(w, "Hello, World!````````` ")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
}
if r.URL.Path == "/api/alarm" {
res,err:=redisc.FindMessage()
b,err:=json.Marshal(res)
if err != nil {
fmt.Println("失敗")
}
w.Header().Set("Content-Type","application/json; charset=utf-8")
w.Header().Set("Content-Length", strconv.Itoa(len(b)))
w.Write(b)
}else {
http.NotFound(w, r)
return
}
客戶端collector
一. 代碼結(jié)構(gòu)
- collector
- cache
- config //結(jié)構(gòu)體配置文件
- http //api接口配置
- log
- nginxInfo //獲取nginx實(shí)例數(shù)據(jù)
- pgsqlInfo //獲取pgsql實(shí)例數(shù)據(jù)
- redisInfo //獲取redis實(shí)例數(shù)據(jù)
- stra //采集配置結(jié)構(gòu)體
- sys //采集配置實(shí)現(xiàn)
- util //網(wǎng)絡(luò)請(qǐng)求工具包
- collector.go //入口
二. 修改內(nèi)容
1.添加Redis數(shù)據(jù)監(jiān)控
2.添加Pgsql數(shù)據(jù)監(jiān)控
3.添加nginx數(shù)據(jù)監(jiān)控
4.rpc數(shù)據(jù)交互改為http數(shù)據(jù)交互
三. 代碼修改記錄
- config
- data.go
//新增data.go文件 //夜鶯插件提交規(guī)范結(jié)構(gòu)體
- log.go
//新增自定義插件運(yùn)行日志
- yaml.go
//新增自定義插件配置文件 //文件位置 etc/configuration.yml
- nginxInfo
//新增nginx.go文件
//采集nginx實(shí)例
- pgsqlInfo
//新增pgsql.go文件
//采集pgsql實(shí)例
- redisInfo
//新增redis.go文件
//采集redis實(shí)例
- sys
-fengjiePlugins//新增cron.go //1.讀取自定義插件配置內(nèi)容 //2.調(diào)用自定義插件采集方法
- funcs
- cron.go
//該文件主要負(fù)責(zé)收集程序采集的數(shù)據(jù)并push到服務(wù)器 //rpc 改用http 并發(fā)太高導(dǎo)致連接超時(shí) //修改方案:賦予每個(gè)并發(fā)請(qǐng)求一個(gè)隨機(jī)延遲 //動(dòng)態(tài)判斷 進(jìn)行休眠 b := rand.Intn(6000) //取隨機(jī)數(shù) time.Sleep(time.Duration(b/100) * time.Second) //睡眠相應(yīng)時(shí)間
- push.go
//新增 接口返回參數(shù)結(jié)構(gòu)體 type reportRes struct { Err string `json:"err"` Dat string `json:"dat"` } //當(dāng)前方法先讀取配置文件中的openRpc屬性判斷是否啟用rpc openRpc:=address.GetOpenRpc("transfer") if(openRpc){ //開啟openrpc fmt.Println("openrpc") count := len(addrs) retry := 0 for { for _, i := range rand.Perm(count) { addr := addrs[i] logger.Error("Push"+addr) reply, err := rpcCall(addr, items) if err != nil { logger.Error(err) continue } else { if reply.Msg != "ok" { err = fmt.Errorf("some item push err: %s", reply.Msg) logger.Error(err) } return err } } time.Sleep(time.Millisecond * 500) retry += 1 if retry == 3 { break } } }else { //http提交數(shù)據(jù) url:=address.GetApi("transfer") var res reportRes err := httplib.Post(url).JSONBodyQuiet(items).SetTimeout(2000 * time.Millisecond).ToJSON(&res) if err != nil { logger.Errorf("curl %s fail: %v", url, err) fmt.Println("curl %s fail: %v", url, err) fmt.Println(items[0].Metric) } if res.Err != "" { logger.Error(res.Err) } }
- plugins | ports | procs
//修改scheduler.go //給一個(gè)隨機(jī)延遲 b := rand.Intn(10000) time.Sleep(time.Duration(b/1000) * time.Second)
- funcs
-collector.go
//調(diào)用自定義插件采集方法
//自定義插件采集
fengjiePlugins.Detect()
服務(wù)端collector
一. 代碼結(jié)構(gòu)
- collector
- cache
- config //結(jié)構(gòu)體配置文件
- http //api接口配置
- log
- nginxInfo //獲取nginx實(shí)例數(shù)據(jù)
- pgsqlInfo //獲取pgsql實(shí)例數(shù)據(jù)
- redisInfo //獲取redis實(shí)例數(shù)據(jù)
- stra //采集配置結(jié)構(gòu)體
- sys //采集配置實(shí)現(xiàn)
- util //網(wǎng)絡(luò)請(qǐng)求工具包
- collector.go //入口
二. 修改內(nèi)容
1.新增接口定時(shí)查詢功能
2.接口返回是否正常使用原rpc數(shù)據(jù)上報(bào)功能
三. 修改記錄
- stra/api.go
//新增api.go文件
//新增api結(jié)構(gòu)體和獲取用戶配置的接口列表
- sys/apiTest
//新增api.go,cron.go,scheduler.go文件
//所有關(guān)于接口的函數(shù)都在這里
- collector.go
//啟動(dòng)接口數(shù)據(jù)采集
apiTest.Detect()
服務(wù)端monapi
一. 代碼結(jié)構(gòu)
- monapi
- config
- cron
- http
- mcache
- notify
- redisc
- scache
二. 修改內(nèi)容
1.新增查詢所有采集配置為api的數(shù)據(jù)列表
2.修改采集配置創(chuàng)建接囗,新增api分類屬性
3.mode 包下collet文件新增結(jié)構(gòu)體ApiCollect园欣,并新增添加帖世,刪除,更新沸枯,查詢方法
三. 修改記錄
- http/routes
- collect.go
//collectPost方法下新增 api分類 case "api": collect := new(model.ApiCollect) b, err := json.Marshal(obj.Data) if err != nil { errors.Bomb("marshal body %s err:%v", obj, err) } err = json.Unmarshal(b, collect) if err != nil { errors.Bomb("unmarshal body %s err:%v", string(b), err) } collect.Creator = creator collect.LastUpdator = creator nid := collect.Nid name := collect.Name old, _ := model.GetCollectByName(obj.Type, name) if old != nil && int64(old.(map[string]interface{})["nid"].(float64)) == nid { errors.Bomb("同節(jié)點(diǎn)下策略名稱 %s 已存在", name) } errors.Dangerous(model.CreateCollect(obj.Type, creator, collect)) //給types數(shù)組新增api屬性 types := []string{"port", "proc", "log", "plugin","api"} //新增獲取所有api的方法 func collectsGetApiAll(c *gin.Context) { collects, err := model.GetApiCollect() if err != nil { logger.Warning("api", err) } if err == nil { c.JSON(200, gin.H{"dat": collects, "err": ""}) return } renderMessage(c, err.Error()) } //collectPut方法下新增 case "api": collect := new(model.ApiCollect) b, err := json.Marshal(recv.Data) if err != nil { errors.Bomb("marshal body %s err:%v", recv, err) } err = json.Unmarshal(b, collect) if err != nil { errors.Bomb("unmarshal body %s err:%v", string(b), err) } nid := collect.Nid name := collect.Name //校驗(yàn)采集是否存在 obj, err := model.GetCollectById(recv.Type, collect.Id) //id找不到的情況 if err != nil { errors.Bomb("采集不存在 type:%s id:%d", recv.Type, collect.Id) } tmpId := obj.(*model.ApiCollect).Id if tmpId == 0 { errors.Bomb("采集不存在 type:%s id:%d", recv.Type, collect.Id) } collect.Creator = creator collect.LastUpdator = creator old, _ := model.GetCollectByName(recv.Type, name) if old != nil && int64(old.(map[string]interface{})["nid"].(float64)) == nid && tmpId != collect.Id { errors.Bomb("同節(jié)點(diǎn)下策略名稱 %s 已存在", name) } errors.Dangerous(collect.Update()) renderData(c, "ok", nil) return
- routes.go
//新增不需要鑒權(quán)的接口 api := r.Group("/api/portal") { api.GET("/collect/apiAllList", collectsGetApiAll) }