Added footer and memory usage.

This commit is contained in:
Andrew Lalis 2023-08-22 10:44:10 -04:00
parent a7be040dea
commit 859f17ccc5
6 changed files with 93 additions and 3 deletions

View File

@ -9,6 +9,7 @@
"d2sqlite3": "~>1.0.0", "d2sqlite3": "~>1.0.0",
"handy-httpd": "~>7.9.3", "handy-httpd": "~>7.9.3",
"jwt": "~>0.4.0", "jwt": "~>0.4.0",
"resusage": "~>0.3.2",
"slf4d": "~>2.4.2" "slf4d": "~>2.4.2"
}, },
"description": "API for the litelist application.", "description": "API for the litelist application.",

View File

@ -9,6 +9,7 @@
"httparsed": "1.2.1", "httparsed": "1.2.1",
"jwt": "0.4.0", "jwt": "0.4.0",
"memutils": "1.0.9", "memutils": "1.0.9",
"resusage": "0.3.2",
"slf4d": "2.4.2", "slf4d": "2.4.2",
"streams": "3.5.0" "streams": "3.5.0"
} }

View File

@ -57,9 +57,7 @@ private HttpServer initServer() {
immutable string API_PATH = "/api"; immutable string API_PATH = "/api";
auto mainHandler = new PathDelegatingHandler(); auto mainHandler = new PathDelegatingHandler();
mainHandler.addMapping(Method.GET, API_PATH ~ "/status", (ref HttpRequestContext ctx) { mainHandler.addMapping(Method.GET, API_PATH ~ "/status", &handleStatus);
ctx.response.writeBodyString("online");
});
auto optionsHandler = toHandler((ref HttpRequestContext ctx) { auto optionsHandler = toHandler((ref HttpRequestContext ctx) {
ctx.response.setStatus(HttpStatus.OK); ctx.response.setStatus(HttpStatus.OK);
@ -82,3 +80,16 @@ private HttpServer initServer() {
return new HttpServer(mainHandler, config); return new HttpServer(mainHandler, config);
} }
void handleStatus(ref HttpRequestContext ctx) {
import resusage;
import std.process;
import std.json;
immutable int pId = thisProcessID();
ProcessMemInfo procInfo = processMemInfo(pId);
JSONValue data = JSONValue(string[string].init);
data.object["virtualMemory"] = JSONValue(procInfo.usedVirtMem);
data.object["physicalMemory"] = JSONValue(procInfo.usedRAM);
ctx.response.writeBodyString(data.toString(), "application/json");
}

View File

@ -1 +1,20 @@
export const API_URL = import.meta.env.VITE_API_URL export const API_URL = import.meta.env.VITE_API_URL
export interface StatusInfo {
virtualMemory: number
physicalMemory: number
}
export async function getStatus(): Promise<StatusInfo | null> {
try {
const response = await fetch(API_URL + "/status")
if (response.ok) {
return await response.json()
}
console.warn("Non-OK status response: ", response.status)
return null
} catch (error: any) {
console.error(error)
return null
}
}

View File

@ -3,11 +3,37 @@ This is a generic container to wrap around a page's content to keep it within
a mobile-friendly width. a mobile-friendly width.
--> -->
<script setup lang="ts"> <script setup lang="ts">
import type {Ref} from "vue";
import {onMounted, ref} from "vue";
import type {StatusInfo} from "@/api/base";
import {getStatus} from "@/api/base";
import {humanFileSize} from "@/util";
const statusInfo: Ref<StatusInfo | null> = ref(null)
onMounted(async () => {
statusInfo.value = await getStatus()
setInterval(async () => {
statusInfo.value = await getStatus()
}, 5000)
})
</script> </script>
<template> <template>
<div class="page-container"> <div class="page-container">
<slot/> <slot/>
<!-- Each contained page also gets a nice little footer! -->
<footer style="text-align: center">
<p style="font-size: smaller">
LiteList created with by
<a href="https://andrewlalis.com" target="_blank">Andrew Lalis</a>
using <a href="https://vuejs.org/" target="_blank">🌿 Vue 3</a> and
<a href="https://github.com/andrewlalis/handy-httpd" target="_blank">🌎 Handy-Httpd</a>.
</p>
<p v-if="statusInfo" style="font-size: smaller; font-family: monospace;">
Memory used: <span v-text="humanFileSize(statusInfo.physicalMemory, true, 1)"></span>
</p>
</footer>
</div> </div>
</template> </template>

View File

@ -25,3 +25,35 @@ export function getSecondsTilExpire(token: string): number {
const decoded = parseJwt(token) const decoded = parseJwt(token)
return decoded.exp - now return decoded.exp - now
} }
/**
* Format bytes as human-readable text.
*
* @param bytes Number of bytes.
* @param si True to use metric (SI) units, aka powers of 1000. False to use
* binary (IEC), aka powers of 1024.
* @param dp Number of decimal places to display.
*
* @return Formatted string.
*/
export function humanFileSize(bytes, si=false, dp=1) {
const thresh = si ? 1000 : 1024;
if (Math.abs(bytes) < thresh) {
return bytes + ' B';
}
const units = si
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
let u = -1;
const r = 10**dp;
do {
bytes /= thresh;
++u;
} while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
return bytes.toFixed(dp) + ' ' + units[u];
}