/

Basic Logging

ByteHide Logger provides six logging levels with simple, intuitive methods. Each level serves different purposes and accepts various parameters for flexible logging. Additionally, ByteHide Logger supports fluent syntax, allowing you to chain multiple features like metadata, context, and tags in a single log call.

Logging Methods Overview

MethodPurposeParameters
Log.Trace(message)Most detailed diagnostic informationstring message
Log.Debug(message)Detailed diagnostic informationstring message
Log.Info(message)General information messagesstring message
Log.Warn(message, exception)Warning messagesstring message, Exception exception = null
Log.Error(message, context, exception)Error messagesstring message, object context, Exception exception = null
Log.Critical(message, exception)Critical errorsstring message, Exception exception = null

Basic Logging Methods

Trace Level

Use for the most detailed diagnostic information:

Log.Trace("Entering method ProcessOrder");
Log.Trace("Processing item 1 of 10");
Log.Trace("Database connection established");

Debug Level

Use for detailed diagnostic information during development:

Log.Debug("User authentication started");
Log.Debug("Cache miss for key: user_123");
Log.Debug("API response received in 250ms");

Info Level

Use for general information about application flow:

Log.Info("Application started successfully");
Log.Info("User logged in");
Log.Info("Order processed successfully");

Advanced Logging Methods

Warn Level

Use for potential issues that don't stop execution:

// Simple warning
Log.Warn("API rate limit approaching");

// Warning with exception
try
{
    // Some operation
}
catch (Exception ex)
{
    Log.Warn("Non-critical operation failed, using fallback", ex);
}

Error Level

Use for errors that affect functionality:

// Error with context and exception
try
{
    ProcessOrder(orderId);
}
catch (Exception ex)
{
    Log.Error("Failed to process order", new { OrderId = orderId, UserId = userId }, ex);
}

// Error with context only
Log.Error("Invalid configuration detected", new { ConfigFile = "appsettings.json", Section = "Database" });

// Error with exception only
Log.Error("Database connection failed", null, ex);

Critical Level

Use for critical errors that may cause application termination:

// Critical error with exception
try
{
    InitializeDatabase();
}
catch (Exception ex)
{
    Log.Critical("Failed to initialize database - application cannot continue", ex);
    Environment.Exit(1);
}

// Critical error without exception
Log.Critical("Out of memory - shutting down");

Fluent Syntax

ByteHide Logger supports fluent syntax, allowing you to combine multiple features in a single, readable chain:

// Combine metadata, context, and tags
Log.WithMetadata("executionTimeMs", 1250)
   .WithContext("sqlQuery", "SELECT * FROM Orders WHERE Status = 'Pending'")
   .WithTags("database", "performance")
   .Warn("Slow database query detected");

// User context with tags
Log.WithContext("orderId", order.Id)
   .WithContext("customerId", order.CustomerId)
   .WithTags("orders", "critical")
   .Error("Order processing failed");

// Multiple metadata and tags
Log.WithMetadata("attemptNumber", 3)
   .WithMetadata("responseCode", 503)
   .WithContext("apiEndpoint", "/api/payments")
   .WithTags("api", "external", "retry")
   .Warn("External API retry limit reached");

Learn More About Fluent Syntax

For comprehensive examples and advanced patterns, see Fluent Syntax - Learn how to combine all logging features effectively.

Context Objects

The Error method accepts an object context parameter for structured logging:

Simple Context

Log.Error("Payment processing failed", new { 
    Amount = 99.99, 
    Currency = "USD", 
    PaymentMethod = "CreditCard" 
}, ex);

Complex Context

var orderContext = new
{
    OrderId = order.Id,
    CustomerId = order.CustomerId,
    Items = order.Items.Select(i => new { i.ProductId, i.Quantity, i.Price }),
    TotalAmount = order.Total,
    PaymentMethod = order.PaymentMethod,
    ShippingAddress = new
    {
        order.ShippingAddress.Street,
        order.ShippingAddress.City,
        order.ShippingAddress.Country
    }
};

Log.Error("Order processing failed", orderContext, ex);

Custom Objects as Context

public class UserContext
{
    public string UserId { get; set; }
    public string UserName { get; set; }
    public string Role { get; set; }
    public DateTime LastLogin { get; set; }
}

var userContext = new UserContext
{
    UserId = "user_123",
    UserName = "john.doe",
    Role = "Admin",
    LastLogin = DateTime.UtcNow.AddHours(-2)
};

