summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dht-client.cabal11
-rw-r--r--src/DPut.hs75
2 files changed, 80 insertions, 6 deletions
diff --git a/dht-client.cabal b/dht-client.cabal
index 73c746f9..54b644d3 100644
--- a/dht-client.cabal
+++ b/dht-client.cabal
@@ -69,7 +69,8 @@ library
69 , RecordWildCards 69 , RecordWildCards
70 , NondecreasingIndentation 70 , NondecreasingIndentation
71 hs-source-dirs: src, ., Presence 71 hs-source-dirs: src, ., Presence
72 exposed-modules: DebugTag 72 exposed-modules: DPut
73 DebugTag
73 Network.SocketLike 74 Network.SocketLike
74 Data.Digest.CRC32C 75 Data.Digest.CRC32C
75 Data.Bits.ByteString 76 Data.Bits.ByteString
@@ -169,7 +170,6 @@ library
169 Network.Tox.Session 170 Network.Tox.Session
170 171
171 build-depends: base 172 build-depends: base
172 , dput-hslogger
173 , containers 173 , containers
174 , dependent-sum 174 , dependent-sum
175 , array 175 , array
@@ -277,21 +277,21 @@ executable avahi
277 hs-source-dirs: examples 277 hs-source-dirs: examples
278 main-is: avahi.hs 278 main-is: avahi.hs
279 default-language: Haskell2010 279 default-language: Haskell2010
280 build-depends: base-prelude, dht-client, avahi, network, dput-hslogger 280 build-depends: base-prelude, dht-client, avahi, network
281 ghc-options: -fobject-code 281 ghc-options: -fobject-code
282 282
283executable dht 283executable dht
284 hs-source-dirs: examples 284 hs-source-dirs: examples
285 main-is: dht.hs 285 main-is: dht.hs
286 default-language: Haskell2010 286 default-language: Haskell2010
287 build-depends: base, haskeline, network, bytestring, transformers, dput-hslogger 287 build-depends: base, haskeline, network, bytestring, transformers
288 ghc-options: -fobject-code 288 ghc-options: -fobject-code
289 289
290executable dhtd 290executable dhtd
291 hs-source-dirs: examples 291 hs-source-dirs: examples
292 main-is: dhtd.hs 292 main-is: dhtd.hs
293 default-language: Haskell2010 293 default-language: Haskell2010
294 build-depends: base, network, bytestring, hashable, deepseq, dput-hslogger 294 build-depends: base, network, bytestring, hashable, deepseq
295 , aeson 295 , aeson
296 , array 296 , array
297 , pretty 297 , pretty
@@ -334,7 +334,6 @@ executable testTox
334 main-is: testTox.hs 334 main-is: testTox.hs
335 default-language: Haskell2010 335 default-language: Haskell2010
336 build-depends: base 336 build-depends: base
337 , dput-hslogger
338 , dht-client 337 , dht-client
339 , stm 338 , stm
340 , stm-chans 339 , stm-chans
diff --git a/src/DPut.hs b/src/DPut.hs
new file mode 100644
index 00000000..38e532d0
--- /dev/null
+++ b/src/DPut.hs
@@ -0,0 +1,75 @@
1{-# LANGUAGE ConstraintKinds #-}
2{-# LANGUAGE ScopedTypeVariables #-}
3module DPut where
4
5import Control.Monad.IO.Class
6import qualified Data.Map.Strict as Map
7import Data.Maybe
8import Data.IORef
9import System.IO.Unsafe (unsafePerformIO)
10import System.Log.Logger
11import qualified Data.ByteString.Char8 as B
12import qualified Data.Text as T
13import qualified Data.Text.Encoding as T
14import Debug.Trace
15import Data.Typeable
16import Data.Dynamic
17
18type IsDebugTag t = (Eq t, Ord t, Show t, Read t, Enum t, Bounded t,Typeable t)
19
20appName :: String
21appName = "toxmpp"
22
23(<.>) :: String -> String -> String
24a <.> b = a ++ "." ++ b
25
26dput :: (MonadIO m, IsDebugTag tag) => tag -> String -> m ()
27dput tag msg = liftIO $ debugM (appName <.> show tag) msg
28
29dputB :: (MonadIO m, IsDebugTag tag) => tag -> B.ByteString -> m ()
30dputB tag msg = liftIO $ debugM (appName <.> show tag) (T.unpack . T.decodeUtf8 $ msg)
31
32{-# NOINLINE verbosityMap #-}
33verbosityMap :: IORef (Map.Map TypeRep Dynamic)
34verbosityMap = unsafePerformIO $ newIORef (Map.empty)
35
36-- | Trace version of 'dput' works in arbitrary monad, using unsafePerformIO.
37tput :: (Applicative m, IsDebugTag tag) => tag -> String -> m ()
38tput tag msg =
39 let mp = unsafePerformIO $ readIORef verbosityMap
40 in if maybe True (fromMaybe True . Map.lookup tag . flip fromDyn Map.empty) (Map.lookup (typeOf tag) mp)
41 then trace msg (pure ())
42 else pure ()
43
44-- | like 'trace' but parameterized with 'DebugTag'
45dtrace :: forall a tag. IsDebugTag tag => tag -> String -> a -> a
46dtrace tag msg result = let mp = unsafePerformIO $ readIORef verbosityMap
47 mp' :: Map.Map tag Bool
48 mp' = maybe Map.empty (flip fromDyn Map.empty) (Map.lookup (typeOf tag) mp)
49 in if fromMaybe True (Map.lookup tag mp')
50 then trace msg result
51 else result
52
53setTagLevel :: forall tag. IsDebugTag tag => Priority -> tag -> IO ()
54setTagLevel level tag = do
55 updateGlobalLogger (appName <.> show tag) (setLevel level)
56 modifyIORef verbosityMap $ \mpByType -> do
57 case Map.lookup (typeOf tag) mpByType of
58 Nothing -> Map.insert (typeOf tag) (toDyn $ Map.fromList [(tag,(level <= DEBUG))]) mpByType
59 Just dyn -> let mpByTag :: Map.Map tag Bool
60 mpByTag = fromDyn dyn Map.empty
61 in Map.insert (typeOf tag) (toDyn $ Map.insert tag (level <= DEBUG) mpByTag) mpByType
62
63setQuiet :: forall tag. IsDebugTag tag => tag -> IO ()
64setQuiet = setTagLevel WARNING
65
66setVerbose :: forall tag. IsDebugTag tag => tag -> IO ()
67setVerbose = setTagLevel DEBUG
68
69getVerbose :: forall tag. IsDebugTag tag => tag -> IO Bool
70getVerbose tag = do
71 logger <- getLogger (appName <.> show tag)
72 case getLevel logger of
73 Just p | p <= DEBUG -> return True
74 _ -> return False
75