mercoledì 12 novembre 2014

Aggiungere Azure Application Insights ad un Web Site

Sviluppando una Web Application, è possibile usare Visual Studio 2013.3 per aggiungere automaticamente tutte le librerie e le configurazioni di cui "Azure Application Insights" ha bisogno pre funzionare.
 
Ma invece per quanto riguarda i Web Sites? Se si crea un Web Site (oppure si vuole modificarne o gestirne uno già esistente) l'opzione per aggiungere l'Application Insights non è presente. Cosa possiamo fare, quindi? Com'è possibile raggiungere lo stesso risultato? Come possiamo integrare Azure Application Insights in un Web Site?
 
È possibile! Basta seguire questi step:
  1. Creare un nuovo servizio "Application Insights" usando il nuovo Azure portal (preview)
  2. Copiare lo snippet di codice JavaScript che viene proposto dal portale ed aggiungerlo a tutte le pagine che si vogliono monitorare (oppure alla master page, se ce n'è una)
  3. In Visual Studio 2013.3, creare una nuova web application vuota ed aggiungere ad essa Application Insights usando il menu contestuale
  4. Copiare i seguenti file dalla cartella "bin" della Web App alla cartella "bin" del Web Site:
    Microsoft.ApplicationInsights.dll
    Microsoft.ApplicationInsights.Extensibility.RuntimeTelemetry.dll
    Microsoft.ApplicationInsights.Extensibility.Web.dll
    Microsoft.Diagnostics.Tracing.EventSource.dll
    (volendo è possibile anche copiare i relativi file .xml e .pdb)
    
  5. Tornare nell'Azure portal (preview), andare nella sezione dell'Application Insights creato precedentemente, cliccare sul bottone "Properties" e copiare il valore della texbox "Instrumentation Key"
  6. Copiare il file ApplicationInsights.config dalla root della Web App alla root folder del Web Site
  7. In questo file, sostituire il valore della chiave "InstrumentationKey" con quello copiato al punto 5
  8.  Cambiare il file web.config del website aggiungendo le seguenti righe:
    <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> 
    
 
A questo punto è possibile avviare e testare il Web Site e, dopo qualche secondo, i dati e le statistiche saranno presenti nella blade dell'Application Insights (sempre sul nuovo Azure portal)

martedì 11 novembre 2014

Gestire i Cloud Load Test con le REST API

Le REST API dei Cloud-based Load Testing (CLT) permettono di automatizzare l'esecuzione dei Load test dal Cloud, in modo da poterli integrare nei processi di Continuous Integration / Deployment e di Test Automation.

Ecco una lista (sicuramente in espansione) di quello che si può fare con queste nuove API:
  • Creare / Lanciare / Stoppare un Load Test Run
  • Recuperare i Load Test Results - un set di gruppi di  KPI - Performance, Throughput, Application
  • Recuperare i Messages del servizio durante l'esecuzione
  • Recuperare le Exceptions, se ci sono
  • Recuperare le Counter instances di un  Load Test run
  • Recuperare gli Application Counters delle App configurate nel load test
  • Recuperare una lista di tutti i Load test Runs eseguiti - con filtri per requester, date, status ecc..
Queste API lavorano in stretta vicinanza con le Azure API, visto che si leggono i test file da un Azure Blob e salvano i risultati nella stessa drop folder sempre sull'Azure Blob.

È importante notare che:
  • Per usare le REST API, è necessario abilitare le alternate credentials su Visual Studio Online e quindi utilizzarle per l'autenticazione
  • Aggiungere"vsclt" al nome dell'account VSO per essere rediretti al "Cloud-based Load Test (CLT) service" di visualstudio.com. Ade sempio, se l'account è https://abc.visualstudio.com/, quando si utilizzano le API indicare https://abc.vsclt.visualstudio.com/
 
Il pattern di base per le  API è il seguente:
VERB    https://{account}.vsclt.visualstudio.com/_apis/clt/{resource}[/{options}]
 
Dove "resource" può essere una delle seguenti e le "options" dipendono dalla resource:
 
Test
  • Per i "Test Runs": testruns
  • Per le "Test Drops" (i container dove vengono salvati i dati): testdrops
 
Dipendenti dai Test Run
  • Per le "Counter Instances": testruns/{testrunid}/counterinstances
  • Per i "Counter Samples": testruns/{testrunid}/countersamples
 
Application Performance Management:
  • Per i "APM Plugins": apm/plugins
  • Per le "APM Applications ": apm/applications
  • Per i "APM Counters ": apm/counters

Creare un Test Run
Per creare un Cloud Load Test Run, è necessario fare una chiamata POST alle API, passando nel body un set di parametri e test settings come in questo esempio.

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"
}


Come si può vedere, nella response si trovano tutti i dati che possono servire relativi al test run appena creato.

Avviare un Test Run
Con questi dati possiamo per esempio avviare (o meglio accodare) il test run, chiamando le API usando un verb PATCH:

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

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


Response:
Status code: 202


Recuperare i Test results
Infine, quando il test è finito, possiamo recuperare i risultati con una call in GET.

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"
      }
    ]
  }
}



Recuperare i Test errors
È anche possibile recuperare una lista di eventuali errori che si sono verificati durante l'esecuzione del test. Di nuovo, va utilizzata una chiamata in GET.

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"
    }
  ]
}