Introduction
Hello dear reader, have been such a long time. As usual the amount of work at the office I’ve to do on a daily basis, side projects, the occasional colleague asking for help, and last but not least, family life, made almost impossible to write any post on this blog lately, luckily today I’ve found a bit of spare time to do so and I hope you like this blog post.
So, what’s Gibraltar? To my understanding, Gibraltar is an step forward to create components that are categorized as those that work as cross cutting concerns in an application, in plain English that would mean that those components are part of the application but do not belong to the business domain of it.
A simple example could be Logging, or User Auditing in a CRM application, because the reason of existence of a CRM application is not to perform any of those tasks, but to handle your contacts, calendars, events and so on.
This is one of the keys concepts when doing AOP programming.
what are the MAIN components of gibraltar
Basically Gibraltar is based on two components:
- Gibraltar Agent
This is a .Net library that provides the API to perform most of the job needed. It’s the principal component, without this you wouldn’t be able to collect the precious information from your application. - Gibraltar Analyst
This is a user friendly standalone application used to analyze the data sent by your application. Provides several built-in tools to display/filter/sort/group the data generated by the Gibraltar Agent.
There’s a third optional component, the Gibraltar Hub, which is a service to host in a centralized place all the data generated by your applications.
For an in-deep look of what those three components are all about, I recommend you to check the following resources:
Getting Started Guide
Gibraltar Architecture
Gibraltar Hub FAQ
Gibraltar Try It FAQ
The sample app
This is a fictitious application that allows you to manage your contacts from several sources like GMail, Facebook and so on.
As you can see, we’ve a simple IFeature interface that is used by concrete classes to be recognized in the system as a feature of it. This interface has a Execute method which is used by the UI to make the feature to run.
I’ve created a base class (FeatureBase) to simplify the implementation of some of the interface members.
Below I’ll show you the code of this class and of the DisplayContactsFromGMail class, the other two classes are pretty identical and do not make much sense to repeat myself over and over.
public abstract class FeatureBase : IFeature
{
public abstract Guid Id { get; }
public string Name
{
get { return GetType().Name; }
}
public abstract string Description { get; }
public virtual void Execute()
{
MessageBox.Show(@"Executing Feature " + Name);
}
}
public class DisplayContactsFromGMail : FeatureBase
{
public override Guid Id
{
get { return Guid.Parse("614DFAA4-70F7-4F5F-82D4-9598C0F39F60"); }
}
public override string Description
{
get { return "Display Contacts from your GMail Account"; }
}
}
As you can see, very simple classes according with the scope of this post.
The second part of the application is the component in charge of discovering and providing the features. It could be implement in many ways, for instance by using a DI tool like StructureMap or Autofac. I choose a simple reflection approach, that is, look at the IFeature assembly for types implementing this interface.
The FeatureCatalog is implemented as follows:
public class FeatureCatalog : IFeatureCatalog
{
private readonly IEnumerable<IFeature> _features;
public FeatureCatalog()
{
_features = typeof(FeatureCatalog)
.Assembly
.GetTypes()
.Where(x => x.IsPublic)
.Where(x => x.IsClass)
.Where(x => !x.IsAbstract)
.Where(x => typeof(IFeature).IsAssignableFrom(x))
.Select(Activator.CreateInstance)
.Cast<IFeature>()
.ToList();
}
public IEnumerable<IFeature> Features
{
get { return _features; }
}
}
Did I said I really love LINQ? :)
Ok, now we’ve everything in place let’s create a simple UI to use the implemented features; if you think this the worst UI you’ve seen in you whole life, please bear with me, UI design is not one of my strong skills :)We’ll load the list of features in the listbox control, and the button at the right side will just execute the selected feature.
Let’s take a look at the code used to load the features into the listbox and the code of the button click event.
private void Form1_Load(object sender, EventArgs e)
{
FeaturesList.DataSource = new FeatureCatalog().Features;
}
private void ExecuteFeatureButton_Click(object sender, EventArgs e)
{
((IFeature) FeaturesList.SelectedItem).Execute();
}
Pretty simple uh? Lets see how the app behaves when executing the DisplayContactsFromGMail feature.
Selecting other features and clicking the button at the right side produces the same effect (display a messagebox with a generic description).
Introducing Gibraltar
Now you may be wondering, “WTF? I’ve not seen any Gibraltar usage anywhere!!”.
I know, I know…please be patience.
Well, let’s say your boss tells you that the users are complaining about the large list of items being displayed on the listbox (menu, tabs or any other method you real app would use to show the available features). Your boss ask you to determine which are the most used features from the application and display the top X in your original control (the listbox) and the rest somewhere else.
So, the first thing you’ve to do is to update the app to track the features usage and determine which are the most used in a given period of time and deploy this new version of the app to your clients, after a few days of monitoring you’ll know what to do and what features put apart.
We could use several different options here, like Dynamic Proxy, Postsharp for IL Weaving, and a few more. But what we can’t do is obviously start manually changing one class at a time to do this, that would be a daunting,tedious and error prone task.
The question is…where should we inject this? In the button click handler…for the scope of this article would probably do the trick, but I suppose in a real project a feature X could call to another feature from the catalog.
So if the catalog is the entry point to retrieve features, then the catalog is the place where this new code should be implemented.
What I’m going to do is to create an IFeature implementation that will act as a wrapper of the real implementations. Each IFeature member implemented in this wrapper will simply forward the call to the real feature undercover, excepting the Execute method where I’m going to record the the feature usage and after that the wrapper will continue with the execution flow.
The usage recording will be performed in a helper class where the Gibraltar related code will be dropped.
Gibraltar besides the normal logging of messages it has something called Metrics, that as its name implies, is specially designed to this kind of scenarios where we need to measure certain aspect of our applications, for this scenario, we will sum the number of times a feature is used, another could be determine what’s the average number of emails our users sent per day and so on.
Is time to modify our application to include the required Gibraltar configuration settings and references…but don’t worry, this step is the easiest one (and the most fun of all of them).
First of all, you’ll need to download and install the Gibraltar bits from here.
Once you have everything in place, go and execute the Gibraltar Analyst program. Bellow are the steps required to enable Gibraltar in your app:
- Tools / Add Gibraltar to an Application.

