Wednesday, November 12, 2014

Adding Azure Application Insights to a Web Site

If you're developing a Web Application, you can use Visual Studio 2013.3 to automatically add all the libraries and configurations that "Azure Application Insights" needs to work.
 
But what about Web Sites? If you create a Web Site (or you have to manage / update one) you'll notice that you don't have such option. So, what can we do it? How can we achieve the same results? How can we integrate Azure Application Insights to a Web Site?
 
Just follow these steps:
  1. Create a new "Application Insights" service using the new Azure portal (preview)
  2. Copy the JavaScript code snippet proposed by the portal and add it to all the pages you want to monitor (or to the master page, if you have one)
  3. In Visual Studio 2013.3, create a new empty web application and add to it the Application Insights using the contextual menu
  4. Copy the following files from the "bin" folder of the Web App to the "bin" folder of the Web Site:
    Microsoft.ApplicationInsights.dll
    Microsoft.ApplicationInsights.Extensibility.RuntimeTelemetry.dll
    Microsoft.ApplicationInsights.Extensibility.Web.dll
    Microsoft.Diagnostics.Tracing.EventSource.dll
    (if you want you can copy also the related .xml and .pdb files)
    
  5. Return to the Azure portal (preview), go to the Application Insights service you've created before, click on the "Properties" button and copy the value of "Instrumentation Key" textbox
  6. Copy the ApplicationInsights.config file from the root of the Web App to the root folder of the Web Site
  7. In this file, replace the value of the "InstrumentationKey" key with the one copied at point 5
  8.  Change the web.config of the website adding these rows:
    <system.web>
     [...]
        <httpModules>
       [...]
          <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.WebRequestTrackingModule, Microsoft.ApplicationInsights.Extensibility.Web" />
       [...]
        </httpModules>
     [...]
    </system.web>
    
    <system.webServer>
     [...]
        <validation validateIntegratedModeConfiguration="false" />
     [...]
     <modules runAllManagedModulesForAllRequests="true">
       [...]
          <remove name="ApplicationInsightsWebTracking" />
          <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.WebRequestTrackingModule, Microsoft.ApplicationInsights.Extensibility.Web" preCondition="managedHandler" />
       [...]
        </modules> 
     [...]
    </system.webServer> 
    
 
Now you can test your Web Site and, after few seconds, you will see you analytics data in the Application Insights blade of the new Azure portal (preview)

Tuesday, November 11, 2014

Manage Cloud Load Tests with the REST API

The Cloud-based Load Testing (CLT) REST APIs give you the ability to execute Load tests from the Cloud in an automated manner, that can be integrated either as part of your Continuous Integration/Deployment pipeline or Test Automation.

Here’s a list of what you can do with these new APIs:
  • Create/Start/Stop a Load Test Run
  • Get Load Test Results  - the set of KPIs groups that you are used to – Performance, Throughput, Application
  • Get Messages from the service during a run
  • Get Exceptions, if any, from the service during a run
  • Get Counter instances and Samples for a Load Test run
  • Get Application Counters for Apps configured with your load test
  • Get list of all past Load test Runs - filtered by requester, date, status etc..
Those APIs work strictly with Azure APIs because they expect to upload files from Azure Blob and to download results to the same drop folder in Azure Blob.

Please note that:
  • For using the REST APIs, you’ll need to enable alternate credentials, and use that for authentication
  • Add "vsclt" to your account name to get redirected to the Cloud-based Load Test (CLT) service within visualstudio.com. If your account is https://abc.visualstudio.com/, then when using APIs, specify this as https://abc.vsclt.visualstudio.com/
 
The base API pattern is:
VERB    https://{account}.vsclt.visualstudio.com/_apis/clt/{resource}[/{options}]
 
Where "resource" can be one of the following and "options" depend on the resource:
 
Test
  • for "Test Runs" (queued test runs): testruns
  • for "Test Drops" (the tests store containers): testdrops
 
Depending on Test Runs
  • for "Counter Instances": testruns/{testrunid}/counterinstances
  • for "Counter Samples": testruns/{testrunid}/countersamples
 
Application Performance Management:
  • for "APM Plugins": apm/plugins
  • for "APM Applications ": apm/applications
  • for "APM Counters ": apm/counters

Create a Test Run
To create a Cloud Load Test Run, you have to make a POST call to the API, passing a set of parameter and test settings like in the example below.

Request Url:
POST    https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns

Request Body:
{
  "name": "MyAppToTest.loadtest",
  "description": "nightly loadtest",
  "testSettings": {
    "cleanupCommand": "",
    "hostProcessPlatform": "x86",
    "setupCommand": ""
  },
  "testDrop": {
    "id": "fe35ed32-eaab-4178-ba7e-ad2577ee187f"
  }
}


