grouped trainer status with graph update to reduce number of requests, used moment for date time format

This commit is contained in:
Luong Hoang 2016-07-01 16:39:28 -04:00
Родитель fca81a615a
Коммит ff5bb10c7f
13 изменённых файлов: 16245 добавлений и 80 удалений

Просмотреть файл

@ -0,0 +1,15 @@
using System;
using System.Net;
namespace DecisionServicePrivateWeb.Classes
{
public class TimeoutWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest w = base.GetWebRequest(uri);
w.Timeout = (int)TimeSpan.FromSeconds(2).TotalMilliseconds;
return w;
}
}
}

Просмотреть файл

@ -188,42 +188,6 @@ namespace DecisionServicePrivateWeb.Controllers
}
}
private class TimeoutWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest w = base.GetWebRequest(uri);
w.Timeout = (int)TimeSpan.FromSeconds(2).TotalMilliseconds;
return w;
}
}
[HttpGet]
public async Task<ActionResult> TrainerStatus()
{
try
{
using (var wc = new TimeoutWebClient())
{
var json = await wc.DownloadStringTaskAsync(ConfigurationManager.AppSettings[ApplicationMetadataStore.AKTrainerURL] + "/status");
return Content(json, "application/json");
}
}
catch (WebException ex)
{
if (ex.Message.Contains("Unable to connect to the remote server"))
return Content("{\"TrainerStatus\":\"NotStarted\"}", "application/json");
new TelemetryClient().TrackException(ex);
return new HttpStatusCodeResult(HttpStatusCode.InternalServerError, ex.Message);
}
catch (Exception ex)
{
new TelemetryClient().TrackException(ex);
return new HttpStatusCodeResult(HttpStatusCode.InternalServerError, ex.Message);
}
}
private void ModelSuccessNotifier(byte[] modelBytes)
{
ModelUpdateTime = DateTime.UtcNow;

Просмотреть файл

@ -6,6 +6,7 @@ using Microsoft.Research.MultiWorldTesting.Contract;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Configuration;
@ -230,10 +231,34 @@ namespace DecisionServicePrivateWeb.Controllers
return new HttpStatusCodeResult(HttpStatusCode.Unauthorized, "A valid token must be specified.");
}
return GetEvalData(windowType, maxNumPolicies);
string trainerStatus = string.Empty;
try
{
using (var wc = new TimeoutWebClient())
{
var trainerStatusJson = wc.DownloadString(ConfigurationManager.AppSettings[ApplicationMetadataStore.AKTrainerURL] + "/status");
JToken jtoken = JObject.Parse(trainerStatusJson);
int numLearnedExamples = (int)jtoken.SelectToken("Stage2_Learn_Total");
trainerStatus = $"Trainer OK. Total learned examples: {numLearnedExamples}";
}
}
catch (Exception ex)
{
if (ex.Message.Contains("Unable to connect to the remote server"))
{
trainerStatus = "Please wait as trainer has not started yet";
}
else
{
new TelemetryClient().TrackException(ex);
trainerStatus = "Error getting trainer status, check Application Insights for more details.";
}
}
return GetEvalData(windowType, maxNumPolicies, trainerStatus);
}
private ActionResult GetEvalData(string windowType, int maxNumPolicies)
private ActionResult GetEvalData(string windowType, int maxNumPolicies, string trainerStatus = null)
{
try
{
@ -280,13 +305,16 @@ namespace DecisionServicePrivateWeb.Controllers
}
}
}
return Json(evalData.Values.Select(a => new { key = GetDemoPolicyName(a.key), values = a.values.Select(v => new object[] { v.Key, v.Value }) }), JsonRequestBehavior.AllowGet);
var evalDataD3 = evalData.Values.Select(a => new { key = GetDemoPolicyName(a.key), values = a.values.Select(v => new object[] { v.Key, v.Value }) });
return Json(new { Data = evalDataD3, TrainerStatus = trainerStatus }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
return new HttpStatusCodeResult(HttpStatusCode.InternalServerError, $"Unable to load evaluation result: {ex.ToString()}");
new TelemetryClient().TrackException(ex);
return Json(new { DataError = "Unable to load evaluation result", TrainerStatus = trainerStatus }, JsonRequestBehavior.AllowGet);
}
}

Просмотреть файл

