Introduction
This article is about monitoring and presenting system resources data (such as CPU usages and Memory Load) integrating Microsoft .NET technologies and the last web tools such as HTML5, jQuery and Flot.
The presented solution can be used as a skeleton of an extend application to manage and monitor remote devices. The following picture is the overall architecture based on WCF services: each remote device exposes a WCF service hosted by a windows service and all the information from the remote devices are collected and exposed by the web application hosted by IIS.
The following implementation is monitoring only one device (the same where it is installed the web server IIS) but can be easily extended to monitor multiple devices just adding a few lines of code. The code to retrieve the system resources usage is based on a C++ COM object I wrote and here provided as dll.
Background
The code provided is packaged in a Visual Studio 2012 solution and it includes both the Windows Service Project and the Web Application project. A base knowledge of WCF, jQuery and HTML5 is required. In addition the main web page makes use of Flot, a javascript plot library for jQuery (for further information please see http://www.flotcharts.org/).
The main topic is about the configuration of the WCF services, Ajax enabled in the web and as wsHttpBinding in the windows services. To consume the data provided by the COM object SystemManager you just need to register LogthetaSystemManagement.dll on the machine you want to monitor (please see above).
Setup the solution and making the code running:
The Solution “SystemMonitor” includes two projects
- SystemManagementService: a Windows Service hosting a WCF service and collecting machine data (CPU usages and Memory load).
- SystemMonitor.WebUI: a web UI hosting a WCF service polling data from Windows services installed on remote devices (in this example, on the same machine of web server) and plotting on a web page.
To compile and make running the solution please follow the steps:
- Register the Logtheta.SystemManagement.dll COM included in the SystemManagementService project: open a shell and run regsvr32 [Path]\Logtheta.SystemManagement.dll. After that you should see the component in dcomcnfg.
- Rebuild All
- Install the Windows Service running the file InstallService.cmd included in the SystemManagementService project. This batch file installs the service and starts it. After that you have an http WCF service responding to the url configured in App.config
- Register SystemMonitor.WebUI as web application (Properties>Web>Create Virtual Directory).
- Run the solution
Using the code
public class SystemManagementService : ISystemManagementService
{
public double GetCPUUsages()
{
ISystemManager systemManager = new SystemManager();
return systemManager.GetCPUUsages();
}
public double GetMemoryUsage()
{
ISystemManager systemManager = new SystemManager();
uint availableMemory = systemManager.GetAvailableRAM();
uint totalMemory = systemManager.GetTotalRAM();
return (1 - ((double)availableMemory) / totalMemory) * 100;
}
}
This code make use of SystemManger
Interop class in Logtheta.SystemManagement.dll to retrieve CPU usages and Memory usage.
This service is wrapped in a Windows Service application to avoid installing IIS in remote device.
You can change the port where the WCF service is responding, just changing the “baseAddress” specified in the App.config:
="1.0"="utf-8"
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<services>
<service name="Logtheta.SystemManagementService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/LogthetaServices/SystemManagementService"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding"
contract="Logtheta.ISystemManagementService"/>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Please note the service is using wsHttpBinding.
Once the windows service on remote device is up and running, you can connect from the web application. In the web.config, you can find the WCF client definition:
<client>
<endpoint address="http://localhost:8000/LogthetaServices/SystemManagementService"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ISystemManagementService"
contract="SystemManagementService.ISystemManagementService"
name="SystemManagementService">
<identity>
<servicePrincipalName value="host/VaioGiuseppe" />
</identity>
</endpoint>
</client>
Please change it if needed. To present the data we need a WCF service AJAX enabled so that we can retrieve data using jQuery in JSON format:
[ServiceBehavior]
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class SystemMonitorService : ISystemMonitorService
{
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public SystemResources GetSystemResources()
{
Uri endPointUri =
new Uri("http://localhost:8000/LogthetaServices/SystemManagementService");
SystemManagementServiceClient systemManagementService =
GetSystemManagementServiceClient(endPointUri);
double cpuUsages = systemManagementService.GetCPUUsages();
double memoryUsage = systemManagementService.GetMemoryUsage();
return new SystemResources { CPUUsages = cpuUsages,
MemoryUsage = memoryUsage , Hostname = "localhost"};
}
private SystemManagementServiceClient GetSystemManagementServiceClient(Uri endPointUri)
{
Binding binding = new WSHttpBinding();
EndpointAddress endpoint = new EndpointAddress(endPointUri);
SystemManagementServiceClient client = new SystemManagementServiceClient(binding, endpoint);
return client;
}
}
Please note main method “GestSystemResources
” is decorated in order to use JSON format. If you made some changes in the remote WCF service configuration, you need to change accordingly the endPoiuntUri
variable.
Now we can call the WCF AJAX enabled service using AJAX. The file app.js in the Scripts folder (web application) contains all the code to retrieve data, to setup the Flot control and to plot the data periodically. The main code in App.js is:
function getData() {
$.ajax({
type: "GET",
url: serviceUrl,
cache: false,
data: {},
contentType: "application/json; charset=utf-8",
dataType: "text",
success: OnSuccess,
error: OnError
});
function OnSuccess(response) {
var s = JSON.parse(response);
cpuPlot.setData([cpuPlotData.buildData(s.d.CPUUsages)]);
cpuPlot.draw();
memPlot.setData([memPlotData.buildData(s.d.MemoryUsage)]);
memPlot.draw();
setTimeout(updateStatistics, updateInterval);
}
function OnError(response) {
var r = JSON.parse(response);
alert("Error");
}
};
Please note the dataType
in the AJAX call must be “text” so that you can interpret the result in the “OnSuccess” callback through JSON.parse
method.
Points of Interest
You can extend the solution to monitor multiple devices, just adding a simple SQL Server DB and Entity Framework to access to the data. You need always to install a windows service on remote machine but you can retrieve data by http even if IIS is not installed.
History