<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Testing The Testing Strategy</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/geoffgr/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/geoffgr/feed.xml</link>
    <description>How does a test harness work? Why are these results different than those? The best way to figure things out is to try them out...</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:10:42 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Geoffgr's blogs are moving to a new site</title>
      <link>https://docs.microsoft.com/archive/blogs/geoffgr/geoffgrs-blogs-are-moving-to-a-new-site</link>
      <pubDate>Mon, 04 Sep 2017 10:59:58 GMT</pubDate>
      <dc:creator><![CDATA[geoffgr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/geoffgr/?p=506</guid>
      <description><![CDATA[All, I am moving my blog posts to a new site and will do all future blogging there. I am leaving...]]></description>
      <content:encoded><![CDATA[All, I am moving my blog posts to a new site and will do all future blogging there. I am leaving copies of my current posts here, but I will no longer be maintaining them or posting new ones here. If you wish to view new posts or continue to follow me, please change your bookmark to <strong><a href="https://testandattack.com/table-of-contents/">https://testandattack.com/table-of-contents/</a></strong>. You will find a much easier list of the posts to navigate and new posts as I add more content on that site.

Thanks to Microsoft and MSDN for hosting this site for me during my years as an employee with Microsoft.]]></content:encoded>
    </item>
    <item>
      <title>Which comes first, the Process or the Tool?</title>
      <link>https://docs.microsoft.com/archive/blogs/geoffgr/which-comes-first-the-process-or-the-tool</link>
      <pubDate>Thu, 28 Jan 2016 04:57:02 GMT</pubDate>
      <dc:creator><![CDATA[geoffgr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/geoffgr/2016/01/28/which-comes-first-the-process-or-the-tool/</guid>
      <description><![CDATA[Prologue  I was just going through my email and came across a question on one of our discussion...]]></description>
      <content:encoded><![CDATA[<h2>Prologue</h2>  <p>I was just going through my email and came across a question on one of our discussion aliases that asked if it was possible to deliver an ALM assessment for a customer without worrying about the tool set they currently use. The customer wanted to have the assessment focus on their process. The person asking the question wanted to make sure we could conduct an assessment in that manner. At first, I was surprised that the question had been asked since I figured the answer is so obvious (after all, this was an internal Microsoft discussion alias). Then it hit me. The answer is obvious to those of us who perform the assessments, and do the training, and work with dozens of different customers each year. But the general IT industry often looks at things differently. The question on the alias was:</p>  <p><em><font color="#0000ff">“I need someone who can do the ALM assessment where the delivery is tools agnostic”</font></em></p>  <p>One of my teammates replied:</p>  <p><font color="#0000ff"><em>“Indeed the ALM assessment doesn't even care about which tools you use.”</em></font></p>  <p>I replied to his answer as follows:</p>  <p><font color="#0000ff"><em>“I would take it one step further and state that any ALM assessment that does focus on tooling is done incorrectly. ALM is a process, the tools are…..well, tools. The process should always dictate the tools. The tools should NEVER dictate the process.”</em></font><font color="#000000"> Now I do believe the tools SHOULD SUPPORT and BOLSTER the process, but that is not the same as dictating the process.</font></p>  <h2>The Process should come first</h2>  <p>I bring this up in my blog because I find myself repeating this sentiment all the time. I delivered an ALM Testing workshop a couple weeks ago (a 3 day high level class that focuses on several different aspects of testing within an ALM based shop). I found myself repeating this message 3 or 4 times per day in response to questions that the attendees were asking. I use this message when I am teaching ALM. I use this message when I am doing an ALM assessment. I use this message when I am delivering a Testing Readiness Assessment. I use this message when I am developing a Performance Test Plan (<a href="https://blogs.msdn.com/b/geoffgr/archive/2014/09/04/all-about-test-planning-part-2-load-patterns-and-data-considerations.aspx" target="_blank">see this post</a>). I can use this message just about anywhere that I am planning or assessing (<em>unless the assessment is something like “Assess how well we are taking advantage of TOOLSET X, which would be a customized offering and not subject to normal rules</em>).</p>  <p>The simple message that I want to make sure I convey is that “<font color="#666666" size="4"><em>The process should define the tools. The tools should NEVER drive the process.</em></font>” In other words, you should:</p>  <ol>   <li>Define your process </li>    <li>Pick tools that fit your process. </li>    <li>Then enter into a lifecycle maintenance loop:      <ol>       <li>Evaluate the process/tools feedback loop </li>        <li>Is the process still relevant? </li>        <li>Are the tools supporting the process? </li>        <li>Lather, rinse, repeat. </li>     </ol>   </li> </ol>  <h2>Don’t Ignore the Tools</h2>  <p>One customer I was recently working with had different tools for source control, development and project management. In order for them to add code reviews to their workflow, they had to create a shelf set, then go to the source control tool to request a review. Then they had to manually add a task to the project management. All of these had to be updated separately and manually upon completion. They were actually avoiding doing regular code reviews because of “lack of time” in their WIP estimates. I showed them the feature of code reviews that is integrated into TFS and Visual Studio [if you have pending changes, you can simply click on the “actions” dropdown, select “Request Review,” and choose a person from the list. That’s it. TFS will make the shelf-set, create a work item task and assign the task to the person. </p>  <p>This is a good example of considering the tools and using them to drive EFFICIENCY. The customer can definitely benefit from the way TFS handles code review workflow. HOWEVER, it is important to know that even if they do not choose to start using TFS, they are still going to be enforcing code reviews as part of their process. </p>]]></content:encoded>
    </item>
    <item>
      <title>Dissecting the Visual Studio Load Test Results Database (Part 6–Data Warehousing)</title>
      <link>https://docs.microsoft.com/archive/blogs/geoffgr/dissecting-the-visual-studio-load-test-results-database-part-6data-warehousing</link>
      <pubDate>Thu, 21 Jan 2016 11:21:00 GMT</pubDate>
      <dc:creator><![CDATA[geoffgr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/geoffgr/2016/01/21/dissecting-the-visual-studio-load-test-results-database-part-6data-warehousing/</guid>
      <description><![CDATA[In the previous post, I showed how I use a couple of stored procedures to recalculate data based on...]]></description>
      <content:encoded><![CDATA[<p>In the previous post, I showed how I use a couple of stored procedures to recalculate data based on various criteria. In this post, I am going to share a few data tables that I use to store &ldquo;Warehousing&rdquo; data to make reports faster and easier to create. In the next post I will show you how to start using this data, and how we can automate some of the sprocs I already posted about.</p>
<p>NOTE1: I have included a sproc in this post that you can download and run against a LoadTest2010 database. It will add all of the below info to the DB.</p>
<p><span style="color: #ff0000"><span style="text-decoration: underline">NOTE2: The last two sprocs will NOT install properly on any version of SQL Server older than 2012. If you experience any errors running the code, make sure your version of SQL is at least 2012.</span></span></p>
<h2><span style="color: #ff0000;font-weight: bold">About the sample code</span></h2>
<p><span style="color: #000000">The code here is all a work in progress. Please play with it, use it, test it and provide me feedback. At the end of this series, I will post the entire SQL codeset with any updates and fixes that get reported.</span></p>
<h2>Data Warehousing</h2>
<p>The idea of creating Data Warehouses is nothing new, and strictly speaking I do not know if what I am creating is officially a data warehouse. However, the idea fits so that&rsquo;s what I am calling it. I add a few tables to the LoadTest2010 database and then populate them with aggregated and recalculated data. The beauty of the data is that it can all be gotten from existing data in the DB and does not break the current schema in any way. I will explain the table schemas first, then I will explain the stored procedures I use to populate the data into the tables.</p>
<h2>The Tables</h2>
<ul>
<li><strong>VSLT_LoadTestCoreInfo</strong>This table contains a single row for each LoadTestRun stored in the database. The main purpose is to extend the data stored in the LoadTestRun table. I will not show all of the columns in this table. You can see the columns in the SQL code and the values are self explanitory. I will explain the FLAG columns though. These are used by my front end reporting tool and help the tool decide what functionality should be exposed for any given run:
<ul>
<li><strong>FLAG_ContainsPages</strong>: TRUE if the run contains web page requests.</li>
<li><strong>FLAG_ContainsTransactions</strong>: TRUE if the run contains Transaction Timers</li>
<li><strong>FLAG_ContainsDetailedTimingInfo</strong>: TRUE if the test run contains the actual details for any of the three 'LoadTest***Detail' tables</li>
<li><strong>FLAG_ContainsStepLoadProfile</strong>: TRUE if the test run contains more than 1 constant value for the "User Load" counter.</li>
<li><strong>FLAG_TestAborted</strong>: TRUE if the Outcome column of the LoadTestRun is equal to 'Aborted'.</li>
<li><strong>FLAG_LoadTestParsingFailed</strong>: This is set to TRUE if any type of error or exception occurs during the execution of the 'VSLT_prc_Update***' stored procedures</li>
<li><strong>FLAG_LoadTestIntervalProfile</strong>: Contains the value associated with the interval profile from the next table below.</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>VSLT_IntervalProfileTypes</strong>[Normalization Table] Contains the list of interval types that could exist in a given load test run. There are two columns: The ID and Description for each type
<ul>
<li><strong>'Data May not be valid'</strong>: Indicates that the routines I use to calculate profiles did not have a proper checksum</li>
<li><strong>'use ENTIRE RUN'</strong>: Indicates that there was only a single User Load for the entire run (including any warmup)</li>
<li><strong>'use INTERVAL VALUES (only one interval exists)'</strong>: This run contains a warmup, or a steady state step ramp, then goes constant, so there is only one interval stored for the run. Use it.</li>
<li><strong>'Indeterminant, multiple intervals exist'</strong>: This run contains multiple valid intervals. Use the full set of interval tools to process it.</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>VSLT_LoadTestIntervals</strong>This table contains the data about any of the constant load "intervals" discovered in a run. There is one row of data for each interval.
<ul>
<li><strong>LoadTestRunId</strong>: What run is this interval associated with.</li>
<li><strong>StartOffset</strong>: How many seconds from the beginning of the run does this constant interval start</li>
<li><strong>EndOffset</strong>: How many seconds from the beginning of the run does this constant interval end</li>
<li><strong>UserLoad</strong>: How many users were executing tests at this interval</li>
<li><strong>NumberOfDataPoints</strong>: How many perfmon collection intervals occurred during this interval (if the test's sample rate is every 5 seconds and the interval is 60 seconds long, then there will be 12 data points</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>VSLT_ScoreCardMachineCPU</strong> This table contains a single row of data per machine per run for any machine that had Perfmon CPU info collected. It is used to easily build summary and comparison reports. It is based on the Perfmon counter <strong>Processor\(_Total)\% Processor Time</strong>
<ul>
<li><strong>LoadTestRunId</strong>: What run is this data associated with.</li>
<li><strong>MachineName</strong>: The Computer Name</li>
<li><strong>MachineTypeId</strong>: The Id for the type of machine this is. This field is currently not used, but exists to allow for aggregating data based on the roles of the machines</li>
<li><strong>InstanceId</strong>: This is the Id contained in the LoadTestPerformanceCounterSample table and allows you to easily pull all data points for building charts or aggregating data</li>
<li><strong>Qty</strong>: The number of perfmon samples collected from this machine during this run.</li>
<li><strong>Min</strong>: The aggregated Minimum value from the perfmon data.</li>
<li><strong>Avg</strong>: The aggregated Avg value from the perfmon data.</li>
<li><strong>Max</strong>: The aggregated Maximum value from the perfmon data.</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>VSLT_ScoreCardMachineAvailableMB</strong> This table contains a single row of data per machine per run for any machine that had Perfmon Memory info collected. It is used to easily build summary and comparison reports. It is based on the Perfmon counter <strong>Memory\Available MBytes</strong>
<ul>
<li><strong>LoadTestRunId</strong>: What run is this data associated with.</li>
<li><strong>MachineName</strong>: The Computer Name</li>
<li><strong>MachineTypeId</strong>: The Id for the type of machine this is. This field is currently not used, but exists to allow for aggregating data based on the roles of the machines</li>
<li><strong>InstanceId</strong>: This is the Id contained in the LoadTestPerformanceCounterSample table and allows you to easily pull all data points for building charts or aggregating data</li>
<li><strong>Qty</strong>: The number of perfmon samples collected from this machine during this run.</li>
<li><strong>Min</strong>: The aggregated Minimum value from the perfmon data.</li>
<li><strong>Avg</strong>: The aggregated Avg value from the perfmon data.</li>
<li><strong>Max</strong>: The aggregated Maximum value from the perfmon data.</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>TSL_DbChangeLogs</strong>This table tracks any changes that my stored procedures makes to the DB
<ul>
<li><strong>LoadTestRunId</strong>: What run is this data associated with.</li>
<li><strong>LogId</strong>: This is an Id for each entry in the table. This Id PLUS the LoadTestRunId form a unique key.</li>
<li><strong>ChangeTypeId</strong>: This Id is used to map to the <strong>TSL_DbChangeLogTypes</strong> table to describe what type of change occurred.</li>
<li><strong>ChangeTime</strong>: The timestamp when the change occurred.</li>
<li><strong>LogComment</strong>: Any additional comments about the change will get stored here.</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>TSL_DbChangeLogTypes</strong> This table holds the descriptions for the types of changes that can be made to the DB by my sprocs. Valid values (<em>shown as [ID], '[description]'</em>) are:
<ul>
<li>1, 'VSLT_prc_UpdateLoadTestCoreInfoTable'</li>
<li>2, 'VSLT_prc_UpdateScoreCardMachineCpuTable'</li>
<li>3, 'VSLT_prc_UpdateScoreCardMachineAvailableMBTable'</li>
<li>4, 'VSLT_prc_GetStartingValuesForImportingPerfmon'</li>
<li>5, 'VSLT_prc_UpdatePerfmonTablesFromImport'</li>
<li>6, 'VSLT_prc_UpdateLoadTestIntervalTable'</li>
<li>7, 'VSLT_prc_UpdateLoadTestCoreInfoTable_IntervalProfileFlag'</li>
</ul>
</li>
</ul>
<h3>&nbsp;</h3>
<h2>The Update Sprocs</h2>
<p>These stored procedures are used to update the values in the above tables. There are a few things to note about these sprocs and their usage:</p>
<ul>
<li>These sprocs use CURSORS to go through all load test runs and only process the runs that have not already been processed. It is safe to run these sprocs as often as you would like.</li>
<li>The main sproc in this group will call ALL OTHER sprocs in the group so that you can get a full update from only a single command.</li>
<li>These sprocs will update the ChangeLogs info every time a change is made.</li>
</ul>
<p>&nbsp;</p>
<hr align="center" size="2" width="90%" />
<p><strong><span style="text-decoration: underline">VSLT_prc_UpdateLoadTestCoreInfoTable</span></strong> - updates all of the data for the <strong><span style="color: #0000ff">VSLT_LoadTestCoreInfo</span></strong> table. It also calls the two below sprocs.</p>
<blockquote>
<p><strong><span style="text-decoration: underline">VSLT_prc_UpdateScoreCardMachineAvailableMBTable</span></strong> updates all of the data for the <strong><span style="color: #0000ff">VSLT_ScoreCardMachineAvailableMB</span></strong> table.</p>
</blockquote>
<blockquote>
<p><strong><span style="text-decoration: underline">VSLT_prc_UpdateScoreCardMachineCpuTable</span></strong> updates all of the data for the <strong><span style="color: #0000ff">VSLT_ScoreCardMachineCPU</span></strong> table.</p>
</blockquote>
<hr align="center" size="2" width="90%" />
<p><strong><span style="text-decoration: underline">VSLT_prc_UpdateLoadTestIntervalTable</span></strong> updates all of the info for the <strong><span style="color: #0000ff">VSLT_LoadTestIntervals</span></strong> table. It also calls the below sproc.</p>
<blockquote>
<p><strong><span style="text-decoration: underline">VSLT_prc_UpdateCoreInfoWithIntervalFlags</span></strong> updates the <strong><span style="color: #0000ff">VSLT_LoadTestCoreInfo</span></strong> table with the following values:</p>
<ul>
<li>FLAG_LoadTestIntervalProfile</li>
<li>MainIntervalStart</li>
<li>MainIntervalEnd</li>
</ul>
</blockquote>
<hr align="center" size="2" width="90%" />
<p>&nbsp;</p>
<h2>Automatically Updating Data</h2>
<p>the following two built in sprocs can be safely modified using the attached ALTER PROCEDURE. This will allow Visual Studio to automatically update all of the VSLT data warehousing tables at the end of every run. I added a brief description below, but study the download to fully understand the changes I make. <em><span style="color: #ff0000">(NOTE: I am working on a routine that will automatically handle interval data on LoadTest2010 databases that are on versions of SQL Server older than 2012. The automatic Interval Update sprocs will not work on earlier versions. Therefore I currently do not automatically call the <strong><span style="text-decoration: underline">UpdateLoadTestIntervalTable</span></strong> sproc from the built in sprocs. I will post that in a future blog entry.)</span></em></p>
<ul>
<li><strong>Prc_UpdateSummaryData3</strong> &ndash; Adds the following code at the very end of the stored procedure:</li>
</ul>
<p><span style="font-family: Courier New"><span style="color: #008000">---------------------------------------------------------------- <br />-- Added by the VSLT Reporting Tool <br /></span><span style="color: #0000ff">EXEC</span> VSLT_prc_UpdateLoadTestCoreInfoTable <br /><span style="color: #008000">----------------------------------------------------------------</span></span></p>
<ul>
<li><strong>Prc_DeleteLoadTestRun</strong> &ndash; Adds the data tables to the list of all tables in the DB (in the proper order). It then adds the calls to delete data from the new tables using the same criteria as the main delete portion.</li>
</ul>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/10/66/57/12/Warehousing%20tables%20and%20update%20sprocs.sql">Warehousing tables and update sprocs.sql</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Dissecting the Visual Studio Load Test Results Database (Part 5– The Slicing of Data)</title>
      <link>https://docs.microsoft.com/archive/blogs/geoffgr/dissecting-the-visual-studio-load-test-results-database-part-5-the-slicing-of-data</link>
      <pubDate>Tue, 05 Jan 2016 09:27:00 GMT</pubDate>
      <dc:creator><![CDATA[geoffgr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/geoffgr/2016/01/05/dissecting-the-visual-studio-load-test-results-database-part-5-the-slicing-of-data/</guid>
      <description><![CDATA[In my last post of this series, I provided some views that set us up to start getting more...]]></description>
      <content:encoded><![CDATA[<p>In my last post of this series, I provided some views that set us up to start getting more meaningful information out of the results DB. In this post, I will start showing you some of the stored procedures I use to slice the data. But first, I need to let you know that some of my stored procedures do require you to have &ldquo;All Individual Details&rdquo; stored in the database for the runs you want to examine. Others do not. I will make a note for each sproc as to the requirements for that sproc.</p>
<h3>A Note About this Particular Series of Posts</h3>
<p>I am starting off fairly simple with the sprocs I am showing here. However, I am leading up to some fairly complex calculations as well as data warehousing. I will be showing you new tables I add to the DB soon that help with a number of calculations, but since they rely on much of the same code as the simple ones, I want to explain these first.</p>
<h3>The start of every report</h3>
<p>We always need to use the LoadTestRunId to define what run(s) we want to work on. To get that, we use a simple query:</p>
<p><span style="font-family: Courier New"><span style="color: #0000ff">SELECT</span> LoadTestRunId, LoadTestName, Description, StartTime, Outcome <span style="color: #0000ff">FROM</span> LoadTestRun</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/8712.List-of-runs_2CD1666C.png"><img style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border: 0px" title="List of runs" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/7416.List-of-runs_thumb_2F0DEF28.png" alt="List of runs" width="644" height="173" border="0" /></a></p>
<p>For the rest of this post, we will use either run #4 or run #52</p>
<h3>Page Response Times</h3>
<p>The first sproc is <strong><span style="font-family: Courier New">VSLT_prc_Page_ResponseTimes</span></strong>. There are also similar sprocs for tests and transactions. There are 5 parameters you can pass in, but only one is required (the LoadTestRunId). If you do not supply any of the others, they will use default values:</p>
<p><span style="font-family: Courier New">@RunId&nbsp; <span style="color: #0000ff">INT</span> <br />,@StartOffset <span style="color: #0000ff">INT</span> = <span style="color: #a5a5a5">NULL</span> <br />,@EndOffset <span style="color: #0000ff">INT</span> = <span style="color: #a5a5a5">NULL</span> <br />,@NameFilter <span style="color: #0000ff">nvarchar</span>(255) = <span style="color: #ff0000">'%'</span> <br />,@NumberOfRows <span style="color: #0000ff">INT</span> = 25</span></p>
<p>To show the basic syntax, here is the call and results for an entire run, in this case run #4:</p>
<p><span style="font-family: Courier New"><span style="color: #0000ff">EXEC</span>&nbsp;&nbsp;&nbsp; VSLT_prc_Page_ResponseTimes <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @RunId = 4 <br /></span></p>
<p><span style="font-family: Courier New"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/5342.PageResponseTimesInterval_2_1BECC27C.png"><img style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border: 0px" title="PageResponseTimesInterval_2" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/8816.PageResponseTimesInterval_2_thumb_44F76178.png" alt="PageResponseTimesInterval_2" width="644" height="82" border="0" /></a></span></p>
<p>Now, let&rsquo;s look at the graph of the user load for the run (image below). Here we can see that the load steps up throughout the run [the highlighted red line], so looking at an overall average is misleading. We want to be able to look at the values during each constant load portion. I chose the portion between 2 minutes 10 seconds and 4 minutes.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/6813.PageResponseTimesInterval_1_1FF9A0FF.png"><img style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border: 0px" title="PageResponseTimesInterval_1" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/2350.PageResponseTimesInterval_1_thumb_6B5BD574.png" alt="PageResponseTimesInterval_1" width="644" height="200" border="0" /></a></p>
<p>To get the values there, I add two more of the parameters to the call to the sproc, and it now calculates the values using only the page responses that were received during the time frame specified. NOTE: The offsets are specified using seconds and are based off of time from the start of the run, so 2 minutes 10 seconds = 130</p>
<p><span style="font-family: Courier New"><span style="color: #0000ff">EXEC</span>&nbsp;&nbsp;&nbsp; VSLT_prc_Page_ResponseTimes <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @RunId = 4, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @StartOffset = 130, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @EndOffset = 240</span></p>
<p>And here are the results [<span style="color: #ff0000">NOTE: The last two columns; Scenario and TestName both use one of the VSLT Views to get the proper names to add here</span>]:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/7725.PageResponseTimesInterval_3_5F59E540.png"><img style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border: 0px" title="PageResponseTimesInterval_3" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/3531.PageResponseTimesInterval_3_thumb_0864843D.png" alt="PageResponseTimesInterval_3" width="644" height="85" border="0" /></a></p>
<h3>The Way It Works</h3>
<p>The heart of the sproc is the WHERE clause filter. The rest of the sproc is all of the joins and the temp tables to allow for multiple queries to be combined (this is required in order to get the 90% and 95% values). Let&rsquo;s break it down and then you can modify it however you want if you need different results.</p>
<p><span style="font-family: Courier New"><span style="color: #0000ff">WHERE</span>&nbsp; <br />a.LoadTestRunId = @RunId</span></p>
<p><em><span style="color: #333333">Pick only this run</span></em></p>
<p><span style="font-family: Courier New"><span style="color: #a5a5a5">AND</span> (@StartOffset <span style="color: #a5a5a5">IS NULL OR</span> c.EndTime &gt;= <span style="color: #9b00d3">DATEADD</span>(<span style="color: #9b00d3">second</span>, @StartOffset, b.StartTime))</span></p>
<p><em><span style="color: #333333">If no start offset was provided, ignore this part of the filter. If it was provided, then filter results to only those which have an end time greater than or equal to the time of the specified offset.</span></em></p>
<p><span style="font-family: Courier New"><span style="color: #a5a5a5">AND</span> (@EndOffset <span style="color: #a5a5a5">IS NULL OR</span> c.EndTime &lt; <span style="color: #9b00d3">DATEADD</span>(<span style="color: #9b00d3">second</span>, @EndOffset, b.StartTime))</span></p>
<p><em><span style="color: #333333">If no end offset was provided, ignore this part of the filter. If it was provided, then filter results to only those which have an end time less than the time of the specified offset.</span></em></p>
<p><span style="font-family: Courier New"><span style="color: #a5a5a5">AND</span> d.RequestUri <span style="color: #a5a5a5">LIKE</span> @NameFilter</span></p>
<p><span style="color: #333333"><em>I cheat here and provide a global value for the name filter, which makes the query slower since it has to scan the entire table, but it simplifies the use of the query. I will probably update this in a future version.</em></span></p>
<p><span style="font-family: Courier New"><span style="color: #a5a5a5">AND</span> (c.Outcome = 0) </span></p>
<p><span style="color: #333333"><em>This filter is hardcoded to only look at requests whose outcome was PASS. </em></span></p>
<p><span style="font-family: Courier New"><span style="color: #a5a5a5">AND</span> (a.InMeasurementInterval = 1) </span></p>
<p><span style="color: #333333"><em>This filter is hardcoded to exclude any requests that were captured during warmup or cooldown.</em></span></p>
<h3>Page Throughput</h3>
<p>This sproc is the same as the Page Response Time except that it focuses on calculating the number of pages per second for each page. It takes the total number of pages executed in a specified interval and uses the interval&rsquo;s duration to get the final value. As with the response time sproc, it takes between 1 and 5 args (the same five). Here is the output for the throughput sproc for the same run as above and the same interval time:</p>
<p><span style="font-family: Courier New"><span style="color: #0000ff">EXEC</span>&nbsp;&nbsp;&nbsp; VSLT_prc_Page_Throughput <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @RunId = 4, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @StartOffset = 130, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @EndOffset = 240</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/6278.PageThroughput_18071FFF.png"><img style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border: 0px" title="PageThroughput" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/3755.PageThroughput_thumb_256D3305.png" alt="PageThroughput" width="644" height="132" border="0" /></a></p>
<p>I could have combined the throughput calculation with the response time sproc, but you will see later on when I get into multiple runs and other parts that it is easier to keep these separate. However, since you are getting access to the code, feel free to handle it however you would like.</p>
<h3>&nbsp;</h3>
<h3>Grouping By Name</h3>
<p>The last part I want to show here is calculating the response times grouped by their name. Sometimes you may have multiple web tests or scenarios that contain calls to the same page. As I explained in an earlier post, Visual Studio tracks each of these separately. However, you can use this sproc to get the response times by using the request URL or reporting name as the grouping mechanism. Take a look at the two tables below. The first shows the response times for a test I ran that had a timer call in two different locations. The second shows the same test results, but with both instances of the call combined and recalculated:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/4682.ResponseGrouping_1_14F4C20A.png"><img style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border: 0px" title="ResponseGrouping_1" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/1067.ResponseGrouping_1_thumb_0554B6F9.png" alt="ResponseGrouping_1" width="644" height="222" border="0" /></a></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/2870.ResponseGrouping_2_0DD81643.png"><img style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border: 0px" title="ResponseGrouping_2" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/0576.ResponseGrouping_2_thumb_02425904.png" alt="ResponseGrouping_2" width="644" height="235" border="0" /></a></p>
<h3>Conclusion</h3>
<p>Hopefully you will start to see how you can use the data in the Database to make more informed evaluations of the results. As we delve into the next part, I will setup some tables that can be used to build quick dashboards and also to allow for more automation of much of the interval calculations shown in this post. As always, please provide feedback.</p>
<p>The sql file attached contains the following stored procedures:</p>
<ul>
<li>VSLT_prc_Page_ResponseTimes</li>
<li>VSLT_prc_Page_Throughput</li>
<li>VSLT_prc_Page_ResponseTimes_GroupedByName</li>
<li>VSLT_prc_Test_ResponseTimes</li>
<li>VSLT_prc_Transaction_ResponseTimes</li>
<li>VSLT_prc_Transaction_ResponseTimes_GroupedByName</li>
</ul>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/10/66/30/42/VSLT%20Sprocs%20Round1.sql">VSLT Sprocs Round1.sql</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Dissecting the Visual Studio Load Test Results Database (Part 4–Building Better Views)</title>
      <link>https://docs.microsoft.com/archive/blogs/geoffgr/dissecting-the-visual-studio-load-test-results-database-part-4building-better-views</link>
      <pubDate>Tue, 08 Dec 2015 14:28:00 GMT</pubDate>
      <dc:creator><![CDATA[geoffgr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/geoffgr/2015/12/08/dissecting-the-visual-studio-load-test-results-database-part-4building-better-views/</guid>
      <description><![CDATA[In the previous posts of this series, I focused on showing you the built in features of the Load...]]></description>
      <content:encoded><![CDATA[<p>In the previous posts of this series, I focused on showing you the built in features of the Load Test Results Database. The next few posts will focus on customizing and extending the database.</p>
<h3>The Mystery of the Perfmon Page Counters</h3>
<p>There are two ways you can look at the details for pages, transactions, etc in the results DB. You can look at the detailed timing tables or you can look at the perfmon data (see <a href="https://blogs.msdn.com/b/geoffgr/archive/2013/10/09/all-about-load-test-results-and-the-results-db-part-2-why-do-the-results-conflict-with-each-other.aspx" target="_blank">this post</a> for details on the differences). Each has a distinct advantage. However, getting data from the perfmon counters can be tricky since the database combines two distinct columns into one for the Instance value.</p>
<p>When I customize my reporting, I use a lot of stored procedures that rely heavily on pulling data from perfmon. In order to make this easier, I create a view that exposes the counters in a way that allows me to use the perfmon values the same way I would use the Page Details. Below is the code for creating the view (note, in the attached zip, I have included some other views that will get used in future posts.</p>
<p><span style="font-family: courier new"><span style="color: #0000ff">CREATE VIEW</span> VSLT_View_PageNamesWithIDs <span style="color: #0000ff">AS</span> <br />&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">SELECT</span> a.LoadTestRunId <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , c.ScenarioId <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , ScenarioName <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , a.TestCaseId <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , TestCaseName <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , RequestId <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , RequestUri <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,RequestUri <span style="color: #9c85c0">+</span> <span style="color: #d16349">'('</span> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">+ RIGHT (</span><span style="color: #c0504d">'000'</span> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">+ CAST(</span>RequestId <span style="color: #0000ff">AS nvarchar</span>(3)), 3) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">+ </span><span style="color: #c0504d">')'</span> <span style="color: #0000ff">AS</span> RequestNameWithId <br />&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">FROM</span> dbo.WebLoadTestRequestMap <span style="color: #0000ff">AS</span> a</span></p>
<p><span style="font-family: courier new">&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">INNER JOIN</span> LoadTestCase <span style="color: #0000ff">AS</span> b <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">ON</span> a.LoadTestRunId = b.LoadTestRunId <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">AND</span> a.TestCaseId = b.TestCaseId</span></p>
<p><span style="font-family: courier new">&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">INNER JOIN</span> LoadTestScenario <span style="color: #0000ff">AS</span> c <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">ON</span> b.LoadTestRunId = c.LoadTestRunId <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">AND</span> b.ScenarioId = c.ScenarioId <br /><span style="color: #0000ff">GO</span> <br /></span></p>
<p><span style="font-family: courier new"><span style="font-family: arial">When we use this in a query, we get the proper names and IDs to use elsewhere:</span></span></p>
<p><span style="font-family: courier new"><span style="color: #0000ff">SELECT</span> * <span style="color: #0000ff">FROM</span> VSLT_View_PageNamesWithIDs <span style="color: #0000ff">WHERE</span> LoadTestRunId = 4</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/1307.View_PageNamesWithIds_49BFF3B5.png"><img style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" title="View_PageNamesWithIds" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/0361.View_PageNamesWithIds_thumb_64F84CB6.png" alt="View_PageNamesWithIds" width="644" height="112" border="0" /></a></p>
<p>In the table above, you can see how you get the proper request ID, which can be used to get info from the LoadTestPageDetails table, and you can determine which test or scenario the page was a part of. The key to this is to build the RequestNameWithId out of the request URI and the request ID. Visual Studio stores the page names and ID as a combined coluimn in the LoadTestPerformanceCounterInstance table. I will show how I incorporate this into creating results in the next post.</p>
<h3>Getting Formatted Perfmon Names From The DB</h3>
<p>The next view set I use is for populating some core tables and for <a href="https://blogs.msdn.com/b/geoffgr/archive/2014/10/15/importing-and-exporting-perfmon-counters-download.aspx" target="_blank">Perfmon Import/Export tool</a>. This view lays out the data in the three Perfmon naming tables in a way that is ready to add to graphs and tables, and makes adding filters to your queries easier when you are trying to get the Perfmon Instance ID that maps to the actual samples in the LoadTestPerformanceCounterSample table. The view does the typical INNER JOINs of the tables, but it also performs one other critical piece. Visual Studio uses a reserved word to indicate the instance for any counter that does not have instances available.</p>
<p>For example, the perfmon counter Memory/Available MBytes does not define instances. Because of this, the instance name would be NULL and that is not a good thing in this type of schema. So Visual Studio inserts the keyword <a href="https://referencesource.microsoft.com/#System/services/monitoring/system/diagnosticts/PerformanceCounterLib.cs" target="_blank">systemdiagnosticsperfcounterlibsingleinstance</a> in the instance name. In order to make items look good in reports, you need to remove that name, therefore the VIEW has the code to handle it.</p>
<p>Finally, the view also sets the order of the combined name in a format that is compatible with Perfmon CSV naming conventions:</p>
<p><span style="font-family: courier new"><span style="color: #0000ff">Machine</span><strong>\</strong><span style="color: #0000ff">Category</span><strong>(</strong><span style="color: #0000ff">Instance</span><strong>)\</strong><span style="color: #0000ff">Counter</span></span></p>
<p>Here is the code for the view:</p>
<p><span style="font-family: courier new"><span style="color: #0000ff">CREATE VIEW</span> VSLT_View_PerfmonInstanceNamesAndIds <span style="color: #0000ff">AS</span> <br />&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">SELECT</span> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance.LoadTestRunId <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,instance.InstanceId <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">,(</span> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #c0504d">'\\'</span> <span style="color: #9c85c0">+</span> category.MachineName <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">+</span> <span style="color: #c0504d">'\'</span> <span style="color: #9c85c0">+</span> category.CategoryName <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">+</span>&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">case</span> instance.InstanceName <span style="color: #0000ff">when</span> <span style="color: #c0504d">'systemdiagnosticsperfcounterlibsingleinstance'</span> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">then</span> <span style="color: #c0504d">''</span> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">else</span> <span style="color: #c0504d">'('</span> <span style="color: #9c85c0">+</span> instance.InstanceName&nbsp; <span style="color: #9c85c0">+</span> <span style="color: #c0504d">')'</span> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">end</span> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">+</span> <span style="color: #c0504d">'\'</span> <span style="color: #9c85c0">+</span> counter.CounterName <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">)</span> <span style="color: #0000ff">AS</span> InstanceName <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,category.MachineName <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,category.CategoryName <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,counter.CounterName <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,<span style="color: #9c85c0">(</span><span style="color: #0000ff">case</span> instance.InstanceName <span style="color: #0000ff">when</span> <span style="color: #c0504d">'systemdiagnosticsperfcounterlibsingleinstance'</span> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">then</span> <span style="color: #9c85c0">''</span> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">else</span> instance.InstanceName <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">end</span><span style="color: #9c85c0">)</span> <span style="color: #0000ff">AS</span> Instance <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,instance.LoadTestItemId</span></p>
<p><span style="font-family: courier new">&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">FROM</span> LoadTestPerformanceCounterCategory <span style="color: #0000ff">AS</span> category </span></p>
<p><span style="font-family: courier new">&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">INNER JOIN</span> LoadTestPerformanceCounter <span style="color: #0000ff">AS</span> counter <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">ON</span> category.LoadTestRunId = counter.LoadTestRunId <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">AND</span> category.CounterCategoryId = counter.CounterCategoryId</span></p>
<p><span style="font-family: courier new">&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">INNER JOIN</span> LoadTestPerformanceCounterInstance <span style="color: #0000ff">AS</span> instance <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff">ON</span> counter.CounterId = instance.CounterId <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #9c85c0">AND</span> counter.LoadTestRunId = instance.LoadTestRunId <br /><span style="color: #0000ff">GO</span></span></p>
<p>Here is a query that uses the view:</p>
<p><span style="font-family: courier new"><span style="color: #0000ff">SELECT</span> * <span style="color: #0000ff">FROM</span> VSLT_View_PerfmonInstanceNamesAndIds <span style="color: #0000ff">WHERE</span> LoadTestRunId = 4 <span style="color: #0000ff">AND</span> CategoryName <span style="color: #9c85c0">IN</span> (<span style="color: #c0504d">'Memory'</span>,<span style="color: #c0504d">'Processor'</span>)</span></p>
<p><span style="font-family: courier new"><span style="font-family: arial"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/0601.View_PerfmonInstanceNamesWithIds_4DCCD238.png"><img style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" title="View_PerfmonInstanceNamesWithIds" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/6201.View_PerfmonInstanceNamesWithIds_thumb_0AF08DBE.png" alt="View_PerfmonInstanceNamesWithIds" width="644" height="176" border="0" /></a></span></span></p>
<h3>Conclusion</h3>
<p>In the next post, I will show you some stored procedures that take advantage of these views, as well as some of the other views in the attached sql file. The sql file contains the following views:</p>
<ul>
<li>VSLT_View_PerfmonInstanceNamesAndIds</li>
<li>VSLT_View_PageSummary</li>
<li>VSLT_View_PageNamesWithIDs</li>
<li>VSLT_View_TestNamesWithIDs</li>
<li>VSLT_View_TransactionNamesWithIDs</li>
</ul>
<p>To use it, simply open it in a SQL editor (Visual Studio or SSMS) and execute it against the LoadTest2010 database.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/10/65/92/70/VSLT_Views.sql">VSLT_Views.sql</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Dissecting the Visual Studio Load Test Results Database (Part 3–Excel Reporting)</title>
      <link>https://docs.microsoft.com/archive/blogs/geoffgr/dissecting-the-visual-studio-load-test-results-database-part-3excel-reporting</link>
      <pubDate>Fri, 13 Nov 2015 06:42:00 GMT</pubDate>
      <dc:creator><![CDATA[geoffgr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/geoffgr/2015/11/13/dissecting-the-visual-studio-load-test-results-database-part-3excel-reporting/</guid>
      <description><![CDATA[In Part 3, we look at the sprocs and calls used to build reports in Excel.
The Excel Reporting...]]></description>
      <content:encoded><![CDATA[<p>In Part 3, we look at the sprocs and calls used to build reports in Excel.</p>
<h3>The Excel Reporting Feature</h3>
<p>In the 2010 release of Visual Studio Ultimate, a new feature was added that allows you to use Microsoft Excel to create either a Run Comparison or Trend Analysis report. You can read the <a href="https://msdn.microsoft.com/en-us/library/vstudio/dd997707(v=vs.140).aspx" target="_blank">standard documentation</a> to learn more about how to use the feature.</p>
<p>The feature uses Office COM Interop to interact with Excel by walking through a wizard, asking questions about how to report, letting you choose which perfmon counters to display, then creating different worksheets for each category chosen.</p>
<h3>Caveats</h3>
<p>The reporting add-in has a few noteable limitations:</p>
<ul>
<li>You can only select runs that were all created with the same loadtest name.</li>
<li>Once a report is created, you cannot change the inputs to it. You will need to create a new instance of the report to modify it (NOTE: You can use the existing report as a template to make creating the new report faster).</li>
<li>The templates that get created save the data categories to collect, but do NOT save any EXCEL formatting.</li>
<li>You cannot choose the time range(s) for the reports.</li>
<li>You must have access to Excel 2010 or newer, and it must be installed on the computer where you are viewing the test results.</li>
</ul>
<h3>Examples</h3>
<p><em><span style="color: #ff0000">The next section shows an example of the SQL calls made from Excel for each of the report types. I selected a bare minimum of counters to use for each report.</span></em></p>
<hr />
<h4>Building a Run Comparison Report</h4>
<p>When you select the &ldquo;Open and Manage Results&rdquo; dialog box, Visual Studio queries the <strong><span style="text-decoration: underline">LoadTestRun</span></strong> table and retrieves a list of available runs to choose from:</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT Name FROM sys.Databases ORDER BY 1 ASC</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryLoadTestReports </span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_FindLoadTestReport @reportId=-1,@name=N'LOADTEST_RUNCOMPARISON_REPORT_DEFAULT'</span></span></p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT DISTINCT LoadTestName FROM LoadTestRun ORDER BY 1 ASC</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec sp_executesql N'SELECT COUNT(*) FROM LoadTestReport WHERE Name = @ReportName',N'@ReportName nvarchar(16)',@ReportName=N'Some Report Name'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryLoadTestRuns @loadTestName=N'LoadTest1'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryPossibleCountersForReport @runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_CreateLoadTestReport @name=N'Some Report Name',@reportType=2,@description=N'',@loadTestName=N'LoadTest1', @lastModifiedBy=N'NORTHAMERICA\geoffgr',@lastRunId=2172, @selectNewReports=1,@runsXml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;',@pageXml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;pages&gt;&lt;p i="0" c="LoadTest:Page" t="Avg. Page Time" /&gt;<span style="color: #c0504d">...[truncated]...</span>&lt;/pages&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec Prc_QueryLoadTestTestComparison @Baseline=2157,@ComparisonRun=2158</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec Prc_QueryLoadTestPageComparison @Baseline=2157,@ComparisonRun=2158</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec Prc_QueryLoadTestTransactionComparison @Baseline=2157,@ComparisonRun=2158</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForMachinesInRun @Baseline=2157,@ComparisonRun=2158</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec Prc_QueryComputedCounterComparison @ReportId=4,@Baseline=2157,@ComparisonRun=2158</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec Prc_QueryLoadTestErrorComparison @Baseline=2157,@ComparisonRun=2158</span></span></p>
<hr />
<h4>Building a Trend Report</h4>
<p>Once you select a run and open it, there are a number of queries and Stored Procs that get called, filling DataSets in Visual Studio and allowing you to look at different graphs and tables. The bulk of core data is grabbed immediately and there are only a few instances where more trips to SQL will occur. Below is a list SQL calls made by selecting to open a single run. A few of the longer queries were truncated to save room on this post. You can run a SQL Profiler trace and capture all of the text yourself if you need to dig in deeper.:</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT Name FROM sys.Databases ORDER BY 1 ASC</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryLoadTestReports </span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_FindLoadTestReport @reportId=-1,@name=N'LOADTEST_TREND_REPORT_DEFAULT'</span></span></p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT DISTINCT LoadTestName FROM LoadTestRun ORDER BY 1 ASC</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec sp_executesql N'SELECT COUNT(*) FROM LoadTestReport WHERE Name = @ReportName',N'@ReportName nvarchar(5)',@ReportName=N'Trend'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryLoadTestRuns @loadTestName=N'00_LoadTest1'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec sp_executesql N'SELECT COUNT(*) FROM LoadTestReport WHERE Name = @ReportName',N'@ReportName nvarchar(5)',@ReportName=N'Trend'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryLoadTestRuns @loadTestName=N'LoadTest1'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryPossibleCountersForReport @runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_CreateLoadTestReport @name=N'Trend',@reportType=1,@description=N'',@loadTestName=N'LoadTest1', @lastModifiedBy=N'NORTHAMERICA\geoffgr',@lastRunId=2172, @selectNewReports=1,@runsXml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;',@pageXml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;pages&gt;&lt;p i="0" c="LoadTest:Page" t="Avg. Page Time" /&gt;&lt;p i="0" c="LoadTest:Page" t="Pages/Sec" /&gt;<span style="color: #c0504d">...[truncated]...</span>&lt;/pages&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'LoadTest:Page',@counterName=N'Avg. Page Time',@runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'LoadTest:Page',@counterName=N'Pages/Sec',@runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'LoadTest:Request',@counterName=N'Requests/Sec', @runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'LoadTest:Scenario',@counterName=N'User Load',@runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'LoadTest:Test',@counterName=N'Avg. Test Time',@runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'LoadTest:Test',@counterName=N'Total Tests',@runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'LoadTest:Transaction',@counterName=N'Avg. Response Time',@runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'LoadTest:Transaction',@counterName=N'Total Transactions',@runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'LoadTest:Transaction',@counterName=N'Transactions/Sec', @runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'Memory',@counterName=N'Available MBytes',@runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'Network Interface',@counterName=N'Bytes Total/sec',@runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'PhysicalDisk',@counterName=N'% Idle Time',@runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'Process',@counterName=N'% Processor Time',@runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec prc_QueryForInstanceCount @categoryName=N'Processor',@counterName=N'% Processor Time',@runsxml=N'&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;runs&gt;&lt;r i="2160" /&gt;&lt;r i="2159" /&gt;&lt;r i="2158" /&gt;&lt;r i="2157" /&gt;&lt;/runs&gt;'</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestPageSummary "5" , "Avg. Page Time"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestPageSummary "5" , "Avg. Page Time"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestPageSummary "5" , "Pages/Sec"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestPageSummary "5" , "Pages/Sec"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestRequestSummary "5" , "Requests/Sec"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestRequestSummary "5" , "Requests/Sec"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestScenarioSummary "5" , "User Load"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestScenarioSummary "5" , "User Load"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestTestCaseSummary "5" , "Avg. Test Time"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestTestCaseSummary "5" , "Avg. Test Time"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestTestCaseSummary "5" , "Total Tests"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestTestCaseSummary "5" , "Total Tests"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestTransactionSummary "5" , "Avg. Response Time"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestTransactionSummary "5" , "Avg. Response Time"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestTransactionSummary "5" , "Total Transactions"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestTransactionSummary "5" , "Total Transactions"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestTransactionSummary "5" , "Transactions/Sec"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryLoadTestTransactionSummary "5" , "Transactions/Sec"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryComputedCounterSummary "5" , "Available MBytes" , "Memory"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryComputedCounterSummary "5" , "Available MBytes" , "Memory"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryComputedCounterSummary "5" , "Bytes Total/sec" , "Network Interface"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryComputedCounterSummary "5" , "Bytes Total/sec" , "Network Interface"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryComputedCounterSummary "5" , "% Idle Time" , "PhysicalDisk"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryComputedCounterSummary "5" , "% Idle Time" , "PhysicalDisk"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryComputedCounterSummary "5" , "% Processor Time" , "Process"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryComputedCounterSummary "5" , "% Processor Time" , "Process"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryComputedCounterSummary "5" , "% Processor Time" , "Processor"</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">Prc_QueryComputedCounterSummary "5" , "% Processor Time" , "Processor"</span></span></p>
<hr />
<h4>Next: &ldquo;Scalpel Please&rdquo;&nbsp;&nbsp;</h4>
<p>In the next post, we will start our deep dive into &ldquo;Slicing and Dicing&rdquo; the data to show you what really happened.</p>]]></content:encoded>
    </item>
    <item>
      <title>Dissecting the Visual Studio Load Test Results Database (Part 1–Intro to the Schema)</title>
      <link>https://docs.microsoft.com/archive/blogs/geoffgr/dissecting-the-visual-studio-load-test-results-database-part-1intro-to-the-schema</link>
      <pubDate>Tue, 13 Oct 2015 03:52:00 GMT</pubDate>
      <dc:creator><![CDATA[geoffgr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/geoffgr/2015/10/13/dissecting-the-visual-studio-load-test-results-database-part-1intro-to-the-schema/</guid>
      <description><![CDATA[Sean Lumley wrote a good blog post years ago about the actual schema for the Visual Studio Load Test...]]></description>
      <content:encoded><![CDATA[<p>Sean Lumley wrote a good blog post years ago about the actual <a href="https://blogs.msdn.com/b/slumley/archive/2010/02/12/description-of-tables-and-columns-in-vs-2010-load-test-database.aspx"><strong>schema</strong> for the <strong>Visual</strong> <strong>Studio</strong> <strong>Load</strong> <strong>Test</strong> <strong>results</strong> <strong>database</strong></a>, but even with that post, navigating the DB and figuring out how things tie together can be confusing at the least, and sometimes almost impossible to figure out. I have been working inside the <strong>database</strong> for several years and have developed a pretty good understanding of how the <strong>schema</strong> works and how to navigate it. In this series of posts, I will share information about how the data is stored, why it is shaped the way it is, and how to extract the information you need for reporting.</p>
<h5>The High Level Schema</h5>
<p>The main <strong>schema</strong> for the <strong>database</strong> was created for the first version of VSTS in 2005. Since then the <strong>schema</strong> has been extended twice, but not changed. This is important because it means that any <strong>results</strong> from <strong>load</strong> tests run in VSTS 2005 are still valid and can still be viewed inside <strong>Visual</strong> <strong>Studio</strong>.</p>
<p>Every table in the <strong>database</strong> has a column for <em><strong>LoadTestRunId</strong></em>. This Id is generated for every single <strong>load</strong> <strong>test</strong> execution that is stored in the <strong>database</strong>. Before <strong>Visual</strong> <strong>Studio</strong> starts the execution of a <strong>test</strong>, it adds a row to the <strong><span style="text-decoration: underline">LoadTestRun</span></strong> table, which triggers the creation of a unique integer via <a href="https://msdn.microsoft.com/en-us/library/ms186775.aspx">SQL&rsquo;s Identity property</a>. Then it grabs that value and uses it throughout the rest of the execution and the writing of the <strong>results</strong>. (NOTE: You can use this step to query the <strong>results</strong> <strong>database</strong> inside a LoadTest plugin and capture the Id so you can add your own custom items to the <strong>database</strong> during a run. <a href="https://blogs.msdn.com/b/billbar/archive/2008/04/03/adding-console-output-to-load-tests-running-unit-tests.aspx">Bill Barnett helped me back in 2008 to do this with console messages for a SQL CE simulation <strong>load</strong> <strong>test</strong> harness using unit tests</a>. The <strong><span style="text-decoration: underline">LoadTestRun</span></strong> table is the primary &ldquo;list&rdquo; for all runs available. There is one row for each <strong>load</strong> <strong>test</strong> that has been executed (or is in the process of being executed).</p>
<p>The rest of the data is heavily normalized and most tables use a combination of the <em><strong>LoadTestRunId</strong></em> and other columns to create multi-column primary keys. The data tables are broken down into a few categories below, and the views (listed separately) are used to &ldquo;un-normalize the data for reporting purposes. The stored procedures will be covered in the next article.</p>
<h6>The Built In Tables</h6>
<ul>
<li><strong>Core Run Tables</strong>
<ul>
<li><strong>LoadTestRun</strong>: Primary Run Table - One row per <strong>load</strong> <strong>test</strong> run</li>
<li><strong>LoadTestSchemaRevision</strong>: For VS 2010 - 2015, this will have a single entry with the value of 3</li>
<li><strong>LoadTestCase</strong>: One row for each inner <strong>test</strong> referenced in the .loadtest file</li>
<li><strong>LoadTestFileAttachment</strong>: Used to store info about attachments from things like data collectors, etc</li>
<li><strong>LoadTestFileAttachmentChunk</strong>: Used to store the actual attachments from the above table</li>
<li><strong>LoadTestDataCollectorLog</strong>: Used to store info about the data collectors used during the run</li>
<li><strong>LoadTestTestLog</strong>: Stores the full testcase <strong>results</strong> of a <strong>test</strong> iteration that is logged</li>
<li><strong>LoadTestSqlTrace</strong>: Stores SQL Proifile data from tests where SQL Tracing is enabled</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>Core Detailed Timings Tables</strong> (These tables may not contain data for some runs. See <a href="https://blogs.msdn.com/b/geoffgr/archive/2013/10/03/all-about-load-test-results-and-the-results-db-part-1.aspx">this post</a>for more information)
<ul>
<li><strong>LoadTestTestDetail</strong>: Stores timing and outcome information for every iteration of every <strong>test</strong> executed.</li>
<li><strong>LoadTestPageDetail</strong>: Stores timing and outcome information for every iteration of every primary level request executed.</li>
<li><strong>LoadTestTransactionDetail</strong>: Stores timing information for every iteration of every transaction that successfully completed. If a request fails while inside a transaction, the transaction will not have an entry.</li>
<li><strong>LoadTestDetailMessage</strong>: One row for every message that occurs during a <strong>test</strong> run. This is the master list of errors.</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>Core Timings Summary Tables </strong>(Qty, Min, Avg, Max, 90%, 95%, 99%, Mean, Std Dev)&nbsp;&nbsp;
<ul>
<li><strong>LoadTestTestSummaryData</strong>: Stores the summary of the LoadTestTestDetail data</li>
<li><strong>LoadTestTransactionSummaryData</strong>: Stores the summary of the LoadTestTransactionDetail data</li>
<li><strong>LoadTestPageSummaryData</strong>: Stores the summary of the LoadTestPageDetail data</li>
<li><strong>LoadTestPageSummaryByNetwork</strong>: Stores the summary of the LoadTestPageDetail data, broken out by network emulator (if applicable)</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>Tables to map names to IDs</strong>
<ul>
<li><strong>WebLoadTestErrorDetail</strong>: (<em>normalized data</em>) Maps error messages to the web pages that caused the errors</li>
<li><strong>WebLoadTestRequestMap</strong>: (<em>normalized data</em>) Maps the request/page name to the PageId for the above tables</li>
<li><strong>WebLoadTestTransaction</strong>: (<em>normalized data</em>) Maps the transaction name to the transactionID for the above tables</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>Error Message Tables</strong>
<ul>
<li><strong>LoadTestMessage</strong>: The details for any message (error, etc) captured during execution</li>
<li><strong>LoadTestMessageType</strong>: (<em>normalized data</em>) the type of message for the above table</li>
<li><strong>LoadTestThresholdMessage</strong>: The details for any threshold violation captured during execution</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>Perfmon Tables </strong>(<em>NOTE: The way the data is stored for the pseudo counters [e.g. <strong>Test</strong>, Transaction, Page, etc] will be discussed in a separate post as <strong>part</strong> of this series.)</em>
<ul>
<li><strong>LoadTestPerformanceCounterCategory</strong>: (<em>normalized data</em>) Stores the perfmon CATEGORY and MACHINE for each perfmon category collected (One row per Machine/Category pair)</li>
<li><strong>LoadTestPerformanceCounter</strong>: (<em>normalized data</em>) Stores one row for each COUNTER collected inside each LoadTestPerformanceCounterCategory entry</li>
<li><strong>LoadTestPerformanceCounterInstance</strong>: (<em>normalized data</em>) Stores one row for each counter INSTANCE collected inside each LoadTestPerformanceCounter entry</li>
<li><strong>LoadTestPerformanceCounterSample</strong>: The actual perfom sampled values. Contains one row for each item in the LoadTestPerformanceCounterInstance table for each LoadTestRunInterval</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>SUT and RIG settings tables</strong>
<ul>
<li><strong>LoadTestRunAgent</strong>: (<em>normalized data</em>) One entry for each agent that was used during <strong>test</strong> execution</li>
<li><strong>LoadTestRunInterval</strong>: (<em>normalized data</em>) One entry for each sample interval during the <strong>test</strong></li>
<li><strong>LoadTestScenario</strong>: (<em>normalized data</em>) One entry for each Scenario defined in the .loadtest file</li>
<li><strong>LoadTestBrowsers</strong>: (<em>normalized data</em>) One entry for each browser type emulated in the <strong>test</strong></li>
<li><strong>LoadTestNetworks</strong>: (<em>normalized data</em>) One entry for each network type emulated in the <strong>test</strong></li>
<li><strong>LoadTestSystemUnderTest</strong>: (<em>normalized data</em>) One entry for each machine that had perfmon data collected and that was NOT a <strong>part</strong> of the <strong>test</strong> rig</li>
<li><strong>LoadTestSystemUnderTestTag</strong>: (<em>normalized data</em>) One row for each machine in LoadTestSystemUnderTest that contains a custom identifier tag</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>Excel Reporting historical data tables</strong>
<ul>
<li><strong>LoadTestReport</strong>: Stores configuration info about any Excel reports that have been created tyhrough the <strong>Visual</strong> <strong>Studio</strong> IDE</li>
<li><strong>LoadTestReportRuns</strong>: (<em>normalized data</em>)</li>
<li><strong>LoadTestReportPage</strong>: (<em>normalized data</em>)</li>
</ul>
</li>
</ul>
<h6>The Built In Views</h6>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>Summary Views</strong>
<ul>
<li><strong>LoadTestMessageSummary</strong>: Combines the LoadTestMessage, LoadTestCase, LoadTestScenario, LoadTestRunAgent, WebLoadTestRequestMap and WebLoadTestErrorDetail tables to provide a summary of the errors and threshold messages (<em>Defines: TestError, Exception, HttpError, ValidationRuleError, ExtractionRuleError, Timeout, DataCollectionError, DataCollectionWarning, Unknown</em>).</li>
<li><strong>LoadTestMessageView</strong>: Combines the LoadTestMessage, LoadTestCase, LoadTestScenario, LoadTestRunAgent, WebLoadTestRequestMap and WebLoadTestErrorDetail tables to provide details about the errors and threshold messages.</li>
<li><strong>LoadTestMessageView2</strong>: Combines the LoadTestMessage, LoadTestCase, LoadTestScenario, LoadTestRunAgent, WebLoadTestRequestMap, WebLoadTestErrorDetail and LoadTestTestLog tables to provide details about the errors and threshold messages.</li>
<li><strong>LoadTestPageResults</strong>: Combines the LoadTestPageSummaryData, WebLoadTestRequestMap, LoadTestCase and LoadTestScenario tables to provide a summary of page performance <span style="text-decoration: underline">based on</span> actaul page data.</li>
<li><strong>LoadTestPageResultsByNetwork</strong>: Combines the LoadTestPageSummaryByNetwork, WebLoadTestRequestMap, LoadTestCase, LoadTestScenario and LoadTestNetworks tables to provide a summary of page performance split into the different networks emulated <span style="text-decoration: underline">based on</span> actaul page data.</li>
<li><strong>LoadTestPageResultsByNetwork2</strong>: Provides the same info as LoadTestPageResultsByNetwork, except it adds 99%, Std Dev and Mean</li>
<li><strong>LoadTestTestResults</strong>: Combines the LoadTestTestSummaryData, LoadTestCase and LoadTestScenario tables to provide a summary of <strong>test</strong> performance <span style="text-decoration: underline">based on</span> actaul <strong>test</strong> data.</li>
<li><strong>LoadTestTransactionResults</strong>: Combines the LoadTestTransactionSummaryData, WebLoadTestTransaction, LoadTestCase and LoadTestScenario tables to provide a summary of transaction performance <span style="text-decoration: underline">based on</span> actaul transaction data.</li>
<li><strong>LoadTestTransactionResults2</strong>: Provides the same info as LoadTestTransactionSummaryData, except it adds 99%, Std Dev and Mean</li>
</ul>
</li>
</ul>
<hr align="center" size="2" width="100%" />
<ul>
<li><strong>Perfmon Data Views</strong>
<ul>
<li><strong>LoadTestComputedCounterSample</strong>: Combines the LoadTestPerformanceCounterCategory, LoadTestPerformanceCounter, LoadTestPerformanceCounterInstance, LoadTestPerformanceCounterSample and LoadTestRunInterval tables to provide perfmon sample values.</li>
<li><strong>LoadTestComputedCounterSummary</strong>: Combines the LoadTestRun, LoadTestPerformanceCounterCategory, LoadTestPerformanceCounter and LoadTestPerformanceCounterInstance tables to provide perfmon cumulative (summary) values.</li>
<li><strong>LoadTestPageSample</strong>: Combines the necessary tables to provide a sampled data of page performance <span style="text-decoration: underline">based on</span> sampled Perfmon Counters (<em>Used for graphing <strong>results</strong></em>).</li>
<li><strong>LoadTestPageSummary</strong>: Combines the necessary tables to provide a summary of page performance <span style="text-decoration: underline">based on</span> sampled Perfmon Counters.</li>
<li><strong>LoadTestRequestSummary</strong>: Combines the necessary tables to provide a summary of request performance <span style="text-decoration: underline">based on</span> sampled Perfmon Counters.</li>
<li><strong>LoadTestScenarioSummary</strong>: Combines the necessary tables to provide a summary of scenario performance <span style="text-decoration: underline">based on</span> sampled Perfmon Counters.</li>
<li><strong>LoadTestTestCaseSample</strong>: Combines the necessary tables to provide a sampled data of <strong>test</strong> case performance <span style="text-decoration: underline">based on</span> sampled Perfmon Counters (<em>Used for graphing <strong>results</strong></em>).</li>
<li><strong>LoadTestTestCaseSummary</strong>: Combines the necessary tables to provide a summary of <strong>test</strong> case performance <span style="text-decoration: underline">based on</span> sampled Perfmon Counters.</li>
<li><strong>LoadTestTransactionSample</strong>: Combines the necessary tables to provide a sampled data of transaction performance <span style="text-decoration: underline">based on</span> sampled Perfmon Counters (<em>Used for graphing <strong>results</strong></em>).</li>
<li><strong>LoadTestTransactionSummary</strong>: Combines the necessary tables to provide a summary of transaction performance <span style="text-decoration: underline">based on</span> sampled Perfmon Counters.</li>
<li><strong>LoadTestWebPageAndUserLoadCounterSample</strong>: Combines the necessary tables to provide a summary of request <strong>Throughput</strong> <span style="text-decoration: underline">based on</span> sampled Perfmon Counters.</li>
<li><strong>LoadTestWebRequestCounterSample</strong>: Combines the necessary tables to provide a sampled data of request performance <span style="text-decoration: underline">based on</span> sampled Perfmon Counters (<em>Used for graphing <strong>results</strong></em>).</li>
<li><strong>LoadTestWebRequestCounterSummary</strong>: Combines the necessary tables to provide a summary of total vs. passed request counts.</li>
</ul>
</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Dissecting the Visual Studio Load Test Results Database (Part 2–Stored Procs and Default Reporting)</title>
      <link>https://docs.microsoft.com/archive/blogs/geoffgr/dissecting-the-visual-studio-load-test-results-database-part-2stored-procs-and-default-reporting</link>
      <pubDate>Mon, 28 Sep 2015 11:17:00 GMT</pubDate>
      <dc:creator><![CDATA[geoffgr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/geoffgr/2015/09/28/dissecting-the-visual-studio-load-test-results-database-part-2stored-procs-and-default-reporting/</guid>
      <description><![CDATA[In Part 1, we visited the high level schema of the Visual Studio Load Test Results Database, showing...]]></description>
      <content:encoded><![CDATA[<p>In Part 1, we visited the high level schema of the Visual Studio Load Test Results Database, showing the tables and views that are a default part of the DB. In Part 2, we will look at the built in Stored Procedures and how some of them get used for building results and reports.</p>
<h3>The Sprocs</h3>
<p>The following list shows all of the built in stored procedures, broken down by the type of functionality they provide. [<em><span style="color: #666666">NOTE: All sprocs that have a 2 or 3 at the end denote a schema revision change where functionality was ADDED to the results. For any of these sprocs, the Schema Revision number stored with each run is used to determine which sproc to call. If the stored schema revision is higher than any of the sproc versions, the highest available sproc version is used.</span></em>]:</p>
<ul>
<li><strong><span style="font-size: x-small">Create/Delete</span></strong>- These are used to control creation and modification of data
<ul>
<li>Prc_DeleteDataCollectorLogs</li>
<li>Prc_DeleteLoadTestRun</li>
<li>prc_FindLoadTestReport</li>
<li>prc_GrantDBAccess</li>
</ul>
</li>
<li><strong><span style="font-size: x-small">Updating Results</span></strong> - These are called just after all results are written to the database at the end of a run. They perform the updates to the summary tables. <a href="https://blogs.msdn.com/b/geoffgr/archive/2013/10/03/all-about-load-test-results-and-the-results-db-part-1.aspx" target="_blank">See this article for more information</a>.
<ul>
<li>Prc_UpdateInstanceSummaryData</li>
<li>prc_UpdateLoadTestReport</li>
<li>Prc_UpdatePageByNetworkPercentiles</li>
<li>Prc_UpdatePagePercentiles</li>
<li>Prc_UpdatePageSummary</li>
<li>Prc_UpdatePageSummary3</li>
<li>Prc_UpdatePageSummaryByNetwork</li>
<li>Prc_UpdatePageSummaryByNetwork3</li>
<li>Prc_UpdateSummaryData</li>
<li>Prc_UpdateSummaryData2</li>
<li>Prc_UpdateSummaryData3</li>
<li>Prc_UpdateTestPercentiles</li>
<li>Prc_UpdateTestSummary</li>
<li>Prc_UpdateTestSummary3</li>
<li>Prc_UpdateTransactionPercentiles</li>
<li>Prc_UpdateTransactionSummary</li>
<li>Prc_UpdateTransactionSummary3</li>
</ul>
</li>
<li><strong><span style="font-size: x-small">Get Misc Info</span></strong>- These [along with various direct queries] grab various pieces of information for generating the results shown inside the Visual Studio IDE
<ul>
<li>Prc_GetAgents</li>
<li>Prc_GetAvailableDetailTypes</li>
<li>Prc_GetCategories</li>
<li>Prc_GetCompletedLoadTestRuns</li>
<li>Prc_GetErrorDetail</li>
<li>Prc_GetFirstSampleForInstance</li>
<li>Prc_GetInitialDetailRange</li>
<li>Prc_GetInstanceSummaries</li>
<li>Prc_GetLastSampleForInstance</li>
<li>Prc_GetRequestMap</li>
<li>Prc_GetRequestMap2</li>
<li>Prc_GetSamplesForInstance</li>
<li>Prc_GetTestCases</li>
<li>Prc_GetTestLog</li>
<li>Prc_GetTransactionMap</li>
<li>Prc_GetUniqueDetailIds</li>
<li>Prc_GetUserPageDetail</li>
<li>Prc_GetUserTestDetail</li>
<li>Prc_GetUserTransactionDetail</li>
</ul>
</li>
<li><strong><span style="font-size: x-small">Error Info</span></strong>- These get information about any errors that occurred during the run, including the details and the actual results, if available.
<ul>
<li>Prc_GetMessagesAll</li>
<li>Prc_GetMessagesAll2</li>
<li>Prc_GetMessagesByAgent</li>
<li>Prc_GetMessagesByAgent2</li>
<li>Prc_GetMessagesByRequest</li>
<li>Prc_GetMessagesByRequest2</li>
<li>Prc_GetMessagesByTest</li>
<li>Prc_GetMessagesByTest2</li>
<li>Prc_GetMessagesByType</li>
<li>Prc_GetMessagesByType2</li>
<li>Prc_GetMessagesTypeSummary</li>
</ul>
</li>
<li><strong><span style="font-size: x-small">Insertion Routines</span></strong>- These procs are called as part of the test execution [and 'Writing Results'] in order to store the data
<ul>
<li>Prc_InsertFileAttachmentChunk</li>
<li>Prc_InsertLoadTestDetailMessage</li>
<li>Prc_InsertLoadTestMessageType</li>
<li>Prc_InsertPageDetail</li>
<li>Prc_InsertPageDetail2</li>
<li>Prc_InsertSample</li>
<li>Prc_InsertSqlTraceRow</li>
<li>Prc_InsertTestDetail</li>
<li>Prc_InsertTestDetail2</li>
<li>Prc_InsertTestLog</li>
<li>Prc_InsertTransactionDetail</li>
<li>Prc_InsertTransactionDetail2</li>
</ul>
</li>
<li><strong><span style="font-size: x-small">Procs for Excel Reporting</span></strong>- These are used by Excel as part of the Excel Reporting AddIn provided by Visual Studio.
<ul>
<li>prc_CreateLoadTestReport</li>
<li>Prc_QueryComputedCounterComparison</li>
<li>Prc_QueryComputedCounterSummary</li>
<li>prc_QueryForInstanceCount</li>
<li>prc_QueryForMachinesInRun</li>
<li>Prc_QueryLoadTestErrorComparison</li>
<li>Prc_QueryLoadTestPageComparison</li>
<li>Prc_QueryLoadTestPageSummary</li>
<li>prc_QueryLoadTestReports</li>
<li>Prc_QueryLoadTestRequestSummary</li>
<li>prc_QueryLoadTestRuns</li>
<li>prc_QueryLoadTestRunsById</li>
<li>Prc_QueryLoadTestScenarioSummary</li>
<li>Prc_QueryLoadTestTestCaseSummary</li>
<li>Prc_QueryLoadTestTestComparison</li>
<li>Prc_QueryLoadTestTransactionComparison</li>
<li>Prc_QueryLoadTestTransactionSummary</li>
<li>prc_QueryPossibleCountersForReport</li>
</ul>
</li>
</ul>
<h3>Examples</h3>
<p><em><span style="color: #ff0000">The next section shows an example of the work that Visual Studio performs when opening a result from the database. The information was captured from a run that had been exported from a full test rig and loaded into my <a href="https://blogs.msdn.com/b/geoffgr/archive/2014/01/06/off-topic-microsoft-surface-pro-ii-review.aspx" target="_blank">Surface Pro 2</a>. I had not added any extra graph objects to the results and all graphing options are still set to default. When you open runs, the queries, sprocs and arguments passed into both will vary. The purpose of this is to allow you to see a fairly representative sample of the data flow between Visual Studio and SQL.</span></em></p>
<hr />
<h4>Opening the Manage Results Dialog</h4>
<p>When you select the &ldquo;Open and Manage Results&rdquo; dialog box, Visual Studio queries the <strong><span style="text-decoration: underline">LoadTestRun</span></strong> table and retrieves a list of available runs to choose from:</p>
<p><span style="font-family: Courier New"><span style="color: #0000ff">select LoadTestRunId, RunId, LoadTestName, Description, Comment, IsLocalRun, ControllerName, StartTime, EndTime, WarmupTime, RunDuration, LoadTest, Outcome, LoadTestSchemaRev,CooldownTime from LoadTestRun where LoadTestRunId = 2156</span></span></p>
<hr />
<h4>Opening a Result</h4>
<p>Once you select a run and open it, there are a number of queries and Stored Procs that get called, filling DataSets in Visual Studio and allowing you to look at different graphs and tables. The bulk of core data is grabbed immediately and there are only a few instances where more trips to SQL will occur. Below is a list SQL calls made by selecting to open a single run. A few of the longer queries were truncated to save room on this post. You can run a SQL Profiler trace and capture all of the text yourself if you need to dig in deeper.:</p>
<p><span style="font-size: x-small"><strong><strong><span style="font-size: x-small"><strong><span style="font-size: x-small">Query</span></strong></span></strong>: </strong></span><span style="font-family: Courier New"><span style="color: #0000ff">select LoadTestRunId, RunId, LoadTestName, Description, Comment, IsLocalRun, ControllerName, StartTime, EndTime, WarmupTime, RunDuration, LoadTest, Outcome, LoadTestSchemaRev,CooldownTime from LoadTestRun where LoadTestRunId = 2156</span></span></p>
<p><strong><span style="font-size: x-small"><strong><span style="font-size: x-small">Sproc</span></strong>: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec Prc_GetRequestMap2 @LoadTestRunId=2156</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec Prc_GetCategories @LoadTestRunId=2156</span></span></p>
<p><strong><span style="font-size: x-small"><strong><span style="font-size: x-small">Query</span></strong>: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT TestCaseId,Percentile90,Percentile95 FROM LoadTestTestSummaryData WHERE LoadTestRunId = 2156</span></span></p>
<p><strong><span style="font-size: x-small"><strong><span style="font-size: x-small">Query</span></strong>: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT TransactionId,Percentile90,Percentile95 FROM LoadTestTransactionSummaryData WHERE LoadTestRunId = 2156</span></span></p>
<p><strong><span style="font-size: x-small"><strong><span style="font-size: x-small">Query</span></strong>: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT PageId,Percentile90,Percentile95 FROM LoadTestPageSummaryData WHERE LoadTestRunId = 2156</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec Prc_GetInstanceSummaries @LoadTestRunId=2156</span></span></p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT TOP 1000 category.MachineName, category.CategoryName, </span></span>[<span style="background-color: #ffff00">truncated</span>]</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec Prc_GetMessagesTypeSummary @LoadTestRunId=2156</span></span></p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">select FileAttachmentId, MachineName, Filename, Filesize from LoadTestFileAttachment where LoadTestRunId = 2156</span></span></p>
<p><strong><span style="font-size: x-small"><strong><span style="font-size: x-small">Query</span></strong>: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">select DataCollectorLogId, DataCollectorDisplayName, MachineName from LoadTestDataCollectorLog where LoadTestRunId = 2156</span></span></p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT ScenarioName, TestCaseName, TransactionName, TransactionCount, Minimum, Maximum, Average, Median, Percentile90, Percentile95, Percentile99, StandardDeviation, AvgTransactionTime FROM LoadTestTransactionResults2 where LoadTestRunId = 2156 ORDER BY ScenarioName, TestCaseName, TransactionName</span></span></p>
<p><strong><span style="font-size: x-small"><strong><span style="font-size: x-small">Query</span></strong>: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT ScenarioName, TestCaseName, RequestUri, NetworkName, PageCount, Minimum, Maximum, Average, Median, Percentile90, Percentile95, Percentile99, StandardDeviation, Goal, PagesMeetingGoal FROM LoadTestPageResultsByNetwork2 where LoadTestRunId = 2156 ORDER BY ScenarioName, TestCaseName, RequestUri, NetworkName</span></span></p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT samples.InstanceId, interval.IntervalEndTime, samples.RawValue, </span></span>[<span style="background-color: #ffff00">truncated</span>]</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT TOP 1000 Event = CASE EventClass WHEN 10 THEN 'RPCCompleted' </span></span></p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT samples.InstanceId, interval.IntervalEndTime, samples.RawValue, </span></span>[<span style="background-color: #ffff00">truncated</span>]</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT samples.InstanceId, interval.IntervalEndTime, samples.RawValue, </span></span>[<span style="background-color: #ffff00">truncated</span>]</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT samples.InstanceId, interval.IntervalEndTime, samples.RawValue, </span></span>[<span style="background-color: #ffff00">truncated</span>]</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT samples.InstanceId, interval.IntervalEndTime, samples.RawValue, </span></span>[<span style="background-color: #ffff00">truncated</span>]</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT samples.InstanceId, interval.IntervalEndTime, samples.RawValue, </span></span>[<span style="background-color: #ffff00">truncated</span>]</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT samples.InstanceId, interval.IntervalEndTime, samples.RawValue, </span></span>[<span style="background-color: #ffff00">truncated</span>]</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT samples.InstanceId, interval.IntervalEndTime, samples.RawValue, </span></span>[<span style="background-color: #ffff00">truncated</span>]</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT samples.InstanceId, interval.IntervalEndTime, samples.RawValue, </span></span>[<span style="background-color: #ffff00">truncated</span>]</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT samples.InstanceId, interval.IntervalEndTime, samples.RawValue, </span></span>[<span style="background-color: #ffff00">truncated</span>]</p>
<hr />
<h4>Adding a Graph Item</h4>
<p>Many of the graph items that you might add will already be stored in the DataSets in Visual Studio. However, if you choose to add a perfmon counter to a graph that has not been loaded, the following will get executed:</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT samples.InstanceId,interval.IntervalEndTime, samples.RawValue, samples.BaseValue, samples.CounterFrequency, samples.SystemFrequency, samples.SampleTimeStamp, samples.SampleTimeStamp100nSec, samples.CounterType, samples.ThresholdRuleResult FROM LoadTestPerformanceCounterSample as samples LEFT OUTER JOIN LoadTestRunInterval AS interval ON samples.LoadTestRunId = interval.LoadTestRunId AND samples.TestRunIntervalId = interval.TestRunIntervalId WHERE samples.LoadTestRunId = 2156 AND (samples.InstanceId = 93) ORDER BY samples.InstanceId, samples.TestRunIntervalId</span></span></p>
<hr />
<h4>Viewing a Table Item</h4>
<p>Table items such as Tests, Transactions, Pages, etc. are already in the DataSets, but a couple of tables (such as Threshold and SQL Trace) are not pre-loaded. The following shows what will execute if you select the Threshold table:</p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">SELECT TOP 1000 category.MachineName, category.CategoryName, counter.CounterName, instance.InstanceName, interval.IntervalEndTime, countersample.ThresholdRuleResult, thresholdMessage.MessageText FROM LoadTestPerformanceCounterCategory AS category INNER JOIN LoadTestPerformanceCounter AS counter ON category.LoadTestRunId = counter.LoadTestRunId AND category.CounterCategoryId = counter.CounterCategoryId INNER JOIN LoadTestPerformanceCounterInstance AS instance ON counter.CounterId = instance.CounterId AND counter.LoadTestRunId = instance.LoadTestRunId INNER JOIN LoadTestPerformanceCounterSample AS countersample ON countersample.InstanceId = instance.InstanceId AND countersample.LoadTestRunId = instance.LoadTestRunId INNER JOIN LoadTestRunInterval AS interval ON interval.LoadTestRunId = countersample.LoadTestRunId AND interval.TestRunIntervalId = countersample.TestRunIntervalId INNER JOIN LoadTestThresholdMessage AS thresholdMessage ON interval.LoadTestRunId = thresholdMessage.LoadTestRunId AND interval.TestRunIntervalId = thresholdMessage.TestRunIntervalId AND countersample.ThresholdRuleMessageId = thresholdMessage.MessageId WHERE countersample.ThresholdRuleMessageId IS NOT NULL AND thresholdMessage.LoadTestRunId = 2156 ORDER BY interval.IntervalEndTime ASC</span></span></p>
<h4>&nbsp;</h4>
<hr />
<h4>The Details Tab</h4>
<p>The following sprocs and queries get executed whenever you switch to the &ldquo;Details&rdquo; tab:</p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec Prc_GetUniqueDetailIds @LoadTestRunId=2156,@DetailType=0</span></span></p>
<p><strong><span style="font-size: x-small">Query: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">select MessageTypeId, MessageType, SubType from LoadTestMessageType where LoadTestRunId = 2156</span></span></p>
<p><strong><span style="font-size: x-small">Sproc: </span></strong><span style="font-family: Courier New"><span style="color: #0000ff">exec Prc_GetAvailableDetailTypes @LoadTestRunId=2156</span></span></p>
<hr />
<h3>Next: Excel&hellip;</h3>
<p>In the next post, we will dive into the sprocs and queries used for the built in Excel Reporting.</p>]]></content:encoded>
    </item>
    <item>
      <title>How Does the User Pacing model differ from the Number of Tests Started model</title>
      <link>https://docs.microsoft.com/archive/blogs/geoffgr/how-does-the-user-pacing-model-differ-from-the-number-of-tests-started-model</link>
      <pubDate>Tue, 16 Jun 2015 04:55:12 GMT</pubDate>
      <dc:creator><![CDATA[geoffgr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/geoffgr/2015/06/16/how-does-the-user-pacing-model-differ-from-the-number-of-tests-started-model/</guid>
      <description><![CDATA[In my post on User Load Profiles, I talked about choosing one of two different load models, based on...]]></description>
      <content:encoded><![CDATA[<p>In my post on <a href="https://blogs.msdn.com/b/geoffgr/archive/2014/09/10/all-about-load-test-planning-part-4-building-the-load-profile.aspx" target="_blank">User Load Profiles</a>, I talked about choosing one of two different load models, based on a couple of the options in Visual Studio. However, I have still received a lot of requests to clarify these two models and to show how I can apply one of the models to the testing I am going to do. Hopefully this post will help clarify some of this.</p>  <p>Each model can easily be selected regardless of what webtests you have created and both can easily be ramped up to different load levels. The primary difference between the two is how Visual Studio handles the think time between each iteration of the virtual users:</p>  <ul>   <li>“<strong>Based on Number Of Tests Started</strong>” executes the test and then waits for the amount of time provided in the “<strong>Think Time Between Test Iterations</strong>” property for the scenario. The start time for the first iteration for each vUser is the start time of the vUser. </li>    <li>“<strong>Based on User Pace</strong>” gets a rough estimate of how long each iteration can execute and still leave enough time for all subsequent iterations to complete. (e.g. 30 tests/user/hour = one test per user every 2 minutes.) The actual start time for the test iteration will be random and can happen anywhere within the calculated window. </li> </ul>  <p><strong>Based on User Pace</strong> is much more predictable regardless of response times and <strong>Based on Number Of Tests Started</strong> is much better at driving load as fast as the system can respond. The images below show the user responses for two virtual users in each of four different load tests:</p>  <ul>   <li>100 users – Based on Number Of Tests Started </li>    <li>100 users – Based on User Pace </li>    <li>1000 users – Based on Number Of Tests Started </li>    <li>1000 users – Based on User Pace </li> </ul>  <p>The four graphs below are representative of the User Activity graphs in Visual Studio, but simplified to make the explanation easier. The blue boxes represent the execution of a single iteration of a test by a single user. The space in between blue boxes is the <strong>Think Time Between Test Iterations</strong>. The gray line at the bottom represents the number of minutes into the overall load test execution.</p>  <p>In tests 1 and 2, we see that the response times are the same, but that test 1 completed more iterations (10) than test 2 (5).</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/0412.numTestsLightLoad_6B12A2AF.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-07-58-metablogapi/0412.numTestsLightLoad_5F00_6B12A2AF.png"><img title="numTestsLightLoad" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="numTestsLightLoad" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/3162.numTestsLightLoad_thumb_21EF87A7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-07-58-metablogapi/3162.numTestsLightLoad_5F00_thumb_5F00_21EF87A7.png" width="644" height="66" /></a></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/7317.userPaceLightLoad_614D3B37.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-07-58-metablogapi/7317.userPaceLightLoad_5F00_614D3B37.png"><img title="userPaceLightLoad" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="userPaceLightLoad" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/7416.userPaceLightLoad_thumb_70EFD6F9.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-07-58-metablogapi/7416.userPaceLightLoad_5F00_thumb_5F00_70EFD6F9.png" width="644" height="66" /></a></p>  <p>In tests 3 and 4, the load against the system has caused the response times to slow down. Test 3 (which is identical to test 1 except for the number of virtual users) now only completes six iterations per user. <em>(NOTE: The iteration in yellow is a test that started but did not complete in the allotted time and therefore isnot counted in the results. See </em><a href="https://blogs.msdn.com/b/geoffgr/archive/2013/08/24/explanation-of-v-s-load-test-warm-up-load-patterns-and-cool-down-and-how-this-affects-the-reported-results.aspx" target="_blank"><em>this post</em></a><em> for details</em>) Test 4 (which is identical to test 2) still completes 5 iterations per user.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/7343.numTestsHeavyLoad_5A308F70.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-07-58-metablogapi/7343.numTestsHeavyLoad_5F00_5A308F70.png"><img title="numTestsHeavyLoad" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="numTestsHeavyLoad" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/1884.numTestsHeavyLoad_thumb_554DDBB4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-07-58-metablogapi/1884.numTestsHeavyLoad_5F00_thumb_5F00_554DDBB4.png" width="644" height="66" /></a></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/5148.userPaceHeavyLoad_7E587AB0.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-07-58-metablogapi/5148.userPaceHeavyLoad_5F00_7E587AB0.png"><img title="userPaceHeavyLoad" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="userPaceHeavyLoad" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/2330.userPaceHeavyLoad_thumb_72568A7C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-07-58-metablogapi/2330.userPaceHeavyLoad_5F00_thumb_5F00_72568A7C.png" width="644" height="66" /></a></p>  <p>The best way to think about this is to observe the “white” space in the images above. This represents the “<strong>think time between iterations.</strong>” </p>  <ul>   <li>With both load profile models, the System Under Test (SUT) controls the time it takes to complete an iteration. </li>    <li>With <strong>Based on Number Of Tests Started</strong> you control the amount of think time (or pacing). </li>    <li>With <strong>Based on User Pace</strong>, Visual Studio controls this, and it uses the SUT’s response time to set it. </li>    <li>If you want to drive load against the system quickly and irrespective of the throughput, then use <strong>Based on Number Of Tests Started.</strong> </li>    <li>If you want to drive load against the system and know that you are providing a known throughput, then use <strong>Based on User Pace.</strong> </li> </ul>]]></content:encoded>
    </item>
    <item>
      <title>All About Load Test Results and the Results DB (Part 5–Requests vs. Pages vs. Transactions</title>
      <link>https://docs.microsoft.com/archive/blogs/geoffgr/all-about-load-test-results-and-the-results-db-part-5requests-vs-pages-vs-transactions</link>
      <pubDate>Wed, 10 Jun 2015 07:04:56 GMT</pubDate>
      <dc:creator><![CDATA[geoffgr]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/geoffgr/2015/06/10/all-about-load-test-results-and-the-results-db-part-5requests-vs-pages-vs-transactions/</guid>
      <description><![CDATA[I was recently asked about the details of transaction timers and realized that I have not made a...]]></description>
      <content:encoded><![CDATA[<p>I was recently asked about the details of transaction timers and realized that I have not made a post that clearly shows the differences between the various timers that Visual Studio collects and reports on. While there is a good help file page on this in the online documentation (<a title="https://msdn.microsoft.com/en-us/library/ms404656.aspx" href="https://msdn.microsoft.com/en-us/library/ms404656.aspx" target="_blank">https://msdn.microsoft.com/en-us/library/ms404656.aspx</a>), I thought I would show a simple example.</p>  <h3>Timing Relationships</h3>  <p>I recorded a webtest against Wikipedia and created a couple of transaction timers in the test. Then I ran the test in order to get the various timers as Visual Studio collects them. Below you can see that </p>  <ol>   <li>each request gets its own timer regardless of whether it is a primary request, a dependent request or a redirect request. </li>    <li>each request that has dependent and/or redirect requests also gets a timer (called a page timer) </li>    <li>each transaction timer I added to the test also gets a timer that includes the sum of all page timers for requests inside the transaction. </li> </ol>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/8551.Webtest-results-annotated_small_3C74CB7C.png"><img title="Webtest results annotated_small" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;padding-right: 0px" border="0" alt="Webtest results annotated_small" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/2664.Webtest-results-annotated_small_thumb_3964FE38.png" width="644" height="390" /></a></p>  <h3>The Effect of “Stop On Error” with Transaction Timers</h3>  <p>Visual Studio webtests have a property called “Stop On Error” which, when set to True will cause the current iteration of the webtest to stop execution as soon as a request fails or the test encounters an error. This is NOT the default behavior, but I recommend that you set it to True because if something fails, chances are that the next requests will probably also fail. <strong><em><u><font color="#ff0000">I suggest always setting this value to True</font></u></em></strong>.</p>  <h5>Setting the value:</h5>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/0844.Stop-On-Error-setting_2ABCE304.png"><img title="Stop On Error setting" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="Stop On Error setting" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/6116.Stop-On-Error-setting_thumb_41128849.png" width="604" height="363" /></a></p>  <h5>If the test passes, there is no effect.</h5>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/4087.Passed_297D6B87.jpg"><img title="Passed" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="Passed" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/1616.Passed_thumb_6B17A7D3.jpg" width="604" height="368" /></a></p>  <h5>If Stop On Error is TRUE and the test fails, the Transaction Timer will NOT be collected or reported.</h5>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/1643.failed-true_7ABA4395.jpg"><img title="failed-true" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="failed-true" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/6406.failed-true_thumb_1112798C.jpg" width="604" height="368" /></a></p>  <h5>If Stop On Error is FALSE and the test fails, the Transaction Timer WILL be collected and reported</h5>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/0083.Failed-False_4716F899.jpg"><img title="Failed-False" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="Failed-False" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/8877.Failed-False_thumb_369E879E.jpg" width="604" height="368" /></a></p>  <h3>Avg Transaction Time vs. Avg Response Time</h3>  <p>In a load test, you will see two different average values available for transaction timers: (<strong>Avg. Transaction Time</strong> and <strong>Avg. Response Time</strong>). The difference is that the <strong><em>Transaction</em></strong> time includes any think times associated with the requests inside the transaction and <strong><em>Response</em></strong> time does NOT include any think time. The below test has two transactions and only SearchResults has a request with Think Time. <font color="#ff0000">(<strong>NOTE</strong>: On the Summary page, the <strong><em>Transaction Time</em></strong> is referred to as <strong><em>Elapsed Time</em></strong>)</font></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/5153.TransVsResponse_46412360.png"><img title="TransVsResponse" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="TransVsResponse" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/2538.TransVsResponse_thumb_6F4BC25C.png" width="604" height="291" /></a></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/6685.TransVsResponseSummary_0A841B5E.png"><img title="TransVsResponseSummary" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="TransVsResponseSummary" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/07/58/metablogapi/2818.TransVsResponseSummary_thumb_33228765.png" width="604" height="230" /></a></p>]]></content:encoded>
    </item>
  </channel>
</rss>