Added server status.

main
BurnyLlama 2021-11-05 21:04:53 +01:00
parent 8fb6047dfb
commit 32cb0ab344
9 changed files with 118 additions and 18 deletions

View File

@ -10,9 +10,9 @@ import njk from 'nunjucks'
import initLog from './libs/utils/log.js'
import routes from './routes/routes.js'
import { generateDB } from './libs/database/generate.js'
import { dbInit } from './libs/database/init.js'
import { getStats, setStat } from './libs/serverStats.js'
import { downloadEssentialData } from './libs/download/dowload.js'
const start = Date.now()
@ -21,10 +21,13 @@ const log = initLog("[ MAIN ]")
// Read the .env file
dotenv.config()
dbInit()
setStat("startup", start)
setStat("lastDBUpdate", start)
if (process.env.DOWNLOAD_FILES === "enabled")
await downloadEssentialData()
dbInit()
generateDB()
const Server = express()

47
libs/serverStats.js Normal file
View File

@ -0,0 +1,47 @@
import { sqlite } from './database/init.js'
let globStats = {
startup: Date.now(),
updatingDB: false,
lastDBUpdate: Date.now()
}
/**
* This function returns current server stats.
*
* @returns {object} Stats for server.
* @author BurnyLlama
*/
export function getStats() {
const uptimeMillis = Date.now() - globStats.startup
const uptimeSeconds = `${uptimeMillis / 1000} s`
const dbBytes = sqlite.prepare("SELECT page_count * page_size as size FROM pragma_page_count(), pragma_page_size()").get().size
const db = {
size: {
bytes: dbBytes,
kbytes: dbBytes / 1024,
mbytes: dbBytes / 1024 ** 2,
gbytes: dbBytes / 1024 ** 3,
},
currentlyUpdating: globStats.updatingDB,
lastUpdate: new Date(globStats.lastDBUpdate).toLocaleString()
}
const stats = { uptimeMillis, uptimeSeconds, db }
console.log(stats)
return stats
}
/**
* This sets a "global" stat...
*
* @param {string} stat The stat you want to set.
* @param {*} value The calue you want 'stat' to have.
*
* @author BurnyLlama
*/
export function setStat(stat, value) {
globStats[stat] = value
}

View File

@ -1,6 +1,7 @@
import { Router } from 'express'
import wrapper from '../libs/database/wrapper.js'
import tx from '../libs/routex.js'
import { getStats } from '../libs/serverStats.js'
const routes = Router()
@ -33,4 +34,13 @@ routes.get(
}
)
routes.get(
'/status',
(req, res) => {
const stats = getStats()
tx(req, res)('pages/stats.njk', { stats }, true, { currentSection: null })
}
)
export default routes

View File

