Friday, 11 March 2016

The dev-ops cycle (a tale from the trenches)

Hi, I would like to describe to you a problem which caused real pain for me and the company I work for. And then I would like to explain to you why these problems were occurring and how we kept failing to address them. And finally what was improved as a result.

Some Background (Windows Workflow)

At company x we have been using Microsoft's Windows Workflow Foundation hosted and scaled using a number of Azure Web Instances. In other words, when there is a problem with the workflows it adversely effects the end users. Pretty flawed design, but this is what we had been working with for sometime.

In general Windows Workflow is a highly effective way to manage software development. It offers a clear overview of a highly complex systems and a highly scalable run-time engine out of the box. This guy (Blake Helms) is a major fan and so is the CTO at my company.

Of course, Windows Workflow does have some peculiarities. See these excellent posts on the dreaded tight loop and managing the workflow persistence store.

A Case Study

On Thursday afternoon our web instances started bouncing wildly between 50% -100% CPU usage, our users were complaining that the site was "slow", and restarting one web instance at a time was only solving the problem temporarily. Looking through the logs it seemed that this had been going for a few days to a lesser or greater extent depending on load. The same pattern was occurring again and again each day getting worse and more noticeable - the overall CPU usage would ramp up and then ramp back down again temporarily disabling Web Instances.

Having spent some time looking at this with our normal analysis techniques it seemed that there was no problem with the workflows. Looking at the workflows coming in every couple of minutes showed that they were being processed as expected. I suggested that we see what happens when the users log off at the end of the day - hoping that we would see a clearer picture out of hours.

Accept The Problem

Dev-ops problems tend to be unpopular in organisations. Most people dislike being disturbed of course, but it is also the stress and fraught nature of such incidents which cause Developers to shy away.

I personally believe that there are huge incentives to take on real live problems, but to reap the benefits they must be seen through from start to finish. Like many things in computer science, when a problem is hard do more of it! This, I guess, is why we are seeing more developers become dev-op specialists.

The Danger

The danger with all dev-ops is that we spot the problems and find a work-around, because this gets the situation off our backs.

This behaviour can create the "dev-ops infinite loop" because the real source of the problem isn't fed back into the development process.

As I am writing this now, it sounds obvious: find the issue and make sure there is a pull request into the next release which fixes it, what's the problem?

Well, it is quite possible that you may not have considered where or how the situation came about from the very beginning. In larger organisations a particular release may have involved many people, which could mean that vital information is lost or unavailable to you. It could also be that information may have been forgotten completely due to a release cycle that is too long or too complex.

Understanding Why - Continuing The Case Study

By Friday team was starting to get desperate because the problem was not going away and we still could not understand why the problem was happening. There seemed to be no difference between out of ours and in hours. A few theories were put forward with minor bug fixes in the code, one of which was a bug which had been present in the system since nearly the first release, lets call this "Theory 1":


  • Email templates are being compiled through the Razor engine every time an email is sent. This causes the CPU usage on the Web Instance to ramp up because it is such a resource heavy operation.


If you have worked with Razor in a highly scaled system, you may have also come across this problem. A fix was developed and released over the weekend. The email Razor templates would now be pre-compiled on app startup thus reducing the load and solving the problem.

However, come Monday morning this did not calm the server instances down. Every time we ran up a new server instance the load would be OK for a time but then would start bouncing up and down giving our users a poor experience when using the site.

A Moment Of Monday Clarity

"Theory 2":

  • There is a workflow which is running which is blocking the web instance and causing the increase in CPU usage.

We had to accept on Monday that it was back to the drawing board. The workflows had been disregarded as a potential cause because the monitoring tools we had written to check the database showed that the workflows were being processed very efficiently. However, there seemed to be no other plausible explanation.

Further analysis on the "workflow instance table" in the database showed us that there were a growing number of workflows being fired of a particular type at very particular intervals. We were able to identify this by changing our workflow monitoring tools to look at the number of workflows queued of a particular type, rather than how many workflows were suspended or overdue.

