DEV Community

Korir Moses
Korir Moses

Posted on

Effective Logging with ILogger in USSD Banking Applications: A .NET Approach

Introduction
Logging is a critical component of any robust software system, especially in banking applications where tracking every transaction and system event is crucial. In .NET applications, ILogger provides a powerful, flexible logging mechanism that can be instrumental in monitoring, debugging, and maintaining USSD banking systems.
Why Logging Matters in USSD Applications
USSD (Unstructured Supplementary Service Data) banking applications operate in real-time, high-stakes environments where:

Every transaction must be traceable
System errors can have significant financial implications
Compliance and audit requirements are stringent

ILogger: Core Concepts and Implementation

public class UssdTransactionService
{
    private readonly ILogger<UssdTransactionService> _logger;

    public UssdTransactionService(ILogger<UssdTransactionService> logger)
    {
        _logger = logger;
    }

    public TransactionResult ProcessTransaction(TransactionRequest request)
    {
        try
        {
            // Log transaction initiation with correlation ID
            using (_logger.BeginScope("CorrelationId:{CorrelationId}", Guid.NewGuid()))
            {
                // Log transaction start with sensitive information masked
                _logger.LogInformation(
                    "Transaction initiated for account ending in {AccountSuffix}", 
                    request.AccountNumber?.Substring(request.AccountNumber.Length - 4)
                );

                // Validate transaction
                if (!ValidateTransaction(request))
                {
                    _logger.LogWarning(
                        "Transaction validation failed for account {AccountSuffix}", 
                        request.AccountNumber?.Substring(request.AccountNumber.Length - 4)
                    );
                    return TransactionResult.Failed();
                }

                // Process transaction
                var result = ExecuteTransaction(request);

                // Log transaction outcome
                if (result.Success)
                {
                    _logger.LogInformation(
                        "Transaction successful for account {AccountSuffix}. Amount: {Amount}", 
                        request.AccountNumber?.Substring(request.AccountNumber.Length - 4),
                        result.Amount
                    );
                }
                else
                {
                    _logger.LogError(
                        "Transaction failed for account {AccountSuffix}. Reason: {FailureReason}", 
                        request.AccountNumber?.Substring(request.AccountNumber.Length - 4),
                        result.FailureReason
                    );
                }

                return result;
            }
        }
        catch (Exception ex)
        {
            // Critical error logging
            _logger.LogCritical(
                ex, 
                "Unhandled exception in transaction processing for account {AccountSuffix}", 
                request.AccountNumber?.Substring(request.AccountNumber.Length - 4)
            );

            return TransactionResult.SystemError();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Logging Configuration in Startup

public void ConfigureServices(IServiceCollection services)
{
    services.AddLogging(configure => 
    {
        configure.AddConsole();
        configure.AddDebug();

        // Configure log levels
        configure.SetMinimumLevel(LogLevel.Information);
    });

    // Add structured logging with Serilog
    services.AddLogging(configure => 
    {
        configure.AddSerilog(new LoggerConfiguration()
            .WriteTo.File("logs/ussd-banking-.txt", rollingInterval: RollingInterval.Day)
            .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200"))
            {
                AutoRegisterTemplate = true,
            })
            .CreateLogger()
        );
    });
}
Enter fullscreen mode Exit fullscreen mode

Best Practices for USSD Application Logging

  1. Sensitive Data Protection

Always mask sensitive information
Never log full account numbers or personal details
Use partial masking techniques

  1. Comprehensive Context Logging

Include correlation IDs
Log contextual information without exposing sensitive data
Track user journey through the application

  1. Log Level Strategy

Trace: Detailed system events (rarely used)
Debug: Detailed information for debugging
Information: General application flow
Warning: Potential issues that don't stop execution
Error: Handled exceptions
Critical: Unhandled exceptions or system-critical failures

Advanced Logging Techniques
Correlation and Tracing

public async Task<TransactionResult> ProcessTransactionWithTracing(TransactionRequest request)
{
    var correlationId = Guid.NewGuid().ToString();

    using (_logger.BeginScope(new Dictionary<string, object>
    {
        ["CorrelationId"] = correlationId,
        ["UserId"] = request.UserId
    }))
    {
        // Transaction processing logic
        _logger.LogInformation("Transaction trace started");

        // Simulate async processing
        await Task.Delay(100);

        _logger.LogInformation("Transaction completed");
    }
}
Enter fullscreen mode Exit fullscreen mode

Logging Providers to Consider

Console Logging
File Logging
Elasticsearch
Azure Application Insights
Serilog
NLog

Performance Considerations

Use structured logging
Implement log filtering
Consider asynchronous logging
Use sampling for high-volume applications

Conclusion
Effective logging with ILogger in USSD banking applications is not just about recording events—it's about creating a comprehensive, secure, and performant tracking mechanism that supports system reliability, security, and auditability.

Top comments (0)