diff options
-rw-r--r-- | dht-client.cabal | 11 | ||||
-rw-r--r-- | src/DPut.hs | 75 |
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 | ||
283 | executable dht | 283 | executable 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 | ||
290 | executable dhtd | 290 | executable 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 #-} | ||
3 | module DPut where | ||
4 | |||
5 | import Control.Monad.IO.Class | ||
6 | import qualified Data.Map.Strict as Map | ||
7 | import Data.Maybe | ||
8 | import Data.IORef | ||
9 | import System.IO.Unsafe (unsafePerformIO) | ||
10 | import System.Log.Logger | ||
11 | import qualified Data.ByteString.Char8 as B | ||
12 | import qualified Data.Text as T | ||
13 | import qualified Data.Text.Encoding as T | ||
14 | import Debug.Trace | ||
15 | import Data.Typeable | ||
16 | import Data.Dynamic | ||
17 | |||
18 | type IsDebugTag t = (Eq t, Ord t, Show t, Read t, Enum t, Bounded t,Typeable t) | ||
19 | |||
20 | appName :: String | ||
21 | appName = "toxmpp" | ||
22 | |||
23 | (<.>) :: String -> String -> String | ||
24 | a <.> b = a ++ "." ++ b | ||
25 | |||
26 | dput :: (MonadIO m, IsDebugTag tag) => tag -> String -> m () | ||
27 | dput tag msg = liftIO $ debugM (appName <.> show tag) msg | ||
28 | |||
29 | dputB :: (MonadIO m, IsDebugTag tag) => tag -> B.ByteString -> m () | ||
30 | dputB tag msg = liftIO $ debugM (appName <.> show tag) (T.unpack . T.decodeUtf8 $ msg) | ||
31 | |||
32 | {-# NOINLINE verbosityMap #-} | ||
33 | verbosityMap :: IORef (Map.Map TypeRep Dynamic) | ||
34 | verbosityMap = unsafePerformIO $ newIORef (Map.empty) | ||
35 | |||
36 | -- | Trace version of 'dput' works in arbitrary monad, using unsafePerformIO. | ||
37 | tput :: (Applicative m, IsDebugTag tag) => tag -> String -> m () | ||
38 | tput 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' | ||
45 | dtrace :: forall a tag. IsDebugTag tag => tag -> String -> a -> a | ||
46 | dtrace 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 | |||
53 | setTagLevel :: forall tag. IsDebugTag tag => Priority -> tag -> IO () | ||
54 | setTagLevel 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 | |||
63 | setQuiet :: forall tag. IsDebugTag tag => tag -> IO () | ||
64 | setQuiet = setTagLevel WARNING | ||
65 | |||
66 | setVerbose :: forall tag. IsDebugTag tag => tag -> IO () | ||
67 | setVerbose = setTagLevel DEBUG | ||
68 | |||
69 | getVerbose :: forall tag. IsDebugTag tag => tag -> IO Bool | ||
70 | getVerbose tag = do | ||
71 | logger <- getLogger (appName <.> show tag) | ||
72 | case getLevel logger of | ||
73 | Just p | p <= DEBUG -> return True | ||
74 | _ -> return False | ||
75 | |||