See LICENSE for this software's licensing terms. At first glance, it resembles the BSD-3 license, but it contains a significant difference which prohibits certain use. Read it carefully. Licenses for third-party components used by RealtimeMonitor are in THIRD_PARTY_LICENSES.MD.
This is a pure JavaScript application (no jQuery, etc.) that is used for monitoring numeric data returned by a server. The data could be from anything at all - machinery, atmospheric sensors... any type of numeric data that you can get into a server is fair game.
Supported methods of data retrieval are Web sockets and AJAX GET/POST polling. The server response must be JSON.
Knowing what the server response looks like, you create a corresponding configuration object to set up the fields you want to display. Optional high and low thresholds can be set on each field. Each threshold has a warning level and a danger level. Visual feedback is given if the data falls outside of the established boundaries.
The fields are laid out vertically in a panel, and you can create as many panels as you wish. Current, highest and lowest values are tracked, and realtime graphs display the last 35 data points for each field.
Compatibility is limited to browsers which support const, let and mutation observers, which means anything loosely modern, including the aging IE 11.
Using RealtimeMonitor is pretty simple - there are three steps:
- Instantiate RealtimeMonitor
- Create a panel via the
newPanel
function - Append the returned DOM object to something
var rtm = new RealtimeMonitor();
var panel = rtm.newPanel( options );
element.appendChild( panel );
See the demo
directory for in-depth code examples of various panel configurations.
The configuration object passed into newPanel
has the following properties:
Property | Data Type | Description | Required ? | Default Value |
---|---|---|---|---|
title |
string | Text displayed in the panel's title bar | yes | none |
url |
object | Specifies how data is retrieved. Click the property name to be taken to the definition of this nested object. | yes | none |
autoConnect |
boolean | If true , the panel will connect as soon as it's added to the page |
no | true |
startMinimized |
boolean | If true , the panel initializes collapsed down to its title bar |
no | false |
notifications |
boolean | If true , and if the browser supports it, native system notifications will display when low or high thresholds reach the warning or danger level |
no | true |
fields |
object array | Specifies field configuration. Each element of the array contains the configuration for a single field. Click the property name to be taken to the definition of this nested object. | yes | none |
Property | Data Type | Description | Required ? | Default Value |
---|---|---|---|---|
address |
string | The URL used to update the panel. Supported protocols are http, https, ws and wss. | yes | none |
method |
string | The HTTP method. Valid values are GET and POST. This property is not used with Web sockets. | yes, if using HTTP(S) | none |
postData |
object | Only define this property if method is POST. An object consisting of key/value pairs defining fields to be sent in the POST. |
yes, if POST | none |
pollInterval |
int | The GET/POST polling interval, in seconds. The lowest possible value is 3; if the value is less than 3, it is ignored and 3 is used instead. (Not used with Web sockets - Web sockets have updates pushed to them whenever the server decides to). | no | 3 |
wsGreeting |
object | For use with Web sockets only. If for whatever reason you need to send data as soon as the connection is established, provide it here. The object will be transmitted as JSON, and will be transmitted only once. | no | none |
wsCloseCodes |
int[ ] | For use with Web sockets only. Specifies CloseEvent.code values that, if encountered, will result in the panel attempting to automatically reconnect. 1000 (normal closure) is not allowed; using it will cause initialization to abort. You'll need a carefully-coded back end to be sure of the reason you're reconnecting. | no | none |
Property | Data Type | Description | Required ? | Default Value |
---|---|---|---|---|
prop |
string | The property name in the JSON response | yes | none |
label |
string | Text displayed in front of the value | yes | none |
suffix |
string | Text displayed after the value to indicate unit of measurement, etc. | no | none |
lowThresholds |
object | An optional object specifying numeric warning and danger levels - used to drive visual feedback. Click the property name to be taken to the definition of this nested object. | no | none |
highThresholds |
object | Same idea as lowThresholds |
no | none |
showLowest |
boolean | Specifies whether to display the lowest recorded value for prop . When enabled, the value will appear as a separate field immediately beneath the field being tracked. When disabled, the value will still be viewable as a tooltip on the field name. |
no | true |
showHighest |
boolean | Same idea as showLowest |
no | true |
Property | Data Type | Description | Required ? | Default Value |
---|---|---|---|---|
warn |
number | The warning threshold | Only if danger is not defined |
none |
danger |
number | The danger threshold | Only if warn is not defined |
none |
Method | Return Type | Description |
---|---|---|
getAvailableThemes() |
string[ ] | Returns all available themes. The array contains the title attribute of all alternate stylesheets. |
getTheme() |
string | Returns the name of the current theme. This is the title attribute of the currently active alternate stylesheet. Returns null if no theme is in use. |
loadTheme(string) |
void | Changes the current theme - in other words, sets an alternate stylesheet to active based on a title attribute matching the supplied argument. |
Event | Description |
---|---|
RTMThemeChange* | Fired when the theme is changed. The theme name is attached to the event in event.detail.themeName . |
* For IE 11 compatibility, RealtimeMonitor contains a polyfill for CustomEvent. If your practice is to keep polyfills separate in your projects, you'll want to remove it from your copy of RealtimeMonitor.
RealtimeMonitor doesn't have an offline simulator. To see it process data, you'll need a Web application that returns JSON in response to requests.
In the demo
directory you'll find a barebones Node.js server which does this. Install Node.js and OpenSSL if you don't have them, then:
For Windows users, run startserver.bat
. The batch script takes care of dependencies, such installing required NPM modules and creating a certificate.
If not using startserver.bat
, change into the base directory, then install the server dependencies:
$ cd js-RealtimeMonitor
$ npm install ws
Then, without changing the working directory:
$ node demo/server.js
By design, the server only honors requests from localhost.
Once the server is running, open demo/demo.html
straight from your filesystem, and it will automatically redirect to the secure localhost URL.
Assuming you've declared thresholds for a field, each status (normal, warning and danger) has a different color associated with it. Color coding is used in three ways:
-
The status of the latest reading is represented as a colored square to the left of the field. The status is determined by comparing the value to the high and low thresholds.
-
The highest & lowest (the historical) readings are displayed as colored text. These values are also compared against the high and low thresholds. Unlike the real-time reading, these fields only change color if the values deteriorate to the point that a worse threshold is breached. In other words, once it reaches 'warning', it can't get back to 'normal', and once it reaches 'danger', it remains there forever.
-
The color of the titlebar indicates the worst status among the latest readings of all fields.
At the bottom of each panel is an area that contains a line graph for the currently chosen field. Cycle through the graphs by clicking a field label.
RealtimeMonitor uses Chart.js for graphing. Compatibility has only been verified with Chart.js v2.7.2, the latest available at the time this software was written. Using a different version could potentially cause a theme's graph colors to malfunction - you'll have to test that yourself.
The graph configurations have been tuned for readability and performance:
- Graphs display a maximum of 35 points at a time, after which data points get shifted off the left edge.
- All Chart.js animations are disabled. In Firefox on a Core i7 with one panel containing 4 fields, CPU use often reached 15% with animations enabled (!). Granted, Firefox isn't the most performant browser out there, but this benchmark wasn't acceptable. With animations disabled, as well as a few other tweaks, the same test scenario resulted in CPU use of 0-1%.
I contemplated making the Chart.js settings configurable so that these choices are not forced on everyone, but ultimately I decided against it. I don't recommend changing these settings.
The application can generate system notifications when a warning or danger threshold is reached. This feature is enabled/disabled through configuration. The goal behind adding notification support is that you can keep your browser out of view and still know when something requires your attention.
Notification technology is currently evolving. As of early 2018, it's still somewhat of a mess; there are deprecated APIs and browsers differ greatly in supported capabilities. IE has no support; Firefox and Chrome support them, but each browser has its own set of annoyances - more on that in a moment.
Each panel displays a notification when one of its warning or danger thresholds is reached. Because it's important to not miss one of these events, the code is written so that the notifications are persistent: they won't close on their own - the user must close them. A panel cannot have more than one open notification at a time, so unless you have a dozen panels and conditions go south in all of them, you won't get buried in notifications.
There is a possible annoyance factor, though. Every time a panel refreshes, it evaluates whether any of its readings crosses into the warning/danger zone, and if so, it displays a notification. That means that if the user closes a notification, it can pop right back up the next time the panel refreshes. Since this could be rather infuriating, the application provides a menu option within each panel to mute/unmute notifications from that panel. As was mentioned at the beginning of this section, notifications can also be defaulted to off via configuration.
Now, onto the browser-specific issues.
By default, Firefox ignores the configuration option that makes notifications persistent. See this bug. To enable persistent notifications, dom.webnotifications.requireinteraction.enabled must be set to true
in about:config. So, unless you/your users are going to be staring at panels continuously, or unless you can get them to fiddle with browser configuration, Firefox is probably a poor choice.
Chrome only displays notifications if the page is loaded over HTTPS - or so I've read. If that's true, there appears to be an exemption for servers running off of localhost, because I ran it on an insecure local server just fine.
The application includes several alternate color schemes, or themes. Themes are implemented by alternate stylesheets which override portions of the base stylesheet. Some browsers, such as Firefox and IE, place alternate stylesheets in a menu that the user can then select from to switch to a different theme. Chrome does not have built-in support for this functionality. I've read that there are third-party Chrome addons that add this capability, but I haven't looked into it any further than that.
Chromium (and by extension, all Chromium-based browsers) has a bug where alternate stylesheets aren't correctly initialized upon page load. Chromium initializes the 'disabled' property of every alternate stylesheet to false
, which is wrong. The workaround for this needs to be made at the page level, not within RealtimeMonitor. If you plan on using themes, you need to forcibly set this property to true
on all alternate stylesheets before instantiating RealtimeMonitor. See the fixBrokenBrowsers
function in demo.js
for code which does this.
-
Graphs are implemented with Chart.js
-
The warning and danger notification icons were provided by Pixabay user Clker-Free-Vector-Images.