Skip to content

Commit

Permalink
New view route for basic blob dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
mario4tier committed Sep 1, 2024
1 parent 329e018 commit a1ccecc
Show file tree
Hide file tree
Showing 23 changed files with 928 additions and 104 deletions.
File renamed without changes.
107 changes: 107 additions & 0 deletions backend/cache/dist/common/cdn-metrics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import dotenv from 'dotenv';
import { promises as fs } from 'fs';
import path from 'path';
const HOME_DIR = process.env.HOME || process.env.USERPROFILE || '';
dotenv.config({ path: path.join(HOME_DIR, 'suiftly-ops', 'dotenv', '.env.metrics') });
// Type guard on string to supported Route conversion.
export const ROUTES = ['blob', 'icon48x48', 'icon96x96', 'icon256x256', 'meta', 'metrics', 'view'];
export const isValidRoute = (route) => {
return ROUTES.includes(route);
};
export async function loadMetricsFile(metricsPath, options = {}) {
const { verbose = false } = options;
try {
const metricsData = await fs.readFile(metricsPath, 'utf-8');
const metrics = JSON.parse(metricsData);
if (verbose) {
console.log('Metrics loaded:', metrics);
}
return metrics;
}
catch (err) {
if (verbose) {
console.error('Error reading metrics file:', err);
}
return undefined;
}
}
export function isValidMetricsType(metrics, options = {}) {
const { verbose = false } = options;
if (verbose) {
console.log('Validating metrics:', metrics);
}
if (!metrics || typeof metrics !== 'object') {
if (verbose) {
console.error('Metrics is not an object');
}
return false;
}
// Cast to Metrics (this does not validate anything).
// Must validate the object properties one by one.
const m = metrics;
// Check top properties
if (typeof m.blobId !== 'string') {
if (verbose) {
console.error('blobId is not a string');
}
return false;
}
if (typeof m.daily !== 'object' || m.daily === null) {
if (verbose) {
console.error('daily is not an object');
}
return false;
}
if (typeof m.sizes !== 'object' || m.sizes === null) {
if (verbose) {
console.error('sizes is not an object');
}
return false;
}
// Check each date in daily
for (const date in m.daily) {
if (typeof date !== 'string') {
if (verbose) {
console.error('date is not a string');
}
return false;
}
const routes = m.daily[date];
if (typeof routes !== 'object' || routes === null) {
if (verbose) {
console.error('routes is not an object');
}
return false;
}
// Check each route in daily[date]
for (const route in routes) {
const routeDay = routes[route];
if (typeof routeDay !== 'object' || routeDay === null) {
if (verbose) {
console.error('routeDay is not an object');
}
return false;
}
if (typeof routeDay.hits !== 'number' ||
typeof routeDay.hitsEdge !== 'number' ||
typeof routeDay.visitors !== 'number') {
if (verbose) {
console.error(`routeDay properties are not numbers for route [${route}]`);
}
return false;
}
}
}
// Check each route in sizes
for (const route in m.sizes) {
const size = m.sizes[route];
if (size !== undefined && typeof size !== 'number') {
if (verbose) {
console.error(`optional size property is not a number for route [${route}]`);
}
return false;
}
}
return true;
}
export const CDN_METRICS_DIR = process.env.CDN_METRICS_DIR || `${HOME_DIR}/cdn-metrics`;
File renamed without changes.
36 changes: 36 additions & 0 deletions backend/cache/dist/common/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Util function to sort object keys (in-place).
// Handles nested objects and arrays recursively.
// Useful to sort prior to JSON.stringify
export function sortObjectKeys(obj) {
if (typeof obj !== 'object' || obj === null) {
return;
}
if (Array.isArray(obj)) {
obj.forEach(sortObjectKeys);
return;
}
const keys = Object.keys(obj);
const sortedKeys = [...keys].sort();
// Check if the keys are already sorted
let isSorted = true;
for (let i = 0; i < keys.length; i++) {
if (keys[i] !== sortedKeys[i]) {
isSorted = false;
break;
}
}
if (!isSorted) {
sortedKeys.forEach(key => {
const value = obj[key];
delete obj[key];
obj[key] = value;
sortObjectKeys(value);
});
}
else {
// If already sorted, still need to sort nested objects
keys.forEach(key => {
sortObjectKeys(obj[key]);
});
}
}
4 changes: 2 additions & 2 deletions backend/cache/dist/controllers/blob.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { spawn } from 'child_process';
import * as fs from 'fs';
import path from 'path';
import { getIdPrefixes } from '../utils/strings.js';
import { isValidBlobId } from '../utils/validation.js';
import { isValidBlobId } from '../common/blob.js';
import { getIdPrefixes } from '../common/strings.js';
// Test Blob Info
//
// MIME type: image/png
Expand Down
6 changes: 3 additions & 3 deletions backend/cache/dist/controllers/metrics.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as fs from 'fs';
import path from 'path';
import { getIdPrefixes } from '../utils/strings.js';
import { isValidBlobId } from '../utils/validation.js';
import { isValidBlobId } from '../common/blob.js';
import { getIdPrefixes } from '../common/strings.js';
// Test Blob Info
//
// MIME type: image/png
Expand Down Expand Up @@ -63,8 +63,8 @@ export const getMetrics = async (req, res) => {
// File does not exist, return "no_metrics" JSON response
res.json({
blobId: id,
status: 'no_metrics',
message: 'No metrics accumulated yet for this blob. Metrics updated every ~24 hours.',
status: 'no_metrics',
});
}
};
Loading

0 comments on commit a1ccecc

Please sign in to comment.