Add metrics getter

This commit is contained in:
Timothy Baldridge 2021-11-29 16:35:23 -07:00
parent 328182dcfb
commit cbb374af26
3 changed files with 104 additions and 2 deletions

View File

@ -1,7 +1,9 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using Chronic.Core;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Nettle; using Nettle;
@ -83,6 +85,28 @@ public class MetricsController : ControllerBase
return new Result {Timestamp = date}; return new Result {Timestamp = date};
} }
private static byte[] EOL = {(byte)'\n'};
[HttpGet]
[Route("report")]
public async Task GetMetrics([FromQuery] string action, [FromQuery] string from, [FromQuery] string? to)
{
var parser = new Parser();
to ??= "now";
var toDate = parser.Parse(to).Start;
var fromDate = parser.Parse(from).Start;
var records = _metricsStore.GetRecords(fromDate!.Value, toDate!.Value, action);
Response.Headers.ContentType = "application/json";
await foreach (var record in records)
{
await JsonSerializer.SerializeAsync(Response.Body, record);
await Response.Body.WriteAsync(EOL);
}
}
public class Result public class Result
{ {
public DateTime Timestamp { get; set; } public DateTime Timestamp { get; set; }

View File

@ -1,6 +1,8 @@
using System; using System;
using System.Collections;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Toolkit.HighPerformance; using Microsoft.Toolkit.HighPerformance;
@ -34,6 +36,81 @@ public class Metrics
fs.Write(data); fs.Write(data);
fs.Write(Encoding.UTF8.GetBytes("\n")); fs.Write(Encoding.UTF8.GetBytes("\n"));
} }
private IEnumerable<DateTime> GetDates(DateTime fromDate, DateTime toDate)
{
for (var d = new DateTime(fromDate.Year, fromDate.Month, fromDate.Day); d <= toDate; d = d.AddDays(1))
{
yield return d;
}
}
public async IAsyncEnumerable<MetricResult> GetRecords(DateTime fromDate, DateTime toDate, string action)
{
var keys = new Dictionary<string, int>();
int GetMetricKey(string key)
{
if (keys.TryGetValue(key, out var v))
return v;
keys.Add(key, keys.Count);
return keys.Count - 1;
}
foreach (var file in GetFiles(fromDate, toDate))
{
await foreach (var line in file.ReadAllLinesAsync())
{
var metric = _dtos.Deserialize<Metric>(line)!;
if (metric.Action != action) continue;
if (metric.Timestamp >= fromDate && metric.Timestamp <= toDate)
{
yield return new MetricResult
{
Timestamp = metric.Timestamp,
Subject = metric.Subject,
Action = metric.Action,
MetricKey = GetMetricKey(metric.MetricsKey),
UserAgent = metric.UserAgent,
GroupingSubject = GetGroupingSubject(metric.Subject)
};
}
}
}
}
private Regex groupingRegex = new("^[^0-9]*");
private string GetGroupingSubject(string metricSubject)
{
try
{
return groupingRegex.Match(metricSubject).Groups[0].ToString();
}
catch (Exception)
{
return metricSubject;
}
}
private IEnumerable<AbsolutePath> GetFiles(DateTime fromDate, DateTime toDate)
{
var folder = _settings.MetricsFolder.ToAbsolutePath();
foreach (var day in GetDates(fromDate, toDate))
{
var file = folder.Combine(day.ToString("yyyy_MM_dd") + ".json");
if (file.FileExists())
yield return file;
}
}
public class MetricResult
{
public string Action { get; set; }
public string Subject { get; set; }
public string GroupingSubject { get; set; }
public long MetricKey { get; set; }
public string UserAgent { get; set; }
public DateTime Timestamp { get; set; }
}
} }

View File

@ -8,6 +8,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Chronic.Core" Version="0.4.0" />
<PackageReference Include="Dapper" Version="2.0.123" /> <PackageReference Include="Dapper" Version="2.0.123" />
<PackageReference Include="Discord.Net.WebSocket" Version="2.4.0" /> <PackageReference Include="Discord.Net.WebSocket" Version="2.4.0" />
<PackageReference Include="FluentFTP" Version="35.0.5" /> <PackageReference Include="FluentFTP" Version="35.0.5" />