Skip to content

Commit b85d44f

Browse files
committed
add otel
1 parent 8d0dc26 commit b85d44f

File tree

129 files changed

+1664
-341
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+1664
-341
lines changed

src/Directory.Packages.props

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,30 @@
1313
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.4" />
1414
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.7" />
1515
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.4.0" />
16+
<PackageVersion Include="OpenTelemetry" Version="1.14.0" />
17+
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.14.0" />
18+
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.14.0" />
19+
<PackageVersion Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.14.0-beta.1" />
20+
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.14.0" />
21+
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.14.0" />
22+
<PackageVersion Include="OpenTelemetry.Instrumentation.EntityFrameworkCore" Version="1.14.0-beta.2" />
23+
<PackageVersion Include="OpenTelemetry.Instrumentation.GrpcNetClient" Version="1.14.0-beta.1" />
24+
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.14.0" />
25+
<PackageVersion Include="OpenTelemetry.Instrumentation.MassTransit" Version="1.0.0-beta.3" />
26+
<PackageVersion Include="OpenTelemetry.Instrumentation.Process" Version="1.14.0-beta.2" />
27+
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.14.0" />
28+
<PackageVersion Include="OpenTelemetry.SemanticConventions" Version="1.0.0-rc9.9" />
1629
<PackageVersion Include="Refit" Version="8.0.0" />
1730
<PackageVersion Include="Refit.HttpClientFactory" Version="8.0.0" />
1831
<PackageVersion Include="ReHackt.Extensions.Options.Validation" Version="8.0.2" />
1932
<PackageVersion Include="Respawn" Version="6.2.1" />
2033
<PackageVersion Include="Scrutor" Version="4.2.2" />
34+
<PackageVersion Include="Serilog.Enrichers.Environment" Version="3.0.1" />
35+
<PackageVersion Include="Serilog.Enrichers.Process" Version="3.0.0" />
36+
<PackageVersion Include="Serilog.Enrichers.Span" Version="3.1.0" />
37+
<PackageVersion Include="Serilog.Exceptions" Version="8.4.0" />
38+
<PackageVersion Include="Serilog.Sinks.Debug" Version="3.0.0" />
39+
<PackageVersion Include="Serilog.Sinks.Elasticsearch" Version="10.0.0" />
2140
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.5.0" />
2241
<PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" />
2342
<PackageVersion Include="coverlet.collector" Version="6.0.0" />
@@ -45,7 +64,7 @@
4564
<PackageVersion Include="FluentValidation" Version="12.0.0" />
4665
<PackageVersion Include="FluentValidation.AspNetCore" Version="11.3.0" />
4766
<PackageVersion Include="FluentValidation.DependencyInjectionExtensions" Version="11.9.0" />
48-
<PackageVersion Include="Serilog" Version="3.1.1" />
67+
<PackageVersion Include="Serilog" Version="4.3.0" />
4968
<PackageVersion Include="MediatR" Version="12.4.1" />
5069
<PackageVersion Include="Ulid" Version="1.3.4" />
5170
<PackageVersion Include="ValueOf" Version="2.0.31" />

src/Services/Basket/Basket.API.IntegrationTests/ApiFactory.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@
88

99
namespace Basket.API.IntegrationTests;
1010

