diff --git a/hledger/Hledger/Cli/Commands/Stats.hs b/hledger/Hledger/Cli/Commands/Stats.hs index 54fe4d3ce..342bec686 100644 --- a/hledger/Hledger/Cli/Commands/Stats.hs +++ b/hledger/Hledger/Cli/Commands/Stats.hs @@ -16,6 +16,7 @@ module Hledger.Cli.Commands.Stats ( where import Data.Default (def) +import System.FilePath (takeFileName) import Data.List (intercalate, nub, sortOn) import Data.List.Extra (nubSort) import qualified Data.Map as Map @@ -39,7 +40,8 @@ import Hledger.Cli.Utils (writeOutputLazyText) statsmode = hledgerCommandMode $(embedFileRelative "Hledger/Cli/Commands/Stats.txt") - [flagReq ["output-file","o"] (\s opts -> Right $ setopt "output-file" s opts) "FILE" "write output to FILE." + [ flagNone ["verbose","v"] (setboolopt "verbose") "show more detailed output" + ,flagReq ["output-file","o"] (\s opts -> Right $ setopt "output-file" s opts) "FILE" "write output to FILE." ] [generalflagsgroup1] hiddenflags @@ -48,15 +50,15 @@ statsmode = hledgerCommandMode -- like Register.summarisePostings -- | Print various statistics for the journal. stats :: CliOpts -> Journal -> IO () -stats opts@CliOpts{reportspec_=rspec, progstarttime_} j = do +stats opts@CliOpts{rawopts_=rawopts, reportspec_=rspec, progstarttime_} j = do let today = _rsDay rspec q = _rsQuery rspec l = ledgerFromJournal q j intervalspans = snd $ reportSpanBothDates j rspec - showstats = showLedgerStats l today - (ls, txncounts) = unzip $ map showstats intervalspans + (ls, txncounts) = unzip $ map (showLedgerStats verbose l today) intervalspans numtxns = sum txncounts b = unlinesB ls + verbose = boolopt "verbose" rawopts writeOutputLazyText opts $ TL.init $ TB.toLazyText b t <- getPOSIXTime let dt = t - progstarttime_ @@ -68,8 +70,8 @@ stats opts@CliOpts{reportspec_=rspec, progstarttime_} j = do RTSStats{..} <- getRTSStats printf (intercalate ", " - ["Runtime stats : %.2f s elapsed" - ,"%.0f txns/s" + ["Runtime stats : %.2f s elapsed" -- keep synced + ,"%.0f txns/s" -- -- ,"%0.0f MB avg live" ,"%0.0f MB live" ,"%0.0f MB alloc" @@ -84,7 +86,7 @@ stats opts@CliOpts{reportspec_=rspec, progstarttime_} j = do else printf (intercalate ", " - ["Runtime stats : %.2f s elapsed" + ["Runtime stats : %.2f s elapsed" -- keep ,"%.0f txns/s" ] ++ "\n(add +RTS -T -RTS for more)\n") (realToFrac dt :: Float) @@ -93,8 +95,8 @@ stats opts@CliOpts{reportspec_=rspec, progstarttime_} j = do toMegabytes n = realToFrac n / 1000000 ::Float -- SI preferred definition, 10^6 -- toMebibytes n = realToFrac n / 1048576 ::Float -- traditional computing definition, 2^20 -showLedgerStats :: Ledger -> Day -> DateSpan -> (TB.Builder, Int) -showLedgerStats l today spn = +showLedgerStats :: Bool -> Ledger -> Day -> DateSpan -> (TB.Builder, Int) +showLedgerStats verbose l today spn = (unlinesB $ map (renderRowB def{tableBorders=False, borderSpaces=False} . showRow) stts ,tnum) where @@ -103,8 +105,8 @@ showLedgerStats l today spn = w = 20 -- keep synced with labels above -- w = maximum $ map (T.length . fst) stts (stts, tnum) = ([ - ("Main file", path) -- ++ " (from " ++ source ++ ")") - ,("Included files", unlines $ drop 1 $ journalFilePaths j) + ("Main file", path') -- ++ " (from " ++ source ++ ")") + ,("Included files", if verbose then unlines includedpaths else show (length includedpaths)) ,("Txns span", printf "%s to %s (%d days)" (showstart spn) (showend spn) days) ,("Last txn", maybe "none" show lastdate ++ showelapsed lastelapsed) ,("Txns", printf "%d (%0.1f per day)" tnum txnrate) @@ -112,8 +114,8 @@ showLedgerStats l today spn = ,("Txns last 7 days", printf "%d (%0.1f per day)" tnum7 txnrate7) ,("Payees/descriptions", show $ size $ fromList $ map (tdescription) ts) ,("Accounts", printf "%d (depth %d)" acctnum acctdepth) - ,("Commodities", printf "%s (%s)" (show $ length cs) (T.intercalate ", " cs)) - ,("Market prices", printf "%s (%s)" (show $ length mktprices) (T.intercalate ", " mktpricecommodities)) + ,("Commodities", printf "%s%s" (show $ length cs) (if verbose then " (" <> T.intercalate ", " cs <> ")" else "")) + ,("Market prices", printf "%s%s" (show $ length mktprices) (if verbose then " (" <> T.intercalate ", " mktpricecommodities <> ")" else "")) -- Txns this month : %(monthtxns)s (last month in the same period: %(lastmonthtxns)s) -- Unmarked txns : %(unmarked)s -- Days since reconciliation : %(reconcileelapsed)s @@ -122,7 +124,8 @@ showLedgerStats l today spn = ,tnum1) where j = ljournal l - path = journalFilePath j + path' = if verbose then path else ".../" <> takeFileName path where path = journalFilePath j + includedpaths = drop 1 $ journalFilePaths j ts = sortOn tdate $ filter (spanContainsDate spn . tdate) $ jtxns j as = nub $ map paccount $ concatMap tpostings ts cs = either error' Map.keys $ commodityStylesFromAmounts $ concatMap (amountsRaw . pamount) $ concatMap tpostings ts -- PARTIAL: diff --git a/hledger/Hledger/Cli/Commands/Stats.md b/hledger/Hledger/Cli/Commands/Stats.md index 4bcc0731d..85a0227cc 100644 --- a/hledger/Hledger/Cli/Commands/Stats.md +++ b/hledger/Hledger/Cli/Commands/Stats.md @@ -4,36 +4,43 @@ Show journal and performance statistics. _FLAGS -The stats command displays summary information for the whole journal, or +The stats command shows summary information for the whole journal, or a matched part of it. With a [reporting interval](#reporting-interval), it shows a report for each report period. -At the end, it shows (in the terminal) the overall run time and number of -transactions processed per second. Note these are approximate and will vary -based on machine, current load, data size, hledger version, haskell lib -versions, GHC version.. but they may be of interest. The `stats` command's -run time is similar to that of a single-column balance report. +The default output is fairly impersonal, though it reveals the main file name. +With `-v/--verbose`, more details are shown, like file paths, included files, +and commodity names. + +It also shows some run time statistics: + +- elapsed time +- throughput: the number of transactions processed per second +- live: the peak memory in use by the program to do its work +- alloc: the peak memory allocation from the OS as seen by GHC. + Measuring this externally, eg with GNU time, is more accurate; + usually that will be a larger number; sometimes (with swapping?) smaller. + +The `stats` command's run time is similar to that of a balance report. Example: ```cli -$ hledger stats -f examples/1000x1000x10.journal -Main file : /Users/simon/src/hledger/examples/1000x1000x10.journal -Included files : -Transactions span : 2000-01-01 to 2002-09-27 (1000 days) -Last transaction : 2002-09-26 (6995 days ago) -Transactions : 1000 (1.0 per day) -Transactions last 30 days: 0 (0.0 per day) -Transactions last 7 days : 0 (0.0 per day) -Payees/descriptions : 1000 -Accounts : 1000 (depth 10) -Commodities : 26 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) -Market prices : 1000 (A) - -Run time : 0.12 s -Throughput : 8342 txns/s +$ hledger stats -f examples/1ktxns-1kaccts.journal +Main file : .../1ktxns-1kaccts.journal +Included files : 0 +Txns span : 2000-01-01 to 2002-09-27 (1000 days) +Last txn : 2002-09-26 (7827 days ago) +Txns : 1000 (1.0 per day) +Txns last 30 days : 0 (0.0 per day) +Txns last 7 days : 0 (0.0 per day) +Payees/descriptions : 1000 +Accounts : 1000 (depth 10) +Commodities : 26 +Market prices : 1000 +Runtime stats : 0.12 s elapsed, 8266 txns/s, 4 MB live, 16 MB alloc ``` This command supports the [-o/--output-file](hledger.html#output-destination) option -(but not [-O/--output-format](hledger.html#output-format) selection). +(but not [-O/--output-format](hledger.html#output-format)). diff --git a/hledger/test/journal/balance-assertions.test b/hledger/test/journal/balance-assertions.test index 68782e486..c746e75da 100755 --- a/hledger/test/journal/balance-assertions.test +++ b/hledger/test/journal/balance-assertions.test @@ -15,9 +15,7 @@ b $-1 = $-3 (b) $1 = $-2 -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 2. same entries as 1 but different parse order, assertion should still pass based on date < @@ -34,9 +32,7 @@ $ hledger -f - stats a $1 =$2 b $-1 =$-2 -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 3. like 1 but switch order of postings in last entry, # assertion should fail and exit code should be non zero @@ -54,7 +50,7 @@ $ hledger -f - stats (b) $1 = $-2 b $-1 = $-3 -$ hledger -f - stats +$ hledger -f - check >2 /Error: -:11:12/ >=1 @@ -63,9 +59,7 @@ $ hledger -f - stats 2013/1/1 (a) 1 =1 -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 5. should work for fractional amount with trailing zeros < @@ -81,9 +75,7 @@ $ hledger -f - stats a $0.7 =$2 b =-$2 -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 6. assertions currently check only a single commodity's balance, like Ledger < @@ -93,9 +85,7 @@ $ hledger -f - stats (a) 0 = A1 (a) C0 = D0 -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 7. balances should accumulate (#195) < @@ -106,9 +96,7 @@ $ hledger -f - stats 1/2 (a) 3F = 4F -$ hledger -f - stats -> !/assertion failed/ ->=0 +$ hledger -f - check # ** 8. what should happen here ? Currently, # in a, 3.4 EUR @@ $5.6 and -3.4 EUR cancel out (wrong ?) @@ -128,9 +116,7 @@ $ hledger -f - stats # a $0.1 =$1.30 # b =-$1.30 -# $ hledger -f - stats -# > /Transactions/ -# >=0 +# $ hledger -f - check # ** 8. Using balance assignment to set balances. < @@ -146,9 +132,7 @@ $ hledger -f - stats a $10 =$11.3 b =$-11.3 -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 9. Multiple assertions for an account in the same transaction. @@ -166,9 +150,7 @@ $ hledger -f - stats b $-1 = $-3 b $-1 = $-4 -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 10. Multiple assertions and assignments for an account in the same transaction. < @@ -196,9 +178,7 @@ $ hledger -f - stats c = 50 B c = 50 A -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 11. Assignments and virtual postings < @@ -214,16 +194,15 @@ $ hledger -f - stats [a] = $5 b = $9 -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check + # ** 12. Having both assignments and posting dates is not supported. < 2013/1/1 a $1 =$1 b =$-1 ; date:2012/1/1 -$ hledger -f - stats +$ hledger -f - check >2 /Balance assignments and custom posting dates may not be combined/ >=1 @@ -247,9 +226,7 @@ $ hledger -f - stats [d] 10 -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 14. Mix different commodities < @@ -261,9 +238,7 @@ $ hledger -f - stats a $-1 = $0 b -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 15. Mix different commodities and assignments < @@ -282,9 +257,7 @@ $ hledger -f - stats a b = 0 zorkmids -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 16. Total assertions (==) parse correctly < @@ -295,9 +268,7 @@ $ hledger -f - stats 2016/1/2 a == $1 -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 17. Total assertions consider entire multicommodity amount < @@ -312,7 +283,7 @@ $ hledger -f - stats 2016/1/3 a 0 == $1 -$ hledger -f - stats +$ hledger -f - check >2 /Error: -:10:15:/ >=1 @@ -331,9 +302,7 @@ $ hledger -f - stats b 0 = $-1 b 0 = 0 zorkmids -$ hledger -f - stats -> /Transactions/ ->=0 +$ hledger -f - check # ** 19. Cost is ignored when checking balance assertions. < diff --git a/hledger/test/journal/include.test b/hledger/test/journal/include.test index cc8cb6244..ad4443707 100644 --- a/hledger/test/journal/include.test +++ b/hledger/test/journal/include.test @@ -74,12 +74,12 @@ $ printf '2018/01/01\n (A) 1\n' >included.journal; HOME="$PWD" hledger -f - pr # They use different file names so a single concurrent shelltest invocation will be fine. # ** 7. test that order of include files is maintained -$ printf 'include _b\n' >_a; touch _b; hledger -f _a stats | grep _ | sed -e 's%.*/%%'; rm -rf _a _b +$ printf 'include _b\n' >_a; touch _b; hledger -f _a stats -v | grep _ | sed -e 's%.*/%%'; rm -rf _a _b _a _b # ** 8. and with --auto code path -$ printf 'include _d\n=\n' >_c; touch _d; hledger -f _c stats --auto | grep _ | sed -e 's%.*/%%'; rm -rf _c _d +$ printf 'include _d\n=\n' >_c; touch _d; hledger -f _c stats -v --auto | grep _ | sed -e 's%.*/%%'; rm -rf _c _d _c _d diff --git a/hledger/test/stats.test b/hledger/test/stats.test index cdb7945b0..dede1acad 100644 --- a/hledger/test/stats.test +++ b/hledger/test/stats.test @@ -7,6 +7,6 @@ $ hledger -f- stats < include a.j include b.j -$ touch a.j b.j; hledger -f- stats; rm -f a.j b.j +$ touch a.j b.j; hledger -f- stats -v; rm -f a.j b.j > /Included files.*\/a\.j .*\/b\.j/