summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2023-02-26 14:47:24 +0200
committerPaul Buetow <paul@buetow.org>2023-02-26 14:47:24 +0200
commit7c31ae967dde77be3c734d43d985b279ff172424 (patch)
tree3bd0e8ec19f7103c2878ec569fb3879b874a0bdc
parent819a87d817d8905523a44d52c274fe879af6408c (diff)
initial human outputing
-rw-r--r--src/guprecords.raku54
1 files changed, 37 insertions, 17 deletions
diff --git a/src/guprecords.raku b/src/guprecords.raku
index 571f90a..976a83c 100644
--- a/src/guprecords.raku
+++ b/src/guprecords.raku
@@ -3,26 +3,25 @@
use v6.d;
subset Nat of Int where * >= 0;
-
subset Cat of Str where * eq any <host os os-major uname>;
subset SubCat of Str where * eq any <boots uptime downtime lifespan meta-score>;
-
subset HostOnlyCat of Cat where * eq 'host';
subset BasicSubCat of SubCat where * ne any <downtime lifespan>;
+our Nat constant DAY = 1 * 24 * 3600;
+our Nat constant MONTH = 30 * DAY;
+
class Epoch {
- our Nat constant DAY = 1 * 24 * 3600;
- our Nat constant MONTH = 30 * DAY;
has Nat $.value is required;
submethod new (Nat $value) { self.bless(:$value) }
- method duration returns Str {
+ method human-duration returns Str {
my DateTime \dt .= new(Instant.from-posix: $!value);
"{dt.year-1970} years, {dt.month} months, {dt.day} days";
}
- method date returns Str {
+ method human-date returns Str {
DateTime.new(Instant.from-posix: $!value).yyyy-mm-dd;
}
@@ -38,6 +37,8 @@ class Aggregate {
has Nat $.last-seen;
has Nat $.boots;
+ method new (Str $name) { self.bless(:$name) }
+
method add-record(Str:D :$uptime is readonly, Str:D :$boot-time is readonly) {
my Int $last-seen = $uptime + $boot-time;
$!uptime += $uptime;
@@ -48,7 +49,7 @@ class Aggregate {
}
method meta-score returns Nat {
- Nat((($!uptime * 2) + ($!boots * Epoch.DAY) + (self.is-active ?? Epoch.MONTH !! 0))/1000000)
+ Nat((($!uptime * 2) + ($!boots * DAY) + (self.is-active ?? MONTH !! 0))/1000000)
}
method is-active(Nat:D \limit = 90) returns Bool {
@@ -59,7 +60,7 @@ class Aggregate {
class HostAggregate is Aggregate {
method lifespan returns Nat { $.last-seen - $.first-boot }
method downtime returns Nat { self.lifespan - $.uptime }
- method meta-score returns Nat { self.downtime + callsame }
+ method meta-score returns Nat { Nat(self.downtime / 1000000) + callsame }
}
class Aggregator {
@@ -70,7 +71,7 @@ class Aggregator {
die "Record file for {$host} already processed - duplicate inputs?"
if %!aggregates<host>{$host}:exists;
- %!aggregates<host>{$host} = HostAggregate.new: :name($host);
+ %!aggregates<host>{$host} = HostAggregate.new($host);
for $file.IO.lines -> Str $line { self!add-line(:$line, :$host) }
}
@@ -80,9 +81,9 @@ class Aggregator {
my Str $uname = $os.split(' ').first;
my Str $os-major = "$uname {$os.split(' ')[1].split('.').first}...";
- %!aggregates<os>{$os} //= Aggregate.new: :name($os);
- %!aggregates<uname>{$uname} //= Aggregate.new: :name($uname);
- %!aggregates<os-major>{$os-major} //= Aggregate.new: :name($os-major);
+ %!aggregates<os>{$os} //= Aggregate.new($os);
+ %!aggregates<uname>{$uname} //= Aggregate.new($uname);
+ %!aggregates<os-major>{$os-major} //= Aggregate.new($os-major);
for %!aggregates<host>{$host}, %!aggregates<os>{$os},
%!aggregates<uname>{$uname}, %!aggregates<os-major>{$os-major} {
@@ -94,15 +95,24 @@ class Aggregator {
class Reporter {
has Cat $.cat is required;
has SubCat $.sub-cat is required;
+ has Nat $.first is required;
has Hash %.aggregates;
method report {
- for self.sort-by($!sub-cat) -> $what {
- $what.raku.say;
- $what.is-active.say;
+ say "Top {$.first} {$.sub-cat}'s by {$.cat}:\n";
+ my Nat $count = 0;
+
+ for self.sort-by($!sub-cat) -> Aggregate $what {
+ self!pretty-say($what, $count+1);
+ last if ++$count == $.first;
}
}
+ method !pretty-say(Aggregate:D \what, Nat:D \position) {
+ my Str \active = what.is-active ?? ' (still active)' !! '';
+ say "{position}. {what.name}{active}:\n\t{self.human-str($.sub-cat, what)}";
+ }
+
multi method sort-by('uptime') { self.sort-by: *.uptime }
multi method sort-by('boots') { self.sort-by: *.boots }
multi method sort-by('meta-score') { self.sort-by: *.meta-score }
@@ -110,11 +120,18 @@ class Reporter {
multi method sort-by(Code:D $sort-by) {
%!aggregates{$!cat}.values.sort(&$sort-by).reverse;
}
+
+ multi method human-str('uptime', Aggregate:D $what) { "Uptime: {Epoch.new($what.uptime).human-duration}" }
+ multi method human-str('boots', Aggregate:D $what) { "Number of boots: {$what.boots}" }
+ multi method human-str('meta-score', Aggregate:D $what) { "Meta score: {$what.meta-score}" }
}
class HostReporter is Reporter {
multi method sort-by('downtime') { self.sort-by: *.downtime }
multi method sort-by('lifespan') { self.sort-by: *.lifespan }
+
+ multi method human-str('downtime', Aggregate:D $what) { "Downtime: {Epoch.new($what.downtime).human-duration}" }
+ multi method human-str('lifespan', Aggregate:D $what) { "Lifespan: {Epoch.new($what.lifespan).human-duration}" }
}
sub do-it(Str:D \stats-dir, Reporter:D \reporter) {
@@ -128,14 +145,17 @@ multi MAIN(
Str :$stats-dir is required, #= The uptimed raw record input dir.
HostOnlyCat :$cat = 'host', #= Category, one of host, os os-major and uname.
SubCat :$sub-cat = 'uptime', #= Sort by one of boots uptime downtime and lifespan.
+ Nat :$first = 13, #= Only show top N entries.
) {
- do-it($stats-dir, HostReporter.new(:$cat, :$sub-cat));
+ do-it($stats-dir, HostReporter.new(:$cat, :$sub-cat, :$first));
}
multi MAIN(
Str :$stats-dir is required,
Cat :$cat,
BasicSubCat :$sub-cat = 'uptime',
+ Nat :$first = 13,
) {
- do-it($stats-dir, Reporter.new(:$cat, :$sub-cat));
+ do-it($stats-dir, Reporter.new(:$cat, :$sub-cat, :$first));
}
+