{-# LANGUAGE OverloadedStrings #-} module Nuxeo.Log ( parseNuxeoLog ) where import Control.Applicative import Data.Attoparsec.ByteString.Char8 import Data.Attoparsec.Combinator import Data.Conduit import Data.Conduit.Attoparsec import Data.Conduit.Binary import qualified Data.Text as T import Data.Time import Nuxeo.Types -- | Parse Nuxeo server.log -- -- @ -- parseNuxeoLog "./server.log" -- >>= return . filter (\l -> nuxeoLogEntryType l == Error) -- >>= mapM_ (\t -> -- putStrLn $ (show $ nuxeoLogEntryType t) -- <> " " -- <> (Text.unpack $ nuxeoLogEntryAction t) -- <> " " -- <> (Text.unpack $ nuxeoLogEntryLog t) -- ) -- @ parseNuxeoLog :: FilePath -> IO NuxeoLog parseNuxeoLog logpath = runConduitRes $ sourceFile logpath .| sinkParser nuxeoLogParser nuxeoLogParser :: Parser NuxeoLog nuxeoLogParser = many $ (nuxeoLogEntryParser <* endOfLine) nuxeoLogEntryParser :: Parser NuxeoLogEntry nuxeoLogEntryParser = do ptime <- timeParser ptype <- space *> nuxeoTypeLogParser psection <- space *> nuxeoLogEntrySectionParser paction <- space *> nuxeoLogEntryActionParser pnuxeolog <- space *> manyTill' anyChar (try $ lookAhead $ (char '\n' *> timeParser *> space *> nuxeoTypeLogParser *> space *> nuxeoLogEntryActionParser)) return $ NuxeoLogEntry ptime ptype psection paction (T.pack pnuxeolog) nuxeoTypeLogParser :: Parser NuxeoLogType nuxeoTypeLogParser = (string "ERROR" *> return NuxeoError) <|> (string "DEBUG" *> return NuxeoDebug) <|> (string "WARN" *> return NuxeoWarning) <|> (string "INFO" *> return NuxeoInfo) <|> fail "Invalid NuxeoTypeLog" nuxeoLogEntrySectionParser :: Parser T.Text nuxeoLogEntrySectionParser = char '[' *> manyTill' anyChar (char ']') <|> fail "Oops parse section" >>= return . T.pack nuxeoLogEntryActionParser :: Parser T.Text nuxeoLogEntryActionParser = char '[' *> manyTill' anyChar (char ']') <|> fail "Oops parse action" >>= return . T.pack timeParser :: Parser LocalTime timeParser = do y <- count 4 digit mm <- char '-' *> count 2 digit d <- char '-' *> count 2 digit h <- char ' ' *> count 2 digit m <- char ':' *> count 2 digit s <- char ':' *> count 2 digit _ <- char ',' *> count 3 digit return $ LocalTime { localDay = fromGregorian (read y) (read mm) (read d) , localTimeOfDay = TimeOfDay (read h) (read m) (read s) }