-
Notifications
You must be signed in to change notification settings - Fork 3
/
LogParser.hs
58 lines (50 loc) · 1.78 KB
/
LogParser.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
{-# LANGUAGE QuasiQuotes #-}
{-# OPTIONS_GHC -fspec-constr-recursive=4 #-}
import Data.Function ((&))
import Data.Functor.Identity (runIdentity)
import Streamly.Data.Parser (Parser)
import Streamly.Unicode.String (str)
import qualified Data.Char as Char
import qualified Streamly.Data.Fold as Fold
import qualified Streamly.Data.Parser as Parser
import qualified Streamly.Data.Stream as Stream
-- Example of a quoted log string to be parsed
quoted :: String
quoted = [str|
"[2023-02-04T09:15:20.549Z] \"GET /cards?customer_id=XXXXP/1.1\" 200
- \"-\" \"-\" 0 75 23 23 \"131.26.22.133,127.16.101.49,127.18.4.69\"
\"edge\" \"7ccc821a-03ff-49c1-a721-977e7cbd78f3\" \"api.example.in\"
\"127.18.55.25:1108\" outbound|443|v21945461|svc.cluster.local
127.18.44.67:75523 127.18.44.67:8443 127.18.4.69:14462
mum.example.net confirmtkt\n"
|]
-- Use double quote as the quoting char
isQuote :: Char -> Maybe Char
isQuote x =
case x of
'"' -> Just x
_ -> Nothing
-- Transliterate \" and \n
tr :: Char -> Char -> Maybe Char
tr q x =
case x of
_ | x == q -> Just x
'n' -> Just '\n'
_ -> Nothing
-- quoted string parser, reads everything inside quotes as a single word
-- and processes the quotes and escapes to expose the words inside it.
parser :: Monad m => Parser Char m [Char]
parser = Parser.wordWithQuotes False tr '\\' isQuote Char.isSpace Fold.toList
main :: IO ()
main = do
-- Strip outer quotes
let res = runIdentity $ Stream.parse parser $ Stream.fromList quoted
-- parse words inside quotes
case res of
Left err -> error $ "Malformed quoted string: " ++ show err
Right unquoted ->
Stream.fromList unquoted
& Stream.parseMany parser
& Stream.catRights
& Stream.toList
>>= print