packages feed

silvi 0.0.3 → 0.0.4

raw patch · 8 files changed

+188/−120 lines, 8 filesdep ~chronosdep ~http-typesdep ~ip

Dependency ranges changed: chronos, http-types, ip, quantification, savage

Files

README.md view
@@ -5,6 +5,8 @@  `silvi` is a Haskell library for generating fake logs from user specifications. +See `src/Silvi/Tutorial.hs` for a quick tutorial on getting started.+ [hackage-badge]:     https://img.shields.io/hackage/v/silvi.svg?label=Hackage [hackage-link]:
silvi.cabal view
@@ -1,22 +1,23 @@ ---------------------------------------------------------------------  name:                      silvi-version:                   0.0.3+version:                   0.0.4 build-type:                Simple cabal-version:             >= 1.10-category:                  Testing+category:                  Development, Testing author:                    Daniel Cartwright maintainer:                dcartwright@layer3com.com license:                   BSD3 license-file:              LICENSE homepage:                  https://github.com/chessai/silvi#readme bug-reports:               https://github.com/chessai/silvi/issues-synopsis:                  A generator for different kinds of logs.-description:               A Haskell library for generating logs-                           from user specifications. extra-source-files:        README.md tested-with:               GHC == 8.0.2                          , GHC == 8.2.1+                         , GHC == 8.2.2+synopsis:                  A generator for different kinds of logs.+description:               A Haskell library for generating logs+                           from user specifications.  --------------------------------------------------------------------- @@ -29,19 +30,19 @@  library     hs-source-dirs:        src-    build-depends:         base           >= 4.9 && < 5.0+    build-depends:         base           >= 4.9    && < 5.0                          , bytestring-                         , chronos-                         , http-types-                         , ip-                         , quantification-                         , savage         >= 1.0.2 && < 2.0+                         , chronos        >= 1.0.1   && < 1.0.3+                         , http-types     >= 0.11   && < 0.13+                         , ip             >= 1.0    && < 2.0+                         , quantification >= 0.3    && < 0.5+                         , savage         >= 1.0.3  && < 2.0                          , text     exposed-modules:       Silvi-                         , Silvi.LogFormat                          , Silvi.Random                          , Silvi.Record                          , Silvi.Types+                         , Silvi.Tutorial      default-language:      Haskell2010     other-extensions:      
src/Silvi.hs view
@@ -1,16 +1,4 @@--- -*- coding: utf-8; mode: haskell; -*----- File: src/Silvi.hs- {-# OPTIONS_GHC -fno-warn-missing-import-lists #-}---- |---   Module     : Silvi---   Copyright  : Copyright 2017 Daniel Cartwright---   License    : BSD3---   Maintainer : dcartwright@layer3com.com---   Stabiility : Stable-  module Silvi  ( module Silvi.Random
− src/Silvi/LogFormat.hs
@@ -1,34 +0,0 @@-{-# LANGUAGE DataKinds         #-}-{-# LANGUAGE OverloadedStrings #-}--module Silvi.LogFormat-  (-  ) where--import           Silvi.Record (Field (..), SingField (..), Value (..))-import           Silvi.Types--{-- - Palo Alto logs formats, as described in:- - https://www.paloaltonetworks.com/documentation/61/pan-os/pan-os/reports-and-logging/syslog-field-descriptions.html- ---}--type TestLog = '[ FieldBracketNum-                , FieldIp-                ]--type PaloAltoTraffic = '[ ]--type PaloAltoThreat = '[]--type PaloAltoHIPMatch = '[]--type PaloAltoConfig = '[]--type PaloAltoSystem = '[]--type PaloAltoSeverity = '[]----type PaloAltoEvent = []-
src/Silvi/Random.hs view
@@ -7,15 +7,19 @@ {-# LANGUAGE ScopedTypeVariables #-}  module Silvi.Random-  ( rand-  , randLogExplicit+  ( randLogExplicit   , randLog+  , print +  , printMany +  , Gen(..)    ) where -import           Chronos                    (now, timeToDatetime)+import qualified Chronos import           Chronos.Types-import           Data.Exists                (Exists (..), Reify (..),-                                             SingList (..))+import           Control.Applicative        (liftA2)+import           Control.Monad              (replicateM, replicateM_)+import           Control.Monad.IO.Class     (MonadIO(..))+import           Data.Exists                (Exists (..), Reify (..), SingList (..)) import           Data.Text                  (Text) import           Data.Word                  (Word8) import           Net.IPv4                   (ipv4)@@ -25,14 +29,14 @@ import           Network.HTTP.Types.Version (http09, http10, http11, http20) import qualified Network.HTTP.Types.Version as HttpV import           Savage-import           Savage.Randy               (element, enum, enumBounded, int,-                                             int8, print, word16, word8)+import           Savage.Internal.Gen        (printOnly)+import           Savage.Randy               (element, enum, enumBounded, int, int8, word16, word8) import           Savage.Range               (constantBounded)-import           Silvi.Record               (Field (..), SingField (..),-                                             Value (..), rmap, rtraverse)+import           Silvi.Record               (Field (..), SingField (..), Value (..)) import           Silvi.Types-import           System.IO.Unsafe           (unsafePerformIO) import           Topaz.Rec                  (Rec (..), fromSingList)+import qualified Topaz.Rec                  as Topaz+import           Prelude                    hiding (print)  rand :: SingField a -> Gen (Value a) rand = \case@@ -50,8 +54,14 @@ randLog = randLogExplicit (fromSingList (reify :: SingList as))  randLogExplicit :: Rec SingField rs -> Gen (Rec Value rs)-randLogExplicit = rtraverse rand+randLogExplicit = Topaz.traverse rand +print :: (MonadIO m, Show a) => Gen a -> m ()+print = printOnly++printMany :: (MonadIO m, Show a) => Int -> Gen a -> m ()+printMany n gen = replicateM_ n (print gen)+ randomIPv4 :: Gen IPv4 randomIPv4 = ipv4   <$> word8 constantBounded@@ -92,42 +102,28 @@   <*> enum 0 59999  randomDate :: Gen Date-randomDate = Date-  <$> (Year       <$> enum 1995 2100)-  <*> (Month      <$> enum    0   11)-  <*> (DayOfMonth <$> enum    1   31)--randomYear' :: Int -- ^ Origin year-            -> Int -- ^ End year, Usually current year-            -> Gen Year-randomYear' a b = Year <$> enum (min a b) (max a b)+randomDate = do+  let year  = randomYear 1995 2021+      month = Month <$> int constantBounded+      day = randomDay 1 =<< liftA2 daysUpperBound year month+  Date <$> year <*> month <*> day+  where daysUpperBound :: Year -> Month -> Int+        daysUpperBound y m = Chronos.daysInMonth (Chronos.isLeapYear y) m --- | Random year, generated from a given year to the current one.--- randomYear :: Int -- ^ Origin year+           -> Int -- ^ End year            -> Gen Year-randomYear a = randomYear' a b-  where b = (getYear . dateYear . datetimeDate) $ (timeToDatetime (unsafePerformIO now))--randomMonth' :: Int -- ^ Origin month-             -> Int -- ^ End month, usually current-             -> Gen Month-randomMonth' a b = Month <$> enum (min a b) (max a b)+randomYear a b = Year <$> enum (min a b) (max a b)  randomMonth :: Int -- ^ Origin month+            -> Int -- ^ End month             -> Gen Month-randomMonth a = randomMonth' a b-  where b = (getMonth . dateMonth . datetimeDate) $ (timeToDatetime (unsafePerformIO now))--randomDay' :: Int -- ^ Origin Day-           -> Int -- ^ End day, usually the current day-           -> Gen DayOfMonth-randomDay' a b = DayOfMonth <$> enum (min a b) (max a b)+randomMonth a b = Month <$> enum (min a b) (max a b)  randomDay :: Int -- ^ Origin Day+          -> Int -- ^ End day           -> Gen DayOfMonth-randomDay a = randomDay' a b-  where b = (getDayOfMonth . dateDay . datetimeDate) $ (timeToDatetime (unsafePerformIO now))+randomDay a b = DayOfMonth <$> enum (min a b) (max a b)  randomOffsetDatetime :: Gen OffsetDatetime randomOffsetDatetime = OffsetDatetime@@ -137,6 +133,12 @@ randomOffset :: Gen Offset randomOffset = element offsets +-- | List of sample+-- | List of Time Zone Offsets. See:+--   https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations+offsets :: [Offset]+offsets = map Offset [100,200,300,330,400,430,500,530,545,600,630,700,800,845,900,930,1000,1030,1100,1200,1245,1300,1345,1400,0,-100,-200,-230,-300,-330,-400,-500,-600,-700,-800,-900,-930,-1000,-1100,-1200]+ -- | List of sample Useridents. userIdents :: [UserId] userIdents = map UserId ["-","andrewthad","cement","chessai"]@@ -145,8 +147,4 @@ urls :: [Url] urls = map Url ["https://github.com","https://youtube.com","layer3com.com"] --- | List of sample--- | List of Time Zone Offsets. See:---   https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations-offsets :: [Offset]-offsets = map Offset [100,200,300,330,400,430,500,530,545,600,630,700,800,845,900,930,1000,1030,1100,1200,1245,1300,1345,1400,0,-100,-200,-230,-300,-330,-400,-500,-600,-700,-800,-900,-930,-1000,-1100,-1200]+
src/Silvi/Record.hs view
@@ -9,11 +9,10 @@ {-# LANGUAGE TypeOperators     #-}  module Silvi.Record-  ( rmap-  , rtraverse-  , Field(..)+  ( Field(..)   , Value(..)   , SingField(..)+  , Rec(..)    ) where  import           Chronos.Types              (OffsetDatetime (..))@@ -27,7 +26,7 @@ import qualified Network.HTTP.Types.Status  as HttpS import qualified Network.HTTP.Types.Version as HttpV import           Silvi.Types-import           Topaz.Rec                  (Rec (..), traverse)+import           Topaz.Rec                  (Rec(..), traverse) import qualified Topaz.Rec                  as Topaz  -- | Different types present in logs.@@ -96,15 +95,3 @@   reify = SingIp instance Reify 'FieldTimestamp where   reify = SingTimestamp---- | Alias for `Topaz.map`.-rmap :: (forall x. f x -> g x) -> Rec f as -> Rec g as-rmap = Topaz.map---- | Alias for `Topaz.traverse`-rtraverse-  :: Applicative h-  => (forall x. f x -> h (g x))-  -> Rec f rs-  -> h (Rec g rs)-rtraverse = Topaz.traverse
+ src/Silvi/Tutorial.hs view
@@ -0,0 +1,101 @@+-- -*- coding: utf-8; mode: haskell; -*-++-- File: src/Silvi/Tutorial.hs+--+-- License:+--     Copyright 2017 Daniel Cartwright+--+--     Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:+--+--     1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.+--+--     2. 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.+--+--     3. Neither the name of the copyright holder nor the names of its 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 HOLDER 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.++{-# OPTIONS_GHC -fno-warn-unused-imports #-}++{-# LANGUAGE DataKinds         #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications  #-}++-- |+--   Module     : Silvi.Tutorial+--   Copyright  : Copyright 2017 Daniel Cartwright+--   License    : BSD3+--   Maintainer : dcartwright@layer3com.com+--   Stability  : stable+module Silvi.Tutorial+  ( -- * Introduction+    -- $introduction++    -- * Defining Log Formats+    -- $def_logs+     +    -- * Generating Random Logs+    -- $rand_logs+    --+    --+  ) where++import           Silvi.Random (randLog, printMany, Gen(..))+import           Silvi.Record (Field (..), SingField (..), Value (..), Rec(..))++--------------------------------------------------------------------------------++-- $introduction+--+-- This library allows you to generate random logs, as well as easily construct+-- any sort of log you might yourself want.+--+-- In general, when using @silvi@, you'll want the following language extensions:+--+-- @+-- {-# LANGUAGE DataKinds         #-}+-- {-# LANGUAGE OverloadedStrings #-}+-- {-# LANGUAGE TypeApplications  #-}+-- @+--+-- And the following imports:+--+-- @+-- import Silvi.Random+-- import Silvi.Record+-- @+-- ++---------------------------------------------------------------------------------++-- $def_logs+--+-- > -- It is easy to define a log. +-- > -- A log is represented as a type-level list consisting of different fields.+-- >+-- > -- 'SimpleLog' represents a Log consisting of just an IPv4 address and a URL.+-- > type SimpleLog = '[ FieldIp+-- >                   , FieldUrl+-- >                   ]++type SimpleLog = '[ FieldIp+                  , FieldUrl+                  ]++---------------------------------------------------------------------------------++-- $rand_logs+-- >+-- > -- 'randSimpleLog' now contains a SimpleLog with randomised inhabitants of the IPv4 and URL types.+-- > randSimpleLog :: Gen (Rec Value as)+-- > randSimpleLog = randLog @SimpleLog+-- > +-- > -- 'main' will print out 1000 'SimpleLog's.+-- > main :: IO ()+-- > main = printMany 1000 randSimpleLog++randSimpleLog :: Gen (Rec Value SimpleLog)+randSimpleLog = randLog @SimpleLog++main :: IO ()+main = printMany 1000 randSimpleLog
src/Silvi/Types.hs view
@@ -1,28 +1,53 @@+{-# LANGUAGE GADTs #-}+ module Silvi.Types   ( Url(..)   , UserId(..)   , ObjSize(..)   , BracketNum(..)+  , Log(..)    ) where +import           Data.Exists import           Data.Text (Text) import           Data.Word (Word16, Word8)+import           Topaz.Rec (Rec(..)) +newtype Log v a = Log { getLog :: Rec v a }+  deriving (Eq)++instance ShowForall f => ShowForall (Log f) where+  showsPrecForall p x = case getLog x of+    RecCons v vs -> showParen (p > 10)+      $ showsPrecForall 11 v+      . showString " "+      . showsPrecForall 11 vs+    RecNil  -> showString ""+ -- | Url type. --   TODO: Expand on this for better randomisation. -- newtype Url = Url { getUrl :: Text }-  deriving (Show,Eq)+  deriving (Eq) +instance Show Url where+  show (Url x) = show x+ -- | UserId type. -- newtype UserId = UserId { getUserId :: Text }-  deriving (Show,Eq)+  deriving (Eq) +instance Show UserId where+  show (UserId x) = show x+ -- | Requested resource size. -- newtype ObjSize = ObjSize { getObjSize :: Word16 }-  deriving (Show,Eq)+  deriving (Eq)++instance Show ObjSize where+  show (ObjSize x) = show x ++ "B"  -- | Angle-bracketed number that appears before many logs. --