- Click on the “…” button and navigate and select your project file and click the “Open” button in the window dialog.

- A set of options will get enabled on this screen, choose “Add the Gibraltar Agent to this Application”.
- The next step will ask you how do you want that the Agent categorize your Application, just pick up the option “Automatically Determine Options”.
- In the step “How should session data be reported to you?” we will choose to use the Gibraltar Hub just for fun, you can leave the other options unchecked.
- Now in this step it will ask you for an account name or the settings of your private hub service. We will choose to provide an account name for our hub service. You can get a 30 days renewable trial of the hub service from the Gibraltar web page here. Just check the options you see below, follow the instructions and in a matter of minutes you’ll have a hub and the client side tooling required to get your app up and running.

Once you’ve registered your hub service trial, introduce the name of your service in the input box and you’re almost ready to go.
- This step is about configuring how do you like to sent your sessions data, I just leave the suggested options checked.

- And that’s all.
Once you perform the steps I outlined above, your project will reload itself with the references and all you need to start integrating your application with Gibraltar.
Now that you’ve configured your project to work together with the Gibraltar Agent. It’s time to configure your Gibraltar Analyst to fetch the generated data from the Gibraltar Hub.
And that’s all folks, you can start fetching data from your hub and view it locally in the Analyst client.
Let’s continue with the implementation of our wrapper.
using System;
using ContactsManager.Metrics;
using Gibraltar.Agent;
namespace ContactsManager.Features
{
public class FeatureWrapper : IFeature
{
private readonly IFeature _feature;
public FeatureWrapper(IFeature feature)
{
_feature = feature;
}
public string Name
{
get { return _feature.Name; }
}
public Guid Id
{
get { return _feature.Id; }
}
public string Description
{
get { return _feature.Description; }
}
public void Execute()
{
FeatureUsageRecorder.Record(_feature, 1);
Log.Information("Contacts Manager", "Feature Usage", "Feature {0} executed", _feature.Name);
try
{
_feature.Execute();
}
catch (Exception ex)
{
Log.Error(ex, "Contacts Manager", "{0} Error {1}", _feature.Name,ex.ToString());
throw;
}
}
}
}
As you can see, it forwards the calls to the real feature (_feature member), and when it gets the time to call to Execute, it uses the FeatureUsageRecorder static class and records this action, logs entrance to the method, it continues by calling the Execute method of the underlying feature, and it case of failure logs the exception.
Now we need to modify the catalog to wrap the features using this new class.
public class FeatureCatalog : IFeatureCatalog
{
private readonly IEnumerable<IFeature> _features;
public FeatureCatalog()
{
_features = typeof(FeatureCatalog)
.Assembly
.GetTypes()
.Where(x => x.IsPublic)
.Where(x => x.IsClass)
.Where(x => !x.IsAbstract)
.Where(x => typeof(IFeature).IsAssignableFrom(x))
.Where(x => !typeof(FeatureWrapper).IsAssignableFrom(x))
.Select(Activator.CreateInstance)
.Cast<IFeature>()
.Select(x => new FeatureWrapper(x))
.ToList();
}
public IEnumerable<IFeature> Features
{
get { return _features; }
}
}
As you can see there, I’m excluding from the assembly scanning to the FeatureWrapper class, and once the IFeature implementations had been instantiated, I’m wrapping them all into the FeatureWrapper class just before calling to ToList in the IEnumerable. This ensure us that the application will still work as usual and that the features are not aware of the fact that we are generating metrics when our clients make use of them.
And what everyone was waiting, the code for the FeatureUsageRecorder class (including imported namespaces):
using ContactsManager.Features;
using Gibraltar.Agent.Metrics;
namespace ContactsManager.Metrics
{
public static class FeatureUsageRecorder
{
private const string MetricKey = "Feature name";
private const string MetricDataObjectType = "ContactsManager";
private const string CategoryName = "Features";
private const string MetricDescription = "Number of times this feature has been used.";
private const string UnitCaption = "Number of Calls";
private const string Caption = "Usage";
private const string CounterName = "Contacts Manager Feature Usage";
private static readonly EventMetricDefinition _featureUsageMetric;
static FeatureUsageRecorder ()
{
if (!EventMetricDefinition.TryGetValue(MetricDataObjectType, CategoryName, CounterName, out _featureUsageMetric))
{
_featureUsageMetric = new EventMetricDefinition(MetricDataObjectType, CategoryName, CounterName);
_featureUsageMetric.AddValue(MetricKey, typeof(int), SummaryFunction.Sum, UnitCaption, Caption,
MetricDescription);
EventMetricDefinition.Register(ref _featureUsageMetric);
}
}
public static void Record(IFeature feature, int count)
{
var metricEntry = EventMetric.Register(_featureUsageMetric, feature.Name);
var metricSample = metricEntry.CreateSample();
metricSample.SetValue(MetricKey, count);
metricSample.Write();
}
}
}
As you can see from the code above, Gibraltar lets you write custom Metrics and defining the fields that this metric will contain.
We are defining a “Contacts Manager Feature Usage” metric under certain category (“Features”), this metric belongs to the “ContactsManager” metric data object type. All of this are arbitrary names, you could choose whatever fits your needs.
Now this metric would be pointless if does not measure anything, so we register a unit that will be keyed with the value of the const MetricKey (“Feature name”), will have a int type, the summary function is defined as a sum of their column, and so on.
In the Record method, we take in a IFeature instance and just store the number of times this feature is used, currently hardcoded to 1, I thought it could be a good idea to call this method each X times a certain feature is used instead of calling it as soon as the feature is used as it is right now.
Now lets execute the application and start clicking the button many times for each feature.
Now close the application and check the Gibraltar Analyst application.
What you will see is something like this:
That’s an extensible and user friendly view of the log entries generated by our application (remember those Log.Information calls from the FeatureWrapper class??). Also this screen provides with filters in order to remove all the collected data that you don’t want to see.
What about our metrics, after all, that was the whole purpose of using Gibraltar. In this screen click onto the “New View” option at the top. You’ll see a pop-up like this one:
Please choose the “New Chart” option, later you can play with the other options.
That will open the metric reporting designer. From the threeview in the left side, expand the content under Metrics/Feature, drag and drop the item named “Contact Manager Feature Usage”:
After performing that command, you’ll get a dialog to define your report, choose the options I show you in the next screenshot:
Click “Ok” and you’ll get the following report:
Final thoughts
For the record, Gibraltar comes with a set of built-in aspects (Postsharp attributes) that somehow, make even easier to work with it (GTrace, GTraceField, and so on). You can read about them here.
I didn’t use it those aspects because they require Postsharp in place for the IL weaving and that would complicated even more the infrastructure code required to run the sample app, and also my experience tells me that Postsharp will work only if you are in control of the application (that means, the source code)…the approach I used here would work in a environment where the features are loaded using a plugin architecture.
You can download the sample app from here.
See you soon.


1 comment:
Hi Jamie,
Thanks for this detailed post introducing logging and metrics with Gibraltar! I think your readers will appreciate your conversational style and step-by-step approach.
Cheers,
Jay Cincotta
Gibraltar Software
Post a Comment