about summary refs log tree commit diff
path: root/packages/slocalc
diff options
context:
space:
mode:
authorFranck Cuny <fcuny@roblox.com>2024-04-16 09:24:12 -0700
committerFranck Cuny <fcuny@roblox.com>2024-04-16 09:24:12 -0700
commitefeef95bbdf2e79e8ba48198cb8ff0534afce324 (patch)
tree2a0b0ae890c437330865311d1ac294fb987c7fbd /packages/slocalc
parentinstall nomad pack (diff)
downloadworld-efeef95bbdf2e79e8ba48198cb8ff0534afce324.tar.gz
move the `slocalc` to a python script
Diffstat (limited to 'packages/slocalc')
-rw-r--r--packages/slocalc/default.nix25
-rwxr-xr-xpackages/slocalc/slocalc.py69
2 files changed, 94 insertions, 0 deletions
diff --git a/packages/slocalc/default.nix b/packages/slocalc/default.nix
new file mode 100644
index 0000000..114120e
--- /dev/null
+++ b/packages/slocalc/default.nix
@@ -0,0 +1,25 @@
+{ lib, python3, stdenvNoCC }:
+
+stdenvNoCC.mkDerivation rec {
+  pname = "slocalc";
+  src = ./slocalc.py;
+  version = "0.1.0";
+
+  buildInputs = [ python3 ];
+  propagatedBuildInputs = [ python3 ];
+
+  dontUnpack = true;
+  dontBuild = true;
+
+  installPhase = ''
+    mkdir -p $out/bin
+    cp $src $out/bin/${pname}
+  '';
+
+  meta = with lib; {
+    description = "Calculate SLO uptime.";
+    license = with licenses; [ mit ];
+    platforms = platforms.unix;
+    maintainers = with maintainers; [ fcuny ];
+  };
+}
diff --git a/packages/slocalc/slocalc.py b/packages/slocalc/slocalc.py
new file mode 100755
index 0000000..e13e850
--- /dev/null
+++ b/packages/slocalc/slocalc.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+"""
+A simple SLO calculator for the command line.
+
+$ slocalc.py 99.99
+daily:     0 days, 0 hours, 0 minutes, 8 seconds
+weekly:    0 days, 0 hours, 1 minutes, 0 seconds
+monthly:   0 days, 0 hours, 4 minutes, 19 seconds
+quarterly: 0 days, 0 hours, 12 minutes, 57 seconds
+yearly:    0 days, 0 hours, 52 minutes, 33 seconds
+"""
+
+from typing import Optional
+from datetime import timedelta
+
+import sys
+
+
+seconds_in_hour = 60 * 60
+
+
+def convert_to_float(s: str) -> Optional[float]:
+    try:
+        return float(s)
+    except ValueError:
+        print(f"error: '{s}' cannot be converted to float")
+        return None
+
+
+def seconds_to_human_readable(seconds: int) -> str:
+    delta = timedelta(seconds=seconds)
+    days = delta.days
+    hours, remainder = divmod(delta.seconds, 3600)
+    minutes, seconds = divmod(remainder, 60)
+    return f"{days} days, {hours} hours, {minutes} minutes, {seconds} seconds"
+
+
+def cli():
+    if len(sys.argv) <= 1:
+        print("you need at least one argument", file=sys.stderr)
+        sys.exit(1)
+
+    uptime = convert_to_float(sys.argv[1])
+    if uptime is None:
+        print("failed to read input")
+        sys.exit(1)
+
+    if uptime <= 0:
+        uptime = 0
+    if uptime >= 100:
+        uptime = 100
+
+    allowed_downtime = ((100 * 100) - (uptime * 100)) / (100 * 100)
+
+    daily_seconds = seconds_in_hour * 24 * allowed_downtime
+    week_seconds = daily_seconds * 7
+    month_seconds = daily_seconds * 30
+    quarter_seconds = daily_seconds * 90
+    year_seconds = daily_seconds * 365
+
+    print("daily:     {0}".format(seconds_to_human_readable(daily_seconds)))
+    print("weekly:    {0}".format(seconds_to_human_readable(week_seconds)))
+    print("monthly:   {0}".format(seconds_to_human_readable(month_seconds)))
+    print("quarterly: {0}".format(seconds_to_human_readable(quarter_seconds)))
+    print("yearly:    {0}".format(seconds_to_human_readable(year_seconds)))
+
+
+if __name__ == "__main__":
+    cli()