show # messages, use msgpack to compress json

This commit is contained in:
proddy
2021-06-16 20:31:35 +02:00
parent 19b37d9e0e
commit 7e7bd29c9a
9 changed files with 71 additions and 58 deletions

View File

@@ -24,7 +24,10 @@ class EMSESP extends Component<RouteComponentProps> {
onChange={(e, path) => this.handleTabChange(path)} onChange={(e, path) => this.handleTabChange(path)}
variant="fullWidth" variant="fullWidth"
> >
<Tab value={`/${PROJECT_PATH}/devices`} label="Devices & Sensors" /> <Tab
value={`/${PROJECT_PATH}/devices`}
label="Devices &amp; Sensors"
/>
<Tab value={`/${PROJECT_PATH}/status`} label="EMS Status" /> <Tab value={`/${PROJECT_PATH}/status`} label="EMS Status" />
<Tab value={`/${PROJECT_PATH}/help`} label="EMS-ESP Help" /> <Tab value={`/${PROJECT_PATH}/help`} label="EMS-ESP Help" />
</Tabs> </Tabs>

View File

@@ -22,7 +22,7 @@ class EMSESPDevicesController extends Component<EMSESPDevicesControllerProps> {
render() { render() {
return ( return (
<SectionContent title="Devices & Sensors"> <SectionContent title="Devices &amp; Sensors">
<RestFormLoader <RestFormLoader
{...this.props} {...this.props}
render={(formProps) => <EMSESPDevicesForm {...formProps} />} render={(formProps) => <EMSESPDevicesForm {...formProps} />}

View File

@@ -108,12 +108,10 @@ const LogEventConsole: FC<LogEventConsoleProps> = (props) => {
<Box id="log-window" className={classes.console}> <Box id="log-window" className={classes.console}>
{events.map((e) => ( {events.map((e) => (
<div className={classes.entry}> <div className={classes.entry}>
<span>{e.time}</span> <span>{e.t}</span>
<span className={styleLevel(e.level)}> <span className={styleLevel(e.l)}>{paddedLevelLabel(e.l)} </span>
{paddedLevelLabel(e.level)}{' '} <span>{paddedNameLabel(e.n)} </span>
</span> <span>{e.m}</span>
<span>{paddedNameLabel(e.name)} </span>
<span>{e.message}</span>
</div> </div>
))} ))}
</Box> </Box>

View File

@@ -22,6 +22,9 @@ import LogEventConsole from './LogEventConsole';
import { LogEvent, LogSettings } from './types'; import { LogEvent, LogSettings } from './types';
import { Decoder } from '@msgpack/msgpack';
const decoder = new Decoder();
interface LogEventControllerState { interface LogEventControllerState {
eventSource?: EventSource; eventSource?: EventSource;
events: LogEvent[]; events: LogEvent[];
@@ -71,12 +74,13 @@ class LogEventController extends Component<
fetch(FETCH_LOG_ENDPOINT) fetch(FETCH_LOG_ENDPOINT)
.then((response) => { .then((response) => {
if (response.status === 200) { if (response.status === 200) {
return response.json(); return response.arrayBuffer();
} else { } else {
throw Error('Unexpected status code: ' + response.status); throw Error('Unexpected status code: ' + response.status);
} }
}) })
.then((json) => { .then((arrayBuffer) => {
const json: any = decoder.decode(arrayBuffer);
this.setState({ events: json.events }); this.setState({ events: json.events });
}) })
.catch((error) => { .catch((error) => {

View File

@@ -5,6 +5,8 @@ import {
SelectValidator SelectValidator
} from 'react-material-ui-form-validator'; } from 'react-material-ui-form-validator';
import { Typography } from '@material-ui/core';
import MenuItem from '@material-ui/core/MenuItem'; import MenuItem from '@material-ui/core/MenuItem';
import { import {
@@ -79,6 +81,9 @@ class LogEventForm extends Component<LogEventFormProps> {
<MenuItem value={7}>DEBUG</MenuItem> <MenuItem value={7}>DEBUG</MenuItem>
<MenuItem value={8}>TRACE</MenuItem> <MenuItem value={8}>TRACE</MenuItem>
</SelectValidator> </SelectValidator>
<Typography color="primary" variant="body2">
<i>Only the last {data.max_messages} messages are shown</i>
</Typography>
</ValidatorForm> </ValidatorForm>
); );
} }

View File

@@ -47,12 +47,13 @@ export enum LogLevel {
} }
export interface LogEvent { export interface LogEvent {
time: string; t: string;
level: LogLevel; l: LogLevel;
name: string; n: string;
message: string; m: string;
} }
export interface LogSettings { export interface LogSettings {
level: LogLevel; level: LogLevel;
max_messages: number;
} }

View File

@@ -18,46 +18,47 @@ const ES_ENDPOINT_ROOT = '/es/'
const LOG_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'logSettings' const LOG_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'logSettings'
const log_settings = { const log_settings = {
level: 6, level: 6,
max_messages: 25,
} }
const FETCH_LOG_ENDPOINT = REST_ENDPOINT_ROOT + 'fetchLog' const FETCH_LOG_ENDPOINT = REST_ENDPOINT_ROOT + 'fetchLog'
const fetch_log = { const fetch_log = {
events: [ events: [
{ {
time: '000+00:00:00.001', t: '000+00:00:00.001',
level: 3, l: 3,
name: 'system', n: 'system',
message: 'this is message 3', m: 'this is message 3',
}, },
{ {
time: '000+00:00:00.002', t: '000+00:00:00.002',
level: 4, l: 4,
name: 'system', n: 'system',
message: 'this is message 4', m: 'this is message 4',
}, },
{ {
time: '000+00:00:00.002', t: '000+00:00:00.002',
level: 5, l: 5,
name: 'system', n: 'system',
message: 'this is message 5', m: 'this is message 5',
}, },
{ {
time: '000+00:00:00.002', t: '000+00:00:00.002',
level: 6, l: 6,
name: 'system', n: 'system',
message: 'this is message 6', m: 'this is message 6',
}, },
{ {
time: '000+00:00:00.002', t: '000+00:00:00.002',
level: 7, l: 7,
name: 'emsesp', n: 'emsesp',
message: 'this is message 7', m: 'this is message 7',
}, },
{ {
time: '000+00:00:00.002', t: '000+00:00:00.002',
level: 8, l: 8,
name: 'mqtt', n: 'mqtt',
message: 'this is message 8', m: 'this is message 8',
}, },
], ],
} }
@@ -753,7 +754,9 @@ const emsesp_devicedata_3 = {
// LOG // LOG
app.get(FETCH_LOG_ENDPOINT, (req, res) => { app.get(FETCH_LOG_ENDPOINT, (req, res) => {
res.json(fetch_log) const encoded = msgpack.encode(fetch_log)
res.write(encoded, 'binary')
res.end(null, 'binary')
}) })
app.get(LOG_SETTINGS_ENDPOINT, (req, res) => { app.get(LOG_SETTINGS_ENDPOINT, (req, res) => {
res.json(log_settings) res.json(log_settings)

View File

@@ -33,6 +33,7 @@ WebLogService::WebLogService(AsyncWebServer * server, SecurityManager * security
// for bring back the whole log // for bring back the whole log
server->on(FETCH_LOG_PATH, HTTP_GET, std::bind(&WebLogService::fetchLog, this, _1)); server->on(FETCH_LOG_PATH, HTTP_GET, std::bind(&WebLogService::fetchLog, this, _1));
// get when page is loaded
server->on(LOG_SETTINGS_PATH, HTTP_GET, std::bind(&WebLogService::getLevel, this, _1)); server->on(LOG_SETTINGS_PATH, HTTP_GET, std::bind(&WebLogService::getLevel, this, _1));
// for setting a level // for setting a level
@@ -104,10 +105,10 @@ void WebLogService::loop() {
void WebLogService::transmit(const QueuedLogMessage & message) { void WebLogService::transmit(const QueuedLogMessage & message) {
DynamicJsonDocument jsonDocument = DynamicJsonDocument(EMSESP_JSON_SIZE_SMALL); DynamicJsonDocument jsonDocument = DynamicJsonDocument(EMSESP_JSON_SIZE_SMALL);
JsonObject logEvent = jsonDocument.to<JsonObject>(); JsonObject logEvent = jsonDocument.to<JsonObject>();
logEvent["time"] = uuid::log::format_timestamp_ms(message.content_->uptime_ms, 3); logEvent["t"] = uuid::log::format_timestamp_ms(message.content_->uptime_ms, 3);
logEvent["level"] = message.content_->level; logEvent["l"] = message.content_->level;
logEvent["name"] = message.content_->name; logEvent["n"] = message.content_->name;
logEvent["message"] = message.content_->text; logEvent["m"] = message.content_->text;
size_t len = measureJson(jsonDocument); size_t len = measureJson(jsonDocument);
char * buffer = new char[len + 1]; char * buffer = new char[len + 1];
@@ -120,7 +121,7 @@ void WebLogService::transmit(const QueuedLogMessage & message) {
// send the current log buffer to the API // send the current log buffer to the API
void WebLogService::fetchLog(AsyncWebServerRequest * request) { void WebLogService::fetchLog(AsyncWebServerRequest * request) {
AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XLARGE_DYN); MsgpackAsyncJsonResponse * response = new MsgpackAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE_DYN); // 8kb buffer
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
JsonArray log = root.createNestedArray("events"); JsonArray log = root.createNestedArray("events");
@@ -128,10 +129,10 @@ void WebLogService::fetchLog(AsyncWebServerRequest * request) {
for (const auto & msg : log_messages_) { for (const auto & msg : log_messages_) {
JsonObject logEvent = log.createNestedObject(); JsonObject logEvent = log.createNestedObject();
auto message = std::move(msg); auto message = std::move(msg);
logEvent["time"] = uuid::log::format_timestamp_ms(message.content_->uptime_ms, 3); logEvent["t"] = uuid::log::format_timestamp_ms(message.content_->uptime_ms, 3);
logEvent["level"] = message.content_->level; logEvent["l"] = message.content_->level;
logEvent["name"] = message.content_->name; logEvent["n"] = message.content_->name;
logEvent["message"] = message.content_->text; logEvent["m"] = message.content_->text;
} }
log_message_id_tail_ = log_messages_.back().id_; log_message_id_tail_ = log_messages_.back().id_;
@@ -140,7 +141,7 @@ void WebLogService::fetchLog(AsyncWebServerRequest * request) {
request->send(response); request->send(response);
} }
// sets the level // sets the level after a POST
void WebLogService::setLevel(AsyncWebServerRequest * request, JsonVariant & json) { void WebLogService::setLevel(AsyncWebServerRequest * request, JsonVariant & json) {
if (not json.is<JsonObject>()) { if (not json.is<JsonObject>()) {
return; return;
@@ -157,14 +158,12 @@ void WebLogService::setLevel(AsyncWebServerRequest * request, JsonVariant & json
request->send(response); request->send(response);
} }
// return the current log level // return the current log level after a GET
void WebLogService::getLevel(AsyncWebServerRequest * request) { void WebLogService::getLevel(AsyncWebServerRequest * request) {
AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL); AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL);
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
root["level"] = log_level();
auto level = log_level(); root["max_messages"] = maximum_log_messages();
root["level"] = level;
response->setLength(); response->setLength();
request->send(response); request->send(response);
} }

View File

@@ -34,7 +34,7 @@ namespace emsesp {
class WebLogService : public uuid::log::Handler { class WebLogService : public uuid::log::Handler {
public: public:
static constexpr size_t MAX_LOG_MESSAGES = 50; static constexpr size_t MAX_LOG_MESSAGES = 30;
WebLogService(AsyncWebServer * server, SecurityManager * securityManager); WebLogService(AsyncWebServer * server, SecurityManager * securityManager);
@@ -71,7 +71,7 @@ class WebLogService : public uuid::log::Handler {
uint64_t last_transmit_ = 0; // Last transmit time uint64_t last_transmit_ = 0; // Last transmit time
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; // Maximum number of log messages to buffer before they are output size_t maximum_log_messages_ = MAX_LOG_MESSAGES; // Maximum number of log messages to buffer before they are output
unsigned long log_message_id_ = 0; // The next identifier to use for queued log messages unsigned long log_message_id_ = 0; // The next identifier to use for queued log messages
unsigned long log_message_id_tail_ = 0; unsigned long log_message_id_tail_ = 0; // last event shown on the screen after fetch
std::list<QueuedLogMessage> log_messages_; // Queued log messages, in the order they were received std::list<QueuedLogMessage> log_messages_; // Queued log messages, in the order they were received
}; };