Response:
{
  "id": "a5e0d4b9-d387-4b3e-9566-163da9c39b67",
  "name": "MyAppToTest.loadtest",
  "createdDate": "2014-11-1T08:51:27.0965365Z",
  "state": "pending",
  "subState": "none",
  "testSettings": {
    "cleanupCommand": "",
    "hostProcessPlatform": "x86",
    "setupCommand": ""
  },
  "testDrop": {
    "id": "fe35ed32-eaab-4178-ba7e-ad2577ee187f",
    "url": "https://dbtek.vsclt.visualstudio.com/_apis/clt/TestDrops/fe35ed32-eaab-4178-ba7e-ad2577ee187f"
  },
  "runSpecificDetails": {
    "duration": 180,
    "virtualUserCount": 250,
    "samplingInterval": 15
  },
  "createdBy": {
    "id": "76cabfe4-0e20-4f5b-862e-9693a68232f1",
    "displayName": "iamtheuser@dbtek.it"
  },
  "url": "https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns/a5e0d4b9-d387-4b3e-9566-163da9c39b67"
}


As you can see, in the response you'll find all the data you need related to the newly created test run.

Start a Test Run
With those data, we can for example start (queue) the test run, calling the API with a PATCH verb:

Request Url:
PATCH    https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns/a5e0d4b9-d387-4b3e-9566-163da9c39b67

Request Body:
{
  "state": "queued"
}


Response:
Status code: 202


Get Test results
Finally, when the test finished, we can get the test run results, with a GET call.

Request Url:
GET    https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns/a5e0d4b9-d387-4b3e-9566-163da9c39b67/results

Response:
{
  "resultsUrl": "http://127.0.0.1:10000/devstoreaccount1/ets-containerfor-aeee0697-d734-43d7-956e-e662252c265c/2150fbd4-e71c-42fd-8b90-95222a556d87/TestResult/LoadTest.ltrar.zip?sv=2012-02-12&se=2014-06-03T05%3A05%3A39Z&sr=b&si=sas_tenant_policyaeee0697-d734-43d7-956e-e662252c265c&sig=n1Tj%2BsCtiOqQu9UtcXsl%2Bn3ixP%2FVebHCKDJvfD5Tr%2FE%3D",
  "counterGroups": {
    "count": 3,
    "value": [
      {
        "groupName": "Performance",
        "url": "https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns/a5e0d4b9-d387-4b3e-9566-163da9c39b67/CounterInstances?groupNames=Performance"
      },
      {
        "groupName": "Throughput",
        "url": "https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns/a5e0d4b9-d387-4b3e-9566-163da9c39b67/CounterInstances?groupNames=Throughput"
      },
      {
        "groupName": "Application",
        "url": "https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns/a5e0d4b9-d387-4b3e-9566-163da9c39b67/CounterInstances?groupNames=Application"
      }
    ]
  }
}



Get Test errors
You can also retrieve a list of errors that eventually happened during the test. Again, use a GET call.

Request Url:
GET    https://dbtek.vsclt.visualstudio.com/_apis/clt/testRuns/47be20f0-ac4a-40cd-acb7-d9f8c44d0404/Errors

Response:
{
  "count": 2,
  "value": [
    {
      "type": "Exception",
      "subType": "UriFormatException",
      "occurrences": 50,
      "testCaseName": "ErrorsAndExceptionsWebTest",
      "scenarioName": "LoadTestingScenarioWarmupDuration",
      "request": "http://www.bing:123.com/----{GET}",
      "stackTrace": "   at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)\n   at System.Uri..ctor(String uriString, Boolean dontEscape)\n   at Microsoft.VisualStudio.TestTools.WebStress.WebTestTransaction..ctor(String requestUrl)\n   at Microsoft.VisualStudio.TestTools.WebStress.WebTestInstrumentedTransaction.CreateTransaction()\n   at Microsoft.VisualStudio.TestTools.WebStress.WebTestInstrumentedTransaction.Execute(WebTestCaseContext testCaseContext, AsyncCallback completionCallback, Object callerState)",
      "messageText": "Invalid URI: Invalid port specified.",
      "lastErrorDate": "2014-11-11T09:14:20.363Z"
    },
    {
      "type": "ExtractionRuleError",
      "subType": "ExtractText",
      "occurrences": 50,
      "testCaseName": "ErrorsAndExceptionsWebTest",
      "scenarioName": "LoadTestingScenarioWarmupDuration",
      "request": "http://www.bing.com/----{GET}",
      "stackTrace": "",
      "messageText": "StartsWith text was not found in the response",
      "lastErrorDate": "2014-11-11T09:14:23.663Z"
    }
  ]
}