Log.Error("User action failed", userContext, ex);

Exception Logging

Exception with Context

try
{
    var result = await ProcessPaymentAsync(paymentRequest);
}
catch (PaymentException ex)
{
    Log.Error("Payment processing failed", new 
    { 
        TransactionId = paymentRequest.TransactionId,
        Amount = paymentRequest.Amount,
        ErrorCode = ex.ErrorCode 
    }, ex);
}
catch (Exception ex)
{
    Log.Critical("Unexpected error during payment processing", ex);
}

Exception Only

try
{
    ConnectToDatabase();
}
catch (SqlException ex)
{
    Log.Warn("Database connection retry needed", ex);
}
catch (TimeoutException ex)
{
    Log.Error("Database connection timeout", null, ex);
}

Practical Examples

Service Layer Logging

public class OrderService
{
    public async Task<Order> CreateOrderAsync(CreateOrderRequest request)
    {
        Log.Info("Creating new order");
        Log.Debug("Validating order request");
        
        try
        {
            var order = new Order(request);
            Log.Trace("Order object created");
            
            await _repository.SaveAsync(order);
            Log.Info("Order created successfully");
            
            return order;
        }
        catch (ValidationException ex)
        {
            Log.Warn("Order validation failed", ex);
            throw;
        }
        catch (Exception ex)
        {
            Log.Error("Failed to create order", new 
            { 
                CustomerId = request.CustomerId,
                ItemCount = request.Items?.Count ?? 0 
            }, ex);
            throw;
        }
    }
}

Controller Logging

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    [HttpPost]
    public async Task<IActionResult> CreateUser(CreateUserRequest request)
    {
        Log.Info("User creation requested");
        
        try
        {
            var user = await _userService.CreateUserAsync(request);
            Log.Info("User created successfully");
            
            return Ok(user);
        }
        catch (DuplicateUserException ex)
        {
            Log.Warn("Duplicate user creation attempt", ex);
            return Conflict("User already exists");
        }
        catch (Exception ex)
        {
            Log.Error("User creation failed", new 
            { 
                Email = request.Email,
                RequestId = HttpContext.TraceIdentifier 
            }, ex);
            
            return StatusCode(500, "Internal server error");
        }
    }
}

Background Service Logging

public class EmailProcessingService : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        Log.Info("Email processing service started");
        
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                Log.Trace("Checking for pending emails");
                var emails = await GetPendingEmailsAsync();
                
                if (emails.Any())
                {
                    Log.Debug($"Processing {emails.Count} pending emails");
                    
                    foreach (var email in emails)
                    {
                        await ProcessEmailAsync(email);
                    }
                    
                    Log.Info($"Processed {emails.Count} emails successfully");
                }
                
                await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
            }
            catch (Exception ex)
            {
                Log.Critical("Email processing service encountered critical error", ex);
                await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
            }
        }
        
        Log.Info("Email processing service stopped");
    }
}

Best Practices

Level Selection Guidelines

When to Use Each Level

  • Trace: Method entry/exit, loop iterations, detailed flow
  • Debug: Variable values, cache hits/misses, intermediate results
  • Info: Application milestones, user actions, business events
  • Warn: Recoverable errors, deprecated usage, performance issues
  • Error: Exceptions, failed operations, data inconsistencies
  • Critical: System failures, security breaches, unrecoverable errors

Context Best Practices

// ✅ Good - Structured context
Log.Error("Order processing failed", new 
{ 
    OrderId = order.Id,
    Stage = "Payment",
    Amount = order.Total 
}, ex);

// ❌ Avoid - String concatenation
Log.Error($"Order {order.Id} processing failed at Payment stage with amount {order.Total}", null, ex);

// ✅ Good - Relevant context only
Log.Error("Database query failed", new { Query = "GetUserById", UserId = userId }, ex);

// ❌ Avoid - Too much context
Log.Error("Database query failed", entireUserObject, ex);

Performance Considerations

// ✅ Efficient - Simple messages for high-frequency logs
Log.Trace("Method entry");

// ✅ Efficient - Avoid expensive operations in log calls
Log.Debug("Cache lookup completed");

// ❌ Avoid - Expensive operations
Log.Debug($"User data: {JsonSerializer.Serialize(complexUserObject)}");

Next Steps

Now that you understand basic logging, explore these advanced features:

Previous
Disable Logging