Author Archive

We have a lot of customers using Gibraltar with the server-side Silverlight apps, but until now, you had to roll your own solution to get client-side log messages into Gibraltar.  There were options such as using NLog or CLog to forward client-side messages to Gibraltar, but we didn’t provide any out-of-the-box capability for client-side logging.

We’ve just released sample code (both source and binary) that will ultimately form the basis for built-in Silverlight and Windows Phone support in a future version of Gibraltar.  It supports Silverlight 3 & 4 as well as Windows Phone 7.x. You can use on binaries as-is (we even provide a NuGet package to make it super easy to integrate), or you can start with our implementation then tweak the code as you wish. Either way, it gives you an easy way to get a more complete picture from your Gibraltar logs today including both client- and server-side logging.

Please check out the bits and let us know what you think!

Understanding the Design
Our support for Silverlight comes in two parts: a client-side library that is a subset of the current Gibraltar.Agent shipping release, and a server-side AgentConnector that acts as the “message sink” for each Silverlight client that writes client-side messages to the Gibraltar log, which is then packaged up and pushed to the Hub and/or Analyst just as you would expect.

image

The Agent Connector is a REST-based WCF service that leverages WebActivator to automatically configure the service route, give you near-zero-config that will have you up and running in less than 5 minutes.

Log messages are continuously streamed from each client to your web application with client-side message buffering to ensure that no more than one outbound request to to the Agent Connector is active at once for each client. Server-side, each client is assigned a unique ID to make it easy to analyze multi-user behaviors and trace individual client sessions from Gibraltar Analyst.

Getting the Bits
There are two different ways you can get the code. The first is through NuGet.org. If you’re not familiar with NuGet, it is a free Visual Studio extension that manages assembly dependencies including automatic downloads and updates. The “Server” component of this design leverages NuGet to pull down Gibraltar.Agent, as well as WebActivator, so either way, you’ll want to check it out.

The second option is to download a zip file containing the same binaries included in the NuGet packages as well as the full source code, an end-to-end sample application and a ReadMe file with details on building and integrating the code.

Installing the Server Bits with NuGet
Your solution will likely have two parts, a Silverlight client app, and a Web Application. To start, you’ll want to have the NuGet Package Manager installed in VS2010. You’ll also want to have already configured the Gibraltar Agent on your web app. If you have not done so, please follow the directions on this page of our User’s Guide.

Right-click your web project, and select “Manage NuGet Packages”. In the resulting window, type “Gibraltar.Agent” into the search box in the top-right corner. You should be presented with a number of packages. Select ‘Gibraltar Agent for Silverlight – Server”. This will add the assembly references, as well as a clientaccesspolicy.xml file, to the root of your app. You can also open up the NuGet Package Console and type “Install-Package Gibraltar.Agent.Silverlight.Server”, which will accomplish the same thing.

Installing and Configuring the Client Bits with NuGet
Now right-click your Silverlight project, call up the NuGet Package Manager again, run the same search, and this time select the “Gibraltar Agent for Silverlight – Client” package. You can also open up the NuGet Package Console and type “Install-Package Gibraltar.Agent.Silverlight.Client”. After it installs the proper assemblies for your project type (the same package has the SL3, SL4, and WP7 binaries), there is one more thing you’ll need to do. You need to add the following string to the ResourceDictionary in your App.xaml file:

<system:String x:Key="GibraltarAgentServer">http://YOURSITEHERE.com/</system:String>

This value needs to be the root of your application, be it a domain, subdomain, or IIS application. This will be combined with the built-in WCF route auto-registered by the Server binaries (“/GibraltarAgentService/”, to be exact). Now, you should be able to use Gibraltar.Agent.Log just like you always have:

Log.TraceCritical("This is a critical message.");

Since multiple clients will likely be connected, the service assigns each IP address a unique integer ID, so you can easily track which messages come from which clients or have Gibraltar filter the view to only show messages from a single client. You’ll see results similar to the screenshot below:

image

Well, there you have it. Get the bits and tell us what you think. Even with this early sample, we’ve sought to make it as robust and forgiving as possible, in line with our goal to “First, Do No Harm”. Your feedback will help us extend and harden our Silverlight support and become an easy-to-use and rock-solid part of the standard distribution for a future Gibraltar version. So, if you find any issues, please do not hesitate to leave a comment and let us know.

Categories : .NET, CEIP, Logging, Silverlight
Comments (5)

A friend of mine posted to Twitter a bit ago that he was having trouble dealing with HttpCompression on Windows Azure. Specifically, only certain default MimeTypes were being compressed (like ASPX and CSS), while other important ones like JSON and SOAP were not.

During another Azure project, I also ran into an issue where logins stopped working after upgrading to Azure OS 2.X Azure SDK 1.3. It turns out that there is a bug in that release that doesn’t allow configuration inheritance for the MachineKey, and the workaround was to manipulate the server configuration in the RoleEntryPoint.

Since I’m already having to manipulate the server config to synchronize the MachineKey settings, I thought I’d whip up some code real quick to solve this problem during the same process, using the httpConpression topic on IIS.net as a guide.

