Monday, April 20, 2009

Silverlight Performance Monitor

With the up and coming release of Silverlight 3 I figured it was time to give Silverlight 2 a shot. One of the issues that my company strives for is up time for both servers and applications so I figured what better way to dig in than a performance monitoring control. So far its up to proof of concept and will hopefully have the final control soon. As this is my first attempt at silverlight feel free to comment.

The first issue I decided to tackle was how can I get Silverlight to read performance counters on a server. Having done this type of control before with AJAX I figured my best bet was to use the System Diagnostics PerformanceCounter class. The only issue was that because Silverlight doesn't run serverside it can not access a class like this, so it was back to javascript and AJAX.

From here I decided to see how Silverlight would act under a looping structure. To do this I used the javascript code below.

var dtPoint;

function
addToGraph(args, context) {

var perfGraph = document.getElementById('TestControl');

WebForm_DoCallback('TestControl', args, addDataPoint, context, ProcessCallBackError, true);

perfGraph.content.Graph.AddDataPoint(dtPoint);
//comback around after 1 second
window.setTimeout("addToGraph()", 1000);

}

function addDataPoint(response, context) {
dtpoint = response;
}

The WebFrom_DoCallback function allowed me to access my serverside code and run the performance monitoring code I needed.

The next issue was the performance monitor piece itself. Since the performance monitor object needs to be alive from the moment the page starts I needed create it at page_load and store it in Session. There are better ways of handling this but for now this works.


PerformanceCounter CpuCounter

{
get
{
return (Session["perfCPU"] as PerformanceCounter);
}
set
{
Session["perfCPU"] = value;
}
}

CpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total", "ServerName");

Also to work with the Callback function your server control needs to implement
ICallbackEventHandler. This will force you to create a method and a function. The more important one right now is
GetCallbackResult(). This allows you to return a string to your javascript call for use at the DOM level.

public string GetCallbackResult()
{
return CpuCounter.NextValue().ToString();
}


This completed most of my looping structure and allowed me to push counter values all the way forward to the page. Next was tackling Silverlight. For now I decided to stick to just code and not design a graphing structure. I found a set of graphs that are open source and were extremely easy to work with. The company is called Visifire and it plugs in perfectly with Visual Studio 2008. All I had to do was create two methods. One to create my graph and another to add a datapoint and make it looks as though its scrolling.

[ScriptableMember]
public void CreateChart(double startPoint)
{
Chart chart = (LayoutRoot.FindName("charPerf") as Chart);
DataSeries dataSeries = new DataSeries();
DataPoint dataPoint;

dataSeries.RenderAs = RenderAs.Line;

for (int i = 0; i < 10; i++)
{
dataPoint = new DataPoint();
dataPoint.YValue = (startPoint <>dataPoint = new DataPoint();
dataPoint.YValue = startPoint;
dataPoint.XValue = 10;
dataSeries.DataPoints.Add(dataPoint);
chart.Series.Add(dataSeries);
}

[ScriptableMember]
public void AddDataPoint(double pointValue)
{
DataSeries dataSeries = new DataSeries();
Chart chart = (LayoutRoot.FindName("charPerf") as Chart);
DataPoint dataPoint = new DataPoint();

if (chart.Series.Count > 0)
{
if (chart.Series[0].DataPoints.Count > 0)
{

chart.Series[0].DataPoints.RemoveAt(0);

for (int i = 0; i < 10; i++)
chart.Series[0].DataPoints[i].XValue = chart.Series[0].DataPoints[i].XValue - 1;

dataPoint.YValue = pointValue;
dataPoint.XValue = 10;
chart.Series[0].DataPoints.Add(dataPoint);
}
}
}

This completed everything I needed to get it running as a proof of concept. Soon I should have cleaner code published but until then feel free to comment.