diff --git a/common/Network/Helics/Types.hs b/common/Network/Helics/Types.hs
new file mode 100644
--- /dev/null
+++ b/common/Network/Helics/Types.hs
@@ -0,0 +1,72 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE CPP #-}
+
+module Network.Helics.Types where
+
+import Control.Exception
+
+import Foreign.C.Types
+import Foreign.C.String
+
+import Data.Typeable
+import Data.Default.Class
+import qualified Data.ByteString as S
+
+-- common
+newtype ReturnCode = ReturnCode CInt deriving (Eq, Typeable, Show)
+instance Exception ReturnCode
+
+-- client
+type StatusCallback = CInt -> IO ()
+newtype StatusCode = StatusCode CInt deriving (Eq, Show)
+
+-- transaction
+newtype TransactionId = TransactionId CLong
+
+newtype SegmentId = SegmentId CLong
+type SqlObfuscator = CString -> IO CString
+
+-- main
+data HelicsConfig = HelicsConfig
+    { licenseKey      :: S.ByteString
+    , appName         :: S.ByteString
+    , language        :: S.ByteString
+    , languageVersion :: S.ByteString
+    , statusCallback  :: Maybe (StatusCode -> IO ())
+    }
+
+instance Default HelicsConfig where
+    def = HelicsConfig
+        (error "license key is not set.")
+        "App"
+        "Haskell"
+        COMPILER_VERSION
+        Nothing
+
+data TransactionType
+    = Default
+    | Web   S.ByteString
+    | Other S.ByteString
+
+instance Default TransactionType where
+    def = Default
+
+data Operation
+    = SELECT
+    | INSERT
+    | UPDATE
+    | DELETE
+    deriving (Show)
+
+data DatastoreSegment = DatastoreSegment
+    { table              :: S.ByteString
+    , operation          :: Operation
+    , sql                :: S.ByteString
+    , sqlTraceRollupName :: S.ByteString
+    , sqlObFuscator      :: Maybe (S.ByteString -> S.ByteString)
+    }
+instance Default DatastoreSegment where
+    def = DatastoreSegment "unknown" SELECT "" "unknown" Nothing
+
+
diff --git a/dummy/Network/Helics.hs b/dummy/Network/Helics.hs
new file mode 100644
--- /dev/null
+++ b/dummy/Network/Helics.hs
@@ -0,0 +1,116 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+
+module Network.Helics
+    ( HelicsConfig(..)
+    , withHelics
+    , sampler
+    -- * metric
+    , recordMetric
+    , recordCpuUsage
+    , recordMemoryUsage
+    -- * transaction
+    , TransactionType(..)
+    , TransactionId
+    , withTransaction
+    , addAttribute
+    , setRequestUrl
+    , setMaxTraceSegments
+    -- * segment
+    , SegmentId
+    , autoScope
+    , rootSegment
+    , genericSegment
+    , Operation(..)
+    , DatastoreSegment(..)
+    , datastoreSegment
+    , externalSegment
+    -- * status code
+    , StatusCode
+    , statusShutdown
+    , statusStarting
+    , statusStopping
+    , statusStarted
+    -- * reexports
+    , def
+    ) where
+
+import System.IO.Error
+
+import Control.Exception
+import Control.Monad
+import Control.Concurrent
+
+import Foreign.C
+import Foreign.Ptr
+import Foreign.Marshal
+import Foreign.Storable
+
+import Data.Word
+import Data.Default.Class
+import qualified Data.ByteString as S
+
+import qualified Network.Helics.Sampler as Sampler
+import Network.Helics.Types
+
+autoScope, rootSegment :: SegmentId
+autoScope   = SegmentId 0
+rootSegment = SegmentId 1
+
+statusShutdown, statusStarting, statusStopping, statusStarted :: StatusCode
+statusShutdown = StatusCode 0
+statusStarting = StatusCode 1
+statusStopping = StatusCode 2
+statusStarted  = StatusCode 3
+
+-- | start new relic®  collector client.
+-- you must call this function when embed-mode.
+withHelics :: HelicsConfig -> IO a -> IO a
+withHelics _ m = m
+
+-- | record custom metric.
+recordMetric :: S.ByteString -> Double -> IO ()
+recordMetric _ _ = return ()
+
+-- | sample and send metric of cpu/memory usage.
+sampler :: Int -- ^ sampling frequency (sec)
+        -> IO ()
+sampler _ = return ()
+
+-- | record CPU usage. Normally, you don't need to call this function. use sampler.
+recordCpuUsage :: Double -> Double -> IO ()
+recordCpuUsage _ _ = return ()
+
+-- | record memory usage. Normally, you don't need to call this function. use sampler.
+recordMemoryUsage :: Double -> IO ()
+recordMemoryUsage _ = return ()
+
+withTransaction :: S.ByteString -- ^ name of transaction
+                -> TransactionType -> (TransactionId -> IO c) -> IO c
+withTransaction _ _ m = m (TransactionId 0)
+
+genericSegment :: SegmentId     -- ^ parent segment id
+               -> S.ByteString  -- ^ name of represent segment
+               -> IO c          -- ^ action in segment
+               -> TransactionId
+               -> IO c
+genericSegment _ _ m _ = m
+
+datastoreSegment :: SegmentId -> DatastoreSegment -> IO a -> TransactionId -> IO a
+datastoreSegment _ _ m _ = m
+
+externalSegment :: SegmentId
+                -> S.ByteString -- ^ host of segment
+                -> S.ByteString -- ^ name of segment
+                -> IO a -> TransactionId -> IO a
+externalSegment _ _ _ m _ = m
+
+addAttribute :: S.ByteString -> S.ByteString -> TransactionId -> IO ()
+addAttribute _ _ _ = return ()
+
+setRequestUrl :: S.ByteString -> TransactionId -> IO ()
+setRequestUrl _ _ = return ()
+
+setMaxTraceSegments :: Int -> TransactionId -> IO ()
+setMaxTraceSegments _ _ = return ()
diff --git a/dummy/Network/Helics/Sampler.hs b/dummy/Network/Helics/Sampler.hs
new file mode 100644
--- /dev/null
+++ b/dummy/Network/Helics/Sampler.hs
@@ -0,0 +1,6 @@
+module Network.Helics.Sampler where
+
+type Callback = Double -> Double -> Int -> IO ()
+
+sampler :: Callback -> Int -> IO ()
+sampler _ _ = return ()
diff --git a/helics.cabal b/helics.cabal
--- a/helics.cabal
+++ b/helics.cabal
@@ -1,5 +1,5 @@
 name:                helics
