DEEP-28, DEEP-29 Metrics added

This commit is contained in:
Andrey Shabarshov 2023-07-11 16:37:24 +01:00
parent 45cbc234ce
commit f3979769e2
4 changed files with 70 additions and 1 deletions

View File

@ -14,10 +14,13 @@ GlobalContext.Properties["LOGS_ROOT"] = Environment.GetEnvironmentVariable("LOGS
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
builder.Logging.AddLog4Net("log4net.config");
var meters = new CustomMetrics();
builder.Services.AddOpenTelemetry()
.WithMetrics(options =>
{
options
.AddMeter(meters.MetricName)
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation()
@ -50,6 +53,7 @@ builder.Services
.AddSingleton<ISecurityService, SecurityService>()
.AddSingleton<IPaymentGateway, PaymentGateway>()
.AddSingleton<TransactionMonitoring>()
.AddSingleton<CustomMetrics>()
;
var app = builder.Build();

View File

@ -20,6 +20,7 @@
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="6.1.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.15.0" />
<PackageReference Include="MongoDB.Driver" Version="2.15.0" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.5.1" />
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.5.0-rc.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="0.5.0-beta.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.0" />

View File

@ -0,0 +1,39 @@
using System.Diagnostics.Metrics;
namespace QRBee.Api.Services
{
public class CustomMetrics
{
private Counter<int> MerchantRequestCounter { get; }
private Counter<int> MerchantResponseCounter { get; }
private Counter<int> SucceededTransactionsCounter { get; }
private Counter<int> FailedTransactionsCounter { get; }
private Counter<long> TotalCreditCardCheckTime { get; }
private Counter<long> TotalPaymentTime { get; }
public string MetricName { get; }
public CustomMetrics(string meterName = "QRBeeMetrics") {
var meter = new Meter(meterName);
MetricName = meterName;
MerchantRequestCounter = meter.CreateCounter<int>("merchant-requests", description: "Merchant has sent a request");
MerchantResponseCounter = meter.CreateCounter<int>("merchant-responses");
SucceededTransactionsCounter = meter.CreateCounter<int>("transaction-succeeded", description: "Transaction succeeded");
FailedTransactionsCounter = meter.CreateCounter<int>("transaction-failed", description: "Transaction failed");
TotalCreditCardCheckTime = meter.CreateCounter<long>("Total-credit-card-check-time","msec");
TotalPaymentTime = meter.CreateCounter<long>("Total-payment-time","msec");
}
public void AddMerchantRequest() => MerchantRequestCounter.Add(1);
public void AddMerchantResponse() => MerchantResponseCounter.Add(1);
public void AddSucceededTransaction() => SucceededTransactionsCounter.Add(1);
public void AddFailedTransaction() => FailedTransactionsCounter.Add(1);
public void AddTotalCreditCardCheckTime(long milliseconds) => TotalCreditCardCheckTime.Add(milliseconds);
public void AddTotalPaymentTime(long milliseconds) => TotalPaymentTime.Add(milliseconds);
}
}

View File

@ -1,6 +1,7 @@
using QRBee.Api.Services.Database;
using QRBee.Core.Data;
using QRBee.Core.Security;
using System.Diagnostics;
using System.Globalization;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
@ -22,10 +23,12 @@ namespace QRBee.Api.Services
private readonly TransactionMonitoring _transactionMonitoring;
private static readonly object _lock = new ();
private readonly CustomMetrics _customMetrics;
private const int MaxNameLength = 512;
private const int MaxEmailLength = 512;
public QRBeeAPIService(IStorage storage, ISecurityService securityService, IPrivateKeyHandler privateKeyHandler, IPaymentGateway paymentGateway, ILogger<QRBeeAPIService> logger, TransactionMonitoring transactionMonitoring)
public QRBeeAPIService(IStorage storage, ISecurityService securityService, IPrivateKeyHandler privateKeyHandler, IPaymentGateway paymentGateway, ILogger<QRBeeAPIService> logger, TransactionMonitoring transactionMonitoring, CustomMetrics metrics)
{
_storage = storage;
_securityService = securityService;
@ -34,6 +37,8 @@ namespace QRBee.Api.Services
_logger = logger;
_transactionMonitoring = transactionMonitoring;
Init(_privateKeyHandler);
_customMetrics = metrics;
}
private static void Init(IPrivateKeyHandler privateKeyHandler)
@ -143,6 +148,9 @@ namespace QRBee.Api.Services
try
{
_customMetrics.AddMerchantRequest();
//1. Check payment request parameters for validity
ValidateTransaction(value);
var tid = value.ClientResponse.MerchantRequest.MerchantTransactionId;
@ -168,13 +176,20 @@ namespace QRBee.Api.Services
_logger.LogInformation($"Transaction=\"{tid}\" Fully validated");
//5. Decrypt client card data
var creditCardCheckTime = Stopwatch.StartNew();
var clientCardData = DecryptClientData(value.ClientResponse.EncryptedClientCardData);
//6. Check client card data for validity
await CheckClientCardData(clientCardData, value.ClientResponse.MerchantRequest.MerchantTransactionId);
_logger.LogInformation($"Transaction=\"{tid}\" Client card data validated");
var milliseconds = creditCardCheckTime.ElapsedMilliseconds;
creditCardCheckTime.Stop();
_customMetrics.AddTotalCreditCardCheckTime(milliseconds);
//7. Register preliminary transaction record with expiry of one minute
var paymentTime = Stopwatch.StartNew();
var info = Convert(value);
info.Status = TransactionInfo.TransactionStatus.Pending;
@ -184,22 +199,32 @@ namespace QRBee.Api.Services
//8. Send client card data to a payment gateway
var gatewayResponse = await _paymentGateway.Payment(info, clientCardData);
milliseconds = paymentTime.ElapsedMilliseconds;
paymentTime.Stop();
_customMetrics.AddTotalPaymentTime(milliseconds);
//9. Record transaction with result
if (gatewayResponse.Success)
{
info.Status=TransactionInfo.TransactionStatus.Succeeded;
info.GatewayTransactionId=gatewayResponse.GatewayTransactionId;
_customMetrics.AddSucceededTransaction();
}
else
{
info.Status = TransactionInfo.TransactionStatus.Rejected;
info.RejectReason = gatewayResponse.ErrorMessage;
_customMetrics.AddFailedTransaction();
}
await _storage.UpdateTransaction(info);
_logger.LogInformation($"Transaction=\"{tid}\" complete Status=\"{info.Status}\"");
//10. Make response for merchant
var response = MakePaymentResponse(value, info.TransactionId ?? "", gatewayResponse.GatewayTransactionId ?? "", info.Status==TransactionInfo.TransactionStatus.Succeeded, info.RejectReason);
_customMetrics.AddMerchantResponse();
return response;
}
catch (Exception e)