diff --git a/packages/web_ui/src/components/InstanceViewPage.jsx b/packages/web_ui/src/components/InstanceViewPage.jsx
index e9bf72c9..c5a27cb5 100644
--- a/packages/web_ui/src/components/InstanceViewPage.jsx
+++ b/packages/web_ui/src/components/InstanceViewPage.jsx
@@ -9,7 +9,7 @@ import { useAccount } from "../model/account";
import ControlContext from "./ControlContext";
import PageLayout from "./PageLayout";
import InstanceConfigTree from "./InstanceConfigTree";
-import InstanceConsole from "./InstanceConsole";
+import LogConsole from "./LogConsole";
import InstanceRcon from "./InstanceRcon";
import AssignInstanceModal from "./AssignInstanceModal";
import StartStopInstanceButton from "./StartStopInstanceButton";
@@ -127,7 +127,7 @@ export default function InstanceViewPage(props) {
account.hasAnyPermission("core.log.follow", "core.instance.send_rcon")
&&
Console
}
- {account.hasPermission("core.log.follow") && }
+ {account.hasPermission("core.log.follow") && }
{
account.hasPermission("core.instance.send_rcon")
&&
diff --git a/packages/web_ui/src/components/InstanceConsole.jsx b/packages/web_ui/src/components/LogConsole.jsx
similarity index 88%
rename from packages/web_ui/src/components/InstanceConsole.jsx
rename to packages/web_ui/src/components/LogConsole.jsx
index aa2d50ca..aa76c7a7 100644
--- a/packages/web_ui/src/components/InstanceConsole.jsx
+++ b/packages/web_ui/src/components/LogConsole.jsx
@@ -49,7 +49,7 @@ function formatLog(info, key) {
return [{level}] {info.message}
;
}
-export default function InstanceConsole(props) {
+export default function LogConsole(props) {
let account = useAccount();
let control = useContext(ControlContext);
let anchor = useRef();
@@ -57,16 +57,20 @@ export default function InstanceConsole(props) {
let [lines, setLines] = useState([]);
useEffect(() => {
+ let logFilter = {
+ all: props.all || false,
+ master: props.master || false,
+ slave_ids: props.slaves || [],
+ instance_ids: props.instances || [],
+ };
+
// Scroll view to the anchor so it sticks to the bottom
let parent = anchor.current.parentElement;
parent.scrollTop = parent.scrollHeight - parent.clientHeight;
if (account.hasPermission("core.log.query")) {
libLink.messages.queryLog.send(control, {
- all: false,
- master: false,
- slave_ids: [],
- instance_ids: [props.id],
+ ...logFilter,
max_level: null,
limit: 400,
order: "desc",
@@ -85,11 +89,11 @@ export default function InstanceConsole(props) {
));
}
- control.onInstanceLog(props.id, logHandler);
+ control.onLog(logFilter, logHandler);
return () => {
- control.offInstanceLog(props.id, logHandler);
+ control.offLog(logFilter, logHandler);
};
- }, [props.id]);
+ }, [props.all, props.master, props.slaves, props.instances]);
return <>
diff --git a/packages/web_ui/src/components/MasterPage.jsx b/packages/web_ui/src/components/MasterPage.jsx
index 53c83877..088d347e 100644
--- a/packages/web_ui/src/components/MasterPage.jsx
+++ b/packages/web_ui/src/components/MasterPage.jsx
@@ -1,15 +1,23 @@
import React, { useContext } from "react";
+import { Typography } from "antd";
+import LogConsole from "./LogConsole";
import { useAccount } from "../model/account";
import MasterConfigTree from "./MasterConfigTree";
import PageLayout from "./PageLayout";
+const { Title } = Typography;
+
export default function SlavesPage() {
let account = useAccount();
return
Master
+ {account.hasPermission("core.log.follow") && <>
+ Console
+
+ >}
{account.hasPermission("core.master.get_config") && }
;
};
diff --git a/packages/web_ui/src/components/SlaveViewPage.jsx b/packages/web_ui/src/components/SlaveViewPage.jsx
index f4076073..c5a985bd 100644
--- a/packages/web_ui/src/components/SlaveViewPage.jsx
+++ b/packages/web_ui/src/components/SlaveViewPage.jsx
@@ -3,6 +3,7 @@ import { Descriptions, PageHeader, Spin, Typography } from "antd";
import { useParams } from "react-router-dom";
import InstanceList from "./InstanceList";
+import LogConsole from "./LogConsole";
import { useAccount } from "../model/account";
import { useInstanceList } from "../model/instance";
import { useSlave } from "../model/slave";
@@ -47,10 +48,13 @@ export default function SlaveViewPage(props) {
{slave["agent"]}
{slave["version"]}
-
{account.hasPermission("core.instance.list") && <>
Instances
>}
+ {account.hasPermission("core.log.follow") && <>
+ Console
+
+ >}
;
}
diff --git a/packages/web_ui/src/index.jsx b/packages/web_ui/src/index.jsx
index febfde98..ae2b6bbc 100644
--- a/packages/web_ui/src/index.jsx
+++ b/packages/web_ui/src/index.jsx
@@ -13,8 +13,9 @@ export { default as BaseConfigTree } from "./components/BaseConfigTree";
export { default as InstanceConfigTree } from "./components/InstanceConfigTree";
export { default as MasterConfigTree } from "./components/MasterConfigTree";
+export { default as LogConsole } from "./components/LogConsole";
+
export { default as AssignInstanceModal } from "./components/AssignInstanceModal";
-export { default as InstanceConsole } from "./components/InstanceConsole";
export { default as InstanceList } from "./components/InstanceList";
export { default as InstanceRcon } from "./components/InstanceRcon";
diff --git a/packages/web_ui/src/util/websocket.jsx b/packages/web_ui/src/util/websocket.jsx
index 18c54f1c..5473ad49 100644
--- a/packages/web_ui/src/util/websocket.jsx
+++ b/packages/web_ui/src/util/websocket.jsx
@@ -27,6 +27,22 @@ export class ControlConnector extends libLink.WebSocketClientConnector {
}
}
+function logFilter({ all, master, slave_ids, instance_ids }, info) {
+ if (all) {
+ return true;
+ }
+ if (master && info.slave_id === undefined) {
+ return true;
+ }
+ if (info.slave_id && slave_ids.includes(info.slave_id)) {
+ return true;
+ }
+ if (info.instance_id && instance_ids.includes(info.instance_id)) {
+ return true;
+ }
+ return false;
+}
+
/**
* Handles running the control
*
@@ -70,7 +86,7 @@ export class Control extends libLink.Link {
this.slaveUpdateHandlers = new Map();
this.instanceUpdateHandlers = new Map();
this.saveListUpdateHandlers = new Map();
- this.instanceLogHandlers = new Map();
+ this.logHandlers = new Map();
this.connector.on("connect", data => {
this.accountName = data.account.name;
@@ -302,23 +318,20 @@ export class Control extends libLink.Link {
async logMessageEventHandler(message) {
let info = message.data.info;
- if (info.instance_id !== undefined) {
- let instanceHandlers = this.instanceLogHandlers.get(info.instance_id);
- for (let handler of instanceHandlers || []) {
- handler(info);
+ for (let [filter, handlers] of this.logHandlers) {
+ if (logFilter(filter, info)) {
+ for (let handler of handlers) {
+ handler(info);
+ }
}
}
}
- async onInstanceLog(id, handler) {
- if (!Number.isInteger(id)) {
- throw new Error("Invalid instance id");
- }
-
- let handlers = this.instanceLogHandlers.get(id);
+ async onLog(filter, handler) {
+ let handlers = this.logHandlers.get(filter);
if (!handlers) {
handlers = [];
- this.instanceLogHandlers.set(id, handlers);
+ this.logHandlers.set(filter, handlers);
}
handlers.push(handler);
@@ -328,15 +341,15 @@ export class Control extends libLink.Link {
}
}
- async offInstanceLog(id, handler) {
- let handlers = this.instanceLogHandlers.get(id);
+ async offLog(filter, handler) {
+ let handlers = this.logHandlers.get(filter);
if (!handlers || !handlers.length) {
- throw new Error(`No handlers for instance ${id} exist`);
+ throw new Error("No handlers for the given filter exists");
}
let index = handlers.lastIndexOf(handler);
if (index === -1) {
- throw new Error(`Given handler is not registered for instance ${id}`);
+ throw new Error("Given handler is not registered for the filter");
}
handlers.splice(index, 1);
@@ -350,13 +363,29 @@ export class Control extends libLink.Link {
return;
}
- await libLink.messages.setLogSubscriptions.send(this, {
+ let combinedFilter = {
all: false,
master: false,
slave_ids: [],
- instance_ids: [...this.instanceLogHandlers.keys()],
- max_level: null,
- });
+ instance_ids: [],
+ };
+
+ for (let filter of this.logHandlers.keys()) {
+ if (filter.all) { combinedFilter.all = true; }
+ if (filter.master) { combinedFilter.master = true; }
+ for (let slaveId of filter.slave_ids || []) {
+ if (!combinedFilter.slave_ids.includes(slaveId)) {
+ combinedFilter.slave_ids.push(slaveId);
+ }
+ }
+ for (let instanceId of filter.instance_ids || []) {
+ if (!combinedFilter.instance_ids.includes(instanceId)) {
+ combinedFilter.instance_ids.push(instanceId);
+ }
+ }
+ }
+
+ await libLink.messages.setLogSubscriptions.send(this, { ...combinedFilter, max_level: null });
}
async debugWsMessageEventHandler(message) {