diff --git a/.gitignore b/.gitignore
index b94e9a479..69800e3b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,7 +26,7 @@ bld/
# Visual Studio 2015 cache/options directory
.vs/
-# Files created by bundling and minification on startup
+# .js files created on build:
src/Web/WebMVC/wwwroot/js/site*
# Uncomment if you have tasks that create the project's static files in wwwroot
diff --git a/deploy/az/servicebus/readme.md b/deploy/az/servicebus/readme.md
index 16da4c7b2..886b3ec60 100644
--- a/deploy/az/servicebus/readme.md
+++ b/deploy/az/servicebus/readme.md
@@ -8,7 +8,7 @@ The ARM template `sbusdeploy.json` and its parameter file (`sbusdeploy.parameter
## Editing sbusdeploy.parameters.json file
-You can edit the `sbusdeploy.parameters.parameters.json` file to set your values, but is not needed. The only parameter than can
+You can edit the `sbusdeploy.parameters.json` file to set your values, but is not needed. The only parameter than can
be set is:
1. `namespaceprefix` is a string that is used to create the namespace. ARM script creates unique values by appending a unique string to this parameter value, so you can leave the default value.
@@ -21,4 +21,4 @@ i. e. if you are in windows, to deploy servicebus in a new resourcegroup located
```
create-resources.cmd servicebus\sbusdeploy newResourceGroup -c westus
-```
\ No newline at end of file
+```
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index f8d608a27..7353c744c 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -7,6 +7,12 @@ version: '3.4'
# An external IP or DNS name has to be used (instead localhost and the 10.0.75.1 IP) when testing the Web apps and the Xamarin apps from remote machines/devices using the same WiFi, for instance.
services:
+ seq:
+ environment:
+ - ACCEPT_EULA=Y
+ ports:
+ - "5340:80"
+
sql.data:
environment:
- SA_PASSWORD=Pass@word
diff --git a/docker-compose.yml b/docker-compose.yml
index 194d7e06c..55d5b10e6 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,6 +1,9 @@
version: '3.4'
services:
+ seq:
+ image: datalust/seq:latest
+
sql.data:
image: microsoft/mssql-server-linux:2017-latest
diff --git a/src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj b/src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj
index f19e84335..6ad9e78d1 100644
--- a/src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj
+++ b/src/ApiGateways/ApiGw-Base/OcelotApiGw.csproj
@@ -6,7 +6,7 @@
-
+
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj
index e0426f3bc..83c6ff356 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs
index eeb58ac3b..924b5b1aa 100644
--- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs
+++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs
@@ -57,7 +57,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
if (!string.IsNullOrEmpty(pathBase))
{
- loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
+ loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase);
app.UsePathBase(pathBase);
}
diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs
index 0fcd13a41..6d3da29b7 100644
--- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs
+++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs
@@ -57,7 +57,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
- loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
+ loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase);
app.UsePathBase(pathBase);
}
diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj b/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj
index 7309593a8..970d01bf8 100644
--- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj
+++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj
index 9704f6ff5..17c5a8293 100644
--- a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj
+++ b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj
@@ -6,7 +6,7 @@
-
+
\ No newline at end of file
diff --git a/src/BuildingBlocks/EventBus/EventBus/Extensions/GenericTypeExtensions.cs b/src/BuildingBlocks/EventBus/EventBus/Extensions/GenericTypeExtensions.cs
new file mode 100644
index 000000000..de5a2cb79
--- /dev/null
+++ b/src/BuildingBlocks/EventBus/EventBus/Extensions/GenericTypeExtensions.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions
+{
+ public static class GenericTypeExtensions
+ {
+ public static string GetGenericTypeName(this Type type)
+ {
+ var typeName = string.Empty;
+
+ if (type.IsGenericType)
+ {
+ var genericTypes = string.Join(",", type.GetGenericArguments().Select(t => t.Name).ToArray());
+ typeName = $"{type.Name.Remove(type.Name.IndexOf('`'))}<{genericTypes}>";
+ }
+ else
+ {
+ typeName = type.Name;
+ }
+
+ return typeName;
+ }
+
+ public static string GetGenericTypeName(this object @object)
+ {
+ return @object.GetType().GetGenericTypeName();
+ }
+ }
+}
diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersisterConnection.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersistentConnection.cs
similarity index 91%
rename from src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersisterConnection.cs
rename to src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersistentConnection.cs
index 2e0555e61..93e5b2917 100644
--- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersisterConnection.cs
+++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersistentConnection.cs
@@ -72,7 +72,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
.Or()
.WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
{
- _logger.LogWarning(ex.ToString());
+ _logger.LogWarning(ex, "RabbitMQ Client could not connect after {TimeOut}s ({ExceptionMessage})", $"{time.TotalSeconds:n1}", ex.Message);
}
);
@@ -88,7 +88,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
_connection.CallbackException += OnCallbackException;
_connection.ConnectionBlocked += OnConnectionBlocked;
- _logger.LogInformation($"RabbitMQ persistent connection acquired a connection {_connection.Endpoint.HostName} and is subscribed to failure events");
+ _logger.LogInformation("RabbitMQ Client acquired a persistent connection to '{HostName}' and is subscribed to failure events", _connection.Endpoint.HostName);
return true;
}
diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs
index a3b6437ef..ac379d50a 100644
--- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs
+++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs
@@ -2,6 +2,7 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@@ -76,7 +77,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
.Or()
.WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
{
- _logger.LogWarning(ex.ToString());
+ _logger.LogWarning(ex, "Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", @event.Id, $"{time.TotalSeconds:n1}", ex.Message);
});
using (var channel = _persistentConnection.CreateModel())
@@ -107,6 +108,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
public void SubscribeDynamic(string eventName)
where TH : IDynamicIntegrationEventHandler
{
+ _logger.LogInformation("Subscribing to dynamic event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName());
+
DoInternalSubscription(eventName);
_subsManager.AddDynamicSubscription | (eventName);
}
@@ -117,6 +120,9 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
{
var eventName = _subsManager.GetEventKey();
DoInternalSubscription(eventName);
+
+ _logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName());
+
_subsManager.AddSubscription();
}
@@ -140,9 +146,13 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
}
public void Unsubscribe()
- where TH : IIntegrationEventHandler
where T : IntegrationEvent
+ where TH : IIntegrationEventHandler
{
+ var eventName = _subsManager.GetEventKey();
+
+ _logger.LogInformation("Unsubscribing from event {EventName}", eventName);
+
_subsManager.RemoveSubscription();
}
@@ -215,7 +225,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
foreach (var subscription in subscriptions)
{
if (subscription.IsDynamic)
- {
+ {
var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler;
if (handler == null) continue;
dynamic eventData = JObject.Parse(message);
diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj
index cc16b89e1..827eb8b11 100644
--- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj
+++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/IRabbitMQPersisterConnection.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/IRabbitMQPersistentConnection.cs
similarity index 100%
rename from src/BuildingBlocks/EventBus/EventBusRabbitMQ/IRabbitMQPersisterConnection.cs
rename to src/BuildingBlocks/EventBus/EventBusRabbitMQ/IRabbitMQPersistentConnection.cs
diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs
index d16eb4625..cd2dc557f 100644
--- a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs
+++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs
@@ -27,7 +27,7 @@
ILifetimeScope autofac)
{
_serviceBusPersisterConnection = serviceBusPersisterConnection;
- _logger = logger;
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
_subsManager = subsManager ?? new InMemoryEventBusSubscriptionsManager();
_subscriptionClient = new SubscriptionClient(serviceBusPersisterConnection.ServiceBusConnectionStringBuilder,
@@ -61,6 +61,8 @@
public void SubscribeDynamic(string eventName)
where TH : IDynamicIntegrationEventHandler
{
+ _logger.LogInformation("Subscribing to dynamic event {EventName} with {EventHandler}", eventName, nameof(TH));
+
_subsManager.AddDynamicSubscription | (eventName);
}
@@ -83,10 +85,12 @@
}
catch (ServiceBusException)
{
- _logger.LogInformation($"The messaging entity {eventName} already exists.");
+ _logger.LogWarning("The messaging entity {eventName} already exists.", eventName);
}
}
+ _logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, nameof(TH));
+
_subsManager.AddSubscription();
}
@@ -105,15 +109,19 @@
}
catch (MessagingEntityNotFoundException)
{
- _logger.LogInformation($"The messaging entity {eventName} Could not be found.");
+ _logger.LogWarning("The messaging entity {eventName} Could not be found.", eventName);
}
+ _logger.LogInformation("Unsubscribing from event {EventName}", eventName);
+
_subsManager.RemoveSubscription();
}
public void UnsubscribeDynamic(string eventName)
where TH : IDynamicIntegrationEventHandler
{
+ _logger.LogInformation("Unsubscribing from dynamic event {EventName}", eventName);
+
_subsManager.RemoveDynamicSubscription | (eventName);
}
@@ -136,17 +144,16 @@
await _subscriptionClient.CompleteAsync(message.SystemProperties.LockToken);
}
},
- new MessageHandlerOptions(ExceptionReceivedHandler) { MaxConcurrentCalls = 10, AutoComplete = false });
+ new MessageHandlerOptions(ExceptionReceivedHandler) { MaxConcurrentCalls = 10, AutoComplete = false });
}
private Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
{
- Console.WriteLine($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}.");
+ var ex = exceptionReceivedEventArgs.Exception;
var context = exceptionReceivedEventArgs.ExceptionReceivedContext;
- Console.WriteLine("Exception context for troubleshooting:");
- Console.WriteLine($"- Endpoint: {context.Endpoint}");
- Console.WriteLine($"- Entity Path: {context.EntityPath}");
- Console.WriteLine($"- Executing Action: {context.Action}");
+
+ _logger.LogError(ex, "ERROR handling message: {ExceptionMessage} - Context: {@ExceptionContext}", ex.Message, context);
+
return Task.CompletedTask;
}
@@ -172,7 +179,7 @@
var handler = scope.ResolveOptional(subscription.HandlerType);
if (handler == null) continue;
var eventType = _subsManager.GetEventTypeByName(eventName);
- var integrationEvent = JsonConvert.DeserializeObject(message, eventType);
+ var integrationEvent = JsonConvert.DeserializeObject(message, eventType);
var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType);
await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent });
}
@@ -194,7 +201,7 @@
}
catch (MessagingEntityNotFoundException)
{
- _logger.LogInformation($"The messaging entity { RuleDescription.DefaultRuleName } Could not be found.");
+ _logger.LogWarning("The messaging entity {DefaultRuleName} Could not be found.", RuleDescription.DefaultRuleName);
}
}
}
diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj
index ef3463cca..601d337b0 100644
--- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj
+++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs
index 0da18f581..fa06e0a0b 100644
--- a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs
+++ b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs
@@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Hosting
try
{
- logger.LogInformation($"Migrating database associated with context {typeof(TContext).Name}");
+ logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name);
if (underK8s)
{
@@ -55,11 +55,11 @@ namespace Microsoft.AspNetCore.Hosting
retry.Execute(() => InvokeSeeder(seeder, context, services));
}
- logger.LogInformation($"Migrated database associated with context {typeof(TContext).Name}");
+ logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name);
}
catch (Exception ex)
{
- logger.LogError(ex, $"An error occurred while migrating the database used on context {typeof(TContext).Name}");
+ logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name);
if (underK8s)
{
throw; // Rethrow under k8s because we rely on k8s to re-run the pod
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj.bak b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj.bak
deleted file mode 100644
index 0d45fd280..000000000
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.iOS/eShopOnContainers.TestRunner.iOS.csproj.bak
+++ /dev/null
@@ -1,175 +0,0 @@
-
-
-
- Debug
- iPhoneSimulator
- {B68C2B56-7581-46AE-B55D-D25DDFD3BFE3}
- {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- Exe
- eShopOnContainers.TestRunner.iOS
- Resources
- eShopOnContainers.TestRunner.iOS
-
-
-
-
- true
- full
- false
- bin\iPhoneSimulator\Debug
- DEBUG
- prompt
- 4
- false
- x86_64
- SdkOnly
- True
- 10.1
- False
- False
- False
- False
- False
- False
- False
- True
- Default
- HttpClientHandler
- False
-
-
- none
- true
- bin\iPhoneSimulator\Release
- prompt
- 4
- None
- x86_64
- false
-
-
- true
- full
- false
- bin\iPhone\Debug
- DEBUG
- prompt
- 4
- false
- ARMv7, ARM64
- Entitlements.plist
- iPhone Developer
- true
-
-
- none
- true
- bin\iPhone\Release
- prompt
- 4
- Entitlements.plist
- ARMv7, ARM64
- false
- iPhone Developer
-
-
- none
- True
- bin\iPhone\Ad-Hoc
- prompt
- 4
- False
- ARMv7, ARM64
- Entitlements.plist
- True
- Automatic:AdHoc
- iPhone Distribution
-
-
- none
- True
- bin\iPhone\AppStore
- prompt
- 4
- False
- ARMv7, ARM64
- Entitlements.plist
- Automatic:AppStore
- iPhone Distribution
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll
- True
-
-
- ..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll
- True
-
-
- ..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll
- True
-
-
- ..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll
- True
-
-
-
- ..\..\packages\xunit.abstractions.2.0.1\lib\netstandard1.0\xunit.abstractions.dll
- True
-
-
- ..\..\packages\xunit.assert.2.2.0-beta4-build3444\lib\netstandard1.0\xunit.assert.dll
- True
-
-
- ..\..\packages\xunit.extensibility.core.2.2.0-beta4-build3444\lib\netstandard1.0\xunit.core.dll
- True
-
-
- ..\..\packages\xunit.extensibility.execution.2.2.0-beta4-build3444\lib\netstandard1.0\xunit.execution.dotnet.dll
- True
-
-
- ..\..\packages\xunit.runner.devices.2.1.0\lib\Xamarin.iOS\xunit.runner.devices.dll
- True
-
-
- ..\..\packages\xunit.runner.utility.2.2.0-beta4-build3444\lib\netstandard1.1\xunit.runner.utility.dotnet.dll
- True
-
-
-
-
-
-
-
-
- {f7b6a162-bc4d-4924-b16a-713f9b0344e7}
- eShopOnContainers.UnitTests
-
-
-
-
-
-
- Este proyecto hace referencia a los paquetes NuGet que faltan en este equipo. Use la restauración de paquetes NuGet para descargarlos. Para obtener más información, consulte http://go.microsoft.com/fwlink/?LinkID=322105. El archivo que falta es {0}.
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Services/Basket/Basket.API/Basket.API.csproj b/src/Services/Basket/Basket.API/Basket.API.csproj
index 77d58aff1..ab1184ae1 100644
--- a/src/Services/Basket/Basket.API/Basket.API.csproj
+++ b/src/Services/Basket/Basket.API/Basket.API.csproj
@@ -13,25 +13,25 @@
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
-
diff --git a/src/Services/Basket/Basket.API/Controllers/BasketController.cs b/src/Services/Basket/Basket.API/Controllers/BasketController.cs
index 0e15e65dd..7bab4e969 100644
--- a/src/Services/Basket/Basket.API/Controllers/BasketController.cs
+++ b/src/Services/Basket/Basket.API/Controllers/BasketController.cs
@@ -5,6 +5,8 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
using Microsoft.eShopOnContainers.Services.Basket.API.Services;
+using Microsoft.Extensions.Logging;
+using Serilog.Context;
using System;
using System.Net;
using System.Threading.Tasks;
@@ -19,9 +21,15 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
private readonly IBasketRepository _repository;
private readonly IIdentityService _identityService;
private readonly IEventBus _eventBus;
+ private readonly ILogger _logger;
- public BasketController(IBasketRepository repository, IIdentityService identityService, IEventBus eventBus)
+ public BasketController(
+ ILogger logger,
+ IBasketRepository repository,
+ IIdentityService identityService,
+ IEventBus eventBus)
{
+ _logger = logger;
_repository = repository;
_identityService = identityService;
_eventBus = eventBus;
@@ -50,7 +58,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
public async Task CheckoutAsync([FromBody]BasketCheckout basketCheckout, [FromHeader(Name = "x-requestid")] string requestId)
{
var userId = _identityService.GetUserIdentity();
-
+
basketCheckout.RequestId = (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) ?
guid : basketCheckout.RequestId;
@@ -70,7 +78,18 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
// Once basket is checkout, sends an integration event to
// ordering.api to convert basket to order and proceeds with
// order creation process
- _eventBus.Publish(eventMessage);
+ try
+ {
+ _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", eventMessage.Id, Program.AppName, eventMessage);
+
+ _eventBus.Publish(eventMessage);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName}", eventMessage.Id, Program.AppName);
+
+ throw;
+ }
return Accepted();
}
diff --git a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs
index 19ae1b594..cb7b6a2d6 100644
--- a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs
+++ b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs
@@ -1,6 +1,9 @@
using Basket.API.IntegrationEvents.Events;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+using Microsoft.eShopOnContainers.Services.Basket.API;
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
+using Microsoft.Extensions.Logging;
+using Serilog.Context;
using System;
using System.Threading.Tasks;
@@ -9,15 +12,24 @@ namespace Basket.API.IntegrationEvents.EventHandling
public class OrderStartedIntegrationEventHandler : IIntegrationEventHandler
{
private readonly IBasketRepository _repository;
+ private readonly ILogger _logger;
- public OrderStartedIntegrationEventHandler(IBasketRepository repository)
+ public OrderStartedIntegrationEventHandler(
+ IBasketRepository repository,
+ ILogger logger)
{
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(OrderStartedIntegrationEvent @event)
{
- await _repository.DeleteBasketAsync(@event.UserId.ToString());
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
+ await _repository.DeleteBasketAsync(@event.UserId.ToString());
+ }
}
}
}
diff --git a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs
index 546483b40..c27200e6f 100644
--- a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs
+++ b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs
@@ -1,6 +1,8 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events;
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
+using Microsoft.Extensions.Logging;
+using Serilog.Context;
using System;
using System.Linq;
using System.Threading.Tasks;
@@ -9,22 +11,31 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Even
{
public class ProductPriceChangedIntegrationEventHandler : IIntegrationEventHandler
{
+ private readonly ILogger _logger;
private readonly IBasketRepository _repository;
- public ProductPriceChangedIntegrationEventHandler(IBasketRepository repository)
+ public ProductPriceChangedIntegrationEventHandler(
+ ILogger logger,
+ IBasketRepository repository)
{
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
}
public async Task Handle(ProductPriceChangedIntegrationEvent @event)
{
- var userIds = _repository.GetUsers();
-
- foreach (var id in userIds)
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
{
- var basket = await _repository.GetBasketAsync(id);
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
- await UpdatePriceInBasketItems(@event.ProductId, @event.NewPrice, @event.OldPrice, basket);
+ var userIds = _repository.GetUsers();
+
+ foreach (var id in userIds)
+ {
+ var basket = await _repository.GetBasketAsync(id);
+
+ await UpdatePriceInBasketItems(@event.ProductId, @event.NewPrice, @event.OldPrice, basket);
+ }
}
}
@@ -35,17 +46,19 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Even
if (itemsToUpdate != null)
{
+ _logger.LogInformation("----- ProductPriceChangedIntegrationEventHandler - Updating items in basket for user: {BuyerId} ({@Items})", basket.BuyerId, itemsToUpdate);
+
foreach (var item in itemsToUpdate)
{
- if(item.UnitPrice == oldPrice)
- {
+ if (item.UnitPrice == oldPrice)
+ {
var originalPrice = item.UnitPrice;
item.UnitPrice = newPrice;
item.OldUnitPrice = originalPrice;
}
}
await _repository.UpdateBasketAsync(basket);
- }
+ }
}
}
}
diff --git a/src/Services/Basket/Basket.API/Program.cs b/src/Services/Basket/Basket.API/Program.cs
index cf53c1b13..893a52400 100644
--- a/src/Services/Basket/Basket.API/Program.cs
+++ b/src/Services/Basket/Basket.API/Program.cs
@@ -12,52 +12,80 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
{
public class Program
{
- public static void Main(string[] args)
+ public static readonly string Namespace = typeof(Program).Namespace;
+ public static readonly string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1);
+
+ public static int Main(string[] args)
{
- BuildWebHost(args).Run();
+ var configuration = GetConfiguration();
+
+ Log.Logger = CreateSerilogLogger(configuration);
+
+ try
+ {
+ Log.Information("Configuring web host ({ApplicationContext})...", AppName);
+ var host = BuildWebHost(configuration, args);
+
+ Log.Information("Starting web host ({ApplicationContext})...", AppName);
+ host.Run();
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
}
- public static IWebHost BuildWebHost(string[] args) =>
+ private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
WebHost.CreateDefaultBuilder(args)
+ .CaptureStartupErrors(false)
.UseFailing(options =>
- {
- options.ConfigPath = "/Failing";
- })
- .UseContentRoot(Directory.GetCurrentDirectory())
+ options.ConfigPath = "/Failing")
.UseStartup()
- .ConfigureAppConfiguration((builderContext, config) =>
- {
- var builtConfig = config.Build();
-
- var configurationBuilder = new ConfigurationBuilder();
-
- if (Convert.ToBoolean(builtConfig["UseVault"]))
- {
- configurationBuilder.AddAzureKeyVault(
- $"https://{builtConfig["Vault:Name"]}.vault.azure.net/",
- builtConfig["Vault:ClientId"],
- builtConfig["Vault:ClientSecret"]);
- }
-
- configurationBuilder.AddEnvironmentVariables();
-
- config.AddConfiguration(configurationBuilder.Build());
- })
- .ConfigureLogging((hostingContext, builder) =>
- {
- builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
- builder.AddConsole();
- builder.AddDebug();
- builder.AddAzureWebAppDiagnostics();
- })
- .UseSerilog((builderContext, config) =>
- {
- config
- .MinimumLevel.Information()
- .Enrich.FromLogContext()
- .WriteTo.Console();
- })
.UseApplicationInsights()
+ .UseContentRoot(Directory.GetCurrentDirectory())
+ .UseConfiguration(configuration)
+ .UseSerilog()
.Build();
+
+ private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
+ {
+ var seqServerUrl = configuration["Serilog:SeqServerUrl"];
+
+ return new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("ApplicationContext", AppName)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
+ .ReadFrom.Configuration(configuration)
+ .CreateLogger();
+ }
+
+ private static IConfiguration GetConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddEnvironmentVariables();
+
+ var config = builder.Build();
+
+ if (config.GetValue("UseVault", false))
+ {
+ builder.AddAzureKeyVault(
+ $"https://{config["Vault:Name"]}.vault.azure.net/",
+ config["Vault:ClientId"],
+ config["Vault:ClientSecret"]);
+ }
+
+ return builder.Build();
+ }
}
}
diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs
index 4b9d65cc7..235b787d0 100644
--- a/src/Services/Basket/Basket.API/Startup.cs
+++ b/src/Services/Basket/Basket.API/Startup.cs
@@ -50,7 +50,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
- RegisterAppInsights(services);
+ RegisterAppInsights(services);
// Add framework services.
services.AddMvc(options =>
@@ -66,7 +66,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
services.AddCustomHealthCheck(Configuration);
- services.Configure(Configuration);
+ services.Configure(Configuration);
//By connecting here we are making sure that our service
//cannot start until redis is ready. This might slow down startup,
@@ -179,9 +179,10 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
+ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
- loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
+ //loggerFactory.AddAzureWebAppDiagnostics();
+ //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json
index 4bff4d70d..33f1c299f 100644
--- a/src/Services/Basket/Basket.API/appsettings.json
+++ b/src/Services/Basket/Basket.API/appsettings.json
@@ -1,10 +1,13 @@
{
- "Logging": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Debug",
- "System": "Information",
- "Microsoft": "Information"
+ "Serilog": {
+ "SeqServerUrl": null,
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "Microsoft": "Warning",
+ "Microsoft.eShopOnContainers": "Information",
+ "System": "Warning"
+ }
}
},
"IdentityUrl": "http://localhost:5105",
diff --git a/src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj b/src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj
index 294d3bcc3..4d422efc8 100644
--- a/src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj
+++ b/src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/src/Services/Basket/Basket.FunctionalTests/BasketScenarios.cs b/src/Services/Basket/Basket.FunctionalTests/BasketScenarios.cs
index 142cc51f1..f010eac9f 100644
--- a/src/Services/Basket/Basket.FunctionalTests/BasketScenarios.cs
+++ b/src/Services/Basket/Basket.FunctionalTests/BasketScenarios.cs
@@ -73,7 +73,6 @@ namespace Basket.FunctionalTests
string BuildCheckout()
{
-
var checkoutBasket = new
{
City = "city",
diff --git a/src/Services/Basket/Basket.UnitTests/Application/BasketWebApiTest.cs b/src/Services/Basket/Basket.UnitTests/Application/BasketWebApiTest.cs
index a2e382b92..0045ce4aa 100644
--- a/src/Services/Basket/Basket.UnitTests/Application/BasketWebApiTest.cs
+++ b/src/Services/Basket/Basket.UnitTests/Application/BasketWebApiTest.cs
@@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.Services.Basket.API.Controllers;
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
+using Microsoft.Extensions.Logging;
using Moq;
using System;
using System.Collections.Generic;
@@ -20,12 +21,14 @@ namespace UnitTest.Basket.Application
private readonly Mock _basketRepositoryMock;
private readonly Mock _identityServiceMock;
private readonly Mock _serviceBusMock;
+ private readonly Mock> _loggerMock;
public BasketWebApiTest()
{
_basketRepositoryMock = new Mock();
_identityServiceMock = new Mock();
_serviceBusMock = new Mock();
+ _loggerMock = new Mock>();
}
[Fact]
@@ -43,7 +46,11 @@ namespace UnitTest.Basket.Application
//Act
var basketController = new BasketController(
- _basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object);
+ _loggerMock.Object,
+ _basketRepositoryMock.Object,
+ _identityServiceMock.Object,
+ _serviceBusMock.Object);
+
var actionResult = await basketController.GetBasketByIdAsync(fakeCustomerId);
//Assert
@@ -65,14 +72,17 @@ namespace UnitTest.Basket.Application
//Act
var basketController = new BasketController(
- _basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object);
+ _loggerMock.Object,
+ _basketRepositoryMock.Object,
+ _identityServiceMock.Object,
+ _serviceBusMock.Object);
var actionResult = await basketController.UpdateBasketAsync(fakeCustomerBasket);
//Assert
Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK);
Assert.Equal(((CustomerBasket)actionResult.Value).BuyerId, fakeCustomerId);
- }
+ }
[Fact]
public async Task Doing_Checkout_Without_Basket_Should_Return_Bad_Request()
@@ -84,7 +94,10 @@ namespace UnitTest.Basket.Application
//Act
var basketController = new BasketController(
- _basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object);
+ _loggerMock.Object,
+ _basketRepositoryMock.Object,
+ _identityServiceMock.Object,
+ _serviceBusMock.Object);
var result = await basketController.CheckoutAsync(new BasketCheckout(), Guid.NewGuid().ToString()) as BadRequestResult;
Assert.NotNull(result);
@@ -102,7 +115,10 @@ namespace UnitTest.Basket.Application
_identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId);
var basketController = new BasketController(
- _basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object);
+ _loggerMock.Object,
+ _basketRepositoryMock.Object,
+ _identityServiceMock.Object,
+ _serviceBusMock.Object);
basketController.ControllerContext = new ControllerContext()
{
@@ -122,7 +138,7 @@ namespace UnitTest.Basket.Application
}
private CustomerBasket GetCustomerBasketFake(string fakeCustomerId)
- {
+ {
return new CustomerBasket(fakeCustomerId)
{
Items = new List()
diff --git a/src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj b/src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj
index d76680291..555bf8e30 100644
--- a/src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj
+++ b/src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj
@@ -7,7 +7,7 @@
-
+
all
diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj
index af93035ec..dfd58311f 100644
--- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj
+++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj
@@ -35,13 +35,13 @@
-
-
-
+
+
+
-
-
+
+
@@ -51,7 +51,10 @@
+
+
+
diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs
index 5d0e38bbf..833841049 100644
--- a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs
+++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs
@@ -77,14 +77,14 @@
}
catch (Exception ex)
{
- logger.LogError(ex.Message);
+ logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message);
return GetPreconfiguredCatalogBrands();
}
return File.ReadAllLines(csvFileCatalogBrands)
.Skip(1) // skip header row
.SelectTry(x => CreateCatalogBrand(x))
- .OnCaughtException(ex => { logger.LogError(ex.Message); return null; })
+ .OnCaughtException(ex => { logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; })
.Where(x => x != null);
}
@@ -132,14 +132,14 @@
}
catch (Exception ex)
{
- logger.LogError(ex.Message);
+ logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message);
return GetPreconfiguredCatalogTypes();
}
return File.ReadAllLines(csvFileCatalogTypes)
.Skip(1) // skip header row
.SelectTry(x => CreateCatalogType(x))
- .OnCaughtException(ex => { logger.LogError(ex.Message); return null; })
+ .OnCaughtException(ex => { logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; })
.Where(x => x != null);
}
@@ -187,7 +187,7 @@
}
catch (Exception ex)
{
- logger.LogError(ex.Message);
+ logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message);
return GetPreconfiguredItems();
}
@@ -198,7 +198,7 @@
.Skip(1) // skip header row
.Select(row => Regex.Split(row, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)") )
.SelectTry(column => CreateCatalogItem(column, csvheaders, catalogTypeIdLookup, catalogBrandIdLookup))
- .OnCaughtException(ex => { logger.LogError(ex.Message); return null; })
+ .OnCaughtException(ex => { logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; })
.Where(x => x != null);
}
@@ -378,7 +378,7 @@
sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
onRetry: (exception, timeSpan, retry, ctx) =>
{
- logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
+ logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", prefix, exception.GetType().Name, exception.Message, retry, retries);
}
);
}
diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs b/src/Services/Catalog/Catalog.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs
index 4c4c746a6..1c1dfd45f 100644
--- a/src/Services/Catalog/Catalog.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs
+++ b/src/Services/Catalog/Catalog.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs
@@ -49,7 +49,7 @@ namespace Catalog.API.Infrastructure.Filters
if (env.IsDevelopment())
{
- json.DeveloperMeesage = context.Exception;
+ json.DeveloperMessage = context.Exception;
}
context.Result = new InternalServerErrorObjectResult(json);
@@ -62,7 +62,7 @@ namespace Catalog.API.Infrastructure.Filters
{
public string[] Messages { get; set; }
- public object DeveloperMeesage { get; set; }
+ public object DeveloperMessage { get; set; }
}
}
}
diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs
index 8c550bf27..3b9476b9f 100644
--- a/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs
+++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs
@@ -4,7 +4,10 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities;
+using Microsoft.eShopOnContainers.Services.Catalog.API;
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
+using Microsoft.Extensions.Logging;
+using Serilog.Context;
using System;
using System.Data.Common;
using System.Threading.Tasks;
@@ -17,10 +20,15 @@ namespace Catalog.API.IntegrationEvents
private readonly IEventBus _eventBus;
private readonly CatalogContext _catalogContext;
private readonly IIntegrationEventLogService _eventLogService;
+ private readonly ILogger _logger;
- public CatalogIntegrationEventService(IEventBus eventBus, CatalogContext catalogContext,
- Func integrationEventLogServiceFactory)
+ public CatalogIntegrationEventService(
+ ILogger logger,
+ IEventBus eventBus,
+ CatalogContext catalogContext,
+ Func integrationEventLogServiceFactory)
{
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
_catalogContext = catalogContext ?? throw new ArgumentNullException(nameof(catalogContext));
_integrationEventLogServiceFactory = integrationEventLogServiceFactory ?? throw new ArgumentNullException(nameof(integrationEventLogServiceFactory));
_eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
@@ -31,26 +39,31 @@ namespace Catalog.API.IntegrationEvents
{
try
{
+ _logger.LogInformation("----- Publishing integration event: {IntegrationEventId_published} from {AppName} - ({@IntegrationEvent})", evt.Id, Program.AppName, evt);
+
await _eventLogService.MarkEventAsInProgressAsync(evt.Id);
_eventBus.Publish(evt);
await _eventLogService.MarkEventAsPublishedAsync(evt.Id);
}
- catch (Exception)
+ catch (Exception ex)
{
+ _logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", evt.Id, Program.AppName, evt);
await _eventLogService.MarkEventAsFailedAsync(evt.Id);
- }
+ }
}
public async Task SaveEventAndCatalogContextChangesAsync(IntegrationEvent evt)
{
+ _logger.LogInformation("----- CatalogIntegrationEventService - Saving changes and integrationEvent: {IntegrationEventId}", evt.Id);
+
//Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction():
//See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
- await ResilientTransaction.New(_catalogContext)
- .ExecuteAsync(async () => {
- // Achieving atomicity between original catalog database operation and the IntegrationEventLog thanks to a local transaction
- await _catalogContext.SaveChangesAsync();
- await _eventLogService.SaveEventAsync(evt, _catalogContext.Database.CurrentTransaction.GetDbTransaction());
- });
+ await ResilientTransaction.New(_catalogContext).ExecuteAsync(async () =>
+ {
+ // Achieving atomicity between original catalog database operation and the IntegrationEventLog thanks to a local transaction
+ await _catalogContext.SaveChangesAsync();
+ await _eventLogService.SaveEventAsync(evt, _catalogContext.Database.CurrentTransaction.GetDbTransaction());
+ });
}
}
}
diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs
index 0f30a3e0a..493a271cc 100644
--- a/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs
+++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs
@@ -8,39 +8,51 @@
using System.Linq;
using global::Catalog.API.IntegrationEvents;
using IntegrationEvents.Events;
+ using Serilog.Context;
+ using Microsoft.Extensions.Logging;
public class OrderStatusChangedToAwaitingValidationIntegrationEventHandler :
IIntegrationEventHandler
{
private readonly CatalogContext _catalogContext;
private readonly ICatalogIntegrationEventService _catalogIntegrationEventService;
+ private readonly ILogger _logger;
- public OrderStatusChangedToAwaitingValidationIntegrationEventHandler(CatalogContext catalogContext,
- ICatalogIntegrationEventService catalogIntegrationEventService)
+ public OrderStatusChangedToAwaitingValidationIntegrationEventHandler(
+ CatalogContext catalogContext,
+ ICatalogIntegrationEventService catalogIntegrationEventService,
+ ILogger logger)
{
_catalogContext = catalogContext;
_catalogIntegrationEventService = catalogIntegrationEventService;
+ _logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
}
- public async Task Handle(OrderStatusChangedToAwaitingValidationIntegrationEvent command)
+ public async Task Handle(OrderStatusChangedToAwaitingValidationIntegrationEvent @event)
{
- var confirmedOrderStockItems = new List();
-
- foreach (var orderStockItem in command.OrderStockItems)
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
{
- var catalogItem = _catalogContext.CatalogItems.Find(orderStockItem.ProductId);
- var hasStock = catalogItem.AvailableStock >= orderStockItem.Units;
- var confirmedOrderStockItem = new ConfirmedOrderStockItem(catalogItem.Id, hasStock);
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
- confirmedOrderStockItems.Add(confirmedOrderStockItem);
- }
+ var confirmedOrderStockItems = new List();
+
+ foreach (var orderStockItem in @event.OrderStockItems)
+ {
+ var catalogItem = _catalogContext.CatalogItems.Find(orderStockItem.ProductId);
+ var hasStock = catalogItem.AvailableStock >= orderStockItem.Units;
+ var confirmedOrderStockItem = new ConfirmedOrderStockItem(catalogItem.Id, hasStock);
- var confirmedIntegrationEvent = confirmedOrderStockItems.Any(c => !c.HasStock)
- ? (IntegrationEvent) new OrderStockRejectedIntegrationEvent(command.OrderId, confirmedOrderStockItems)
- : new OrderStockConfirmedIntegrationEvent(command.OrderId);
+ confirmedOrderStockItems.Add(confirmedOrderStockItem);
+ }
- await _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(confirmedIntegrationEvent);
- await _catalogIntegrationEventService.PublishThroughEventBusAsync(confirmedIntegrationEvent);
+ var confirmedIntegrationEvent = confirmedOrderStockItems.Any(c => !c.HasStock)
+ ? (IntegrationEvent)new OrderStockRejectedIntegrationEvent(@event.OrderId, confirmedOrderStockItems)
+ : new OrderStockConfirmedIntegrationEvent(@event.OrderId);
+
+ await _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(confirmedIntegrationEvent);
+ await _catalogIntegrationEventService.PublishThroughEventBusAsync(confirmedIntegrationEvent);
+
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs
index 0a45547f9..7d383254f 100644
--- a/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs
+++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs
@@ -4,28 +4,40 @@
using System.Threading.Tasks;
using Infrastructure;
using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events;
+ using Microsoft.Extensions.Logging;
+ using Serilog.Context;
public class OrderStatusChangedToPaidIntegrationEventHandler :
IIntegrationEventHandler
{
private readonly CatalogContext _catalogContext;
+ private readonly ILogger _logger;
- public OrderStatusChangedToPaidIntegrationEventHandler(CatalogContext catalogContext)
+ public OrderStatusChangedToPaidIntegrationEventHandler(
+ CatalogContext catalogContext,
+ ILogger logger)
{
_catalogContext = catalogContext;
+ _logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
}
- public async Task Handle(OrderStatusChangedToPaidIntegrationEvent command)
+ public async Task Handle(OrderStatusChangedToPaidIntegrationEvent @event)
{
- //we're not blocking stock/inventory
- foreach (var orderStockItem in command.OrderStockItems)
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
{
- var catalogItem = _catalogContext.CatalogItems.Find(orderStockItem.ProductId);
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
- catalogItem.RemoveStock(orderStockItem.Units);
- }
+ //we're not blocking stock/inventory
+ foreach (var orderStockItem in @event.OrderStockItems)
+ {
+ var catalogItem = _catalogContext.CatalogItems.Find(orderStockItem.ProductId);
+
+ catalogItem.RemoveStock(orderStockItem.Units);
+ }
- await _catalogContext.SaveChangesAsync();
+ await _catalogContext.SaveChangesAsync();
+
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Services/Catalog/Catalog.API/Program.cs b/src/Services/Catalog/Catalog.API/Program.cs
index c4ebb6183..c75b56c39 100644
--- a/src/Services/Catalog/Catalog.API/Program.cs
+++ b/src/Services/Catalog/Catalog.API/Program.cs
@@ -9,66 +9,97 @@ using Microsoft.Extensions.Options;
using Serilog;
using System;
using System.IO;
+
namespace Microsoft.eShopOnContainers.Services.Catalog.API
{
public class Program
{
- public static void Main(string[] args)
+ public static readonly string Namespace = typeof(Program).Namespace;
+ public static readonly string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1);
+
+ public static int Main(string[] args)
{
- BuildWebHost(args)
- .MigrateDbContext((context,services)=>
+ var configuration = GetConfiguration();
+
+ Log.Logger = CreateSerilogLogger(configuration);
+
+ try
+ {
+ Log.Information("Configuring web host ({ApplicationContext})...", AppName);
+ var host = BuildWebHost(configuration, args);
+
+ Log.Information("Applying migrations ({ApplicationContext})...", AppName);
+ host.MigrateDbContext((context, services) =>
{
var env = services.GetService();
var settings = services.GetService>();
var logger = services.GetService>();
new CatalogContextSeed()
- .SeedAsync(context,env,settings,logger)
- .Wait();
-
+ .SeedAsync(context, env, settings, logger)
+ .Wait();
})
- .MigrateDbContext((_,__)=> { })
- .Run();
+ .MigrateDbContext((_, __) => { });
+
+ Log.Information("Starting web host ({ApplicationContext})...", AppName);
+ host.Run();
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
}
- public static IWebHost BuildWebHost(string[] args) =>
+ private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
WebHost.CreateDefaultBuilder(args)
- .UseStartup()
+ .CaptureStartupErrors(false)
+ .UseStartup()
.UseApplicationInsights()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseWebRoot("Pics")
- .ConfigureAppConfiguration((builderContext, config) =>
- {
- var builtConfig = config.Build();
+ .UseConfiguration(configuration)
+ .UseSerilog()
+ .Build();
+
+ private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
+ {
+ var seqServerUrl = configuration["Serilog:SeqServerUrl"];
- var configurationBuilder = new ConfigurationBuilder();
+ return new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("ApplicationContext", AppName)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
+ .ReadFrom.Configuration(configuration)
+ .CreateLogger();
+ }
- if (Convert.ToBoolean(builtConfig["UseVault"]))
- {
- configurationBuilder.AddAzureKeyVault(
- $"https://{builtConfig["Vault:Name"]}.vault.azure.net/",
- builtConfig["Vault:ClientId"],
- builtConfig["Vault:ClientSecret"]);
- }
+ private static IConfiguration GetConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddEnvironmentVariables();
- configurationBuilder.AddEnvironmentVariables();
+ var config = builder.Build();
- config.AddConfiguration(configurationBuilder.Build());
- })
- .ConfigureLogging((hostingContext, builder) =>
- {
- builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
- builder.AddConsole();
- builder.AddDebug();
- builder.AddAzureWebAppDiagnostics();
- })
- .UseSerilog((builderContext, config) =>
- {
- config
- .MinimumLevel.Information()
- .Enrich.FromLogContext()
- .WriteTo.Console();
- })
- .Build();
+ if (config.GetValue("UseVault", false))
+ {
+ builder.AddAzureKeyVault(
+ $"https://{config["Vault:Name"]}.vault.azure.net/",
+ config["Vault:ClientId"],
+ config["Vault:ClientSecret"]);
+ }
+
+ return builder.Build();
+ }
}
}
\ No newline at end of file
diff --git a/src/Services/Catalog/Catalog.API/Properties/launchSettings.json b/src/Services/Catalog/Catalog.API/Properties/launchSettings.json
index 2b21ca280..8f2cde4db 100644
--- a/src/Services/Catalog/Catalog.API/Properties/launchSettings.json
+++ b/src/Services/Catalog/Catalog.API/Properties/launchSettings.json
@@ -13,7 +13,10 @@
"launchBrowser": true,
"launchUrl": "/swagger",
"environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
+ "ConnectionString": "server=localhost,5433;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word",
+ "ASPNETCORE_ENVIRONMENT": "Development",
+ "EventBusConnection": "localhost",
+ "Serilog:SeqServerUrl": "http://locahost:5340"
}
},
"Microsoft.eShopOnContainers.Services.Catalog.API": {
diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs
index 9c91a743e..0258a0a98 100644
--- a/src/Services/Catalog/Catalog.API/Startup.cs
+++ b/src/Services/Catalog/Catalog.API/Startup.cs
@@ -60,17 +60,18 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API
}
- public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
+ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//Configure logs
- loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
+ //loggerFactory.AddAzureWebAppDiagnostics();
+ //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
- loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
+ loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase);
app.UsePathBase(pathBase);
}
diff --git a/src/Services/Catalog/Catalog.API/appsettings.json b/src/Services/Catalog/Catalog.API/appsettings.json
index 0bf489699..b26f63bff 100644
--- a/src/Services/Catalog/Catalog.API/appsettings.json
+++ b/src/Services/Catalog/Catalog.API/appsettings.json
@@ -2,12 +2,15 @@
"ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word",
"PicBaseUrl": "http://localhost:5101/api/v1/catalog/items/[0]/pic/",
"UseCustomizationData": false,
- "Logging": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Trace",
- "System": "Information",
- "Microsoft": "Information"
+ "Serilog": {
+ "SeqServerUrl": null,
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "Microsoft": "Warning",
+ "Microsoft.eShopOnContainers": "Information",
+ "System": "Warning"
+ }
}
},
"AzureServiceBusEnabled": false,
diff --git a/src/Services/Catalog/Catalog.API/web.config b/src/Services/Catalog/Catalog.API/web.config
index e04a0397b..2157aef31 100644
--- a/src/Services/Catalog/Catalog.API/web.config
+++ b/src/Services/Catalog/Catalog.API/web.config
@@ -2,8 +2,10 @@
-
+
-
+
+
+
\ No newline at end of file
diff --git a/src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj b/src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj
index 04aeeb8ef..4cc9f337c 100644
--- a/src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj
+++ b/src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj
@@ -33,7 +33,7 @@
-
+
diff --git a/src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj b/src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj
index e69d785b1..02b12502b 100644
--- a/src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj
+++ b/src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj
@@ -7,7 +7,7 @@
-
+
all
diff --git a/src/Services/Identity/Identity.API/Controllers/AccountController.cs b/src/Services/Identity/Identity.API/Controllers/AccountController.cs
index 7a1fea312..6e9bbce16 100644
--- a/src/Services/Identity/Identity.API/Controllers/AccountController.cs
+++ b/src/Services/Identity/Identity.API/Controllers/AccountController.cs
@@ -20,7 +20,7 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
{
///
- /// This sample controller implements a typical login/logout/provision workflow for local and external accounts.
+ /// This sample controller implements a typical login/logout/provision workflow for local accounts.
/// The login service encapsulates the interactions with the user data store. This data store is in-memory only and cannot be used for production!
/// The interaction service provides a way for the UI to communicate with identityserver for validation and context retrieval
///
@@ -58,8 +58,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
if (context?.IdP != null)
{
- // if IdP is passed, then bypass showing the login screen
- return ExternalLogin(context.IdP, returnUrl);
+ throw new NotImplementedException("External login is not implemented!");
}
var vm = await BuildLoginViewModelAsync(returnUrl, context);
@@ -209,7 +208,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
}
catch (Exception ex)
{
- _logger.LogCritical(ex.Message);
+ _logger.LogError(ex, "LOGOUT ERROR: {ExceptionMessage}", ex.Message);
}
}
@@ -238,28 +237,6 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
return Redirect(redirectUrl);
}
- ///
- /// initiate roundtrip to external authentication provider
- ///
- [HttpGet]
- public IActionResult ExternalLogin(string provider, string returnUrl)
- {
- if (returnUrl != null)
- {
- returnUrl = UrlEncoder.Default.Encode(returnUrl);
- }
- returnUrl = "/account/externallogincallback?returnUrl=" + returnUrl;
-
- // start challenge and roundtrip the return URL
- var props = new AuthenticationProperties
- {
- RedirectUri = returnUrl,
- Items = { { "scheme", provider } }
- };
- return new ChallengeResult(provider, props);
- }
-
-
// GET: /Account/Register
[HttpGet]
[AllowAnonymous]
diff --git a/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs b/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs
index 3dbf28171..a1fda6455 100644
--- a/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs
+++ b/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs
@@ -51,7 +51,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
{
retryForAvaiability++;
- logger.LogError(ex.Message,$"There is an error migrating data for ApplicationDbContext");
+ logger.LogError(ex, "EXCEPTION ERROR while migrating {DbContextName}", nameof(ApplicationDbContext));
await SeedAsync(context,env,logger,settings, retryForAvaiability);
}
@@ -80,7 +80,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
}
catch (Exception ex)
{
- logger.LogError(ex.Message);
+ logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message);
return GetDefaultUser();
}
@@ -89,7 +89,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
.Skip(1) // skip header column
.Select(row => Regex.Split(row, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)") )
.SelectTry(column => CreateApplicationUser(column, csvheaders))
- .OnCaughtException(ex => { logger.LogError(ex.Message); return null; })
+ .OnCaughtException(ex => { logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; })
.Where(x => x != null)
.ToList();
@@ -199,7 +199,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
string imagesZipFile = Path.Combine(contentRootPath, "Setup", "images.zip");
if (!File.Exists(imagesZipFile))
{
- logger.LogError($" zip file '{imagesZipFile}' does not exists.");
+ logger.LogError("Zip file '{ZipFileName}' does not exists.", imagesZipFile);
return;
}
@@ -221,14 +221,14 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
}
else
{
- logger.LogWarning($"Skip file '{entry.Name}' in zipfile '{imagesZipFile}'");
+ logger.LogWarning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile);
}
}
}
}
catch (Exception ex)
{
- logger.LogError($"Exception in method GetPreconfiguredImages WebMVC. Exception Message={ex.Message}");
+ logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); ;
}
}
}
diff --git a/src/Services/Identity/Identity.API/Identity.API.csproj b/src/Services/Identity/Identity.API/Identity.API.csproj
index a6dea0d4b..d9acbfa09 100644
--- a/src/Services/Identity/Identity.API/Identity.API.csproj
+++ b/src/Services/Identity/Identity.API/Identity.API.csproj
@@ -17,18 +17,24 @@
-
-
+
+
-
+
+
+
+
+
+
+
diff --git a/src/Services/Identity/Identity.API/Models/AccountViewModels/ExternalLoginConfirmationViewModel.cs b/src/Services/Identity/Identity.API/Models/AccountViewModels/ExternalLoginConfirmationViewModel.cs
deleted file mode 100644
index 5d4f597a2..000000000
--- a/src/Services/Identity/Identity.API/Models/AccountViewModels/ExternalLoginConfirmationViewModel.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-
-namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
-{
- public class ExternalLoginConfirmationViewModel
- {
- [Required]
- [EmailAddress]
- public string Email { get; set; }
- }
-}
diff --git a/src/Services/Identity/Identity.API/Models/ManageViewModels/ManageLoginsViewModel.cs b/src/Services/Identity/Identity.API/Models/ManageViewModels/ManageLoginsViewModel.cs
deleted file mode 100644
index 0b24c3b7c..000000000
--- a/src/Services/Identity/Identity.API/Models/ManageViewModels/ManageLoginsViewModel.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using Microsoft.AspNetCore.Http.Authentication;
-using Microsoft.AspNetCore.Identity;
-using System.Collections.Generic;
-
-namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
-{
- public class ManageLoginsViewModel
- {
- public IList CurrentLogins { get; set; }
-
- public IList OtherLogins { get; set; }
- }
-}
diff --git a/src/Services/Identity/Identity.API/Models/ManageViewModels/RemoveLoginViewModel.cs b/src/Services/Identity/Identity.API/Models/ManageViewModels/RemoveLoginViewModel.cs
deleted file mode 100644
index c9171fcf3..000000000
--- a/src/Services/Identity/Identity.API/Models/ManageViewModels/RemoveLoginViewModel.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
-{
- public class RemoveLoginViewModel
- {
- public string LoginProvider { get; set; }
- public string ProviderKey { get; set; }
- }
-}
diff --git a/src/Services/Identity/Identity.API/Program.cs b/src/Services/Identity/Identity.API/Program.cs
index 401a2b8a5..8204a1ebf 100644
--- a/src/Services/Identity/Identity.API/Program.cs
+++ b/src/Services/Identity/Identity.API/Program.cs
@@ -14,70 +14,99 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API
{
public class Program
{
- public static void Main(string[] args)
+ public static readonly string Namespace = typeof(Program).Namespace;
+ public static readonly string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1);
+
+ public static int Main(string[] args)
{
- BuildWebHost(args)
- .MigrateDbContext((_, __) => { })
- .MigrateDbContext((context, services) =>
- {
- var env = services.GetService();
- var logger = services.GetService>();
- var settings = services.GetService>();
-
- new ApplicationDbContextSeed()
- .SeedAsync(context, env, logger, settings)
- .Wait();
- })
- .MigrateDbContext((context,services)=>
- {
- var configuration = services.GetService();
-
- new ConfigurationDbContextSeed()
- .SeedAsync(context, configuration)
- .Wait();
- }).Run();
- }
+ var configuration = GetConfiguration();
- public static IWebHost BuildWebHost(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
- .UseKestrel()
- .UseContentRoot(Directory.GetCurrentDirectory())
- .UseIISIntegration()
- .UseStartup()
- .ConfigureAppConfiguration((builderContext, config) =>
- {
- var builtConfig = config.Build();
+ Log.Logger = CreateSerilogLogger(configuration);
+
+ try
+ {
+ Log.Information("Configuring web host ({ApplicationContext})...", AppName);
+ var host = BuildWebHost(configuration, args);
- var configurationBuilder = new ConfigurationBuilder();
+ Log.Information("Applying migrations ({ApplicationContext})...", AppName);
+ host.MigrateDbContext((_, __) => { })
+ .MigrateDbContext((context, services) =>
+ {
+ var env = services.GetService();
+ var logger = services.GetService>();
+ var settings = services.GetService>();
- if (Convert.ToBoolean(builtConfig["UseVault"]))
+ new ApplicationDbContextSeed()
+ .SeedAsync(context, env, logger, settings)
+ .Wait();
+ })
+ .MigrateDbContext((context, services) =>
{
- configurationBuilder.AddAzureKeyVault(
- $"https://{builtConfig["Vault:Name"]}.vault.azure.net/",
- builtConfig["Vault:ClientId"],
- builtConfig["Vault:ClientSecret"]);
- }
-
- configurationBuilder.AddEnvironmentVariables();
-
- config.AddConfiguration(configurationBuilder.Build());
- })
- .ConfigureLogging((hostingContext, builder) =>
- {
- builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
- builder.AddConsole();
- builder.AddDebug();
- builder.AddAzureWebAppDiagnostics();
- })
+ new ConfigurationDbContextSeed()
+ .SeedAsync(context, configuration)
+ .Wait();
+ });
+
+ Log.Information("Starting web host ({ApplicationContext})...", AppName);
+ host.Run();
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
+ }
+
+ private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
+ WebHost.CreateDefaultBuilder(args)
+ .CaptureStartupErrors(false)
+ .UseStartup()
.UseApplicationInsights()
- .UseSerilog((builderContext, config) =>
- {
- config
- .MinimumLevel.Information()
- .Enrich.FromLogContext()
- .WriteTo.Console();
- })
+ .UseContentRoot(Directory.GetCurrentDirectory())
+ .UseConfiguration(configuration)
+ .UseSerilog()
.Build();
+
+ private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
+ {
+ var seqServerUrl = configuration["Serilog:SeqServerUrl"];
+
+ return new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("ApplicationContext", AppName)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
+ .ReadFrom.Configuration(configuration)
+ .CreateLogger();
+ }
+
+ private static IConfiguration GetConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddEnvironmentVariables();
+
+ var config = builder.Build();
+
+ if (config.GetValue("UseVault", false))
+ {
+ builder.AddAzureKeyVault(
+ $"https://{config["Vault:Name"]}.vault.azure.net/",
+ config["Vault:ClientId"],
+ config["Vault:ClientSecret"]);
+ }
+
+ return builder.Build();
+ }
+
}
}
diff --git a/src/Services/Identity/Identity.API/Startup.cs b/src/Services/Identity/Identity.API/Startup.cs
index b6e0d1390..e672bab60 100644
--- a/src/Services/Identity/Identity.API/Startup.cs
+++ b/src/Services/Identity/Identity.API/Startup.cs
@@ -42,12 +42,12 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API
// Add framework services.
services.AddDbContext(options =>
options.UseSqlServer(Configuration["ConnectionString"],
- sqlServerOptionsAction: sqlOptions =>
- {
- sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
- //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
- sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
- }));
+ sqlServerOptionsAction: sqlOptions =>
+ {
+ sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
+ //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
+ sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
+ }));
services.AddIdentity()
.AddEntityFrameworkStores()
@@ -90,22 +90,22 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString,
- sqlServerOptionsAction: sqlOptions =>
- {
- sqlOptions.MigrationsAssembly(migrationsAssembly);
- //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
- sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
- });
+ sqlServerOptionsAction: sqlOptions =>
+ {
+ sqlOptions.MigrationsAssembly(migrationsAssembly);
+ //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
+ sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
+ });
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString,
- sqlServerOptionsAction: sqlOptions =>
- {
- sqlOptions.MigrationsAssembly(migrationsAssembly);
- //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
- sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
- });
+ sqlServerOptionsAction: sqlOptions =>
+ {
+ sqlOptions.MigrationsAssembly(migrationsAssembly);
+ //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
+ sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
+ });
})
.Services.AddTransient();
@@ -117,8 +117,11 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
- {
- loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
+ {
+ //loggerFactory.AddConsole(Configuration.GetSection("Logging"));
+ //loggerFactory.AddDebug();
+ //loggerFactory.AddAzureWebAppDiagnostics();
+ //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
if (env.IsDevelopment())
{
@@ -133,7 +136,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
- loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
+ loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase);
app.UsePathBase(pathBase);
}
diff --git a/src/Services/Identity/Identity.API/appsettings.json b/src/Services/Identity/Identity.API/appsettings.json
index c5a109218..74d8e826c 100644
--- a/src/Services/Identity/Identity.API/appsettings.json
+++ b/src/Services/Identity/Identity.API/appsettings.json
@@ -5,12 +5,15 @@
"SpaClient": "http://localhost:5104",
"XamarinCallback": "http://localhost:5105/xamarincallback",
"UseCustomizationData": false,
- "Logging": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Trace",
- "System": "Information",
- "Microsoft": "Information"
+ "Serilog": {
+ "SeqServerUrl": null,
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "Microsoft": "Warning",
+ "Microsoft.eShopOnContainers": "Information",
+ "System": "Warning"
+ }
}
},
"ApplicationInsights": {
diff --git a/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs b/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs
index e9c299d23..f6b9ed708 100644
--- a/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs
+++ b/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs
@@ -6,6 +6,7 @@
using Microsoft.eShopOnContainers.Services.Locations.API.IntegrationEvents.Events;
using Microsoft.eShopOnContainers.Services.Locations.API.Model;
using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel;
+ using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -14,11 +15,16 @@
{
private readonly ILocationsRepository _locationsRepository;
private readonly IEventBus _eventBus;
+ private readonly ILogger _logger;
- public LocationsService(ILocationsRepository locationsRepository, IEventBus eventBus)
+ public LocationsService(
+ ILocationsRepository locationsRepository,
+ IEventBus eventBus,
+ ILogger logger)
{
_locationsRepository = locationsRepository ?? throw new ArgumentNullException(nameof(locationsRepository));
_eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task GetLocationAsync(int locationId)
@@ -37,11 +43,11 @@
}
public async Task AddOrUpdateUserLocationAsync(string userId, LocationRequest currentPosition)
- {
+ {
// Get the list of ordered regions the user currently is within
var currentUserAreaLocationList = await _locationsRepository.GetCurrentUserRegionsListAsync(currentPosition);
-
- if(currentUserAreaLocationList is null)
+
+ if (currentUserAreaLocationList is null)
{
throw new LocationDomainException("User current area not found");
}
@@ -66,13 +72,17 @@
{
var newUserLocations = MapUserLocationDetails(newLocations);
var @event = new UserLocationUpdatedIntegrationEvent(userId, newUserLocations);
+
+ _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
_eventBus.Publish(@event);
}
private List MapUserLocationDetails(List newLocations)
{
var result = new List();
- newLocations.ForEach(location => {
+ newLocations.ForEach(location =>
+ {
result.Add(new UserLocationDetails()
{
LocationId = location.LocationId,
diff --git a/src/Services/Location/Locations.API/Locations.API.csproj b/src/Services/Location/Locations.API/Locations.API.csproj
index f7f0ff3c8..0233fbcbf 100644
--- a/src/Services/Location/Locations.API/Locations.API.csproj
+++ b/src/Services/Location/Locations.API/Locations.API.csproj
@@ -7,12 +7,12 @@
-
-
-
-
-
+
+
+
+
+
@@ -25,7 +25,10 @@
+
+
+
diff --git a/src/Services/Location/Locations.API/Program.cs b/src/Services/Location/Locations.API/Program.cs
index 11be8d68c..c13df985f 100644
--- a/src/Services/Location/Locations.API/Program.cs
+++ b/src/Services/Location/Locations.API/Program.cs
@@ -11,48 +11,78 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
{
public class Program
{
- public static void Main(string[] args)
+ public static readonly string Namespace = typeof(Program).Namespace;
+ public static readonly string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1);
+
+ public static int Main(string[] args)
{
- BuildWebHost(args).Run();
+ var configuration = GetConfiguration();
+
+ Log.Logger = CreateSerilogLogger(configuration);
+
+ try
+ {
+ Log.Information("Configuring web host ({ApplicationContext})...", AppName);
+ var host = BuildWebHost(configuration, args);
+
+ Log.Information("Starting web host ({ApplicationContext})...", AppName);
+ host.Run();
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
}
- public static IWebHost BuildWebHost(string[] args) =>
+ private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
WebHost.CreateDefaultBuilder(args)
- .UseContentRoot(Directory.GetCurrentDirectory())
+ .CaptureStartupErrors(false)
.UseStartup()
- .ConfigureAppConfiguration((builderContext, config) =>
- {
- var builtConfig = config.Build();
-
- var configurationBuilder = new ConfigurationBuilder();
-
- if (Convert.ToBoolean(builtConfig["UseVault"]))
- {
- configurationBuilder.AddAzureKeyVault(
- $"https://{builtConfig["Vault:Name"]}.vault.azure.net/",
- builtConfig["Vault:ClientId"],
- builtConfig["Vault:ClientSecret"]);
- }
-
- configurationBuilder.AddEnvironmentVariables();
-
- config.AddConfiguration(configurationBuilder.Build());
- })
- .ConfigureLogging((hostingContext, builder) =>
- {
- builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
- builder.AddConsole();
- builder.AddDebug();
- builder.AddAzureWebAppDiagnostics();
- })
.UseApplicationInsights()
- .UseSerilog((builderContext, config) =>
- {
- config
- .MinimumLevel.Information()
- .Enrich.FromLogContext()
- .WriteTo.Console();
- })
+ .UseContentRoot(Directory.GetCurrentDirectory())
+ .UseConfiguration(configuration)
+ .UseSerilog()
.Build();
+
+ private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
+ {
+ var seqServerUrl = configuration["Serilog:SeqServerUrl"];
+
+ return new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("ApplicationContext", AppName)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
+ .ReadFrom.Configuration(configuration)
+ .CreateLogger();
+ }
+
+ private static IConfiguration GetConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddEnvironmentVariables();
+
+ var config = builder.Build();
+
+ if (config.GetValue("UseVault", false))
+ {
+ builder.AddAzureKeyVault(
+ $"https://{config["Vault:Name"]}.vault.azure.net/",
+ config["Vault:ClientId"],
+ config["Vault:ClientSecret"]);
+ }
+
+ return builder.Build();
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/Services/Location/Locations.API/Startup.cs b/src/Services/Location/Locations.API/Startup.cs
index d18769fcc..5ef9d195d 100644
--- a/src/Services/Location/Locations.API/Startup.cs
+++ b/src/Services/Location/Locations.API/Startup.cs
@@ -153,9 +153,10 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
+ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
- loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
+ //loggerFactory.AddAzureWebAppDiagnostics();
+ //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
diff --git a/src/Services/Location/Locations.API/appsettings.json b/src/Services/Location/Locations.API/appsettings.json
index cd4166bb0..43fe53873 100644
--- a/src/Services/Location/Locations.API/appsettings.json
+++ b/src/Services/Location/Locations.API/appsettings.json
@@ -2,12 +2,15 @@
"ConnectionString": "mongodb://nosql.data",
"Database": "LocationsDb",
"IdentityUrl": "http://localhost:5105",
- "Logging": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Trace",
- "System": "Information",
- "Microsoft": "Information"
+ "Serilog": {
+ "SeqServerUrl": null,
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "Microsoft": "Warning",
+ "Microsoft.eShopOnContainers": "Information",
+ "System": "Warning"
+ }
}
},
"AzureServiceBusEnabled": false,
diff --git a/src/Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj b/src/Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj
index a1ad058cb..5de852a32 100644
--- a/src/Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj
+++ b/src/Services/Location/Locations.FunctionalTests/Locations.FunctionalTests.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs
index 8d7091804..ac800909e 100644
--- a/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs
+++ b/src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs
@@ -77,7 +77,7 @@
sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
onRetry: (exception, timeSpan, retry, ctx) =>
{
- logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
+ logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", prefix, exception.GetType().Name, exception.Message, retry, retries);
}
);
}
diff --git a/src/Services/Marketing/Marketing.API/IntegrationEvents/Handlers/UserLocationUpdatedIntegrationEventHandler.cs b/src/Services/Marketing/Marketing.API/IntegrationEvents/Handlers/UserLocationUpdatedIntegrationEventHandler.cs
index 77574c0e5..3d5e62e45 100644
--- a/src/Services/Marketing/Marketing.API/IntegrationEvents/Handlers/UserLocationUpdatedIntegrationEventHandler.cs
+++ b/src/Services/Marketing/Marketing.API/IntegrationEvents/Handlers/UserLocationUpdatedIntegrationEventHandler.cs
@@ -4,6 +4,8 @@
using Marketing.API.Model;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Repositories;
+ using Microsoft.Extensions.Logging;
+ using Serilog.Context;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -12,20 +14,29 @@
: IIntegrationEventHandler
{
private readonly IMarketingDataRepository _marketingDataRepository;
+ private readonly ILogger _logger;
- public UserLocationUpdatedIntegrationEventHandler(IMarketingDataRepository repository)
+ public UserLocationUpdatedIntegrationEventHandler(
+ IMarketingDataRepository repository,
+ ILogger logger)
{
_marketingDataRepository = repository ?? throw new ArgumentNullException(nameof(repository));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(UserLocationUpdatedIntegrationEvent @event)
{
- var userMarketingData = await _marketingDataRepository.GetAsync(@event.UserId);
- userMarketingData = userMarketingData ??
- new MarketingData() { UserId = @event.UserId };
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
- userMarketingData.Locations = MapUpdatedUserLocations(@event.LocationList);
- await _marketingDataRepository.UpdateLocationAsync(userMarketingData);
+ var userMarketingData = await _marketingDataRepository.GetAsync(@event.UserId);
+ userMarketingData = userMarketingData ??
+ new MarketingData() { UserId = @event.UserId };
+
+ userMarketingData.Locations = MapUpdatedUserLocations(@event.LocationList);
+ await _marketingDataRepository.UpdateLocationAsync(userMarketingData);
+ }
}
private List MapUpdatedUserLocations(List newUserLocations)
diff --git a/src/Services/Marketing/Marketing.API/Marketing.API.csproj b/src/Services/Marketing/Marketing.API/Marketing.API.csproj
index 8efd65ef2..f9aff6e38 100644
--- a/src/Services/Marketing/Marketing.API/Marketing.API.csproj
+++ b/src/Services/Marketing/Marketing.API/Marketing.API.csproj
@@ -20,15 +20,15 @@
-
+
-
-
-
+
+
+
-
-
+
+
@@ -41,7 +41,10 @@
+
+
+
diff --git a/src/Services/Marketing/Marketing.API/Program.cs b/src/Services/Marketing/Marketing.API/Program.cs
index cca7f4d79..ae26c9786 100644
--- a/src/Services/Marketing/Marketing.API/Program.cs
+++ b/src/Services/Marketing/Marketing.API/Program.cs
@@ -12,59 +12,89 @@
public class Program
{
- public static void Main(string[] args)
+ public static readonly string Namespace = typeof(Program).Namespace;
+ public static readonly string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1);
+
+ public static int Main(string[] args)
{
- BuildWebHost(args)
- .MigrateDbContext((context, services) =>
+ var configuration = GetConfiguration();
+
+ Log.Logger = CreateSerilogLogger(configuration);
+
+ try
{
- var logger = services.GetService>();
+ Log.Information("Configuring web host ({ApplicationContext})...", AppName);
+ var host = BuildWebHost(configuration, args);
+
+ Log.Information("Applying migrations ({ApplicationContext})...", AppName);
+ host.MigrateDbContext((context, services) =>
+ {
+ var logger = services.GetService>();
+
+ new MarketingContextSeed()
+ .SeedAsync(context, logger)
+ .Wait();
+ });
- new MarketingContextSeed()
- .SeedAsync(context,logger)
- .Wait();
+ Log.Information("Starting web host ({ApplicationContext})...", AppName);
+ host.Run();
- }).Run();
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
}
- public static IWebHost BuildWebHost(string[] args) =>
+ private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
WebHost.CreateDefaultBuilder(args)
+ .CaptureStartupErrors(false)
+ .UseStartup()
.UseApplicationInsights()
.UseContentRoot(Directory.GetCurrentDirectory())
- .UseStartup()
.UseWebRoot("Pics")
- .ConfigureAppConfiguration((builderContext, config) =>
- {
- var builtConfig = config.Build();
+ .UseConfiguration(configuration)
+ .UseSerilog()
+ .Build();
- var configurationBuilder = new ConfigurationBuilder();
+ private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
+ {
+ var seqServerUrl = configuration["Serilog:SeqServerUrl"];
- if (Convert.ToBoolean(builtConfig["UseVault"]))
- {
- configurationBuilder.AddAzureKeyVault(
- $"https://{builtConfig["Vault:Name"]}.vault.azure.net/",
- builtConfig["Vault:ClientId"],
- builtConfig["Vault:ClientSecret"]);
- }
+ return new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("ApplicationContext", AppName)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
+ .ReadFrom.Configuration(configuration)
+ .CreateLogger();
+ }
- configurationBuilder.AddEnvironmentVariables();
+ private static IConfiguration GetConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddEnvironmentVariables();
- config.AddConfiguration(configurationBuilder.Build());
- })
- .ConfigureLogging((hostingContext, builder) =>
- {
- builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
- builder.AddConsole();
- builder.AddDebug();
- builder.AddAzureWebAppDiagnostics();
- })
- .UseApplicationInsights()
- .UseSerilog((builderContext, config) =>
- {
- config
- .MinimumLevel.Information()
- .Enrich.FromLogContext()
- .WriteTo.Console();
- })
- .Build();
+ var config = builder.Build();
+
+ if (config.GetValue("UseVault", false))
+ {
+ builder.AddAzureKeyVault(
+ $"https://{config["Vault:Name"]}.vault.azure.net/",
+ config["Vault:ClientId"],
+ config["Vault:ClientSecret"]);
+ }
+
+ return builder.Build();
+ }
}
}
diff --git a/src/Services/Marketing/Marketing.API/Startup.cs b/src/Services/Marketing/Marketing.API/Startup.cs
index 276a82fa9..75c749452 100644
--- a/src/Services/Marketing/Marketing.API/Startup.cs
+++ b/src/Services/Marketing/Marketing.API/Startup.cs
@@ -179,7 +179,8 @@
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILoggerFactory loggerFactory)
{
- loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
+ //loggerFactory.AddAzureWebAppDiagnostics();
+ //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
var pathBase = Configuration["PATH_BASE"];
diff --git a/src/Services/Marketing/Marketing.API/appsettings.json b/src/Services/Marketing/Marketing.API/appsettings.json
index 2af660446..c16978dce 100644
--- a/src/Services/Marketing/Marketing.API/appsettings.json
+++ b/src/Services/Marketing/Marketing.API/appsettings.json
@@ -1,8 +1,13 @@
{
- "Logging": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Trace"
+ "Serilog": {
+ "SeqServerUrl": null,
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "Microsoft": "Warning",
+ "Microsoft.eShopOnContainers": "Information",
+ "System": "Warning"
+ }
}
},
"ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word",
diff --git a/src/Services/Marketing/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj b/src/Services/Marketing/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj
index 743f2fb1d..13f91249a 100644
--- a/src/Services/Marketing/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj
+++ b/src/Services/Marketing/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/src/Services/Ordering/Ordering.API/Application/Behaviors/LoggingBehavior.cs b/src/Services/Ordering/Ordering.API/Application/Behaviors/LoggingBehavior.cs
index 2708db8a9..35023b297 100644
--- a/src/Services/Ordering/Ordering.API/Application/Behaviors/LoggingBehavior.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Behaviors/LoggingBehavior.cs
@@ -1,9 +1,11 @@
using MediatR;
using Microsoft.Extensions.Logging;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
-namespace Ordering.API.Infrastructure.Behaviors
+namespace Ordering.API.Application.Behaviors
{
public class LoggingBehavior : IPipelineBehavior
{
@@ -12,9 +14,10 @@ namespace Ordering.API.Infrastructure.Behaviors
public async Task Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate next)
{
- _logger.LogInformation($"Handling {typeof(TRequest).Name}");
+ _logger.LogInformation("----- Handling command {CommandName} ({@Command})", request.GetGenericTypeName(), request);
var response = await next();
- _logger.LogInformation($"Handled {typeof(TResponse).Name}");
+ _logger.LogInformation("----- Command {CommandName} handled - response: {@Response}", request.GetGenericTypeName(), response);
+
return response;
}
}
diff --git a/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs b/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs
index 6f9aed9e5..d9d3e0b0a 100644
--- a/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs
@@ -1,11 +1,11 @@
using MediatR;
using Microsoft.EntityFrameworkCore;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
using Microsoft.Extensions.Logging;
using Ordering.API.Application.IntegrationEvents;
+using Serilog.Context;
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -28,33 +28,41 @@ namespace Ordering.API.Application.Behaviors
public async Task Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate next)
{
- TResponse response = default(TResponse);
+ var response = default(TResponse);
+ var typeName = request.GetGenericTypeName();
try
{
- var strategy = _dbContext.Database.CreateExecutionStrategy();
- await strategy.ExecuteAsync(async () =>
+ if (_dbContext.HasActiveTransaction)
{
- _logger.LogInformation($"Begin transaction {typeof(TRequest).Name}");
+ return await next();
+ }
+
+ var strategy = _dbContext.Database.CreateExecutionStrategy();
- await _dbContext.BeginTransactionAsync();
+ await strategy.ExecuteAsync(async () =>
+ {
+ using (var transaction = await _dbContext.BeginTransactionAsync())
+ using (LogContext.PushProperty("TransactionContext", transaction.TransactionId))
+ {
+ _logger.LogInformation("----- Begin transaction {TransactionId} for {CommandName} ({@Command})", transaction.TransactionId, typeName, request);
- response = await next();
+ response = await next();
- await _dbContext.CommitTransactionAsync();
+ _logger.LogInformation("----- Commit transaction {TransactionId} for {CommandName}", transaction.TransactionId, typeName);
- _logger.LogInformation($"Committed transaction {typeof(TRequest).Name}");
+ await _dbContext.CommitTransactionAsync(transaction);
+ }
await _orderingIntegrationEventService.PublishEventsThroughEventBusAsync();
});
return response;
}
- catch (Exception)
+ catch (Exception ex)
{
- _logger.LogInformation($"Rollback transaction executed {typeof(TRequest).Name}");
+ _logger.LogError(ex, "ERROR Handling transaction for {CommandName} ({@Command})", typeName, request);
- _dbContext.RollbackTransaction();
throw;
}
}
diff --git a/src/Services/Ordering/Ordering.API/Application/Behaviors/ValidatorBehavior.cs b/src/Services/Ordering/Ordering.API/Application/Behaviors/ValidatorBehavior.cs
index de0a2ba4b..6fc12258b 100644
--- a/src/Services/Ordering/Ordering.API/Application/Behaviors/ValidatorBehavior.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Behaviors/ValidatorBehavior.cs
@@ -1,20 +1,31 @@
using FluentValidation;
using MediatR;
+using Microsoft.Extensions.Logging;
using Ordering.Domain.Exceptions;
-using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
-namespace Ordering.API.Infrastructure.Behaviors
+namespace Ordering.API.Application.Behaviors
{
public class ValidatorBehavior : IPipelineBehavior
{
+ private readonly ILogger> _logger;
private readonly IValidator[] _validators;
- public ValidatorBehavior(IValidator[] validators) => _validators = validators;
+
+ public ValidatorBehavior(IValidator[] validators, ILogger> logger)
+ {
+ _validators = validators;
+ _logger = logger;
+ }
public async Task Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate next)
{
+ var typeName = request.GetGenericTypeName();
+
+ _logger.LogInformation("----- Validating command {CommandType}", typeName);
+
var failures = _validators
.Select(v => v.Validate(request))
.SelectMany(result => result.Errors)
@@ -23,12 +34,13 @@ namespace Ordering.API.Infrastructure.Behaviors
if (failures.Any())
{
+ _logger.LogWarning("Validation errors - {CommandType} - Command: {@Command} - Errors: {@ValidationErrors}", typeName, request, failures);
+
throw new OrderingDomainException(
$"Command Validation Errors for type {typeof(TRequest).Name}", new ValidationException("Validation exception", failures));
}
- var response = await next();
- return response;
+ return await next();
}
}
-}
+}
\ No newline at end of file
diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs
index a4c4facb8..85858486c 100644
--- a/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs
@@ -2,6 +2,7 @@
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
+using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
@@ -40,7 +41,11 @@ namespace Ordering.API.Application.Commands
// Use for Idempotency in Command process
public class CancelOrderIdentifiedCommandHandler : IdentifiedCommandHandler
{
- public CancelOrderIdentifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
+ public CancelOrderIdentifiedCommandHandler(
+ IMediator mediator,
+ IRequestManager requestManager,
+ ILogger> logger)
+ : base(mediator, requestManager, logger)
{
}
diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs
index 9a3035d5c..00a088c09 100644
--- a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs
@@ -6,6 +6,7 @@
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
+ using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
@@ -18,17 +19,20 @@
private readonly IIdentityService _identityService;
private readonly IMediator _mediator;
private readonly IOrderingIntegrationEventService _orderingIntegrationEventService;
+ private readonly ILogger _logger;
// Using DI to inject infrastructure persistence Repositories
public CreateOrderCommandHandler(IMediator mediator,
IOrderingIntegrationEventService orderingIntegrationEventService,
- IOrderRepository orderRepository,
- IIdentityService identityService)
+ IOrderRepository orderRepository,
+ IIdentityService identityService,
+ ILogger logger)
{
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
_identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
_orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(CreateOrderCommand message, CancellationToken cancellationToken)
@@ -36,20 +40,22 @@
// Add Integration event to clean the basket
var orderStartedIntegrationEvent = new OrderStartedIntegrationEvent(message.UserId);
await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStartedIntegrationEvent);
-
+
// Add/Update the Buyer AggregateRoot
// DDD patterns comment: Add child entities and value-objects through the Order Aggregate-Root
// methods and constructor so validations, invariants and business logic
// make sure that consistency is preserved across the whole aggregate
var address = new Address(message.Street, message.City, message.State, message.Country, message.ZipCode);
var order = new Order(message.UserId, message.UserName, address, message.CardTypeId, message.CardNumber, message.CardSecurityNumber, message.CardHolderName, message.CardExpiration);
-
+
foreach (var item in message.OrderItems)
{
order.AddOrderItem(item.ProductId, item.ProductName, item.UnitPrice, item.Discount, item.PictureUrl, item.Units);
}
- _orderRepository.Add(order);
+ _logger.LogInformation("----- Creating Order - Order: {@Order}", order);
+
+ _orderRepository.Add(order);
return await _orderRepository.UnitOfWork
.SaveEntitiesAsync();
@@ -60,7 +66,11 @@
// Use for Idempotency in Command process
public class CreateOrderIdentifiedCommandHandler : IdentifiedCommandHandler
{
- public CreateOrderIdentifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
+ public CreateOrderIdentifiedCommandHandler(
+ IMediator mediator,
+ IRequestManager requestManager,
+ ILogger> logger)
+ : base(mediator, requestManager, logger)
{
}
diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommandHandler.cs
index f00ea44c8..e389e3975 100644
--- a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommandHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommandHandler.cs
@@ -1,5 +1,10 @@
using MediatR;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
+using Microsoft.Extensions.Logging;
+using Ordering.API.Application.Behaviors;
+using Ordering.API.Application.Commands;
+using System;
using System.Threading;
using System.Threading.Tasks;
@@ -16,11 +21,16 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
{
private readonly IMediator _mediator;
private readonly IRequestManager _requestManager;
+ private readonly ILogger> _logger;
- public IdentifiedCommandHandler(IMediator mediator, IRequestManager requestManager)
+ public IdentifiedCommandHandler(
+ IMediator mediator,
+ IRequestManager requestManager,
+ ILogger> logger)
{
_mediator = mediator;
_requestManager = requestManager;
+ _logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
}
///
@@ -48,16 +58,60 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
else
{
await _requestManager.CreateRequestForCommandAsync(message.Id);
- try
- {
- // Send the embeded business command to mediator so it runs its related CommandHandler
- var result = await _mediator.Send(message.Command);
- return result;
- }
- catch
- {
- return default(R);
- }
+ try
+ {
+ var command = message.Command;
+ var commandName = command.GetGenericTypeName();
+ var idProperty = string.Empty;
+ var commandId = string.Empty;
+
+ switch (command)
+ {
+ case CreateOrderCommand createOrderCommand:
+ idProperty = nameof(createOrderCommand.UserId);
+ commandId = createOrderCommand.UserId;
+ break;
+
+ case CancelOrderCommand cancelOrderCommand:
+ idProperty = nameof(cancelOrderCommand.OrderNumber);
+ commandId = $"{cancelOrderCommand.OrderNumber}";
+ break;
+
+ case ShipOrderCommand shipOrderCommand:
+ idProperty = nameof(shipOrderCommand.OrderNumber);
+ commandId = $"{shipOrderCommand.OrderNumber}";
+ break;
+
+ default:
+ idProperty = "Id?";
+ commandId = "n/a";
+ break;
+ }
+
+ _logger.LogInformation(
+ "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
+ commandName,
+ idProperty,
+ commandId,
+ command);
+
+ // Send the embeded business command to mediator so it runs its related CommandHandler
+ var result = await _mediator.Send(command);
+
+ _logger.LogInformation(
+ "----- Command result: {@Result} - {CommandName} - {IdProperty}: {CommandId} ({@Command})",
+ result,
+ commandName,
+ idProperty,
+ commandId,
+ command);
+
+ return result;
+ }
+ catch
+ {
+ return default(R);
+ }
}
}
}
diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs
index cee307ca2..c40ddb37f 100644
--- a/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs
@@ -2,6 +2,7 @@
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
+using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
@@ -40,7 +41,11 @@ namespace Ordering.API.Application.Commands
// Use for Idempotency in Command process
public class SetAwaitingValidationIdentifiedOrderStatusCommandHandler : IdentifiedCommandHandler
{
- public SetAwaitingValidationIdentifiedOrderStatusCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
+ public SetAwaitingValidationIdentifiedOrderStatusCommandHandler(
+ IMediator mediator,
+ IRequestManager requestManager,
+ ILogger> logger)
+ : base(mediator, requestManager, logger)
{
}
diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs
index 211e568cb..8282bf6ab 100644
--- a/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs
@@ -2,6 +2,7 @@
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
+using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
@@ -43,7 +44,11 @@ namespace Ordering.API.Application.Commands
// Use for Idempotency in Command process
public class SetPaidIdentifiedOrderStatusCommandHandler : IdentifiedCommandHandler
{
- public SetPaidIdentifiedOrderStatusCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
+ public SetPaidIdentifiedOrderStatusCommandHandler(
+ IMediator mediator,
+ IRequestManager requestManager,
+ ILogger> logger)
+ : base(mediator, requestManager, logger)
{
}
diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs
index 4e1bc6185..e9c3eb75c 100644
--- a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs
@@ -2,6 +2,7 @@
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
+using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
@@ -43,7 +44,11 @@ namespace Ordering.API.Application.Commands
// Use for Idempotency in Command process
public class SetStockConfirmedOrderStatusIdenfifiedCommandHandler : IdentifiedCommandHandler
{
- public SetStockConfirmedOrderStatusIdenfifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
+ public SetStockConfirmedOrderStatusIdenfifiedCommandHandler(
+ IMediator mediator,
+ IRequestManager requestManager,
+ ILogger> logger)
+ : base(mediator, requestManager, logger)
{
}
diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs
index 2b7a72526..2e6c794d2 100644
--- a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs
@@ -2,6 +2,7 @@
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
+using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
@@ -44,7 +45,11 @@ namespace Ordering.API.Application.Commands
// Use for Idempotency in Command process
public class SetStockRejectedOrderStatusIdenfifiedCommandHandler : IdentifiedCommandHandler
{
- public SetStockRejectedOrderStatusIdenfifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
+ public SetStockRejectedOrderStatusIdenfifiedCommandHandler(
+ IMediator mediator,
+ IRequestManager requestManager,
+ ILogger> logger)
+ : base(mediator, requestManager, logger)
{
}
diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs
index b4a6ac26d..fcac86ef9 100644
--- a/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs
@@ -2,6 +2,7 @@
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
+using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
@@ -9,7 +10,7 @@ namespace Ordering.API.Application.Commands
{
// Regular CommandHandler
public class ShipOrderCommandHandler : IRequestHandler
- {
+ {
private readonly IOrderRepository _orderRepository;
public ShipOrderCommandHandler(IOrderRepository orderRepository)
@@ -26,7 +27,7 @@ namespace Ordering.API.Application.Commands
public async Task Handle(ShipOrderCommand command, CancellationToken cancellationToken)
{
var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber);
- if(orderToUpdate == null)
+ if (orderToUpdate == null)
{
return false;
}
@@ -40,7 +41,11 @@ namespace Ordering.API.Application.Commands
// Use for Idempotency in Command process
public class ShipOrderIdentifiedCommandHandler : IdentifiedCommandHandler
{
- public ShipOrderIdentifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
+ public ShipOrderIdentifiedCommandHandler(
+ IMediator mediator,
+ IRequestManager requestManager,
+ ILogger> logger)
+ : base(mediator, requestManager, logger)
{
}
diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs
index d738c07ee..bea8eaac5 100644
--- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs
@@ -8,16 +8,16 @@ using System.Threading.Tasks;
namespace Ordering.API.Application.DomainEventHandlers.BuyerAndPaymentMethodVerified
{
- public class UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler
+ public class UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler
: INotificationHandler
{
- private readonly IOrderRepository _orderRepository;
- private readonly ILoggerFactory _logger;
+ private readonly IOrderRepository _orderRepository;
+ private readonly ILoggerFactory _logger;
public UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler(
- IOrderRepository orderRepository, ILoggerFactory logger)
+ IOrderRepository orderRepository, ILoggerFactory logger)
{
- _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
+ _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
@@ -28,10 +28,11 @@ namespace Ordering.API.Application.DomainEventHandlers.BuyerAndPaymentMethodVeri
{
var orderToUpdate = await _orderRepository.GetAsync(buyerPaymentMethodVerifiedEvent.OrderId);
orderToUpdate.SetBuyerId(buyerPaymentMethodVerifiedEvent.Buyer.Id);
- orderToUpdate.SetPaymentId(buyerPaymentMethodVerifiedEvent.Payment.Id);
+ orderToUpdate.SetPaymentId(buyerPaymentMethodVerifiedEvent.Payment.Id);
- _logger.CreateLogger(nameof(UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler))
- .LogTrace($"Order with Id: {buyerPaymentMethodVerifiedEvent.OrderId} has been successfully updated with a payment method id: { buyerPaymentMethodVerifiedEvent.Payment.Id }");
+ _logger.CreateLogger()
+ .LogTrace("Order with Id: {OrderId} has been successfully updated with a payment method {PaymentMethod} ({Id})",
+ buyerPaymentMethodVerifiedEvent.OrderId, nameof(buyerPaymentMethodVerifiedEvent.Payment), buyerPaymentMethodVerifiedEvent.Payment.Id);
}
- }
+ }
}
diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCancelled/OrderCancelledDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCancelled/OrderCancelledDomainEventHandler.cs
index 32967f6a7..f8fddf3a8 100644
--- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCancelled/OrderCancelledDomainEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCancelled/OrderCancelledDomainEventHandler.cs
@@ -33,9 +33,9 @@ namespace Ordering.API.Application.DomainEventHandlers.OrderCancelled
public async Task Handle(OrderCancelledDomainEvent orderCancelledDomainEvent, CancellationToken cancellationToken)
{
- _logger.CreateLogger(nameof(OrderCancelledDomainEvent))
- .LogTrace($"Order with Id: {orderCancelledDomainEvent.Order.Id} has been successfully updated with " +
- $"a status order id: {OrderStatus.Shipped.Id}");
+ _logger.CreateLogger()
+ .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})",
+ orderCancelledDomainEvent.Order.Id, nameof(OrderStatus.Cancelled), OrderStatus.Cancelled.Id);
var order = await _orderRepository.GetAsync(orderCancelledDomainEvent.Order.Id);
var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString());
diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderGracePeriodConfirmed/OrderStatusChangedToAwaitingValidationDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderGracePeriodConfirmed/OrderStatusChangedToAwaitingValidationDomainEventHandler.cs
index e1c54af4f..edea66895 100644
--- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderGracePeriodConfirmed/OrderStatusChangedToAwaitingValidationDomainEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderGracePeriodConfirmed/OrderStatusChangedToAwaitingValidationDomainEventHandler.cs
@@ -33,9 +33,9 @@
public async Task Handle(OrderStatusChangedToAwaitingValidationDomainEvent orderStatusChangedToAwaitingValidationDomainEvent, CancellationToken cancellationToken)
{
- _logger.CreateLogger(nameof(OrderStatusChangedToAwaitingValidationDomainEvent))
- .LogTrace($"Order with Id: {orderStatusChangedToAwaitingValidationDomainEvent.OrderId} has been successfully updated with " +
- $"a status order id: {OrderStatus.AwaitingValidation.Id}");
+ _logger.CreateLogger()
+ .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})",
+ orderStatusChangedToAwaitingValidationDomainEvent.OrderId, nameof(OrderStatus.AwaitingValidation), OrderStatus.AwaitingValidation.Id);
var order = await _orderRepository.GetAsync(orderStatusChangedToAwaitingValidationDomainEvent.OrderId);
diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderPaid/OrderStatusChangedToPaidDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderPaid/OrderStatusChangedToPaidDomainEventHandler.cs
index d3dca202f..a934a621d 100644
--- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderPaid/OrderStatusChangedToPaidDomainEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderPaid/OrderStatusChangedToPaidDomainEventHandler.cs
@@ -35,9 +35,9 @@
public async Task Handle(OrderStatusChangedToPaidDomainEvent orderStatusChangedToPaidDomainEvent, CancellationToken cancellationToken)
{
- _logger.CreateLogger(nameof(OrderStatusChangedToPaidDomainEventHandler))
- .LogTrace($"Order with Id: {orderStatusChangedToPaidDomainEvent.OrderId} has been successfully updated with " +
- $"a status order id: {OrderStatus.Paid.Id}");
+ _logger.CreateLogger()
+ .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})",
+ orderStatusChangedToPaidDomainEvent.OrderId, nameof(OrderStatus.Paid), OrderStatus.Paid.Id);
var order = await _orderRepository.GetAsync(orderStatusChangedToPaidDomainEvent.OrderId);
var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString());
diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderShipped/OrderShippedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderShipped/OrderShippedDomainEventHandler.cs
index 3be83a2ae..7f4754865 100644
--- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderShipped/OrderShippedDomainEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderShipped/OrderShippedDomainEventHandler.cs
@@ -33,9 +33,9 @@ namespace Ordering.API.Application.DomainEventHandlers.OrderShipped
public async Task Handle(OrderShippedDomainEvent orderShippedDomainEvent, CancellationToken cancellationToken)
{
- _logger.CreateLogger(nameof(OrderShippedDomainEvent))
- .LogTrace($"Order with Id: {orderShippedDomainEvent.Order.Id} has been successfully updated with " +
- $"a status order id: {OrderStatus.Shipped.Id}");
+ _logger.CreateLogger()
+ .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})",
+ orderShippedDomainEvent.Order.Id, nameof(OrderStatus.Shipped), OrderStatus.Shipped.Id);
var order = await _orderRepository.GetAsync(orderShippedDomainEvent.Order.Id);
var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString());
diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs
index 99b2a21a0..e47192dcd 100644
--- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs
@@ -61,7 +61,9 @@ namespace Ordering.API.Application.DomainEventHandlers.OrderStartedEvent
var orderStatusChangedTosubmittedIntegrationEvent = new OrderStatusChangedToSubmittedIntegrationEvent(orderStartedEvent.Order.Id, orderStartedEvent.Order.OrderStatus.Name, buyer.Name);
await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedTosubmittedIntegrationEvent);
- _logger.CreateLogger(nameof(ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler)).LogTrace($"Buyer {buyerUpdated.Id} and related payment method were validated or updated for orderId: {orderStartedEvent.Order.Id}.");
+ _logger.CreateLogger()
+ .LogTrace("Buyer {BuyerId} and related payment method were validated or updated for orderId: {OrderId}.",
+ buyerUpdated.Id, orderStartedEvent.Order.Id);
}
}
}
diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmed/OrderStatusChangedToStockConfirmedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmed/OrderStatusChangedToStockConfirmedDomainEventHandler.cs
index e910964e8..0e9ca4f08 100644
--- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmed/OrderStatusChangedToStockConfirmedDomainEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmed/OrderStatusChangedToStockConfirmedDomainEventHandler.cs
@@ -33,9 +33,9 @@
public async Task Handle(OrderStatusChangedToStockConfirmedDomainEvent orderStatusChangedToStockConfirmedDomainEvent, CancellationToken cancellationToken)
{
- _logger.CreateLogger(nameof(OrderStatusChangedToStockConfirmedDomainEventHandler))
- .LogTrace($"Order with Id: {orderStatusChangedToStockConfirmedDomainEvent.OrderId} has been successfully updated with " +
- $"a status order id: {OrderStatus.StockConfirmed.Id}");
+ _logger.CreateLogger()
+ .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})",
+ orderStatusChangedToStockConfirmedDomainEvent.OrderId, nameof(OrderStatus.StockConfirmed), OrderStatus.StockConfirmed.Id);
var order = await _orderRepository.GetAsync(orderStatusChangedToStockConfirmedDomainEvent.OrderId);
var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString());
diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/GracePeriodConfirmedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/GracePeriodConfirmedIntegrationEventHandler.cs
index f8dcc6edb..2e003b322 100644
--- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/GracePeriodConfirmedIntegrationEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/GracePeriodConfirmedIntegrationEventHandler.cs
@@ -1,8 +1,13 @@
using MediatR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
+using Microsoft.eShopOnContainers.Services.Ordering.API;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
+using Microsoft.Extensions.Logging;
+using Ordering.API.Application.Behaviors;
using Ordering.API.Application.Commands;
using Ordering.API.Application.IntegrationEvents.Events;
+using Serilog.Context;
using System.Threading.Tasks;
namespace Ordering.API.Application.IntegrationEvents.EventHandling
@@ -10,10 +15,14 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling
public class GracePeriodConfirmedIntegrationEventHandler : IIntegrationEventHandler
{
private readonly IMediator _mediator;
+ private readonly ILogger _logger;
- public GracePeriodConfirmedIntegrationEventHandler(IMediator mediator)
+ public GracePeriodConfirmedIntegrationEventHandler(
+ IMediator mediator,
+ ILogger logger)
{
_mediator = mediator;
+ _logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
}
///
@@ -26,8 +35,21 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling
///
public async Task Handle(GracePeriodConfirmedIntegrationEvent @event)
{
- var command = new SetAwaitingValidationOrderStatusCommand(@event.OrderId);
- await _mediator.Send(command);
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
+ var command = new SetAwaitingValidationOrderStatusCommand(@event.OrderId);
+
+ _logger.LogInformation(
+ "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
+ command.GetGenericTypeName(),
+ nameof(command.OrderNumber),
+ command.OrderNumber,
+ command);
+
+ await _mediator.Send(command);
+ }
}
}
}
diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs
index 5f4fc28e1..a123dd891 100644
--- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs
@@ -2,26 +2,48 @@
{
using MediatR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
+ using Microsoft.eShopOnContainers.Services.Ordering.API;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
+ using Microsoft.Extensions.Logging;
+ using Ordering.API.Application.Behaviors;
using Ordering.API.Application.Commands;
using Ordering.API.Application.IntegrationEvents.Events;
- using System;
+ using Serilog.Context;
using System.Threading.Tasks;
+ using System;
public class OrderPaymentFailedIntegrationEventHandler :
IIntegrationEventHandler
{
private readonly IMediator _mediator;
+ private readonly ILogger _logger;
- public OrderPaymentFailedIntegrationEventHandler(IMediator mediator)
+ public OrderPaymentFailedIntegrationEventHandler(
+ IMediator mediator,
+ ILogger logger)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(OrderPaymentFailedIntegrationEvent @event)
{
- var command = new CancelOrderCommand(@event.OrderId);
- await _mediator.Send(command);
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
+ var command = new CancelOrderCommand(@event.OrderId);
+
+ _logger.LogInformation(
+ "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
+ command.GetGenericTypeName(),
+ nameof(command.OrderNumber),
+ command.OrderNumber,
+ command);
+
+ await _mediator.Send(command);
+ }
}
}
}
diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs
index 6c201d77e..9cc69e5e8 100644
--- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs
@@ -2,9 +2,14 @@
{
using MediatR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
+ using Microsoft.eShopOnContainers.Services.Ordering.API;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
+ using Microsoft.Extensions.Logging;
+ using Ordering.API.Application.Behaviors;
using Ordering.API.Application.Commands;
using Ordering.API.Application.IntegrationEvents.Events;
+ using Serilog.Context;
using System;
using System.Threading.Tasks;
@@ -12,16 +17,33 @@
IIntegrationEventHandler
{
private readonly IMediator _mediator;
+ private readonly ILogger _logger;
- public OrderPaymentSuccededIntegrationEventHandler(IMediator mediator)
+ public OrderPaymentSuccededIntegrationEventHandler(
+ IMediator mediator,
+ ILogger logger)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(OrderPaymentSuccededIntegrationEvent @event)
{
- var command = new SetPaidOrderStatusCommand(@event.OrderId);
- await _mediator.Send(command);
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
+ var command = new SetPaidOrderStatusCommand(@event.OrderId);
+
+ _logger.LogInformation(
+ "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
+ command.GetGenericTypeName(),
+ nameof(command.OrderNumber),
+ command.OrderNumber,
+ command);
+
+ await _mediator.Send(command);
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs
index c5561508b..6438b01d0 100644
--- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs
@@ -1,27 +1,49 @@
namespace Ordering.API.Application.IntegrationEvents.EventHandling
{
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using System.Threading.Tasks;
using Events;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using MediatR;
using System;
using Ordering.API.Application.Commands;
+ using Microsoft.Extensions.Logging;
+ using Serilog.Context;
+ using Microsoft.eShopOnContainers.Services.Ordering.API;
+ using Ordering.API.Application.Behaviors;
- public class OrderStockConfirmedIntegrationEventHandler :
+ public class OrderStockConfirmedIntegrationEventHandler :
IIntegrationEventHandler
{
private readonly IMediator _mediator;
+ private readonly ILogger _logger;
- public OrderStockConfirmedIntegrationEventHandler(IMediator mediator)
+ public OrderStockConfirmedIntegrationEventHandler(
+ IMediator mediator,
+ ILogger logger)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(OrderStockConfirmedIntegrationEvent @event)
{
- var command = new SetStockConfirmedOrderStatusCommand(@event.OrderId);
- await _mediator.Send(command);
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
+ var command = new SetStockConfirmedOrderStatusCommand(@event.OrderId);
+
+ _logger.LogInformation(
+ "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
+ command.GetGenericTypeName(),
+ nameof(command.OrderNumber),
+ command.OrderNumber,
+ command);
+
+ await _mediator.Send(command);
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockRejectedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockRejectedIntegrationEventHandler.cs
index af7d98f74..b457211ed 100644
--- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockRejectedIntegrationEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockRejectedIntegrationEventHandler.cs
@@ -1,31 +1,53 @@
namespace Ordering.API.Application.IntegrationEvents.EventHandling
{
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using System.Threading.Tasks;
using Events;
using System.Linq;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using MediatR;
using Ordering.API.Application.Commands;
+ using Microsoft.Extensions.Logging;
+ using Serilog.Context;
+ using Microsoft.eShopOnContainers.Services.Ordering.API;
+ using Ordering.API.Application.Behaviors;
public class OrderStockRejectedIntegrationEventHandler : IIntegrationEventHandler
{
private readonly IMediator _mediator;
+ private readonly ILogger _logger;
- public OrderStockRejectedIntegrationEventHandler(IMediator mediator)
+ public OrderStockRejectedIntegrationEventHandler(
+ IMediator mediator,
+ ILogger logger)
{
_mediator = mediator;
+ _logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
}
public async Task Handle(OrderStockRejectedIntegrationEvent @event)
{
- var orderStockRejectedItems = @event.OrderStockItems
- .FindAll(c => !c.HasStock)
- .Select(c => c.ProductId)
- .ToList();
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
- var command = new SetStockRejectedOrderStatusCommand(@event.OrderId, orderStockRejectedItems);
- await _mediator.Send(command);
+ var orderStockRejectedItems = @event.OrderStockItems
+ .FindAll(c => !c.HasStock)
+ .Select(c => c.ProductId)
+ .ToList();
+
+ var command = new SetStockRejectedOrderStatusCommand(@event.OrderId, orderStockRejectedItems);
+
+ _logger.LogInformation(
+ "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
+ command.GetGenericTypeName(),
+ nameof(command.OrderNumber),
+ command.OrderNumber,
+ command);
+
+ await _mediator.Send(command);
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs
index 33f327c6b..a1452b23c 100644
--- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs
+++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs
@@ -1,52 +1,82 @@
-using System;
-using MediatR;
+using MediatR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
-using System.Threading.Tasks;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
+using Microsoft.eShopOnContainers.Services.Ordering.API;
using Microsoft.Extensions.Logging;
+using Ordering.API.Application.Behaviors;
using Ordering.API.Application.IntegrationEvents.Events;
+using Serilog.Context;
+using System.Threading.Tasks;
+using System;
namespace Ordering.API.Application.IntegrationEvents.EventHandling
{
public class UserCheckoutAcceptedIntegrationEventHandler : IIntegrationEventHandler
{
private readonly IMediator _mediator;
- private readonly ILoggerFactory _logger;
+ private readonly ILogger _logger;
- public UserCheckoutAcceptedIntegrationEventHandler(IMediator mediator,
- ILoggerFactory logger)
+ public UserCheckoutAcceptedIntegrationEventHandler(
+ IMediator mediator,
+ ILogger logger)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
- _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
///
/// Integration event handler which starts the create order process
///
- ///
+ ///
/// Integration event message which is sent by the
/// basket.api once it has successfully process the
/// order items.
///
///
- public async Task Handle(UserCheckoutAcceptedIntegrationEvent eventMsg)
+ public async Task Handle(UserCheckoutAcceptedIntegrationEvent @event)
{
- var result = false;
-
- if (eventMsg.RequestId != Guid.Empty)
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
{
- var createOrderCommand = new CreateOrderCommand(eventMsg.Basket.Items, eventMsg.UserId, eventMsg.UserName, eventMsg.City, eventMsg.Street,
- eventMsg.State, eventMsg.Country, eventMsg.ZipCode,
- eventMsg.CardNumber, eventMsg.CardHolderName, eventMsg.CardExpiration,
- eventMsg.CardSecurityNumber, eventMsg.CardTypeId);
-
- var requestCreateOrder = new IdentifiedCommand(createOrderCommand, eventMsg.RequestId);
- result = await _mediator.Send(requestCreateOrder);
- }
-
- _logger.CreateLogger(nameof(UserCheckoutAcceptedIntegrationEventHandler))
- .LogTrace(result ? $"UserCheckoutAccepted integration event has been received and a create new order process is started with requestId: {eventMsg.RequestId}" :
- $"UserCheckoutAccepted integration event has been received but a new order process has failed with requestId: {eventMsg.RequestId}");
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
+ var result = false;
+
+ if (@event.RequestId != Guid.Empty)
+ {
+ using (LogContext.PushProperty("IdentifiedCommandId", @event.RequestId))
+ {
+ var createOrderCommand = new CreateOrderCommand(@event.Basket.Items, @event.UserId, @event.UserName, @event.City, @event.Street,
+ @event.State, @event.Country, @event.ZipCode,
+ @event.CardNumber, @event.CardHolderName, @event.CardExpiration,
+ @event.CardSecurityNumber, @event.CardTypeId);
+
+ var requestCreateOrder = new IdentifiedCommand(createOrderCommand, @event.RequestId);
+
+ _logger.LogInformation(
+ "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
+ requestCreateOrder.GetGenericTypeName(),
+ nameof(requestCreateOrder.Id),
+ requestCreateOrder.Id,
+ requestCreateOrder);
+
+ result = await _mediator.Send(requestCreateOrder);
+
+ if (result)
+ {
+ _logger.LogInformation("----- CreateOrderCommand suceeded - RequestId: {RequestId}", @event.RequestId);
+ }
+ else
+ {
+ _logger.LogWarning("CreateOrderCommand failed - RequestId: {RequestId}", @event.RequestId);
+ }
+ }
+ }
+ else
+ {
+ _logger.LogWarning("Invalid IntegrationEvent - RequestId is missing - {@IntegrationEvent}", @event);
+ }
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs
index 9c1bd4e1b..9d85e2dd4 100644
--- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs
+++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs
@@ -5,7 +5,9 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities;
+using Microsoft.eShopOnContainers.Services.Ordering.API;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
+using Microsoft.Extensions.Logging;
using System;
using System.Data.Common;
using System.Diagnostics;
@@ -21,39 +23,49 @@ namespace Ordering.API.Application.IntegrationEvents
private readonly OrderingContext _orderingContext;
private readonly IntegrationEventLogContext _eventLogContext;
private readonly IIntegrationEventLogService _eventLogService;
+ private readonly ILogger _logger;
- public OrderingIntegrationEventService(IEventBus eventBus,
+ public OrderingIntegrationEventService(IEventBus eventBus,
OrderingContext orderingContext,
IntegrationEventLogContext eventLogContext,
- Func integrationEventLogServiceFactory)
+ Func integrationEventLogServiceFactory,
+ ILogger logger)
{
_orderingContext = orderingContext ?? throw new ArgumentNullException(nameof(orderingContext));
_eventLogContext = eventLogContext ?? throw new ArgumentNullException(nameof(eventLogContext));
_integrationEventLogServiceFactory = integrationEventLogServiceFactory ?? throw new ArgumentNullException(nameof(integrationEventLogServiceFactory));
_eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
_eventLogService = _integrationEventLogServiceFactory(_orderingContext.Database.GetDbConnection());
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task PublishEventsThroughEventBusAsync()
{
var pendindLogEvents = await _eventLogService.RetrieveEventLogsPendingToPublishAsync();
+
foreach (var logEvt in pendindLogEvents)
{
+ _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", logEvt.EventId, Program.AppName, logEvt.IntegrationEvent);
+
try
{
await _eventLogService.MarkEventAsInProgressAsync(logEvt.EventId);
_eventBus.Publish(logEvt.IntegrationEvent);
await _eventLogService.MarkEventAsPublishedAsync(logEvt.EventId);
}
- catch (Exception)
+ catch (Exception ex)
{
+ _logger.LogError(ex, "ERROR publishing integration event: {IntegrationEventId} from {AppName}", logEvt.EventId, Program.AppName);
+
await _eventLogService.MarkEventAsFailedAsync(logEvt.EventId);
- }
+ }
}
}
public async Task AddAndSaveEventAsync(IntegrationEvent evt)
{
+ _logger.LogInformation("----- Enqueuing integration event {IntegrationEventId} to repository ({@IntegrationEvent})", evt.Id, evt);
+
await _eventLogService.SaveEventAsync(evt, _orderingContext.GetCurrentTransaction.GetDbTransaction());
}
}
diff --git a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs
index e2c711b69..ae35b0377 100644
--- a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs
+++ b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs
@@ -1,9 +1,12 @@
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services;
+using Microsoft.Extensions.Logging;
+using Ordering.API.Application.Behaviors;
using Ordering.API.Application.Commands;
using System;
using System.Collections.Generic;
@@ -20,12 +23,18 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
private readonly IMediator _mediator;
private readonly IOrderQueries _orderQueries;
private readonly IIdentityService _identityService;
+ private readonly ILogger _logger;
- public OrdersController(IMediator mediator, IOrderQueries orderQueries, IIdentityService identityService)
+ public OrdersController(
+ IMediator mediator,
+ IOrderQueries orderQueries,
+ IIdentityService identityService,
+ ILogger logger)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
_orderQueries = orderQueries ?? throw new ArgumentNullException(nameof(orderQueries));
_identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
[Route("cancel")]
@@ -39,6 +48,14 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
if (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty)
{
var requestCancelOrder = new IdentifiedCommand(command, guid);
+
+ _logger.LogInformation(
+ "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
+ requestCancelOrder.GetGenericTypeName(),
+ nameof(requestCancelOrder.Command.OrderNumber),
+ requestCancelOrder.Command.OrderNumber,
+ requestCancelOrder);
+
commandResult = await _mediator.Send(requestCancelOrder);
}
@@ -61,6 +78,14 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
if (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty)
{
var requestShipOrder = new IdentifiedCommand(command, guid);
+
+ _logger.LogInformation(
+ "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
+ requestShipOrder.GetGenericTypeName(),
+ nameof(requestShipOrder.Command.OrderNumber),
+ requestShipOrder.Command.OrderNumber,
+ requestShipOrder);
+
commandResult = await _mediator.Send(requestShipOrder);
}
@@ -114,6 +139,13 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
[HttpPost]
public async Task> CreateOrderDraftFromBasketDataAsync([FromBody] CreateOrderDraftCommand createOrderDraftCommand)
{
+ _logger.LogInformation(
+ "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
+ createOrderDraftCommand.GetGenericTypeName(),
+ nameof(createOrderDraftCommand.BuyerId),
+ createOrderDraftCommand.BuyerId,
+ createOrderDraftCommand);
+
return await _mediator.Send(createOrderDraftCommand);
}
}
diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs b/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs
index 99a413f9f..67275a587 100644
--- a/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs
+++ b/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs
@@ -7,7 +7,6 @@ using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Ordering.API.Application.Behaviors;
using Ordering.API.Application.DomainEventHandlers.OrderStartedEvent;
using Ordering.API.Application.Validations;
-using Ordering.API.Infrastructure.Behaviors;
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.AutofacModules
{
diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs b/src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs
index 975fb9a6a..7dcbe194e 100644
--- a/src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs
+++ b/src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs
@@ -75,7 +75,7 @@
}
catch (Exception ex)
{
- log.LogError(ex.Message);
+ log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message);
return GetPredefinedCardTypes();
}
@@ -83,7 +83,7 @@
return File.ReadAllLines(csvFileCardTypes)
.Skip(1) // skip header column
.SelectTry(x => CreateCardType(x, ref id))
- .OnCaughtException(ex => { log.LogError(ex.Message); return null; })
+ .OnCaughtException(ex => { log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; })
.Where(x => x != null);
}
@@ -119,7 +119,7 @@
}
catch (Exception ex)
{
- log.LogError(ex.Message);
+ log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message);
return GetPredefinedOrderStatus();
}
@@ -127,7 +127,7 @@
return File.ReadAllLines(csvFileOrderStatus)
.Skip(1) // skip header row
.SelectTry(x => CreateOrderStatus(x, ref id))
- .OnCaughtException(ex => { log.LogError(ex.Message); return null; })
+ .OnCaughtException(ex => { log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; })
.Where(x => x != null);
}
@@ -183,7 +183,7 @@
sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
onRetry: (exception, timeSpan, retry, ctx) =>
{
- logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
+ logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", prefix, exception.GetType().Name, exception.Message, retry, retries);
}
);
}
diff --git a/src/Services/Ordering/Ordering.API/Ordering.API.csproj b/src/Services/Ordering/Ordering.API/Ordering.API.csproj
index f69c6f673..f7443f9a4 100644
--- a/src/Services/Ordering/Ordering.API/Ordering.API.csproj
+++ b/src/Services/Ordering/Ordering.API/Ordering.API.csproj
@@ -5,6 +5,7 @@
aspnet-Ordering.API-20161122013547
$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
..\..\..\..\docker-compose.dcproj
+ 7.1
@@ -29,13 +30,12 @@
-
-
-
-
+
+
-
+
+
@@ -45,10 +45,13 @@
+
+
+
-
+
diff --git a/src/Services/Ordering/Ordering.API/Program.cs b/src/Services/Ordering/Ordering.API/Program.cs
index 8db59598c..8fc18c8bb 100644
--- a/src/Services/Ordering/Ordering.API/Program.cs
+++ b/src/Services/Ordering/Ordering.API/Program.cs
@@ -15,10 +15,22 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API
{
public class Program
{
- public static void Main(string[] args)
+ public static readonly string Namespace = typeof(Program).Namespace;
+ public static readonly string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1);
+
+ public static int Main(string[] args)
{
- BuildWebHost(args)
- .MigrateDbContext((context, services) =>
+ var configuration = GetConfiguration();
+
+ Log.Logger = CreateSerilogLogger(configuration);
+
+ try
+ {
+ Log.Information("Configuring web host ({ApplicationContext})...", AppName);
+ var host = BuildWebHost(configuration, args);
+
+ Log.Information("Applying migrations ({ApplicationContext})...", AppName);
+ host.MigrateDbContext((context, services) =>
{
var env = services.GetService();
var settings = services.GetService>();
@@ -28,47 +40,66 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API
.SeedAsync(context, env, settings, logger)
.Wait();
})
- .MigrateDbContext((_,__)=>{})
- .Run();
+ .MigrateDbContext((_, __) => { });
+
+ Log.Information("Starting web host ({ApplicationContext})...", AppName);
+ host.Run();
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
}
- public static IWebHost BuildWebHost(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
+ private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
+ WebHost.CreateDefaultBuilder(args)
+ .CaptureStartupErrors(false)
.UseStartup()
+ .UseApplicationInsights()
.UseContentRoot(Directory.GetCurrentDirectory())
- .ConfigureAppConfiguration((builderContext, config) =>
- {
- var builtConfig = config.Build();
+ .UseConfiguration(configuration)
+ .UseSerilog()
+ .Build();
- var configurationBuilder = new ConfigurationBuilder();
-
- if (Convert.ToBoolean(builtConfig["UseVault"]))
- {
- configurationBuilder.AddAzureKeyVault(
- $"https://{builtConfig["Vault:Name"]}.vault.azure.net/",
- builtConfig["Vault:ClientId"],
- builtConfig["Vault:ClientSecret"]);
- }
+ private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
+ {
+ var seqServerUrl = configuration["Serilog:SeqServerUrl"];
- configurationBuilder.AddEnvironmentVariables();
+ return new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("ApplicationContext", AppName)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
+ .ReadFrom.Configuration(configuration)
+ .CreateLogger();
+ }
- config.AddConfiguration(configurationBuilder.Build());
- })
- .ConfigureLogging((hostingContext, builder) =>
- {
- builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
- builder.AddConsole();
- builder.AddDebug();
- builder.AddAzureWebAppDiagnostics();
- })
- .UseApplicationInsights()
- .UseSerilog((builderContext, config) =>
- {
- config
- .MinimumLevel.Information()
- .Enrich.FromLogContext()
- .WriteTo.Console();
- })
- .Build();
+ private static IConfiguration GetConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddEnvironmentVariables();
+
+ var config = builder.Build();
+
+ if (config.GetValue("UseVault", false))
+ {
+ builder.AddAzureKeyVault(
+ $"https://{config["Vault:Name"]}.vault.azure.net/",
+ config["Vault:ClientId"],
+ config["Vault:ClientSecret"]);
+ }
+
+ return builder.Build();
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs
index 03e9b1d7f..cd34f98dd 100644
--- a/src/Services/Ordering/Ordering.API/Startup.cs
+++ b/src/Services/Ordering/Ordering.API/Startup.cs
@@ -74,14 +74,15 @@
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
- loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
+ //loggerFactory.AddAzureWebAppDiagnostics();
+ //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
- loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
+ loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase);
app.UsePathBase(pathBase);
- }
+ }
app.UseCors("CorsPolicy");
@@ -121,10 +122,9 @@
eventBus.Subscribe>();
eventBus.Subscribe>();
eventBus.Subscribe>();
- eventBus.Subscribe>();
+ eventBus.Subscribe>();
}
-
protected virtual void ConfigureAuth(IApplicationBuilder app)
{
if (Configuration.GetValue("UseLoadTest"))
@@ -167,7 +167,7 @@
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddControllersAsServices(); //Injecting Controllers themselves thru DI
- //For further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
+ //For further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
services.AddCors(options =>
{
diff --git a/src/Services/Ordering/Ordering.API/appsettings.json b/src/Services/Ordering/Ordering.API/appsettings.json
index 96dd74630..64b24a354 100644
--- a/src/Services/Ordering/Ordering.API/appsettings.json
+++ b/src/Services/Ordering/Ordering.API/appsettings.json
@@ -2,12 +2,15 @@
"ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;",
"IdentityUrl": "http://localhost:5105",
"UseCustomizationData": false,
- "Logging": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Trace",
- "System": "Information",
- "Microsoft": "Information"
+ "Serilog": {
+ "SeqServerUrl": null,
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "Microsoft": "Warning",
+ "Microsoft.eShopOnContainers": "Information",
+ "System": "Warning"
+ }
}
},
"AzureServiceBusEnabled": false,
diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj b/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj
index b4ee75da7..b889f5453 100644
--- a/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj
+++ b/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj
@@ -15,16 +15,19 @@
-
-
+
+
-
+
+
+
+
diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Program.cs b/src/Services/Ordering/Ordering.BackgroundTasks/Program.cs
index 3c78efa10..8f8cf41e1 100644
--- a/src/Services/Ordering/Ordering.BackgroundTasks/Program.cs
+++ b/src/Services/Ordering/Ordering.BackgroundTasks/Program.cs
@@ -1,33 +1,75 @@
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Serilog;
+using System;
+using System.IO;
namespace Ordering.BackgroundTasks
{
public class Program
{
- public static void Main(string[] args)
+ public static readonly string Namespace = typeof(Program).Namespace;
+ public static readonly string AppName = Namespace;
+
+ public static int Main(string[] args)
{
- BuildWebHost(args).Run();
+ var configuration = GetConfiguration();
+
+ Log.Logger = CreateSerilogLogger(configuration);
+
+ try
+ {
+ Log.Information("Configuring web host ({ApplicationContext})...", AppName);
+ var host = BuildWebHost(configuration, args);
+
+ Log.Information("Starting web host ({ApplicationContext})...", AppName);
+ host.Run();
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
}
- public static IWebHost BuildWebHost(string[] args) =>
+ private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
WebHost.CreateDefaultBuilder(args)
- .UseStartup()
- .ConfigureLogging((hostingContext, builder) =>
- {
- builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
- builder.AddDebug();
- builder.AddConsole();
- })
- .UseSerilog((builderContext, config) =>
- {
- config
- .MinimumLevel.Information()
- .Enrich.FromLogContext()
- .WriteTo.Console();
- })
+ .CaptureStartupErrors(false)
+ .UseStartup()
+ .UseConfiguration(configuration)
+ .UseSerilog()
.Build();
+
+ private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
+ {
+ var seqServerUrl = configuration["Serilog:SeqServerUrl"];
+
+ return new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("ApplicationContext", AppName)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
+ .ReadFrom.Configuration(configuration)
+ .CreateLogger();
+ }
+
+ private static IConfiguration GetConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddEnvironmentVariables();
+
+ return builder.Build();
+ }
}
}
diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Tasks/GracePeriodManagerTask.cs b/src/Services/Ordering/Ordering.BackgroundTasks/Tasks/GracePeriodManagerTask.cs
index fbf92f978..328fb95c4 100644
--- a/src/Services/Ordering/Ordering.BackgroundTasks/Tasks/GracePeriodManagerTask.cs
+++ b/src/Services/Ordering/Ordering.BackgroundTasks/Tasks/GracePeriodManagerTask.cs
@@ -20,9 +20,10 @@ namespace Ordering.BackgroundTasks.Tasks
private readonly BackgroundTaskSettings _settings;
private readonly IEventBus _eventBus;
- public GracePeriodManagerService(IOptions settings,
- IEventBus eventBus,
- ILogger logger)
+ public GracePeriodManagerService(
+ IOptions settings,
+ IEventBus eventBus,
+ ILogger logger)
{
_settings = settings?.Value ?? throw new ArgumentNullException(nameof(settings));
_eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
@@ -32,27 +33,27 @@ namespace Ordering.BackgroundTasks.Tasks
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
- _logger.LogDebug($"GracePeriodManagerService is starting.");
+ _logger.LogDebug("GracePeriodManagerService is starting.");
- stoppingToken.Register(() => _logger.LogDebug($"#1 GracePeriodManagerService background task is stopping."));
+ stoppingToken.Register(() => _logger.LogDebug("#1 GracePeriodManagerService background task is stopping."));
while (!stoppingToken.IsCancellationRequested)
{
- _logger.LogDebug($"GracePeriodManagerService background task is doing background work.");
+ _logger.LogDebug("GracePeriodManagerService background task is doing background work.");
CheckConfirmedGracePeriodOrders();
await Task.Delay(_settings.CheckUpdateTime, stoppingToken);
}
- _logger.LogDebug($"GracePeriodManagerService background task is stopping.");
+ _logger.LogDebug("GracePeriodManagerService background task is stopping.");
await Task.CompletedTask;
}
private void CheckConfirmedGracePeriodOrders()
{
- _logger.LogDebug($"Checking confirmed grace period orders");
+ _logger.LogDebug("Checking confirmed grace period orders");
var orderIds = GetConfirmedGracePeriodOrders();
@@ -60,6 +61,8 @@ namespace Ordering.BackgroundTasks.Tasks
{
var confirmGracePeriodEvent = new GracePeriodConfirmedIntegrationEvent(orderId);
+ _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", confirmGracePeriodEvent.Id, Program.AppName, confirmGracePeriodEvent);
+
_eventBus.Publish(confirmGracePeriodEvent);
}
}
@@ -81,7 +84,7 @@ namespace Ordering.BackgroundTasks.Tasks
}
catch (SqlException exception)
{
- _logger.LogCritical($"FATAL ERROR: Database connections could not be opened: {exception.Message}");
+ _logger.LogCritical(exception, "FATAL ERROR: Database connections could not be opened: {Message}", exception.Message);
}
}
diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json b/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json
index fd26645ab..3697c53a5 100644
--- a/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json
+++ b/src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json
@@ -1,15 +1,13 @@
{
"ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;",
- "Logging": {
- "IncludeScopes": false,
- "Debug": {
- "LogLevel": {
- "Default": "Debug"
- }
- },
- "Console": {
- "LogLevel": {
- "Default": "Debug"
+ "Serilog": {
+ "SeqServerUrl": null,
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "Microsoft": "Warning",
+ "Microsoft.eShopOnContainers": "Information",
+ "System": "Warning"
}
}
},
diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs
index 2fd52917e..1269fd259 100644
--- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs
+++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs
@@ -32,8 +32,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
int cardTypeId, string alias, string cardNumber,
string securityNumber, string cardHolderName, DateTime expiration, int orderId)
{
- var existingPayment = _paymentMethods.Where(p => p.IsEqualTo(cardTypeId, cardNumber, expiration))
- .SingleOrDefault();
+ var existingPayment = _paymentMethods
+ .SingleOrDefault(p => p.IsEqualTo(cardTypeId, cardNumber, expiration));
if (existingPayment != null)
{
@@ -41,16 +41,14 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
return existingPayment;
}
- else
- {
- var payment = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration);
- _paymentMethods.Add(payment);
+ var payment = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration);
- AddDomainEvent(new BuyerAndPaymentMethodVerifiedDomainEvent(this, payment, orderId));
+ _paymentMethods.Add(payment);
- return payment;
- }
+ AddDomainEvent(new BuyerAndPaymentMethodVerifiedDomainEvent(this, payment, orderId));
+
+ return payment;
}
}
}
diff --git a/src/Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj b/src/Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj
index 394e7a1a7..05ede2017 100644
--- a/src/Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj
+++ b/src/Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarios.cs b/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarios.cs
index b544ea221..9b46e1841 100644
--- a/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarios.cs
+++ b/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarios.cs
@@ -3,7 +3,7 @@ using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
-using WebMVC.Models;
+using WebMVC.Services.ModelDTOs;
using Xunit;
namespace Ordering.FunctionalTests
diff --git a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/BuyerEntityTYpeConfiguration.cs b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/BuyerEntityTypeConfiguration.cs
similarity index 100%
rename from src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/BuyerEntityTYpeConfiguration.cs
rename to src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/BuyerEntityTypeConfiguration.cs
diff --git a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs
index c0e37fb14..f668d5cc8 100644
--- a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs
+++ b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs
@@ -27,10 +27,12 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
private readonly IMediator _mediator;
private IDbContextTransaction _currentTransaction;
- private OrderingContext(DbContextOptions options) : base (options) { }
+ private OrderingContext(DbContextOptions options) : base(options) { }
public IDbContextTransaction GetCurrentTransaction => _currentTransaction;
+ public bool HasActiveTransaction => _currentTransaction != null;
+
public OrderingContext(DbContextOptions options, IMediator mediator) : base(options)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
@@ -47,7 +49,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
modelBuilder.ApplyConfiguration(new OrderItemEntityTypeConfiguration());
modelBuilder.ApplyConfiguration(new CardTypeEntityTypeConfiguration());
modelBuilder.ApplyConfiguration(new OrderStatusEntityTypeConfiguration());
- modelBuilder.ApplyConfiguration(new BuyerEntityTypeConfiguration());
+ modelBuilder.ApplyConfiguration(new BuyerEntityTypeConfiguration());
}
public async Task SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken))
@@ -67,17 +69,24 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
return true;
}
- public async Task BeginTransactionAsync()
+ public async Task BeginTransactionAsync()
{
- _currentTransaction = _currentTransaction ?? await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted);
+ if (_currentTransaction != null) return null;
+
+ _currentTransaction = await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted);
+
+ return _currentTransaction;
}
- public async Task CommitTransactionAsync()
+ public async Task CommitTransactionAsync(IDbContextTransaction transaction)
{
+ if (transaction == null) throw new ArgumentNullException(nameof(transaction));
+ if (transaction != _currentTransaction) throw new InvalidOperationException($"Transaction {transaction.TransactionId} is not current");
+
try
{
await SaveChangesAsync();
- _currentTransaction?.Commit();
+ transaction.Commit();
}
catch
{
@@ -118,7 +127,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
var optionsBuilder = new DbContextOptionsBuilder()
.UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.OrderingDb;Integrated Security=true");
- return new OrderingContext(optionsBuilder.Options,new NoMediator());
+ return new OrderingContext(optionsBuilder.Options, new NoMediator());
}
class NoMediator : IMediator
diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs
new file mode 100644
index 000000000..0e2665232
--- /dev/null
+++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs
@@ -0,0 +1,38 @@
+using Microsoft.AspNetCore.SignalR;
+using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+using Microsoft.Extensions.Logging;
+using Serilog.Context;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Ordering.SignalrHub.IntegrationEvents
+{
+ public class OrderStatusChangedToAwaitingValidationIntegrationEventHandler : IIntegrationEventHandler
+ {
+ private readonly IHubContext _hubContext;
+ private readonly ILogger _logger;
+
+ public OrderStatusChangedToAwaitingValidationIntegrationEventHandler(
+ IHubContext hubContext,
+ ILogger logger)
+ {
+ _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ }
+
+
+ public async Task Handle(OrderStatusChangedToAwaitingValidationIntegrationEvent @event)
+ {
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
+ await _hubContext.Clients
+ .Group(@event.BuyerName)
+ .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
+ }
+ }
+ }
+}
diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToCancelledIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToCancelledIntegrationEventHandler.cs
index 171eb81f7..6257bb237 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToCancelledIntegrationEventHandler.cs
+++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToCancelledIntegrationEventHandler.cs
@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+using Microsoft.Extensions.Logging;
using Ordering.SignalrHub.IntegrationEvents.Events;
+using Serilog.Context;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -11,18 +13,27 @@ namespace Ordering.SignalrHub.IntegrationEvents.EventHandling
public class OrderStatusChangedToCancelledIntegrationEventHandler : IIntegrationEventHandler
{
private readonly IHubContext _hubContext;
+ private readonly ILogger _logger;
- public OrderStatusChangedToCancelledIntegrationEventHandler(IHubContext hubContext)
+ public OrderStatusChangedToCancelledIntegrationEventHandler(
+ IHubContext hubContext,
+ ILogger logger)
{
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(OrderStatusChangedToCancelledIntegrationEvent @event)
{
- await _hubContext.Clients
- .Group(@event.BuyerName)
- .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
+ await _hubContext.Clients
+ .Group(@event.BuyerName)
+ .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs
index 4b0eb780c..836e02d3c 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs
+++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs
@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+using Microsoft.Extensions.Logging;
using Ordering.SignalrHub.IntegrationEvents.Events;
+using Serilog.Context;
using System;
using System.Threading.Tasks;
@@ -9,18 +11,27 @@ namespace Ordering.SignalrHub.IntegrationEvents.EventHandling
public class OrderStatusChangedToPaidIntegrationEventHandler : IIntegrationEventHandler
{
private readonly IHubContext _hubContext;
+ private readonly ILogger _logger;
- public OrderStatusChangedToPaidIntegrationEventHandler(IHubContext hubContext)
+ public OrderStatusChangedToPaidIntegrationEventHandler(
+ IHubContext hubContext,
+ ILogger logger)
{
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(OrderStatusChangedToPaidIntegrationEvent @event)
{
- await _hubContext.Clients
- .Group(@event.BuyerName)
- .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
+ await _hubContext.Clients
+ .Group(@event.BuyerName)
+ .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
+ }
}
}
}
diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToShippedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToShippedIntegrationEventHandler.cs
index 7a19a0659..5b08d08b4 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToShippedIntegrationEventHandler.cs
+++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToShippedIntegrationEventHandler.cs
@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+using Microsoft.Extensions.Logging;
using Ordering.SignalrHub.IntegrationEvents.Events;
+using Serilog.Context;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -11,18 +13,27 @@ namespace Ordering.SignalrHub.IntegrationEvents.EventHandling
public class OrderStatusChangedToShippedIntegrationEventHandler : IIntegrationEventHandler
{
private readonly IHubContext _hubContext;
+ private readonly ILogger _logger;
- public OrderStatusChangedToShippedIntegrationEventHandler(IHubContext hubContext)
+ public OrderStatusChangedToShippedIntegrationEventHandler(
+ IHubContext hubContext,
+ ILogger logger)
{
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(OrderStatusChangedToShippedIntegrationEvent @event)
{
- await _hubContext.Clients
- .Group(@event.BuyerName)
- .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
+ await _hubContext.Clients
+ .Group(@event.BuyerName)
+ .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
+ }
}
}
}
diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs
index 324ea6259..348627716 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs
+++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs
@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+using Microsoft.Extensions.Logging;
using Ordering.SignalrHub.IntegrationEvents.Events;
+using Serilog.Context;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -12,18 +14,27 @@ namespace Ordering.SignalrHub.IntegrationEvents.EventHandling
IIntegrationEventHandler
{
private readonly IHubContext _hubContext;
+ private readonly ILogger _logger;
- public OrderStatusChangedToStockConfirmedIntegrationEventHandler(IHubContext hubContext)
+ public OrderStatusChangedToStockConfirmedIntegrationEventHandler(
+ IHubContext hubContext,
+ ILogger logger)
{
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(OrderStatusChangedToStockConfirmedIntegrationEvent @event)
{
- await _hubContext.Clients
- .Group(@event.BuyerName)
- .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
+ await _hubContext.Clients
+ .Group(@event.BuyerName)
+ .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
+ }
}
}
}
diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToSubmittedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToSubmittedIntegrationEventHandler.cs
index 5fac4c1da..422bc4a7a 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToSubmittedIntegrationEventHandler.cs
+++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToSubmittedIntegrationEventHandler.cs
@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
+using Microsoft.Extensions.Logging;
using Ordering.SignalrHub.IntegrationEvents.Events;
+using Serilog.Context;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -12,18 +14,27 @@ namespace Ordering.SignalrHub.IntegrationEvents.EventHandling
IIntegrationEventHandler
{
private readonly IHubContext _hubContext;
+ private readonly ILogger _logger;
- public OrderStatusChangedToSubmittedIntegrationEventHandler(IHubContext hubContext)
+ public OrderStatusChangedToSubmittedIntegrationEventHandler(
+ IHubContext hubContext,
+ ILogger logger)
{
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(OrderStatusChangedToSubmittedIntegrationEvent @event)
{
- await _hubContext.Clients
- .Group(@event.BuyerName)
- .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
+
+ await _hubContext.Clients
+ .Group(@event.BuyerName)
+ .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/orderStatusChangedToAwaitingValidationIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/orderStatusChangedToAwaitingValidationIntegrationEventHandler.cs
deleted file mode 100644
index 6c2733b77..000000000
--- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/orderStatusChangedToAwaitingValidationIntegrationEventHandler.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using Microsoft.AspNetCore.SignalR;
-using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace Ordering.SignalrHub.IntegrationEvents
-{
- public class OrderStatusChangedToAwaitingValidationIntegrationEventHandler : IIntegrationEventHandler
- {
- private readonly IHubContext _hubContext;
-
- public OrderStatusChangedToAwaitingValidationIntegrationEventHandler(IHubContext hubContext)
- {
- _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
- }
-
-
- public async Task Handle(OrderStatusChangedToAwaitingValidationIntegrationEvent @event)
- {
- await _hubContext.Clients
- .Group(@event.BuyerName)
- .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus });
- }
- }
-}
diff --git a/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs b/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs
index 5fd6f3eb9..943198980 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs
+++ b/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs
@@ -19,7 +19,7 @@ namespace Ordering.SignalrHub
public override async Task OnDisconnectedAsync(Exception ex)
{
- await Groups.AddToGroupAsync(Context.ConnectionId, Context.User.Identity.Name);
+ await Groups.RemoveFromGroupAsync(Context.ConnectionId, Context.User.Identity.Name);
await base.OnDisconnectedAsync(ex);
}
}
diff --git a/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj b/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj
index 1bd2334b4..08df863ce 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj
+++ b/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj
@@ -1,4 +1,4 @@
-
+
netcoreapp2.2
@@ -10,9 +10,9 @@
-
+
-
+
@@ -20,14 +20,16 @@
-
-
+
+
-
+
+
+
diff --git a/src/Services/Ordering/Ordering.SignalrHub/Program.cs b/src/Services/Ordering/Ordering.SignalrHub/Program.cs
index 3fe2e8c24..fdb3f5f3a 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/Program.cs
+++ b/src/Services/Ordering/Ordering.SignalrHub/Program.cs
@@ -13,28 +13,67 @@ namespace Ordering.SignalrHub
{
public class Program
{
- public static void Main(string[] args)
+ public static readonly string Namespace = typeof(Program).Namespace;
+ public static readonly string AppName = Namespace;
+
+ public static int Main(string[] args)
{
- BuildWebHost(args).Run();
+ var configuration = GetConfiguration();
+
+ Log.Logger = CreateSerilogLogger(configuration);
+
+ try
+ {
+ Log.Information("Configuring web host ({ApplicationContext})...", AppName);
+ var host = BuildWebHost(configuration, args);
+
+ Log.Information("Starting web host ({ApplicationContext})...", AppName);
+ host.Run();
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
}
- public static IWebHost BuildWebHost(string[] args) =>
+ private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
WebHost.CreateDefaultBuilder(args)
+ .CaptureStartupErrors(false)
.UseStartup()
- .ConfigureLogging((hostingContext, builder) =>
- {
- builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
- builder.AddConsole();
- builder.AddDebug();
- builder.AddAzureWebAppDiagnostics();
- })
- .UseSerilog((builderContext, config) =>
- {
- config
- .MinimumLevel.Information()
- .Enrich.FromLogContext()
- .WriteTo.Console();
- })
+ .UseConfiguration(configuration)
+ .UseSerilog()
.Build();
+
+ private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
+ {
+ var seqServerUrl = configuration["Serilog:SeqServerUrl"];
+
+ return new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("ApplicationContext", AppName)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
+ .ReadFrom.Configuration(configuration)
+ .CreateLogger();
+ }
+
+ private static IConfiguration GetConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddEnvironmentVariables();
+
+ return builder.Build();
+ }
+
}
}
diff --git a/src/Services/Ordering/Ordering.SignalrHub/Startup.cs b/src/Services/Ordering/Ordering.SignalrHub/Startup.cs
index 20f8b739b..e8bb7ecd1 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/Startup.cs
+++ b/src/Services/Ordering/Ordering.SignalrHub/Startup.cs
@@ -30,6 +30,8 @@ namespace Ordering.SignalrHub
Configuration = configuration;
}
+ public IConfiguration Configuration { get; }
+
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public IServiceProvider ConfigureServices(IServiceCollection services)
@@ -115,17 +117,18 @@ namespace Ordering.SignalrHub
return new AutofacServiceProvider(container.Build());
}
- public IConfiguration Configuration { get; }
-
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
- loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
+ //loggerFactory.AddConsole(Configuration.GetSection("Logging"));
+ //loggerFactory.AddDebug();
+ //loggerFactory.AddAzureWebAppDiagnostics();
+ //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
- loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
+ loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase);
app.UsePathBase(pathBase);
}
@@ -156,13 +159,13 @@ namespace Ordering.SignalrHub
private void ConfigureEventBus(IApplicationBuilder app)
{
var eventBus = app.ApplicationServices.GetRequiredService();
-
+
eventBus.Subscribe();
eventBus.Subscribe();
eventBus.Subscribe();
eventBus.Subscribe();
eventBus.Subscribe();
- eventBus.Subscribe();
+ eventBus.Subscribe();
}
private void ConfigureAuthService(IServiceCollection services)
diff --git a/src/Services/Ordering/Ordering.SignalrHub/appsettings.json b/src/Services/Ordering/Ordering.SignalrHub/appsettings.json
index ab02fda0f..bd752de48 100644
--- a/src/Services/Ordering/Ordering.SignalrHub/appsettings.json
+++ b/src/Services/Ordering/Ordering.SignalrHub/appsettings.json
@@ -1,11 +1,14 @@
{
"IdentityUrl": "http://localhost:5105",
- "Logging": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Trace",
- "System": "Information",
- "Microsoft": "Information"
+ "Serilog": {
+ "SeqServerUrl": null,
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "Microsoft": "Warning",
+ "Microsoft.eShopOnContainers": "Information",
+ "System": "Warning"
+ }
}
},
"AzureServiceBusEnabled": false,
diff --git a/src/Services/Ordering/Ordering.UnitTests/Application/IdentifiedCommandHandlerTest.cs b/src/Services/Ordering/Ordering.UnitTests/Application/IdentifiedCommandHandlerTest.cs
index e0f861017..95bc4cc81 100644
--- a/src/Services/Ordering/Ordering.UnitTests/Application/IdentifiedCommandHandlerTest.cs
+++ b/src/Services/Ordering/Ordering.UnitTests/Application/IdentifiedCommandHandlerTest.cs
@@ -8,6 +8,7 @@ namespace UnitTest.Ordering.Application
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
+ using Microsoft.Extensions.Logging;
using Moq;
using System.Collections;
using System.Collections.Generic;
@@ -17,11 +18,13 @@ namespace UnitTest.Ordering.Application
{
private readonly Mock _requestManager;
private readonly Mock _mediator;
+ private readonly Mock>> _loggerMock;
public IdentifiedCommandHandlerTest()
{
_requestManager = new Mock();
_mediator = new Mock();
+ _loggerMock = new Mock>>();
}
[Fact]
@@ -38,7 +41,7 @@ namespace UnitTest.Ordering.Application
.Returns(Task.FromResult(true));
//Act
- var handler = new IdentifiedCommandHandler(_mediator.Object, _requestManager.Object);
+ var handler = new IdentifiedCommandHandler(_mediator.Object, _requestManager.Object, _loggerMock.Object);
var cltToken = new System.Threading.CancellationToken();
var result = await handler.Handle(fakeOrderCmd, cltToken);
@@ -61,7 +64,7 @@ namespace UnitTest.Ordering.Application
.Returns(Task.FromResult(true));
//Act
- var handler = new IdentifiedCommandHandler(_mediator.Object, _requestManager.Object);
+ var handler = new IdentifiedCommandHandler(_mediator.Object, _requestManager.Object, _loggerMock.Object);
var cltToken = new System.Threading.CancellationToken();
var result = await handler.Handle(fakeOrderCmd, cltToken);
diff --git a/src/Services/Ordering/Ordering.UnitTests/Application/NewOrderCommandHandlerTest.cs b/src/Services/Ordering/Ordering.UnitTests/Application/NewOrderCommandHandlerTest.cs
index 80a0deb25..77fede857 100644
--- a/src/Services/Ordering/Ordering.UnitTests/Application/NewOrderCommandHandlerTest.cs
+++ b/src/Services/Ordering/Ordering.UnitTests/Application/NewOrderCommandHandlerTest.cs
@@ -13,6 +13,7 @@ namespace UnitTest.Ordering.Application
using global::Ordering.API.Application.IntegrationEvents;
using global::Ordering.API.Application.Models;
using MediatR;
+ using Microsoft.Extensions.Logging;
using System.Collections;
using System.Collections.Generic;
using Xunit;
@@ -50,8 +51,9 @@ namespace UnitTest.Ordering.Application
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
+ var LoggerMock = new Mock>();
//Act
- var handler = new CreateOrderCommandHandler(_mediator.Object, _orderingIntegrationEventService.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
+ var handler = new CreateOrderCommandHandler(_mediator.Object, _orderingIntegrationEventService.Object, _orderRepositoryMock.Object, _identityServiceMock.Object, LoggerMock.Object);
var cltToken = new System.Threading.CancellationToken();
var result = await handler.Handle(fakeOrderCmd, cltToken);
diff --git a/src/Services/Ordering/Ordering.UnitTests/Application/OrdersWebApiTest.cs b/src/Services/Ordering/Ordering.UnitTests/Application/OrdersWebApiTest.cs
index c5b8a1764..b19a764e9 100644
--- a/src/Services/Ordering/Ordering.UnitTests/Application/OrdersWebApiTest.cs
+++ b/src/Services/Ordering/Ordering.UnitTests/Application/OrdersWebApiTest.cs
@@ -4,6 +4,7 @@ using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries;
using Microsoft.eShopOnContainers.Services.Ordering.API.Controllers;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services;
+using Microsoft.Extensions.Logging;
using Moq;
using Ordering.API.Application.Commands;
using System;
@@ -19,12 +20,14 @@ namespace UnitTest.Ordering.Application
private readonly Mock _mediatorMock;
private readonly Mock _orderQueriesMock;
private readonly Mock _identityServiceMock;
+ private readonly Mock> _loggerMock;
public OrdersWebApiTest()
{
_mediatorMock = new Mock();
_orderQueriesMock = new Mock();
_identityServiceMock = new Mock();
+ _loggerMock = new Mock>();
}
[Fact]
@@ -35,7 +38,7 @@ namespace UnitTest.Ordering.Application
.Returns(Task.FromResult(true));
//Act
- var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object);
+ var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object);
var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), Guid.NewGuid().ToString()) as OkResult;
//Assert
@@ -51,7 +54,7 @@ namespace UnitTest.Ordering.Application
.Returns(Task.FromResult(true));
//Act
- var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object);
+ var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object);
var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), String.Empty) as BadRequestResult;
//Assert
@@ -66,7 +69,7 @@ namespace UnitTest.Ordering.Application
.Returns(Task.FromResult(true));
//Act
- var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object);
+ var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object);
var actionResult = await orderController.ShipOrderAsync(new ShipOrderCommand(1), Guid.NewGuid().ToString()) as OkResult;
//Assert
@@ -82,7 +85,7 @@ namespace UnitTest.Ordering.Application
.Returns(Task.FromResult(true));
//Act
- var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object);
+ var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object);
var actionResult = await orderController.ShipOrderAsync(new ShipOrderCommand(1), String.Empty) as BadRequestResult;
//Assert
@@ -102,7 +105,7 @@ namespace UnitTest.Ordering.Application
.Returns(Task.FromResult(fakeDynamicResult));
//Act
- var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object);
+ var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object);
var actionResult = await orderController.GetOrdersAsync();
//Assert
@@ -119,7 +122,7 @@ namespace UnitTest.Ordering.Application
.Returns(Task.FromResult(fakeDynamicResult));
//Act
- var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object);
+ var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object);
var actionResult = await orderController.GetOrderAsync(fakeOrderId) as OkObjectResult;
//Assert
@@ -135,7 +138,7 @@ namespace UnitTest.Ordering.Application
.Returns(Task.FromResult(fakeDynamicResult));
//Act
- var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object);
+ var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object);
var actionResult = await orderController.GetCardTypesAsync();
//Assert
diff --git a/src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj b/src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj
index ac61a4ec3..0a35885a8 100644
--- a/src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj
+++ b/src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj
@@ -7,7 +7,7 @@
-
+
all
diff --git a/src/Services/Payment/Payment.API/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs b/src/Services/Payment/Payment.API/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs
index c70a32093..b26d64d40 100644
--- a/src/Services/Payment/Payment.API/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs
+++ b/src/Services/Payment/Payment.API/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs
@@ -2,45 +2,58 @@
{
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
+ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Payment.API.IntegrationEvents.Events;
+ using Serilog.Context;
using System.Threading.Tasks;
- public class OrderStatusChangedToStockConfirmedIntegrationEventHandler :
+ public class OrderStatusChangedToStockConfirmedIntegrationEventHandler :
IIntegrationEventHandler
{
private readonly IEventBus _eventBus;
private readonly PaymentSettings _settings;
+ private readonly ILogger _logger;
- public OrderStatusChangedToStockConfirmedIntegrationEventHandler(IEventBus eventBus,
- IOptionsSnapshot settings)
+ public OrderStatusChangedToStockConfirmedIntegrationEventHandler(
+ IEventBus eventBus,
+ IOptionsSnapshot settings,
+ ILogger logger)
{
_eventBus = eventBus;
_settings = settings.Value;
- }
+ _logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
+ }
public async Task Handle(OrderStatusChangedToStockConfirmedIntegrationEvent @event)
{
- IntegrationEvent orderPaymentIntegrationEvent;
+ using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
+ {
+ _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
- //Business feature comment:
- // When OrderStatusChangedToStockConfirmed Integration Event is handled.
- // Here we're simulating that we'd be performing the payment against any payment gateway
- // Instead of a real payment we just take the env. var to simulate the payment
- // The payment can be successful or it can fail
+ IntegrationEvent orderPaymentIntegrationEvent;
- if (_settings.PaymentSucceded)
- {
- orderPaymentIntegrationEvent = new OrderPaymentSuccededIntegrationEvent(@event.OrderId);
- }
- else
- {
- orderPaymentIntegrationEvent = new OrderPaymentFailedIntegrationEvent(@event.OrderId);
- }
+ //Business feature comment:
+ // When OrderStatusChangedToStockConfirmed Integration Event is handled.
+ // Here we're simulating that we'd be performing the payment against any payment gateway
+ // Instead of a real payment we just take the env. var to simulate the payment
+ // The payment can be successful or it can fail
+
+ if (_settings.PaymentSucceded)
+ {
+ orderPaymentIntegrationEvent = new OrderPaymentSuccededIntegrationEvent(@event.OrderId);
+ }
+ else
+ {
+ orderPaymentIntegrationEvent = new OrderPaymentFailedIntegrationEvent(@event.OrderId);
+ }
- _eventBus.Publish(orderPaymentIntegrationEvent);
+ _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", orderPaymentIntegrationEvent.Id, Program.AppName, orderPaymentIntegrationEvent);
- await Task.CompletedTask;
+ _eventBus.Publish(orderPaymentIntegrationEvent);
+
+ await Task.CompletedTask;
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Services/Payment/Payment.API/Payment.API.csproj b/src/Services/Payment/Payment.API/Payment.API.csproj
index a91fc6797..0ff842f74 100644
--- a/src/Services/Payment/Payment.API/Payment.API.csproj
+++ b/src/Services/Payment/Payment.API/Payment.API.csproj
@@ -7,20 +7,23 @@
+
+
-
-
-
-
+
+
+
-
-
+
+
+
+
diff --git a/src/Services/Payment/Payment.API/Program.cs b/src/Services/Payment/Payment.API/Program.cs
index 7a589e8a4..9b0aded5c 100644
--- a/src/Services/Payment/Payment.API/Program.cs
+++ b/src/Services/Payment/Payment.API/Program.cs
@@ -4,40 +4,85 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Serilog;
+using System;
using System.IO;
namespace Payment.API
{
public class Program
{
- public static void Main(string[] args)
+ public static readonly string Namespace = typeof(Program).Namespace;
+ public static readonly string AppName = Namespace;
+
+ public static int Main(string[] args)
{
- BuildWebHost(args).Run();
+ var configuration = GetConfiguration();
+
+ Log.Logger = CreateSerilogLogger(configuration);
+
+ try
+ {
+ Log.Information("Configuring web host ({ApplicationContext})...", AppName);
+ var host = BuildWebHost(configuration, args);
+
+ Log.Information("Starting web host ({ApplicationContext})...", AppName);
+ host.Run();
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
}
- public static IWebHost BuildWebHost(string[] args) =>
+ private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
WebHost.CreateDefaultBuilder(args)
- .UseContentRoot(Directory.GetCurrentDirectory())
+ .CaptureStartupErrors(false)
.UseStartup()
- .ConfigureAppConfiguration((builderContext, config) =>
- {
- config.AddEnvironmentVariables();
- })
- .ConfigureLogging((hostingContext, builder) =>
- {
- builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
- builder.AddConsole();
- builder.AddDebug();
- builder.AddAzureWebAppDiagnostics();
- })
.UseApplicationInsights()
- .UseSerilog((builderContext, config) =>
- {
- config
- .MinimumLevel.Information()
- .Enrich.FromLogContext()
- .WriteTo.Console();
- })
+ .UseContentRoot(Directory.GetCurrentDirectory())
+ .UseConfiguration(configuration)
+ .UseSerilog()
.Build();
+
+ private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
+ {
+ var seqServerUrl = configuration["Serilog:SeqServerUrl"];
+
+ return new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("ApplicationContext", AppName)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
+ .ReadFrom.Configuration(configuration)
+ .CreateLogger();
+ }
+
+ private static IConfiguration GetConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddEnvironmentVariables();
+
+ var config = builder.Build();
+
+ if (config.GetValue("UseVault", false))
+ {
+ builder.AddAzureKeyVault(
+ $"https://{config["Vault:Name"]}.vault.azure.net/",
+ config["Vault:ClientId"],
+ config["Vault:ClientSecret"]);
+ }
+
+ return builder.Build();
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/Services/Payment/Payment.API/Startup.cs b/src/Services/Payment/Payment.API/Startup.cs
index 62a3b2321..4d5010868 100644
--- a/src/Services/Payment/Payment.API/Startup.cs
+++ b/src/Services/Payment/Payment.API/Startup.cs
@@ -91,7 +91,8 @@ namespace Payment.API
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
- loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
+ //loggerFactory.AddAzureWebAppDiagnostics();
+ //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
diff --git a/src/Services/Payment/Payment.API/appsettings.json b/src/Services/Payment/Payment.API/appsettings.json
index acc9a2be0..bf6157648 100644
--- a/src/Services/Payment/Payment.API/appsettings.json
+++ b/src/Services/Payment/Payment.API/appsettings.json
@@ -1,8 +1,13 @@
{
- "Logging": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Warning"
+ "Serilog": {
+ "SeqServerUrl": null,
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "Microsoft": "Warning",
+ "Microsoft.eShopOnContainers": "Information",
+ "System": "Warning"
+ }
}
},
"PaymentSucceded": true,
diff --git a/src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj b/src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj
index f65e0c441..4329edaec 100644
--- a/src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj
+++ b/src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj
@@ -9,9 +9,8 @@
-
-
-
+
+
diff --git a/src/Web/WebMVC/Controllers/AccountController.cs b/src/Web/WebMVC/Controllers/AccountController.cs
index cf22de133..0f214b8ea 100644
--- a/src/Web/WebMVC/Controllers/AccountController.cs
+++ b/src/Web/WebMVC/Controllers/AccountController.cs
@@ -16,7 +16,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
public async Task SignIn(string returnUrl)
{
var user = User as ClaimsPrincipal;
-
+
var token = await HttpContext.GetTokenAsync("access_token");
if (token != null)
@@ -33,11 +33,11 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
-
+
// "Catalog" because UrlHelper doesn't support nameof() for controllers
// https://github.com/aspnet/Mvc/issues/5853
var homeUrl = Url.Action(nameof(CatalogController.Index), "Catalog");
- return new SignOutResult(OpenIdConnectDefaults.AuthenticationScheme,
+ return new SignOutResult(OpenIdConnectDefaults.AuthenticationScheme,
new AspNetCore.Authentication.AuthenticationProperties { RedirectUri = homeUrl });
}
}
diff --git a/src/Web/WebMVC/Controllers/CampaignsController.cs b/src/Web/WebMVC/Controllers/CampaignsController.cs
index 058012d26..d26e60f94 100644
--- a/src/Web/WebMVC/Controllers/CampaignsController.cs
+++ b/src/Web/WebMVC/Controllers/CampaignsController.cs
@@ -2,7 +2,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
{
using AspNetCore.Authorization;
using AspNetCore.Mvc;
- using global::WebMVC.Models;
+ using global::WebMVC.Services.ModelDTOs;
using global::WebMVC.Services;
using global::WebMVC.ViewModels;
using Microsoft.Extensions.Options;
diff --git a/src/Web/WebMVC/Controllers/OrderManagementController.cs b/src/Web/WebMVC/Controllers/OrderManagementController.cs
index abd0b21ab..7d61b0221 100644
--- a/src/Web/WebMVC/Controllers/OrderManagementController.cs
+++ b/src/Web/WebMVC/Controllers/OrderManagementController.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
-using WebMVC.Models;
+using WebMVC.Services.ModelDTOs;
using Microsoft.eShopOnContainers.WebMVC.Services;
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
using Microsoft.AspNetCore.Authorization;
diff --git a/src/Web/WebMVC/Infrastructure/HttpClientRequestIdDelegatingHandler.cs b/src/Web/WebMVC/Infrastructure/HttpClientRequestIdDelegatingHandler.cs
index 17e4591a1..37bea4d30 100644
--- a/src/Web/WebMVC/Infrastructure/HttpClientRequestIdDelegatingHandler.cs
+++ b/src/Web/WebMVC/Infrastructure/HttpClientRequestIdDelegatingHandler.cs
@@ -17,7 +17,10 @@ namespace WebMVC.Infrastructure
{
if (request.Method == HttpMethod.Post || request.Method == HttpMethod.Put)
{
- request.Headers.Add("x-requestid", Guid.NewGuid().ToString());
+ if (!request.Headers.Contains("x-requestid"))
+ {
+ request.Headers.Add("x-requestid", Guid.NewGuid().ToString());
+ }
}
return await base.SendAsync(request, cancellationToken);
diff --git a/src/Web/WebMVC/Infrastructure/WebContextSeed.cs b/src/Web/WebMVC/Infrastructure/WebContextSeed.cs
index 65063e34f..c34730ac1 100644
--- a/src/Web/WebMVC/Infrastructure/WebContextSeed.cs
+++ b/src/Web/WebMVC/Infrastructure/WebContextSeed.cs
@@ -15,7 +15,7 @@ namespace WebMVC.Infrastructure
{
public static void Seed(IApplicationBuilder applicationBuilder, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
- var log = loggerFactory.CreateLogger("WebMVC seed");
+ var log = loggerFactory.CreateLogger();
var settings = (AppSettings)applicationBuilder
.ApplicationServices.GetRequiredService>().Value;
@@ -39,7 +39,7 @@ namespace WebMVC.Infrastructure
string overrideCssFile = Path.Combine(contentRootPath, "Setup", "override.css");
if (!File.Exists(overrideCssFile))
{
- log.LogError($" override css file '{overrideCssFile}' does not exists.");
+ log.LogError("Override css file '{FileName}' does not exists.", overrideCssFile);
return;
}
@@ -48,7 +48,7 @@ namespace WebMVC.Infrastructure
}
catch (Exception ex)
{
- log.LogError($"Exception in method GetPreconfiguredCSS WebMVC. Exception Message={ex.Message}");
+ log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message);
}
}
@@ -59,7 +59,7 @@ namespace WebMVC.Infrastructure
string imagesZipFile = Path.Combine(contentRootPath, "Setup", "images.zip");
if (!File.Exists(imagesZipFile))
{
- log.LogError($" zip file '{imagesZipFile}' does not exists.");
+ log.LogError("Zip file '{ZipFileName}' does not exists.", imagesZipFile);
return;
}
@@ -81,14 +81,14 @@ namespace WebMVC.Infrastructure
}
else
{
- log.LogWarning($"Skip file '{entry.Name}' in zipfile '{imagesZipFile}'");
+ log.LogWarning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile);
}
}
}
}
catch ( Exception ex )
{
- log.LogError($"Exception in method GetPreconfiguredImages WebMVC. Exception Message={ex.Message}");
+ log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message);
}
}
diff --git a/src/Web/WebMVC/Program.cs b/src/Web/WebMVC/Program.cs
index 5000e0422..c329237ce 100644
--- a/src/Web/WebMVC/Program.cs
+++ b/src/Web/WebMVC/Program.cs
@@ -3,40 +3,74 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Serilog;
+using System;
using System.IO;
namespace Microsoft.eShopOnContainers.WebMVC
{
public class Program
{
- public static void Main(string[] args)
+ public static readonly string Namespace = typeof(Program).Namespace;
+ public static readonly string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1);
+
+ public static int Main(string[] args)
{
- BuildWebHost(args).Run();
+ var configuration = GetConfiguration();
+
+ Log.Logger = CreateSerilogLogger(configuration);
+
+ try
+ {
+ Log.Information("Configuring web host ({ApplicationContext})...", AppName);
+ var host = BuildWebHost(configuration, args);
+
+ Log.Information("Starting web host ({ApplicationContext})...", AppName);
+ host.Run();
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
}
- public static IWebHost BuildWebHost(string[] args) =>
+ private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
WebHost.CreateDefaultBuilder(args)
- .UseContentRoot(Directory.GetCurrentDirectory())
+ .CaptureStartupErrors(false)
.UseStartup()
- .ConfigureAppConfiguration((builderContext, config) =>
- {
- config.AddEnvironmentVariables();
- })
- .ConfigureLogging((hostingContext, builder) =>
- {
- builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
- builder.AddConsole();
- builder.AddDebug();
- builder.AddAzureWebAppDiagnostics();
- })
.UseApplicationInsights()
- .UseSerilog((builderContext, config) =>
- {
- config
- .MinimumLevel.Information()
- .Enrich.FromLogContext()
- .WriteTo.Console();
- })
+ .UseConfiguration(configuration)
+ .UseSerilog()
.Build();
+
+ private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
+ {
+ var seqServerUrl = configuration["Serilog:SeqServerUrl"];
+
+ return new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("ApplicationContext", AppName)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
+ .ReadFrom.Configuration(configuration)
+ .CreateLogger();
+ }
+
+ private static IConfiguration GetConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddEnvironmentVariables();
+
+ return builder.Build();
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/Web/WebMVC/Services/BasketService.cs b/src/Web/WebMVC/Services/BasketService.cs
index 41a0fd207..2ee26eff6 100644
--- a/src/Web/WebMVC/Services/BasketService.cs
+++ b/src/Web/WebMVC/Services/BasketService.cs
@@ -6,7 +6,7 @@ using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using WebMVC.Infrastructure;
-using WebMVC.Models;
+using WebMVC.Services.ModelDTOs;
namespace Microsoft.eShopOnContainers.WebMVC.Services
{
diff --git a/src/Web/WebMVC/Services/IBasketService.cs b/src/Web/WebMVC/Services/IBasketService.cs
index cfbea5ff0..8c096bfaf 100644
--- a/src/Web/WebMVC/Services/IBasketService.cs
+++ b/src/Web/WebMVC/Services/IBasketService.cs
@@ -3,7 +3,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using WebMVC.Models;
+using WebMVC.Services.ModelDTOs;
namespace Microsoft.eShopOnContainers.WebMVC.Services
{
diff --git a/src/Web/WebMVC/Services/ILocationService.cs b/src/Web/WebMVC/Services/ILocationService.cs
index ac2295e10..d5f7b7224 100644
--- a/src/Web/WebMVC/Services/ILocationService.cs
+++ b/src/Web/WebMVC/Services/ILocationService.cs
@@ -1,5 +1,5 @@
using System.Threading.Tasks;
-using WebMVC.Models;
+using WebMVC.Services.ModelDTOs;
namespace WebMVC.Services
{
diff --git a/src/Web/WebMVC/Services/IOrderingService.cs b/src/Web/WebMVC/Services/IOrderingService.cs
index 1de2c631c..480ea4119 100644
--- a/src/Web/WebMVC/Services/IOrderingService.cs
+++ b/src/Web/WebMVC/Services/IOrderingService.cs
@@ -3,7 +3,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using WebMVC.Models;
+using WebMVC.Services.ModelDTOs;
namespace Microsoft.eShopOnContainers.WebMVC.Services
{
diff --git a/src/Web/WebMVC/Services/LocationService.cs b/src/Web/WebMVC/Services/LocationService.cs
index 3e58ef125..8d81cbd22 100644
--- a/src/Web/WebMVC/Services/LocationService.cs
+++ b/src/Web/WebMVC/Services/LocationService.cs
@@ -6,7 +6,7 @@ using Newtonsoft.Json;
using System.Net.Http;
using System.Threading.Tasks;
using WebMVC.Infrastructure;
-using WebMVC.Models;
+using WebMVC.Services.ModelDTOs;
namespace WebMVC.Services
{
diff --git a/src/Web/WebMVC/Models/BasketDTO.cs b/src/Web/WebMVC/Services/ModelDTOs/BasketDTO.cs
similarity index 95%
rename from src/Web/WebMVC/Models/BasketDTO.cs
rename to src/Web/WebMVC/Services/ModelDTOs/BasketDTO.cs
index 4609c8533..130a729f5 100644
--- a/src/Web/WebMVC/Models/BasketDTO.cs
+++ b/src/Web/WebMVC/Services/ModelDTOs/BasketDTO.cs
@@ -1,7 +1,7 @@
using System;
using System.ComponentModel.DataAnnotations;
-namespace WebMVC.Models
+namespace WebMVC.Services.ModelDTOs
{
public class BasketDTO
{
diff --git a/src/Web/WebMVC/Models/LocationDTO.cs b/src/Web/WebMVC/Services/ModelDTOs/LocationDTO.cs
similarity index 86%
rename from src/Web/WebMVC/Models/LocationDTO.cs
rename to src/Web/WebMVC/Services/ModelDTOs/LocationDTO.cs
index 88169c421..40c9f07a8 100644
--- a/src/Web/WebMVC/Models/LocationDTO.cs
+++ b/src/Web/WebMVC/Services/ModelDTOs/LocationDTO.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-namespace WebMVC.Models
+namespace WebMVC.Services.ModelDTOs
{
public class LocationDTO
{
diff --git a/src/Web/WebMVC/Models/OrderDTO.cs b/src/Web/WebMVC/Services/ModelDTOs/OrderDTO.cs
similarity index 82%
rename from src/Web/WebMVC/Models/OrderDTO.cs
rename to src/Web/WebMVC/Services/ModelDTOs/OrderDTO.cs
index 13646ea38..5f925a8ee 100644
--- a/src/Web/WebMVC/Models/OrderDTO.cs
+++ b/src/Web/WebMVC/Services/ModelDTOs/OrderDTO.cs
@@ -1,7 +1,7 @@
using System;
using System.ComponentModel.DataAnnotations;
-namespace WebMVC.Models
+namespace WebMVC.Services.ModelDTOs
{
public class OrderDTO
{
diff --git a/src/Web/WebMVC/Models/OrderProcessAction.cs b/src/Web/WebMVC/Services/ModelDTOs/OrderProcessAction.cs
similarity index 93%
rename from src/Web/WebMVC/Models/OrderProcessAction.cs
rename to src/Web/WebMVC/Services/ModelDTOs/OrderProcessAction.cs
index bd746bb36..c1309d59b 100644
--- a/src/Web/WebMVC/Models/OrderProcessAction.cs
+++ b/src/Web/WebMVC/Services/ModelDTOs/OrderProcessAction.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-namespace WebMVC.Models
+namespace WebMVC.Services.ModelDTOs
{
public class OrderProcessAction
{
diff --git a/src/Web/WebMVC/Services/OrderingService.cs b/src/Web/WebMVC/Services/OrderingService.cs
index e3d24422f..489946db5 100644
--- a/src/Web/WebMVC/Services/OrderingService.cs
+++ b/src/Web/WebMVC/Services/OrderingService.cs
@@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using WebMVC.Infrastructure;
-using WebMVC.Models;
+using WebMVC.Services.ModelDTOs;
namespace Microsoft.eShopOnContainers.WebMVC.Services
{
diff --git a/src/Web/WebMVC/Startup.cs b/src/Web/WebMVC/Startup.cs
index 0ec33bc8c..6156bdf09 100644
--- a/src/Web/WebMVC/Startup.cs
+++ b/src/Web/WebMVC/Startup.cs
@@ -52,7 +52,8 @@ namespace Microsoft.eShopOnContainers.WebMVC
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
- loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
+ //loggerFactory.AddAzureWebAppDiagnostics();
+ //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
app.UseHealthChecks("/hc", new HealthCheckOptions()
{
@@ -73,7 +74,7 @@ namespace Microsoft.eShopOnContainers.WebMVC
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
- loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
+ loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{PathBase}'", pathBase);
app.UsePathBase(pathBase);
}
@@ -92,8 +93,6 @@ namespace Microsoft.eShopOnContainers.WebMVC
app.UseAuthentication();
- var log = loggerFactory.CreateLogger("identity");
-
WebContextSeed.Seed(app, env, loggerFactory);
app.UseHttpsRedirection();
diff --git a/src/Web/WebMVC/ViewModels/Order.cs b/src/Web/WebMVC/ViewModels/Order.cs
index 28dbe9968..2beaf43b1 100644
--- a/src/Web/WebMVC/ViewModels/Order.cs
+++ b/src/Web/WebMVC/ViewModels/Order.cs
@@ -7,7 +7,7 @@ using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
-using WebMVC.Models;
+using WebMVC.Services.ModelDTOs;
namespace Microsoft.eShopOnContainers.WebMVC.ViewModels
{
diff --git a/src/Web/WebMVC/WebMVC.csproj b/src/Web/WebMVC/WebMVC.csproj
index 0dc03e164..317a0140a 100644
--- a/src/Web/WebMVC/WebMVC.csproj
+++ b/src/Web/WebMVC/WebMVC.csproj
@@ -20,10 +20,10 @@
-
+
-
-
+
+
@@ -37,7 +37,10 @@
+
+
+
diff --git a/src/Web/WebMVC/appsettings.json b/src/Web/WebMVC/appsettings.json
index 161e247a6..591964725 100644
--- a/src/Web/WebMVC/appsettings.json
+++ b/src/Web/WebMVC/appsettings.json
@@ -11,12 +11,15 @@
"UseLoadTest": false,
"ActivateCampaignDetailFunction": "False",
"UseCustomizationData": false,
- "Logging": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Trace",
- "System": "Information",
- "Microsoft": "Information"
+ "Serilog": {
+ "SeqServerUrl": null,
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "Microsoft": "Warning",
+ "Microsoft.eShopOnContainers": "Information",
+ "System": "Warning"
+ }
}
},
"ApplicationInsights": {
diff --git a/src/Web/WebMonolithic/eShopWeb/Infrastructure/CatalogContextSeed.cs b/src/Web/WebMonolithic/eShopWeb/Infrastructure/CatalogContextSeed.cs
index c67baebc3..e95fdd8f4 100644
--- a/src/Web/WebMonolithic/eShopWeb/Infrastructure/CatalogContextSeed.cs
+++ b/src/Web/WebMonolithic/eShopWeb/Infrastructure/CatalogContextSeed.cs
@@ -51,7 +51,7 @@
{
retryForAvaiability++;
var log = loggerFactory.CreateLogger("catalog seed");
- log.LogError(ex.Message);
+ log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message);
await SeedAsync(applicationBuilder, loggerFactory, retryForAvaiability);
}
}
diff --git a/src/Web/WebSPA/Server/Infrastructure/WebContextSeed.cs b/src/Web/WebSPA/Server/Infrastructure/WebContextSeed.cs
index a2fde45b3..74de66b5c 100644
--- a/src/Web/WebSPA/Server/Infrastructure/WebContextSeed.cs
+++ b/src/Web/WebSPA/Server/Infrastructure/WebContextSeed.cs
@@ -15,7 +15,7 @@ namespace WebSPA.Infrastructure
{
public static void Seed(IApplicationBuilder applicationBuilder, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
- var log = loggerFactory.CreateLogger("WebSPA seed");
+ var log = loggerFactory.CreateLogger();
var settings = (AppSettings)applicationBuilder
.ApplicationServices.GetRequiredService>().Value;
@@ -37,7 +37,7 @@ namespace WebSPA.Infrastructure
string imagesZipFile = Path.Combine(contentRootPath, "Setup", "images.zip");
if (!File.Exists(imagesZipFile))
{
- log.LogError($" zip file '{imagesZipFile}' does not exists.");
+ log.LogError("Zip file '{ZipFileName}' does not exists.", imagesZipFile);
return;
}
@@ -59,14 +59,14 @@ namespace WebSPA.Infrastructure
}
else
{
- log.LogWarning($"Skip file '{entry.Name}' in zipfile '{imagesZipFile}'");
+ log.LogWarning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile);
}
}
}
}
catch (Exception ex)
{
- log.LogError($"Exception in method GetPreconfiguredImages WebSPA. Exception Message={ex.Message}");
+ log.LogError(ex, "ERROR in GetPreconfiguredImages: {Message}", ex.Message);
}
}
}
diff --git a/src/Web/WebSPA/Startup.cs b/src/Web/WebSPA/Startup.cs
index 5cfeb98fc..7a418c432 100644
--- a/src/Web/WebSPA/Startup.cs
+++ b/src/Web/WebSPA/Startup.cs
@@ -116,7 +116,7 @@ namespace eShopConContainers.WebSPA
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
- loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
+ loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase);
app.UsePathBase(pathBase);
}
diff --git a/src/Web/WebSPA/WebSPA.csproj b/src/Web/WebSPA/WebSPA.csproj
index 2d554810b..3afb1a033 100644
--- a/src/Web/WebSPA/WebSPA.csproj
+++ b/src/Web/WebSPA/WebSPA.csproj
@@ -86,16 +86,16 @@
-
-
-
+
+
+
-
+
diff --git a/src/Web/WebStatus/Program.cs b/src/Web/WebStatus/Program.cs
index 11a4f02b9..d2de3ceae 100644
--- a/src/Web/WebStatus/Program.cs
+++ b/src/Web/WebStatus/Program.cs
@@ -3,36 +3,85 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Serilog;
+using System;
using System.IO;
namespace WebStatus
{
public class Program
{
- public static void Main(string[] args)
+ public static readonly string Namespace = typeof(Program).Namespace;
+ public static readonly string AppName = Namespace;
+
+ public static int Main(string[] args)
{
- BuildWebHost(args).Run();
+ var configuration = GetConfiguration();
+
+ Log.Logger = CreateSerilogLogger(configuration);
+
+ try
+ {
+ Log.Information("Configuring web host ({ApplicationContext})...", AppName);
+ var host = BuildWebHost(configuration, args);
+
+ Log.Information("Starting web host ({ApplicationContext})...", AppName);
+ host.Run();
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
}
- public static IWebHost BuildWebHost(string[] args) =>
+ private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
WebHost.CreateDefaultBuilder(args)
- .UseContentRoot(Directory.GetCurrentDirectory())
- .UseStartup()
- .ConfigureLogging((hostingContext, builder) =>
- {
- builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
- builder.AddConsole();
- builder.AddDebug();
- builder.AddAzureWebAppDiagnostics();
- })
+ .CaptureStartupErrors(false)
+ .UseStartup()
.UseApplicationInsights()
- .UseSerilog((builderContext, config) =>
- {
- config
- .MinimumLevel.Information()
- .Enrich.FromLogContext()
- .WriteTo.Console();
- })
+ .UseContentRoot(Directory.GetCurrentDirectory())
+ .UseConfiguration(configuration)
+ .UseSerilog()
.Build();
+
+ private static Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
+ {
+ var seqServerUrl = configuration["Serilog:SeqServerUrl"];
+
+ return new LoggerConfiguration()
+ .MinimumLevel.Verbose()
+ .Enrich.WithProperty("ApplicationContext", AppName)
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
+ .ReadFrom.Configuration(configuration)
+ .CreateLogger();
+ }
+
+ private static IConfiguration GetConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddEnvironmentVariables();
+
+ var config = builder.Build();
+
+ if (config.GetValue("UseVault", false))
+ {
+ builder.AddAzureKeyVault(
+ $"https://{config["Vault:Name"]}.vault.azure.net/",
+ config["Vault:ClientId"],
+ config["Vault:ClientSecret"]);
+ }
+
+ return builder.Build();
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/Web/WebStatus/Startup.cs b/src/Web/WebStatus/Startup.cs
index fbfa5e74c..5b35ee84f 100644
--- a/src/Web/WebStatus/Startup.cs
+++ b/src/Web/WebStatus/Startup.cs
@@ -39,7 +39,8 @@ namespace WebStatus
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
- loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
+ //loggerFactory.AddAzureWebAppDiagnostics();
+ //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
if (env.IsDevelopment())
{
diff --git a/src/Web/WebStatus/WebStatus.csproj b/src/Web/WebStatus/WebStatus.csproj
index f2b912dbb..60c6f00e2 100644
--- a/src/Web/WebStatus/WebStatus.csproj
+++ b/src/Web/WebStatus/WebStatus.csproj
@@ -11,20 +11,23 @@
-
+
-
-
-
+
+
+
+
-
-
+
+
+
+
diff --git a/src/Web/WebStatus/appsettings.json b/src/Web/WebStatus/appsettings.json
index 6f486424c..9ff359423 100644
--- a/src/Web/WebStatus/appsettings.json
+++ b/src/Web/WebStatus/appsettings.json
@@ -80,5 +80,16 @@
],
"EvaluationTimeOnSeconds": 10,
"MinimumSecondsBetweenFailureNotifications": 60
+ },
+ "Serilog": {
+ "SeqServerUrl": null,
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "Microsoft": "Warning",
+ "Microsoft.eShopOnContainers": "Information",
+ "System": "Warning"
+ }
+ }
}
}
diff --git a/src/Web/WebhookClient/WebhookClient.csproj b/src/Web/WebhookClient/WebhookClient.csproj
index 895cbac54..989606184 100644
--- a/src/Web/WebhookClient/WebhookClient.csproj
+++ b/src/Web/WebhookClient/WebhookClient.csproj
@@ -11,7 +11,6 @@
-
diff --git a/test/ServicesTests/Application.FunctionalTests/Application.FunctionalTests.csproj b/test/ServicesTests/Application.FunctionalTests/Application.FunctionalTests.csproj
index 47a467300..c7ae7fd95 100644
--- a/test/ServicesTests/Application.FunctionalTests/Application.FunctionalTests.csproj
+++ b/test/ServicesTests/Application.FunctionalTests/Application.FunctionalTests.csproj
@@ -67,7 +67,7 @@
-
+
diff --git a/test/ServicesTests/Application.FunctionalTests/Services/Ordering/OrderingScenarios.cs b/test/ServicesTests/Application.FunctionalTests/Services/Ordering/OrderingScenarios.cs
index b09526bf3..179717583 100644
--- a/test/ServicesTests/Application.FunctionalTests/Services/Ordering/OrderingScenarios.cs
+++ b/test/ServicesTests/Application.FunctionalTests/Services/Ordering/OrderingScenarios.cs
@@ -9,7 +9,7 @@ using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
-using WebMVC.Models;
+using WebMVC.Services.ModelDTOs;
using Xunit;
namespace FunctionalTests.Services.Ordering
| | |