Windows Azure MMC v2 – Diagnostic Viewer Plugins

We’ve been working during the last couple of months with Ryan Dunn and David Aiken on various things related to Windows Azure management API. One of them, released yesterday was the Windows Azure MMC v2 (read Ryan’s post about it) This version provides a significant amount of features compared to the first version.

Ryan covered pretty much of the features in this 15 minutes screencast, so I will focus on the extensibility of the Windows Azure MMC.

The Windows Azure MMC has the following extensibility points:

  • Adding a new module (i.e. a new node somewhere in the tree)
  • Adding a new diagnostic data viewer
  • Adding a new table storage viewer

One of the pieces that we enjoyed building with Sebastian (aka Iaco) was the diagnostics data analysis. This functionality allows you to work with the data generated by the Windows Azure diagnostics infrastructure and it’s built using MEF and the MVVM pattern. If you want to create your own visualizer or viewer for diagnostic data, keep reading….

How to implement a diagnostics data viewer

We used MVVM pattern throughout the MMC (how we did that is long enough to write another blog post). So implementing a diagnostics plugin means in a few words: creating a ViewModel + UserControl, decorate the ViewModel with the ViewerExport attribute, derive from ViewerViewModelBase<UserControlType> and implement OnSearchAsync and OnSearchAsyncCompleted. These are the step by step instructions to do that. Download the code here: http://snipurl.com/mmcplugin

  1. First, open Visual Studio 2008 or 2010 and create a new WPF User Control Library.

    image
  2. Add references to the following dlls (all of them located %install_dir%\WindowsAzureMMC\release)
    • MicrosoftManagementConsole.Infrastructure
    • Microsoft.Samples.WindowsAzureMmc.Model
    • Microsoft.Samples.WindowsAzureMmc.ServiceManagement
    • System.CompositionModel.Composition

      image 
  3. Right click on the project and add a new class called “SimpleAzureDiagnosticsEventViewer” and decorate it with the following attributes 

    [PartCreationPolicy(CreationPolicy.NonShared)]
    [ViewerExport("Simple Datagrid Azure Logs", ViewerType.WindowsAzureLogsViewer)]
    public class SimpleAzureDiagnosticsEventViewer
  4. Derive the class from ViewerViewModelBase<UserControl1> [1]. The viewers must implement the IViewer interface but we provide this base class that helps with some infrastructure code.

    public class SimpleAzureDiagnosticsEventViewer : ViewerViewModelBase<UserControl1>
  5. Override the OnSearchAsync and OnSearchAsyncCompleted methods

    protected override System.Collections.IEnumerable OnSearchAsync(FilterCriteria criteria)
    {
    }
  6. protected override void OnSearchAsyncCompleted(SearchCompletedEventArgs args)
    {
    }

  7. Finally use the DataProvider [1] (service injected through the base class) to perform a search on the WindowsAzure Logs and fill the EventLogEntries collection (notice the RetrieveWindowsAzureLogsData)
  8. public ObservableCollection<WindowsAzureLogData> EventLogEntries { get; set; }

    public SimpleAzureDiagnosticsEventViewer()
    {
        this.EventLogEntries = new ObservableCollection<WindowsAzureLogData>();
    }

    protected override System.Collections.IEnumerable OnSearchAsync(Microsoft.Samples.WindowsAzureMmc.Model.Diagnostics.Analysis.FilterCriteria criteria)
    {
        return this.DataProvider.RetrieveWindowsAzureLogData(criteria);
    }

    protected override void OnSearchAsyncCompleted(SearchCompletedEventArgs args)
    {
        bool noData = (args.Result == null) || (((IEnumerable<WindowsAzureLogData>)args.Result).Count<WindowsAzureLogData>() == 0);

        if (!noData)
        {
            var result = (IEnumerable<WindowsAzureLogData>)args.Result;
            foreach (var item in result)
            {
                this.EventLogEntries.Add(item);
            }
        }
    }

  9. Finally, put some XAML on the usercontrol bounded to the EventLogEntries collection. In this case we are using the WPF Toolkit datagrid. Notice the ItemsSource property bounded to EventLogEntries
  10. <UserControl x:Class="SimpleDiagnosticPlugin.UserControl1"
        xmlns="
    http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:toolkit="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
        >
        <Grid>
            <toolkit:DataGrid AutoGenerateColumns="False" Name="EventsGrid" ItemsSource="{Binding EventLogEntries}"
                                  Height="300" VerticalAlignment="Top" IsReadOnly="True">          
                <toolkit:DataGrid.Columns>
                    <toolkit:DataGridTextColumn Header="Level" Width="Auto"  Binding="{Binding LogLevel}" />
                    <toolkit:DataGridTextColumn Header="Message" Width="Auto" Binding="{Binding Message}" />
                    <toolkit:DataGridTextColumn Header="Date and Time" Width="Auto" Binding="{Binding EventDateTime}" />
                </toolkit:DataGrid.Columns>
            </toolkit:DataGrid>
        </Grid>
    </UserControl>

  11. Compile and grab the output dll and copy to %install_dir%\WindowsAzureMMC\release.
  12. If you have the MMC open, click on Refresh Plugins if not open it and browse to the diagnostics node.
    image
  13. Click on the Windows Azure Logs dropdown and the new plugin will appear. Select the new plugin and the search will start. The MMC will call the Search method of the IViewer which will end up calling OnSearchAsync with the filter defined.
     
    image  
  14. If you choose Excel this is what happens

    image 

The user experience is probably not the best, we had to make it generic enough with the usual time constraints and the MMC UX constraints. Things can be much better, hopefully in a v3.

I will leave you with some food for thought…. how hard would be to create a plugin that mixes the perf data and event logs data?

image

[1] The ViewerViewModelBase class. Plugins should derive from it.

image

[2] The IDataProvider interface. The default implementation DataProvider is a wrapper over the diagnostics API that queries the diagnostics tables

image

Download the code of this simple plugin from http://snipurl.com/mmcplugin

Published: May 13 2010

blog comments powered by Disqus