diff --git a/Directory.Packages.props b/Directory.Packages.props
index 6fa73c7c..16c6d821 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -8,44 +8,44 @@
-
-
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
@@ -63,28 +63,28 @@
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
-
+
+
@@ -103,4 +103,4 @@
-
+
\ No newline at end of file
diff --git a/TransactionProcessor.BusinessLogic.Tests/Manager/TransactionProcessorManagerTests.cs b/TransactionProcessor.BusinessLogic.Tests/Manager/TransactionProcessorManagerTests.cs
index 34e15bd5..06f5c8d7 100644
--- a/TransactionProcessor.BusinessLogic.Tests/Manager/TransactionProcessorManagerTests.cs
+++ b/TransactionProcessor.BusinessLogic.Tests/Manager/TransactionProcessorManagerTests.cs
@@ -34,7 +34,7 @@ public class TransactionProcessorManagerTests
public TransactionProcessorManagerTests()
{
- Logger.Initialise(Microsoft.Extensions.Logging.Abstractions.NullLogger.Instance);
+ Logger.Initialise(new NullLogger());
this.TransactionProcessorReadModelRepository = new ITransactionProcessorReadModelRepositoryImposter();
StringSerialiser.Initialise(new Shared.Serialisation.SystemTextJsonSerializer(new System.Text.Json.JsonSerializerOptions()));
this.AggregateService = new IAggregateServiceImposter();
diff --git a/TransactionProcessor.BusinessLogic/Common/Extensions.cs b/TransactionProcessor.BusinessLogic/Common/Extensions.cs
index 6dba322e..c318043a 100644
--- a/TransactionProcessor.BusinessLogic/Common/Extensions.cs
+++ b/TransactionProcessor.BusinessLogic/Common/Extensions.cs
@@ -30,27 +30,22 @@ public static async Task> GetToken(TokenResponse currentTo
// Get a token to talk to the estate service
String clientId = ConfigurationReader.GetValue("AppSettings", "ClientId");
String clientSecret = ConfigurationReader.GetValue("AppSettings", "ClientSecret");
- Logger.LogDebug($"Client Id is {clientId}");
- Logger.LogDebug($"Client Secret is {clientSecret}");
-
+
if (currentToken == null)
{
Result tokenResult= await securityServiceClient.GetToken(clientId, clientSecret, cancellationToken);
if (tokenResult.IsFailed)
return ResultHelpers.CreateFailure(tokenResult);
TokenResponse token =tokenResult.Data;
- Logger.LogDebug($"Token is {token.AccessToken}");
return Result.Success(token);
}
if (currentToken.Expires.UtcDateTime.Subtract(DateTime.UtcNow) < TimeSpan.FromMinutes(2))
{
- Logger.LogDebug($"Token is about to expire at {currentToken.Expires.DateTime:O}");
Result tokenResult = await securityServiceClient.GetToken(clientId, clientSecret, cancellationToken);
if (tokenResult.IsFailed)
return ResultHelpers.CreateFailure(tokenResult);
TokenResponse token = tokenResult.Data;
- Logger.LogDebug($"Token is {token.AccessToken}");
return Result.Success(token);
}
diff --git a/TransactionProcessor.BusinessLogic/OperatorInterfaces/AgencyBanking/AgencyBankingProxy.cs b/TransactionProcessor.BusinessLogic/OperatorInterfaces/AgencyBanking/AgencyBankingProxy.cs
index c2ee141e..7a5ce771 100644
--- a/TransactionProcessor.BusinessLogic/OperatorInterfaces/AgencyBanking/AgencyBankingProxy.cs
+++ b/TransactionProcessor.BusinessLogic/OperatorInterfaces/AgencyBanking/AgencyBankingProxy.cs
@@ -42,14 +42,15 @@ public async Task> ProcessSaleMessage(Guid transactionI
Dictionary additionalTransactionMetadata,
CancellationToken cancellationToken) {
try {
- Logger.LogInformation($"AgencyBanking sale request received. TransactionId=[{transactionId}], OperatorId=[{operatorId}], MerchantId=[{merchant.MerchantId}], TransactionDateTime=[{transactionDateTime:o}], TransactionReference=[{transactionReference}]");
+ Logger.LogInformation("AgencyBanking sale request received. TransactionId=[{TransactionId}], OperatorId=[{OperatorId}], MerchantId=[{MerchantId}], TransactionDateTime=[{TransactionDateTime}], TransactionReference=[{TransactionReference}]",
+ transactionId, operatorId, merchant.MerchantId, transactionDateTime.ToString("O"), transactionReference);
// Check the meta data for the message type
String messageType = additionalTransactionMetadata.ExtractFieldFromMetadata("AgencyBankingMessageType");
if (String.IsNullOrEmpty(messageType))
{
- Logger.LogWarning($"AgencyBanking sale request rejected. TransactionId=[{transactionId}] missing AgencyBankingMessageType");
+ Logger.LogWarning("AgencyBanking sale request rejected. TransactionId=[{TransactionId}] missing AgencyBankingMessageType", transactionId);
return Result.Invalid("AgencyBankingMessageType - Message Type is a required field for this transaction type");
}
@@ -58,11 +59,11 @@ public async Task> ProcessSaleMessage(Guid transactionI
if (String.IsNullOrEmpty(accountNumber))
{
- Logger.LogWarning($"AgencyBanking sale request rejected. TransactionId=[{transactionId}] missing AgencyBankingAccountNumber");
+ Logger.LogWarning("AgencyBanking sale request rejected. TransactionId=[{TransactionId}] missing AgencyBankingAccountNumber", transactionId);
return Result.Invalid("AgencyBankingAccountNumber - Account Number is a required field for this transaction type");
}
- Logger.LogInformation($"AgencyBanking sale request metadata resolved. TransactionId=[{transactionId}], MessageType=[{messageType}], AccountNumber=[{accountNumber}]");
+ Logger.LogInformation("AgencyBanking sale request metadata resolved. TransactionId=[{TransactionId}], MessageType=[{MessageType}], AccountNumber=[{AccountNumber}]", transactionId, messageType, accountNumber);
Result result = messageType switch {
"balanceenquiry" => await ProcessBalanceEnquiry(transactionId, merchant.MerchantId.ToString(), accountNumber, cancellationToken),
@@ -73,7 +74,7 @@ public async Task> ProcessSaleMessage(Guid transactionI
};
if (result.Status == ResultStatus.Invalid) {
- Logger.LogWarning($"AgencyBanking sale request rejected. TransactionId=[{transactionId}] unsupported message type [{messageType}]");
+ Logger.LogWarning("AgencyBanking sale request rejected. TransactionId=[{TransactionId}] unsupported message type [{MessageType}]", transactionId, messageType);
}
return result;
@@ -82,7 +83,7 @@ public async Task> ProcessSaleMessage(Guid transactionI
throw;
}
catch (Exception ex) {
- Logger.LogError($"AgencyBanking sale request failed. TransactionId=[{transactionId}]", ex);
+ Logger.LogError(ex,"AgencyBanking sale request failed. TransactionId=[{TransactionId}]", transactionId);
return Result.Failure($"AgencyBanking request failed [{ex.Message}]");
}
}
@@ -103,13 +104,13 @@ private async Task> ProcessWithdrawal(Guid transactionI
if (String.IsNullOrWhiteSpace(amountValue))
{
- Logger.LogWarning($"AgencyBanking withdrawal request rejected. TransactionId=[{transactionId}] missing Amount");
+ Logger.LogWarning("AgencyBanking withdrawal request rejected. TransactionId=[{TransactionId}] missing Amount", transactionId);
return Result.Invalid("Amount - Amount is a required field for this transaction type");
}
if (Decimal.TryParse(amountValue, out Decimal amount) == false)
{
- Logger.LogWarning($"AgencyBanking withdrawal request rejected. TransactionId=[{transactionId}] invalid Amount [{amountValue}]");
+ Logger.LogWarning("AgencyBanking withdrawal request rejected. TransactionId=[{TransactionId}] invalid Amount [{Amount}]", amountValue);
return Result.Invalid("Amount - Amount is not a valid decimal value");
}
@@ -117,21 +118,23 @@ private async Task> ProcessWithdrawal(Guid transactionI
request.Content = CreateContent(body);
string requestBody = await request.Content.ReadAsStringAsync(cancellationToken);
- Logger.LogWarning($"AgencyBanking withdrawal request starting. TransactionId=[{transactionId}], AgentId=[{agentId}], AccountNumber=[{accountNumber}], RequestUri=[{request.RequestUri}], RequestBody=[{requestBody}]");
+ Logger.LogWarning("AgencyBanking withdrawal request starting. TransactionId=[{TransactionId}], AgentId=[{AgentId}], AccountNumber=[{AccountNumber}], RequestUri=[{Uri}], RequestBody=[{requestBody}]",
+ transactionId, agentId, accountNumber, request.RequestUri, requestBody);
HttpResponseMessage response = await this.HttpClient.SendAsync(request, cancellationToken);
String responseContent = await response.Content.ReadAsStringAsync(cancellationToken);
- Logger.LogWarning($"AgencyBanking withdrawal response received. TransactionId=[{transactionId}], StatusCode=[{response.StatusCode}], ContentLength=[{responseContent?.Length ?? 0}]");
+ Logger.LogWarning("AgencyBanking withdrawal response received. TransactionId=[{TransactionId}], StatusCode=[{StatusCode}], ContentLength=[{ContentLength}]",
+ transactionId, response.StatusCode, responseContent?.Length ?? 0);
if (response.IsSuccessStatusCode == false)
{
- Logger.LogWarning($"AgencyBanking withdrawal failed. TransactionId=[{transactionId}], StatusCode=[{response.StatusCode}], ResponseBody=[{responseContent}]");
+ Logger.LogWarning("AgencyBanking withdrawal failed. TransactionId=[{TransactionId}], StatusCode=[{StatusCode}], ResponseBody=[{ResponseBody}]",transactionId, response.StatusCode, responseContent);
return Result.Invalid($"Failed to process withdrawal {responseContent}");
}
- TransactionResult balanceEnquiryResponse = StringSerialiser.Deserialise(responseContent, SerialiserOptions);
- Logger.LogWarning($"AgencyBanking withdrawal completed. TransactionId=[{transactionId}], ResponseCode=[{balanceEnquiryResponse.ResponseCode}]");
+ TransactionResult withdrawalResponse = StringSerialiser.Deserialise(responseContent, SerialiserOptions);
+ Logger.LogWarning("AgencyBanking withdrawal completed. TransactionId=[{TransactionId}], ResponseCode=[{ResponseCode}]", transactionId, withdrawalResponse.ResponseCode);
OperatorResponse operatorResponse = new()
{
@@ -153,20 +156,22 @@ private async Task> ProcessMiniStatement(String agentId
request.Content = CreateContent(body);
string requestBody = await request.Content.ReadAsStringAsync(cancellationToken);
- Logger.LogWarning($"AgencyBanking mini-statement request starting. AgentId=[{agentId}], AccountNumber=[{accountNumber}], RequestUri=[{request.RequestUri}], RequestBody=[{requestBody}]");
+ Logger.LogWarning("AgencyBanking mini-statement request starting. AgentId=[{AgentId}], AccountNumber=[{AccountNumber}], RequestUri=[{RequestUri}], RequestBody=[{RequestBody}]", agentId, accountNumber, request.RequestUri, requestBody);
HttpResponseMessage response = await this.HttpClient.SendAsync(request, cancellationToken);
String responseContent = await response.Content.ReadAsStringAsync(cancellationToken);
- Logger.LogWarning($"AgencyBanking mini-statement response received. AgentId=[{agentId}], AccountNumber=[{accountNumber}], StatusCode=[{response.StatusCode}], ContentLength=[{responseContent?.Length ?? 0}]");
+ Logger.LogWarning("AgencyBanking mini-statement response received. AgentId=[{AgentId}], AccountNumber=[{AccountNumber}], StatusCode=[{StatusCode}], ContentLength=[{ContentLength}]",
+ agentId, accountNumber, response.StatusCode, responseContent?.Length ?? 0);
if (response.IsSuccessStatusCode == false) {
- Logger.LogWarning($"AgencyBanking mini-statement failed. AgentId=[{agentId}], AccountNumber=[{accountNumber}], StatusCode=[{response.StatusCode}], ResponseBody=[{responseContent}]");
+ Logger.LogWarning("AgencyBanking mini-statement failed. AgentId=[{AgentId}], AccountNumber=[{AccountNumber}], StatusCode=[{StatusCode}], ResponseBody=[{ResponseContent}]",
+ agentId, accountNumber, response.StatusCode, responseContent);
return Result.Invalid($"Failed to process mini-statement {responseContent}");
}
MiniStatementResponse miniStatementResponse = StringSerialiser.Deserialise(responseContent, SerialiserOptions);
- Logger.LogWarning($"AgencyBanking mini-statement completed. AgentId=[{agentId}], AccountNumber=[{accountNumber}], ResponseCode=[{miniStatementResponse.ResponseCode}]");
+ Logger.LogWarning("AgencyBanking mini-statement completed. AgentId=[{AgentId}], AccountNumber=[{AccountNumber}], ResponseCode=[{ResponseCode}]", agentId, accountNumber, miniStatementResponse.ResponseCode);
// Transform the mini-statement response into an operator response
List statementLines = miniStatementResponse.Transactions.Select(line => new OperatorStatementLine { Amount = line.Amount, TransactionDate = line.TransactionDate, TransactionType = line.TransactionType }).ToList();
@@ -191,34 +196,36 @@ private async Task> ProcessDeposit(Guid transactionId,
if (String.IsNullOrWhiteSpace(amountValue))
{
- Logger.LogWarning($"AgencyBanking deposit request rejected. TransactionId=[{transactionId}] missing Amount");
+ Logger.LogWarning("AgencyBanking deposit request rejected. TransactionId=[{TransactionId}] missing Amount", transactionId);
return Result.Invalid("Amount - Amount is a required field for this transaction type");
}
if (Decimal.TryParse(amountValue, out Decimal amount) == false)
{
- Logger.LogWarning($"AgencyBanking deposit request rejected. TransactionId=[{transactionId}] invalid Amount [{amountValue}]");
+ Logger.LogWarning("AgencyBanking deposit request rejected. TransactionId=[{TransactionId}] invalid Amount [{Amount}]", transactionId, amountValue);
return Result.Invalid("Amount - Amount is not a valid decimal value");
}
DepositRequest body = new() { AgentId = agentId, AccountNumber = accountNumber, Amount = amount, TransactionId = transactionId.ToString() };
request.Content = CreateContent(body);
string requestBody = await request.Content.ReadAsStringAsync(cancellationToken);
- Logger.LogWarning($"AgencyBanking deposit request starting. TransactionId=[{transactionId}], AgentId=[{agentId}], AccountNumber=[{accountNumber}], RequestUri=[{request.RequestUri}], RequestBody=[{requestBody}]");
+ Logger.LogWarning("AgencyBanking deposit request starting. TransactionId=[{TransactionId}], AgentId=[{AgentId}], AccountNumber=[{AccountNumber}], RequestUri=[{RequestUri}], RequestBody=[{RequestBody}]",
+ transactionId, agentId, accountNumber, request.RequestUri, requestBody);
HttpResponseMessage response = await this.HttpClient.SendAsync(request, cancellationToken);
String responseContent = await response.Content.ReadAsStringAsync(cancellationToken);
- Logger.LogWarning($"AgencyBanking deposit response received. TransactionId=[{transactionId}], StatusCode=[{response.StatusCode}], ContentLength=[{responseContent?.Length ?? 0}]");
+ Logger.LogWarning("AgencyBanking deposit response received. TransactionId=[{TransactionId}], StatusCode=[{StatusCode}], ContentLength=[{ContentLength}]",
+ transactionId, response.StatusCode, responseContent?.Length ?? 0);
if (response.IsSuccessStatusCode == false)
{
- Logger.LogWarning($"AgencyBanking deposit failed. TransactionId=[{transactionId}], StatusCode=[{response.StatusCode}], ResponseBody=[{responseContent}]");
+ Logger.LogWarning("AgencyBanking deposit failed. TransactionId=[{TransactionId}], StatusCode=[{StatusCode}], ResponseBody=[{ResponseContent}]", transactionId, response.StatusCode, responseContent);
return Result.Invalid($"Failed to process deposit {responseContent}");
}
- TransactionResult balanceEnquiryResponse = StringSerialiser.Deserialise(responseContent, SerialiserOptions);
- Logger.LogWarning($"AgencyBanking deposit completed. TransactionId=[{transactionId}], ResponseCode=[{balanceEnquiryResponse.ResponseCode}]");
+ TransactionResult depositResponse = StringSerialiser.Deserialise(responseContent, SerialiserOptions);
+ Logger.LogWarning("AgencyBanking deposit completed. TransactionId=[{TransactionId}], ResponseCode=[{ResponseCode}]", transactionId, depositResponse.ResponseCode);
OperatorResponse operatorResponse = new()
{
@@ -244,20 +251,24 @@ private async Task> ProcessBalanceEnquiry(Guid transact
request.Content = CreateContent(body);
string requestBody = await request.Content.ReadAsStringAsync(cancellationToken);
- Logger.LogWarning($"AgencyBanking balance enquiry request starting. TransactionId=[{transactionId}], AgentId=[{agentId}], AccountNumber=[{accountNumber}], RequestUri=[{request.RequestUri}], RequestBody=[{requestBody}]");
+ Logger.LogWarning("AgencyBanking balance enquiry request starting. TransactionId=[{TransactionId}], AgentId=[{AgentId}], AccountNumber=[{AccountNumber}], RequestUri=[{Uri}], RequestBody=[{RequestBody}]",
+ transactionId, agentId, accountNumber, request.RequestUri, requestBody);
HttpResponseMessage response = await this.HttpClient.SendAsync(request, cancellationToken);
String responseContent = await response.Content.ReadAsStringAsync(cancellationToken);
- Logger.LogWarning($"AgencyBanking balance enquiry response received. TransactionId=[{transactionId}], StatusCode=[{response.StatusCode}], ContentLength=[{responseContent?.Length ?? 0}]");
+ Logger.LogWarning("AgencyBanking balance enquiry response received. TransactionId=[{TransactionId}], StatusCode=[{StatusCode}], ContentLength=[{ContentLength}]",
+ transactionId, response.StatusCode, responseContent?.Length ?? 0);
if (response.IsSuccessStatusCode == false) {
- Logger.LogWarning($"AgencyBanking balance enquiry failed. TransactionId=[{transactionId}], StatusCode=[{response.StatusCode}], ResponseBody=[{responseContent}]");
+ Logger.LogWarning("AgencyBanking balance enquiry failed. TransactionId=[{TransactionId}], StatusCode=[{StatusCode}], ResponseBody=[{ResponseContent}]",
+ transactionId, response.StatusCode, responseContent);
return Result.Invalid($"Failed to process balance enquiry {responseContent}");
}
BalanceEnquiryResponse balanceEnquiryResponse = StringSerialiser.Deserialise(responseContent, SerialiserOptions);
- Logger.LogWarning($"AgencyBanking balance enquiry completed. TransactionId=[{transactionId}], ResponseMessage=[{balanceEnquiryResponse.ResponseMessage}], AvailableBalance=[{balanceEnquiryResponse.AvailableBalance}]");
+ Logger.LogWarning("AgencyBanking balance enquiry completed. TransactionId=[{TransactionId}], ResponseMessage=[{ResponseMessage}], AvailableBalance=[{AvailableBalance}]",
+ transactionId, balanceEnquiryResponse.ResponseMessage, balanceEnquiryResponse.AvailableBalance);
OperatorResponse operatorResponse = new() {
IsSuccessful = true,
diff --git a/TransactionProcessor.BusinessLogic/OperatorInterfaces/PataPawaPrePay/PataPawaPrePayProxy.cs b/TransactionProcessor.BusinessLogic/OperatorInterfaces/PataPawaPrePay/PataPawaPrePayProxy.cs
index d84f50f0..5d7c7c85 100644
--- a/TransactionProcessor.BusinessLogic/OperatorInterfaces/PataPawaPrePay/PataPawaPrePayProxy.cs
+++ b/TransactionProcessor.BusinessLogic/OperatorInterfaces/PataPawaPrePay/PataPawaPrePayProxy.cs
@@ -46,21 +46,27 @@ public async Task> ProcessLogonMessage(CancellationToke
content.Add(new StringContent(this.Configuration.Password), "password");
requestMessage.Content = content;
+ String bodyForLog = $"request=login&username={Uri.EscapeDataString(this.Configuration.Username)}&password=[REDACTED]";
+
+ Logger.LogWarning("Sending logon request to PataPawaPrePay {Url}. Form fields: {RequestBody}", requestMessage.RequestUri, bodyForLog);
+
HttpResponseMessage responseMessage = await this.HttpClient.SendAsync(requestMessage, cancellationToken);
// Check the send was successful
if (responseMessage.IsSuccessStatusCode == false) {
+ Logger.LogWarning("Error sending logon request to PataPawaPrePay {Url}. Status Code {StatusCode}", requestMessage.RequestUri, responseMessage.StatusCode);
return Result.Failure($"Error sending logon request to Patapawa. Status Code [{responseMessage.StatusCode}]");
}
// Get the response
String responseContent = await responseMessage.Content.ReadAsStringAsync(cancellationToken);
- Logger.LogInformation($"Received response message from Patapawa [{responseContent}]");
+ Logger.LogWarning("Received logon response message from Patapawa [{ResponseContent}]", responseContent);
return this.CreateFromLogon(responseContent);
}
catch (Exception ex) {
+ Logger.LogError(ex, "Error processing logon message for PataPawaPrePay");
return Result.Failure($"Error processing logon message for PataPawaPrePay [{ex.Message}]");
}
}
@@ -69,22 +75,23 @@ public async Task> ProcessSaleMessage(Guid transactionI
Models.Merchant.Merchant merchant, DateTime transactionDateTime, String transactionReference, Dictionary additionalTransactionMetadata, CancellationToken cancellationToken){
// Get the logon response for the operator
OperatorResponse logonResponse = this.MemoryCache.Get("PataPawaPrePayLogon");
- if (logonResponse == null)
- {
+ if (logonResponse == null) {
+ Logger.LogWarning("PataPawaPrePay sale request rejected. TransactionId=[{TransactionId}] - logonResponse is null", transactionId);
return Result.Invalid("PataPawaPrePayLogon - logonResponse is null");
}
+
String apiKey = logonResponse.AdditionalTransactionResponseMetadata.ExtractFieldFromMetadata("PataPawaPrePaidAPIKey");
- if (String.IsNullOrEmpty(apiKey))
- {
+ if (String.IsNullOrEmpty(apiKey)) {
+ Logger.LogWarning("PataPawaPrePay sale request rejected. TransactionId=[{TransactionId}] - APIKey is a required field for this transaction type", transactionId);
return Result.Invalid("PataPawaPrePayAPIKey - APIKey is a required field for this transaction type");
}
// Check the meta data for the sale message type
String messageType = additionalTransactionMetadata.ExtractFieldFromMetadata("PataPawaPrePayMessageType");
- if (String.IsNullOrEmpty(messageType))
- {
+ if (String.IsNullOrEmpty(messageType)) {
+ Logger.LogWarning("PataPawaPrePay sale request rejected. TransactionId=[{TransactionId}] - Message Type is a required field for this transaction type", transactionId);
return Result.Invalid("PataPawaPrePayMessageType - Message Type is a required field for this transaction type");
}
@@ -92,13 +99,14 @@ public async Task> ProcessSaleMessage(Guid transactionI
if (String.IsNullOrEmpty(meterNumber))
{
+ Logger.LogWarning("PataPawaPrePay sale request rejected. TransactionId=[{TransactionId}] - Meter Number is a required field for this transaction type", transactionId);
return Result.Invalid("MeterNumber - Meter Number is a required field for this transaction type");
}
return messageType switch
{
"meter" => await this.PerformMeterTransaction(meterNumber, apiKey, cancellationToken),
- "vend" => await this.PerformVendTransaction(meterNumber, apiKey, additionalTransactionMetadata, cancellationToken),
+ "vend" => await this.PerformVendTransaction(transactionId, meterNumber, apiKey, additionalTransactionMetadata, cancellationToken),
_ => Result.Invalid($"PataPawaPrePayMessageType - Unsupported Message Type {messageType}")
};
}
@@ -113,12 +121,18 @@ private async Task> PerformMeterTransaction(String mete
content.Add(new StringContent(apiKey), "key");
requestMessage.Content = content;
+ string bodyForLog =
+ $"request=meter&username={Uri.EscapeDataString(this.Configuration.Username)}" +
+ $"&meter={Uri.EscapeDataString(meterNumber)}&key=[REDACTED]";
+
+ Logger.LogWarning("Sending meter request to PataPawaPrePay {Url}. Form fields: {RequestBody}", requestMessage.RequestUri, bodyForLog);
+
HttpResponseMessage responseMessage = await this.HttpClient.SendAsync(requestMessage, cancellationToken);
// Get the response
String responseContent = await responseMessage.Content.ReadAsStringAsync(cancellationToken);
- Logger.LogInformation($"Received response message from Patapawa [{responseContent}]");
+ Logger.LogInformation("Received response message from PataPawaPrePay [{ResponseContent}]", responseContent);
return this.CreateFromMeter(responseContent);
}
@@ -126,17 +140,19 @@ private async Task> PerformMeterTransaction(String mete
throw;
}
catch (Exception ex) {
+ Logger.LogError(ex, "Error processing meter message for PataPawaPrePay");
return Result.Failure($"Error performing meter transaction for meter number {meterNumber} [{ex.Message}]");
}
}
- private async Task> PerformVendTransaction(String meterNumber, String apiKey, Dictionary additionalTransactionMetadata, CancellationToken cancellationToken)
+ private async Task> PerformVendTransaction(Guid transactionId, String meterNumber, String apiKey, Dictionary additionalTransactionMetadata, CancellationToken cancellationToken)
{
try {
String customerName = additionalTransactionMetadata.ExtractFieldFromMetadata("CustomerName");
if (String.IsNullOrEmpty(customerName))
{
+ Logger.LogWarning("PataPawaPrePay vend request rejected. TransactionId=[{TransactionId}] - CustomerName is a required field for this transaction type", transactionId);
return Result.Invalid("CustomerName - Customer Name is a required field for this transaction type");
}
@@ -144,10 +160,10 @@ private async Task> PerformVendTransaction(String meter
if (String.IsNullOrEmpty(amount))
{
+ Logger.LogWarning("PataPawaPrePay sale request rejected. TransactionId=[{TransactionId}] - Amount is a required field for this transaction type", transactionId);
return Result.Invalid("Amount - Amount is a required field for this transaction type");
}
-
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, this.Configuration.Url);
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new StringContent("vend"), "request");
@@ -158,12 +174,21 @@ private async Task> PerformVendTransaction(String meter
content.Add(new StringContent(customerName), "customerName");
requestMessage.Content = content;
+ string bodyForLog =
+ $"request=vend&username={Uri.EscapeDataString(this.Configuration.Username)}" +
+ $"&meter={Uri.EscapeDataString(meterNumber)}" +
+ $"&key=[REDACTED]" +
+ $"&amount={Uri.EscapeDataString(amount)}" +
+ $"&customerName={Uri.EscapeDataString(customerName)}";
+
+ Logger.LogWarning("Sending vend request to PataPawaPrePay {Url}. Form fields: {RequestBody}", requestMessage.RequestUri, bodyForLog);
+
HttpResponseMessage responseMessage = await this.HttpClient.SendAsync(requestMessage, cancellationToken);
// Get the response
String responseContent = await responseMessage.Content.ReadAsStringAsync(cancellationToken);
- Logger.LogInformation($"Received response message from Patapawa [{responseContent}]");
+ Logger.LogInformation("Received response message from PataPawaPrePay [{ResponseContent}]", responseContent);
return this.CreateFromVend(responseContent);
}
@@ -171,6 +196,7 @@ private async Task> PerformVendTransaction(String meter
throw;
}
catch (Exception ex) {
+ Logger.LogError(ex, "Error processing meter message for PataPawaPrePay");
return Result.Failure($"Error performing vend transaction for meter number {meterNumber} [{ex.Message}]");
}
}
diff --git a/TransactionProcessor.BusinessLogic/OperatorInterfaces/SafaricomPinless/SafaricomPinlessProxy.cs b/TransactionProcessor.BusinessLogic/OperatorInterfaces/SafaricomPinless/SafaricomPinlessProxy.cs
index 288b3acd..7f49a283 100644
--- a/TransactionProcessor.BusinessLogic/OperatorInterfaces/SafaricomPinless/SafaricomPinlessProxy.cs
+++ b/TransactionProcessor.BusinessLogic/OperatorInterfaces/SafaricomPinless/SafaricomPinlessProxy.cs
@@ -85,18 +85,20 @@ public async Task> ProcessSaleMessage(Guid transactionI
if (String.IsNullOrEmpty(transactionAmount))
{
+ Logger.LogWarning("Safaricom sale request rejected. TransactionId=[{TransactionId}] - Amount is a required field for this transaction type", transactionId);
return Result.Invalid("Amount is a required field for this transaction type");
}
if (String.IsNullOrEmpty(customerMsisdn))
{
+ Logger.LogWarning("Safaricom sale request rejected. TransactionId=[{TransactionId}] - CustomerAccountNumber is a required field for this transaction type", transactionId);
return Result.Invalid("CustomerAccountNumber is a required field for this transaction type");
}
// Multiply amount before sending
// Covert the transaction amount to Decimal and remove decimal places
- if (Decimal.TryParse(transactionAmount, out Decimal amountAsDecimal) == false)
- {
+ if (Decimal.TryParse(transactionAmount, out Decimal amountAsDecimal) == false) {
+ Logger.LogWarning("Safaricom sale request rejected. TransactionId=[{TransactionId}] - Transaction Amount is not a valid decimal value", transactionId);
return Result.Invalid("Transaction Amount is not a valid decimal value");
}
@@ -104,24 +106,24 @@ public async Task> ProcessSaleMessage(Guid transactionI
String requestUrl = this.BuildRequest(transactionDateTime, transactionReference, customerMsisdn, operatorTransactionAmount);
- Logger.LogInformation($"Sending message to Safaricom [{requestUrl}]");
+ Logger.LogInformation("Sending message to Safaricom [{RequestBody}]", requestUrl);
// Concatenate the request message
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, new Uri(requestUrl));
// Send the request to Safaricom
HttpResponseMessage responseMessage = await this.HttpClient.SendAsync(requestMessage, cancellationToken);
+ String responseContent = await responseMessage.Content.ReadAsStringAsync(cancellationToken);
+ Logger.LogWarning("Safaricom response received. TransactionId=[{TransactionId}], StatusCode=[{StatusCode}], ContentLength=[{ContentLength}]",
+ transactionId, responseMessage.StatusCode, responseContent?.Length ?? 0);
// Check the send was successful
- if (responseMessage.IsSuccessStatusCode == false)
- {
+ if (responseMessage.IsSuccessStatusCode == false) {
+ Logger.LogWarning("Safaricom sale failed. TransactionId=[{TransactionId}], StatusCode=[{StatusCode}], ResponseBody=[{ResponseContent}]", transactionId, responseMessage.StatusCode, responseContent);
return Result.Failure($"Error sending request [{requestUrl}] to Safaricom. Status Code [{responseMessage.StatusCode}]");
}
-
- // Get the response
- String responseContent = await responseMessage.Content.ReadAsStringAsync();
-
- Logger.LogInformation($"Received response message from Safaricom [{responseContent}]");
+
+ Logger.LogInformation("Safaricom sale completed [{ResponseContent}]", responseContent);
return this.CreateFrom(responseContent);
}
@@ -129,6 +131,7 @@ public async Task> ProcessSaleMessage(Guid transactionI
throw;
}
catch (Exception ex) {
+ Logger.LogError(ex, "Error sending request to Safaricom");
return Result.Failure($"Error sending request to Safaricom [{ex.Message}]");
}
}
diff --git a/TransactionProcessor.BusinessLogic/OperatorInterfaces/VoucherManagement/VoucherManagementProxy.cs b/TransactionProcessor.BusinessLogic/OperatorInterfaces/VoucherManagement/VoucherManagementProxy.cs
index 8faf5256..97cf19ab 100644
--- a/TransactionProcessor.BusinessLogic/OperatorInterfaces/VoucherManagement/VoucherManagementProxy.cs
+++ b/TransactionProcessor.BusinessLogic/OperatorInterfaces/VoucherManagement/VoucherManagementProxy.cs
@@ -47,11 +47,13 @@ public async Task> ProcessSaleMessage(Guid transactionI
// Covert the transaction amount to Decimal and remove decimal places
if (Decimal.TryParse(transactionAmount, out Decimal amountAsDecimal) == false)
{
+ Logger.LogWarning("Voucher sale request rejected. TransactionId=[{TransactionId}] - Transaction Amount is not a valid decimal value", transactionId);
return Result.Invalid("Transaction Amount is not a valid decimal value");
}
if (String.IsNullOrEmpty(recipientEmail) && String.IsNullOrEmpty(recipientMobile))
{
+ Logger.LogWarning("Voucher sale request rejected. TransactionId=[{TransactionId}] - Recipient details (either email or mobile) is a required field for this transaction type", transactionId);
return Result.Invalid("Recipient details (either email or mobile) is a required field for this transaction type");
}
diff --git a/TransactionProcessor.BusinessLogic/Services/SettlementDomainService.cs b/TransactionProcessor.BusinessLogic/Services/SettlementDomainService.cs
index 5c33547a..7b7a881f 100644
--- a/TransactionProcessor.BusinessLogic/Services/SettlementDomainService.cs
+++ b/TransactionProcessor.BusinessLogic/Services/SettlementDomainService.cs
@@ -119,7 +119,7 @@ private async Task> ProcessSettlementFees(List<(Guid transactionId,
return ResultHelpers.CreateFailure(saveResult);
}
catch (Exception ex) {
- Logger.LogError($"Failed to process transaction {feeToSettle.transactionId} for settlement {settlementAggregateId}", ex);
+ Logger.LogError(ex,$"Failed to process transaction {feeToSettle.transactionId} for settlement {settlementAggregateId}");
failedResults.Add(Result.Failure($"Failed to process transaction {feeToSettle.transactionId} for settlement {settlementAggregateId}: {ex.Message}"));
}
}
@@ -145,10 +145,8 @@ public async Task AddMerchantFeePendingSettlement(SettlementCommands.Add
SettlementAggregate settlementAggregate = getSettlementResult.Data;
- Logger.LogInformation("In ApplySettlementUpdates");
if (settlementAggregate.IsCreated == false)
{
- Logger.LogInformation("In ApplySettlementUpdates - aggregate not created");
Result createResult = settlementAggregate.Create(command.EstateId, command.MerchantId, command.SettlementDueDate.Date);
if (createResult.IsFailed)
return ResultHelpers.CreateFailure(createResult);
@@ -165,7 +163,6 @@ public async Task AddMerchantFeePendingSettlement(SettlementCommands.Add
FeeValue = command.FeeValue,
SettlementDueDate = command.SettlementDueDate
};
- Logger.LogInformation("In ApplySettlementUpdates - about to add fee");
Result stateResult = settlementAggregate.AddFee(command.MerchantId, command.TransactionId, calculatedFee);
if (stateResult.IsFailed)
return ResultHelpers.CreateFailure(stateResult);
diff --git a/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs b/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs
index 731caebc..5ddade9e 100644
--- a/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs
+++ b/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs
@@ -474,8 +474,7 @@ private async Task> ProcessMessageWithOperator(Models.M
}
catch (Exception e) {
// Log out the error
- Logger.LogError(e);
- Logger.LogWarning(e.StackTrace);
+ Logger.LogError(e, "Error processing operator message");
return ResultHelpers.CreateFailedResult(new OperatorResponse { IsSuccessful = false, ResponseCode = "9999", ResponseMessage = e.GetCombinedExceptionMessages() });
}
}
@@ -550,7 +549,7 @@ private async Task ResendEmailMessage(String accessToken,
public async Task> ProcessSaleTransaction(TransactionCommands.ProcessSaleTransactionCommand command,
CancellationToken cancellationToken) {
- Logger.LogInformation($"Starting ProcessSaleTransaction for TransactionId {command.TransactionId}");
+ Logger.LogInformation("Starting ProcessSaleTransaction for TransactionId {TransactionId}", command.TransactionId);
try {
Result transactionResult = await GetTransactionAggregate(command, cancellationToken);
@@ -580,7 +579,7 @@ public async Task> ProcessSaleTransaction
return ResultHelpers.CreateFailure(saveResult);
Transaction transaction = transactionAggregate.GetTransaction();
- Logger.LogInformation($"Transaction {command.TransactionId} completed successfully");
+ Logger.LogInformation("Transaction {TransactionId} completed successfully", command.TransactionId);
return Result.Success(new ProcessSaleTransactionResponse {
ResponseMessage = transaction.ResponseMessage,
@@ -592,19 +591,19 @@ public async Task> ProcessSaleTransaction
});
}
catch (Exception ex) {
- Logger.LogError($"Unhandled exception during ProcessSaleTransaction for {command.TransactionId}", ex);
+ Logger.LogError(ex, "Unhandled exception during ProcessSaleTransaction for {TransactionId}", command.TransactionId);
return Result.Failure(ex.GetExceptionMessages());
}
}
private async Task> GetTransactionAggregate(TransactionCommands.ProcessSaleTransactionCommand command,
CancellationToken cancellationToken) {
- Logger.LogDebug($"Fetching TransactionAggregate for TransactionId {command.TransactionId}");
+ Logger.LogDebug("Fetching TransactionAggregate for TransactionId {TransactionId}", command.TransactionId);
Result result = await DomainServiceHelper.GetAggregateOrFailure(ct => AggregateService.GetLatest(command.TransactionId, ct), command.TransactionId, cancellationToken, false);
if (result.IsFailed)
- Logger.LogWarning($"TransactionAggregate not found for TransactionId {command.TransactionId}");
+ Logger.LogWarning("TransactionAggregate not found for TransactionId {TransactionId}", command.TransactionId);
return result;
}
@@ -613,12 +612,13 @@ private async Task> GetTransactionAggregate(Transac
private async Task> ValidateTransaction(TransactionCommands.ProcessSaleTransactionCommand command,
CancellationToken cancellationToken) {
Decimal? amount = command.AdditionalTransactionMetadata.ExtractFieldFromMetadata("Amount");
- Logger.LogInformation($"Validating Sale Transaction for Merchant {command.MerchantId}, Product {command.ProductId}");
+ Logger.LogInformation("Validating Sale Transaction Id {TransactionId} for Merchant {MerchantId}, Product {ProductId}", command.TransactionId, command.MerchantId, command.ProductId);
TransactionSource transactionSourceValue = (TransactionSource)command.TransactionSource;
Result result = await TransactionValidationService.ValidateSaleTransaction(command.EstateId, command.MerchantId, command.ContractId, command.ProductId, command.DeviceIdentifier, command.OperatorId, amount, transactionSourceValue, cancellationToken);
- Logger.LogInformation($"Validation completed with ResponseCode {result.Data?.ResponseCode}, Message {result.Data?.ResponseMessage}");
+ Logger.LogInformation("Validation completed for Transaction Id {TransactionId} with ResponseCode {ResponseCode}, Message {ResponseMessage}",
+ command.TransactionId, result.Data?.ResponseCode, result.Data?.ResponseMessage);
return result;
}
@@ -628,7 +628,7 @@ private async Task> ValidateTransaction(Tran
CancellationToken cancellationToken) {
Guid floatAggregateId = command.OperatorId;
- Logger.LogDebug($"Fetching FloatAggregate {floatAggregateId}");
+ Logger.LogDebug("Fetching FloatAggregate {FloatId} for TransactionId {TransactionId}", floatAggregateId, command.TransactionId);
Result floatAggregateResult = await DomainServiceHelper.GetAggregateOrFailure(ct => AggregateService.GetLatest(floatAggregateId, ct), floatAggregateId, cancellationToken, false);
@@ -640,7 +640,7 @@ private async Task> ValidateTransaction(Tran
Decimal unitCost = floatAggregate.GetUnitCostPrice();
Decimal totalCost = floatAggregate.GetTotalCostPrice(amount);
- Logger.LogInformation($"Float cost calculated: UnitCost={unitCost}, TotalCost={totalCost}");
+ Logger.LogInformation("Float cost calculated for TransactionId {TransactionId}: UnitCost={UnitCost}, TotalCost={TotalCost}", command.TransactionId, unitCost, totalCost);
return (unitCost, totalCost);
}
@@ -704,12 +704,14 @@ private static Result ApplyReconciliationValidationResult(ReconciliationAggregat
DateTime? start = null, end = null;
if (validationResult.Data.ResponseCode != TransactionResponseCode.Success) {
- Logger.LogInformation($"Validation failed with ResponseCode {validationResult.Data.ResponseCode}: {validationResult.Data.ResponseMessage}");
+ Logger.LogInformation("Validation failed for TransactionId {TransactionId} with ResponseCode {ResponseCode}: {ResponseMessage}",
+ command.TransactionId, validationResult.Data.ResponseCode, validationResult.Data.ResponseMessage);
+
transactionAggregate.DeclineTransactionLocally(validationResult.Data.ResponseCode, validationResult.Data.ResponseMessage);
return (start, end);
}
- Logger.LogInformation($"Validation success, processing with Operator {command.OperatorId}");
+ Logger.LogInformation("Validation success for TransactionId {TransactionId} processing with Operator {OperatorId}", command.TransactionId, command.OperatorId);
transactionAggregate.RecordAdditionalRequestData(command.OperatorId, command.AdditionalTransactionMetadata);
Result merchantResult = await GetMerchant(command.MerchantId, cancellationToken);
@@ -721,11 +723,11 @@ private static Result ApplyReconciliationValidationResult(ReconciliationAggregat
end = DateTime.Now;
if (operatorResult.IsSuccess) {
- Logger.LogInformation("Operator authorised transaction successfully");
+ Logger.LogInformation("Operator {OperatorId} authorised transaction {TransactionId} successfully", command.OperatorId, command.TransactionId);
transactionAggregate.AuthoriseTransaction(command.OperatorId, operatorResult.Data.AuthorisationCode, operatorResult.Data.ResponseCode, operatorResult.Data.ResponseMessage, operatorResult.Data.TransactionId, TransactionResponseCode.Success, "SUCCESS");
}
else {
- Logger.LogWarning($"Operator declined transaction: {operatorResult.Data.ResponseMessage}");
+ Logger.LogWarning("Operator {OperatorId} declined transaction {TransactionId}: {ResponseMessage}", command.OperatorId, command.TransactionId, operatorResult.Data.ResponseMessage);
transactionAggregate.DeclineTransaction(command.OperatorId, operatorResult.Data.ResponseCode, operatorResult.Data.ResponseMessage, TransactionResponseCode.TransactionDeclinedByOperator, "DECLINED BY OPERATOR");
}
diff --git a/TransactionProcessor.DatabaseTests/DatabaseTestFixture.cs b/TransactionProcessor.DatabaseTests/DatabaseTestFixture.cs
index 4f827cfb..597e727a 100644
--- a/TransactionProcessor.DatabaseTests/DatabaseTestFixture.cs
+++ b/TransactionProcessor.DatabaseTests/DatabaseTestFixture.cs
@@ -43,9 +43,10 @@ public string GetLocalConnectionString(string databaseName)
private NlogLogger CreateLogger()
{
- NlogLogger logger = new NlogLogger();
+ NlogLogger logger = new();
logger.Initialise(LogManager.GetLogger("Specflow"), "Specflow");
- LogManager.AddHiddenAssembly(typeof(NlogLogger).Assembly);
+ LogManager.Setup().SetupLogFactory(setup =>
+ setup.AddCallSiteHiddenAssembly(typeof(NlogLogger).Assembly));
return logger;
}
}
diff --git a/TransactionProcessor.IntegrationTests/Common/DockerHelper.cs b/TransactionProcessor.IntegrationTests/Common/DockerHelper.cs
index 317d7b72..e61e64f7 100644
--- a/TransactionProcessor.IntegrationTests/Common/DockerHelper.cs
+++ b/TransactionProcessor.IntegrationTests/Common/DockerHelper.cs
@@ -131,9 +131,8 @@ public override ContainerBuilder SetupTestHostContainer()
(String imageName, Boolean useLatest) imageDetails = this.GetImageDetails(ContainerType.TestHost).Data;
- ContainerBuilder testHostContainer = new ContainerBuilder()
+ ContainerBuilder testHostContainer = new ContainerBuilder(imageDetails.imageName)
.WithName(this.TestHostContainerName) // similar to WithName()
- .WithImage(imageDetails.imageName)
.WithEnvironment(environmentVariables)
.MountHostFolder(this.HostTraceFolder)
.WithPortBinding(DockerPorts.TestHostPort, true);
diff --git a/TransactionProcessor.IntegrationTests/Common/GenericSteps.cs b/TransactionProcessor.IntegrationTests/Common/GenericSteps.cs
index fd24e23d..f291360d 100644
--- a/TransactionProcessor.IntegrationTests/Common/GenericSteps.cs
+++ b/TransactionProcessor.IntegrationTests/Common/GenericSteps.cs
@@ -29,9 +29,10 @@ public async Task StartSystem()
{
// Initialise a logger
String scenarioName = this.ScenarioContext.ScenarioInfo.Title.Replace(" ", "");
- NlogLogger logger = new NlogLogger();
+ NlogLogger logger = new();
logger.Initialise(LogManager.GetLogger(scenarioName), scenarioName);
- LogManager.AddHiddenAssembly(typeof(NlogLogger).Assembly);
+ LogManager.Setup().SetupLogFactory(setup =>
+ setup.AddCallSiteHiddenAssembly(typeof(NlogLogger).Assembly));
DockerServices dockerServices = DockerServices.SqlServer | DockerServices.CallbackHandler | DockerServices.KurrentDb |
DockerServices.FileProcessor | DockerServices.MessagingService | DockerServices.SecurityService |
diff --git a/TransactionProcessor.Repository/ITransactionProcessorReadModelRepository.cs b/TransactionProcessor.Repository/ITransactionProcessorReadModelRepository.cs
index a9798ae2..c160492c 100644
--- a/TransactionProcessor.Repository/ITransactionProcessorReadModelRepository.cs
+++ b/TransactionProcessor.Repository/ITransactionProcessorReadModelRepository.cs
@@ -2369,7 +2369,7 @@ public static async Task> ExecuteSafeAsync(Func ExecuteSafeAsync(Func () => Logger.LogWarning(message),
- LogLevel.Information => () => Logger.LogInformation(message),
- LogLevel.Debug => () => Logger.LogDebug(message),
- LogLevel.Trace => () => Logger.LogTrace(message),
- _ => () => Logger.LogInformation(message)
+ LogLevel.Warning => () => Logger.LogWarning(messageTemplate, args),
+ LogLevel.Information => () => Logger.LogInformation(messageTemplate, args),
+ LogLevel.Debug => () => Logger.LogDebug(messageTemplate, args),
+ LogLevel.Trace => () => Logger.LogTrace(messageTemplate, args),
+ _ => () => Logger.LogInformation(messageTemplate, args)
};
action();
diff --git a/TransactionProcessor/Controllers/DomainEventController.cs b/TransactionProcessor/Controllers/DomainEventController.cs
index 3d8f62cd..a94ae779 100644
--- a/TransactionProcessor/Controllers/DomainEventController.cs
+++ b/TransactionProcessor/Controllers/DomainEventController.cs
@@ -88,26 +88,23 @@ public async Task PostEventAsync([FromBody] Object request,
try
{
- Logger.LogWarning($"Processing event - ID [{domainEvent.EventId}], Type[{domainEvent.GetType().Name}]");
+ Logger.LogWarning("Processing event - ID [{EventId}], Type[{EventType}]", domainEvent.EventId, domainEvent.GetType().Name);
- if (eventHandlers == null || eventHandlers.Any() == false)
- {
+ if (eventHandlers == null || eventHandlers.Any() == false) {
// Log a warning out
- Logger.LogInformation($"No event handlers configured for Event Type [{domainEvent.GetType().Name}]");
+ Logger.LogInformation("No event handlers configured for Event Type [{EventType}]", domainEvent.GetType().Name);
return Results.Ok();
}
List executions = eventHandlers
- .Select(domainEventHandler => this.ExecuteHandler(domainEventHandler, domainEvent, cancellationToken))
- .ToList();
+ .Select(domainEventHandler => this.ExecuteHandler(domainEventHandler, domainEvent, cancellationToken))
+ .ToList();
- try
- {
+ try {
await Task.WhenAll(executions.Select(execution => execution.Task));
}
- catch (Exception ex)
- {
- Logger.LogError(new Exception($"One or more handlers threw while processing event [{domainEvent.EventId}]", ex));
+ catch (Exception ex) {
+ Logger.LogError(ex, "One or more handlers threw while processing event [{EventId}]", domainEvent.EventId);
}
List failures = executions.SelectMany(this.GetFailures).ToList();
@@ -123,14 +120,14 @@ public async Task PostEventAsync([FromBody] Object request,
});
}
- Logger.LogWarning($"Finished processing event - ID [{domainEvent.EventId}]");
+ Logger.LogWarning("Finished processing event - ID [{EventId}]", domainEvent.EventId);
return Results.Ok();
}
catch (Exception ex)
{
String domainEventData = StringSerialiser.Serialise(domainEvent);
- Logger.LogError(new Exception($" Failed to Process Event, Event Data received [{domainEventData}]", ex));
+ Logger.LogError(ex,"Failed to Process Event Id {EventId}, Event Data received [{EventData}]", domainEvent.EventId, domainEventData);
throw;
}
@@ -157,7 +154,7 @@ private void Callback(CancellationToken cancellationToken,
{
if (cancellationToken.IsCancellationRequested) //I think this would always be true anyway
{
- Logger.LogInformation($"Cancel request for EventId {eventId}");
+ Logger.LogInformation("Cancel request for EventId {EventId}", eventId);
cancellationToken.ThrowIfCancellationRequested();
}
}
diff --git a/TransactionProcessor/Extensions.cs b/TransactionProcessor/Extensions.cs
index be00b29c..0c71934d 100644
--- a/TransactionProcessor/Extensions.cs
+++ b/TransactionProcessor/Extensions.cs
@@ -1,5 +1,6 @@
using JasperFx.Core;
using MediatR;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using SimpleResults;
using System.IO;
using TransactionProcessor.Aggregates;
@@ -24,6 +25,7 @@ namespace TransactionProcessor
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+ using System.IO.Abstractions;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -38,10 +40,10 @@ public static class Extensions {
String logMessage = $"{subType} - {message}";
switch (tt) {
case TraceEventType.Critical:
- Logger.LogCritical(new Exception(logMessage));
+ Logger.LogCritical(logMessage);
break;
case TraceEventType.Error:
- Logger.LogError(new Exception(logMessage));
+ Logger.LogError(logMessage);
break;
case TraceEventType.Warning:
Logger.LogWarning(logMessage);
@@ -124,7 +126,8 @@ public StatementFilePollerService(IMediator mediator, IConfiguration configurati
public void Start() {
foreach (FileProfile fileProfile in this.FileProfiles) {
- Logger.LogWarning($"File Profile: {fileProfile.Name} Listening on Folder: [{fileProfile.ListeningDirectory}] IsEnabled: {fileProfile.IsEnabled}");
+ String logMessage = $"Listening on Folder: [{fileProfile.ListeningDirectory}] IsEnabled: {fileProfile.IsEnabled}";
+ Logger.LogWarning("File Profile: {FileProfileName} " + logMessage, fileProfile.Name);
Directory.CreateDirectory(fileProfile.ListeningDirectory);
FileSystemWatcher fileSystemWatcher = new FileSystemWatcher
@@ -148,7 +151,7 @@ private void FileHandler(FileSystemEventArgs e, FileProfile fileProfile)
String failedFolder = Path.Combine(fileProfile.ListeningDirectory, "failed");
try {
- Logger.LogInformation($"File detected on profile {fileProfile.Name} File name [{e.Name}]");
+ Logger.LogInformation("File detected on profile {FileProfileName} File name [{FileName}]", fileProfile.Name, e.Name);
// Make sure the file is not locked by another process
await using (FileStream stream = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.None)) {
@@ -186,14 +189,14 @@ private void FileHandler(FileSystemEventArgs e, FileProfile fileProfile)
String failedFilePath = Path.Combine(failedFolder, e.Name);
File.Move(e.FullPath, failedFilePath);
// Log the error
- Logger.LogWarning($"Failed to process file [{e.FullPath}]: {result.Message}");
+ Logger.LogWarning("Failed to process file [{FileName}]: " + result.Message, e.FullPath);
}
else {
// Move the file to the processed folder
String processedFilePath = Path.Combine(processedFolder, e.Name);
File.Move(e.FullPath, processedFilePath);
// Log success
- Logger.LogInformation($"Successfully processed file [{e.FullPath}]");
+ Logger.LogInformation("Successfully processed file [{FileName}]", e.FullPath);
}
}
catch (Exception ex) {
@@ -202,8 +205,7 @@ private void FileHandler(FileSystemEventArgs e, FileProfile fileProfile)
String failedFilePath = Path.Combine(failedFolder, e.Name);
File.Move(e.FullPath, failedFilePath);
// Log the error
- Console.Error.WriteLine($"Failed to process file [{e.FullPath}]: {ex.Message}");
- Logger.LogError($"Failed to process file [{e.FullPath}]", ex);
+ Logger.LogError(ex, "Failed to process file [{FileName}]", e.FullPath);
}
});
}
@@ -243,30 +245,30 @@ internal async Task OperatorLogonAsync(String operatorId, CancellationToken canc
try {
Func resolver = this.OperatorProxyResolver;
if (resolver == null) {
- Logger.LogWarning($"Auto logon for operator Id [{operatorId}] skipped because no operator proxy resolver was registered");
+ Logger.LogWarning("Auto logon for operator Id [{OperatorId}] skipped because no operator proxy resolver was registered", operatorId);
return;
}
IOperatorProxy proxy = resolver(operatorId);
if (proxy == null) {
- Logger.LogWarning($"Auto logon for operator Id [{operatorId}] skipped because no operator proxy was resolved");
+ Logger.LogWarning("Auto logon for operator Id [{OperatorId}] skipped because no operator proxy was resolved", operatorId);
return;
}
Result logonResult = await proxy.ProcessLogonMessage(cancellationToken);
if (logonResult.IsSuccess) {
- Logger.LogInformation($"Auto logon for operator Id [{operatorId}] status [{logonResult.Data.IsSuccessful}]");
+ Logger.LogInformation("Auto logon for operator Id [{OperatorId}] status [{" + logonResult.Data.IsSuccessful + "}]", operatorId);
return;
}
- Logger.LogWarning($"Auto logon for operator Id [{operatorId}] status [{logonResult.Message}]");
+ Logger.LogWarning("Auto logon for operator Id [{OperatorId}] status [{" + logonResult.Message + "}]", operatorId);
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.Unavailable) {
- Logger.LogWarning($"Auto logon for operator Id [{operatorId}] deferred because the operator gRPC service is unavailable: {ex.Status.Detail}");
+ Logger.LogWarning("Auto logon for operator Id [{operatorId}] deferred because the operator gRPC service is unavailable: " + ex.Status.Detail, operatorId);
}
catch (Exception ex) {
- Logger.LogError(new Exception($"Auto logon for operator Id [{operatorId}] failed", ex));
+ Logger.LogError(ex, "Auto logon for operator Id [{OperatorId}] failed", operatorId);
}
}
}
diff --git a/TransactionProcessor/Program.cs b/TransactionProcessor/Program.cs
index c91ef077..8ce9d0f7 100644
--- a/TransactionProcessor/Program.cs
+++ b/TransactionProcessor/Program.cs
@@ -77,7 +77,9 @@ public static WebApplication BuildApplication(string[] args)
});
WebApplication app = builder.Build();
- Logger.Initialise(app.Services.GetRequiredService().CreateLogger("TransactionProcessor"));
+ LogManager.Setup().LoadConfigurationFromFile("NLog.config");
+ NLog.Logger logger = LogManager.GetLogger("TransactionProcessor");
+ Shared.Logger.Logger.Initialise(logger, "TransactionProcessor");
configuration.LogConfiguration(Logger.LogWarning);
StringSerialiser.Initialise(app.Services.GetRequiredService());
TypeProvider.LoadDomainEventsTypeDynamically();
diff --git a/TransactionProcessor/nlog.config b/TransactionProcessor/nlog.config
index 96828f11..4ab07db7 100644
--- a/TransactionProcessor/nlog.config
+++ b/TransactionProcessor/nlog.config
@@ -11,14 +11,22 @@
archiveNumbering="Sequence"
concurrentWrites="true"
maxArchiveFiles="2"/>
-
+
+
+
+
+
+
+
+
@@ -33,15 +41,7 @@
s
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file