The Temporary Fix

On Monday evening we were able to push a small fix which restricted the workflow in question so that it ran only in out of office hours. We hoped this would get the users and the CEO off our backs - yes it got pretty serious! But we were still not entirely clear on what the route cause of the problem was.

Finding A Lasting Solution

The final solution to the problem was eventually deduced through some more thorough detective work. The kind of detective work that is hard to do properly when under pressure.

What went into the last release that could be very resource hungry? And what could cause this hunger to increase gradually over the days that proceeded afterwards?

The answer turned out to be from a new more generic workflow which had been written to replace a number of other workflow processes. There was actually nothing wrong with what the workflow was doing. The only error that the developer had made was to fail to consider its impact when deployed "en masse" if you will. This workflow had been written by a developer who had left the company some months before. Something like this would have been tricky to predict.

Areas For Improvement

I would say that this tale lays bare some quite common problems within software organisations.

  • Before the software was released, there was no effort made to load test the solution.
  • When the release was promoted to production, there were so many changes made by so many developers over so much time that there was no "scrum master" or technical leader who knew enough about what was in the release.
  • After the release was running, the tools for monitoring the solution where not sensitive or sophisticated enough to show a larger than expected increase in server resource usage.
  • The problem went unnoticed for too long.
  • When the problem was identified, developers hoped that it would just "go away" without pursuing the problem vigorously enough.
  • Developers put too much faith in one solution working without thinking enough about developing some ideas on other solutions.
  • Nobody in the team was calm enough to look through the new feature list and suggest a feature with risks.

What has happened since this incident:
  • UAT goes through a load test before being promoted to Production.
  • Releases are kept much smaller and more frequent
  • The workflow database monitoring tools have been improved
  • We gave ourselves a kick and tried to learn as much as we can from the case.
  • The incident resolution process has been looked at.


Getting started with Python...in Windows 10

Python is increasingly popular
The testing team where I work are using it in a big way to run automation scripts. It seems to be the language of choice to teach to 17 and 18 year old's at A-Level. I was recently forced to admit that I had never written a single line of code in Python... time to change that!

Getting started
Full of enthusiasm I went to the beginners guide on the Python Wiki . Immediately there seems to have be a break in the development of the language. In 2010 Python 3 was released and it looks like some want to hang on to Python 2. Did it really break that badly? Honestly I don't know the history but it makes for a baffling first impression. Looking around it seems that somebody is recommending Python 3 for learning and then you can go back to v2... erm no thanks! Sounds terrible, I'll stick to 3. I later found the Python 2 clock, there is a  rough deprecation deadline for Python 2.7 in 2020.

Ok, so it looks like JetBrains have made a super cool IDE with a free download... oh I have to pay for this after the 30 day trial. Hmph! Not very friendly for a beginner. I thought this was a script kiddies language?

This is more like it. Now all I have to do is download the web based installer - it asks me whether I want to install Python to the Windows Path, I think yes. In the latest installer, it is not set by default so watch out for this option.

Setup successful and a nice link to the docs. Now we are getting somewhere. I then fire up my Powershell console of choice and type "python". Thanks to ticking the install to Windows Path option this works.

Now lets do the standard Hello World app. In Python 2 you would write:
print "hello world!"

In Python 3 its:

print("hello world!")

Confusing huh!

I will continue this tutorial with next time I write. I will demonstrate how to define the structures that underpin the language.

Friday, 30 October 2015

PowerShell Unit Testing with Pester 3.3

I have been working with the Pester unit testing framework at the moment, so I thought I would share some of the more interesting bits...

PowerShell returns everything from a function!

I think this is a trap every PowerShell programmer has fallen into at some point - probably at the beginning. The return statement will return everything which is not "captured" in a function. In my case the answer was to wrap some xml manipulation code in a function which casts to void so that the return statement would actually return the custom PSObject I was expecting instead of an XmlElement which was being created at some point in my code.


   [void](do-XmlManipulation $myParamater)

This was the explanation which really hit home

