Monday, August 3, 2015

Azure Application Insights: Know Your Users

(The layout of this blog post is terrible, I know. Blogger.com just seems not to be suitable for pictured step-by-step guides. Or at least not with the amount of effort that I was willing to spend.)

When I was looking for a way to collect voluntary usage statistics for a desktop App, I stumbled upon Application Insights, which is a Microsoft Azure service that is currently in preview. There is an introduction and further readings on MSDN. However, I will give a short summary of which steps to take to set AppInsights up and what the results will look like so you can get a quick glance at what you can expect.

Feature Summary


FeatureUse cases
Track pagesTrack which pages (web), windows (desktop) or screens (mobile) are visited how often by your users and what they load time was.
Track sessionsTrack all active server sessions (web) or running app instances (desktop and mobile).
Track eventsTrack some meaningful events for you, such as clicking of a certain button, choosing a certain option or executing a certain command.
Track metricsTrack how often something in your app happens, how many datasets your users manage with your app or some other averages.
Track web requestsWeb only: Track requests to other web services and how long they take.
Track crashes and tracesTrack detailed information about crashes, exceptions or some other unexpected situation, including full call stacks and many other properties, such as geographical area, operating system, and more.
Custom propertiesAttach custom properties of any kind either to the context that all metrics are collected in, or for each telemetry item itself.
Time rangeSpecify the time range that should be included in the graphs on the App Insights dashboard.
AlertsSpecify alerts that trigger when certain conditions are met (such as when more than 100 exceptions are logged within 15 minutes). This seems to be useful for web services only.
Data exportYou can download data for any kind of telemetry item as an Excel spreadsheet.
Continuous exportIf the one-time export is not enough, you can continuously export to an Azure storage space. This seems to be possible in JSON format only, so you need some hand-crafted code to process the data any further. See https://azure.microsoft.com/en-us/documentation/articles/app-insights-export-telemetry/ for more details.


Requirements


Application Insights runs on Microsoft Azure, so an Azure subscription is a prerequisite. You can use it either on mobile apps (iOS and Android), web sites and services (ASP.NET, WCF, J2EE) or desktop apps (either Classic or Windows Store Apps - in other words: anything written in .NET). AppInsights is free for a limited number of datasets and will cost about $25,- for standard and $100,- for premium accounts. See the pricing table.

Getting Started


For the impatient, there is a TL;DR version of it at the bottom.

To get started, you need to log into your Azure account at the new Azure Portal or register for a new account, and add Application Insights.
When you first log in, it looks something like this:

An empty Azure Portal start screen

The design of the home screen is kept in the tiled style, just like the Windows 8 start page or Windows Phone home screens. I personally find this pretty neat and clear.

You can add Application Insights by hitting the big fat + in the upper left corner and then browse to [Developer Services > Application Insights].

A shortcut on the "Home Screen" will be created automatically for you. But before, you will have to set up your new instance of Application Insights.
Add Application Insights to your Azure account
First you have to select the Application Type. I think this does not influence the capabilities of the instance at all - instead only a few default settings and pinned elements on the dashboard will differ. I find the names a bit misleading, personally, since there is no clear mapping from the name to the underlying technology. E.g. I use the type "Windows Store Application" for a classic desktop application written in C# and WPF.

I have no idea what a Resource Group is, but rumor has it you can find out more here.

If you have multiple Subscriptions you can select the one that should be billed for this AppInsights instance here.

Currently, there is only the "Central US" Location. I guess, if App Insights will find it's users, there will be more locations added.
Set up Application Insights - Step 1 of 2

There is now a new icon on your home screen: "tutorial APPLICATIONINSIGHTS" (I have no clue why the instance name is in lowercase and the service name is in ALL CAPS).

Click this new icon and you will finally find your Application Insights.

Set up Application Insights - Step 1 of 2

You are now on the usage statistics dashboard, which will be the starting point for all analysis. The dashboard is fully configurable and is populated with some default widgets. These, too, are aligned in tiles. The most prominent default tile is the Timeline. You can watch the trend in numbers of metric items of the past week and you will see new items coming in live. All views in Application Insights are viewing live data, which is especially useful for websites I'd imagine.

If you are interested in statistics of a longer time range, let's say half a year, you can easily configure that via the "Time Range" tool button.

I will describe more features after we got some data into our dashboard.

Set up Application Insights - Step 1 of 2

The last step in the Azure Portal before some coding is to copy the Instrumentation Key, which is our unique identifier that we need to provide to AppInsight's Telemetry API that is used to collect and send telemetry data into our Azure AppInsights dashboard.

Set up Application Insights - Step 1 of 2

