Fluent Syntax
ByteHide Logger supports fluent syntax, allowing you to chain multiple logging features in a single, readable call. This enables you to combine metadata, context, tags, correlation IDs, and logging levels seamlessly. Note that global configuration methods are not fluent and should be called separately.
Basic Fluent Chaining
Single Feature Chaining
// Metadata only
Log.WithMetadata("executionTime", 450)
.Info("Operation completed");
// Context only
Log.WithContext("orderId", order.Id)
.Error("Order validation failed");
// Tags only
Log.WithTags("database", "performance")
.Warn("Query execution time exceeded");
// Correlation ID only
Log.WithCorrelationId("req-12345")
.Info("Request processing started");
Multiple Feature Chaining
// Metadata + Context + Tags
Log.WithMetadata("responseTime", 2500)
.WithContext("apiEndpoint", "/api/orders")
.WithTags("api", "performance", "external")
.Warn("API response time exceeded threshold");
// Context + Tags + Correlation ID
Log.WithCorrelationId("req-abc123")
.WithContext("action", "login")
.WithTags("authentication", "security")
.Info("User login successful");
// All features combined
Log.WithCorrelationId("req-def456")
.WithMetadata("processingTimeMs", 850)
.WithContext("operation", "OrderProcessing")
.WithTags("orders", "business-logic")
.Info("Order processing completed");
Practical Examples
// Database operations
Log.WithMetadata("executionTimeMs", 1250)
.WithMetadata("rowsAffected", 150)
.WithContext("sqlQuery", "SELECT * FROM Orders WHERE Status = 'Pending'")
.WithTags("database", "performance")
.Warn("Slow query detected");
// API operations
Log.WithCorrelationId("req-abc123")
.WithMetadata("responseTimeMs", 2500)
.WithContext("endpoint", "/api/payments")
.WithTags("api", "external", "timeout")
.Error("External API timeout");
// Business operations
Log.WithMetadata("orderValue", 299.99m)
.WithContext("orderId", order.Id)
.WithContext("paymentMethod", "CreditCard")
.WithTags("orders", "payment")
.Info("Payment processing started");
Error Handling
try
{
await ProcessOrderAsync(order);
}
catch (PaymentException ex)
{
Log.WithCorrelationId("req-123")
.WithMetadata("errorCode", ex.ErrorCode)
.WithContext("orderId", order.Id)
.WithContext("paymentMethod", order.PaymentMethod)
.WithTags("payment", "error")
.Error("Payment processing failed", ex);
}
catch (Exception ex)
{
Log.WithCorrelationId("req-123")
.WithContext("orderId", order.Id)
.WithTags("orders", "error", "critical")
.Error("Unexpected error during order processing", ex);
}
Performance Monitoring
var stopwatch = Stopwatch.StartNew();
var result = await ProcessOrderAsync(order);
stopwatch.Stop();
Log.WithCorrelationId("req-123")
.WithMetadata("executionTimeMs", stopwatch.ElapsedMilliseconds)
.WithContext("operation", "ProcessOrder")
.WithContext("orderId", order.Id)
.WithTags("performance", "orders")
.Info("Order processing completed");
Non-Fluent Global Methods
The following global configuration methods are not fluent and must be called separately:
// ✅ Global configuration - call separately, not in chains
Log.SetProjectToken("your-project-token");
Log.AddMetaContext("AppVersion", "1.2.3");
Log.Identify(new AuthUser { Id = "123", Email = "user@example.com" });
Log.Disable();
Log.Enable();
Log.Logout();
Log.Reset();
// ✅ Then use fluent syntax for individual logs
Log.WithCorrelationId("req-123")
.WithMetadata("processingTime", 500)
.WithContext("operation", "UserLogin")
.WithTags("authentication", "success")
.Info("User authenticated successfully");
Important
Global methods like SetProjectToken
, AddMetaContext
, Identify
, Disable
, Enable
, Logout
, and Reset
are not chainable. These configure the logger globally and should be called independently, typically during application startup or specific events.
Best Practices
Fluent Syntax Best Practices
- Chain logically: Group related metadata and context together
- Use meaningful keys: Make metadata and context keys descriptive
- Tag consistently: Establish tagging conventions across your application
- Include relevant timing: Add execution times for performance tracking
- Combine with correlation IDs: Use correlation IDs for request tracking
- Don't over-chain: Keep chains readable - break into multiple lines if needed
- Separate global config: Use global methods independently, not in fluent chains
Common Patterns Summary
// Complete fluent pattern with correlation ID
Log.WithCorrelationId(requestId)
.WithMetadata("executionTimeMs", elapsed)
.WithContext("operation", operationName)
.WithTags("performance", "monitoring")
.Info("Operation completed");
// Error handling pattern
Log.WithCorrelationId(requestId)
.WithMetadata("errorCode", ex.ErrorCode)
.WithMetadata("retryAttempt", 2)
.WithContext("operation", "PaymentProcessing")
.WithTags("error", "payment", "critical")
.Error("Payment failed");
// API request pattern
Log.WithCorrelationId(requestId)
.WithMetadata("responseTimeMs", responseTime)
.WithMetadata("statusCode", 200)
.WithContext("endpoint", endpoint)
.WithContext("httpMethod", "POST")
.WithTags("api", "external")
.Info("API call completed");
// Database operation pattern
Log.WithMetadata("rowsAffected", rows)
.WithMetadata("executionTimeMs", executionTime)
.WithContext("sqlQuery", query)
.WithContext("tableName", "Orders")
.WithTags("database", "performance")
.Debug("Query executed");
Next Steps
- Basic Logging - Learn the fundamental logging methods
- Exception Handling - Master exception logging with Error and Critical methods
- Metadata & Context - Deep dive into metadata and context
- Tags - Master the tagging system
- Correlation IDs - Track requests across services