/// <summary> /// Initializes a new instance of the <see cref="ReplayFilerRunnerResult"/> class. /// </summary> /// <param name="description">The description, from the replay file.</param> /// <param name="baseUri">The base URI.</param> /// <param name="uri">The relative URI.</param> /// <param name="iterations">The number of iterations performed.</param> /// <param name="concurrentRequests">The number of concurrent requests performed.</param> /// <param name="lastStatusCode">The last status code observed.</param> /// <param name="lastResponseBodySize">The last size of the response body observed.</param> /// <param name="lastResponseBodyChecksum">The last response body checksum observed.</param> /// <param name="responseTimeStats">The response time statistics</param> /// <param name="requestsPerSec">The number of requests per second.</param> /// <param name="testStartTime">The approximate timestamp when the first iteration started.</param> /// <param name="testEndTime">The approximate timestamp when all iterations finished.</param> public ReplayFilerRunnerResult( string description, string baseUri, string uri, int iterations, int concurrentRequests, int lastStatusCode, long lastResponseBodySize, string lastResponseBodyChecksum, PercentileStats<TimeSpan> responseTimeStats, double requestsPerSec, DateTimeOffset testStartTime, DateTimeOffset testEndTime) { this.responseTimeStats = responseTimeStats; this.Description = description; this.BaseUri = baseUri; this.Uri = uri; this.Iterations = iterations; this.ConcurrentRequests = concurrentRequests; this.LastStatusCode = lastStatusCode; this.LastResponseBodySize = lastResponseBodySize; this.LastResponseBodyChecksum = lastResponseBodyChecksum; this.RequestsPerSec = requestsPerSec; this.TestStartTime = testStartTime; this.TestEndTime = testEndTime; }
/// <summary> /// Asynchronously runs the specified replay file. /// </summary> /// <param name="replayFile">The replay file.</param> /// <param name="callback">The callback to call at the completion of each of the request in the replay file..</param> /// <param name="uriRunnerOptions">The options for the uri runner.</param> /// <param name="iterations">The iterations.</param> /// <param name="concurrentRequests">The number of concurrent requests to execute.</param> /// <returns>The list of the results.</returns> public static async Task RunReplayFileAsync( ReplayFile replayFile, Action<ReplayFilerRunnerResult> callback, UriRunnerOptions uriRunnerOptions, int iterations = 1, int concurrentRequests = 1) { var consoleWriteLine = StringWriterFuns.ConsoleWriter(); using (var handler = new HttpClientHandler()) using (var client = new HttpClient(handler)) { handler.AllowAutoRedirect = true; handler.AutomaticDecompression = DecompressionMethods.None; handler.UseProxy = true; // Need to set this to false to make sure the http client does not // mess around with our own cookies. handler.UseCookies = false; client.BaseAddress = new Uri(replayFile.BaseUri); foreach (var header in replayFile.Headers) { if (!client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value)) { consoleWriteLine("Failed to add header: {0} = {1}", header.Key, header.Value); } } foreach (var uri in replayFile.Uris) { var sw = new Stopwatch(); var numberOfRequests = iterations * concurrentRequests; var allResults = new List<UriRunnerResult>(capacity: numberOfRequests); var startTimeUtc = DateTimeOffset.UtcNow; // Exec same URI with the specified concurrency level var uris = Enumerable.Repeat(uri, concurrentRequests).ToArray(); for (var i = 0; i < iterations; i++) { sw.Start(); var runUrisResults = await UriRunner.RunUrisConcurrentlyAsync( client: client, uris: uris, uriRunnerOptions: uriRunnerOptions); sw.Stop(); allResults.AddRange(runUrisResults); } var endTimeUtc = DateTimeOffset.UtcNow; var requestsPerSec = (double)numberOfRequests / sw.Elapsed.TotalSeconds; var responseTimes = allResults.Select(r => r.ResponseTime); var percentiles = new PercentileStats<TimeSpan>(responseTimes); var lastResult = allResults.Last(); var reportLine = new ReplayFilerRunnerResult( iterations: iterations, concurrentRequests: concurrentRequests, lastStatusCode: (int)lastResult.StatusCode, lastResponseBodySize: lastResult.BodySize, lastResponseBodyChecksum: lastResult.BodyChecksum, responseTimeStats: percentiles, description: replayFile.Description, baseUri: replayFile.BaseUri, uri: uri, requestsPerSec: requestsPerSec, testStartTime: startTimeUtc, testEndTime: endTimeUtc); if (callback != null) { callback(reportLine); } } } }