@@ -1,8 +1,17 @@
1−module Katip.Scribes.ElasticSearch where
1+module Katip.Scribes.ElasticSearch
4-------------------------------------------------------------------------------
9-------------------------------------------------------------------------------
10+import Control.Applicative
11+import Control.Concurrent.Async
12+import Control.Concurrent.STM
5import Control.Monad
13import Control.Monad
6import Data.UUID
15import Data.UUID
7import Database.Bloodhound
16import Database.Bloodhound
8import System.Random
17import System.Random
@@ -16,13 +25,18 @@ mkEsScribe
17 -> IndexName
26 -> IndexName
18 -> MappingName
27 -> MappingName
19 -> Severity
29 -> Severity
20 -> Verbosity
30 -> Verbosity
21 -> IO Scribe
31 -> IO Scribe
22−mkEsScribe server ix mapping sev verb = return $ Scribe $ \ i -> do
32+mkEsScribe server ix mapping qs sev verb = do
23− did <- mkDocId
33+ q <- newTBQueueIO $ unEsQueueSize qs
34+ worker <- startWorker server ix mapping q
37+ return $ Scribe $ \ i ->
24− when (_itemSeverity i >= sev) $
38+ when (_itemSeverity i >= sev) $
25− void $ indexDocument server ix mapping (itemJson verb i) did
39+ void $ atomically $ tryWriteTBQueue q (itemJson verb i)
28-------------------------------------------------------------------------------
42-------------------------------------------------------------------------------
@@ -30,8 +44,44 @@ mkDocId :: IO DocId
30mkDocId = (DocId . toString) `fmap` randomIO
44mkDocId = (DocId . toString) `fmap` randomIO
47+-------------------------------------------------------------------------------
48+newtype EsQueueSize = EsQueueSize {
50+ } deriving (Show, Eq, Ord, Bounded)
53+mkEsQueueSize :: Int -> Maybe EsQueueSize
55+ | n >= 0 = Just $ EsQueueSize n
56+ | otherwise = Nothing
59+-------------------------------------------------------------------------------
66+startWorker server ix mapping q = async $ forever $ do
67+ v <- atomically $ readTBQueue q
68+ res <- waitCatch =<< async (sendLog v)
69+ when (isLeft res) $ inCaseOfEmergency
71+ sendLog v = void $ indexDocument server ix mapping v =<< mkDocId
72+ --TODO reenqueue? drop? would be nice to log but we don't have that context
73+ inCaseOfEmergency = return ()
76+-------------------------------------------------------------------------------
77+tryWriteTBQueue :: TBQueue a -> a -> STM Bool
78+tryWriteTBQueue q v = do
79+ ok <- not <$> isFullTBQueue q
80+ when ok $ writeTBQueue q v
84+-------------------------------------------------------------------------------
85+isLeft :: Either a b -> Bool
86+isLeft (Left _) = True