Skip to content

Commit

Permalink
Added logging output to the General Debug tab
Browse files Browse the repository at this point in the history
  • Loading branch information
qstokkink committed Jan 21, 2025
1 parent e153da9 commit f6d3218
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 3 deletions.
33 changes: 33 additions & 0 deletions src/tribler/core/restapi/logging_endpoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import logging
from logging.handlers import MemoryHandler

from aiohttp import web

from tribler.core.restapi.rest_endpoint import RESTEndpoint, RESTResponse


class LoggingEndpoint(RESTEndpoint):
"""
This endpoint allows retrieval of the logs.
"""

path = '/api/logging'

def __init__(self) -> None:
"""
Create a new logging endpoint.
"""
super().__init__()

self.base_handler = logging.getLogger().handlers[0]

self.memory_logger = MemoryHandler(100000)
logging.getLogger().addHandler(self.memory_logger)

self.app.add_routes([web.get("", self.get_logs)])

def get_logs(self, request: web.Request) -> RESTResponse:
"""
Return the most recent logs.
"""
return RESTResponse("\n".join(self.base_handler.format(r) for r in self.memory_logger.buffer))
2 changes: 2 additions & 0 deletions src/tribler/core/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from tribler.core.restapi.events_endpoint import EventsEndpoint
from tribler.core.restapi.file_endpoint import FileEndpoint
from tribler.core.restapi.ipv8_endpoint import IPv8RootEndpoint
from tribler.core.restapi.logging_endpoint import LoggingEndpoint
from tribler.core.restapi.rest_manager import RESTManager
from tribler.core.restapi.settings_endpoint import SettingsEndpoint
from tribler.core.restapi.shutdown_endpoint import ShutdownEndpoint
Expand Down Expand Up @@ -166,6 +167,7 @@ def register_rest_endpoints(self) -> None:
"""
Register all core REST endpoints without initializing them.
"""
self.rest_manager.add_endpoint(LoggingEndpoint()) # Do this first to register logging for the other endpoints.
self.rest_manager.add_endpoint(WebUIEndpoint())
self.rest_manager.add_endpoint(FileEndpoint())
self.rest_manager.add_endpoint(CreateTorrentEndpoint(self.download_manager))
Expand Down
30 changes: 27 additions & 3 deletions src/tribler/ui/src/pages/Debug/General/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { KeyValue } from "@/models/keyvalue.model";
import { triblerService } from "@/services/tribler.service";
import { isErrorDict } from "@/services/reporting";
import { ColumnDef } from "@tanstack/react-table";
import { useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { useInterval } from '@/hooks/useInterval';


Expand All @@ -20,7 +20,20 @@ const generalColumns: ColumnDef<KeyValue>[] = [
]

export default function General() {
const [stats, setStats] = useState<KeyValue[]>([])
const [stats, setStats] = useState<KeyValue[]>([]);
const [logs, setLogs] = useState<string>("");

// The following three definitions are for the fancy scrolling-when-at-the-bottom effect of the logs
const [shouldScrollDown, setShouldScrollDown] = useState<boolean>(true);
const [logContainer, setLogContainer] = useState<HTMLDOMElement | null>(null);
const logContainerRef = useCallback((node: HTMLDOMElement | null) => {
if (shouldScrollDown && (node !== null)){
if (logContainer !== null)
setShouldScrollDown(false);
setLogContainer(node);
node.scrollTop = node.scrollHeight;
}
}, [logs]);

useInterval(async () => {
const newStats = new Array<KeyValue>();
Expand Down Expand Up @@ -54,7 +67,18 @@ export default function General() {
}

setStats(newStats);

const logOutput = await triblerService.getLogs();
if (logOutput !== undefined && !isErrorDict(logOutput)){
if (logContainer !== null)
setShouldScrollDown(logContainer.scrollTop >= (logContainer.scrollHeight - logContainer.clientHeight));
setLogs(logOutput);
}
}, 5000, true);

return <SimpleTable data={stats} columns={generalColumns} />
return (<div className="w-full h-full flex flex-col">
<SimpleTable className="flex-grow" data={stats} columns={generalColumns} />
<div className="flex-none bg-neutral-100 dark:bg-neutral-900 text-muted-foreground border-y pl-3 py-2 text-sm font-medium">Logs</div>
<div className="whitespace-pre text-xs pl-1 h-96 flex-grow overflow-scroll overflow-hidden scroll-smooth" ref={logContainerRef}>{logs}</div>
</div>);
}
8 changes: 8 additions & 0 deletions src/tribler/ui/src/services/tribler.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,14 @@ export class TriblerService {
}
}

async getLogs(): Promise<undefined | ErrorDict | string> {
try {
return (await this.http.get('/logging')).data;
} catch (error) {
return formatAxiosError(error as Error | AxiosError);
}
}

// Torrents / search

async getMetainfo(uri: string): Promise<undefined | ErrorDict | {metainfo: string, download_exists: boolean, valid_certificate: boolean}> {
Expand Down

0 comments on commit f6d3218

Please sign in to comment.