mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Logs in UI (#4562)
* Log all services to RAM * Gracefully handle shutdown * Add logs route * Remove tail * Return logs for services * Display log chooser with copy button * show logs for specific services * Clean up settings logs * Add copy functionality to logs * Add copy functionality to logs * Fix merge * Set archive count to 0 Co-authored-by: Felipe Santos <felipecassiors@gmail.com>
This commit is contained in:
parent
4f79ca1bf0
commit
964bcc0733
@ -180,8 +180,8 @@ ENV S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
|
|||||||
# But this is not working currently because of:
|
# But this is not working currently because of:
|
||||||
# https://github.com/just-containers/s6-overlay/issues/503
|
# https://github.com/just-containers/s6-overlay/issues/503
|
||||||
ENV S6_SERVICES_GRACETIME=30000
|
ENV S6_SERVICES_GRACETIME=30000
|
||||||
# Configure logging to prepend timestamps, log to stdout, keep 1 archive and rotate on 10MB
|
# Configure logging to prepend timestamps, log to stdout, keep 0 archives and rotate on 10MB
|
||||||
ENV S6_LOGGING_SCRIPT="T 1 n1 s10000000 T"
|
ENV S6_LOGGING_SCRIPT="T 1 n0 s10000000 T"
|
||||||
# TODO: remove after a new version of s6-overlay is released. See:
|
# TODO: remove after a new version of s6-overlay is released. See:
|
||||||
# https://github.com/just-containers/s6-overlay/issues/460#issuecomment-1327127006
|
# https://github.com/just-containers/s6-overlay/issues/460#issuecomment-1327127006
|
||||||
ENV S6_SERVICES_READYTIME=50
|
ENV S6_SERVICES_READYTIME=50
|
||||||
|
@ -1142,3 +1142,24 @@ def vainfo():
|
|||||||
else "",
|
else "",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/logs/<service>", methods=["GET"])
|
||||||
|
def logs(service: str):
|
||||||
|
log_locations = {
|
||||||
|
"frigate": "/dev/shm/logs/frigate/current",
|
||||||
|
"go2rtc": "/dev/shm/logs/go2rtc/current",
|
||||||
|
"nginx": "/dev/shm/logs/nginx/current",
|
||||||
|
}
|
||||||
|
service_location = log_locations.get(service)
|
||||||
|
|
||||||
|
if not service:
|
||||||
|
return f"{service} is not a valid service", 404
|
||||||
|
|
||||||
|
try:
|
||||||
|
file = open(service_location, "r")
|
||||||
|
contents = file.read()
|
||||||
|
file.close()
|
||||||
|
return contents, 200
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
return f"Could not find log file: {e}", 500
|
||||||
|
@ -48,6 +48,7 @@ export default function Sidebar() {
|
|||||||
<Destination href="/storage" text="Storage" />
|
<Destination href="/storage" text="Storage" />
|
||||||
<Destination href="/system" text="System" />
|
<Destination href="/system" text="System" />
|
||||||
<Destination href="/config" text="Config" />
|
<Destination href="/config" text="Config" />
|
||||||
|
<Destination href="/logs" text="Logs" />
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className="flex flex-grow" />
|
<div className="flex flex-grow" />
|
||||||
{ENV !== 'production' ? (
|
{ENV !== 'production' ? (
|
||||||
|
@ -38,6 +38,7 @@ export default function App() {
|
|||||||
<AsyncRoute path="/storage" getComponent={Routes.getStorage} />
|
<AsyncRoute path="/storage" getComponent={Routes.getStorage} />
|
||||||
<AsyncRoute path="/system" getComponent={Routes.getSystem} />
|
<AsyncRoute path="/system" getComponent={Routes.getSystem} />
|
||||||
<AsyncRoute path="/config" getComponent={Routes.getConfig} />
|
<AsyncRoute path="/config" getComponent={Routes.getConfig} />
|
||||||
|
<AsyncRoute path="/logs" getComponent={Routes.getLogs} />
|
||||||
<AsyncRoute path="/styleguide" getComponent={Routes.getStyleGuide} />
|
<AsyncRoute path="/styleguide" getComponent={Routes.getStyleGuide} />
|
||||||
<Cameras default path="/" />
|
<Cameras default path="/" />
|
||||||
</Router>
|
</Router>
|
||||||
|
51
web/src/routes/Logs.jsx
Normal file
51
web/src/routes/Logs.jsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { h } from 'preact';
|
||||||
|
import Heading from '../components/Heading';
|
||||||
|
import { useCallback, useEffect, useState } from 'preact/hooks';
|
||||||
|
import ButtonsTabbed from '../components/ButtonsTabbed';
|
||||||
|
import useSWR from 'swr';
|
||||||
|
import Button from '../components/Button';
|
||||||
|
|
||||||
|
export default function Logs() {
|
||||||
|
const [logService, setLogService] = useState('frigate');
|
||||||
|
const [logs, setLogs] = useState('frigate');
|
||||||
|
|
||||||
|
const { data: frigateLogs } = useSWR('logs/frigate');
|
||||||
|
const { data: go2rtcLogs } = useSWR('logs/go2rtc');
|
||||||
|
const { data: nginxLogs } = useSWR('logs/nginx');
|
||||||
|
|
||||||
|
const handleCopyLogs = useCallback(() => {
|
||||||
|
async function copy() {
|
||||||
|
await window.navigator.clipboard.writeText(logs);
|
||||||
|
}
|
||||||
|
copy();
|
||||||
|
}, [logs]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
switch (logService) {
|
||||||
|
case 'frigate':
|
||||||
|
setLogs(frigateLogs);
|
||||||
|
break;
|
||||||
|
case 'go2rtc':
|
||||||
|
setLogs(go2rtcLogs);
|
||||||
|
break;
|
||||||
|
case 'nginx':
|
||||||
|
setLogs(nginxLogs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}, [frigateLogs, go2rtcLogs, nginxLogs, logService, setLogs]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4 p-2 px-4">
|
||||||
|
<Heading>Logs</Heading>
|
||||||
|
|
||||||
|
<ButtonsTabbed viewModes={['frigate', 'go2rtc', 'nginx']} setViewMode={setLogService} />
|
||||||
|
|
||||||
|
<div className='overflow-auto font-mono text-sm text-gray-900 dark:text-gray-100 rounded bg-gray-100 dark:bg-gray-800 p-2 whitespace-pre-wrap'>
|
||||||
|
{logs}
|
||||||
|
</div>
|
||||||
|
<Button className="" onClick={handleCopyLogs}>
|
||||||
|
Copy to Clipboard
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -43,6 +43,11 @@ export async function getConfig(_url, _cb, _props) {
|
|||||||
return module.default;
|
return module.default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getLogs(_url, _cb, _props) {
|
||||||
|
const module = await import('./Logs.jsx');
|
||||||
|
return module.default;
|
||||||
|
}
|
||||||
|
|
||||||
export async function getStyleGuide(_url, _cb, _props) {
|
export async function getStyleGuide(_url, _cb, _props) {
|
||||||
const module = await import('./StyleGuide.jsx');
|
const module = await import('./StyleGuide.jsx');
|
||||||
return module.default;
|
return module.default;
|
||||||
|
Loading…
Reference in New Issue
Block a user