Design Admin UI Notifications
Implementation
NOTE: This section is outdated, please see Update section below.
Capabilities Considered
Notification bar
Description: A bar much like the "Default System Configuration" is shown on the Admin UI, under which all recorded error messages are displayed and can be dismissed.
Analysis: This would be pretty straightforward to implement and the architecture section below assumes that some sort of global notification list like this will be used. Please read the architecture section for implementation methods, pros, and cons of this capability.
Acknowledgement
Description: The user would be able to dismiss individual or all notifications after reviewing them.
Analysis: If the notification bar is implemented, acknowledgement would definitely be needed. This should also be pretty straightforward if using the notification bar way of displaying notifications. The Architecture section below also assumes that this is needed and goes more in depth on implementation, pros, and cons.
Highlighting/badging of apps/bundles/features that have errors
Description: When an error is recorded, highlight or badge the appropriate app.
Analysis: The admin ui mbean currently does a bundle-to-ui-app mapping that would be needed for this, but if using the backend to record notifications (see architecture section below) this functionality could be built into the endpoint. Dismissal of these notifications could be done in a few ways. One way could be by simply dismissing the notifications when the app is clicked on, but knowing what the error message in each one was could be confusing. Another way would be to put a "Notifications" or "Issues" tab under each app, and record the errors specific to that app under those tabs. They could be dismissed from that tab just like the notifications bar. It would essentially be like "scoping" the error messages to each bundle by physically putting the error display under each app in the ui.
Highlighting of specific configuration fields
Description: When there is a configuration error, highlight the app, configuration, and configuration field so that users can drill down to the issue and resolve it
Analysis: This goes a lot further than simple notifications. There would have to be an entire system set up for reporting configuration errors and where they are located, which currently does not exist. The information in the error messages generated by the loggers are not enough on their own to determine which specific configuration field is at fault. This capability is a bit outside the scope of admin UI notifications.
Link to pre-filtered log-viewer
Description: When a displayed notification is selected, open up a page to the admin ui LogViewer and preselect its filters to match the error message.
Analysis: Thile it is certainly possible to open the logviewer and change its filters, there are a few drawbacks that make this not very viable. The logviewer only records up to (by default) 500 logs from the time it is opened. If the backend is maintaining the list of notifications (see architecture section below), then it is very possible that the error message would not be viewable inside the admin ui's logviewer. Also, if the error message is displayed as a notification, then opening the error message in the logviewer would not provide any additional information already available in the notification.
Providing feedback on long-running processes
Description: Record errors that occur during long running processes such as a catalog export.
Analysis: If the notifications are recorded on the backend (see architecture section below), then this would automatically be handled.The logs would always be monitored and errors would be saved as notifications to be displayed the next time the user opens the admin ui. If notifications were recorded by the front end, this may become an issue. The frontend would have to stay open and would eventually become timed out by the server, halting all recording and clearing saved notifications.
Architecture
Backend Records
This seems like the most reasonable solution. There is a backend component that starts up with the system as early as possible to begin recording logs (much like the current logging backend endpoint does) and maintains a list of any error messages that arise. When the Admin UI is loaded, it hits the backend and retrieves the list of error logs that have been recorded and displays them to the user. When the user dismisses the error message, the frontend hits the backend endpoint with the log as an argument and the backend removes that log entry from its list of recorded error messages. In this configuration, the endpoint would return the list of error messages is no argument was provided, and would not return anything if an argument was provided, instead only removing the error message that was provided as the argument.
Pros:
- Recording is done entirely on the backend, putting less stress on the frontend.
- Error messages would be recorded even when the admin UI is not open.
- Error messages would be recorded from startup, even before the admin UI is available.
- The recording and dismissal of notifications would persist between browser sessions.
Cons:
- Another endpoint would need to be created.
- Unless the polling was implemented, new notifications would only appear on refresh.
- May cause some synchronization issues if multiple browser windows are opened at once.
- Notification dismissal would be permanent.
Variations to consider:
- It could be possible to build this functionality into the logging endpoint already present, but it would probably be best to just create a new endpoint.
- Do not send back any sort of dismissal call. Dismissals would only be saved in the current session. Maybe have some sort of global dismiss with a warning that it wil remove current notifications from the server. But this leaves the user is a strange situation where local dismissal then refreshing would result in the dismissed logs reappearing.
Frontend Records
This seems a bit less viable. The frontend component makes use of the logging endpoint already provided, and simply records and saves any error messages as notifications that it retrieves from the endpoint.
Pros:
- No new endpoint would have to be created.
- Error messages would be session-specific.
- Polling must be used in this setup, so notifications would be updated without having to refresh.
Cons:
- It would put more load on the front end to constantly monitor the logs.
- It the volume of logs is high enough, error messages could be missed (similar to the logviewer currently)
- Notifications would only begin after the admin UI was opened, meaning that the admin UI must remain open to record notifications.
- Errors on startup before the admin UI is available would not be caught.
- Notifications would not persist between sessions.
Design
Notifications Bar
Identical to the current "Default System Configurations" warning, there would be a bar labeled something like "Error Notifications" and would expand down to list the errors that were recorded. They could be dismissed in the same way, by clicking the "dismiss" button next to each item, or by clicking the title's "dismiss all" button to clear all notifications.
(insert image)
Notifications Bell
Same as the Notifications Bar explained above, but notifications instead show up as an Alerts Bell in the top right next to the "Log Out" button. Clicking it will open a drop down menu with dismissible notifications inside.
(insert image)
App-specific Notifications Tab
Instead of a global notifications bar, each app will have a "Notifications" or "Issues" tab. When a notification comes in, it will be delegated to one of these tabs. If there are any undismissed notifications, the App will be highlighted/badged to indicate that there are unacknowledged issues in that app.
Example of a highlighted/badged app:
(insert image)
Example of issues tab underneath each app. Tab title is red when list is not empty:
(insert image)
Recommendation
My recommendation would be to go with the Backend Records architecture, and the App-specific Notifications Tab. This would allow the user to quickly understand which apps are having issues, and also be able to record notifications while not in the admin ui. Opening the admin ui would show all notifications that have happened since the user last dismissed them. It would also allow for issues to be recorded at startup, which is usually when configuration errors tend to be reported. The endpoint could also map the bundle name to its correct app, and send that data along with the notifications to the frontend so that it can be delegated to its correct tab.
Update: 27 April 2016
Based on initial feedback and conversation, the notification backend is going to be designed as a more generalized OSGI service that can be used to generate notifications in the ui from any source, not only the logs. There are a few other things to consider using this approach:
Design
The app-specific error tabs can still be utilized, but since any notifications can be pushed to this service, there would also be a need for a generic notifications area for any notifications that do not pertain to a specific app. One approach would be to put app-specific notifications under their respective app tabs, and generic notifications in a top notifications bar. If this is the case, then the bar could either be put at the top underneath the "Default Configurations" banner, or combined with that banner into a single bar, and the Default Configurations warning would be treated as a notification. The implementation of the Default Configuration warning banner would need to be considered to determine how it could be integrated as a notification.
One other concern with delegating notifications to specific apps is that there would be no way of viewing all notifications at once, and the user would have to switch between different apps to find the most critical ones. One solution to this is to have an error tab under system that displays notifications from all apps.
Architecture
Creating an OSGI service that maintains the current state of notifications seems like the best approach. The notification service would maintain a list of incoming notifications and deliver them to the frontend to be displayed. When a notification is dismissed from the front end, it would tell the notification service to remove that item from its list of notifications. This would allow notifications to accumulate and persist independent of the frontend.
Communication
For adding new notifications to the notification service, the service would be called like any other OSGI service, with the option to specify a specific app to be categorized under or to be added to the generic notifications list.
For retrieving the list of notifications from the notification service, one possibility could be to poll the backend regularly to get a list of notifications and update the frontend's display, or it can be pushed updates in realtime via a cometD endpoint.
For dismissing notifications, the frontend would use one of the methods mentioned above to notify the backend to dismiss a specific notification, and the backend would remove it from the list of notifications it maintains.
Notifications Generated from Error Logs
One of the initial notification generators created would watch the logs and generate notifications from any error messages that it receives. These would be sent to the notification service along with the corresponding app to categorize it under. One capability that would need to be covered is the ability to dedupe any error messages. Sometimes multiple identical error messages come in, so they would need to be deduplicated in order to prevent the notification service from being flooded.
Responsibilities of the Notification Service
The previous section raises the issue of whether or not deduplication should be on the notification generators, or on the notification service -- and more generally, what the responsibilities of the notification service itself should be.
To keep the notification service reusable and focused, its only responsibilities should be to add notifications to a list, remove them from the list, and serve them to the frontend. This way the notification service acts as a gateway for components to get notifications into the admin UI. Deduplication, throttling, or any other logic related to the generation of notifications, should be left up the the components generating the notifications themselves.
Current Frontend Design
Here is our current plan for the frontend display of notifications. The backend will send notifications along with an associated Application. If the notification includes an application, it will be filed under an `Issues` tab underneath the respective app and the app will be badged. If no app is specified, it is categorized as `General` and displayed under the banner at the top of the screen. To view all logs, there will be an issues tab underneath `System`.
Examples:
This image shows how apps will be badged when they have undismissed notifications:
(insert image)
There will be an `Issues` tab underneath the Application's page. When there are undismissed notifications, the title of the tab will turn red:
(insert image)
All uncategorized notifications will be shown underneath the top red banner, and default configuration warnings will be treated as notifications under this banner:
(insert image)
To view all notifications at once, there will be an `Issues` tab underneath the System page which aggregates all of the notifications:
(insert image)
Severity Levels
Something that needs further consideration is whether or not the notifications should be able to specify a severity level, and if so, what those levels should be. Since there is no need to restrict the notification levels to the same set as the Karaf logs, the severity levels could be anything.