@@ -0,0 +1,55 @@
1+{-# LANGUAGE DataKinds,
2+ TypeOperators,
3+ OverloadedStrings,
4+ ScopedTypeVariables #-}
5+
6+module Server.Logger (
7+ Logger,
8+ LoggerAPI,
9+ mkLogger,
10+ Log
11+) where
12+
13+import Network.Wai
14+import Control.Concurrent.STM
15+import Data.CyclicBuffer
16+import Servant
17+import Servant.API
18+import Servant.Server
19+import Data.Text.Encoding
20+import qualified Data.Text as T
21+import Data.Foldable
22+import qualified Data.ByteString as BL
23+import Data.List
24+import Server.App
25+import Data.CaseInsensitive (original)
26+import Data.Monoid ((<>), mempty, mappend)
27+import Network.HTTP.Types.Header
28+import Network.Wai.Middleware.RequestLogger
29+import Data.Default.Class
30+import qualified System.Log.FastLogger as FL
31+import Data.ByteString.Char8 (unpack)
32+
33+type Log = T.Text
34+
35+type LoggerAPI = "log" :> Get '[PlainText] Log
36+type Logger = App Log
37+
38+mkLogger :: Int -> IO (Middleware, Logger)
39+mkLogger lim = do
40+ buff <- newTVarIO $ mkCyclicBuffer lim
41+ logger <- mkWaiLogger buff
42+ return (logger, getLog buff)
43+
44+getLog :: TVar (CyclicBuffer BL.ByteString) -> Logger
45+getLog buff = decodeUtf8 . BL.concat . intersperse "\n" . elems <$> liftIO (readTVarIO buff)
46+
47+mkWaiLogger :: TVar (CyclicBuffer BL.ByteString) -> IO Middleware
48+mkWaiLogger buff = let
49+ settings = def {
50+ -- outputFormat = CustomOutputFormatWithDetails (\ date req _ _ tDiff bss bldr ->
51+ -- FL.toLogStr (show date) <> (FL.toLogStr . unpack $ fold bss))
52+ outputFormat = Detailed False,
53+ destination = Callback (atomically . modifyTVar buff . flip insertIntoCyclicBuffer . FL.fromLogStr)
54+ }
55+ in mkRequestLogger settings