2019-12-15 04:33:48 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Alphaleonis.Win32.Filesystem;
|
2019-12-29 22:57:01 +00:00
|
|
|
|
using CouchDB.Driver.Extensions;
|
|
|
|
|
using MongoDB.Driver;
|
2019-12-15 04:33:48 +00:00
|
|
|
|
using Nancy;
|
2019-12-29 22:57:01 +00:00
|
|
|
|
using Wabbajack.CacheServer.DTOs;
|
2019-12-15 04:33:48 +00:00
|
|
|
|
using Wabbajack.Common;
|
|
|
|
|
|
|
|
|
|
namespace Wabbajack.CacheServer
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Extremely
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class Metrics : NancyModule
|
|
|
|
|
{
|
|
|
|
|
private static SemaphoreSlim _lockObject = new SemaphoreSlim(1);
|
|
|
|
|
|
2019-12-29 22:57:01 +00:00
|
|
|
|
public static async Task Log(DateTime timestamp, string action, string subject)
|
2019-12-15 04:33:48 +00:00
|
|
|
|
{
|
2019-12-29 22:57:01 +00:00
|
|
|
|
var msg = new[] {string.Join("\t", new[]{timestamp.ToString(), action, subject})};
|
2019-12-15 04:33:48 +00:00
|
|
|
|
Utils.Log(msg.First());
|
2019-12-29 22:57:01 +00:00
|
|
|
|
var db = Server.Config.Metrics.Connect();
|
|
|
|
|
await db.InsertOneAsync(new Metric {Timestamp = timestamp, Action = action, Subject = subject});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Task Log(string action, string subject)
|
|
|
|
|
{
|
|
|
|
|
return Log(DateTime.Now, action, subject);
|
2019-12-15 04:33:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Metrics() : base("/")
|
|
|
|
|
{
|
|
|
|
|
Get("/metrics/{Action}/{Value}", HandleMetrics);
|
2019-12-16 02:24:05 +00:00
|
|
|
|
Get("/metrics/chart/", HandleChart);
|
|
|
|
|
Get("/metrics/chart/{Action}/", HandleChart);
|
|
|
|
|
Get("/metrics/chart/{Action}/{Value}/", HandleChart);
|
2019-12-29 22:57:01 +00:00
|
|
|
|
Get("/metrics/ingest/{filename}", HandleBulkIngest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task<string> HandleBulkIngest(dynamic arg)
|
|
|
|
|
{
|
|
|
|
|
Log("Bulk Loading " + arg.filename.ToString());
|
|
|
|
|
|
|
|
|
|
var lines = File.ReadAllLines(Path.Combine(@"c:\tmp", (string)arg.filename));
|
|
|
|
|
|
|
|
|
|
var db = Server.Config.Metrics.Connect();
|
|
|
|
|
|
|
|
|
|
var data = lines.Select(line => line.Split('\t'))
|
|
|
|
|
.Where(line => line.Length == 3)
|
|
|
|
|
.Select(line => new Metric{ Timestamp = DateTime.Parse(line[0]), Action = line[1], Subject = line[2] })
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
foreach (var metric in data)
|
|
|
|
|
await db.InsertOneAsync(metric);
|
|
|
|
|
|
|
|
|
|
return $"Processed {lines.Length} records";
|
2019-12-15 04:33:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task<string> HandleMetrics(dynamic arg)
|
|
|
|
|
{
|
|
|
|
|
var date = DateTime.UtcNow;
|
|
|
|
|
await Log(date, arg.Action, arg.Value);
|
|
|
|
|
return date.ToString();
|
|
|
|
|
}
|
2019-12-16 02:24:05 +00:00
|
|
|
|
|
|
|
|
|
private async Task<Response> HandleChart(dynamic arg)
|
|
|
|
|
{
|
2019-12-29 22:57:01 +00:00
|
|
|
|
/*var data = (await GetData()).Select(line => line.Split('\t'))
|
2019-12-16 02:24:05 +00:00
|
|
|
|
.Where(line => line.Length == 3)
|
2019-12-29 22:57:01 +00:00
|
|
|
|
.Select(line => new {date = DateTime.Parse(line[0]), Action = line[1], Value = line[2]});*/
|
|
|
|
|
|
|
|
|
|
var q = (IQueryable<Metric>)Server.Config.Metrics.Connect().AsQueryable();
|
2019-12-16 02:24:05 +00:00
|
|
|
|
|
|
|
|
|
// Remove guids / Default, which come from testing
|
|
|
|
|
|
|
|
|
|
if (arg?.Action != null)
|
2019-12-29 22:57:01 +00:00
|
|
|
|
{
|
|
|
|
|
var action = (string)arg.Action;
|
|
|
|
|
q = q.Where(d => d.Action == action);
|
|
|
|
|
}
|
2019-12-16 02:24:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (arg?.Value != null)
|
2019-12-29 22:57:01 +00:00
|
|
|
|
{
|
|
|
|
|
var value = (string)arg.Value;
|
|
|
|
|
q = q.Where(d => d.Subject.StartsWith(value));
|
|
|
|
|
}
|
2019-12-16 02:24:05 +00:00
|
|
|
|
|
2019-12-29 22:57:01 +00:00
|
|
|
|
var data = (await q.Take(Int32.MaxValue).ToListAsync()).AsEnumerable();
|
|
|
|
|
data = data.Where(d => !Guid.TryParse(d.Subject ?? "", out Guid v) && (d.Subject ?? "") != "Default");
|
|
|
|
|
|
|
|
|
|
var grouped_and_counted = data.GroupBy(d => d.Timestamp.ToString("yyyy-MM-dd"))
|
2019-12-16 02:24:05 +00:00
|
|
|
|
.OrderBy(d => d.Key)
|
|
|
|
|
.Select(d => new {Day = d.Key, Count = d.Count()})
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
|
sb.Append("<html><head><script src=\"https://cdn.jsdelivr.net/npm/chart.js@2.8.0\"></script></head>");
|
|
|
|
|
sb.Append("<body><canvas id=\"myChart\"></canvas>");
|
|
|
|
|
sb.Append("<script language='javascript'>");
|
|
|
|
|
var script = @"var ctx = document.getElementById('myChart').getContext('2d');
|
|
|
|
|
var chart = new Chart(ctx, {
|
|
|
|
|
// The type of chart we want to create
|
|
|
|
|
type: 'line',
|
|
|
|
|
|
|
|
|
|
// The data for our dataset
|
|
|
|
|
data: {
|
|
|
|
|
labels: [{{LABELS}}],
|
|
|
|
|
datasets: [{
|
|
|
|
|
label: '{{DATASET}}',
|
|
|
|
|
backgroundColor: 'rgb(255, 99, 132)',
|
|
|
|
|
borderColor: 'rgb(255, 99, 132)',
|
|
|
|
|
data: [{{DATA}}]
|
|
|
|
|
}]
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Configuration options go here
|
|
|
|
|
options: {}
|
|
|
|
|
});";
|
|
|
|
|
sb.Append(script.Replace("{{LABELS}}", string.Join(",", grouped_and_counted.Select(e => "'"+e.Day+"'")))
|
|
|
|
|
.Replace("{{DATA}}", string.Join(",", grouped_and_counted.Select(e => e.Count.ToString())))
|
|
|
|
|
.Replace("{{DATASET}}", (arg.Action ?? "*") + " - " + (arg.Value ?? "*")));
|
|
|
|
|
|
|
|
|
|
sb.Append("</script>");
|
|
|
|
|
sb.Append("</body></html>");
|
|
|
|
|
var response = (Response)sb.ToString();
|
|
|
|
|
response.ContentType = "text/html";
|
|
|
|
|
return response;
|
|
|
|
|
}
|
2019-12-29 22:57:01 +00:00
|
|
|
|
|
|
|
|
|
public void Log(string l)
|
|
|
|
|
{
|
|
|
|
|
Utils.Log("Metrics: " + l);
|
|
|
|
|
}
|
2019-12-15 04:33:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|