From 95d72cf0bd9ca9b25ac5c30b8810b3440f8fdfe6 Mon Sep 17 00:00:00 2001 From: Gervasio Marchand Date: Thu, 12 Jan 2023 16:11:24 -0300 Subject: [PATCH] Pull data from Grafana --- src/FakeRelay.Core/Config.cs | 13 +++- src/FakeRelay.Core/Helpers/GrafanaHelper.cs | 68 +++++++++++++++++++ .../Controllers/ApiController.cs | 25 +++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 src/FakeRelay.Core/Helpers/GrafanaHelper.cs diff --git a/src/FakeRelay.Core/Config.cs b/src/FakeRelay.Core/Config.cs index 8a2bb79..a889e10 100644 --- a/src/FakeRelay.Core/Config.cs +++ b/src/FakeRelay.Core/Config.cs @@ -13,6 +13,9 @@ public class Config public string ConfigPath { get; } public string? HomeRedirect { get; } + public string? GrafanaHost { get; } + public string? GrafanaKey { get; } + public int? GrafanaDataSourceId { get; } private Config() { @@ -20,13 +23,16 @@ public class Config PublicKey = Host = ConfigPath = ""; } - private Config(string publicKey, byte[] privateKey, string host, string configPath, string? homeRedirect) + private Config(string publicKey, byte[] privateKey, string host, string configPath, string? homeRedirect, string? grafanaHost, string? grafanaKey, int? grafanaDataSourceId) { PrivateKey = privateKey; PublicKey = publicKey; Host = host; ConfigPath = configPath; HomeRedirect = homeRedirect; + GrafanaHost = grafanaHost; + GrafanaKey = grafanaKey; + GrafanaDataSourceId = grafanaDataSourceId; } public static void Init(string path) @@ -50,7 +56,7 @@ public class Config using var rsa = RSA.Create(); rsa.ImportFromPem(data.PrivateKey.ToCharArray()); - Instance = new Config(data.PublicKey, rsa.ExportRSAPrivateKey(), data.Host, path, data.HomeRedirect); + Instance = new Config(data.PublicKey, rsa.ExportRSAPrivateKey(), data.Host, path, data.HomeRedirect, data.GrafanaHost, data.GrafanaKey, data.GrafanaDataSourceId); } public static void CreateConfig(string path, string host, string publicKey, string privateKey) @@ -70,5 +76,8 @@ public class Config public string? PrivateKey { get; set; } public string? Host { get; set; } public string? HomeRedirect { get; set; } + public string? GrafanaHost { get; set; } + public string? GrafanaKey { get; set; } + public int? GrafanaDataSourceId { get; set; } } } diff --git a/src/FakeRelay.Core/Helpers/GrafanaHelper.cs b/src/FakeRelay.Core/Helpers/GrafanaHelper.cs new file mode 100644 index 0000000..f9ba48d --- /dev/null +++ b/src/FakeRelay.Core/Helpers/GrafanaHelper.cs @@ -0,0 +1,68 @@ +using System.Net.Http.Headers; +using System.Runtime.Serialization; +using Jil; + +namespace FakeRelay.Core.Helpers; + +public static class GrafanaHelper +{ + private static HttpClient? _httpClient; + private static HttpClient HttpClient => _httpClient ??= GetHttpClient(); + + private static HttpClient GetHttpClient() + { + var httpClient = new HttpClient { BaseAddress = new Uri("https://" + Config.Instance.GrafanaHost) }; + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Config.Instance.GrafanaKey); + + return httpClient; + } + + public static async Task GetCountInPeriod(string hostname, string period) + { + if (Config.Instance.GrafanaHost.IsNullOrEmpty() || Config.Instance.GrafanaKey.IsNullOrEmpty() || !Config.Instance.GrafanaDataSourceId.HasValue) + { + return -1; + } + + var requestContent = new StringContent($@" +{{""queries"":[{{""datasourceId"":{Config.Instance.GrafanaDataSourceId.Value},""expr"":""increase(fr_index_requests{{exported_instance=\""{hostname}\""}}[{period}])""}}],""to"":""now"",""from"":""now""}} + "); + requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + var result = await HttpClient.PostAsync("/api/ds/query", requestContent); + if (!result.IsSuccessStatusCode) + { + return -1; + } + + var json = await result.Content.ReadAsStringAsync(); + var data = JSON.Deserialize(json, Options.CamelCase); + return (int)Math.Round(data.Results.A.Frames[0].Data.Values[1][0]); + } +} + +public class GrafanaResponse +{ + public ResultData Results { get; set; } + + public class ResultData + { + [DataMember(Name = "A")] + public AData A { get; set; } + + public class AData + { + public FrameData[] Frames { get; set; } + + public class FrameData + { + public DataData Data { get; set; } + + public class DataData + { + public float[][] Values { get; set; } + } + } + } + } +} diff --git a/src/FakeRelay.Web/Controllers/ApiController.cs b/src/FakeRelay.Web/Controllers/ApiController.cs index 1bf6844..850560c 100644 --- a/src/FakeRelay.Web/Controllers/ApiController.cs +++ b/src/FakeRelay.Web/Controllers/ApiController.cs @@ -1,4 +1,6 @@ using System.Collections.Immutable; +using System.Text.RegularExpressions; +using FakeRelay.Core; using FakeRelay.Core.Helpers; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Memory; @@ -53,4 +55,27 @@ public class ApiController : Controller Response.Headers["instance"] = host; return Content(response, "application/activity+json"); } + + [Route("index-posts-count")] + public async Task IndexedPostsCount(string period) + { + if (Config.Instance.GrafanaHost.IsNullOrEmpty() || Config.Instance.GrafanaKey.IsNullOrEmpty()) + { + return NotFound(); + } + + if (!Regex.IsMatch(period, "^[0-9]+[mhd]$")) + { + return BadRequest(); + } + + var host = await GetHostFromRequest(); + if (host == null) + { + return Unauthorized(); + } + + var count = await GrafanaHelper.GetCountInPeriod(host, period); + return Content(count.ToString()); + } }