-version:             0.2.1
+version:             0.3.0
 synopsis:            New Relic® agent SDK wrapper for Haskell.
 description:         
   New Relic® agent SDK wrapper for Haskell.
@@ -28,27 +28,35 @@
 flag example
   default: False
 
+flag dummy
+  description: compile dummy modules on !linux.
+  default:     True
+
 library
   exposed-modules:     Network.Helics
                        Network.Helics.Sampler
-  other-modules:       Network.Helics.Foreign.Common
-                       Network.Helics.Foreign.Client
-                       Network.Helics.Foreign.Transaction
-                       Network.Helics.Foreign.System
-  -- other-extensions:    
+  other-modules:       Network.Helics.Types
+  ghc-options:         -Wall -O2
+  default-language:    Haskell2010
   build-depends:       base               >=4.6  && <4.8
                      , data-default-class >=0.0  && <0.1
-                     , time               >=1.2  && <1.6
-                     , unix               >=2.6  && <2.8
                      , bytestring         >=0.10 && <0.11
-                     , bytestring-show    >=0.3  && <0.4
-  ghc-options:         -Wall -O2
-  hs-source-dirs:      src
-  build-tools:         hsc2hs
-  extra-libraries:     newrelic-collector-client
-                     , newrelic-transaction
-                     , newrelic-common
-  default-language:    Haskell2010
+
+  if flag(dummy) && !os(linux)
+    hs-source-dirs:      common, dummy
+  else
+    other-modules:       Network.Helics.Foreign.Common
+                         Network.Helics.Foreign.Client
+                         Network.Helics.Foreign.Transaction
+                         Network.Helics.Foreign.System
+    build-depends:       time               >=1.2  && <1.6
+                       , unix               >=2.6  && <2.8
+                       , bytestring-show    >=0.3  && <0.4
+    hs-source-dirs:      common, src
+    build-tools:         hsc2hs
+    extra-libraries:     newrelic-collector-client
+                       , newrelic-transaction
+                       , newrelic-common
 
 executable helics-example
   main-is:             example.hs
