1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
import Control.Applicative( (<$>) )
import Control.Monad( unless )
import Data.Time.Clock( UTCTime(..) )
import Data.Time.LocalTime( TimeZone(), ZonedTime(..), zonedTimeToUTC, utcToZonedTime )
import Diddo( Diddo(..), LogEntry(..), parseDiddoLogline, formatDiddo, logToDiddo, parseToZonedTime )
import System.Console.GetOpt
import System.Environment( getArgs )
import System.Exit( exitSuccess, exitFailure )
import System.IO( stderr, hPutStr )
import qualified Data.Map as Map
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
data Optionset = Optionset
{ optVerbose :: Bool
, optVersion :: Bool
, optHelp :: Bool
, optInputFiles :: [String]
, optOutputFile :: String
, optInputFormat :: String
, optOutputFormat :: String
, optStartDate :: String
, optEndDate :: String
}
defaultOpts :: Optionset
defaultOpts = Optionset
{ optVerbose = False
, optVersion = False
, optHelp = False
, optInputFiles = []
, optOutputFile = ""
, optInputFormat = "%FT%T%z"
, optOutputFormat = "%FT%T%z"
, optStartDate = ""
, optEndDate = ""
}
availableOptions :: [OptDescr (Optionset -> IO Optionset)]
availableOptions =
[ Option ['h'] ["help"]
(NoArg (\ _ -> putStrLn (usageInfo "Usage: diddohs [OPTION...]" availableOptions) >> exitSuccess))
"Display program help"
, Option ['v'] ["verbose"]
(NoArg (\ optset -> return optset { optVerbose = True }))
"More detailed output"
, Option ['V'] ["version"]
(NoArg (\ optset -> return optset { optVersion = True }))
"Display program version"
, Option ['f'] ["file"]
(ReqArg (\ arg optset -> return optset { optInputFiles = optInputFiles optset ++ [arg]}) "FILE" )
"Read from FILE"
, Option ['w'] ["output"]
(ReqArg (\ arg optset -> return optset { optOutputFile = arg }) "FILE")
"Write to FILE"
, Option ['i'] ["informat"]
(ReqArg (\ arg optset -> return optset { optInputFormat = arg }) "FORMAT")
"Timeformat used in input"
, Option ['o'] ["outformat"]
(ReqArg (\ arg optset -> return optset { optOutputFormat = arg }) "FORMAT")
"Timeformat used in output"
, Option ['s'] ["start"]
(ReqArg (\ arg optset -> return optset { optStartDate = arg }) "DATE")
"Start of reporting period"
, Option ['e'] ["end"]
(ReqArg (\ arg optset -> return optset { optEndDate = arg }) "DATE")
"End of reporting period"
]
-- SECTION: Map of logentries to Map of Diddos
logentryMapToDiddoMap :: Map.Map UTCTime Diddo.LogEntry -> Map.Map UTCTime Diddo.Diddo
logentryMapToDiddoMap logmap = Map.mapWithKey toDddEntry logmap
where
toDddEntry key value = Diddo.logToDiddo (precedingTimestamp key) value
precedingTimestamp x = case Map.lookupLT x logmap of
Just (y,_) -> y
Nothing -> fst $ Map.findMin logmap
-- SECTION: Map of logentries to Map of DiddoEntries
getLoglines :: [String] -> IO [T.Text]
getLoglines [] = T.lines <$> TIO.getContents
getLoglines files@(_:_) = T.lines . T.concat <$> mapM TIO.readFile files
main :: IO ()
main = do
-- SECTION: option processing
(userOpts,args,errs) <-
getArgs >>= return . getOpt Permute availableOptions
unless (null errs) $ do
mapM_ (hPutStr stderr) errs
exitFailure
opts <- foldl (>>=) (return defaultOpts) userOpts
let
inDateFmt = optInputFormat opts
outDateFmt = optOutputFormat opts
startDate = parseToZonedTime inDateFmt $ optStartDate opts
endDate = parseToZonedTime inDateFmt $ optEndDate opts
-- SECTION: option processing
loglines <- getLoglines $ optInputFiles opts
let
timestampLogentryMap =
Map.fromList $ map Diddo.parseDiddoLogline loglines
(_, _, startedTimestampLogentryMap) =
Map.splitLookup (zonedTimeToUTC startDate) timestampLogentryMap
(endedTimestampLogentryMap, lastEntry, _) =
Map.splitLookup (zonedTimeToUTC endDate) startedTimestampLogentryMap
timestampDiddoMap =
logentryMapToDiddoMap timestampLogentryMap
-- DEBUG
mapM_ putStrLn args
-- DEBUG
mapM_ (TIO.putStrLn . snd) $ Map.toAscList $ Map.map (Diddo.formatDiddo outDateFmt) timestampDiddoMap
|