11-
public class ApiFactory(string postgresConnection, string redisConnectionString) : WebApplicationFactory<Program>
11+
public class ApiFactory(
12+
string postgresConnection,
13+
string redisConnectionString,
14+
string elasticSearchString) : WebApplicationFactory<Program>
1215
{
1316
protected override void ConfigureWebHost(IWebHostBuilder builder)
1417
{
1518
Environment.SetEnvironmentVariable("ConnectionStrings__Database", postgresConnection);
1619
Environment.SetEnvironmentVariable("ConnectionStrings__Redis", redisConnectionString);
20+
Environment.SetEnvironmentVariable("Logger__elasticsearch", elasticSearchString);
1721

1822
builder.ConfigureTestServices(service =>
1923
{

src/Services/Basket/Basket.API.IntegrationTests/ApiSpecification.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ public class GetWebApiContainerFactory : ICollectionFixture<ApiSpecification>
1616
}
1717
public class ApiSpecification : IAsyncLifetime
1818
{
19-
private readonly CancellationTokenSource _timeoutCancellationTokenSource = new(TimeSpan.FromSeconds(30));
2019
private IDistributedCache? _cache;
2120
private WireMockServer? _discountWireMockServer;
2221
private ApiFactory? _factory;
@@ -40,7 +39,10 @@ internal HttpClient HttpClient
4039
_postgresDataSeeder ??= new PostgresDataSeeder(GetDocumentStore());
4140

4241
internal RedisDataSeeder RedisDataSeeder => _redisDataSeeder ??= new RedisDataSeeder(GetCache());
43-
internal CancellationToken CancellationToken => _timeoutCancellationTokenSource.Token;
42+
internal CancellationToken CreateTimeoutToken(int seconds = 120)
43+
{
44+
return new CancellationTokenSource(TimeSpan.FromSeconds(seconds)).Token;
45+
}
4446

4547
public void ResetWireMockServer()
4648
{
@@ -53,7 +55,10 @@ public async Task InitializeAsync()
5355
_discountWireMockServer = StartWireMockServer();
5456
Environment.SetEnvironmentVariable("Grpc__Discount", _discountWireMockServer.Url);
5557

56-
_factory = new ApiFactory(_webApiContainer.PostgresConnectionString, _webApiContainer.RedisConnectionString);
58+
_factory = new ApiFactory(
59+
_webApiContainer.PostgresConnectionString,
60+
_webApiContainer.RedisConnectionString,
61+
_webApiContainer.ElasticSearchUri);
5762
_store = _factory.Services.GetRequiredService<IDocumentStore>();
5863
_cache = _factory.Services.GetRequiredService<IDistributedCache>();
5964
await Task.CompletedTask;
@@ -66,7 +71,7 @@ public async Task DisposeAsync()
6671
await _factory.DisposeAsync();
6772

6873
_httpClient?.Dispose();
69-
_store?.Advanced.ResetAllData(CancellationToken);
74+
_store?.Advanced.ResetAllData(CreateTimeoutToken());
7075
_store?.Dispose();
7176
await _webApiContainer.DisposeAsync();
7277
_discountWireMockServer?.Stop();

src/Services/Basket/Basket.API.IntegrationTests/Features/BaseEndpoint.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public BaseEndpoint(ApiSpecification apiSpecification)
1010
}
1111
public async Task InitializeAsync()
1212
{
13-
await _apiSpecification.GetDocumentStore().Advanced.ResetAllData().ConfigureAwait(false);
13+
await _apiSpecification.GetDocumentStore().Advanced.ResetAllData(CancellationToken.None).ConfigureAwait(false);
1414
}
1515

1616
public async Task DisposeAsync()

src/Services/Basket/Basket.API.IntegrationTests/Features/DeleteBasket/DeleteBasketTests.cs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
1-
using System.Net;
2-
using System.Net.Http.Json;
3-
using Basket.API.Authorization;
41
using Basket.API.Features.DeleteBasket;
5-
using Basket.API.IntegrationTests.AutoFixture;
6-
using Basket.API.IntegrationTests.Database.Postgres;
7-
using Basket.API.IntegrationTests.Database.Redis;
8-
using Basket.API.Models;
9-
using IntegrationTests.Common;
10-
using Shouldly;
112

123
namespace Basket.API.IntegrationTests.Features.DeleteBasket;
134

@@ -31,7 +22,7 @@ public DeleteBasketTests(ApiSpecification apiSpecification) : base(apiSpecificat
3122
public async Task DeleteBasket_No_Token_Returns_Unauthorized(string username)
3223
{
3324
// Arrange
34-
var timeout = _apiSpecification.CancellationToken;
25+
var timeout = _apiSpecification.CreateTimeoutToken();
3526

3627
// Act
3728
var result = await _client
@@ -46,7 +37,7 @@ public async Task DeleteBasket_No_Token_Returns_Unauthorized(string username)
4637
public async Task DeleteBasket_No_Permission_Returns_Forbidden(string username)
4738
{
4839
// Arrange
49-
var timeout = _apiSpecification.CancellationToken;
40+
var timeout = _apiSpecification.CreateTimeoutToken();
5041

5142
// Act
5243
var result = await _client
@@ -61,7 +52,7 @@ public async Task DeleteBasket_No_Permission_Returns_Forbidden(string username)
6152
public async Task DeleteBasket_Deletes_Basket_From_Cache_And_PostgresDb_Returns_Ok()
6253
{
6354
// Arrange
64-
var timeout = _apiSpecification.CancellationToken;
55+
var timeout = _apiSpecification.CreateTimeoutToken();
6556
var username = "test username 1";
6657

6758
var shoppingCart = new ShoppingCart

src/Services/Basket/Basket.API.IntegrationTests/Features/GetBasket/GetBasketTests.cs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,4 @@
1-
using System.Net;
2-
using System.Net.Http.Json;
3-
using Basket.API.Authorization;
41
using Basket.API.Features.GetBasket;
5-
using Basket.API.IntegrationTests.Database.Postgres;
6-
using Basket.API.IntegrationTests.Database.Redis;
7-
using Basket.API.Models;
8-
using IntegrationTests.Common;
9-
using Microsoft.AspNetCore.Mvc;
10-
using Newtonsoft.Json;
11-
using Shouldly;
122

133
namespace Basket.API.IntegrationTests.Features.GetBasket;
144

@@ -30,7 +20,7 @@ public GetBasketTests(ApiSpecification apiSpecification) : base(apiSpecification
3020
public async Task GetBasket_No_Token_Returns_Unauthorized()
3121
{
3222
// Arrange
33-
var timeout = _apiSpecification.CancellationToken;
23+
var timeout = _apiSpecification.CreateTimeoutToken();
3424
const string username = "test username 1";
3525

3626
// Act
@@ -45,7 +35,7 @@ public async Task GetBasket_No_Token_Returns_Unauthorized()
4535
public async Task GetBasket_No_Permission_Returns_Forbidden()
4636
{
4737
// Arrange
48-
var timeout = _apiSpecification.CancellationToken;
38+
var timeout = _apiSpecification.CreateTimeoutToken();
4939
const string username = "test username 1";
5040

5141
// Act
@@ -61,7 +51,7 @@ public async Task GetBasket_No_Permission_Returns_Forbidden()
6151
public async Task GetBasket_Basket_NotFound_Returns_NotFound()
6252
{
6353
// Arrange
64-
var timeout = _apiSpecification.CancellationToken;
54+
var timeout = _apiSpecification.CreateTimeoutToken();
6555
const string username = "test username 1";
6656

6757
// Act
@@ -83,7 +73,7 @@ public async Task GetBasket_Basket_NotFound_Returns_NotFound()
8373
public async Task GetBasket_Basket_Only_Exists_In_Postgres_database_Should_Return_Basket_And_Add_To_Redis()
8474
{
8575
// Arrange
86-
var timeout = _apiSpecification.CancellationToken;
76+
var timeout = _apiSpecification.CreateTimeoutToken();
8777
const string username = "test username 2";
8878

8979
var shoppingCart = new ShoppingCart
@@ -131,7 +121,7 @@ public async Task GetBasket_Basket_Only_Exists_In_Postgres_database_Should_Retur
131121
public async Task GetBasket_Basket_Only_Exists_In_Redis_database_Should_Return_Basket()
132122
{
133123
// Arrange
134-
var timeout = _apiSpecification.CancellationToken;
124+
var timeout = _apiSpecification.CreateTimeoutToken();
135125
const string username = "test username 3";
136126

137127
var shoppingCart = new ShoppingCart

src/Services/Basket/Basket.API.IntegrationTests/Features/StoreBasket/StoreBasketTests.cs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,6 @@
1-
using System.Net;
2-
using System.Net.Http.Json;
3-
using Basket.API.Authorization;
41
using Basket.API.Features.StoreBasket;
5-
using Basket.API.IntegrationTests.AutoFixture;
6-
using Basket.API.IntegrationTests.Database.Postgres;
7-
using Basket.API.IntegrationTests.Database.Redis;
82
using Basket.API.IntegrationTests.ServerGivens;
93
using Basket.API.Models.Dtos;
10-
using IntegrationTests.Common;
11-
using Microsoft.AspNetCore.Mvc;
12-
using Newtonsoft.Json;
13-
using Shouldly;
144

155
namespace Basket.API.IntegrationTests.Features.StoreBasket;
166

@@ -35,7 +25,7 @@ public StoreBasketTests(ApiSpecification apiSpecification) : base(apiSpecificati
3525
public async Task StoreBasket_Null_Username_Returns_BadRequest(StoreBasketRequest request)
3626
{
3727
// Arrange
38-
var token = _apiSpecification.CancellationToken;
28+
var token = _apiSpecification.CreateTimeoutToken();
3929
var invalidRequest =
4030
new StoreBasketRequest(new BasketDtoRequest(string.Empty, request.ShoppingCart!.Items));
4131

@@ -60,7 +50,7 @@ public async Task StoreBasket_Null_Username_Returns_BadRequest(StoreBasketReques
6050
public async Task StoreBasket_Null_Request_Returns_BadRequest(StoreBasketRequest request)
6151
{
6252
// Arrange
63-
var token = _apiSpecification.CancellationToken;
53+
var token = _apiSpecification.CreateTimeoutToken();
6454
request = new StoreBasketRequest(null);
6555

6656
// Act
@@ -107,7 +97,7 @@ public async Task StoreBasket_Null_Items_In_Request_Returns_BadRequest(StoreBask
10797
public async Task StoreBasket_Zero_Quantity_In_Items_In_Request_Returns_BadRequest(StoreBasketRequest request)
10898
{
10999
// Arrange
110-
var token = _apiSpecification.CancellationToken;
100+
var token = _apiSpecification.CreateTimeoutToken();
111101
var invalidRequest =
112102
new StoreBasketRequest(new BasketDtoRequest(
113103
request.ShoppingCart!.Username,
@@ -133,7 +123,7 @@ public async Task StoreBasket_Zero_Quantity_In_Items_In_Request_Returns_BadReque
133123
public async Task StoreBasket_Zero_Price_In_Items_In_Request_Returns_BadRequest(StoreBasketRequest request)
134124
{
135125
// Arrange
136-
var token = _apiSpecification.CancellationToken;
126+
var token = _apiSpecification.CreateTimeoutToken();
137127
var invalidRequest =
138128
new StoreBasketRequest(new BasketDtoRequest(
139129
request.ShoppingCart!.Username,
@@ -159,7 +149,7 @@ public async Task StoreBasket_Zero_Price_In_Items_In_Request_Returns_BadRequest(
159149
public async Task StoreBasket_Valid_Request_Saves_Data_In_PostgresDb_And_Redis(StoreBasketRequest request)
160150
{
161151
// Arrange
162-
var token = _apiSpecification.CancellationToken;
152+
var token = _apiSpecification.CreateTimeoutToken();
163153
_discountGiven.GetDiscountGiven(request.ShoppingCart!.Items!.FirstOrDefault()!.ProductName);
164154

165155
// Act
@@ -193,7 +183,7 @@ public async Task StoreBasket_Valid_Request_Saves_Data_In_PostgresDb_And_Redis(S
193183
public async Task StoreBasket_Valid_Request_Saves_Data_With_Valid_TotalPrice(StoreBasketRequest request)
194184
{
195185
// Arrange
196-
var token = _apiSpecification.CancellationToken;
186+
var token = _apiSpecification.CreateTimeoutToken();
197187
var validRequest = new StoreBasketRequest(new BasketDtoRequest(request.ShoppingCart!.Username,
198188
new List<BasketItem>
199189
{
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
global using Shouldly;
2+
global using System.Net;
3+
global using System.Net.Http.Json;
4+
global using Basket.API.IntegrationTests.AutoFixture;
5+
global using Basket.API.IntegrationTests.Database.Postgres;
6+
global using Basket.API.IntegrationTests.Database.Redis;
7+
global using Basket.API.Models;
8+
global using IntegrationTests.Common;
9+
global using Basket.API.Authorization;
10+
global using Newtonsoft.Json;
11+
global using Microsoft.AspNetCore.Mvc;

src/Services/Basket/Basket.API.IntegrationTests/WebApiContainerFactory.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ namespace Basket.API.IntegrationTests;
66
public class WebApiContainerFactory : IAsyncLifetime
77
{
88
private const ushort PostgresPort = 5432;
9-
109
private const ushort RedisPort = 6379;
10+
private const ushort ElasticSearchPort = 9200;
1111

1212
private readonly IContainer _postgres = new ContainerBuilder()
1313
.WithImage("postgres")
@@ -24,6 +24,14 @@ public class WebApiContainerFactory : IAsyncLifetime
2424
.WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(RedisPort))
2525
.Build();
2626

27+
private readonly IContainer _elasticsearch = new ContainerBuilder()
28+
.WithImage("docker.elastic.co/elasticsearch/elasticsearch:8.1.2")
29+
.WithPortBinding(9200, true)
30+
.WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(ElasticSearchPort))
31+
.Build();
32+
33+
internal string ElasticSearchUri =>
34+
$"http://{_elasticsearch.Hostname}:{_elasticsearch.GetMappedPublicPort(ElasticSearchPort)}";
2735
internal Uri PostgresUri => new($"http://{_postgres.Hostname}:{_postgres.GetMappedPublicPort(PostgresPort)}");
2836

2937
internal string PostgresConnectionString =>
@@ -35,11 +43,13 @@ public async Task InitializeAsync()
3543
{
3644
await _postgres.StartAsync().ConfigureAwait(false);
3745
await _redis.StartAsync().ConfigureAwait(false);
46+
await _elasticsearch.StartAsync().ConfigureAwait(false);
3847
}
3948

4049
public async Task DisposeAsync()
4150
{
4251
await _postgres.DisposeAsync().ConfigureAwait(false);
4352
await _redis.DisposeAsync().ConfigureAwait(false);
53+
await _elasticsearch.DisposeAsync().ConfigureAwait(false);
4454
}
4555
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace Basket.API.Configurations.ConfigurationOptions;
4+
5+
internal sealed record LoggerConfigurations
6+
{
7+
[ConfigurationKeyName("Logger:elasticsearch")]
8+
[Required]
9+
public required string ElasticSearch { get; init; }
10+
}

0 commit comments

Comments
 (0)