Collecting data from a desktop app

For our testing purposes, we will create a simple WPF application with three buttons.
Our Test Application
We will track three different telemetry items:
  • Click of Button 1, including the total number of clicks on this button in the running session.
  • Click of Button 2, including the exact timestamp of the click.
  • A crash.
All items share some context information that is initialized in app startup. I chose to set the User ID to a fixed user called "tutorial1" and add a custom property named "app_start" that includes the time when the app was started.
To start collecting data, we need to utilize AppInsight's telemetry API. We can install the required assemblies via NuGet by right-clicking our project in the Solution Explorer, then selecting "Manage NuGet Packages" and install the package named Microsoft.ApplicationInsights (Application Insights Core API).

The class Microsoft.ApplicationInsights.TelemetryClient is the core class that we need to collect data. First, we initialize the Instrumentation Key and the context in MainWindow's ctor:

private TelemetryClient tc = new TelemetryClient();

public MainWindow()
{
    tc.InstrumentationKey = "aea76edd-a119-4ce3-bba0-2a31ec66880d";
    tc.Context.User.Id = "tutorial1";
    tc.Context.Properties["app_start"] = DateTime.Now.ToString(CultureInfo.InvariantCulture.DateTimeFormat);

    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

    InitializeComponent();
}

Then, we will add three event handlers for the aforementioned events that we would like to track:

private int button1Counter = 0;

private void button1_Click(object sender, RoutedEventArgs e)
{
    var ev = new EventTelemetry("button1");
    ev.Properties["click_counter"] = (++button1Counter).ToString();
    tc.TrackEvent(ev);
    tc.Flush();
}

private void button2_Click(object sender, RoutedEventArgs e)
{
    var ev = new EventTelemetry("button2");
    ev.Properties["click_time"] = DateTime.Now.ToString(CultureInfo.InvariantCulture.DateTimeFormat);
    tc.TrackEvent(ev);
    tc.Flush();
}

private void buttonCrash_Click(object sender, RoutedEventArgs e)
{
    object foo = null;
    string crash = foo.ToString();
}

private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    if (e.ExceptionObject is Exception) {
        tc.TrackException(new ExceptionTelemetry((Exception) e.ExceptionObject));
        tc.Flush();
    }
}

That's all!
Now we can start this nice little demo app and mash the buttons a few times. Remember that the app will actually crash when you click on Crash!.
When you are done playing with your app, we can head back to the Azure Portal and look at the AppInsights dashboard. As I said earlier, the data is updated live, so the newly created items should be visible immediately. If they are not, just hit "Refresh".


Watch Live Telemetry Data

Voila! There it is: One user, and four crashes - I apparently hit on "Crash!" four times. We can inspect the crashes to see more information.


Inspect crashes

You can see interesting things like how many times the crash occured, how many users where affected. If I initialized the context of the TelemetryClient properly, we could see the affected program versions, devices names and operating systems that the crash happened on. I'm sure that you can imagine that all these properties will be very interesting when trying to fix crashes in your app.

As with any telemetry items, you can even attach custom properties to the crash log, so you can include information that might be interesting in your specific app, such as the title of the active window when the crash happened or even the free disk space or things like that.

You could see these custom properties together with a few other properties that are gathered by default on the "Exception Properties" page.
Exception properties page

If you are not using an online crash logging facility already, this will really take your bug fixing to a new level!

There are similarly useful stats for your custom events that you logged when clicking the two buttons.

Custom event infos

TL;DR


See the feature list and the requirements at the top.
Then, execute these steps:
  • Create an Azure account, if you do not already have one
  • Add [Developer Services > Application Insights] in your Azure Portal
  • Copy the Instrumentation Key
  • Create a new WPF app
  • Add the package "Microsoft.ApplicationInsights" Core API via NuGet
  • Create a Microsoft.ApplicationInsights.TelemetryClient and call TrackEvent, TrackPageView, TrackException, TrackMetric, TrackRequest or TrackTrace.
  • Watch the data appear in the AppInsights dashboard

Code


You can find the full example code on GitHub.

Thursday, June 18, 2015

Hacky and Clean Programming

When I do programming, I do it in either of two "modes". Each of these modes serves a different purpose and I use them at different stages to achieve a goal. It is very important to be aware of the current stage you are in, because programming in the wrong mode can be most harmful for either productivity or code quality.

I call these two modes the "hacker mode" and the "clean mode".

Hacker mode

In "hacker mode", I try out either new technologies or architectural ideas. For example, when your current goal is to write a library to control a Bluetooth  device, I would first go into "hacker mode" and try things out and figure out what would be the most efficient and most stable way to use the raw Bluetooth API.

