feat(index): add back hot stats (#14664)

This commit is contained in:
Tony
2024-03-05 13:55:39 +08:00
committed by GitHub
parent 0f51d2f93a
commit d17ebe81d0
7 changed files with 128 additions and 26 deletions
+4 -4
View File
@@ -52,16 +52,16 @@ describe('route throws an error', () => {
expect(value).toBe('7');
break;
case 'Hot Routes:':
expect(value).toBe('4 /test/:id<br>');
expect(value).toBe('4 /test/:id<br>');
break;
case 'Hot Paths:':
expect(value).toBe('2 /test/error<br>2 /test/slow<br>1 /test/httperror<br>1 /thisDoesNotExist<br>1 /<br>');
expect(value).toBe('2 /test/error<br>2 /test/slow<br>1 /test/httperror<br>1 /thisDoesNotExist<br>1 /<br>');
break;
case 'Hot Error Routes:':
expect(value).toBe('3 /test/:id<br>');
expect(value).toBe('4 /test/:id<br>');
break;
case 'Hot Error Paths:':
expect(value).toBe('2 /test/error<br>1 /test/httperror<br>1 /test/slow<br>1 /thisDoesNotExist<br>');
expect(value).toBe('2 /test/error<br>1 /test/httperror<br>1 /test/slow<br>1 /thisDoesNotExist<br>');
break;
default:
}
+16 -5
View File
@@ -15,6 +15,9 @@ import { getCurrentPath } from '@/utils/helpers';
const __dirname = getCurrentPath(import.meta.url);
export const errorHandler: ErrorHandler = (error, ctx) => {
const requestPath = ctx.req.path;
const matchedRoute = ctx.req.routePath;
const hasMatchedRoute = matchedRoute !== '/*';
let message = '';
if (error.name && (error.name === 'HTTPError' || error.name === 'RequestError')) {
message = `${error.message}: target website might be blocking our access, you can <a href="https://docs.rsshub.app/install/">host your own RSSHub instance</a> for a better usability.`;
@@ -27,16 +30,26 @@ export const errorHandler: ErrorHandler = (error, ctx) => {
debug.hitCache++;
}
debug.error++;
if (!debug.errorPaths[requestPath]) {
debug.errorPaths[requestPath] = 0;
}
debug.errorPaths[requestPath]++;
if (!debug.errorRoutes[matchedRoute] && hasMatchedRoute) {
debug.errorRoutes[matchedRoute] = 0;
}
hasMatchedRoute && debug.errorRoutes[matchedRoute]++;
setDebugInfo(debug);
if (config.sentry.dsn) {
Sentry.withScope((scope) => {
scope.setTag('name', ctx.req.path.split('/')[1]);
scope.setTag('name', requestPath.split('/')[1]);
Sentry.captureException(error);
});
}
logger.error(`Error in ${ctx.req.path}: ${message}`);
logger.error(`Error in ${requestPath}: ${message}`);
if (config.isPackage) {
return ctx.json({
@@ -59,13 +72,11 @@ export const errorHandler: ErrorHandler = (error, ctx) => {
ctx.status(404);
}
const requestPath = ctx.req.path;
return ctx.html(
art(path.resolve(__dirname, '../views/error.art'), {
requestPath,
message,
errorPath: ctx.req.path,
errorRoute: hasMatchedRoute ? matchedRoute : requestPath,
nodeVersion: process.version,
gitHash,
})
+11
View File
@@ -4,6 +4,11 @@ import { getDebugInfo, setDebugInfo } from '@/utils/debug-info';
const middleware: MiddlewareHandler = async (ctx, next) => {
{
const debug = getDebugInfo();
if (!debug.paths[ctx.req.path]) {
debug.paths[ctx.req.path] = 0;
}
debug.paths[ctx.req.path]++;
debug.request++;
setDebugInfo(debug);
}
@@ -12,6 +17,12 @@ const middleware: MiddlewareHandler = async (ctx, next) => {
{
const debug = getDebugInfo();
const hasMatchedRoute = ctx.req.routePath !== '/*';
if (!debug.routes[ctx.req.routePath] && hasMatchedRoute) {
debug.routes[ctx.req.routePath] = 0;
}
hasMatchedRoute && debug.routes[ctx.req.routePath]++;
if (ctx.res.headers.get('RSSHub-Cache-Status')) {
debug.hitCache++;
}
+16 -1
View File
@@ -1,8 +1,23 @@
const debug = {
type DebugInfo = {
hitCache: number;
request: number;
etag: number;
error: number;
paths: Record<string, number>;
routes: Record<string, number>;
errorPaths: Record<string, number>;
errorRoutes: Record<string, number>;
};
const debug: DebugInfo = {
hitCache: 0,
request: 0,
etag: 0,
error: 0,
routes: {},
paths: {},
errorRoutes: {},
errorPaths: {},
};
export const getDebugInfo = () => debug;
+1 -1
View File
@@ -1,7 +1,7 @@
import gitRevSync from 'git-rev-sync';
let gitHash = process.env.HEROKU_SLUG_COMMIT?.slice(0, 8) || process.env.VERCEL_GIT_COMMIT_SHA?.slice(0, 8);
let gitDate;
let gitDate: Date | undefined;
if (!gitHash) {
try {
gitHash = gitRevSync.short(undefined, 8);
+4 -4
View File
@@ -41,13 +41,13 @@
<h1>Looks like something went wrong</h1>
<pre class="message">Route requested: {{@ requestPath }}</pre>
<pre class="message">Path requested: {{@ requestPath }}</pre>
<pre class="message">Error message: {{@ message }}</pre>
<pre class="message">
Helpful Information to provide when opening issue:
Path: {{@ errorPath }}
Node version: {{@ nodeVersion}}
Git Hash: {{@ gitHash}}
Route: {{@ errorRoute }}
Node version: {{@ nodeVersion }}
Git Hash: {{@ gitHash }}
</pre>
<pre class="message">
If you believe this is an error caused by RSSHub, please <a href="https://github.com/DIYgod/RSSHub/issues/new?assignees=&labels=RSS+bug&template=bug_report_en.yml" target="_blank">report on github</a>
+76 -11
View File
@@ -11,6 +11,19 @@ const Layout: FC = (props) => (
<head>
<title>Welcome to RSSHub!</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
{`
details::-webkit-scrollbar {
width: 0.25rem;
}
details::-webkit-scrollbar-thumb {
border-radius: 0.125rem;
background-color: #e4e4e7;
}
details::-webkit-scrollbar-thumb:hover {
background-color: #a1a1aa;
}`}
</style>
</head>
<body className="antialiased text-zinc-700">{props.children}</body>
</html>
@@ -20,7 +33,7 @@ const Index: FC<{ debugQuery: string | undefined }> = ({ debugQuery }) => {
const debug = getDebugInfo();
const showDebug = !config.debugInfo || config.debugInfo === 'false' ? false : config.debugInfo === 'true' || config.debugInfo === debugQuery;
const { disallowRobot, nodeName } = config;
const { disallowRobot, nodeName, cache } = config;
const duration = Date.now() - startTime;
@@ -57,8 +70,8 @@ const Index: FC<{ debugQuery: string | undefined }> = ({ debugQuery }) => {
]
: []),
{
name: 'Cache Length',
value: config.cache.routeExpire + 's',
name: 'Cache Duration',
value: cache.routeExpire + 's',
},
{
name: 'Request Amount',
@@ -81,9 +94,57 @@ const Index: FC<{ debugQuery: string | undefined }> = ({ debugQuery }) => {
value: debug.request ? ((1 - debug.error / debug.request) * 100).toFixed(2) + '%' : 0,
},
{
name: 'Run Time',
name: 'Uptime',
value: (duration / 3_600_000).toFixed(2) + ' hour(s)',
},
{
name: 'Hot Routes',
value: Object.keys(debug.routes)
.sort((a, b) => debug.routes[b] - debug.routes[a])
.slice(0, 30)
.map((route) => (
<>
{debug.routes[route]} {route}
<br />
</>
)),
},
{
name: 'Hot Paths',
value: Object.keys(debug.paths)
.sort((a, b) => debug.paths[b] - debug.paths[a])
.slice(0, 30)
.map((path) => (
<>
{debug.paths[path]} {path}
<br />
</>
)),
},
{
name: 'Hot Error Routes',
value: Object.keys(debug.errorRoutes)
.sort((a, b) => debug.errorRoutes[b] - debug.errorRoutes[a])
.slice(0, 30)
.map((route) => (
<>
{debug.routes[route]} {route}
<br />
</>
)),
},
{
name: 'Hot Error Paths',
value: Object.keys(debug.errorPaths)
.sort((a, b) => debug.errorPaths[b] - debug.errorPaths[a])
.slice(0, 30)
.map((path) => (
<>
{debug.errorPaths[path]} {path}
<br />
</>
)),
},
],
};
@@ -105,22 +166,22 @@ const Index: FC<{ debugQuery: string | undefined }> = ({ debugQuery }) => {
<p className="text-xl font-medium text-zinc-600">Everything is RSSible</p>
<div className="font-bold space-x-4 text-sm">
<a target="_blank" href="https://docs.rsshub.app">
<button className="text-white bg-[#F5712C] py-2 px-4 rounded-full">View Docs</button>
<button className="text-white bg-[#F5712C] hover:bg-[#DD4A15] py-2 px-4 rounded-full">View Docs</button>
</a>
<a target="_blank" href="https://github.com/DIYgod/RSSHub">
<button className="bg-zinc-200 py-2 px-4 rounded-full">View on GitHub</button>
<button className="bg-zinc-200 hover:bg-zinc-300 py-2 px-4 rounded-full">View on GitHub</button>
</a>
<a target="_blank" href="https://docs.rsshub.app/support" className="text-[#F5712C]">
<button className="text-white bg-red-500 py-2 px-4 rounded-full"> Sponsor</button>
<button className="text-white bg-red-500 hover:bg-red-600 py-2 px-4 rounded-full"> Sponsor</button>
</a>
</div>
{info.showDebug ? (
<details className="text-xs w-96 !mt-8">
<details className="text-xs w-96 !mt-8 max-h-[400px] overflow-auto">
<summary className="text-sm cursor-pointer">Debug Info</summary>
{info.debug.map((item) => (
<div class="debug-item my-3 pl-8">
<span class="debug-key">{item.name}: </span>
<span class="debug-value">{item.value}</span>
<span class="debug-key w-32 text-right inline-block mr-2">{item.name}: </span>
<span class="debug-value inline-block break-all align-top">{item.value}</span>
</div>
))}
</details>
@@ -142,7 +203,11 @@ const Index: FC<{ debugQuery: string | undefined }> = ({ debugQuery }) => {
</a>
</p>
<p className="!mt-6">
Please consider <a target="_blank" href="https://docs.rsshub.app/support" className="text-[#F5712C]">sponsoring</a> to help keep this open source project alive.
Please consider{' '}
<a target="_blank" href="https://docs.rsshub.app/support" className="text-[#F5712C]">
sponsoring
</a>{' '}
to help keep this open source project alive.
</p>
<p>
Made with by{' '}