Skip to content

Commit

Permalink
feat(settings): logs viewer (#997)
Browse files Browse the repository at this point in the history
  • Loading branch information
danshilm committed Mar 17, 2021
1 parent d76bf32 commit 54429bb
Show file tree
Hide file tree
Showing 8 changed files with 471 additions and 16 deletions.
48 changes: 48 additions & 0 deletions overseerr-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,54 @@ paths:
responses:
'204':
description: 'Flushed cache'
/settings/logs:
get:
summary: Returns logs
description: Returns list of all log items and details
tags:
- settings
parameters:
- in: query
name: take
schema:
type: number
nullable: true
example: 25
- in: query
name: skip
schema:
type: number
nullable: true
example: 0
- in: query
name: filter
schema:
type: string
nullable: true
enum: [debug, info, warn, error]
default: debug
responses:
'200':
description: Server log returned
content:
application/json:
schema:
type: array
items:
type: object
properties:
label:
type: string
example: server
level:
type: string
example: info
message:
type: string
example: Server ready on port 5055
timestamp:
type: string
example: 2020-12-15T16:20:00.069Z
/settings/notifications:
get:
summary: Return notification settings
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"email-templates": "^8.0.3",
"express": "^4.17.1",
"express-openapi-validator": "^4.12.5",
"express-rate-limit": "^5.2.6",
"express-session": "^1.17.1",
"formik": "^2.2.6",
"gravatar-url": "^3.1.0",
Expand Down Expand Up @@ -89,6 +90,7 @@
"@types/csurf": "^1.11.0",
"@types/email-templates": "^8.0.2",
"@types/express": "^4.17.11",
"@types/express-rate-limit": "^5.1.1",
"@types/express-session": "^1.17.3",
"@types/lodash": "^4.14.168",
"@types/node": "^14.14.35",
Expand Down
13 changes: 13 additions & 0 deletions server/interfaces/api/settingsInterfaces.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
import type { PaginatedResponse } from './common';

export type LogMessage = {
timestamp: string;
level: string;
label: string;
message: string;
};

export interface LogsResultsResponse extends PaginatedResponse {
results: LogMessage[];
}

export interface SettingsAboutResponse {
version: string;
totalRequests: number;
Expand Down
102 changes: 93 additions & 9 deletions server/routes/settings/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
import { Router } from 'express';
import { getSettings, Library, MainSettings } from '../../lib/settings';
import rateLimit from 'express-rate-limit';
import fs from 'fs';
import { merge, omit } from 'lodash';
import path from 'path';
import { getRepository } from 'typeorm';
import { User } from '../../entity/User';
import PlexAPI from '../../api/plexapi';
import PlexTvAPI from '../../api/plextv';
import Media from '../../entity/Media';
import { MediaRequest } from '../../entity/MediaRequest';
import { User } from '../../entity/User';
import {
LogMessage,
LogsResultsResponse,
SettingsAboutResponse,
} from '../../interfaces/api/settingsInterfaces';
import { scheduledJobs } from '../../job/schedule';
import cacheManager, { AvailableCacheIds } from '../../lib/cache';
import { Permission } from '../../lib/permissions';
import { plexFullScanner } from '../../lib/scanners/plex';
import { getSettings, Library, MainSettings } from '../../lib/settings';
import logger from '../../logger';
import { isAuthenticated } from '../../middleware/auth';
import { merge, omit } from 'lodash';
import Media from '../../entity/Media';
import { MediaRequest } from '../../entity/MediaRequest';
import { getAppVersion } from '../../utils/appVersion';
import { SettingsAboutResponse } from '../../interfaces/api/settingsInterfaces';
import notificationRoutes from './notifications';
import sonarrRoutes from './sonarr';
import radarrRoutes from './radarr';
import cacheManager, { AvailableCacheIds } from '../../lib/cache';
import { plexFullScanner } from '../../lib/scanners/plex';
import sonarrRoutes from './sonarr';

const settingsRoutes = Router();

Expand Down Expand Up @@ -223,6 +231,82 @@ settingsRoutes.post('/plex/sync', (req, res) => {
return res.status(200).json(plexFullScanner.status());
});

settingsRoutes.get(
'/logs',
rateLimit({ windowMs: 60 * 1000, max: 50 }),
(req, res, next) => {
const pageSize = req.query.take ? Number(req.query.take) : 25;
const skip = req.query.skip ? Number(req.query.skip) : 0;

let filter: string[] = [];
switch (req.query.filter) {
case 'debug':
filter.push('debug');
// falls through
case 'info':
filter.push('info');
// falls through
case 'warn':
filter.push('warn');
// falls through
case 'error':
filter.push('error');
break;
default:
filter = ['debug', 'info', 'warn', 'error'];
}

const logFile = process.env.CONFIG_DIRECTORY
? `${process.env.CONFIG_DIRECTORY}/logs/overseerr.log`
: path.join(__dirname, '../../../config/logs/overseerr.log');
const logs: LogMessage[] = [];

try {
fs.readFileSync(logFile)
.toString()
.split('\n')
.forEach((line) => {
if (!line.length) return;

const timestamp = line.match(new RegExp(/^.{24}/)) || [];
const level = line.match(new RegExp(/\s\[\w+\]/)) || [];
const label = line.match(new RegExp(/[^\s]\[\w+\s*\w*\]/)) || [];
const message = line.match(new RegExp(/:\s.*/)) || [];

if (level.length && filter.includes(level[0].slice(2, -1))) {
logs.push({
timestamp: timestamp[0],
level: level.length ? level[0].slice(2, -1) : '',
label: label.length ? label[0].slice(2, -1) : '',
message: message.length ? message[0].slice(2) : '',
});
}
});

const displayedLogs = logs.reverse().slice(skip, skip + pageSize);

return res.status(200).json({
pageInfo: {
pages: Math.ceil(logs.length / pageSize),
pageSize,
results: logs.length,
page: Math.ceil(skip / pageSize) + 1,
},
results: displayedLogs,
} as LogsResultsResponse);
} catch (error) {
logger.error('Something went wrong while fetching the logs', {
label: 'Logs',
errorMessage: error.message,
});
return next({
status: 500,
message: 'Something went wrong while fetching the logs',
});
}
}
);

settingsRoutes.get('/jobs', (_req, res) => {
return res.status(200).json(
scheduledJobs.map((job) => ({
Expand Down
2 changes: 1 addition & 1 deletion src/components/RequestList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const RequestList: React.FC = () => {
}
}, []);

// Set fitler values to local storage any time they are changed
// Set filter values to local storage any time they are changed
useEffect(() => {
window.localStorage.setItem(
'rl-filter-settings',
Expand Down

0 comments on commit 54429bb

Please sign in to comment.