When hacking, I do not care for code quality. I may violate my own guidelines, use ugly casts, name variables "x", "foo" or "data". The uglier, the better. Because I will definitely throw that code away. This is a very important aspect that should not be violated. You have to be aware that you will throw it away, and you have to actually do this in the end. If what you hacked somehow does not work out, throw it away and start with a new hacking session - and throw this one away, too, once you learned the important aspects.

And if you are afraid that, when re-writing what you have hacked before, the Second System Effect (as described by Fred Brooks in The Mythical Man Month) might kick in, I can assure you that with this method I have not yet ever experienced this. I think the Second System Effect applies to larger scales only, and only when putting effort into producing high quality in the first system, too.

After I hacked away and figured out which calls must be made in which order and know the parameters for best results and found a good structure for the API and the implementation, I sit back, have a good look at it and memorize the important parts. Then I stash the code aside for later reference and mentally mark it as "To Be Deleted".

Now I can switch to "clean mode".

Clean mode

I am programming in "clean mode" when I have a good mental model of what I want to create. When I know the important key parts of implementation and have an idea how the API and the architecture should look like. Sometimes this information comes from a hacking session. Sometimes it is just there because I have been thinking about the problem for days, months or even years and now finally decided that everything is clear and can be put into code.

Most of the time, when programming in clean mode, I am doing DDD - Documentation Driven Development. Don't worry, this is not the new hip paradigm that you missed. It's essentially TDD, but I am writing the documentation of the code even before writing the tests.

Most important: The Docs

One major argument why TDD is cool is because you get "a feeling how your code works out when it is put into actual use". The same argument goes for writing docs. When writing docs, I always try to state the important details, not the obvious. When thinking about the non-obvious, you will learn whether the overall design is slick, or does have a few rough edges. With docs and tests combined, you can be pretty sure that the design is sound and that it works out well in practice.

There are a few, easy rules to follow when writing docs. This is especially important when writing them before the actual implementation.

First, it must be clear what the core function of the element you are documenting is. If there is not one core function, but multiple tasks  that are accomplished, you are most likely doing it wrong. Describe the core function of the element in one sentence, i.e. in a @brief.

Second, state the preconditions that must be met to use the element. The less preconditions you can name, the better. If there are no preconditions that are not enforced by the type system, you are doing it right. If the type system is not strong enough to express the constraints of the input parameters, document them in detail. The rumor has it that Haskell has an awesome type system, but unfortunately I have had not yet a chance to use it for productive work.

Third, and maybe most important for maintenance, state the side effects that may happen and which conditions they may likely happen under. If you are a really good programmer, you are writing functional code and can skip this part. You simply do not have side-effects then.

Additionally to these, the standard rules obviously apply: Describing each parameter in detail, possible exceptions thrown, how the return value has to be interpreted, etc.

While I do this, I always have two aspects in mind:
1. What actual use does the element have for a potential user and which goals would he target?
2. How will I possibly implement this element?

And it is very important not to get distracted by the implementation and create a bad API that does not resemble the tasks that a user of the class want it to accomplish, but instead just wraps the underlying technology. But it is also important to not create APIs that can not possibly be implemented in any reasonable way, or the performance will suffer considerably. You should avoid leaky abstractions for (nearly) all costs, but there is often a limit to this. (This is often worth prototyping in hacky mode.)

When I am done writing the docs, I begin writing the tests and see how my idea of how the API might be put to use actually performs. I use the docs that I have written and the side-effects and corner-cases that I have described to derive test cases and therefore get a pretty decent coverage.

I often draw some rough pseudo-UML to visualize the dependencies and relationships.

When actually implementing the functionality, I apply all the lessons that you have learned from Clean Code. I am aware of the docs and update them, when necessary. This may also lead to redesign the API and therefore the tests. I am consciously taking the risk that implementation details that do not fit into the API are costly, because I have experienced it many times that this approach is worth it, since it results in well architectured, maintainable, clean and most importantly easy to use code.

Final notes

As stated in the beginning, it is most important to distinguish these two modes of programming and apply the correct one in each situation. Also, I would advice against using a mixture of both. Do not write hacky code in a clean code base and do not write clean code while hacking. It is just not worth it, because you either harm your code bases quality or are less productive than you could.

Only do hacking in fresh, isolated code bases that are drilled down to the minimal. This of course requires you to isolate parts and think of good, small components to build your software in, which is valuable in itself.

Monday, May 18, 2015

The Software Industry is standing in it's own way