@ -212,6 +212,10 @@
<Content Include="Content\img\jsoneditor-icons.svg" />
<Content Include="Scripts\api-guide.js" />
<Content Include="Scripts\api-test-drive.js" />
<Content Include="Scripts\moment-with-locales.js" />
<Content Include="Scripts\moment-with-locales.min.js" />
<Content Include="Scripts\moment.js" />
<Content Include="Scripts\moment.min.js" />
<Content Include="Views\Home\APIGuide.cshtml" />
<Content Include="Views\Home\APITest.cshtml" />
<Content Include="Scripts\jsoneditor.map" />
@ -257,6 +261,9 @@
<Compile Include="Classes\DecisionServiceClientFactory.cs" />
<Compile Include="Classes\EvalD3.cs" />
<Compile Include="Classes\EvalResult.cs" />
<Compile Include="Classes\TimeoutWebClient.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Controllers\APIUtil.cs" />
<Compile Include="Controllers\AutomationController.cs" />
<Compile Include="Controllers\APIController.cs" />

Просмотреть файл

@ -92,7 +92,7 @@ function chooseAction() {
$("#article").attr("src", actions[data.Action - 1].image);
$("#article").attr("style", actions[data.Action - 1].imgStyle);
$("#articleText").text(actions[data.Action - 1].text);
$("#statusModel").text('Latest model: ' + new Date(parseInt(modelTime.substr(6))));
$("#statusModel").text('Latest model obtained at: ' + moment(new Date(parseInt(modelTime.substr(6)))).format('MMMM Do YYYY, h:mm:ss a'));
})
.fail(function (jqXHR, textStatus, errorThrown) {
$("#status").text("Error: " + textStatus + " " + errorThrown);
@ -174,35 +174,4 @@ $(document).keydown(function (e) {
reportReward(0);
break;
}
});
function trainerStatus() {
$.ajax({
method: "GET",
url: "/API/trainerStatus",
timeout: 2000 // 2 second
})
.done(function (data) {
/*
var str = "";
for (var property in data) {
if (data.hasOwnProperty(property)) {
str += property.replace("_", " ") + ": " + data[property] + " | ";
}
}
*/
var msg;
if (data['TrainerStatus'] == 'NotStarted')
msg = "Please wait as trainer has not started yet";
else
msg = "Trainer OK. Total learned examples: " + data['Stage2_Learn_Total'];
$("#statusTrainer").text(msg + " - " + new Date());
})
.fail(function (jqXHR, textStatus, errorThrown) {
$("#statusTrainer").text("Please wait as trainer has not started yet. Error: " + textStatus + " " + errorThrown);
});
}
trainerStatus();
setInterval(trainerStatus, 10 * 1000);
});

Просмотреть файл

@ -27,15 +27,21 @@
chart.yAxis.axisLabel("Average Reward");
if (response == null) {
response = [];
response = { Data: [] };
}
else {
if (response.DataError) {
$('#eval-chart-status').text(response.DataError);
}
$("#statusTrainer").text(response.TrainerStatus + " (Last updated at: " + moment().format('MMMM Do YYYY, h:mm:ss a') + ")");
}
d3.select('#' + chartId + ' svg')
.datum(response)
.datum(response.Data)
.call(chart);
nv.utils.windowResize(chart.update);
$('#eval-chart-status').text('Graph Updated At: ' + new Date($.now()));
$('#eval-chart-status').text('Graph updated at: ' + moment().format('MMMM Do YYYY, h:mm:ss a'));
return chart;
});

Разница между файлами не показана из-за своего большого размера Загрузить разницу

76
mc/Scripts/moment-with-locales.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

4040
mc/Scripts/moment.js Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

7
mc/Scripts/moment.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -138,6 +138,7 @@
@section scripts {
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="https://cdn.rawgit.com/novus/nvd3/v1.8.1/build/nv.d3.min.js" charset="utf-8"></script>
<script type="text/javascript" src="/scripts/eval.js"></script>
<script type="text/javascript" src="/scripts/api-test-drive.js"></script>
<script type="text/javascript" src="~/Scripts/moment.min.js"></script>
<script type="text/javascript" src="~/Scripts/eval.js"></script>
<script type="text/javascript" src="~/Scripts/api-test-drive.js"></script>
}

Просмотреть файл

@ -4,7 +4,7 @@
http://go.microsoft.com/fwlink/?LinkId=301880
-->
<configuration>
<appSettings file="..\AppSettingsSecrets.config">
<appSettings file="..\..\AppSettingsSecrets.config">
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />

Просмотреть файл

@ -25,6 +25,7 @@
<package id="Microsoft.Tpl.Dataflow" version="4.5.24" targetFramework="net452" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net452" />
<package id="Modernizr" version="2.6.2" targetFramework="net452" />
<package id="Moment.js" version="2.13.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net452" />
<package id="Rx-Core" version="2.2.5" targetFramework="net452" />
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net452" />