grpc/pygui: added grpc alert api, updated pygui to better handle and display alerts
This commit is contained in:
parent
e34002b851
commit
f8d862a296
7 changed files with 97 additions and 31 deletions
|
@ -445,6 +445,23 @@ class CoreGrpcClient:
|
|||
)
|
||||
return self.stub.AddSessionServer(request)
|
||||
|
||||
def alert(
|
||||
self,
|
||||
session_id: int,
|
||||
level: core_pb2.ExceptionLevel,
|
||||
source: str,
|
||||
text: str,
|
||||
node_id: int = None,
|
||||
) -> core_pb2.SessionAlertResponse:
|
||||
request = core_pb2.SessionAlertRequest(
|
||||
session_id=session_id,
|
||||
level=level,
|
||||
source=source,
|
||||
text=text,
|
||||
node_id=node_id,
|
||||
)
|
||||
return self.stub.SessionAlert(request)
|
||||
|
||||
def events(
|
||||
self,
|
||||
session_id: int,
|
||||
|
|
|
@ -109,7 +109,12 @@ from core.api.grpc.wlan_pb2 import (
|
|||
)
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import InterfaceData, LinkData, LinkOptions, NodeOptions
|
||||
from core.emulator.enumerations import EventTypes, LinkTypes, MessageFlags
|
||||
from core.emulator.enumerations import (
|
||||
EventTypes,
|
||||
ExceptionLevels,
|
||||
LinkTypes,
|
||||
MessageFlags,
|
||||
)
|
||||
from core.emulator.session import NT, Session
|
||||
from core.errors import CoreCommandError, CoreError
|
||||
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||
|
@ -584,6 +589,15 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
session.distributed.add_server(request.name, request.host)
|
||||
return core_pb2.AddSessionServerResponse(result=True)
|
||||
|
||||
def SessionAlert(
|
||||
self, request: core_pb2.SessionAlertRequest, context: ServicerContext
|
||||
) -> core_pb2.SessionAlertResponse:
|
||||
session = self.get_session(request.session_id, context)
|
||||
level = ExceptionLevels(request.level)
|
||||
node_id = request.node_id if request.node_id else None
|
||||
session.exception(level, request.source, request.text, node_id)
|
||||
return core_pb2.SessionAlertResponse(result=True)
|
||||
|
||||
def Events(self, request: core_pb2.EventsRequest, context: ServicerContext) -> None:
|
||||
session = self.get_session(request.session_id, context)
|
||||
event_types = set(request.events)
|
||||
|
|
|
@ -271,7 +271,7 @@ class CoreClient:
|
|||
|
||||
def handle_exception_event(self, event: ExceptionEvent) -> None:
|
||||
logging.info("exception event: %s", event)
|
||||
self.app.statusbar.core_alarms.append(event)
|
||||
self.app.statusbar.add_alert(event)
|
||||
|
||||
def join_session(self, session_id: int, query_location: bool = True) -> None:
|
||||
logging.info("join session(%s)", session_id)
|
||||
|
|
|
@ -52,6 +52,7 @@ class AlertsDialog(Dialog):
|
|||
for alarm in self.app.statusbar.core_alarms:
|
||||
exception = alarm.exception_event
|
||||
level_name = ExceptionLevel.Enum.Name(exception.level)
|
||||
node_id = exception.node_id if exception.node_id else ""
|
||||
insert_id = self.tree.insert(
|
||||
"",
|
||||
tk.END,
|
||||
|
@ -60,7 +61,7 @@ class AlertsDialog(Dialog):
|
|||
exception.date,
|
||||
level_name,
|
||||
alarm.session_id,
|
||||
exception.node_id,
|
||||
node_id,
|
||||
exception.source,
|
||||
),
|
||||
tags=(level_name,),
|
||||
|
@ -98,15 +99,17 @@ class AlertsDialog(Dialog):
|
|||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def reset_alerts(self) -> None:
|
||||
self.codetext.text.delete("1.0", tk.END)
|
||||
self.codetext.text.config(state=tk.NORMAL)
|
||||
self.codetext.text.delete(1.0, tk.END)
|
||||
self.codetext.text.config(state=tk.DISABLED)
|
||||
for item in self.tree.get_children():
|
||||
self.tree.delete(item)
|
||||
self.app.statusbar.core_alarms.clear()
|
||||
self.app.statusbar.clear_alerts()
|
||||
|
||||
def click_select(self, event: tk.Event) -> None:
|
||||
current = self.tree.selection()[0]
|
||||
alarm = self.alarm_map[current]
|
||||
self.codetext.text.config(state=tk.NORMAL)
|
||||
self.codetext.text.delete("1.0", "end")
|
||||
self.codetext.text.insert("1.0", alarm.exception_event.text)
|
||||
self.codetext.text.delete(1.0, tk.END)
|
||||
self.codetext.text.insert(1.0, alarm.exception_event.text)
|
||||
self.codetext.text.config(state=tk.DISABLED)
|
||||
|
|
|
@ -5,7 +5,7 @@ import tkinter as tk
|
|||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING, List, Optional
|
||||
|
||||
from core.api.grpc.core_pb2 import ExceptionEvent
|
||||
from core.api.grpc.core_pb2 import ExceptionEvent, ExceptionLevel
|
||||
from core.gui.dialogs.alerts import AlertsDialog
|
||||
from core.gui.themes import Styles
|
||||
|
||||
|
@ -22,6 +22,7 @@ class StatusBar(ttk.Frame):
|
|||
self.zoom: Optional[ttk.Label] = None
|
||||
self.cpu_usage: Optional[ttk.Label] = None
|
||||
self.alerts_button: Optional[ttk.Button] = None
|
||||
self.alert_style = Styles.no_alert
|
||||
self.running: bool = False
|
||||
self.core_alarms: List[ExceptionEvent] = []
|
||||
self.draw()
|
||||
|
@ -60,10 +61,30 @@ class StatusBar(ttk.Frame):
|
|||
self.cpu_usage.grid(row=0, column=2, sticky="ew")
|
||||
|
||||
self.alerts_button = ttk.Button(
|
||||
self, text="Alerts", command=self.click_alerts, style=Styles.green_alert
|
||||
self, text="Alerts", command=self.click_alerts, style=self.alert_style
|
||||
)
|
||||
self.alerts_button.grid(row=0, column=3, sticky="ew")
|
||||
|
||||
def add_alert(self, event: ExceptionEvent) -> None:
|
||||
self.core_alarms.append(event)
|
||||
level = event.exception_event.level
|
||||
self._set_alert_style(level)
|
||||
label = f"Alerts ({len(self.core_alarms)})"
|
||||
self.alerts_button.config(text=label, style=self.alert_style)
|
||||
|
||||
def _set_alert_style(self, level: ExceptionLevel) -> None:
|
||||
if level in [ExceptionLevel.FATAL, ExceptionLevel.ERROR]:
|
||||
self.alert_style = Styles.red_alert
|
||||
elif level == ExceptionLevel.WARNING and self.alert_style != Styles.red_alert:
|
||||
self.alert_style = Styles.yellow_alert
|
||||
elif self.alert_style == Styles.no_alert:
|
||||
self.alert_style = Styles.green_alert
|
||||
|
||||
def clear_alerts(self):
|
||||
self.core_alarms.clear()
|
||||
self.alert_style = Styles.no_alert
|
||||
self.alerts_button.config(text="Alerts", style=self.alert_style)
|
||||
|
||||
def click_alerts(self) -> None:
|
||||
dialog = AlertsDialog(self.app)
|
||||
dialog.show()
|
||||
|
|
|
@ -14,6 +14,7 @@ class Styles:
|
|||
tooltip_frame: str = "Tooltip.TFrame"
|
||||
service_checkbutton: str = "Service.TCheckbutton"
|
||||
picker_button: str = "Picker.TButton"
|
||||
no_alert: str = "NAlert.TButton"
|
||||
green_alert: str = "GAlert.TButton"
|
||||
red_alert: str = "RAlert.TButton"
|
||||
yellow_alert: str = "YAlert.TButton"
|
||||
|
@ -175,33 +176,29 @@ def style_listbox(widget: tk.Widget) -> None:
|
|||
)
|
||||
|
||||
|
||||
def _alert_style(style: ttk.Style, name: str, background: str):
|
||||
style.configure(
|
||||
name,
|
||||
background=background,
|
||||
padding=0,
|
||||
relief=tk.RIDGE,
|
||||
borderwidth=1,
|
||||
font="TkDefaultFont",
|
||||
foreground="black",
|
||||
highlightbackground="white",
|
||||
)
|
||||
style.map(name, background=[("!active", background), ("active", "white")])
|
||||
|
||||
|
||||
def theme_change(event: tk.Event) -> None:
|
||||
style = ttk.Style()
|
||||
style.configure(Styles.picker_button, font="TkSmallCaptionFont")
|
||||
style.configure(
|
||||
Styles.green_alert,
|
||||
background="green",
|
||||
padding=0,
|
||||
relief=tk.RIDGE,
|
||||
borderwidth=1,
|
||||
font="TkDefaultFont",
|
||||
)
|
||||
style.configure(
|
||||
Styles.yellow_alert,
|
||||
background="yellow",
|
||||
padding=0,
|
||||
relief=tk.RIDGE,
|
||||
borderwidth=1,
|
||||
font="TkDefaultFont",
|
||||
)
|
||||
style.configure(
|
||||
Styles.red_alert,
|
||||
background="red",
|
||||
padding=0,
|
||||
relief=tk.RIDGE,
|
||||
borderwidth=1,
|
||||
font="TkDefaultFont",
|
||||
Styles.no_alert, padding=0, relief=tk.RIDGE, borderwidth=1, font="TkDefaultFont"
|
||||
)
|
||||
_alert_style(style, Styles.green_alert, "green")
|
||||
_alert_style(style, Styles.yellow_alert, "yellow")
|
||||
_alert_style(style, Styles.red_alert, "red")
|
||||
|
||||
|
||||
def scale_fonts(fonts_size: Dict[str, int], scale: float) -> None:
|
||||
|
|
|
@ -43,6 +43,8 @@ service CoreApi {
|
|||
}
|
||||
rpc AddSessionServer (AddSessionServerRequest) returns (AddSessionServerResponse) {
|
||||
}
|
||||
rpc SessionAlert (SessionAlertRequest) returns (SessionAlertResponse) {
|
||||
}
|
||||
|
||||
// streams
|
||||
rpc Events (EventsRequest) returns (stream Event) {
|
||||
|
@ -318,6 +320,18 @@ message AddSessionServerResponse {
|
|||
bool result = 1;
|
||||
}
|
||||
|
||||
message SessionAlertRequest {
|
||||
int32 session_id = 1;
|
||||
ExceptionLevel.Enum level = 2;
|
||||
string source = 3;
|
||||
string text = 4;
|
||||
int32 node_id = 5;
|
||||
}
|
||||
|
||||
message SessionAlertResponse {
|
||||
bool result = 1;
|
||||
}
|
||||
|
||||
message EventsRequest {
|
||||
int32 session_id = 1;
|
||||
repeated EventType.Enum events = 2;
|
||||
|
|
Loading…
Reference in a new issue