diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Author name here (c) 2016
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Author name here nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/app/Main.hs b/app/Main.hs
new file mode 100644
--- /dev/null
+++ b/app/Main.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Main where
+
+import Control.Concurrent            (threadDelay)
+import Control.Concurrent.STM.TQueue
+import Protolude                     hiding (bracket)
+
+import LoggerThread
+
+main :: IO ()
+main = do
+  args <- getArgs
+  putText ("command line arguments: " <> show args)
+  numCapabilities <- getNumCapabilities
+  putText ("number of cores: " <> show numCapabilities)
+  withLoggerThread mainThread
+
+mainThread :: Logger -> IO ()
+mainThread logger = do
+  logger "logginng stuff"
+  threadDelay (1000 * 1000)
+  logger "logginng stuff again"
+  threadDelay (1000 * 1000)
+  logger "final logginng, exiting after this"
diff --git a/logger-thread.cabal b/logger-thread.cabal
new file mode 100644
--- /dev/null
+++ b/logger-thread.cabal
@@ -0,0 +1,51 @@
+name:                logger-thread
+version:             0.1.0.0
+synopsis:            Run FastLogger in a thread and direct all queued messages to it.
+description:         Please see README.md
+homepage:            https://github.com/joe9/logger-thread#readme
+license:             BSD3
+license-file:        LICENSE
+author:              joe9
+maintainer:          joe9mail@gmail.com
+copyright:           2016 Joe9
+category:            Web
+build-type:          Simple
+-- extra-source-files:
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     LoggerThread
+  build-depends:       base < 6
+                     , protolude
+                     , fast-logger
+                     , safe-exceptions
+                     , stm
+                     , text
+                     , time
+  default-language:    Haskell2010
+  default-extensions:  NoImplicitPrelude
+  other-extensions:    OverloadedStrings
+
+executable logger-thread-exe
+  hs-source-dirs:      app
+  main-is:             Main.hs
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  build-depends:       base < 6
+                     , logger-thread
+                     , protolude
+                     , stm
+  default-language:    Haskell2010
+
+-- test-suite logger-thread-test
+--   type:                exitcode-stdio-1.0
+--   hs-source-dirs:      test
+--   main-is:             Spec.hs
+--   build-depends:       base
+--                      , logger-thread
+--   ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+--   default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/joe9/logger-thread
diff --git a/src/LoggerThread.hs b/src/LoggerThread.hs
new file mode 100644
--- /dev/null
+++ b/src/LoggerThread.hs
@@ -0,0 +1,80 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module LoggerThread
+  ( withLoggerThread
+  , Logger
+  ) where
+
+import Control.Concurrent.STM.TQueue
+import Control.Exception.Safe
+import Control.Monad.STM             (atomically)
+import Data.Text
+import Protolude                     hiding (bracket)
+import System.Log.FastLogger
+
+type Logger = Text -> IO ()
+
+toLog :: TQueue Text -> Text -> IO ()
+toLog chan s = atomically (writeTQueue chan (s <> singleton '\n'))
+
+withLoggerThread :: (Logger -> IO ()) -> IO ()
+withLoggerThread mainThread = do
+  logChannel <- atomically newTQueue
+  bracket
+    (async (loggerThread logChannel))
+    (\loggerThreadAsync -> do
+       putText "after the main thread, stop the loggerThread"
+       -- dummy text to unblock the logger channel
+       threadDelay (1000 * 1000)
+       cancel loggerThreadAsync
+       putText "cancelled the loggerThread"
+       wait loggerThreadAsync)
+    (\loggerThreadAsync -> do
+       link loggerThreadAsync
+       withException
+         (mainThread (toLog logChannel))
+         (\e -> do
+            putText "exception in main thread"
+            (print :: SomeException -> IO ()) e
+            putText "main thread exiting"))
+
+--   1 MiB = 1 mebibyte = 1,0242 bytes = 1,048,576 bytes
+--   100 MiB = 1,048,576 * 100 bytes
+loggerThread :: TQueue Text -> IO ()
+loggerThread chan =
+  withFastLogger
+    (LogStderr 1048576)
+    (\f ->
+       withException
+         (readAndLog chan f)
+         (\e -> do
+            putText "exception in logger thread"
+            (print :: SomeException -> IO ()) e
+            shutdownLogging chan f))
+
+shutdownLogging :: TQueue Text -> (LogStr -> IO a) -> IO ()
+shutdownLogging chan f = do
+  putText "in shutdownLogging"
+  maybeValue <- atomically (tryReadTQueue chan)
+  case maybeValue of
+    Just t -> (f . (toLogStr :: Text -> LogStr)) t >> shutdownLogging chan f
+    Nothing -> putText "LoggerThread stopped reading, exiting" >> return ()
+
+readAndLog :: TQueue Text -> (LogStr -> IO a) -> IO ()
+readAndLog chan f =
+  atomically (readTQueue chan) >>= f . (toLogStr :: Text -> LogStr) >>
+  readAndLog chan f
+-- log rotation is a system function, not an application function
+-- should not be doing this here
+-- not sure how to use this. If I use it readAndLog, it gives this
+-- message
+-- GetMarketsServer: /home/j/var/betfair//log/aping-20160820-betfair.log: openFile: resource busy (file is locked)
+-- checkAndRotate :: FileLogSpec -> IO ()
+-- checkAndRotate spec =
+--   do size <- getFileSize (log_file spec)
+--      when (size > log_file_size spec)
+--           (rotate spec)
+-- getFileSize
+--   :: BasicPrelude.FilePath -> IO Integer
+-- getFileSize path = withFile path ReadMode hFileSize