If you don’t already have a RoleEntryPoint in your app… well, you should. Copy the code below into a new class file in your main application, and add a reference to Microsoft.Web.Administration.dll, as specified here. You’ll also notice Gibraltar-specific code peppered throughout… this is all that you need to get Gibraltar working on Windows Azure (as long as you’re also using the tip from my previous post as well).

(The code is long, and it’s in VB… because that’s the language this particular app was in. If you need it converted to C#, you can do so here.

UPDATE: My colleage Kendall pointed out that the role event handlers should be declared at the very beginning, and that, even though the RoleInstance’s OnStart event is called on a separate thread from the main app, it should still run the WarmUp loop on a separate thread, so that the function can return MyBase.OnStart() and exit properly. Good call.

  Imports System.Linq
  Imports Microsoft.WindowsAzure.Diagnostics
  Imports Microsoft.WindowsAzure.ServiceRuntime
  Imports Microsoft.Web.Administration
  Imports System.Threading

  Namespace Fon.Apps

  Public Class WebRole Inherits RoleEntryPoint

  Public Overrides Function OnStart() As Boolean

  ' For information on handling configuration changes
  ' see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
  AddHandler RoleEnvironment.Changing, AddressOf RoleEnvironment_Changing
  AddHandler RoleEnvironment.Stopping, AddressOf RoleEnvironment_Stopping

  Gibraltar.Agent.Log.SendSessionsOnExit = True

  Using server As New ServerManager()

  'Cycle through the sites and set the MachineKey for each one.
  For Each site In server.Sites

  Dim siteConfig = site.GetWebConfiguration()

  'Get the appSettings section
  Dim appSettings = siteConfig.GetSection("appSettings").GetCollection().ToDictionary(Function(e) DirectCast(e("key"), String), Function(e) DirectCast(e("value"), String))

  'Reconfigure the machine key
  Dim machineKeySection = siteConfig.GetSection("system.web/machineKey")
  machineKeySection.SetAttributeValue("validationKey", appSettings("validationKey"))
  machineKeySection.SetAttributeValue("validation", appSettings("validation"))
  machineKeySection.SetAttributeValue("decryptionKey", appSettings("decryptionKey"))
  machineKeySection.SetAttributeValue("decryption", appSettings("decryption"))

  Next

  'Turn on compression for JSON and SOAP.
  Dim config As Configuration = server.GetApplicationHostConfiguration()
  Dim httpCompressionSection As ConfigurationSection = config.GetSection("system.webServer/httpCompression")
  Dim dynamicTypesCollection As ConfigurationElementCollection = httpCompressionSection.GetCollection("dynamicTypes")
  
  Dim e1 As ConfigurationElement = dynamicTypesCollection.CreateElement("add")
  e1("mimeType") = "application/json"
  e1("enabled") = True
  dynamicTypesCollection.AddAt(0, e1)

  Dim e2 As ConfigurationElement = dynamicTypesCollection.CreateElement("add")
  e2("mimeType") = "application/json;charset=utf-8"
  e2("enabled") = True
  dynamicTypesCollection.AddAt(0, e2)

  Dim e3 As ConfigurationElement = dynamicTypesCollection.CreateElement("add")
  e3("mimeType") = "application/soap+xml"
  e3("enabled") = True
  dynamicTypesCollection.AddAt(0, e3)

  server.CommitChanges()

  End Using

  'Poor man's Application Warm-up here
  Tasks.Task.Factory.StartNew(Sub()
  Try
  While (True)
  Trace.WriteLine("Warming up web site...")
  Dim webClient As New Net.WebClient()
  webClient.DownloadString("http://mysite.com/WarmUp.ashx?WarmUp=True")
  Thread.Sleep(TimeSpan.FromMinutes(9))
  End While

  Catch ex As Exception
  Gibraltar.Agent.Log.RecordException(ex, "WindowsAzure.WebRole.Startup", True)

  End Try
  End Sub)

  Return MyBase.OnStart()

  End Function

  Private Sub RoleEnvironment_Stopping(sender As Object, e As RoleEnvironmentStoppingEventArgs)
  Gibraltar.Agent.Log.EndSession(Gibraltar.Agent.SessionStatus.Normal, "Azure's configuration settings have changed.")
  End Sub

  Private Sub RoleEnvironment_Changing(sender As Object, e As RoleEnvironmentChangingEventArgs)

  ' If a configuration setting is changing
  If e.Changes.Any(Function(change) TypeOf change Is RoleEnvironmentConfigurationSettingChange) Then

  ' Set e.Cancel to true to restart this role instance
  Gibraltar.Agent.Log.EndSession(Gibraltar.Agent.SessionStatus.Normal, "Azure's configuration settings have changed.")
  e.Cancel = True
  End If

  End Sub

  End Class

  End Namespace

  

You might have noticed the While loop that cycles every 9 minutes and makes a request to a specific website. Though the actual site details have been abstracted out, this is a trick that I use to keep my application “warmed up,” and is a variation on the technique used by Christian Weyer.

For the MachineKey part, you’ll also need to add the following entries to the appSettings section of each of the web.configs in your Role, being sure to replace your values where appropriate:

  <add key="decryption" value="Auto" />
  <add key="decryptionKey" value="YOURVALUEHERE" />
  <add key="validation" value="SHA1" />
  <add key="validationKey" value="YOURVALUEHERE" />

You’ll also notice that it’s also pretty easy to add additional MimeTypes to compress. Just continue to copy the pattern for any of the items you think are missing. Be sure not to add ones that don’t already exist, or you’ll likely crash your role.

Anyways, I I hope that helps some of you that are trying to resolve various Azure issues.

Comments (0)

One of the great things about coming to work for Gibraltar is learning about all of these things that I didn’t know the product could do. For example, the other day, I was asked in one of our Live Support chats about how to see the details of a web site session in progress.

Gibraltar collects a wealth of information about your running website. However, by default, you can’t analyze the data until the web server process completes.  I knew that live monitoring is one of the killer features slated for Gibraltar 3.0, but I didn’t realize that there are also very simple, workable ways to get Gibraltar data anytime you need it within the current Gibraltar 2.5 release.

As a former Gibraltar customer, when I wanted to get this data in the past, I simply recycled the AppDomain myself. I had Gibraltar configured to “autoSendSessions”, so whenever I recycled the AppPool, I’d automatically receive the latest logs.  I realize that is not the best answer for a number of reasons, but it is what worked for me, so I passed that suggesion to the customer.

A little later, our fearless leader Jay messaged me and asked why I hadn’t sent him the link to the Code Samples page, which shows how to make Gibraltar immediately send the package for the current session whenever an error is logged. Feeling a little sheepish, I admitted “Because I didn’t know we had that feature.”

It turns out, we have some pretty cool samples that do a lot of very useful things. If you haven’t had a chance to check them out yet, you should. This also got me thinking about some ways we can make our samples more visible and accessible. Stay tuned for some cool web site updates in the coming weeks.

Before I go, I wanted to suggest a slight tweak to the “Submitting Sessions on Error” sample I just pointed you to. In .NET 3.5 and later (4.0 for you VBers out there), you can take advantage of Lambda Expressions to simplify this call a little bit. The version I use looks like this:

protected void Application_Start()
{
    Log.MessageAlert += (sender, e) =>
                                {
                                    if (e.TopSeverity <= LogMessageSeverity.Error)
                                    {
                                        e.SendSession = true;
                                        e.MinimumDelay = new TimeSpan(0, 5, 0);
                                    }
                                };
}

Or for the VB folk:

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
    AddHandler Log.MessageAlert, Sub(sender1 As Object, e1 As LogMessageAlertEventArgs)
                                 If (e1.TopSeverity <= LogMessageSeverity.Error) Then
                                     e1.SendSession = True
                                     e1.MinimumDelay = New TimeSpan(0, 5, 0)
                                 End If
                             End Sub
End Sub

This is simply some neat syntactical sugar that IMO makes your code a bit easier to read. Instead of having to follow the event handler to another method, you can see how the event is handled right there, without another method signature clogging up your code. Under the covers, the compiler will create the signature as an anonymous method, and sort everything out for you. Neat, huh?

I learn something new every day around here. Hope this little tidbit makes you more productive.

Comments (1)

Hello from the newest member of the Gibraltar team!

I’m Robert McLaws, and I’m thrilled to start the new year with bang joining the development team here at Gibraltar Software.  In my previous job on the Impulse team at Stardock, I used Gibraltar to help me understand issues with my deployed software, sometimes even before my co-workers had even finished writing me an e-mail to report the problem. It has absolutely changed the way I look at software development, laid bare all of my coding mistakes, and made me a better programmer.

At Stardock, I spent most of my time working in .NET 4, and I was constantly talking to the team here at Gibraltar about ideas for the product, and ways to make the developer experience better. Between their quick product releases, and the VistaDB acquisition, they always seemed to be on the “right track” when it came to developers. They reminded me very much of how SourceGear and Eric Sink were pushing the “ISV Way” back in the early part of the 2000’s.

Over the last year, I’ve had the pleasure (and occasional frustration) of working with a lot of Microsoft’s 2010 wave of technologies, including the latest Windows Azure CTPs, and some Windows Phone 7 / Silverlight work as well.  The Gibraltar guys spent a lot of time talking with me about exciting ideas for taking Gibraltar further.  And the more we talked,  the more I realized I wanted to be part of the team that would make it happen.

Though I don’t really tote pistols to work, I jumping in with both feet lending my insight and abilities to take our products and web sites to the next level.  Initially I’ll be enhancing the community and customer support areas of our web sites.  I’m also participating in the design of product enhancements that will include some of the cool new technologies above. Stay tuned for more details in the days and weeks ahead.

I’d like to take the opportunity to say thanks to everyone here at Gibraltar, and I’m looking forward to getting to know all of our users, and to making 2011 a breakout year.

As always, we love to hear your ideas on what we can do to help our products deliver for you.  You can drop me a line directly or contact support if you’d like.  I’m also on Twitter as RobertMclaws.

Happy coding!

Categories : ISV
Comments (0)