It helped me realise the awful truth!

Mocking

Mocking in Pester is fantastically simple, there is an object called Mock!

You simply type Mock followed by the function that you wish to mock and then return.

Mock get-MyObject {
   return { [PSCustomObject]@{ Project = "New and Exciting Project" } }
}


In this case I have returned a Powershell object with the property "Project" which is a string. For example, the code in the module may look like this:
## myRealCodeModule.psm1

$document = get-MyObject

function get-MyObject {  
   $xmlDocument = Get-Content -Path "C:\temp.xml"
      return $xmlDocument
   }
}

But the unit test will simply bypass the attempt to get the xml file and will return our object, as defined in our unit test, instead.

Unit testing powershell modules

I keep all my most important logic in PowerShell modules. Sure, I will unit test the main PowerShell script but probably this will be mostly mocking, the real meat should be found in nicely named and separated modules.

Example of testing mocked functions in the main PowerShell script:

$scriptPath = Split-Path $script:MyInvocation.MyCommand.Path
Import-Module ("{0}\migrate.ps1" -f $scriptPath) -Verbose

Describe 'Migrate' {
    Context "When calling" {
        Mock Restore-Database {
            return "OK"
        }
    }
 
 It 'Should call all mocks' {
  Assert-VerifiableMocks
 }
}

One of the strengths of modules is that they must be imported. When they are imported a snapshot is kept in the scope of the importing script. Unfortunately, that means when changing the module, the changes are not immediately reflected because a snapshot still exists against the unit test script. My particular solution is to use "remove-module". There is the recommended solution from Pester here. However, for my purposes this is overkill.


Get-Module | Remove-Module
$scriptPath = (Get-Location).Path
Import-Module ("{0}\myRealCodeModule.psm1" -f $scriptPath)


The other strength of modules is that only exported functions are exposed, which means that functions can be internalised or made "private". This is a good thing because I have more scope for writing neat, well named functions which will make my code more readable to future maintainers.

Unfortunately this is a potential barrier to unit testing effectively. Luckily Pester has the answer here as well with "InModuleScope":


   Describe 'When unit testing get-MyObject which is not exported by the module' {
      InModuleScope myRealCodeModule {
         It 'Should have called the mock' {
            
            Mock get-MyObject {
               return { [PSCustomObject]@{ Project = "New and Exciting Project" } }
            }
            
            my-MainExportedAndThereforePublicFunction

            Assert-MockCalled get-MyObject -Times 1
         }
      }
   }




For a getting started guide: see this excellent blog

Monday, 12 October 2015

ES6 or JS2015 is finally here!

Short post this time. I have been away from the Javascripot space for a little while, but now I have started a new NodeJS project.

I am incredibly excited about the wide spread adoption of ES6 this year and I have to say that VS Code has just made me incredibly happy. Not only does VS Code give ES6 intellisense but by telling the IDE that you wish to compile in ES6 you can stop it giving red squiggly lines as well. Fantastic stuff. Just add a jsconfig.json file with the following:

{
    "compilerOptions": {
        "target": "ES6"
    }
}

The only bad news is that surely I have to remember which features have actually been implemented by the V8 engine.

Well again I was very happy to discover that there is not a great deal left. The only proviso is that you have to run node --harmony which something you can alias in you command line runner of choice.

