Parser logów w Groovy

Podczas debugowania wadliwego działania redeliveringu w ActiveMQ ostateczną metodą okazało się ‘echo dupa’ 😉 Jednakże przy próbie jednoczesnego obserwowania działania aplikacji przy 10 wiadomościach wpadających do kolejki okazało się, że metoda kartki i papieru zabiera trochę za dużo czasu. Zatem zaprzęgłem do pracy Grooviego i postanowiłem na szybko napisać mały parserek plików z logami.

Główne pomysły i kod podkradłem z tej strony. Jednakże ja do logów zapisywałem informację o tym, która to próba ponownego doręczenia się wykonuje, ilość łącznych, informację o wątku, który to wykonuje oraz informacji z samej wiadomości w kolejce JMS.  To oczywiście było dopisywane do wiersza ze wskazaniem informacji o wątku i daty. Całość wyglądała mniej więcej tak:

[#|2012-02-17T11:16:02.419+0100|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=80;_ThreadName=testowaKolejka-1;|CURRENT:4 MAX:4 id:identyfikator1-1-1-1|#]

I z tego narodził się poniższy kod. Być może komuś się przyda w przyszłości.

/* Mozna uzyc podejscia, ktore odczytuje plik linia po linii. Jednakze
 istnieje szansa, ze 1 wpis do loga zajmie wiecej niz domyslna 1 linie.
 Dlatego tez uzywamy podejscia, ktore wyciagnie plik do 1 lancucha tekstowego
 nastepnie zas kolejne przyporzadkowania do wzorca wyrazen regularnych.

 !!!UWAGA!!! - rozwiazanie moze byc malo wydajne przy duzych plikach

  */

def logLineStart = /^\[\#\|\d{4}-\d{2}-\d{2}/   // Wpis w logu o wyjatku
def log = new File('C:\\log.log').text
def informationEntries = []
def presentationData = [:]

def splitter = log =~ """(?xms)
    (    ${logLineStart}   .*?)
    (?=  ${logLineStart} | \\Z)
"""

splitter.each { matched, entry ->

    // Replace jest po to by otrzymac jeden lancuch tekstowy w przypadku dopasowan ze znakiem
    // nowej linii. Wowczas dane nie bylyby poprawne.
    if (entry =~ /CURRENT:/) {
         informationEntries.add( entry.replaceAll("[\r\n]","") )
    }

}

def redeliveryAttemptData = []

informationEntries.each {
    // Wpisy na liscie wygladaja mniej wiecej tak
    // [#|2012-02-17T15:49:50.525+0100|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=134;_ThreadName=testowaKolejka-1;|CURRENT:4 MAX:4 id:identyfikator1-1-1-1|#]

    // Zatem po prostu rozbijamy ten string i wyciagamy dane z listy
    redeliveryAttemptData = it.tokenize('|')

    String currentEntryData = redeliveryAttemptData.get(1)
    String currentEntryThread = redeliveryAttemptData.get(5)
    String currentEntryInfo = redeliveryAttemptData.get(6)

    // Wpierw potrzebna nam data i godzina z dokladnoscia do sekund
    def dataRegexp = /\d{2}:\d{2}:\d{2}\.\d{3}/
    def currentMinutesSec =  currentEntryData.find(dataRegexp)

    // Informacja o numerze watku, ktory procesowal wiadomosc
    def threadRegexp = /=jmsContainerEmailIn-\d{1,}/
    def currentThreadInfo =  currentEntryThread.find(threadRegexp).tokenize('-').get(1)

    // Logowane przeze mnie informacje o wiadomosci i metadane redeliveringu
    def listWithCurrentInfo = currentEntryInfo.tokenize(' ')
    def currentRound = listWithCurrentInfo.get(0).tokenize(':').get(1)
    def currentId = listWithCurrentInfo.get(2).tokenize(':').get(1)

    if( !presentationData[ currentId ] ) {
        presentationData[ currentId ] = [:]
    }

    presentationData[ currentId ][ 'id' ] = currentId
    presentationData[ currentId ][ currentRound ] = currentMinutesSec + '( ' + currentThreadInfo + ' )'

}

// Drukujemy na konsole w formie CSV. Mozna inaczej - stad
// zreszta zapisywanie danych do mapy
presentationData.each { key, value ->

    StringBuffer sb = new StringBuffer(64)

    sb.append( value.get('id')).append(',')

    for ( i in ['0','1','2','3','4'] ) {
        sb.append( value.get( i ) ).append(',')
    }

    println sb

}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s