PrometheusStarter.cs
1 using Core; 2 using KubernetesWorkflow; 3 using KubernetesWorkflow.Types; 4 using Logging; 5 using System.Text; 6 using Utils; 7 8 namespace MetricsPlugin 9 { 10 public class PrometheusStarter 11 { 12 private readonly PrometheusContainerRecipe recipe = new PrometheusContainerRecipe(); 13 private readonly IPluginTools tools; 14 15 public PrometheusStarter(IPluginTools tools) 16 { 17 this.tools = tools; 18 } 19 20 public RunningPod CollectMetricsFor(Address[] targets, TimeSpan scrapeInterval) 21 { 22 if (!targets.Any()) throw new ArgumentException(nameof(targets) + " must not be empty."); 23 24 Log($"Starting metrics server for {targets.Length} targets..."); 25 var startupConfig = new StartupConfig(); 26 startupConfig.Add(new PrometheusStartupConfig(GeneratePrometheusConfig(targets, scrapeInterval))); 27 28 var workflow = tools.CreateWorkflow(); 29 var runningContainers = workflow.Start(1, recipe, startupConfig).WaitForOnline(); 30 if (runningContainers.Containers.Length != 1) throw new InvalidOperationException("Expected only 1 Prometheus container to be created."); 31 32 Log("Metrics server started."); 33 return runningContainers; 34 } 35 36 public MetricsAccess CreateAccessForTarget(RunningPod metricsPod, Address target) 37 { 38 var metricsQuery = new MetricsQuery(tools, metricsPod.Containers.Single()); 39 return new MetricsAccess(metricsQuery, target); 40 } 41 42 public string GetPrometheusId() 43 { 44 return recipe.Image; 45 } 46 47 private void Log(string msg) 48 { 49 tools.GetLog().Log(msg); 50 } 51 52 private string GeneratePrometheusConfig(Address[] targets, TimeSpan scrapeInterval) 53 { 54 var secs = Convert.ToInt32(scrapeInterval.TotalSeconds); 55 if (secs < 1) throw new Exception("ScrapeInterval can't be < 1s"); 56 if (secs > 60) throw new Exception("ScrapeInterval can't be > 60s"); 57 58 var config = ""; 59 config += "global:\n"; 60 config += $" scrape_interval: {secs}s\n"; 61 config += $" scrape_timeout: {secs}s\n"; 62 config += "\n"; 63 config += "scrape_configs:\n"; 64 config += " - job_name: services\n"; 65 config += " metrics_path: /metrics\n"; 66 config += " static_configs:\n"; 67 config += " - targets:\n"; 68 69 foreach (var target in targets) 70 { 71 config += $" - '{FormatTarget(target)}'\n"; 72 } 73 74 var bytes = Encoding.ASCII.GetBytes(config); 75 return Convert.ToBase64String(bytes); 76 } 77 78 private string FormatTarget(Address target) 79 { 80 return ScrapeTargetHelper.FormatTarget(target); 81 } 82 } 83 84 public static class ScrapeTargetHelper 85 { 86 public static string FormatTarget(Address target) 87 { 88 var host = target.Host.Replace("http://", "").Replace("https://", ""); 89 return $"{host}:{target.Port}"; 90 } 91 } 92 }