The Software Industry is driven by Programming. Without programming, there would not be software, obviously.
The easier and faster programming will get, the better will the software industry deliver innovations, maintain their cash cows, gain customers, make revenue.
But then why is programming so hard? Why does it cost so much and why is it so often done so badly?

Learning a Programming Language is hard


Ever tried to explain to some non-programmer that has never seen or written source-code before how an application or website is built?

They have no clue, not even the slightest, what "programming" really is. In contrast to other complex fields such as architecture, brain-surgery, chemistry or law, the majority of people does not know how programming in principal works.

But they could be excellent programmers, perhaps. They are maybe just not into programming because they are not attracted to fiddling with source files, wading through compiler errors, gathering information from sources spread across the internet and writing expressions that are meaningless to them. (Ever thought about why it is called a "class", anyone?)

And then, there are so many!


Not only non-programmers need to learn a programming language. Especially when seeking a new job after programming for like 10 years for the same company, you will notice that the industry is split afar. Are you a C++ guru? Good luck finding a job if you do not have any embedded companies nearby. Are you a PHP veteran? You will be out of luck if you do not have any web companies in your reach. Wikipedia lists 122 programming languages.

Even if only counting the ones widely in use, you come up with quite a number: Java, C#, C++, C, Objective C, Visual Basic, PHP, Perl, Ruby, Python, JavaScript, COBOL (ugh!), FORTRAN (ugh, too), Object Pascal/Delphi.

And then there are the newcomers and niche-languages, maybe in use by your favorite start-up you would like to apply at: D, TypeScript, CoffeeScript, Clojure, Scala, F#, Go, Rust, Dart, Haskell, Lisp, Lua, Swift, Tcl, Erlang.

Not enough? Then here is a small excerpt from popular domain specific languages: SQL and PL/SQL (in different flavors from different DBMSes), CSS, XUL (for Mozilla Firefox), Regular Expressions, UNIX Shell Script, PowerShell, Matlab, XSLT, UML.

And knowing one of them is not enough


Making it even worse, you often have to use many of them to build a software, especially when doing web development. You need a backend language like Ruby (with the domain-specific framework "on Rails"), a domain specific language inside the UI template. Then you need to write the HTML skeleton and the CSS styles. Most often, you need to write some raw SQL, too. This sums up to SIX languages in parallel use. Have you ever heard bout context switches being harmful for work productivity?

At the company I am currently working for, we are looking for C++ programmers. We create software in the business domain. That doesn't suit too well - most applicants have a very, very technical background with either Matlab or embedded engineering as their main focus. UI and usability is often not important in these fields. Office software meets quite different requirements than mathematical or electrical stuff, that's why low-level programmers are usually not suited for the work we are doing.

But we can not easily hire a, say, web UI and usability expert with HTML, JavaScript and Ruby background. Because learning C++ is very hard, and if you do not already know it, the chance of writing buggy code is very high. So the only way to hire a programmer is either find a good C++ programmer that is not a number cruncher, or we hire a programmer without C++ background and train them before they take on actual work, which is very costly.

And even with the same Language, Things can be different


And even if you are an awesome programmer in, let's say Ruby, this does not get you far. What if the company you want to work for uses a framework that you have never used before and is totally different? Even when you create the same stuff with it. Try to learn Ruby on Rails? That's nearly as much as learning a new programming language. Try to learn Qt when you already know MFC or vice versa? Even harder, since you will fall back to your old habit and create shabby stuff that will not fit the new environment.

How silly this is


Why do we need so many languages, most of them only justified by irrational reasons? Why can't we have only a few programming languages that differ in their fundamental properties and are used in all domains that require these properties? One object-oriented language, one functional language, one declarative language, one data-definition language. Or maybe even only one programming language in different flavors or in different "modes".

Each language's quality would rise, their community would be bigger, making it easier to find help online. You could actually use the language that you learned at your university in your job. The evolution of the language would be quicker, since there will be more parties interested in it. Sure, this will bring up other problems, such as concurrent ideas and visions for the language. But these can be addressed. Or circumvented, if a single organization is responsible for the language. This has worked in the past, for example with UML, Java, C#, OpenGL.

The software industry is strange. No other industry would allow so many different approaches to the same problems at hand, because it does imply a huge financial risk for each company in the industry. The software industry might be just too wealthy or too ignorant to see and address these issues with programming. I think the main cause for the current status quo is because it is so easy to build a new language or a new framework. And the inner drive of many programmers to create "their own baby" instead of making someone else's product better and use it for your own purposes. That's in some way related with the complexity and diversity of current programming languages. Often forks, clones or similar projects are started because the initiator is used to a different programming language. Why would anyone port SQLite to CSharp, if you can access SQLite's C API from within C#?