diff --git a/src/Network/Helics.hs b/src/Network/Helics.hs
deleted file mode 100644
--- a/src/Network/Helics.hs
+++ /dev/null
@@ -1,260 +0,0 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards #-}
-
-module Network.Helics
-    ( HelicsConfig(..)
-    , withHelics
-    , sampler
-    -- * metric
-    , recordMetric
-    , recordCpuUsage
-    , recordMemoryUsage
-    -- * transaction
-    , TransactionType(..)
-    , TransactionId
-    , withTransaction
-    , addAttribute
-    , setRequestUrl
-    , setMaxTraceSegments
-    -- * segment
-    , SegmentId
-    , autoScope
-    , rootSegment
-    , genericSegment
-    , Operation(..)
-    , DatastoreSegment(..)
-    , datastoreSegment
-    , externalSegment
-    -- * status code
-    , StatusCode
-    , statusShutdown
-    , statusStarting
-    , statusStopping
-    , statusStarted
-    -- * reexports
-    , def
-    ) where
-
-import System.IO.Error
-
-import Control.Exception
-import Control.Monad
-import Control.Concurrent
-
-import Foreign.C
-import Foreign.Ptr
-import Foreign.Marshal
-import Foreign.Storable
-
-import Data.Word
-import Data.Default.Class
-import qualified Data.ByteString as S
-
-import qualified Network.Helics.Sampler as Sampler
-import Network.Helics.Foreign.Common
-import Network.Helics.Foreign.Client
-import Network.Helics.Foreign.Transaction
-
-data HelicsConfig = HelicsConfig
-    { licenseKey      :: S.ByteString
-    , appName         :: S.ByteString
-    , language        :: S.ByteString
-    , languageVersion :: S.ByteString
-    , statusCallback  :: Maybe (StatusCode -> IO ())
-    }
-
-instance Default HelicsConfig where
-    def = HelicsConfig
-        (error "license key is not set.")
-        "App"
-        "Haskell"
-        COMPILER_VERSION
-        Nothing
-
-guardNr :: CInt -> IO ()
-guardNr c = unless (c == 0) $ throwIO $ ReturnCode c
-
-initialize :: HelicsConfig -> IO ()
-initialize HelicsConfig{..} =
-    S.useAsCString licenseKey      $ \key ->
-    S.useAsCString appName         $ \app ->
-    S.useAsCString language        $ \lng ->
-    S.useAsCString languageVersion $ \ver ->
-    newrelic_init key app lng ver >>= guardNr
-
-shutdown :: S.ByteString -> IO ()
-shutdown reason =
-    S.useAsCString reason $ \r ->
-    newrelic_request_shutdown r >>= \c ->
-    guardNr c
-
--- | start new relic®  collector client.
--- you must call this function when embed-mode.
-withHelics :: HelicsConfig -> IO a -> IO a
-withHelics cfg m = bracket bra ket (const m)
-  where
-    bra = do
-        mv <- newEmptyMVar
-        cb <- makeStatusCallback (\i -> do
-            when (i == 3 || i == 0) $ putMVar mv ()
-            maybe (return ()) ($ StatusCode i) $ statusCallback cfg)
-        newrelic_register_status_callback cb
-
-        newrelic_register_message_handler newrelic_message_handler
-
-        initialize cfg
-        takeMVar mv
-        return (freeHaskellFunPtr cb, mv)
-
-    ket (freePtr, mv) = do
-        shutdown "withHelics: shutdown"
-        takeMVar mv :: IO ()
-        freePtr :: IO ()
-
--- | record custom metric.
-recordMetric :: S.ByteString -> Double -> IO ()
-recordMetric str d = S.useAsCString str $ \mtr ->
-    newrelic_record_metric mtr (realToFrac d) >>= guardNr
-
--- | sample and send metric of cpu/memory usage.
-sampler :: Int -- ^ sampling frequency (sec)
-        -> IO ()
-sampler s = flip Sampler.sampler (s * 10^(6::Int)) $ \user cpu mem -> do
-    recordCpuUsage user cpu
-    recordMemoryUsage (fromIntegral mem / (1024 * 1024))
-
--- | record CPU usage. Normally, you don't need to call this function. use sampler.
-recordCpuUsage :: Double -> Double -> IO ()
-recordCpuUsage ut p =
-    newrelic_record_cpu_usage (realToFrac ut) (realToFrac p) >>= guardNr
-
--- | record memory usage. Normally, you don't need to call this function. use sampler.
-recordMemoryUsage :: Double -> IO ()
-recordMemoryUsage mb = 
-   newrelic_record_memory_usage (realToFrac mb) >>= guardNr
-
-data TransactionType
-    = Default
-    | Web   S.ByteString
-    | Other S.ByteString
-
-instance Default TransactionType where
-    def = Default
-
-withTransaction :: S.ByteString -- ^ name of transaction
-                -> TransactionType -> (TransactionId -> IO c) -> IO c
-withTransaction name typ act = bracket bra ket
-    (\tid -> act tid `catch` exceptionHandler tid)
-  where
-    bra = do
-        tid <- newrelic_transaction_begin
-        guardNr =<< S.useAsCString name (newrelic_transaction_set_name tid)
-        return $ TransactionId tid
-    ket (TransactionId tid) = do
-        case typ of
-            Default -> return ()
-            Web cat ->
-                guardNr =<< S.useAsCString cat (newrelic_transaction_set_category tid)
-            Other cat -> do
-                guardNr =<< newrelic_transaction_set_type_other tid
-                guardNr =<< S.useAsCString cat (newrelic_transaction_set_category tid)
-        guardNr =<< newrelic_transaction_end tid
-
-    exceptionHandler (TransactionId tid) se = case fromException se of
-        Just e -> do
-            withCString (show $ ioeGetErrorType e) $ \et ->
-                withCString (ioeGetErrorString e)  $ \msg ->
-                newrelic_transaction_notice_error tid et msg nullPtr nullPtr >>= guardNr
-            ioError e
-
-        Nothing -> do
-            withCString (show se) $ \et ->
-                newrelic_transaction_notice_error tid et nullPtr nullPtr nullPtr >>= guardNr
-            throwIO se
-
-guardSid :: CLong -> IO CLong
-guardSid sid =
-   if sid >= 0
-   then return sid
-   else throwIO $ ReturnCode (fromIntegral sid)
-
-segment :: CLong -> IO CLong -> IO a -> IO a
-segment tid m a = bracket (m >>= guardSid) (newrelic_segment_end tid) (const a)
-
-genericSegment :: SegmentId     -- ^ parent segment id
-               -> S.ByteString  -- ^ name of represent segment
-               -> IO c          -- ^ action in segment
-               -> TransactionId
-               -> IO c
-genericSegment (SegmentId pid) name act (TransactionId tid) = segment tid
-    (S.useAsCString name $ newrelic_segment_generic_begin tid pid) act
-
-data Operation
-    = SELECT
-    | INSERT
-    | UPDATE
-    | DELETE
-    deriving (Show)
-
-opToBS :: Operation -> S.ByteString
-opToBS SELECT = newrelicDatastoreSelect
-opToBS INSERT = newrelicDatastoreInsert
-opToBS UPDATE = newrelicDatastoreUpdate
-opToBS DELETE = newrelicDatastoreDelete
-
-data DatastoreSegment = DatastoreSegment
-    { table              :: S.ByteString
-    , operation          :: Operation
-    , sql                :: S.ByteString
-    , sqlTraceRollupName :: S.ByteString
-    , sqlObFuscator      :: Maybe (S.ByteString -> S.ByteString)
-    }
-instance Default DatastoreSegment where
-    def = DatastoreSegment "unknown" SELECT "" "unknown" Nothing
-
-toCObfuscator :: (S.ByteString -> S.ByteString) -> CString -> IO CString
-toCObfuscator f i = do
-    s <- S.packCString i
-    m <- mallocBytes (S.length s + 1)
-    pokeByteOff m (S.length s) (0 :: Word8)
-    S.useAsCString (f s) (\c -> copyBytes m c (S.length s))
-    return m
-
-datastoreSegment :: SegmentId -> DatastoreSegment -> IO a -> TransactionId -> IO a
-datastoreSegment (SegmentId pid) DatastoreSegment{..} act (TransactionId tid) = 
-    S.useAsCString table              $ \tbl ->
-    S.useAsCString (opToBS operation) $ \op ->
-    S.useAsCString sql                $ \q  ->
-    S.useAsCString sqlTraceRollupName $ \tr -> do
-    case sqlObFuscator of
-        Nothing -> segment tid
-            (newrelic_segment_datastore_begin tid pid tbl op q tr
-                newrelic_basic_literal_replacement_obfuscator) act
-        Just f ->
-            bracket (makeObfuscator $ toCObfuscator f) freeHaskellFunPtr $ \cf ->
-            segment tid
-                (newrelic_segment_datastore_begin tid pid tbl op q tr cf) act
-
-externalSegment :: SegmentId
-                -> S.ByteString -- ^ host of segment
-                -> S.ByteString -- ^ name of segment
-                -> IO a -> TransactionId -> IO a
-externalSegment (SegmentId pid) host name act (TransactionId tid) =
-    S.useAsCString host $ \h ->
-    S.useAsCString name $ \n ->
-    segment tid (newrelic_segment_external_begin tid pid h n) act
-
-addAttribute :: S.ByteString -> S.ByteString -> TransactionId -> IO ()
-addAttribute name value (TransactionId tid) =
-   S.useAsCString name  $ \n ->
-   S.useAsCString value $ \v ->
-   guardNr =<< newrelic_transaction_add_attribute tid n v
-
-setRequestUrl :: S.ByteString -> TransactionId -> IO ()
-setRequestUrl req (TransactionId tid) =
-   guardNr =<< S.useAsCString req (newrelic_transaction_set_request_url tid)
-
-setMaxTraceSegments :: Int -> TransactionId -> IO ()
-setMaxTraceSegments mx (TransactionId tid) = guardNr =<<
-    newrelic_transaction_set_max_trace_segments tid (fromIntegral mx)
diff --git a/src/Network/Helics/Foreign/Client.hsc b/src/Network/Helics/Foreign/Client.hsc
--- a/src/Network/Helics/Foreign/Client.hsc
+++ b/src/Network/Helics/Foreign/Client.hsc
@@ -6,9 +6,7 @@
 
 import Foreign.C
 import Foreign.Ptr
