文章
· 十月 21, 2022 阅读大约需 6 分钟

基于cconsole.log的cache数据库的实时监控

cache数据库自身带有系统监控Portal界面,但需要运维人员定期主动查看才能获取监控信息。当系统故障发生时,容易出现由于没有及时获取故障信息而不能及时处理,从而导致造成的影响扩大。本文研究通过解析cache数据库控制台日志(cconsole.log)进行监控信息获取并主动推送微信或短信实现cache数据库主动实时监控。

cache数据库在运行时会将所有控制台消息包括一般消息、系统错误、某些操作系统错误和网络错误都会发送到控制台日志文件,通过操作员控制台工具从其他系统远程启动的作业的成功或失败等信息也会写入控制台日志,因此通过对控制台日志的解析即可获取所需要监控信息。具体步骤方法如下:

解析控制台日志

控制台日志默认存储在install-dir\mgr路径下。

根据cache版本不同,使用的读取方法也不同。对于cache2016版本以上,系统提供了EnsLib.SQL.Snapshot类,可以直接获取日志的行和列信息,非常方便。对于cache2010及以下版本则无此方法,需要使用%File文件读取方法。

随着系统运行时间增加,控制台日志也会不断增大,造成每次检索时间加大,且不容易找出最近的监控信息,作出有效监控。较好的方式是每次解析时均从上次的节点继续进行,以便获取新的有效的监控信息。可以使用指定global来记录每次执行的最后一行ID,下次执行时从ID+1行开始解析来达到目的。对于控制台日志,EnsLib.SQL.Snapshot方法里提供了方法以获取当前行,对于cache2010及以下版本,则需要记录最后一次处理的内容,再次处理的时先找到本条内容的位置,从此位置继续处理代码示例如下。

cache2016及以上版本代码示例:

ClassMethod GetAlertInfo() As %String
{

//cconsole.log存储路径
  set FilePath="D:\InterSystems\HealthShare\mgr\cconsole.log" 

//使用EnsLib.SQL.Snapshot读取日志
  set snap=##class(EnsLib.SQL.Snapshot).%New()
      set snap.MaxRowsToGet=-1
      do snap.ImportFile(FilePath,," ")
      do Consolelogshow
      do snap.Clean()
      quit $$$OK

//处理日志内容
Consolelogshow
      set colsCount=snap.ColCount

//获取上一次处理的最后一行行号
      set snap.%CurrentRow=$g(^AlertCurrentRow("Consolelog","CurrentRow"))
      k ^AlertCurrentRow("Consolelog","PID")
      while snap.Next()
      {
           set alertLevel=snap.GetData(3)
           set pid=snap.GetData(2)
           set pid=$p(pid,"(",2)
           set pid=$p(pid,")",1)
           continue:pid=""

 //0级别信息不处理
           continue:((alertLevel=0))

 //进程号已存在不处理,即只获取每次每个进程的第一条告警/错误信息
           continue:($d(^AlertCurrentRow("Consolelog","PID",pid)))

 //记录已处理的进程号
           set ^AlertCurrentRow("Consolelog","PID",pid)=1

 //定义并组装监控消息内容
           set alertInfo=""
           i ((alertLevel=1)||(alertLevel=2)||(alertLevel=3)){
           f i=4:1:colsCount{
               set alertInfo=alertInfo_" "_snap.GetData(i)
           }
           set alertInfo=snap.GetData(1)_":"_alertLevel_":"_alertInfo
           continue:((alertLevel=1)&&(alertInfo'["Warning"))

 //发送监控信息至信息推送平台,如微信或短信等
           set rt=..sendAlertInfo(alertInfo)
           }

 //记录当前处理的行
           set ^AlertCurrentRow("Consolelog","CurrentRow")=snap.%CurrentRow
  }
      quit $$$OK
}

cache2010及以下版本代码示例:

ClassMethod GetAlertInfo() As %String
{
  //使用%File读取日志
  set file=##class(%File).%New("/cachesys/mgr/cconsole.log")
  set Status= file.Open("R")
  k ^AlertCurrentRow("Consolelog","PID")

  //获取上次处理的信息内容
     set LastPosition=$g(^AlertCurrentRow("Consolelog","LastPosition"))
  s:LastPosition="" LastPosition=0
  set LastPosition=LastPosition+1
  set int=0
  while 'file.AtEnd{
    i int=0{

      //跳转到上次处理的最后位置
      do file.MoveTo(LastPosition)
    }
    set file.LineTerminator=$c(10)
    set text= file.ReadLine(,.sc)
    set int=int+1

    //解析日志
    set pid=$p(text," ",2)
    set pid=$p(pid,"(",2)
    set pid=$p(pid,")",1)
    set alertLevel=$p(text," ",3)
    s:text'="" textLast=text

    //定义并组装监控消息内容
   i  
((alertLevel=1)&&(alertLevel["Warning"))||(alertLevel=2)||(alertLevel=3){
   set length=$length(text," ")
   set alert="",alertInfo=""
   f i=4:1:length{
     set alert=$p(text," ",i)
     i i=4{
       set alertInfo=alert
     }else{
       set alertInfo=alertInfo_" "_alert
     }
   }
   set alertInfo=$p(text," ",1)_": "_alertLevel_": "_pid_":"_alertInfo
   set alertInfo=$zcvt(alertInfo,"O","UTF8")
   i '$d(^AlertCurrentRow("Consolelog","PID",pid)){

      //记录已处理的进程号
      set ^AlertCurrentRow("Consolelog","PID",pid)=1
      //发送监控信息至信息推送平台,如微信或短信等
      set rt=..sendAlertInfo(alertInfo)
    }
  }
 }

 //记录最后处理的行内容
 set ^AlertCurrentRow("Consolelog","LastPosition")=file.FindAt(1,textLast)
   do file.Close()
   quit $$$OK
}

控制台日志在记录信息时,经常会记录一系列问题。记录模式为时间+进程ID+信息级别+详细信息。如图1所示。信息级别从0级到3级,问题严重程度依次增加。为0的一般为正常运行信息,也是占日志主要部分的内容。问题级别为1的为警告信息。问题级别为2的为错误信息。问题级别为3的为严重错误信息。因此信息级别为1以上均是监控需要关注的信息。需要将此部分信息及时发出。

 

1 cconsole.log普通记录示例

有时候控制台日志也会有其它格式的信息出现,如图2所示。此类信息说明有比较严重的异常行为出现,需要重点关注,因为一般将其全部发出。

 

2 cconsole.log特殊记录示例

监控信息推送

控制台日志会对一个进程的多个操作进行记录,如果将所有信息发出,则会造成信息量过大而找不到重点。一般将每个进程的第一个告警或错误信息发出即可。处理方式见上述示例代码。

获取到所需要发送的监控信息调取微信(如图3)或短信(如图4或其它信息推送终端的接口即可进行信息推送。

   

                     图3 微信告警示例                                                          4 短信告警示例

任务部署

将程序部署成定时任务,按照所需自定义监控频率即可实现cache数据库的主动实时监控。如图5所示。

 

5 监控任务示例

讨论 (3)3
登录或注册以继续