WIP
parent
35b2a8e80d
commit
7715b1ee3d
|
@ -4,6 +4,7 @@ using ln.http;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using ln.skyscanner.http;
|
using ln.skyscanner.http;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using ln.skyscanner.crawl;
|
||||||
namespace ln.skyscanner
|
namespace ln.skyscanner
|
||||||
{
|
{
|
||||||
public enum ComponentState { STOPPED, INITIALIZED, STARTED, FAILED }
|
public enum ComponentState { STOPPED, INITIALIZED, STARTED, FAILED }
|
||||||
|
@ -15,6 +16,7 @@ namespace ln.skyscanner
|
||||||
|
|
||||||
|
|
||||||
public HTTPServer HTTPServer { get; private set; }
|
public HTTPServer HTTPServer { get; private set; }
|
||||||
|
public Crawler Crawler { get; private set; }
|
||||||
|
|
||||||
public SkyScanner(String[] args)
|
public SkyScanner(String[] args)
|
||||||
{
|
{
|
||||||
|
@ -85,6 +87,23 @@ namespace ln.skyscanner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Crawler **/
|
||||||
|
|
||||||
|
public ComponentState CrawlerStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Crawler != null)
|
||||||
|
{
|
||||||
|
if (Crawler.ThreadStates.Length > 0)
|
||||||
|
{
|
||||||
|
return ComponentState.STARTED;
|
||||||
|
}
|
||||||
|
return ComponentState.INITIALIZED;
|
||||||
|
}
|
||||||
|
return ComponentState.STOPPED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace ln.skyscanner.http
|
||||||
{
|
{
|
||||||
SkyScanner = skyScannerHttpApplication.SkyScanner;
|
SkyScanner = skyScannerHttpApplication.SkyScanner;
|
||||||
|
|
||||||
TemplateResource statistics = new TemplateResource(this, System.IO.Path.Combine(SkyScanner.BasePath,"templates","statistics.html"), SkyScanner);
|
SkyScannerHttpManagement management = new SkyScannerHttpManagement(this,SkyScanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
// /**
|
||||||
|
// * File: SkyScannerHttpManagement.cs
|
||||||
|
// * Author: haraldwolff
|
||||||
|
// *
|
||||||
|
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||||
|
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||||
|
// *
|
||||||
|
// *
|
||||||
|
// **/
|
||||||
|
using System;
|
||||||
|
using ln.http.resources;
|
||||||
|
using ln.logging;
|
||||||
|
using System.Threading;
|
||||||
|
namespace ln.skyscanner.http
|
||||||
|
{
|
||||||
|
public class SkyScannerHttpManagement : JsonCallResource
|
||||||
|
{
|
||||||
|
public SkyScanner SkyScanner { get; }
|
||||||
|
|
||||||
|
public SkyScannerHttpManagement(Resource container,SkyScanner skyScanner)
|
||||||
|
: base(container, "management")
|
||||||
|
{
|
||||||
|
SkyScanner = skyScanner;
|
||||||
|
}
|
||||||
|
public SkyScannerHttpManagement(Resource container, string name, SkyScanner skyScanner)
|
||||||
|
: base(container, name)
|
||||||
|
{
|
||||||
|
SkyScanner = skyScanner;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Callable]
|
||||||
|
public SkyScannerStatistics GetStatistics()
|
||||||
|
{
|
||||||
|
SkyScannerStatistics statistics = new SkyScannerStatistics(SkyScanner);
|
||||||
|
return statistics;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Callable]
|
||||||
|
public void StartCrawler()
|
||||||
|
{
|
||||||
|
Logging.Log(LogLevel.INFO, "Management: StartCrawler() called");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Callable]
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
Thread thread = new Thread(()=>SkyScanner.Stop());
|
||||||
|
thread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class SkyScannerStatistics
|
||||||
|
{
|
||||||
|
public SkyScannerState States;
|
||||||
|
|
||||||
|
public SkyScannerStatistics(SkyScanner skyScanner)
|
||||||
|
{
|
||||||
|
States.HttpServer = skyScanner.HttpStatus;
|
||||||
|
States.Crawler = skyScanner.CrawlerStatus;
|
||||||
|
|
||||||
|
States.Checks = ComponentState.STOPPED;
|
||||||
|
States.Dispatcher = ComponentState.STOPPED;
|
||||||
|
|
||||||
|
|
||||||
|
States.Manager = ComponentState.STARTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public struct SkyScannerState
|
||||||
|
{
|
||||||
|
public ComponentState HttpServer;
|
||||||
|
public ComponentState Crawler;
|
||||||
|
public ComponentState Manager;
|
||||||
|
public ComponentState Checks;
|
||||||
|
public ComponentState Dispatcher;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,6 +50,7 @@
|
||||||
<Compile Include="SkyScanner.cs" />
|
<Compile Include="SkyScanner.cs" />
|
||||||
<Compile Include="http\SkyScannerHttpApplication.cs" />
|
<Compile Include="http\SkyScannerHttpApplication.cs" />
|
||||||
<Compile Include="http\SkyScannerHttpApi.cs" />
|
<Compile Include="http\SkyScannerHttpApi.cs" />
|
||||||
|
<Compile Include="http\SkyScannerHttpManagement.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
@ -62,10 +63,10 @@
|
||||||
<None Include="templates\static\style.css">
|
<None Include="templates\static\style.css">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Include="templates\statistics.html">
|
<None Include="templates\static\interface.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Include="templates\static\interface.js">
|
<None Include="templates\static\workspace.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
|
|
||||||
<link href="/static/style.css" rel="stylesheet" />
|
<link href="/static/style.css" rel="stylesheet" />
|
||||||
<script type="text/javascript" src="/static/interface.js"></script>
|
<script type="text/javascript" src="/static/interface.js"></script>
|
||||||
|
<script type="text/javascript" src="/static/workspace.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body onload="initApi('<%=request.self()%>');">
|
||||||
<div id="body">
|
<div id="body">
|
||||||
<section id="header">
|
<section id="header">
|
||||||
<div class="skylogo">
|
<div class="skylogo">
|
||||||
|
@ -16,16 +17,38 @@
|
||||||
|
|
||||||
<div id="indicators">
|
<div id="indicators">
|
||||||
<div id="indHttpServer" class="indicator" state="STARTED"><div></div>HTTPServer</div>
|
<div id="indHttpServer" class="indicator" state="STARTED"><div></div>HTTPServer</div>
|
||||||
<div id="indManager" class="indicator"><div></div>Manager</div>
|
<div id="indManager" class="indicator" state=""><div></div>Manager</div>
|
||||||
<div id="indCrawler" class="indicator"><div></div>Crawler</div>
|
<div id="indCrawler" class="indicator" state=""><div></div>Crawler</div>
|
||||||
<div id="indChecks" class="indicator"><div></div>Checks</div>
|
<div id="indChecks" class="indicator" state=""><div></div>Checks</div>
|
||||||
<div id="indHttpServer" class="indicator"><div></div>Message Dispatcher</div>
|
<div id="indDispatcher" class="indicator" state=""><div></div>Message Dispatcher</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section id="nav">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<a href=""><div>Übersicht</div></a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href=""><div>Crawler</div></a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href=""><div>Überwachung</div></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="nav"></section>
|
|
||||||
<section id="state"></section>
|
<section id="state"></section>
|
||||||
<section id="content"><%=__frame__%></section>
|
<section id="content">
|
||||||
<section id="footer"></section>
|
<%=__frame__%>
|
||||||
|
</section>
|
||||||
|
<section id="footer">
|
||||||
|
<div>
|
||||||
|
<button onclick="api.call('api/management','Shutdown')">Shutdown</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
workspace = new Workspace();
|
||||||
|
workspace.createPanel("Ein Test Panel","Ich bin ein Panel");
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
<%frame "frame.html"%>
|
<%frame "frame.html"%>
|
||||||
|
|
||||||
<h1>SkyScanner</h1>
|
<div id="workspace">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
|
@ -2,16 +2,107 @@
|
||||||
|
|
||||||
function API(baseurl){
|
function API(baseurl){
|
||||||
|
|
||||||
|
this.baseurl = baseurl;
|
||||||
|
|
||||||
|
this.get = function(page, handler = null){
|
||||||
|
var x = new XMLHttpRequest();
|
||||||
|
var async = (handler != null);
|
||||||
|
|
||||||
|
if (async)
|
||||||
|
{
|
||||||
|
x.onload = function(){
|
||||||
|
var responseText = x.responseText;
|
||||||
|
handler( responseText );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x.open("GET", this.baseurl + page, async);
|
||||||
|
x.send();
|
||||||
|
|
||||||
|
if (!async)
|
||||||
|
return x.responseText
|
||||||
|
}
|
||||||
|
this.post = function(page, handler = null){
|
||||||
|
var x = new XMLHttpRequest();
|
||||||
|
if (handler != null)
|
||||||
|
{
|
||||||
|
x.onload = function(){
|
||||||
|
var responseText = x.responseText;
|
||||||
|
handler( responseText );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x.open("POST", this.baseurl + page);
|
||||||
|
x.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getJson = function(page, handler){
|
||||||
|
var j = function(t){
|
||||||
|
handler(JSON.parse(t));
|
||||||
|
};
|
||||||
|
return this.get( page, j );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.call = function(endpoint,method,parameters = []){
|
||||||
|
var x = new XMLHttpRequest();
|
||||||
|
x.open("POST", this.baseurl + endpoint, false);
|
||||||
|
x.setRequestHeader("content-type","application/json");
|
||||||
|
|
||||||
|
var methodCall = {
|
||||||
|
"MethodName": method,
|
||||||
|
"Parameters": parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
x.send(JSON.stringify(methodCall));
|
||||||
|
|
||||||
|
var result = JSON.parse(x.responseText);
|
||||||
|
if (result.Exception != null)
|
||||||
|
throw result.Exception;
|
||||||
|
|
||||||
|
return result.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function $(id)
|
||||||
|
{
|
||||||
|
return document.getElementById(id);
|
||||||
|
}
|
||||||
|
function CE(eName)
|
||||||
|
{
|
||||||
|
return document.createElement(eName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var api = null;
|
||||||
api = API("<%=request.self()%>");
|
|
||||||
|
|
||||||
|
|
||||||
function loadStatistics()
|
function loadStatistics()
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var stats = api.call("api/management","GetStatistics");
|
||||||
|
|
||||||
|
$("indHttpServer").attributes["state"].value = stats.States.HttpServer;
|
||||||
|
$("indManager").attributes["state"].value = stats.States.Manager;
|
||||||
|
$("indCrawler").attributes["state"].value = stats.States.Crawler;
|
||||||
|
$("indChecks").attributes["state"].value = stats.States.Checks;
|
||||||
|
$("indDispatcher").attributes["state"].value = stats.States.Dispatcher;
|
||||||
|
|
||||||
|
} catch (e)
|
||||||
|
{
|
||||||
|
$("indHttpServer").attributes["state"].value = 3;
|
||||||
|
$("indManager").attributes["state"].value = 0;
|
||||||
|
$("indCrawler").attributes["state"].value = 0;
|
||||||
|
$("indChecks").attributes["state"].value = 0;
|
||||||
|
$("indDispatcher").attributes["state"].value = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function initApi(baseurl)
|
||||||
|
{
|
||||||
|
api = new API(baseurl);
|
||||||
|
setInterval( loadStatistics, 1000 );
|
||||||
|
|
||||||
|
log("API initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,18 @@
|
||||||
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header {
|
#header {
|
||||||
|
@ -43,7 +55,7 @@
|
||||||
}
|
}
|
||||||
.indicator > div {
|
.indicator > div {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: red;
|
background-color: #404040;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 11px;
|
width: 11px;
|
||||||
height: 11px;
|
height: 11px;
|
||||||
|
@ -52,6 +64,71 @@
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.indicator[state=STARTED] > div {
|
.indicator[state="1"] > div {
|
||||||
background-color: #00D000;
|
background-color: #C0C000;
|
||||||
}
|
}
|
||||||
|
.indicator[state="2"] > div {
|
||||||
|
background-color: #00D000;
|
||||||
|
}
|
||||||
|
.indicator[state="3"] > div {
|
||||||
|
background-color: #D00000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
bottom: 0px;
|
||||||
|
height: 32px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
|
||||||
|
|
||||||
|
background-color: #c7def5;
|
||||||
|
padding: 6px;
|
||||||
|
padding-left: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav {
|
||||||
|
display: block;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav > div {
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav > div > div {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
width: 160px;
|
||||||
|
|
||||||
|
|
||||||
|
border: 1px solid black;
|
||||||
|
padding: 4px;
|
||||||
|
|
||||||
|
margin-left: 32px;
|
||||||
|
margin-right: 32px;
|
||||||
|
|
||||||
|
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
top: 80px;
|
||||||
|
bottom: 32px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
|
||||||
|
background-color: #F0F0D0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#workspace {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
function Workspace()
|
||||||
|
{
|
||||||
|
this.desktop = $("workspace");
|
||||||
|
|
||||||
|
this.loadPanel = function(title,page){
|
||||||
|
var content = api.get(page);
|
||||||
|
this.createPanel(title,content);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.createPanel = function(title,content){
|
||||||
|
var divFrame = CE("div");
|
||||||
|
var divTitle = CE("div");
|
||||||
|
var divPanel = CE("DIV");
|
||||||
|
|
||||||
|
divFrame.appendChild(divTitle);
|
||||||
|
divFrame.appendChild(divPanel);
|
||||||
|
|
||||||
|
divTitle.innerText = title;
|
||||||
|
divPanel.innerText = content;
|
||||||
|
|
||||||
|
this.desktop.appendChild(divFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var workspace = null;
|
|
@ -1,6 +0,0 @@
|
||||||
<%=response.SetHeader("Content-Type","application/json")%>
|
|
||||||
{
|
|
||||||
"ComponentState": {
|
|
||||||
"HttpServer": "<%=this.HttpStatus%>"
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue