logger is a cloud-based logging application built to support development and monitoring factors.
Commercial alternatives are unnecessarily costly and complex, considering the lack of revenue from developing solely as a hobby.
At the same time, logger serves as a pilot for developing with the chosen technologies for factors.
|Log||A list of entries that document events from the monitored application.|
|Entry||Consist of a timestamp, a session id and a message.|
|Timestamp||Shows when the event occurred.|
|Session||Shows the session id, which helps isolate events from a particular user session if many sessions send events to the log.|
|Message||Describes the occurred event.|
|logger||The actual web application described in this document.||logger|
|C#||Object-oriented programming language.||C# documentation|
|.NET Core||Open-source platform for running apps on Windows, macOS and Linux.||.NET Core guide|
|Rider||C# development tool from JetBrains.||Rider|
|SmarterASP.NET||ASP.NET hosting on Windows 10 virtualized servers supporting the .NET Core runtime.||SmarterASP.NET|
|factors||A monitored app logging to logger.||factors|
|Material||A user interface standard developed by Google.||Material Design|
|DevExtreme||A user interface component suite developed by DevExpress.||DevExtreme|
1.4 Change log
|1.0||January 2020||Initial release.|
2. Solution overview
logger runs on a cloud-based virtualized Windows 10 server on top of IIS and the .NET Core runtime:
logger shows a simple list of log entries collected from another monitored app like factors.
The solution supports viewing the log, pinging it to verify readiness and clearing it:
The application basically holds a list of entries:
Each entry consists of a timestamp, a browser session id and a message.
5. Design constraints
5.1 Life span
The solution is needed as long as factors is in development and later in operation.
|Minimize costs||Long running hobby development doesn’t warrant expensive licenses or subscriptions.||Since a platform for factors is already chosen, logger targets the same platform to avoid extra costs.|
|Material||Choosing a widely used user interface standard is likely to make logger more approachable to new users.||The user interface is built using the DevExtreme component suite.|
|Web application||Web applications are accessible to everyone everywhere on all platforms.||logger is built using a technology that makes it easy to develop and deploy web applications.|
|.NET Core||Cross-platform that makes it easy to build web applications using C#.|
Supported on many affordable hosting platforms.
|logger is built using C#.|
|C#||Modern feature-rich object-oriented programming language.||logger is developed using a C# development tool.|
|Rider||Subscription-based C# development tool with the same refactoring and coding aids as JetBrains ReSharper for VisualStudio.||Imposes a monthly subscription cost, but is deemed worthwhile compared to the free VisualStudio, which requires a ReSharper subscription instead.|
|DevExtreme||Feature-rich user interface component suite that supports Material.|
Free for non-commercial use.
|SmarterASP.NET||An affordable cloud-based platform offering virtualized Windows 10 servers that support .NET Core.||Imposes a cost of an annual subscription.|
6. Design principles
|Support local testing om MacOS.||logger is developed on a Mac and deployed on a Windows server.||The data model is defined using an abstract class. One subclass that works on MacOS is instantiated when logger is run in development mode, and another subclass that only works on Windows is instantiated when logger is run in production mode.|
7. Design goals
Since no sensitive data is created or modified in logger, accountability is not an issue.
There is no applicable regulation to be compliant with.
logger can’t expose any sensitive information.
Data integrity is maintained by strict concurrency management when adding new data.
A simple user interface based on the widely acknowledged Material design ensured good usability.
The column headers support sorting to make it easier to read the log.
When running in development mode, only one instance of the application runs, and concurrency isn’t an issue.
When deployed in production, logger instantiates a shared memory buffer that is shared across all http servers instantiated by the ISS host.
To avoid multiple processes colliding when writing to the shared buffer, all updates first acquire a mutex before changing the buffer. This prevent concurrency problems that could endanger the data integrity.
To avoid exhausting the server’s memory ressources, the buffer size is limited to 32768 bytes, which corresponds to 100-300 entries.
When the buffer fills up, oldest entries are discarded to make room for new entries.
Keeping log data in memory ensure highest possible performance when displaying log data and writing new entries.
The log view only refreshes data when the server-side buffer has been updated.
Not required – performance is easily observable when using the application, and since capacity is limited, performance doesn’t degrade as more entries are added.
The buffer size is defined as a constant in the code. It can easily be increased, and a new version built and deployed in minutes.
The server shuts down logger after 20 minutes of inactivity, and any log entries in the buffer are discarded.
Since shared memory files aren’t supported by .NET Core on MacOS, the buffering logic is defined as an abstract class. When testing the application on MacOS, it instantiates a simple StringBuilder-based buffer that works well enough on MacOS.
The user interface also offers a ping command, which writes to the log in the same way as a monitored application would, demonstrating that it’s still capable of accepting and showing new entries.
The user interface offers a clear command that empties the log buffer.
8. High-level design
When the browser requests the home page from the web server, the web server (specifically IIS serving as proxy for the Kestrel server built into .NET Core on the Windows 10 server) starts a process that instantiates a PageModel to handle the incoming HTTP request.
The HttpServer startup code creates either a LocalData or GlobalData object depending on the environment. Both data classes are derived from the AbstractData class. The PageModel only knows the AbstractData class.
The PageModel parses the Index.cshtml Razor page into a pure HTML page, which is returned to the browser for rendering.
The refresh function fetches the server’s data version. If the server’s version is different from the currently rendered local version, the dxDataGrid component is ordered to reload its data from the PageModel. Then, the local version is updated to avoid unnecessary new data loading until there is actually new data on the server.
When started by the IIS/Kestrel software on the web server, the Program class starts a process that instantiates the Index class and directs incoming HTTP requests to its methods.
The initialization code in the Startup class creates either a LocalData or GlobalData object, which is passed to the Index constructor.
The LocalData class uses a StringBuilder to hold the written log entries. The StringBuilder is local to the running process, so it can’t be shared by different processes serving different browser sessions. But it works fine for debugging the application during development.
The GlobalData uses a globally SharedMemoryFile to hold the written log entries. It’s accessible from every process, ensuring that all browser sessions view and write to the same central log.
SharedMemoryFile isn’t supported on Linux, which is the primary reason for using a the simple StringBuilder in the LocalData class.
The application is designed run be fully functional when run on the developer machine. Rider is used to debug the running application during testing.
The built code is deployed directly from within Rider to an FTP location, which is mapped on the cloud-based Windows 10 server to the application’s root folder.
The web application must be stopped before deployment to avoid problems when uploading new code files.
To check the application’s readiness, it’s easiest to just open it in any browser. Furthermore, it offers a ping button that writes a log entry, which verifies full operational capability.
The cloud-based Windows server is managed via the dashboard accessible on SmarterASP.NET’s website.
The IIS server and its application pool can be stopped and restarted to stop any running browser sessions when deploying a new version.