Move stats api to separate file
This commit is contained in:
parent
48e25dd352
commit
c3c92b47f1
2 changed files with 88 additions and 73 deletions
78
src/index.js
78
src/index.js
|
|
@ -6,6 +6,8 @@ const commandLineArgs = require("command-line-args");
|
||||||
const commandLineUsage = require("command-line-usage");
|
const commandLineUsage = require("command-line-usage");
|
||||||
const cors = require('cors');
|
const cors = require('cors');
|
||||||
|
|
||||||
|
const statsRoutes = require('./stats.js');
|
||||||
|
|
||||||
// create prisma db client
|
// create prisma db client
|
||||||
const { PrismaClient } = require("@prisma/client");
|
const { PrismaClient } = require("@prisma/client");
|
||||||
const prisma = new PrismaClient();
|
const prisma = new PrismaClient();
|
||||||
|
|
@ -87,6 +89,9 @@ app.get('/', async (req, res) => {
|
||||||
res.sendFile(path.join(__dirname, 'public/index.html'));
|
res.sendFile(path.join(__dirname, 'public/index.html'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// stats API in separate file
|
||||||
|
app.use('/api/v1/stats', statsRoutes);
|
||||||
|
|
||||||
app.get('/api', async (req, res) => {
|
app.get('/api', async (req, res) => {
|
||||||
|
|
||||||
const links = [
|
const links = [
|
||||||
|
|
@ -650,42 +655,6 @@ app.get('/api/v1/nodes/:nodeId/position-history', async (req, res) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/api/v1/stats/hardware-models', async (req, res) => {
|
|
||||||
try {
|
|
||||||
|
|
||||||
// get nodes from db
|
|
||||||
const results = await prisma.node.groupBy({
|
|
||||||
by: ['hardware_model'],
|
|
||||||
orderBy: {
|
|
||||||
_count: {
|
|
||||||
hardware_model: 'desc',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
_count: {
|
|
||||||
hardware_model: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const hardwareModelStats = results.map((result) => {
|
|
||||||
return {
|
|
||||||
count: result._count.hardware_model,
|
|
||||||
hardware_model: result.hardware_model,
|
|
||||||
hardware_model_name: HardwareModel.valuesById[result.hardware_model] ?? "UNKNOWN",
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
hardware_model_stats: hardwareModelStats,
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch(err) {
|
|
||||||
console.error(err);
|
|
||||||
res.status(500).json({
|
|
||||||
message: "Something went wrong, try again later.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/api/v1/text-messages', async (req, res) => {
|
app.get('/api/v1/text-messages', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
|
@ -812,43 +781,6 @@ app.get('/api/v1/waypoints', async (req, res) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/api/v1/messages-per-hour', async (req, res) => {
|
|
||||||
try {
|
|
||||||
const hours = 168;
|
|
||||||
const now = new Date();
|
|
||||||
const startTime = new Date(now.getTime() - hours * 60 * 60 * 1000);
|
|
||||||
|
|
||||||
const messages = await prisma.textMessage.findMany({
|
|
||||||
where: { created_at: { gte: startTime } },
|
|
||||||
select: { packet_id: true, created_at: true },
|
|
||||||
distinct: ['packet_id'], // Ensures only unique packet_id entries are counted
|
|
||||||
orderBy: { created_at: 'asc' }
|
|
||||||
});
|
|
||||||
|
|
||||||
// Pre-fill `uniqueCounts` with zeros for all hours
|
|
||||||
const uniqueCounts = Object.fromEntries(
|
|
||||||
Array.from({ length: hours }, (_, i) => {
|
|
||||||
const hourTime = new Date(now.getTime() - (hours - i) * 60 * 60 * 1000);
|
|
||||||
const hourString = hourTime.toISOString().slice(0, 13); // YYYY-MM-DD HH
|
|
||||||
return [hourString, 0];
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// Populate actual message counts
|
|
||||||
messages.forEach(({ created_at }) => {
|
|
||||||
const hourString = created_at.toISOString().slice(0, 13); // YYYY-MM-DD HH
|
|
||||||
uniqueCounts[hourString]++;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Convert to final result format
|
|
||||||
const result = Object.entries(uniqueCounts).map(([hour, count]) => ({ hour, count }));
|
|
||||||
|
|
||||||
res.json(result);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching messages:', error);
|
|
||||||
res.status(500).json({ error: 'Internal Server Error' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// start express server
|
// start express server
|
||||||
const listener = app.listen(port, () => {
|
const listener = app.listen(port, () => {
|
||||||
|
|
|
||||||
83
src/stats.js
Normal file
83
src/stats.js
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// create prisma db client
|
||||||
|
const { PrismaClient } = require("@prisma/client");
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
|
|
||||||
|
router.get('/hardware-models', async (req, res) => {
|
||||||
|
try {
|
||||||
|
|
||||||
|
// get nodes from db
|
||||||
|
const results = await prisma.node.groupBy({
|
||||||
|
by: ['hardware_model'],
|
||||||
|
orderBy: {
|
||||||
|
_count: {
|
||||||
|
hardware_model: 'desc',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
_count: {
|
||||||
|
hardware_model: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const hardwareModelStats = results.map((result) => {
|
||||||
|
return {
|
||||||
|
count: result._count.hardware_model,
|
||||||
|
hardware_model: result.hardware_model,
|
||||||
|
hardware_model_name: HardwareModel.valuesById[result.hardware_model] ?? "UNKNOWN",
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
hardware_model_stats: hardwareModelStats,
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch(err) {
|
||||||
|
console.error(err);
|
||||||
|
res.status(500).json({
|
||||||
|
message: "Something went wrong, try again later.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/messages-per-hour', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const hours = 168;
|
||||||
|
const now = new Date();
|
||||||
|
const startTime = new Date(now.getTime() - hours * 60 * 60 * 1000);
|
||||||
|
|
||||||
|
const messages = await prisma.textMessage.findMany({
|
||||||
|
where: { created_at: { gte: startTime } },
|
||||||
|
select: { packet_id: true, created_at: true },
|
||||||
|
distinct: ['packet_id'], // Ensures only unique packet_id entries are counted
|
||||||
|
orderBy: { created_at: 'asc' }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pre-fill `uniqueCounts` with zeros for all hours
|
||||||
|
const uniqueCounts = Object.fromEntries(
|
||||||
|
Array.from({ length: hours }, (_, i) => {
|
||||||
|
const hourTime = new Date(now.getTime() - (hours - i) * 60 * 60 * 1000);
|
||||||
|
const hourString = hourTime.toISOString().slice(0, 13); // YYYY-MM-DD HH
|
||||||
|
return [hourString, 0];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Populate actual message counts
|
||||||
|
messages.forEach(({ created_at }) => {
|
||||||
|
const hourString = created_at.toISOString().slice(0, 13); // YYYY-MM-DD HH
|
||||||
|
uniqueCounts[hourString]++;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Convert to final result format
|
||||||
|
const result = Object.entries(uniqueCounts).map(([hour, count]) => ({ hour, count }));
|
||||||
|
|
||||||
|
res.json(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching messages:', error);
|
||||||
|
res.status(500).json({ error: 'Internal Server Error' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue