Skip to content

Commit

Permalink
Merge pull request #7 from dusrdev:No-Export-Content-Length
Browse files Browse the repository at this point in the history
No-Export-Content-Length
  • Loading branch information
dusrdev authored Nov 11, 2024
2 parents 55c0a3e + 197f18b commit 99a4d47
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 29 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Implemented much better mechanism to keep to track of concurrent connections, as well vastly improved the control and execution model of limited max connections parallel pulse.
- `-b`, `--batch` is not longer a valid parameter, now the parameter is `-c` (connections) to better reflect the real behavioral effect.
- Implement better mechanism to keep track of content size, now it should require less resources and be available even when `--no-export` is used.

## Version 1.0.3.0

Expand Down
6 changes: 6 additions & 0 deletions src/Pulse/Core/PulseMonitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public async Task SendAsync(int requestId) {
internal static async Task<Response> SendRequest(int id, Request requestRecipe, HttpClient httpClient, bool saveContent, CancellationToken cancellationToken = default) {
HttpStatusCode statusCode = 0;
string content = "";
long contentLength = 0;
int currentConcurrencyLevel = 0;
StrippedException exception = StrippedException.Default;
var headers = Enumerable.Empty<KeyValuePair<string, IEnumerable<string>>>();
Expand All @@ -105,6 +106,10 @@ internal static async Task<Response> SendRequest(int id, Request requestRecipe,
Interlocked.Decrement(ref _concurrencyLevel);
statusCode = response.StatusCode;
headers = response.Headers;
var length = response.Content.Headers.ContentLength;
if (length.HasValue) {
contentLength = length.Value;
}
if (saveContent) {
content = await response.Content.ReadAsStringAsync(cancellationToken);
}
Expand All @@ -125,6 +130,7 @@ internal static async Task<Response> SendRequest(int id, Request requestRecipe,
StatusCode = statusCode,
Headers = headers,
Content = content,
ContentLength = contentLength,
Duration = duration,
Exception = exception,
MaximumConcurrencyLevel = currentConcurrencyLevel
Expand Down
14 changes: 3 additions & 11 deletions src/Pulse/Core/PulseSummary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ public sealed class PulseSummary {
/// </summary>
public required Parameters Parameters { get; init; }

/// <summary>
/// The character encoding to use
/// </summary>
public Encoding CharEncoding { get; init; } = Encoding.Default;

/// <summary>
/// Produces a summary, and saves unique requests if export is enabled.
/// </summary>
Expand Down Expand Up @@ -65,8 +60,7 @@ public sealed class PulseSummary {
maxDuration = Math.Max(maxDuration, duration);
avgDuration += multiplier * duration;
// size
ReadOnlySpan<char> span = result.Content ?? ReadOnlySpan<char>.Empty;
var size = CharEncoding.GetByteCount(span);
var size = result.ContentLength;
if (size > 0) {
minSize = Math.Min(minSize, size);
maxSize = Math.Max(maxSize, size);
Expand Down Expand Up @@ -124,10 +118,8 @@ public sealed class PulseSummary {
public (bool exportRequired, HashSet<Response> uniqueRequests) SummarizeSingle() {
var result = Result.Results.First();
double duration = result.Duration.TotalMilliseconds;
ReadOnlySpan<char> span = result.Content ?? ReadOnlySpan<char>.Empty;
var size = CharEncoding.GetByteCount(span);

var statusCode = result.StatusCode;

ClearNextLinesError(3);
WriteLine("Summary:" * Color.Green);
WriteLine(["Request count: ", "1" * Color.Yellow]);
Expand All @@ -142,7 +134,7 @@ public sealed class PulseSummary {
WriteLine(["Success: ", "false" * Color.Red]);
}
WriteLine(["Request Duration: ", $"{duration:0.##}ms" * Color.Cyan]);
WriteLine(["Content Size: ", Utils.Strings.FormatBytes(size) * Color.Cyan]);
WriteLine(["Content Size: ", Utils.Strings.FormatBytes(result.ContentLength) * Color.Cyan]);
if (statusCode is 0) {
WriteLine(["Status code: ", "0 [Exception]" * Color.Red]);
} else {
Expand Down
5 changes: 5 additions & 0 deletions src/Pulse/Core/Response.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public readonly struct Response {
/// </summary>
public required string Content { get; init; }

/// <summary>
/// The response content length
/// </summary>
public required long ContentLength { get; init; }

/// <summary>
/// The time taken from sending the request to receiving the response
/// </summary>
Expand Down
51 changes: 33 additions & 18 deletions tests/Pulse.Tests.Unit/ExporterTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Net;
using System.Text;

using Pulse.Configuration;

Expand Down Expand Up @@ -41,24 +42,27 @@ public void Exporter_ToHtmlTable_ContainsAllHeaders() {
new("X-Custom-Header", ["value1", "value2"])
};

const string content = "Hello World";

var response = new Response {
Id = 1337,
StatusCode = HttpStatusCode.OK,
Content = "Hello World",
Content = content,
ContentLength = Encoding.Default.GetByteCount(content),
Headers = headers,
Exception = StrippedException.Default,
Duration = TimeSpan.FromSeconds(1),
MaximumConcurrencyLevel = 1
};

// Act
var content = Exporter.ToHtmlTable(response.Headers);
var fileContent = Exporter.ToHtmlTable(response.Headers);

// Assert
foreach (var header in headers) {
content.Should().Contain(header.Key);
fileContent.Should().Contain(header.Key);
foreach (var value in header.Value) {
content.Should().Contain(value);
fileContent.Should().Contain(value);
}
}
}
Expand All @@ -68,10 +72,13 @@ public async Task Exporter_ExportHtmlAsync_CorrectFileName() {
// Arrange
var dirInfo = Directory.CreateTempSubdirectory();
try {
const string content = "Hello World";

var response = new Response {
Id = 1337,
StatusCode = HttpStatusCode.OK,
Content = "Hello World",
Content = content,
ContentLength = Encoding.Default.GetByteCount(content),
Headers = [],
Exception = StrippedException.Default,
Duration = TimeSpan.FromSeconds(1),
Expand Down Expand Up @@ -100,10 +107,13 @@ public async Task Exporter_ExportHtmlAsync_ContainsAllHeaders() {
new("X-Custom-Header", ["value1", "value2"])
};

const string content = "Hello World";

var response = new Response {
Id = 1337,
StatusCode = HttpStatusCode.OK,
Content = "Hello World",
Content = content,
ContentLength = Encoding.Default.GetByteCount(content),
Headers = headers,
Exception = StrippedException.Default,
Duration = TimeSpan.FromSeconds(1),
Expand All @@ -116,12 +126,12 @@ public async Task Exporter_ExportHtmlAsync_ContainsAllHeaders() {
// Assert
var file = dirInfo.GetFiles();
file.Length.Should().Be(1, "because 1 file was created");
var content = File.ReadAllText(file[0].FullName);
var fileContent = File.ReadAllText(file[0].FullName);

foreach (var header in headers) {
content.Should().Contain(header.Key);
fileContent.Should().Contain(header.Key);
foreach (var value in header.Value) {
content.Should().Contain(value);
fileContent.Should().Contain(value);
}
}
} finally {
Expand All @@ -134,10 +144,13 @@ public async Task Exporter_ExportHtmlAsync_WithoutException_HasContent() {
// Arrange
var dirInfo = Directory.CreateTempSubdirectory();
try {
const string content = "Hello World";

var response = new Response {
Id = 1337,
StatusCode = HttpStatusCode.OK,
Content = "Hello World",
Content = content,
ContentLength = Encoding.Default.GetByteCount(content),
Headers = [],
Exception = StrippedException.Default,
Duration = TimeSpan.FromSeconds(1),
Expand All @@ -150,8 +163,8 @@ public async Task Exporter_ExportHtmlAsync_WithoutException_HasContent() {
// Assert
var file = dirInfo.GetFiles();
file.Length.Should().Be(1, "because 1 file was created");
var content = File.ReadAllText(file[0].FullName);
content.Should().Contain("Hello World", "because the content is present");
var fileContent = File.ReadAllText(file[0].FullName);
fileContent.Should().Contain("Hello World", "because the content is present");
} finally {
dirInfo.Delete(true);
}
Expand All @@ -162,14 +175,16 @@ public async Task Exporter_ExportHtmlAsync_WithException_HasExceptionAndNoConten
// Arrange
var dirInfo = Directory.CreateTempSubdirectory();
try {
var exception = new Exception("Test");
const string content = "Hello World";
var exception = new StrippedException(nameof(Exception), "test", "");

var response = new Response {
Id = 1337,
StatusCode = HttpStatusCode.OK,
Content = "Hello World",
Content = content,
ContentLength = Encoding.Default.GetByteCount(content),
Headers = [],
Exception = StrippedException.FromException(exception),
Exception = exception,
Duration = TimeSpan.FromSeconds(1),
MaximumConcurrencyLevel = 1
};
Expand All @@ -180,9 +195,9 @@ public async Task Exporter_ExportHtmlAsync_WithException_HasExceptionAndNoConten
// Assert
var file = dirInfo.GetFiles();
file.Length.Should().Be(1, "because 1 file was created");
var content = File.ReadAllText(file[0].FullName);
content.Should().NotContain("Hello World", "because the content is not present");
content.Should().Contain(exception.Message, "because the exception is present");
var fileContent = File.ReadAllText(file[0].FullName);
fileContent.Should().NotContain("Hello World", "because the content is not present");
fileContent.Should().Contain(exception.Message, "because the exception is present");
} finally {
dirInfo.Delete(true);
}
Expand Down

0 comments on commit 99a4d47

Please sign in to comment.