-
-newtype StatusCode = StatusCode CInt
-    deriving (Eq, Show)
+import Network.Helics.Types
 
 #{enum StatusCode, StatusCode
  , statusShutdown = NEWRELIC_STATUS_CODE_SHUTDOWN
@@ -19,7 +17,6 @@
 
 foreign import ccall "&newrelic_message_handler" newrelic_message_handler :: FunPtr (Ptr rawMessage -> IO ())
 
-type StatusCallback = CInt -> IO ()
 foreign import ccall "wrapper" makeStatusCallback :: StatusCallback -> IO (FunPtr StatusCallback)
 foreign import ccall newrelic_register_status_callback :: FunPtr StatusCallback -> IO ()
 
diff --git a/src/Network/Helics/Foreign/Common.hsc b/src/Network/Helics/Foreign/Common.hsc
--- a/src/Network/Helics/Foreign/Common.hsc
+++ b/src/Network/Helics/Foreign/Common.hsc
@@ -5,27 +5,9 @@
 
 #include <newrelic_common.h>
 
-import Data.Typeable
-import Control.Exception
 import Foreign.C
 import Foreign.Ptr
-
-newtype ReturnCode = ReturnCode CInt
-    deriving (Eq, Typeable)
-
-instance Show ReturnCode where
-    show c@(ReturnCode i)
-        | c == returnCodeOther                 = "ReturnCode Other(" ++ show (#{const NEWRELIC_RETURN_CODE_OTHER} :: Int) ++ ")"
-        | c == returnCodeDisabled              = "ReturnCode Disabled(" ++ show (#{const NEWRELIC_RETURN_CODE_DISABLED} :: Int) ++ ")"
-        | c == returnCodeInvalidParam          = "ReturnCode Invalid param(" ++ show (#{const NEWRELIC_RETURN_CODE_INVALID_PARAM} :: Int) ++ ")"
-        | c == returnCodeInvalidId             = "ReturnCode Invalid id(" ++ show (#{const NEWRELIC_RETURN_CODE_INVALID_ID} :: Int) ++ ")"
-        | c == returnCodeTransactionNotStarted = "ReturnCode Transaction not started(" ++ show (#{const NEWRELIC_RETURN_CODE_TRANSACTION_NOT_STARTED} :: Int) ++ ")"
-        | c == returnCodeTransactionInProgress = "ReturnCode Transaction in progress(" ++ show (#{const NEWRELIC_RETURN_CODE_TRANSACTION_IN_PROGRESS} :: Int) ++ ")"
-        | c == returnCodeTransactionNotNamed   = "ReturnCode Transaction not named(" ++ show (#{const NEWRELIC_RETURN_CODE_TRANSACTION_NOT_NAMED} :: Int) ++ ")"
-        | otherwise                            = "ReturnCode Unknown(" ++ show i ++ ")"
-
-
-instance Exception ReturnCode
+import Network.Helics.Types
 
 #{enum ReturnCode, ReturnCode
  , returnCodeOk                    = NEWRELIC_RETURN_CODE_OK
diff --git a/src/Network/Helics/Foreign/Transaction.hsc b/src/Network/Helics/Foreign/Transaction.hsc
--- a/src/Network/Helics/Foreign/Transaction.hsc
+++ b/src/Network/Helics/Foreign/Transaction.hsc
@@ -8,10 +8,7 @@
 import Foreign.C
 import Foreign.Ptr
 import qualified Data.ByteString as S
-
-newtype TransactionId = TransactionId CLong
-
-newtype SegmentId = SegmentId CLong
+import Network.Helics.Types
 
 autoScope, rootSegment :: SegmentId
 autoScope   = SegmentId #const NEWRELIC_AUTOSCOPE
@@ -55,7 +52,6 @@
 
 foreign import ccall newrelic_segment_generic_begin :: CLong -> CLong -> CString -> IO CLong
 
-type SqlObfuscator = CString -> IO CString
 foreign import ccall "wrapper" makeObfuscator :: SqlObfuscator -> IO (FunPtr SqlObfuscator)
 foreign import ccall newrelic_segment_datastore_begin
     :: CLong -> CLong -> CString -> CString -> CString -> CString -> FunPtr SqlObfuscator -> IO CLong
diff --git a/src/Network/Helics/Sampler.hs b/src/Network/Helics/Sampler.hs
deleted file mode 100644
--- a/src/Network/Helics/Sampler.hs
+++ /dev/null
@@ -1,44 +0,0 @@
-module Network.Helics.Sampler where
-
-import System.Posix.Process
-
-import Foreign.C.Types
-
-import GHC.Conc
-
-import Control.Applicative
-
-import Network.Helics.Foreign.System
-
-import Data.Time.Clock
-
-type Callback = Double -> Double -> Int -> IO ()
-
-sampler :: Callback -> Int -> IO ()
-sampler callback sleep = do
-    t     <- fromIntegral <$> clockTick
-    core  <- fromIntegral <$> getNumCapabilities
-    cTime <- getCurrentTime
-    uTime <- fromIntegral <$> getUserTime
-    pSize <- fromIntegral <$> pageSize
-    pid   <- getProcessID
-    threadDelay sleep
-    go t core pSize pid cTime uTime
-  where
-
-    unCClock (CClock c) = c
-    getUserTime = unCClock . userTime <$> getProcessTimes
-
-    go tick core pSize pid = loop
-      where
-        loop cTime uTime = do
-            cTime' <- getCurrentTime
-            uTime' <- fromIntegral <$> getUserTime
-            pages  <- getPages pid
-            let real = realToFrac $ diffUTCTime cTime' cTime
-                user = (uTime' - uTime) / tick
-                cpu  = user / (real * core)
-                mem  = pages * pSize
-            callback user cpu mem
-            threadDelay sleep
-            loop cTime' uTime'
