feat: add shard status page

This commit is contained in:
spiral 2022-01-11 22:09:50 -05:00
parent e897a33c41
commit b6da842206
No known key found for this signature in database
GPG Key ID: A6059F0CA0E1BD31
4 changed files with 209 additions and 1 deletions

View File

@ -25,7 +25,7 @@
"discord-markdown": "^2.5.1", "discord-markdown": "^2.5.1",
"gh-pages": "^3.2.3", "gh-pages": "^3.2.3",
"moment": "^2.29.1", "moment": "^2.29.1",
"sass": "^1.45.1", "sass": "^1.47.0",
"svelecte": "^3.4.5", "svelecte": "^3.4.5",
"svelte-autosize": "^1.0.1", "svelte-autosize": "^1.0.1",
"svelte-icons": "^2.1.0", "svelte-icons": "^2.1.0",

View File

@ -7,6 +7,7 @@
import Footer from './lib/Footer.svelte'; import Footer from './lib/Footer.svelte';
import Public from "./pages/Public.svelte"; import Public from "./pages/Public.svelte";
import Main from "./pages/profiles/Main.svelte"; import Main from "./pages/profiles/Main.svelte";
import Status from './pages/status.svelte';
// theme cdns (I might make some myself too) // theme cdns (I might make some myself too)
let light = "https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css"; let light = "https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css";
@ -64,5 +65,6 @@
<Route path = "profile/g"> <Route path = "profile/g">
hey please provide a group hey please provide a group
</Route> </Route>
<Route path="status"><Status /></Route>
<Footer /> <Footer />
</Router> </Router>

89
src/lib/shard.svelte Normal file
View File

@ -0,0 +1,89 @@
<script lang="ts">
let isHovering = false;
export let shard = {
id: 1,
status: "",
ping:0,
last_connection:0,
last_heartbeat:0.
};
let color = "background-color: #fff";
// shard is down
// todo: check if last heartbeat is really recent, since database up/down status can get out of sync
if (shard.status != "up") color = "background-color: #000;";
// shard latency is < 250ms: OK!
else if (shard.ping < 300) color = "background-color: #00cc00;";
// shard latency is 250ms < ping < 600ms: slow, but OK
else if (shard.ping < 600) color = "background-color: #da9317;";
// shard latency is >600ms, this might be problematic
else color = "background-color: #cc0000;"
</script>
<div class="wrapper">
<div
on:click={() => isHovering = !isHovering}
class="shard" id={shard.id.toString()}
style={color}
>{ shard.id }</div>
{#if isHovering}
<div class="more-info">
<h3>Shard { shard.id }</h3>
<br>
<span>Status: <b>{ shard.status }</b></span><br>
<span>Latency: { shard.ping }ms</span><br>
<span>Last connection: { new Date(shard.last_connection).toUTCString().match(/([0-9][0-9]:[0-9][0-9]:[0-9][0-9])/)?.shift() }</span><br>
<span>Last heartbeat: { new Date(shard.last_heartbeat).toUTCString().match(/([0-9][0-9]:[0-9][0-9]:[0-9][0-9])/)?.shift() }</span><br>
<br>
</div>
{/if}
</div>
<style>
.wrapper {
height: 55px;
width: 55px;
display: block;
float: left;
}
.shard {
color: #fff;
display: block;
float: left;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
justify-content: center;
z-index: 1;
height: 50px;
width: 50px;
margin-right: 5px;
margin-bottom: 5px;
border-radius: 2px;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome, Edge, Opera and Firefox */
}
.more-info {
/* display: none; */
position: absolute;
margin-top: 3em;
will-change: transform;
min-height: 150px;
width: 200px;
z-index: 2;
border-radius: 5px;
background-color: #333;
color: #fff;
opacity: 95%;
text-align: center;
}
</style>

117
src/pages/status.svelte Normal file
View File

@ -0,0 +1,117 @@
<script lang="ts">
import { Container } from 'sveltestrap';
import ShardItem from '../lib/shard.svelte';
let message = "Loading...";
let shards = [];
let pingAverage = "";
let currentCommitMsg = "";
let foundShard = {
id: 1,
status: 1,
ping:"",
last_connection:0,
last_heartbeat:0.
};
foundShard = null;
let findShardInput = "";
let valid = false;
const get = async () => {
const pkdata = await fetch("https://api.pluralkit.me/v1/meta").then(x => x.json());
shards = pkdata.shards.sort((x, y) => (x.id > y.id) ? 1 : -1);
let pings = 0;
shards = shards.map(shard => {
shard.ping = Math.trunc(shard.ping * 1000);
pings += shard.ping;
return shard;
});
pingAverage = Math.trunc(pings / shards.length).toString();
currentCommitMsg = `Current Git commit: <a href="https://github.com/xSke/PluralKit/commit/${pkdata.version}">${pkdata.version}</a>`;
message = "";
};
get();
setTimeout(get, 30 * 1000);
// javascript wants everything to be BigInts
const getShardID = (guild_id: string, num_shards: number) => guild_id == "" ? -1 : (BigInt(guild_id) >> BigInt(22)) % BigInt(num_shards);
let shardInfoMsg = "";
let shardInfoHandler = (_: Event) => {
if (findShardInput == "" || !findShardInput) {
valid = false;
foundShard = null;
shardInfoMsg = "";
return;
};
var match = findShardInput.match(/https:\/\/[\w+]?discord[app]?.com\/channels\/(\d+)\/\d+\/\d+/);
if (match != null) {
console.log("match", match)
foundShard = shards[Number(getShardID(match[1], shards.length))];
valid = true;
shardInfoMsg = "";
return;
}
try {
var shard = getShardID(findShardInput, shards.length);
if (shard == -1) {
valid = false;
foundShard == null;
shardInfoMsg = "Invalid server ID";
return;
}
foundShard = shards[Number(shard)];
valid = true;
shardInfoMsg = "";
} catch(e) {
valid = false;
shardInfoMsg = "Invalid server ID";
}
};
</script>
<Container>
<h1>Bot status</h1>
<span>{@html currentCommitMsg}</span>
<br>
<noscript>Please enable JavaScript to view this page!</noscript>
{ shards.length } shards ({ shards.filter(x => x.status == "up").length } up) <br>
Average latency: { pingAverage }ms
<br><br>
All times in UTC. More statistics available at <a href="https://stats.pluralkit.me">https://stats.pluralkit.me</a>
<br><br>
<details>
<summary><b>Find my shard</b></summary>
<br>
Enter a server ID or a message link to find the shard currently assigned to your server:
<br>
<input bind:value={findShardInput} on:input={shardInfoHandler} />
<br><br>
<span>{ shardInfoMsg }</span>
{#if valid}
<h3>Your shard is: Shard { foundShard.id }</h3>
<br>
<span>Status: <b>{ foundShard.status }</b></span><br>
<span>Latency: { foundShard.ping }ms</span><br>
<span>Last connection: { new Date(foundShard.last_connection).toUTCString()?.match(/([0-9][0-9]:[0-9][0-9]:[0-9][0-9])/)?.shift() }</span><br>
<span>Last heartbeat: { new Date(foundShard.last_heartbeat).toUTCString().match(/([0-9][0-9]:[0-9][0-9]:[0-9][0-9])/)?.shift() }</span><br>
{/if}
</details>
<br><br>
<h2>Shard status</h2>
<span>{ message }</span>
{#each shards as shard}
<ShardItem shard={shard} />
{/each}
</Container>