夜莺修改日志


前端代码


一. 代码结构


- config: 开发 & 构建配置
  - proxy.config.js:代理配置
  - theme.js:antd 主题配置
  - webpack.config.js:webpack 开发环境补充配置,覆盖默认配置
  - webpack.build.config.js:webpack 构建补充配置,覆盖默认配置
  - webpack.build.config.js:webpack dll补充配置,覆盖默认配置
  - webpackConfigResolveAlias.js 文件路径别名配置
- src:源代码所在目录
  - assets:全局资源 img、css
  - common: 全局配置、通用方法
  - components:公共组件
  - pages:路由匹配的页面组件
  - app.jsx 菜单、路由配置组件
  - index.html:单页
  - index.jsx:入口文件
  - fetk.config.js 开发工具配置页面

二. 修改内容

1.添加接口查询功能

2.修改页面图标和公司名称

3.添加报警提示音

三. 代码修改记录

  • common/request.tsx
//新增
if (!data) {
    return data;
  }
  if(data.notify_type){
    return data;
  }
  • components/Layout/index.tsx
//新增定时任务 提示报警信息
    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("创林监控系统报警,   ip为"+res.event.endpoint+"    错误为"+res.event.sname);   
            new Audio(url).play()
          }
        }
      });
      
    },60000)
  • interface/index.tsx
//interface返回参数新增notify_type属性
notify_type:any | ResponseDat,
  • locales/zh.ts
//新增接口页面属性名
'collect.api': '接口',
'collect.api.name': '接口',
'collect.api.name.placeholder': 'http://xxx.xxxx.xxx/xxx',
'collect.api.ip': '主机ip',
'collect.api.ip.placeholder': '192.168.0.1',
  • pages/Monitor
    • Collect
      • CollectForm
        • APIForm.tsx
         //整页新增
        
        • index.tsx
         //新增页面
         export default {
           log: LOGForm,
           port: PORTForm,
           proc: PROCForm,
           plugin: PLUGINForm,
           api:APIForm, //新增
        };
        
      • config.tsx
       //typeMap新增api接口属性
       export const typeMap: any = {
        log: '日志',
        port: '端口',
        proc: '进程',
        plugin: '插件',
        api:'接口'//新增属性
      };
      
    • 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
       //新增采集数据信息提示
       title={() => {
          const currentMetricMeta = getCurrentMetricMeta(metric);
           if (currentMetricMeta) {
             return (
                <div>
                   <p>含义:{currentMetricMeta.meaning}</p>
                   <p>单位:{currentMetricMeta.unit}</p>
                </div>
             );
           }
        return '';
      }}
      

邮件服务


一. 代码结构

- mail-sender
- config          //配置
- cron            //发送数据
- dataobj         //警报结构体
- etc             //配置文件
- redisc          //redis操作方法

二. 修改内容

1.在报警邮件发送前向Redis存储报警信息

2.对外暴露一个报警信息查询接口,接口用成功后删除当前报警信息

三. 修改记录

  • cron/sender.go
//sendMail方法中新增
redisc.AddMessage(message)
  • redisc/poper.go
//新增两个数据
/**
添加报警数据
 */
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数据
        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转换失败", 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转换失败", 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转换失败", err
    }
    if(setres=="" || setres=="nil"){
        logger.Errorf("返回空")
    }
    return "ok", nil
    
}

/**
查找报警数据
 */
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数据
        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)
        //设置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函数下新增端口监听
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


一. 代码结构

  - collector
    - cache 
    - config        //结构体配置文件
    - http          //api接口配置
    - log
    - nginxInfo     //获取nginx实例数据
    - pgsqlInfo     //获取pgsql实例数据
    - redisInfo     //获取redis实例数据
    - stra          //采集配置结构体
    - sys           //采集配置实现
    - util          //网络请求工具包
    - collector.go  //入口

二. 修改内容

1.添加Redis数据监控

2.添加Pgsql数据监控

3.添加nginx数据监控

4.rpc数据交互改为http数据交互

三. 代码修改记录

  • config
    • data.go
    //新增data.go文件
    //夜莺插件提交规范结构体
    
    • log.go
    //新增自定义插件运行日志
    
    • yaml.go
    //新增自定义插件配置文件 
    //文件位置  etc/configuration.yml
    
  • nginxInfo
 //新增nginx.go文件
 //采集nginx实例
  • pgsqlInfo
 //新增pgsql.go文件
 //采集pgsql实例
  • redisInfo
 //新增redis.go文件
 //采集redis实例
  • sys
    -fengjiePlugins
    //新增cron.go
    //1.读取自定义插件配置内容
    //2.调用自定义插件采集方法
    
    • funcs
      • cron.go
      //该文件主要负责收集程序采集的数据并push到服务器
      //rpc 改用http 并发太高导致连接超时
      //修改方案:赋予每个并发请求一个随机延迟
      //动态判断 进行休眠
          b := rand.Intn(6000) //取随机数
          time.Sleep(time.Duration(b/100) * time.Second) //睡眠相应时间
      
      • push.go
      //新增 接口返回参数结构体
      type reportRes struct {
        Err string `json:"err"`
        Dat string `json:"dat"`
      }
      //当前方法先读取配置文件中的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提交数据
          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
    //给一个随机延迟
    b := rand.Intn(10000)
    time.Sleep(time.Duration(b/1000) * time.Second)
    

-collector.go

//调用自定义插件采集方法
//自定义插件采集
fengjiePlugins.Detect()

服务端collector


一. 代码结构

  - collector
    - cache 
    - config        //结构体配置文件
    - http          //api接口配置
    - log
    - nginxInfo     //获取nginx实例数据
    - pgsqlInfo     //获取pgsql实例数据
    - redisInfo     //获取redis实例数据
    - stra          //采集配置结构体
    - sys           //采集配置实现
    - util          //网络请求工具包
    - collector.go  //入口

二. 修改内容

1.新增接口定时查询功能

2.接口返回是否正常使用原rpc数据上报功能

三. 修改记录

  • stra/api.go
 //新增api.go文件
 //新增api结构体和获取用户配置的接口列表
  • sys/apiTest
//新增api.go,cron.go,scheduler.go文件
//所有关于接口的函数都在这里
  • collector.go
//启动接口数据采集
apiTest.Detect()

服务端monapi


一. 代码结构

- monapi
  - config
  - cron
  - http
  - mcache
  - notify
  - redisc
  - scache

二. 修改内容

1.新增查询所有采集配置为api的数据列表

2.修改采集配置创建接囗,新增api分类属性

3.mode 包下collet文件新增结构体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("同节点下策略名称 %s 已存在", name)
              }
              errors.Dangerous(model.CreateCollect(obj.Type, creator, collect))
    
    //给types数组新增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
    
          //校验采集是否存在
          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("同节点下策略名称 %s 已存在", name)
          }
    
          errors.Dangerous(collect.Update())
          renderData(c, "ok", nil)
          return
    
    • routes.go
    //新增不需要鉴权的接口
    api := r.Group("/api/portal")
      {
          api.GET("/collect/apiAllList", collectsGetApiAll)
      }
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355