2010年8月19日木曜日

すべてのアプリケーションの利用状況を調べる

log.nsfではデフォルトで数日分の情報が蓄積され、それ以前の情報は破棄されます。
当方では過去ログを追うために保存用のDBを用意しています。
保存用のDBの実態は log.nsf のレプリカなのですが、log.nsf で破棄された情報が保存用へ伝わらないようにしています。
他のサーバーにある保存用DBへ毎朝、複製するよう接続文書で設定しています。

そうして蓄積された情報の中に Session文書があります。
Session文書にはユーザーやサーバーが読み書きしたアプリケーションごとの件数などがアプリケーションごとに記録されています。

当方ではSession文書を集計することで、ユーザーのアクセスが無いものをチェックしています。

以下は保存用DBから半年分のSession文書から読み込みと書き込みの件数を集計して、タブ区切りのテキストファイルへ書き出すサンプルです。
Sub Initialize
    'logArchive.nsf をサーチして半年間のSession文書を取得する
    Dim strTAB As String, strCRLF As String
    Const ARCHIVE_SERVER = "hogehoge/org"
    Const ARCHIVE_FILE = "LogArchive.nsf"
    strTAB = Chr(9)
    strCRLF = Chr(13) & Chr(10)
    Dim listExclude List As String, listCounter List As String
    listExclude("CN=Administrator/O=org") = "1" '1に意味は無い
    listExclude("CN=hogehoge/O=org") = "1"
    
    Dim logdb As NotesDatabase
    Dim dc As NotesDocumentCollection
    Dim doc As NotesDocument
    Dim ndt As New NotesDateTime( "Today" )
    Call ndt.AdjustMonth( -6 ) '半年分の情報を検索する
    
    '検索する
    Set logdb = New NotesDatabase( ARCHIVE_SERVER, ARCHIVE_FILE )
    Print "検索開始"
    Set dc = logdb.Search( | Form="Session" |, ndt, 0 )
    Print "検索終了、取得した文書数 : " & Cstr( dc.count ) & ", 集計開始"
    
    '集計する
    Set doc = dc.GetFirstDocument
    While Not ( doc Is Nothing )
        If doc.HasItem( "Body" ) Then
            UserName$ = doc.GetItemValue( "UserName" )(0)
            If Not Iselement( listExclude( UserName$ ) ) Then
                rtBody = Split( doc.GetItemValue( "Body" )(0), strCRLF )
                For i% = 0 To Ubound( rtBody )
                    varData = Split( rtBody(i%), strTAB )
                    strPath$ = Lcase$( varData( 0 ) )
                    If Right( strPath$, 4 ) <> ".ntf" Then
                        If Iselement( listCounter( strPath$ ) ) Then
                            varRW = Split( listCounter( strPath$ ), strTAB )
                            listCounter( strPath$ ) = Cstr( Cdbl( varRW(0) ) + Cdbl( varData(1) ) ) & _
                            strTAB & Cstr( Cdbl( varRW(1) ) + Cdbl( varData(2) ) )
                        Else
                            listCounter( strPath$ ) = Cstr( varData(1) ) & strTAB & Cstr( varData(2) )
                        End If
                    End If
                Next i%
            End If
        End If
        Set doc = dc.GetNextDocument( doc )
    Wend
    Print "集計終了, 出力開始"
    
    '出力する
    Dim objWshShell As Variant
    Set objWshShell = CreateObject("WScript.Shell")
    tmpPath$ = objWshShell.SpecialFolders("Desktop")
    filename$ = tmpPath$ & "\半年間の読み書き件数.txt"
    fileNum% = Freefile()
    Open filename$ For Output As fileNum%
    Print #fileNum%, "ファイルパス" & strTAB & "読み込み" & strTAB & "書き込み"
    Forall o In listCounter
        Print #fileNum%, Listtag( o ) & strTAB & o
    End Forall
    Close fileNum%
    Print "出力終了、処理完了"
End Sub

補足すると、アプリケーションごとの読み書き件数は Session文書の "Body" アイテムにあります。
アプリケーションのファイルパス、読み込み件数、書き込み件数などがタブで区切られ、
これらがアプリケーションごとに改行で区切られています。

また、ここではサーバーや管理者のSession文書を除外しています。

サンプルでは読み込み件数と書き込み件数のみを集計していますが、最終アクセス日付をSession文書の日付情報から求めることもできそうですね。