{-# LANGUAGE CPP #-}
module System.Log.Handler.Log4jXML (
log4jStreamHandler,
log4jFileHandler,
log4jStreamHandler',
log4jFileHandler'
) where
import Control.Concurrent (myThreadId)
import Data.List (isPrefixOf)
import System.IO
import Data.Time.Format (defaultTimeLocale)
import Data.Time
import System.Log
import System.Log.Handler
import System.Log.Handler.Simple (streamHandler, GenericHandler(..))
log4jHandler :: (Priority -> String) -> Handle -> Priority -> IO (GenericHandler Handle)
log4jHandler :: (Priority -> String)
-> Handle -> Priority -> IO (GenericHandler Handle)
log4jHandler Priority -> String
showPrio Handle
h Priority
pri = do
hndlr <- Handle -> Priority -> IO (GenericHandler Handle)
streamHandler Handle
h Priority
pri
return $ setFormatter hndlr xmlFormatter
where
xmlFormatter :: a -> (Priority,String) -> String -> IO String
xmlFormatter :: forall a. a -> (Priority, String) -> String -> IO String
xmlFormatter a
_ (Priority
prio,String
msg) String
logger = do
time <- IO UTCTime
getCurrentTime
thread <- myThreadId
return . show $ Elem "log4j:event"
[ ("logger" , logger )
, ("timestamp", millis time )
, ("level" , showPrio prio)
, ("thread" , show thread )
]
(Just $ Elem "log4j:message" [] (Just $ CDATA msg))
where
millis :: t -> String
millis t
t = TimeLocale -> String -> t -> String
forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
"%s" t
t
String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
3 (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ TimeLocale -> String -> t -> String
forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
"%q" t
t)
log4jStreamHandler :: Handle -> Priority -> IO (GenericHandler Handle)
log4jStreamHandler :: Handle -> Priority -> IO (GenericHandler Handle)
log4jStreamHandler = (Priority -> String)
-> Handle -> Priority -> IO (GenericHandler Handle)
log4jHandler Priority -> String
forall a. Show a => a -> String
show
log4jStreamHandler' :: Handle -> Priority -> IO (GenericHandler Handle)
log4jStreamHandler' :: Handle -> Priority -> IO (GenericHandler Handle)
log4jStreamHandler' = (Priority -> String)
-> Handle -> Priority -> IO (GenericHandler Handle)
log4jHandler Priority -> String
show' where
show' :: Priority -> String
show' :: Priority -> String
show' Priority
NOTICE = String
"INFO"
show' Priority
WARNING = String
"WARN"
show' Priority
CRITICAL = String
"ERROR"
show' Priority
ALERT = String
"ERROR"
show' Priority
EMERGENCY = String
"FATAL"
show' Priority
p = Priority -> String
forall a. Show a => a -> String
show Priority
p
log4jFileHandler :: FilePath -> Priority -> IO (GenericHandler Handle)
log4jFileHandler :: String -> Priority -> IO (GenericHandler Handle)
log4jFileHandler String
fp Priority
pri = do
h <- String -> IOMode -> IO Handle
openFile String
fp IOMode
AppendMode
sh <- log4jStreamHandler h pri
return (sh{closeFunc = hClose})
log4jFileHandler' :: FilePath -> Priority -> IO (GenericHandler Handle)
log4jFileHandler' :: String -> Priority -> IO (GenericHandler Handle)
log4jFileHandler' String
fp Priority
pri = do
h <- String -> IOMode -> IO Handle
openFile String
fp IOMode
AppendMode
sh <- log4jStreamHandler' h pri
return (sh{closeFunc = hClose})
data XML = Elem String [(String, String)] (Maybe XML)
| CDATA String
instance Show XML where
show :: XML -> String
show (CDATA String
s) = String
"<![CDATA[" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
escapeCDATA String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"]]>" where
escapeCDATA :: String -> String
escapeCDATA = String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace String
"]]>" String
"]]<"
show (Elem String
name [(String, String)]
attrs Maybe XML
child) = String
"<" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ [(String, String)] -> String
showAttrs [(String, String)]
attrs String -> String -> String
forall a. [a] -> [a] -> [a]
++ Maybe XML -> String
forall {a}. Show a => Maybe a -> String
showChild Maybe XML
child where
showAttrs :: [(String, String)] -> String
showAttrs [] = String
""
showAttrs ((String
k,String
v):[(String, String)]
as) = String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
k String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"=\"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
escapeAttr String
v String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\""
String -> String -> String
forall a. [a] -> [a] -> [a]
++ [(String, String)] -> String
showAttrs [(String, String)]
as
where escapeAttr :: String -> String
escapeAttr = String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace String
"\"" String
"""
(String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace String
"<" String
"<"
(String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace String
"&" String
"&"
showChild :: Maybe a -> String
showChild Maybe a
Nothing = String
"/>"
showChild (Just a
c) = String
">" String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"</" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
">"
replace :: Eq a => [a] -> [a] -> [a] -> [a]
replace :: forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace [a]
_ [a]
_ [ ] = []
replace [a]
from [a]
to xs :: [a]
xs@(a
a:[a]
as) = if [a] -> [a] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isPrefixOf [a]
from [a]
xs
then [a]
to [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop ([a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
from) [a]
xs else a
a a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a] -> [a] -> [a] -> [a]
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace [a]
from [a]
to [a]
as