🔷 📊 Performance Monitoring - TuskLang for C# - "Monitoring Mastery"
📊 Performance Monitoring - TuskLang for C# - "Monitoring Mastery"
Master performance monitoring with TuskLang in your C# applications!
Performance monitoring is essential for maintaining application health and optimizing performance. This guide covers metrics collection, performance profiling, monitoring dashboards, and real-world monitoring scenarios for TuskLang in C# environments.
📈 Monitoring Philosophy
"We Don't Bow to Any King"
- Monitor everything - Track all performance metrics - Real-time alerts - Get notified of issues immediately - Historical analysis - Understand performance trends - Proactive optimization - Optimize before problems occur - Business metrics - Monitor what matters to users📊 Metrics Collection
Example: Metrics Collection Service
// MetricsCollectionService.cs
using System.Diagnostics;public class MetricsCollectionService
{
private readonly TuskLang _parser;
private readonly ILogger<MetricsCollectionService> _logger;
private readonly Dictionary<string, Metric> _metrics;
private readonly Timer _collectionTimer;
public MetricsCollectionService(ILogger<MetricsCollectionService> logger)
{
_parser = new TuskLang();
_logger = logger;
_metrics = new Dictionary<string, Metric>();
LoadMetricsConfiguration();
_collectionTimer = new Timer(CollectMetrics, null, TimeSpan.Zero, TimeSpan.FromSeconds(30));
}
private void LoadMetricsConfiguration()
{
var config = _parser.ParseFile("config/metrics.tsk");
var metricDefinitions = config["metrics"] as Dictionary<string, object>;
foreach (var metric in metricDefinitions ?? new Dictionary<string, object>())
{
var metricName = metric.Key;
var metricConfig = metric.Value as Dictionary<string, object>;
if (metricConfig != null)
{
_metrics[metricName] = new Metric
{
Name = metricName,
Type = metricConfig["type"].ToString(),
Description = metricConfig["description"].ToString(),
Unit = metricConfig["unit"].ToString()
};
}
}
_logger.LogInformation("Loaded {Count} metric definitions", _metrics.Count);
}
private void CollectMetrics(object? state)
{
try
{
// Collect system metrics
CollectSystemMetrics();
// Collect application metrics
CollectApplicationMetrics();
// Collect custom metrics
CollectCustomMetrics();
_logger.LogDebug("Metrics collection completed");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during metrics collection");
}
}
private void CollectSystemMetrics()
{
var process = Process.GetCurrentProcess();
RecordMetric("cpu_usage_percent", process.TotalProcessorTime.TotalMilliseconds / Environment.ProcessorCount);
RecordMetric("memory_usage_mb", process.WorkingSet64 / 1024 / 1024);
RecordMetric("thread_count", process.Threads.Count);
RecordMetric("handle_count", process.HandleCount);
}
private void CollectApplicationMetrics()
{
var gc = GC.GetGCMemoryInfo();
RecordMetric("heap_size_mb", gc.HeapSizeBytes / 1024 / 1024);
RecordMetric("gc_collections", GC.CollectionCount(0) + GC.CollectionCount(1) + GC.CollectionCount(2));
RecordMetric("active_connections", GetActiveConnections());
RecordMetric("request_queue_length", GetRequestQueueLength());
}
private void CollectCustomMetrics()
{
// Collect business-specific metrics
RecordMetric("active_users", GetActiveUserCount());
RecordMetric("database_connections", GetDatabaseConnectionCount());
RecordMetric("cache_hit_rate", GetCacheHitRate());
}
public void RecordMetric(string name, double value)
{
if (_metrics.ContainsKey(name))
{
var metric = _metrics[name];
metric.AddValue(value);
_logger.LogDebug("Recorded metric {MetricName}: {Value} {Unit}", name, value, metric.Unit);
}
}
public async Task<Dictionary<string, object>> GetMetricsSnapshotAsync()
{
var snapshot = new Dictionary<string, object>();
foreach (var metric in _metrics)
{
snapshot[metric.Key] = new Dictionary<string, object>
{
["current_value"] = metric.Value.CurrentValue,
["average_value"] = metric.Value.AverageValue,
["min_value"] = metric.Value.MinValue,
["max_value"] = metric.Value.MaxValue,
["unit"] = metric.Value.Unit,
["description"] = metric.Value.Description,
["last_updated"] = metric.Value.LastUpdated.ToString("yyyy-MM-dd HH:mm:ss")
};
}
return snapshot;
}
// Placeholder methods for metric collection
private int GetActiveConnections() => 42;
private int GetRequestQueueLength() => 15;
private int GetActiveUserCount() => 1250;
private int GetDatabaseConnectionCount() => 8;
private double GetCacheHitRate() => 0.85;
}
public class Metric
{
public string Name { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public string Unit { get; set; } = string.Empty;
public double CurrentValue { get; private set; }
public double AverageValue { get; private set; }
public double MinValue { get; private set; } = double.MaxValue;
public double MaxValue { get; private set; } = double.MinValue;
public int SampleCount { get; private set; }
public DateTime LastUpdated { get; private set; }
public void AddValue(double value)
{
CurrentValue = value;
MinValue = Math.Min(MinValue, value);
MaxValue = Math.Max(MaxValue, value);
if (SampleCount == 0)
{
AverageValue = value;
}
else
{
AverageValue = ((AverageValue * SampleCount) + value) / (SampleCount + 1);
}
SampleCount++;
LastUpdated = DateTime.UtcNow;
}
}
🔍 Performance Profiling
Example: Performance Profiling Service
// PerformanceProfilingService.cs
public class PerformanceProfilingService
{
private readonly TuskLang _parser;
private readonly ILogger<PerformanceProfilingService> _logger;
private readonly Dictionary<string, PerformanceProfile> _profiles;
public PerformanceProfilingService(ILogger<PerformanceProfilingService> logger)
{
_parser = new TuskLang();
_logger = logger;
_profiles = new Dictionary<string, PerformanceProfile>();
LoadProfilingConfiguration();
}
private void LoadProfilingConfiguration()
{
var config = _parser.ParseFile("config/profiling.tsk");
var profilingRules = config["profiling_rules"] as Dictionary<string, object>;
foreach (var rule in profilingRules ?? new Dictionary<string, object>())
{
var ruleName = rule.Key;
var ruleConfig = rule.Value as Dictionary<string, object>;
if (ruleConfig != null)
{
_profiles[ruleName] = new PerformanceProfile
{
Name = ruleName,
ThresholdMs = int.Parse(ruleConfig["threshold_ms"].ToString()),
Enabled = bool.Parse(ruleConfig["enabled"].ToString())
};
}
}
_logger.LogInformation("Loaded {Count} profiling rules", _profiles.Count);
}
public IDisposable CreateProfile(string operationName)
{
return new PerformanceScope(operationName, this);
}
public void RecordOperation(string operationName, long durationMs, Dictionary<string, object>? metadata = null)
{
if (!_profiles.ContainsKey(operationName))
{
return;
}
var profile = _profiles[operationName];
profile.RecordOperation(durationMs, metadata);
if (durationMs > profile.ThresholdMs)
{
_logger.LogWarning("Performance threshold exceeded for {OperationName}: {DurationMs}ms > {ThresholdMs}ms",
operationName, durationMs, profile.ThresholdMs);
}
}
public async Task<Dictionary<string, object>> GetPerformanceReportAsync()
{
var report = new Dictionary<string, object>();
foreach (var profile in _profiles)
{
report[profile.Key] = new Dictionary<string, object>
{
["total_operations"] = profile.Value.TotalOperations,
["average_duration_ms"] = profile.Value.AverageDuration,
["min_duration_ms"] = profile.Value.MinDuration,
["max_duration_ms"] = profile.Value.MaxDuration,
["threshold_exceeded_count"] = profile.Value.ThresholdExceededCount,
["threshold_ms"] = profile.Value.ThresholdMs,
["enabled"] = profile.Value.Enabled
};
}
return report;
}
}public class PerformanceScope : IDisposable
{
private readonly string _operationName;
private readonly PerformanceProfilingService _profilingService;
private readonly Stopwatch _stopwatch;
private readonly Dictionary<string, object> _metadata;
public PerformanceScope(string operationName, PerformanceProfilingService profilingService)
{
_operationName = operationName;
_profilingService = profilingService;
_stopwatch = Stopwatch.StartNew();
_metadata = new Dictionary<string, object>();
}
public void AddMetadata(string key, object value)
{
_metadata[key] = value;
}
public void Dispose()
{
_stopwatch.Stop();
_profilingService.RecordOperation(_operationName, _stopwatch.ElapsedMilliseconds, _metadata);
}
}
public class PerformanceProfile
{
public string Name { get; set; } = string.Empty;
public long ThresholdMs { get; set; }
public bool Enabled { get; set; }
public int TotalOperations { get; private set; }
public double AverageDuration { get; private set; }
public long MinDuration { get; private set; } = long.MaxValue;
public long MaxDuration { get; private set; }
public int ThresholdExceededCount { get; private set; }
public void RecordOperation(long durationMs, Dictionary<string, object>? metadata = null)
{
if (!Enabled) return;
TotalOperations++;
MinDuration = Math.Min(MinDuration, durationMs);
MaxDuration = Math.Max(MaxDuration, durationMs);
if (TotalOperations == 1)
{
AverageDuration = durationMs;
}
else
{
AverageDuration = ((AverageDuration * (TotalOperations - 1)) + durationMs) / TotalOperations;
}
if (durationMs > ThresholdMs)
{
ThresholdExceededCount++;
}
}
}
📊 Monitoring Dashboard
Example: Monitoring Dashboard Service
// MonitoringDashboardService.cs
public class MonitoringDashboardService
{
private readonly MetricsCollectionService _metricsService;
private readonly PerformanceProfilingService _profilingService;
private readonly TuskLang _parser;
private readonly ILogger<MonitoringDashboardService> _logger;
public MonitoringDashboardService(
MetricsCollectionService metricsService,
PerformanceProfilingService profilingService,
ILogger<MonitoringDashboardService> logger)
{
_metricsService = metricsService;
_profilingService = profilingService;
_parser = new TuskLang();
_logger = logger;
}
public async Task<Dictionary<string, object>> GetDashboardDataAsync()
{
var dashboard = new Dictionary<string, object>();
// System health
dashboard["system_health"] = await GetSystemHealthAsync();
// Performance metrics
dashboard["performance_metrics"] = await GetPerformanceMetricsAsync();
// Application metrics
dashboard["application_metrics"] = await GetApplicationMetricsAsync();
// Alerts
dashboard["alerts"] = await GetActiveAlertsAsync();
return dashboard;
}
private async Task<Dictionary<string, object>> GetSystemHealthAsync()
{
var health = new Dictionary<string, object>();
var metrics = await _metricsService.GetMetricsSnapshotAsync();
// CPU health
var cpuUsage = Convert.ToDouble(metrics["cpu_usage_percent"]);
health["cpu_health"] = new Dictionary<string, object>
{
["status"] = cpuUsage > 80 ? "Critical" : cpuUsage > 60 ? "Warning" : "Healthy",
["value"] = cpuUsage,
["threshold"] = 80
};
// Memory health
var memoryUsage = Convert.ToDouble(metrics["memory_usage_mb"]);
health["memory_health"] = new Dictionary<string, object>
{
["status"] = memoryUsage > 1000 ? "Critical" : memoryUsage > 500 ? "Warning" : "Healthy",
["value"] = memoryUsage,
["threshold"] = 1000
};
return health;
}
private async Task<Dictionary<string, object>> GetPerformanceMetricsAsync()
{
var performance = new Dictionary<string, object>();
var profilingReport = await _profilingService.GetPerformanceReportAsync();
foreach (var profile in profilingReport)
{
var profileData = profile.Value as Dictionary<string, object>;
if (profileData != null)
{
var avgDuration = Convert.ToDouble(profileData["average_duration_ms"]);
var threshold = Convert.ToInt64(profileData["threshold_ms"]);
performance[profile.Key] = new Dictionary<string, object>
{
["average_duration_ms"] = avgDuration,
["threshold_ms"] = threshold,
["status"] = avgDuration > threshold ? "Slow" : "Normal",
["total_operations"] = profileData["total_operations"]
};
}
}
return performance;
}
private async Task<Dictionary<string, object>> GetApplicationMetricsAsync()
{
var metrics = await _metricsService.GetMetricsSnapshotAsync();
var application = new Dictionary<string, object>();
// Active users
application["active_users"] = new Dictionary<string, object>
{
["current"] = Convert.ToInt32(metrics["active_users"]),
["trend"] = "increasing"
};
// Cache performance
var cacheHitRate = Convert.ToDouble(metrics["cache_hit_rate"]);
application["cache_performance"] = new Dictionary<string, object>
{
["hit_rate"] = cacheHitRate,
["status"] = cacheHitRate > 0.8 ? "Good" : cacheHitRate > 0.6 ? "Fair" : "Poor"
};
return application;
}
private async Task<List<Dictionary<string, object>>> GetActiveAlertsAsync()
{
var alerts = new List<Dictionary<string, object>>();
var metrics = await _metricsService.GetMetricsSnapshotAsync();
// Check for critical alerts
var cpuUsage = Convert.ToDouble(metrics["cpu_usage_percent"]);
if (cpuUsage > 90)
{
alerts.Add(new Dictionary<string, object>
{
["level"] = "Critical",
["message"] = $"CPU usage is critically high: {cpuUsage:F1}%",
["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")
});
}
var memoryUsage = Convert.ToDouble(metrics["memory_usage_mb"]);
if (memoryUsage > 1500)
{
alerts.Add(new Dictionary<string, object>
{
["level"] = "Warning",
["message"] = $"Memory usage is high: {memoryUsage:F0}MB",
["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")
});
}
return alerts;
}
}
🛠️ Real-World Monitoring Scenarios
- API performance: Monitor response times and throughput - Database performance: Monitor query performance and connection usage - Memory usage: Monitor memory consumption and garbage collection - Business metrics: Monitor user activity and business KPIs🧩 Best Practices
- Collect metrics at appropriate intervals - Set meaningful thresholds for alerts - Use correlation IDs for tracing - Monitor both technical and business metrics - Implement automated alerting🏁 You're Ready!
You can now: - Implement comprehensive metrics collection - Profile application performance - Create monitoring dashboards - Set up automated alerting
Next: Deployment Strategies
---
"We don't bow to any king" - Your monitoring mastery, your performance excellence, your observability power.
Monitor everything. Optimize continuously. 📊