Adding Administration Facilities


Evidently, the Windows Communication Foundation provides a rich set of tools for managing Windows Communication Foundation applications. It also allows software developers to add their own tools for systems, and allows business administrators to monitor characteristics unique to a system.

For example, in the trading service solution, a natural quantity for business administrators to want to monitor is the volume of trades. Among various ways in which that quantity could be exposed for examination, adding a performance counter for trade volume to the trade recording service would allow it to be monitored using the Performance Console that is built into Windows operating systems.

To add this performance counter, or any other management facility, to a Windows Communication Foundation application, a step that is often required is that of accessing a running instance of the application via WMI. To see how to do this to add the trade volume performance counter, follow these instructions:

  1. In Visual Studio 2005, open the Program.cs file of the TradeRecordingServiceHost project in the trading service solution. After initializing the host of the trade recording service, the code in that file calls a custom IntializeCounters() method of the trading service's service type:

    public static void Main(string[] args) {     if (!(MessageQueue.Exists(queueName)))     {         MessageQueue.Create(queueName, true);     }     TradeRecorder tradeRecorder = new TradeRecorder();     using (ServiceHost host = new ServiceHost(tradeRecorder))     {         host.Open();         tradeRecorder.InitializeCounters(host.Description.Endpoints);         Console.WriteLine("The trade recording service is available.");         Console.ReadKey();     } }

  2. Examine that method, which is in the tradeRecorder.cs module of the TradeRecordingService project. It is reproduced in Listing 12.1.

    Listing 12.1. InitializeCounters() Method

    public void InitializeCounters(ServiceEndpointCollection endpoints) {     List<string> names = new List<string>();     foreach (ServiceEndpoint endpoint in endpoints)     {         names.Add(             string.Format("{0}@{1}",                 this.GetType().Name, endpoint.Address.ToString()));     }     while (true)     {         try         {            foreach (string name in names)            {                string condition = string.Format(                    "SELECT * FROM Service WHERE Name=\"{0}\"", name);                SelectQuery query = new SelectQuery(condition);                ManagementScope managementScope =                    new ManagementScope(                        @"\\.\root\ServiceModel",                        new ConnectionOptions());                ManagementObjectSearcher searcher =                    new ManagementObjectSearcher(managementScope, query);                ManagementObjectCollection instances = searcher.Get();                foreach (ManagementBaseObject instance in instances)                {                    PropertyData data =                        instance.Properties["CounterInstanceName"];                    this.volumeCounter = new PerformanceCounter(                        TradeRecorder.CounterCategoryName,                        TradeRecorder.VolumeCounterName,                        data.Value.ToString());                    this.volumeCounter.ReadOnly = false;                    this.volumeCounter.RawValue = 0;                    break;                }           }           break;      }      catch(COMException)      {      }   }   if(this.volumeCounter != null)   {       Console.WriteLine("Volume counter initialized.");   }   Console.WriteLine("Counters initialized."); }

    The code for the method assembles a list of the names for the service's endpoints:

    foreach (ServiceEndpoint endpoint in endpoints)     {         names.Add(             string.Format("{0}@{1}",                 this.GetType().Name, endpoint.Address.ToString()));     }

    Then it uses those names to retrieve the WMI objects corresponding to the endpoints of the running instance of the service:

    string condition = string.Format(                     "SELECT * FROM Service WHERE Name=\"{0}\"", name);                 SelectQuery query = new SelectQuery(condition);                 ManagementScope managementScope =                     new ManagementScope(                         @"\\.\root\ServiceModel",                         new ConnectionOptions());                 ManagementObjectSearcher searcher =                     new ManagementObjectSearcher(managementScope, query);                 ManagementObjectCollection instances = searcher.Get();

    Those objects are then used to add the trade volume counter to that instance of the service:

    foreach (ManagementBaseObject instance in instances) {     PropertyData data =         instance.Properties["CounterInstanceName"];     this.volumeCounter = new PerformanceCounter(         TradeRecorder.CounterCategoryName,         TradeRecorder.VolumeCounterName,         data.Value.ToString());     this.volumeCounter.ReadOnly = false;     this.volumeCounter.RawValue = 0;     break; }

  3. Look at the RecordTrades() method of the trade recording service's service type, which is in the same module:

    void ITradeRecorder.RecordTrades(Trade[] trades) {     Console.WriteLine("Recording trade ...");     return;     lock (this)     {         while (this.volumeCounter == null)         {             Thread.Sleep(100);         }     }     foreach(Trade trade in trades)     {         this.tradeCount+=((trade.Count != null)?trade.Count.Value:0);         this.volumeCounter.RawValue = this.tradeCount;         Console.WriteLine(string.Format("Recorded trade for {0}",trade));     } }

    The method updates the trading volume performance counter with the value of each trade the service records. Currently, however, this return statement,

    Console.WriteLine("Recording trade ..."); return;

    causes the method to exit prematurely. The reason is that the performance counter would not have been available until the WMI provider was activated for the service according to the instructions given previously. Only after the WMI provider was activated for the service would the InitializeCounters() method have been able to succeed in retrieving the running instance of the service to which to add the performance counter.

  4. Because the WMI provider has now been activated for the service, comment out the return statement:

    Console.WriteLine("Recording trade ..."); //return;

  5. Choose Debug, Start Debugging from the menus.

  6. Wait until there is activity in the console window of the trade recording service host.

  7. Choose Run from the Windows Start menu; then enter

    perfmon

    and click OK.

  8. In the Performance console, right-click on the graph on the right side, and choose Add Counters from the context menu, as shown in Figure 12.73.

  9. Select tradeRecording from the Performance Object list, TRadeRecording being the name provided by the InitializeCounters() method for a custom performance counter category for the trade volume counter. As shown in Figure 12.82, the Trade Volume counter is shown as being available for the running instance of the trade recording service.

    Figure 12.82. Adding the Trade Volume performance counter.

  10. Click the Add button on the Add Counters dialog, and then the Close button.

  11. Enter a keystroke into the console application window of the client application.

  12. Observe, in the Performance Console, the movement of the custom trade volume performance counter, as depicted in Figure 12.83.

    Figure 12.83. Monitoring the trade volume performance counter.

  13. In Visual Studio 2005, stop debugging the trading service solution.

  14. In the Performance Console, choose File, Exit from the menus to close the console.




Presenting Microsoft Communication Foundation. Hands-on.
Microsoft Windows Communication Foundation: Hands-on
ISBN: 0672328771
EAN: 2147483647
Year: 2006
Pages: 132

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net