This commit is contained in:
2018-08-24 17:57:30 +00:00
parent cbb153166f
commit 1cfa78472e
6 changed files with 157 additions and 22 deletions

View File

@@ -16,6 +16,11 @@ Cleanup and sticking to the following code convention:
DATES, TIMES, TIMESTAMPS - All dates and times sent or retrieved from the REST interface must be in UTC / GMT time zone.
It is the client's responsibility to display and accept dates in local format but interaction with the server is in UTC only.
Localized text - All text prsented by the server will be a locale key only and it is the clients responsibility to display in local text format with the exception of:
- Ops logs, Metrics, event logs: these items and any other future pre-generated text items will be localized at the server according to the logged in users' locale

View File

@@ -9,6 +9,13 @@ Items are only removed from log when source object is deleted (and replaced with
Needs a cleaner job that periodically looks for non-existant objects that are logged
Has to handle a scenario where there is no data for an object because in future we will likely have a purge feature or maybe a feature to turn it off and needs to accept that scenario
ROUTES
------
Fetch a constructed, localized log for the following:
- Supply user ID, optional time range, get back a log of everything the user did in order for all time or just the specified time range
- Supply object type, object id, optional time range, get back a log of history for that object for all time or time range specified
Fetch the above but in raw form as data as well??
EVENT_TYPES
-----------

View File

@@ -64,8 +64,12 @@ and backend. I want to know what happens under typical heavy usage simulating m
I'm guessing something that autodrives a browser or simulates one to access via client UI for full end to end testing.
- Should be configurable to simulate various loads:
- Smoke test (Quick bug test): excercises one of everything once only looking for fundamental problems
- Load test (Slower longer test to look for scaling issues related to a huge, busy office): exercises typical daily load of very large office but configurable to run in simulated days, so
can run it as a simulated week with 7 or month with 30 or years by entering in the number of days to simulate. Would be nice if it did month end type stuff or delayed then billed out etc.
- Load / scale / assurance test (Slower longer test to look for scaling issues related to a huge, busy office): exercises typical daily load of very large office but configurable to run in simulated days, so
can run it as a simulated week with 7 or month with 30 or years by entering in the number of days to simulate.
Would be nice if it did month end type stuff or delayed then billed out etc.
Should report stats about timing etc from the client perspective, we already have metrics for the backend perspective.
I'd like to know immediately if something is weirdly slow, not just in error.
Should not erase data at end so we can then manually login and check things out with a full load of at scale data

View File

@@ -5,4 +5,6 @@ No other data formats are supported, your code must supply and consume JSON form
All developer interaction with the AyaNova API is via the REST server interface only.
DATES, TIMES, TIMESTAMPS - All dates and times sent or retrieved from the REST interface must be in UTC / GMT time zone. It is the client's responsibility to display and accept dates in local format but interaction with the server is in UTC only.
**TODO FILL THS OUT**

View File

@@ -0,0 +1,136 @@
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using AyaNova.Models;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Biz;
namespace AyaNova.Api.Controllers
{
/// <summary>
/// Log files controller
/// </summary>
[ApiVersion("8.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[Authorize]
public class EventLogController : Controller
{
private readonly AyContext ct;
private readonly ILogger<LogFilesController> log;
private readonly ApiServerState serverState;
/// <summary>
/// ctor
/// </summary>
/// <param name="dbcontext"></param>
/// <param name="logger"></param>
/// <param name="apiServerState"></param>
public EventLogController(AyContext dbcontext, ILogger<LogFilesController> logger, ApiServerState apiServerState)
{
ct = dbcontext;
log = logger;
serverState = apiServerState;
}
/// <summary>
/// Get events as text document for object specified
///
/// Required roles:
/// OpsAdminFull | OpsAdminLimited
/// </summary>
/// <returns>Snapshot of metrics</returns>
[HttpGet("TextSnapShot")]
public async Task<IActionResult> GetObjectLog()
{
//Open or opsOnly and user is opsadminfull or opsadminlimited
if (!serverState.IsOpenOrOpsOnly || (serverState.IsOpsOnly && !Authorized.HasAnyRole(HttpContext.Items, AuthorizationRoles.OpsAdminFull | AuthorizationRoles.OpsAdminLimited)))
{
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
}
if (!Authorized.IsAuthorizedToRead(HttpContext.Items, AyaType.Metrics))
{
return StatusCode(401, new ApiNotAuthorizedResponse());
}
string sResult = await GetTheMetrics("plain");
//Log
EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct);
return Content(sResult);
}
/// <summary>
/// Get metrics as json object
///
/// Required roles:
/// OpsAdminFull | OpsAdminLimited
/// </summary>
/// <returns>Snapshot of metrics</returns>
[HttpGet("JsonSnapShot")]
public async Task<IActionResult> GetJsonMetrics()
{
//Open or opsOnly and user is opsadminfull or opsadminlimited
if (!serverState.IsOpenOrOpsOnly || (serverState.IsOpsOnly && !Authorized.HasAnyRole(HttpContext.Items, AuthorizationRoles.OpsAdminFull | AuthorizationRoles.OpsAdminLimited)))
{
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
}
if (!Authorized.IsAuthorizedToRead(HttpContext.Items, AyaType.Metrics))
{
return StatusCode(401, new ApiNotAuthorizedResponse());
}
string sResult = await GetTheMetrics("json");
JObject json = JObject.Parse(sResult);
//Log
EventLogProcessor.AddEntry(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct);
return Ok(new ApiOkResponse(json));
}
/// <summary>
/// Get the metrics snapshot
/// </summary>
/// <param name="format">Either "json" for json format or "plain" for plaintext format</param>
/// <returns></returns>
private async Task<string> GetTheMetrics(string format)
{
var snapshot = metrics.Snapshot.Get();
var formatters = ((IMetricsRoot)metrics).OutputMetricsFormatters;
string sResult = $"ERROR GETTING METRICS IN {format} FORMAT";
foreach (var formatter in formatters)
{
if (formatter.MediaType.Format == format)
{
using (var stream = new MemoryStream())
{
await formatter.WriteAsync(stream, snapshot);
sResult = System.Text.Encoding.UTF8.GetString(stream.ToArray());
}
}
}
return sResult;
}
//------------
}
}

View File

@@ -132,26 +132,7 @@ namespace AyaNova.Api.Controllers
}
});
// Newtonsoft.Json.Linq.JObject o = Newtonsoft.Json.Linq.JObject.FromObject(new
// {
// logs = new
// {
// licensedTo = ActiveKey.RegisteredTo,
// registeredEmail = ActiveKey.FetchEmail,
// trial = ActiveKey.Trial,
// keySerial = ActiveKey.Id,
// keySource = ActiveKey.Source,
// created = ActiveKey.Created.ToString(),
// features =
// from f in files
// orderby f
// select new
// {
// logName = f
// }
// }
// });
return Ok(new ApiOkResponse(o));