zoukankan      html  css  js  c++  java
  • [Good for enterprise] GFE我们是怎么监控的?

    This artical will also be published in English - http://www.cnblogs.com/LarryAtCNBlog/p/3890743.html

    Cont. http://www.cnblogs.com/LarryAtCNBlog/p/3900838.html

    问:Good for enterprise(以下简称GFE)是什么?

    答:mobile messaging software,允许内部邮件系统的邮件发送到user的手机上,并支持client policy管理,如不允许client另存邮件,或者不允许在越狱或root的手机上进行邮件同步,远程锁住client,擦除client之类。支持安卓和ios,windows phone官网有人提及过,不清楚处不处于开发阶段或打不打算开发。 client可以从google play或app store下载,当然要是公司没有买GFE,光下载个client也是没用。GFE只是Good technology公司家族的一员,GFE分为两个组件,一个叫GMC(Good mobile control)另一个叫GMM(Good mobile messaging)。

    我们公司GFE以前出过一些issue,当然,就是email不同步什么的,对于一个在我们公司定义为Critical级别的service,一旦出现issue,自然incident management什么的就来了,于是乎,GFE的监控就是一个很大的问题,会被management team查问为什么没有监控,或者为什么监控没起作用?

    实际上Good公司是提供监控的,在和vendor谈的时候可以提出来让他们监控,但是这种监控非常有限,就是看看GMM和GMC的状态,pending了多少messages.

    而我也问过Good方面,他们并没有提供end-to-end的monitoring方式,GMC和GMM的日志也只是用来上传给他们自己看的而不是给我们内部的support team调查用,所以,确认了我方能做的只有windows event viewer和监控一下service的启动状态,而大多数出问题的时候service都是运行着的,并没有crash,因而意义并不明显。实际上问到这一步已经可以向management team说明,这是Good方面没有提供这种监控,我们也没有办法。但是,身为一个有责任心的IT :D,自己想办法写了一个powershell script来解决,经过一段时间的使用和调较,终于成功的抓到了最近的几次issue。

    我所在的公司用的是Exchange 2010,用的自然也就是Exchange版的GFE。就目前为止,我公司遇到的几次issue总结如下:

    (注意,一个EventID可能对应多种信息,有些信息是正常的,因此不能以简单的EventID来做监控,PS:Good总结过一些valuable monitoring eventIDs,可以向vendor要)

    1. 和Exchange之间的MAPI连接错误,EventID是3563和3386。

    3563:基本上和user有关的错误如MAPI error,pausing user,unpausing user都是该EventID。出现issue的时候该EventID的生成数量取决于GFE当前有多少出问题的用户数,而且平常这个Event也是偶尔会有的,因此不能有一个event被生成就发一次告警。下面是一个error例子, 

    Pausing user XXXXXX. (MAPI error - Can not access the users mailbox due to network error.)

     3386:Good调用API打开Exchange失败。

    Good Messaging Server failed to open message store for user XXXXXX. Verify that Exchange Server is operation and accessible. Verify that GoodAdmin account has correct permission on user's mailbox.  (HRESULT:GDMAPI_OpenMsgStore failed (FormatMessage returned 0. The error was 0x80040115))

     上面提及的两个Event偶尔都会生成,不过马上会恢复,因此要排除掉这种偶尔的情况,具体详情可以看脚本中的解释。

    2. 与Good NOC之间的连接失败(内网当然是不对外开放的,我公司用的是proxy让GFE和NOC通讯),这类event是比较危险的,它们的出现意味着的的确确有问题,当然也很有可能自己恢复。

    5662样例, 

    Good Messaging Server failed to login to Good Mobile Messaging Data Center as hostname XXXXXXX Error code 65547 (errNetTimeout)

    5669样例, 

    Good Messaging Server failed to connect and authenticate with Good Mobile Messaging Data Center at proxy://:?????@proxyxxxx:proxyport/https://xml28.good.com:443/ with hostname XXXXXX.  Reason code 65546 (errNetRecv)

    5675样例, 

    Failed to add a message to connection xxxxxxx.  Error code 65538 (errNetConnect)

    5733样例,

    Unable to batch messages towards XML gateway 65547:errNetTimeout

    以上提及的Event的出现都意味着和Good NOC之间通讯至少失败过一次,这是相当不应该出现的,因此在script中,我也把它们的threshold定义为了1,即,抓到该event就告警。

    3. 线程hang up,导致Good进程挂死。

    1299/1300/1301:平常偶尔也出现,一般来说Good会自行恢复,但是我们要抓的情况就是它不自己恢复的情况。

    1299样例,

    Timed operation failed, name:dowork-5 time (ms):1200000, thread name:dowork-5, thread state:handleMessage:svcAdmin, thread id;505861040

    1300样例, 

    Timed operation failed (list of threads), name:dowork-5 time (ms):1200000, thread name:InboundMgr, thread state:starting, thread id;688420216

    1301显示的是堆栈信息,比较长,这里就贴前几行,

    Stack for thread 1384 is 
    --# FV EIP----- RetAddr- FramePtr StackPtr Symbol
    
      0 .V 77821f46 759e338a 52d3ff88 52d3fe28 ZwWaitForWorkViaWorkerFactory +00018 bytes
        Sig: ZwWaitForWorkViaWorkerFactory
        Decl: ZwWaitForWorkViaWorkerFactory

    上面提及的3个EventID在我公司出现issue而没有自行恢复的情况就出现过一次,而且平常这几个event也是极少。当时出现的情况就是几分钟内生成了好几百条event。

    到此,几个关键的event就表述完成,下面是脚本的部分,我在我公司定义的是每15分钟一执行。

    上面也说了3563这个event实际上和当前GFE的用户数量有关,因此threshold也要根据IT平时的经验来判断,而且平时该event也是偶尔生成的,一般在5-10分钟之内会自动恢复,所以用了Pattern和MinusPattern两个匹配来排除“自动恢复”这种情况。

    #更改working directory
    Set-Location (Get-Item ($MyInvocation.MyCommand.Definition)).DirectoryName
    
    #定义要监控的event和属性
    #ID为需要监控的eventID,如果使用数组如@(xx,yy),说明这两个EventID在统计的时候是一起算的,如xx产生了10条,yy产生了10条,加一起20再和threshold比较
    #Pattern是C#中的正则表达式,用于过滤出含特定字符的event。
    #MinusPattern也是正则表达式,用于过滤出含特定字符的event。
    #如果Pattern和MinusPattern都有值的话,pattern匹配到了100条,而MinusPattern匹配到了90条,减一下最终为10条再和threshold比较,这样可以排除掉“自动恢复的情况”
    #Threshold就是前几属性的匹配过后,与最终值的数值比较,超过threshold就发告警
    $Events = @(
        @{ID = 3563; Pattern = 'Pausing .*MAPI error'; MinusPattern = 'Unpausing'; Threshold = 100;},
        @{ID = @(1299, 1300, 1301); Pattern = $null; Threshold = 100;},
        @{ID = 3386; Pattern = 'GDMAPI_OpenMsgStore failed'; Threshold = 100;},
        @{ID = @(5662, 5669); Pattern = $null; Threshold = 1;},
        @{ID = 5675; Pattern = 'errNetConnect'; Threshold = 1;},
        @{ID = 5733; Pattern = 'errNetTimeout'; Threshold = 1;}
    )
    
    $Date = Get-Date
    $strDate = $Date.ToString("yyyy-MM-dd")
    
    $End_time = $Date
    $Start_time = $Date.AddMinutes(-15)
    $strLogFile = "${strDate}.log.txt"
    $strLogFile_e = "${strDate}_Error.log.txt"
    
    #定义邮件发送属性
    $Mail_From = "$($env:COMPUTERNAME)@fil.com"
    $Mail_To = 'xxxxx@xxx.xxx'
    $Mail_Subject = 'Good event IDs warning'
    $Mail_SMTPServer = 'smtpserver'
    
    Set-Content -Path $strLogFile_e -Value $null 
    
    function Add-Log
    {
        PARAM(
            [String]$Path,
            [String]$Value,
            [String]$Type
        )
        $Type = $Type.ToUpper()
        Write-Host "$((Get-Date).ToString('[HH:mm:ss] '))[$Type] $Value"
        if($Path){
            Add-Content -Path $Path -Value "$((Get-Date).ToString('[HH:mm:ss] '))[$Type] $Value"
        }
    }
    
    Add-Log -Path $strLogFile_e -Value "Catch logs after : $($Start_time.ToString('HH:mm:ss'))" -Type Info
    Add-Log -Path $strLogFile_e -Value "Catch logs before: $($End_time.ToString('HH:mm:ss'))" -Type Info
    Add-Log -Path $strLogFile_e -Value "Working directory: $($PWD.Path)" -Type Info
    
    $EventsCache = @(Get-EventLog -LogName Application -After $Start_time -Before $End_time.AddMinutes(5))
    Add-Log -Path $strLogFile_e -Value "Total logs count : $($EventsCache.Count)" -Type Info
    $Mail_Body = $null
    foreach($e in $Events)
    {
        $Events_e_ALL = $null
        $Events_e_Matched = $null
        $Events_e_NMatched = $null
        $Events_e_FinalCount = 0
    
        $Events_e_ALL = @($EventsCache | ?{$e.ID -contains $_.EventID})
        Add-Log -Path $strLogFile_e -Value "Captured [$($e.ID -join '], [')], count: $($Events_e_ALL.Count)" -Type Info
        $Events_e_Matched = @($Events_e_ALL | ?{$_.Message -imatch $e.Pattern})
        Add-Log -Path $strLogFile_e -Value "Pattern matched, count: $($Events_e_Matched.Count)" -Type Info
        
        if($e.MinusPattern)
        {
            $Events_e_NMatched = @($Events_e_ALL | ?{$_.Message -imatch $e.MinusPattern})
            Add-Log -Path $strLogFile_e -Value "Minus pattern matched, count: $($Events_e_NMatched.Count)" -Type Info
        }
    
        $Events_e_FinalCount = $Events_e_Matched.Count - [int]$Events_e_NMatched.Count
        Add-Log -Path $strLogFile_e -Value "Final matched, count: $Events_e_FinalCount" -Type Info
        if($Events_e_FinalCount -ge $e.Threshold)
        {
            Add-Log -Path $strLogFile_e -Value "Over threshold: $($e.Threshold)" -Type Warning
            $Mail_Body += "Event ID: [$($e.ID -join '], [')] warning!`n"
        }
    }
    
    Add-Log -Path $strLogFile_e -Value "===================split line====================" -Type Info
    Get-Content -Path $strLogFile_e | Add-Content -Path $strLogFile
    
    If($Mail_Body)
    {
        try
        {
            Send-MailMessage -From $Mail_From -To $Mail_To -Subject $Mail_Subject -Body $Mail_Body -SmtpServer $Mail_SMTPServer -Attachments $strLogFile_e
        }
        catch
        {
            Add-Log -Path $strLogFile -Value "Failed to send mail, cause: $($Error[0])" -Type Error
        }
    }

    - Larry Song / 2014-08-04

  • 相关阅读:
    c++ fstream中seekg()和seekp()的用法
    java连接MySql数据库
    AspNetPager查询分页问题(点击页码,不再是查询后的数据集)viewstate解决
    C#操作XML文档
    关于PHP程序员解决问题的能力
    HDOJ 1874( dijkstra )
    错排问题 (Mathematics)
    中缀表达式到后缀表达式 (Data_Structure)
    几次到1(分治递归)
    max(int) = 0x7fffffff
  • 原文地址:https://www.cnblogs.com/LarryAtCNBlog/p/3890033.html
Copyright © 2011-2022 走看看