Skip to content

Commit

Permalink
Increase logging of testcontainer
Browse files Browse the repository at this point in the history
  • Loading branch information
Mpdreamz committed Oct 22, 2024
1 parent ba5d3b2 commit 425c103
Show file tree
Hide file tree
Showing 13 changed files with 332 additions and 63 deletions.
16 changes: 8 additions & 8 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@
<PackageVersion Include="StackExchange.Redis" Version="2.7.20" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageVersion Include="Testcontainers.Elasticsearch" Version="3.7.0" />
<PackageVersion Include="Testcontainers.Kafka" Version="3.7.0" />
<PackageVersion Include="Testcontainers.MongoDb" Version="3.7.0" />
<PackageVersion Include="Testcontainers.MsSql" Version="3.7.0" />
<PackageVersion Include="Testcontainers.MySql" Version="3.7.0" />
<PackageVersion Include="Testcontainers.Oracle" Version="3.7.0" />
<PackageVersion Include="Testcontainers.PostgreSql" Version="3.7.0" />
<PackageVersion Include="Testcontainers.RabbitMq" Version="3.7.0" />
<PackageVersion Include="Testcontainers.Redis" Version="3.7.0" />
<PackageVersion Include="Testcontainers.Kafka" Version="3.10.0" />
<PackageVersion Include="Testcontainers.MongoDb" Version="3.10.0" />
<PackageVersion Include="Testcontainers.MsSql" Version="3.10.0" />
<PackageVersion Include="Testcontainers.MySql" Version="3.10.0" />
<PackageVersion Include="Testcontainers.Oracle" Version="3.10.0" />
<PackageVersion Include="Testcontainers.PostgreSql" Version="3.10.0" />
<PackageVersion Include="Testcontainers.RabbitMq" Version="3.10.0" />
<PackageVersion Include="Testcontainers.Redis" Version="3.10.0" />
<PackageVersion Include="YamlDotNet" Version="11.2.1" />
<PackageVersion Include="xunit" Version="2.7.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.7" PrivateAssets="All" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
Expand Down
2 changes: 1 addition & 1 deletion sample/StackExchangeRedisSample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,5 @@ await Agent.Tracer.CaptureTransaction("Set and Get String", ApiConstants.TypeDb,
await Task.Delay(TimeSpan.FromMilliseconds(100));
}
Console.WriteLine("Stopping Redis Container...");
await container.StopAsync();
await container.StopAsync(ctx.Token);
Console.WriteLine("Exiting");
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,49 @@
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using System;
using System.Threading;
using System.Threading.Tasks;
using Testcontainers.Elasticsearch;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;