The other option is to run babel. In the end I have settled on doing the following :

  • npm install babel  
  • Add require(("babel/register") to the server.js file
The advantage of this approach is that I do not have to remember to write a custom build script with the correct parameters.


Monday, 3 August 2015

A Basic Gulp Gotcha

Recently I have been incorporating gulp into my personal website project. For those completely unfamiliar with Gulp, it is a tool which can be used to primarily to amalgamate your css or javascript into a single file to reduce the number of web requests required to satisfy your various dependencies. Checkout this highly amusing slideshow comparing Gulp with Grunt, it also gives further detail as to why these sort of build tools are such a good idea. It is worth noting that minifying may not be necessary if utilising  HTTP/2 "server push" technology. However there are many plugins and use cases for Grunt which you may still find useful.

I configured my gulpfile.js to do just three things:
  1. Concatenate all files from a set directory into one file and put it in the build folder
  2. Minify the resulting JavasScript
  3. Rename the file, changing the extension to .min.js









Everything was working great. By simply running 'gulp app-build' from the command line I could produce a nice small file, perfect for a snappy web experience.

However, I came across some serious issues when trying to deploy the project to production. I tried adding Gulp to my Kudu deployment script like I had done to load my npm modules. I was frustrated when despite my insistent hacking (which went further into the early hours of the night than I would like to admit!) I kept getting the following error or similar:

When I came back to revisit this problem during a sensible time of day, I discovered my mistake.
This issue on Github was a particular givaway. My thanks to Matheiu Swiip. I had incorrectly assumed that gulp was a tool that I could make a part of my build.

UPDATE:
Having spoken to a colleague about this, it turns out that you can in fact use gulp as part of the build. But any dependencies marked as "dev-dependencies" in the npm package file. So all I need to do is move the ones I need for my build into the main "dependencies" area.

I don't think that anybody doubts the reasons for minfying JS files. But in case anybody is interested, this is the difference it made to my AngularJS app:

We start with:


And after minfication:

At 938KB and 123KB we can see that AngularJS itself is the biggest file.

When finally I got gulp working properly in my production environment and I had concatenated and minified my dependencies things started looking really peachy:




Saturday, 4 April 2015

The full DNS lowdown for your website - A practical guide focusing on Windows Azure

Ok, so what is DNS or the Domain Name System? I have always thought of it as a human friendly way of naming computers which are serving content. However, while a snappy explanation to serve up to a non technical person, it does not really get to the knob of the issue.

DNS assigns names to IP addresses, DNS is Hierarchical and DNS is a protocol.

The DNS protocol specification simply describes how the DNS records should be formatted. This means that there is no need to have a single centralised database, indeed this would be very unwise!

Each DNS record has a type. There are a number of types, but the most commonly used are A, CNAME, MX and NS.

For those who really want to dig into the full specification Microsoft have compiled the current documents for the DNS specification here. For instance if you want to know what the types really are see RFC 1034 (November 1987).


Setting up DNS for your website

So moving away from theory to real life ...I want to set up my website so that when you type the URL mysite.com into chrome it goes straight to my website.

First of all I need to buy a domain name. There are a number of providers, Ghandi and DNSSimple are considered particularly good ones.

Once I have bought a domain name I can get going and set-up some CNAME (canonical name of an Alias - see RFC 1034 :-) ) records. This is because in this first instance I am telling my domain name to simply look for the azure domain name server which will be something like myproject.azuresites.com.

Therefore my CNAME record looks like:
host typetarget
www     CNAME     myproject.azuresites.net

So when I go to www.mydomain.com I get the resource hosted at myproject.azuresites.net.

What is actually happening here is that Azure has already setup an A record pointing from myproject.azuresites.net to the virtual IP address. The virtual IP address will then resolve to any number of different boxes in their "Cloud" server farm. I imagine it is probably powered by nerd sweat =P.

DNS changes can take up to 48 hours to propagate, although personally I have never had to wait longer than half an hour. There are a few little tricks which can help to minimise any confusion:

  1. Try checking a DNS tracking site e.g. whatsmydns.net 
  2. If it has propagated and you are still not seeing the correct result try flushing your local DNS cache by going to the cmd prompt and typing: ipconfig/flushdns.

Incoming email

What I want to do is push all the emails sent into my domains email address into my gmail account. To do this I need to understand a little about the DNS Mail Exchanger (MX) record.

So, the MX record.
host      type        target
  @          MX             ? depends ?

The target depends on what you are trying to achieve. You need a "mailbox" which is going to track emails going to your domain. E.g. to email@mydomain.com.

