From 485af03367c345096d316aae0059973585cb5dc0 Mon Sep 17 00:00:00 2001 From: benbierens Date: Fri, 11 Aug 2023 12:38:26 +0200 Subject: [PATCH] very wip: automatic grafana dashboard --- DistTestCore/DistTestCore.csproj | 8 + DistTestCore/Http.cs | 17 +++ .../Metrics/GrafanaContainerRecipe.cs | 4 +- DistTestCore/Metrics/dashboard.json | 138 ++++++++++++++++++ DistTestCore/PrometheusStarter.cs | 68 +++------ 5 files changed, 183 insertions(+), 52 deletions(-) create mode 100644 DistTestCore/Metrics/dashboard.json diff --git a/DistTestCore/DistTestCore.csproj b/DistTestCore/DistTestCore.csproj index 512d692..94a2271 100644 --- a/DistTestCore/DistTestCore.csproj +++ b/DistTestCore/DistTestCore.csproj @@ -10,6 +10,14 @@ Arm64 + + + + + + Never + + diff --git a/DistTestCore/Http.cs b/DistTestCore/Http.cs index 866a640..1239fd7 100644 --- a/DistTestCore/Http.cs +++ b/DistTestCore/Http.cs @@ -68,6 +68,23 @@ namespace DistTestCore }, $"HTTP-POST-JSON: {route}"); } + public string HttpPostString(string route, string body) + { + return Retry(() => + { + using var client = GetClient(); + var url = GetUrl() + route; + Log(url, body); + client.SetBasicAuthentication("admin", "admin"); + var content = new StringContent(body); + content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); + var result = Time.Wait(client.PostAsync(url, content)); + var str = Time.Wait(result.Content.ReadAsStringAsync()); + Log(url, str); + return str; + }, $"HTTP-POST-STRING: {route}"); + } + public string HttpPostStream(string route, Stream stream) { return Retry(() => diff --git a/DistTestCore/Metrics/GrafanaContainerRecipe.cs b/DistTestCore/Metrics/GrafanaContainerRecipe.cs index b873fa8..12af581 100644 --- a/DistTestCore/Metrics/GrafanaContainerRecipe.cs +++ b/DistTestCore/Metrics/GrafanaContainerRecipe.cs @@ -19,8 +19,8 @@ namespace DistTestCore.Metrics // enabled = true //GF____FILE - //AddEnvVar("GF_AUTH_ANONYMOUS_ENABLED", "true"); - //AddEnvVar("GF_AUTH_DISABLE_LOGIN_FORM", "true"); + AddEnvVar("GF_AUTH_ANONYMOUS_ENABLED", "true"); + AddEnvVar("GF_AUTH_DISABLE_LOGIN_FORM", "true"); //[auth] //disable_login_form = true diff --git a/DistTestCore/Metrics/dashboard.json b/DistTestCore/Metrics/dashboard.json new file mode 100644 index 0000000..59b6bbb --- /dev/null +++ b/DistTestCore/Metrics/dashboard.json @@ -0,0 +1,138 @@ +{ + "dashboard": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "c89eaad3-9184-429f-ac94-8ba0b1824dbb" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "c89eaad3-9184-429f-ac94-8ba0b1824dbb" + }, + "editorMode": "builder", + "expr": "codexApiDownloads_total", + "instant": false, + "range": true, + "refId": "A" + } + ], + "title": "Codex API Downloads", + "type": "timeseries" + } + ], + "refresh": "10s", + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Codex", + "uid": null, + "version": 2, + "weekStart": "" + }, + "message": "Default Codex Dashboard", + "overwrite": false +} diff --git a/DistTestCore/PrometheusStarter.cs b/DistTestCore/PrometheusStarter.cs index 4e27952..d58ba6d 100644 --- a/DistTestCore/PrometheusStarter.cs +++ b/DistTestCore/PrometheusStarter.cs @@ -2,13 +2,8 @@ using DistTestCore.Metrics; using KubernetesWorkflow; using Logging; -using System; -using System.Diagnostics; -using System.Net.Http.Headers; +using System.Reflection; using System.Text; -using Utils; -using static System.Net.Mime.MediaTypeNames; -using static System.Net.WebRequestMethods; namespace DistTestCore { @@ -40,44 +35,10 @@ namespace DistTestCore var c = grafanaContainers.Containers.First().ClusterExternalAddress; - - - //{ - // //setup reusable http client - // HttpClient client = new HttpClient(); - // Uri baseUri = new Uri(c.Host + ":" + c.Port); - // client.BaseAddress = baseUri; - // client.DefaultRequestHeaders.Clear(); - // client.DefaultRequestHeaders.ConnectionClose = true; - - // //Post body content - // var values = new List>(); - // values.Add(new KeyValuePair("grant_type", "client_credentials")); - // var content = new FormUrlEncodedContent(values); - - // var authenticationString = $"admin:admin"; - // var base64EncodedAuthenticationString = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(authenticationString)); - - // var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/oauth2/token"); - // requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", base64EncodedAuthenticationString); - // requestMessage.Content = content; - - // //make the request - // var responsea = Time.Wait(client.SendAsync(requestMessage)); - // responsea.EnsureSuccessStatusCode(); - // string responseBody = Time.Wait(responsea.Content.ReadAsStringAsync()); - // Console.WriteLine(responseBody); - - //} - - //POST / api / datasources HTTP / 1.1 - //Accept: application / json - //Content - Type: application / json - //Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk - var http = new Http(new NullLog(), new DefaultTimeSet(), c, "api/"); var response = http.HttpPostJson("datasources", new GrafanaDataSource { + uid = "c89eaad3-9184-429f-ac94-8ba0b1824dbb", name = "CodexPrometheus", type = "prometheus", url = prometheusUrl, @@ -89,26 +50,19 @@ namespace DistTestCore } }); - - // [{ "id":1,"uid":"c89eaad3-9184-429f-ac94-8ba0b1824dbb","orgId":1, - // "name":"Prometheus","type":"prometheus","typeName":"Prometheus", - // "typeLogoUrl":"public/app/plugins/datasource/prometheus/img/prometheus_logo.svg", - // "access":"proxy","url":"http://kubernetes.docker.internal:31234","user":"","database":"", - // "basicAuth":false,"isDefault":true,"jsonData":{ "httpMethod":"POST"},"readOnly":false}] - + var response2 = http.HttpPostString("dashboards/db", GetDashboardJson()); var grafanaUrl = c.Host + ":" + c.Port; System.Diagnostics.Process.Start("C:\\Users\\Ben\\AppData\\Local\\Programs\\Opera\\opera.exe", grafanaUrl); LogEnd("Metrics server started."); - - return runningContainers; } public class GrafanaDataSource { + public string uid { get; set; } = string.Empty; public string name { get; set; } = string.Empty; public string type { get; set; } = string.Empty; public string url { get; set; } = string.Empty; @@ -122,6 +76,20 @@ namespace DistTestCore public string httpMethod { get; set; } = string.Empty; } + private string GetDashboardJson() + { + var assembly = Assembly.GetExecutingAssembly(); + var resourceName = "DistTestCore.Metrics.dashboard.json"; + + //var names = assembly.GetManifestResourceNames(); + + using (Stream stream = assembly.GetManifestResourceStream(resourceName)) + using (StreamReader reader = new StreamReader(stream)) + { + return reader.ReadToEnd(); + } + } + private string GeneratePrometheusConfig(RunningContainer[] nodes) { var config = "";