{-# LANGUAGE CPP #-}
module System.Log.Handler.Log4jXML (
log4jStreamHandler,
log4jFileHandler,
log4jStreamHandler',
log4jFileHandler'
) where
import Control.Concurrent (myThreadId)
import Data.List (isPrefixOf)
import System.IO
#if MIN_VERSION_time(1,5,0)
import Data.Time.Format (defaultTimeLocale)
#else
import System.Locale (defaultTimeLocale)
#endif
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
GenericHandler Handle
hndlr <- Handle -> Priority -> IO (GenericHandler Handle)
streamHandler Handle
h Priority
pri
GenericHandler Handle -> IO (GenericHandler Handle)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (GenericHandler Handle -> IO (GenericHandler Handle))
-> GenericHandler Handle -> IO (GenericHandler Handle)
forall a b. (a -> b) -> a -> b
$ GenericHandler Handle
-> LogFormatter (GenericHandler Handle) -> GenericHandler Handle
forall a. LogHandler a => a -> LogFormatter a -> a
setFormatter GenericHandler Handle
hndlr LogFormatter (GenericHandler Handle)
forall a. a -> (Priority, String) -> String -> IO String
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
UTCTime
time <- IO UTCTime
getCurrentTime
ThreadId
thread <- IO ThreadId
myThreadId
String -> IO String
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> IO String) -> (XML -> String) -> XML -> IO String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XML -> String
forall a. Show a => a -> String
show (XML -> IO String) -> XML -> IO String
forall a b. (a -> b) -> a -> b
$ String -> [(String, String)] -> Maybe XML -> XML
Elem String
"log4j:event"
[ (String
"logger" , String
logger )
, (String
"timestamp", UTCTime -> String
forall {t}. FormatTime t => t -> String
millis UTCTime
time )
, (String
"level" , Priority -> String
showPrio Priority
prio)
, (String
"thread" , ThreadId -> String
forall a. Show a => a -> String
show ThreadId
thread )
]
(XML -> Maybe XML
forall a. a -> Maybe a
Just (XML -> Maybe XML) -> XML -> Maybe XML
forall a b. (a -> b) -> a -> b
$ String -> [(String, String)] -> Maybe XML -> XML
Elem String
"log4j:message" [] (XML -> Maybe XML
forall a. a -> Maybe a
Just (XML -> Maybe XML) -> XML -> Maybe XML
forall a b. (a -> b) -> a -> b
$ String -> XML
CDATA String
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
Handle
h <- String -> IOMode -> IO Handle
openFile String
fp IOMode
AppendMode
GenericHandler Handle
sh <- Handle -> Priority -> IO (GenericHandler Handle)
log4jStreamHandler Handle
h Priority
pri
GenericHandler Handle -> IO (GenericHandler Handle)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (GenericHandler Handle
sh{closeFunc = hClose})
log4jFileHandler' :: FilePath -> Priority -> IO (GenericHandler Handle)
log4jFileHandler' :: String -> Priority -> IO (GenericHandler Handle)
log4jFileHandler' String
fp Priority
pri = do
Handle
h <- String -> IOMode -> IO Handle
openFile String
fp IOMode
AppendMode
GenericHandler Handle
sh <- Handle -> Priority -> IO (GenericHandler Handle)
log4jStreamHandler' Handle
h Priority
pri
GenericHandler Handle -> IO (GenericHandler Handle)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (GenericHandler Handle
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