The easiest way is to buy a mailbox from your domain supplier and then configure your preferred email client app (e.g. gmail, yahoo etc...) to look at their SMTP server. You can then send/receive the mail from the mailbox via SSL encrypted connection. Take a look at this page for help on setting this up. I am working on providing you an alternative solution so watch this space...!

Outgoing Email

This is actually a big subject, many organisations and individuals have got into a lot of trouble over outgoing emails form an app. Span has always been the issue. The steps put in place to reduce spam have unfortunately produced a world where people often say "Your system/ you didn't send the email :( ".... " yes I have :/"..."Have you checked your span filter? :)". 



Non-www

Generally people no longer bother with typing the full address www.mydomain.com. In fact, the average Joe, will be completely baffled as to why their browser throws back an error.

Again DNS comes to the rescue, try:
host      type        target
  @      CNAME    myproject.azuresites.net

If you use this in conjunction with the 'www' record mentioned above then your users should be able to go to www.mydomain.com or mydomain.com with the same result.... some juicy content. hmmm!

Generally you may think that one or the other domain names (non-www or with www) is the preferable URL which should be visible to "the average Joe". What you probably want is the server to immediately redirect to say mydomain.com as soon as somebody goes to www.mydomain.com in their browser.

There are a number of techniques for doing this. With an IIS or Apache web server you can use a command line file which by convention is of the file type .htaccess. Placing this file in the route directory of your code will cause the hosting OS to immediately run the file when serving a resource. You can write something like:

# Redirect www urls to non-www
RewriteEngine on
RewriteCond %{HTTP_HOST} !^mydomain\.com
RewriteRule (.*) http://mydomain.com/$1 [R=301,L]

I am using NodeJS and this has its own technique to achieve this:

// redirect for non-www
app.all('/*', function(req, res, next) {
  if (req.headers.host.match(/^www\./) !== null) {
    res.redirect(301, req.protocol + '://' + req.headers.host.replace(/^www\./, '') + req.url);
  } else {
    next();
  }
})

app.set('trust proxy', true);

Sub-domains

Again these are easy to setup as well. Simply use the * symbol in your CNAME record:
* CNAME myproject.azuresites.net

Then the request to a certain subdomain e.g. elephants.mydomain.com can be sniffed for and intercepted by your code.

Wednesday, 5 November 2014

Asynchronous JavaScript programming in Node

I want to be able to read an atom feed!! This is NodeJS, so of course there is this great library for doing just that (feed-read), the feed function is asynchronous. I also want to use a Node abstraction in the form using Express modules.
Ok, no problem, I thought. I tried putting the feed directly in my server.js file. There was a simple problem - I don't have the blog data because feed-read has made an asynchronous call to gather the feed information leaving me with nothing.
Once I understood the problem I started searching for solutions. What generally comes up are yet more helpful libraries to help you 'deal with' the async 'problem'.
I am sure there are more complicated problems which may merit a complex library but I happen to know that this is something that JavaScript is great at. JQuery introduced the idea of a promise in version 1.5 and this is basically the same problem, with a similar solution. So the answer?

In my case chain callbacks. Yes, if you are using a function from an abstracted module, pass in a function which will then pass a function etc... When the function at the bottom of the chain passes us some data back we will be ready!! Use an API call to do this perhaps so we can give our users a spinner while they are waiting.
     var blogReader = { 
      GetMostRecentBlog : function(callback) {  
        feed('http://bloglocation.com/feeds', function(articles) {  
         var mostRecentBlogPost = articles[0];  
         var blog = {  
            Title: mostRecentBlogPost.title,  
            Content: mostRecentBlogPost.content  
         };  
         callback(blog);  
       }); 
    };  
    module.exports = blogReader;
    
    You then can use it like :
     blogReader.GetMostRecentBlog(function(blog) {  
       //use Blog object here for display  
     });  
    
I found this exact pattern in Mixu's Node book chapter 7 - http://book.mixu.net/node/ch7.html. He also talks about two other useful patterns to deal with asynchronous calls which may be useful on larger scale projects - Parallel and Limited Parallel patterns.

 As always, the code for my solution can be found on github.