namespace Elastic.Apm.Elasticsearch.Tests
{
public sealed class ElasticsearchFixture : IAsyncLifetime
public sealed class ElasticsearchFixture(IMessageSink sink) : IAsyncLifetime
{
private readonly ElasticsearchContainer _container = new ElasticsearchBuilder().Build();

public string ConnectionString => _container.GetConnectionString();

public Task InitializeAsync() => _container.StartAsync();
public async Task InitializeAsync()
{
await _container.StartAsync();

public Task DisposeAsync() => _container.DisposeAsync().AsTask();
var (stdOut, stdErr) = await _container.GetLogsAsync();

sink.OnMessage(new DiagnosticMessage(stdOut));
sink.OnMessage(new DiagnosticMessage(stdErr));
}

public async Task DisposeAsync()
{
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromMinutes(2));

try
{
sink.OnMessage(new DiagnosticMessage($"Stopping {nameof(ElasticsearchFixture)}"));
await _container.StopAsync(cts.Token);
}
catch (Exception e)
{
sink.OnMessage(new DiagnosticMessage(e.Message));
}

sink.OnMessage(new DiagnosticMessage($"Disposing {nameof(ElasticsearchFixture)}"));
await _container.DisposeAsync();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,32 @@
// Elasticsearch B.V licenses this file, including any modifications, to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.

using System;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using Testcontainers.MongoDb;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;

namespace Elastic.Apm.MongoDb.Tests.Fixture
{
public class MongoFixture<TConfiguration, TDocument> : IAsyncLifetime
where TConfiguration : IMongoConfiguration<TDocument>, new()
{
private readonly IMessageSink _sink;
private const string MongoDbImage = "mongo:4.4.5";

private readonly TConfiguration _configuration;

private readonly MongoDbContainer _container = new MongoDbBuilder().WithImage(MongoDbImage).Build();

public MongoFixture() => _configuration = new TConfiguration();
public MongoFixture(IMessageSink sink)
{
_sink = sink;
_configuration = new TConfiguration();
}

public IMongoCollection<TDocument> Collection { get; private set; }

Expand All @@ -33,14 +42,32 @@ public async Task InitializeAsync()
.GetCollection<TDocument>(_configuration.CollectionName);

await _configuration.InitializeAsync(Collection);

var (stdOut, stdErr) = await _container.GetLogsAsync();

_sink.OnMessage(new DiagnosticMessage(stdOut));
_sink.OnMessage(new DiagnosticMessage(stdErr));
}

public async Task DisposeAsync()
{
if (Collection != null)
await _configuration.DisposeAsync(Collection);

await _container.StopAsync();
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromMinutes(2));

try
{
_sink.OnMessage(new DiagnosticMessage($"Stopping {nameof(MongoDbContainer)}"));
await _container.StopAsync(cts.Token);
}
catch (Exception e)
{
_sink.OnMessage(new DiagnosticMessage(e.Message));
}

_sink.OnMessage(new DiagnosticMessage($"Disposing {nameof(MongoDbContainer)}"));
await _container.DisposeAsync();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Testcontainers.MsSql;
using Xunit;
Expand Down Expand Up @@ -47,6 +49,23 @@ public async Task InitializeAsync()
_sink.OnMessage(new DiagnosticMessage(stdErr));
}

public async Task DisposeAsync() => await _container.DisposeAsync();
public async Task DisposeAsync()
{
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromMinutes(2));

try
{
_sink.OnMessage(new DiagnosticMessage($"Stopping {nameof(SqlServerFixture)}"));
await _container.StopAsync(cts.Token);
}
catch (Exception e)
{
_sink.OnMessage(new DiagnosticMessage(e.Message));
}

_sink.OnMessage(new DiagnosticMessage($"Disposing {nameof(SqlServerFixture)}"));
await _container.DisposeAsync();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Elastic.Apm.Api;
using Elastic.Apm.Tests.Utilities;
Expand All @@ -21,8 +22,11 @@ public class ProfilingSessionTests
[DockerFact]
public async Task Capture_Redis_Commands_On_Transaction()
{
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromMinutes(2));

await using var container = new RedisBuilder().Build();
await container.StartAsync();
await container.StartAsync(cts.Token);

var connection = await ConnectionMultiplexer.ConnectAsync(container.GetConnectionString());
var count = 0;
Expand All @@ -32,7 +36,7 @@ public async Task Capture_Redis_Commands_On_Transaction()
if (count < 5)
{
count++;
await Task.Delay(500);
await Task.Delay(500, cts.Token);
}
else
throw new Exception("Could not connect to redis for integration test");
Expand Down Expand Up @@ -73,14 +77,17 @@ await agent.Tracer.CaptureTransaction("Set and Get String", ApiConstants.TypeDb,
foreach (var span in payloadSender.Spans)
AssertSpan(span);

await container.StopAsync();
await container.StopAsync(cts.Token);
}

[DockerFact]
public async Task Capture_Redis_Commands_On_Span()
{
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromMinutes(2));

await using var container = new RedisBuilder().Build();
await container.StartAsync();
await container.StartAsync(cts.Token);

var connection = await ConnectionMultiplexer.ConnectAsync(container.GetConnectionString());
var count = 0;
Expand All @@ -90,7 +97,7 @@ public async Task Capture_Redis_Commands_On_Span()
if (count < 5)
{
count++;
await Task.Delay(500);
await Task.Delay(500, cts.Token);
}
else
throw new Exception("Could not connect to redis for integration test");
Expand Down Expand Up @@ -155,7 +162,7 @@ await t.CaptureSpan($"parent span {i}", ApiConstants.TypeDb, async () =>
AssertSpan(span);
}

await container.StopAsync();
await container.StopAsync(cts.Token);
}

private static void AssertSpan(ISpan span)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,29 @@ public sealed class ElasticsearchTestFixture(IMessageSink sink) : IAsyncLifetime
{
private readonly IMessageSink _sink = sink;

public ElasticsearchContainer Container { get; } = new ElasticsearchBuilder().Build();
public ElasticsearchContainer Container { get; } = new ElasticsearchBuilder().Build();

public ElasticsearchClient? Client { get; private set; }
public ElasticsearchClient? Client { get; private set; }

public async Task InitializeAsync()
{
await Container.StartAsync();
public async Task InitializeAsync()
{
await Container.StartAsync();

var (stdOut, stdErr) = await Container.GetLogsAsync();
var (stdOut, stdErr) = await Container.GetLogsAsync();

_sink.OnMessage(new DiagnosticMessage(stdOut));
_sink.OnMessage(new DiagnosticMessage(stdErr));
_sink.OnMessage(new DiagnosticMessage(stdOut));
_sink.OnMessage(new DiagnosticMessage(stdErr));

var settings = new ElasticsearchClientSettings(new Uri(Container.GetConnectionString()));
settings.ServerCertificateValidationCallback(CertificateValidations.AllowAll);
var settings = new ElasticsearchClientSettings(new Uri(Container.GetConnectionString()));
settings.ServerCertificateValidationCallback(CertificateValidations.AllowAll);

Client = new ElasticsearchClient(settings);
if (Client == null)
throw new Exception("`new ElasticsearchClient(settings)` returned `null`");
Client = new ElasticsearchClient(settings);
if (Client == null)
throw new Exception("`new ElasticsearchClient(settings)` returned `null`");

//Increase Elasticsearch high disk watermarks, Github Actions container typically has around
//~7GB free (8%) of the available space.
var response = await Client.Transport.RequestAsync<StringResponse>(HttpMethod.PUT, "_cluster/settings", PostData.String(@"{
//Increase Elasticsearch high disk watermarks, Github Actions container typically has around
//~7GB free (8%) of the available space.
var response = await Client.Transport.RequestAsync<StringResponse>(HttpMethod.PUT, "_cluster/settings", PostData.String(@"{
""persistent"": {
""cluster.routing.allocation.disk.watermark.low"": ""90%"",
""cluster.routing.allocation.disk.watermark.low.max_headroom"": ""100GB"",
Expand All @@ -52,16 +52,25 @@ public async Task InitializeAsync()
}
}"));

if (!response.ApiCallDetails.HasSuccessfulStatusCode)
throw new Exception(response.ToString());
}
if (!response.ApiCallDetails.HasSuccessfulStatusCode)
throw new Exception(response.ToString());
}

async Task IAsyncLifetime.DisposeAsync()
{
if (Container.State == TestcontainersStates.Running)
async Task IAsyncLifetime.DisposeAsync()
{
await Container.StopAsync();
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromMinutes(2));

try
{
_sink.OnMessage(new DiagnosticMessage($"Stopping {nameof(ElasticsearchTestFixture)}"));
await Container.StopAsync(cts.Token);
}
catch (Exception e)
{
_sink.OnMessage(new DiagnosticMessage(e.Message));
}
_sink.OnMessage(new DiagnosticMessage($"Disposing {nameof(ElasticsearchTestFixture)}"));
await Container.DisposeAsync();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,52 @@
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using System;
using System.Threading;
using System.Threading.Tasks;
using Testcontainers.MySql;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;

namespace Elastic.Apm.Profiler.Managed.Tests.AdoNet
{
[CollectionDefinition("MySql")]
public sealed class MySqlCollection : ICollectionFixture<MySqlFixture> { }

public sealed class MySqlFixture : IAsyncLifetime
public sealed class MySqlFixture(IMessageSink sink) : IAsyncLifetime
{
private readonly MySqlContainer _container = new MySqlBuilder().WithImage("mysql:8.0.32").Build();

public string ConnectionString => _container.GetConnectionString();

public Task InitializeAsync() => _container.StartAsync();
public async Task InitializeAsync()
{
await _container.StartAsync();

public Task DisposeAsync() => _container.DisposeAsync().AsTask();
var (stdOut, stdErr) = await _container.GetLogsAsync();

sink.OnMessage(new DiagnosticMessage(stdOut));
sink.OnMessage(new DiagnosticMessage(stdErr));
}

public async Task DisposeAsync()
{
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromMinutes(2));

try
{
sink.OnMessage(new DiagnosticMessage($"Stopping {nameof(MySqlFixture)}"));
await _container.StopAsync(cts.Token);
}
catch (Exception e)
{
sink.OnMessage(new DiagnosticMessage(e.Message));
}

sink.OnMessage(new DiagnosticMessage($"Disposing {nameof(MySqlFixture)}"));
await _container.DisposeAsync();
}
}
}
Loading

0 comments on commit 425c103

Please sign in to comment.