@ -36,15 +36,6 @@
.map-info {
margin: .25rem 2rem;
td {
padding: .25rem 0;
vertical-align: middle;
}
td:first-child {
width: 9ch;
}
}
a.map-more-info {
@ -77,10 +68,6 @@ a.map-more-info {
width: 100%;
height: auto;
}
td:first-child {
width: 14ch;
}
}
.leaderboard {

View File

@ -142,6 +142,26 @@ input {
}
//
// TABLES
//
tr {
width: max-content;
td {
padding: .25rem 0;
vertical-align: middle;
width: max-content;
}
td:first-child {
padding: .25rem 1.5rem .25rem 0;
}
}
//
// FOOTER
//

View File

@ -1 +1 @@
.map{background-color:#20203f;border-radius:1rem;box-shadow:.25rem 0 2rem #00001f;display:flex;flex-direction:column;justify-content:center;margin:2rem 1rem;transition:transform .3s,box-shadow .3s}.map:hover{transform:scale(1.05);box-shadow:.5rem 0 4rem #00001f}.map-image{border-radius:1rem 1rem 0 0;width:360px;height:225px}.map-name{font-size:1.2rem;font-weight:bold;margin:1rem 2rem .5rem 2rem}.map-info{margin:.25rem 2rem}.map-info td{padding:.25rem 0;vertical-align:middle}.map-info td:first-child{width:9ch}a.map-more-info{margin:.75rem auto 1.25rem auto;padding:.15rem .5rem;border:.1rem solid #fba7c6;border-radius:.5rem;color:#fba7c6;text-decoration:none transparent;transition:color .3s,background-color .3s}a.map-more-info:hover{color:#10102f;background-color:#fba7c6}.map-detailed{padding-bottom:1rem}.map-detailed:hover{transform:none}.map-detailed .map-image{width:100%;height:auto}.map-detailed td:first-child{width:14ch}.leaderboard{width:max-content;margin:2rem;padding:1.5rem 2rem;background-color:#20203f;border-radius:1rem;box-shadow:.25rem 0 2rem #00001f}.rank{display:flex;margin:1.5rem 0}.rank .country-image{height:1.5rem;margin:auto .5rem auto 0}.rank .rank-position{color:#ee588f;margin:auto .5rem auto 0;font-weight:bold}.rank .rank-player{margin:auto 2rem auto 0}.rank .rank-time{color:#9090af;font-family:"Manrope Light";margin:auto 0 auto auto}.leaderboard-history{width:min(70ch,70vw);margin:2rem;padding:1.5rem 2rem;background-color:#20203f;border-radius:1rem;box-shadow:.25rem 0 2rem #00001f}
.map{background-color:#20203f;border-radius:1rem;box-shadow:.25rem 0 2rem #00001f;display:flex;flex-direction:column;justify-content:center;margin:2rem 1rem;transition:transform .3s,box-shadow .3s}.map:hover{transform:scale(1.05);box-shadow:.5rem 0 4rem #00001f}.map-image{border-radius:1rem 1rem 0 0;width:360px;height:225px}.map-name{font-size:1.2rem;font-weight:bold;margin:1rem 2rem .5rem 2rem}.map-info{margin:.25rem 2rem}a.map-more-info{margin:.75rem auto 1.25rem auto;padding:.15rem .5rem;border:.1rem solid #fba7c6;border-radius:.5rem;color:#fba7c6;text-decoration:none transparent;transition:color .3s,background-color .3s}a.map-more-info:hover{color:#10102f;background-color:#fba7c6}.map-detailed{padding-bottom:1rem}.map-detailed:hover{transform:none}.map-detailed .map-image{width:100%;height:auto}.leaderboard{width:max-content;margin:2rem;padding:1.5rem 2rem;background-color:#20203f;border-radius:1rem;box-shadow:.25rem 0 2rem #00001f}.rank{display:flex;margin:1.5rem 0}.rank .country-image{height:1.5rem;margin:auto .5rem auto 0}.rank .rank-position{color:#ee588f;margin:auto .5rem auto 0;font-weight:bold}.rank .rank-player{margin:auto 2rem auto 0}.rank .rank-time{color:#9090af;font-family:"Manrope Light";margin:auto 0 auto auto}.leaderboard-history{width:min(70ch,70vw);margin:2rem;padding:1.5rem 2rem;background-color:#20203f;border-radius:1rem;box-shadow:.25rem 0 2rem #00001f}

View File

@ -1 +1 @@
*{margin:0;padding:0;border:0 none transparent;box-sizing:border-box;scroll-behavior:smooth;font-family:"Manrope Regular",sans-serif;font-size:1rem;line-height:1.5}html,body{color:#e0e0ff;background-color:#10102f;height:100%}nav{display:flex;align-items:center;background-color:#20203f;border-radius:0 0 2rem 2rem;box-shadow:.5rem 0 4rem #00001f;margin:0 0 2rem 0;padding:1rem 2rem}nav .logo{width:3rem;height:3rem;margin-right:2rem;border-radius:100%;background-color:#ee588f}nav a{color:#fba7c6;border-bottom:.1rem solid transparent;margin:.25rem 1rem .5rem 1rem;padding:.15rem .5rem .25rem .5rem;font-size:1.25rem;text-decoration:none transparent;transition:border .3s}nav a:hover{border-bottom:.1rem solid #fba7c6}nav a.current{color:#ee588f}nav a.current:hover{border-bottom:.1rem solid #ee588f}main.flex-container{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-around;margin:0 10vw}header,h1,h2,h3,h4,h5,h6{color:#fba7c6}header{font-size:4rem}h1{font-size:1.5rem;font-weight:normal}h2{font-size:1.35rem;font-weight:normal}h3{font-size:1.2rem;font-weight:normal}h4{font-size:1.05rem;font-weight:normal}h5{font-size:.9rem;font-weight:normal}a{color:#a3cefa}form{display:flex;flex-direction:column;justify-content:center;align-items:center}input{color:#e0e0ff;background-color:#20203f;margin:1em 0;padding:.75em 1.25em;width:min(80ch,80vw);outline:0 none transparent;border:.2rem solid transparent;border-radius:.5rem;box-shadow:.25rem 0 2rem #00001f;transition:border .3s,background-color .5s,border-radius .5s}input:hover{background-color:#30304f;border-radius:1rem}input:active,input:focus{border:.2rem solid #ee588f}footer{display:flex;flex-direction:column;align-items:center;margin:5vh 2rem}footer a{color:#74b6fb;font-size:.8rem}
*{margin:0;padding:0;border:0 none transparent;box-sizing:border-box;scroll-behavior:smooth;font-family:"Manrope Regular",sans-serif;font-size:1rem;line-height:1.5}html,body{color:#e0e0ff;background-color:#10102f;height:100%}nav{display:flex;align-items:center;background-color:#20203f;border-radius:0 0 2rem 2rem;box-shadow:.5rem 0 4rem #00001f;margin:0 0 2rem 0;padding:1rem 2rem}nav .logo{width:3rem;height:3rem;margin-right:2rem;border-radius:100%;background-color:#ee588f}nav a{color:#fba7c6;border-bottom:.1rem solid transparent;margin:.25rem 1rem .5rem 1rem;padding:.15rem .5rem .25rem .5rem;font-size:1.25rem;text-decoration:none transparent;transition:border .3s}nav a:hover{border-bottom:.1rem solid #fba7c6}nav a.current{color:#ee588f}nav a.current:hover{border-bottom:.1rem solid #ee588f}main.flex-container{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-around;margin:0 10vw}header,h1,h2,h3,h4,h5,h6{color:#fba7c6}header{font-size:4rem}h1{font-size:1.5rem;font-weight:normal}h2{font-size:1.35rem;font-weight:normal}h3{font-size:1.2rem;font-weight:normal}h4{font-size:1.05rem;font-weight:normal}h5{font-size:.9rem;font-weight:normal}a{color:#a3cefa}form{display:flex;flex-direction:column;justify-content:center;align-items:center}input{color:#e0e0ff;background-color:#20203f;margin:1em 0;padding:.75em 1.25em;width:min(80ch,80vw);outline:0 none transparent;border:.2rem solid transparent;border-radius:.5rem;box-shadow:.25rem 0 2rem #00001f;transition:border .3s,background-color .5s,border-radius .5s}input:hover{background-color:#30304f;border-radius:1rem}input:active,input:focus{border:.2rem solid #ee588f}tr{width:max-content}tr td{padding:.25rem 0;vertical-align:middle;width:max-content}tr td:first-child{padding:.25rem 1.5rem .25rem 0}footer{display:flex;flex-direction:column;align-items:center;margin:5vh 2rem}footer a{color:#74b6fb;font-size:.8rem}

View File

@ -3,6 +3,6 @@
Made with <3 by team qwik
</p>
<p>
<a href="https://git.qwik.space/BurnyLlama/ddstats-server">Source Code</a> • <a href="/api/reference">API Reference</a> • <a href="/instance-info">Instance Info</a>
<a href="https://git.qwik.space/BurnyLlama/ddstats-server">Source Code</a> • <a href="/api/reference">API Reference</a> • <a href="/status">Server Status</a>
</p>
</footer>

33
views/pages/stats.njk Normal file
View File

@ -0,0 +1,33 @@
{% extends "../templates/basic.njk" %}
{% import "../components/_utils.njk" as utils %}
{% set stats = data.stats %}
{% block body %}
<main class="flex-container">
<div class="stats">
<h1>
Current server status
</h1>
<table>
<tr>
<td>Uptime:</td>
<td>{{ utils.fancyTime(stats.uptimeMillis / 1000) }}</td>
</tr>
<tr>
<td>Uptime seconds:</td>
<td>{{ stats.uptimeSeconds }}</td>
</tr>
<tr>
<td>Database size:</td>
<td>{{ stats.db.size.kbytes }} KB || {{ stats.db.size.mbytes | round(2) }} MB || {{ stats.db.size.gbytes | round(2) }} GB</td>
</tr>
<tr>
<td>Database status:</td>
<td>{{ "Currently updating the database..." if stats.db.currentlyUpdating else "Last update was at " + stats.db.lastUpdate }}</td>
</tr>
</table>
</div>
</main>
{% endblock %}