Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade /programs, add desksaver #171

Closed
wants to merge 13 commits into from
121 changes: 121 additions & 0 deletions virtual-programs/watcher.folk
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
set ::watchdog_debug 0

When the collected matches for [list /someone/ claims /page/ has program /program/] are /matches/ & the clock time is /t/ {
# Analyze the matches, watch for non-virtual programs
set webPrograms [list]
set realPrograms [list]
foreach match $matches {
set page [dict get $match page]
switch -glob $page {
"virtual-programs/*" {
continue;
}
"setup.folk.default" {
continue;
}
"web-program-*" {
lappend webPrograms $page
}
default {
lappend realPrograms $page
}
}
}

Claim there are [llength $webPrograms] web programs
Claim there are [llength $realPrograms] real programs
}

When the clock time is /t/ {
# Monitor RAM, CPU, and disk usage
set ramInfo [exec free -m]
set lines [split $ramInfo "\n"]
set memLine [lindex $lines 1]
set memParts [regexp -all -inline {\S+} $memLine]
set totalMem [lindex $memParts 1]
set usedMem [lindex $memParts 2]
set freeMem [lindex $memParts 3]

if {$::watchdog_debug} {
puts "Total Memory: $totalMem MB"
puts "Used Memory: $usedMem MB"
puts "Free Memory: $freeMem MB"
}

set ramUsage [expr {$usedMem / $totalMem * 100}]

if {$::watchdog_debug} {
puts "RAM Usage: $ramUsage%"
}

# Calculate CPU usage
set cpuInfo [exec top -bn1 | grep "Cpu(s)"]
set cpuUsage [lindex [regexp -all -inline {\d+\.\d+} $cpuInfo] 0]

if {$::watchdog_debug} {
puts "CPU Usage: $cpuUsage%"
}

# Calculate disk usage
set dfOutput [exec df -h /]
set diskLine [lindex [split $dfOutput "\n"] 1]
set diskParts [regexp -all -inline {\S+} $diskLine]
set diskUsage [string map {% {}} [lindex $diskParts 4]]

if {$::watchdog_debug} {
puts "Disk Usage: $diskUsage%"
}

Claim RAM usage is $ramUsage
Claim CPU usage is $cpuUsage
Claim disk usage is $diskUsage

# # Check for high resource usage and make warnings if necessary
if {$ramUsage > 90} {
Claim $this has warning"High RAM usage: $ramUsage MB"
}
if {$cpuUsage > 80} {
Claim $this has warning "High CPU usage: $cpuUsage%"
}
if {$diskUsage > 90} {
Claim $this has warning "High disk usage: $diskUsage%"
}
}

Wish the web server handles route "/resource-usage" with handler {
set ramUsage 0
set cpuUsage 0
set diskUsage 0

When /someone/ claims RAM usage is /ramUsage/ & /someone/ claims CPU usage is /cpuUsage/ & /someone/ claims disk usage is /diskUsage/ {
set ramUsage $ramUsage
set cpuUsage $cpuUsage
set diskUsage $diskUsage
}

html {
<html>
<head>
<link rel="stylesheet" href="/style.css">
<title>Statements</title>
</head>
<body>
<nav>
<a href="/new"><button>New program</button></a>
<a href="/programs">Running programs</a>
<a href="/timings">Timings</a>
<a href="/keyboards">Keyboards</a>
<a href="/statementClauseToId.pdf">statementClauseToId graph</a>
<a href="/statements.pdf">statements graph</a>
</nav>
<h1>Resource Usage</h1>
<div>
<!-- TODO: how to subs the real values into the html proc? -->
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I'm missing something @osnr ... when I use subst here instead of html the page doesn't render at all, html doesn't fill in the $.*Usage variables though.

Screenshot 2024-08-15 at 11 52 25 PM

<p>RAM Usage: $ramUsage %</p>
<p>CPU Usage: $cpuUsage %</p>
<p>Disk Usage: $diskUsage %</p>
</div>
</body>
</html>
}
}
81 changes: 73 additions & 8 deletions web.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ proc getDotAsPdf {dot contentTypeVar} {
set response [read $fd]; close $fd; return $response
}

proc emitHTMLForProgramList {programList label} {
set prettyLabel [string map {- " "} $label]
set prettyLabel [string totitle $prettyLabel]:
set returnList [list "<details data-label='$label' data-count='[llength $programList]'><summary>$prettyLabel ([llength $programList])</summary>"]
lappend returnList "<ul>"
foreach item $programList {
lappend returnList "<li>$item</li>"
}
lappend returnList "</ul>"
lappend returnList "</details>"
join $returnList
}

proc handlePage {path httpStatusVar contentTypeVar} {
upvar $contentTypeVar contentType
switch -exact -- $path {
Expand Down Expand Up @@ -61,18 +74,70 @@ proc handlePage {path httpStatusVar contentTypeVar} {
}
}
"/programs" {
set programs [Statements::findMatches [list /someone/ claims /programName/ has program /program/]]
# TODO:
# - Make this synchronous
# - Maybe should actually, move this to a virtual-program/watcher.folk.default programs that makes claims like:
# Claim virtual programs are [list {page a program p_a} {page b program p_b} {page c program p_c}]
# Claim core programs are [list {page a program p_a} {page b program p_b} {page c program p_c}]
# Claim web programs are [list {page a program p_a} {page b program p_b} {page c program p_c}]
# Claim real programs are [list {page a program p_a} {page b program p_b} {page c program p_c}]

set programs [Statements::findMatches [list /someone/ claims /page/ has program /program/]]
set vp [list]; # virtual programs
set cp [list]; # core programs
set wp [list]; # web programs
set rp [list]; # real programs

# TODO:
# Right now this duplicates the virtual-programs/watcher.folk logic.
# Let's refactor this to use the claim logic in the future.
# - @cwervo 2024-09-15
foreach match $programs {
set page [dict get $match page]
switch -glob $page {
"virtual-programs/*" {
lappend vp $page
}
"setup.folk.default" {
lappend cp $page
}
"web-program-*" {
lappend wp $page
}
default {
lappend rp $page
}
}
}

subst {
<html>
<head>
<link rel="stylesheet" href="/style.css">
<title>Running programs</title>
<link rel="stylesheet" href="/style.css">
<title>Running programs</title>
<link rel="stylesheet" href="/style.css">
<style>
body {
font-family: math;
}
summary {
font-family: monospace;
font-size: 2em;
}
</style>
<script src="/lib/folk.js"></script>
<script>
/* TODO:
( ) Add a ws.watch() for /someone/ claims /page/ has program /program/
*/
</script>
</head>
<body>
[join [lmap p $programs { dict with p {subst {
<h2>$programName</h2>
<pre><code>[htmlEscape [lindex $program 1]]</code></pre>
}} }] "\n"]
[emitHTMLForProgramList $rp "real-programs"]
[emitHTMLForProgramList $wp "web-programs"]
[emitHTMLForProgramList $vp "virtual-programs"]
[emitHTMLForProgramList $cp "core-programs"]
[expr {[llength $rp] ? "<h2>[llength $rp] [expr {[llength $rp] == 1 ? "program is" : "programs are"}] out.</h2>" : "No real programs are out."}]
</body>
</html>
}
Expand Down Expand Up @@ -232,4 +297,4 @@ if {[catch {set ::serverSock [socket -server handleConnect 4273]}] == 1} {
}

::websocket::server $::serverSock
::websocket::live $::serverSock /ws handleWS
::websocket::live $::serverSock /ws handleWS