Skip to content

Instantly share code, notes, and snippets.

@petermarks
Forked from commandodev/Automata.hs
Created November 23, 2011 23:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save petermarks/1390231 to your computer and use it in GitHub Desktop.
Save petermarks/1390231 to your computer and use it in GitHub Desktop.
EnumLogfile
module Automata where
import Control.Applicative
import Control.Monad.Trans
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as C
import qualified Data.Map as M
import Data.List
import Data.Word
import System.Environment
import Data.Enumerator hiding (head, map)
import qualified Data.Enumerator.Binary as EB
import qualified Data.Enumerator.List as EL
-- Data Types
data Entry = Entry {
date :: BS.ByteString,
host :: BS.ByteString,
program :: BS.ByteString,
message :: BS.ByteString
} deriving Show
type Summary = M.Map BS.ByteString Int
nl :: Word8
nl = 10
-- Enumerator
filelines :: FilePath -> Enumerator BS.ByteString IO a
filelines fname = EB.enumFile fname $= EB.splitWhen (== nl)
-- Iteratees
count :: Monad m => Iteratee BS.ByteString m Int
count = EL.fold (flip $ const (+1)) 0
summary :: Monad m => Iteratee BS.ByteString m Summary
summary = EL.fold op M.empty
where op :: Summary -> BS.ByteString -> Summary
op sumMap line = M.insertWith' (+) (program $ parseEntry line) 1 sumMap
-- Utils
parseEntry :: BS.ByteString -> Entry
parseEntry s = Entry d h p m
where d1:d2:d3:h:p':ms = C.words s
d = C.unwords [d1,d2,d3]
p = BS.init p'
m = C.unwords ms
top10 :: Summary -> [(Int, BS.ByteString)]
top10 = take 10 . reverse . sort . map swap . M.toList
-- swap is missing from my Data.Tuple
swap :: (a,b) -> (b,a)
swap (a,b) = (b,a)
main :: IO ()
main = do
fname <- head <$> getArgs
run_ $ filelines fname $$ EB.zip count (top10 <$> summary) >>= liftIO . print
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment