changeset 1451:71684fc9c692

new index page table Ignore-this: 7668675a04bd5cc03cf4e1799c54d4d1 darcs-hash:5b546637d01f1fa70134c09470007ed1251d708c
author drewp <drewp@bigasterisk.com>
date Wed, 25 Sep 2019 17:27:35 -0700
parents ca96da46c73e
children 1dd4da407c0b
files service/collector/sse_collector.py service/collector/static/index.html service/collector/static/state.js
diffstat 3 files changed, 161 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/service/collector/sse_collector.py	Wed Sep 25 17:25:36 2019 -0700
+++ b/service/collector/sse_collector.py	Wed Sep 25 17:27:35 2019 -0700
@@ -120,7 +120,8 @@
             'created': round(self.created, 2),
             'ageHours': round((time.time() - self.created) / 3600, 2),
             'streamId': self.streamId,
-            'remoteIp': self.request.remote_ip,
+            'remoteIp': self.request.remote_ip, # wrong, need some forwarded-for thing
+            'foafAgent': self.request.headers.get('X-Foaf-Agent'),
             'userAgent': self.request.headers.get('user-agent'),
         }
         
@@ -282,8 +283,10 @@
 
     def state(self) -> Dict:
         return {
-            'clients': [ps.state() for ps in self.clients.values()],
-            'sseHandlers': [h.state() for h in self.handlers],
+            'clients': sorted([ps.state() for ps in self.clients.values()],
+                              key=lambda r: r['reconnectedPatchSource']['url']),
+            'sseHandlers': sorted([h.state() for h in self.handlers],
+                                  key=lambda r: (r['streamId'],  r['created'])),
             'statements': self.statements.state(),
         }
 
@@ -420,13 +423,7 @@
         except Exception:
             import traceback; traceback.print_exc()
             raise
-        
-        
-class Root(cyclone.web.RequestHandler):
-    def get(self) -> None:
-        self.write('<html><body>sse_collector</body></html>')
-
-        
+              
 if __name__ == '__main__':
     arg = docopt("""
     Usage: sse_collector.py [options]
@@ -447,7 +444,9 @@
         9072,
         cyclone.web.Application(
             handlers=[
-                (r'/', Root),
+                (r"/()", cyclone.web.StaticFileHandler, {
+                    "path": "static", "default_filename": "index.html"}),
+                (r'/static/(.*)',cyclone.web.StaticFileHandler, {"path": "static"}), 
                 (r'/state', State),
                 (r'/graph/(.*)', PatchSink),
                 (r'/stats/(.*)', StatsHandler, {'serverName': 'collector'}),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/collector/static/index.html	Wed Sep 25 17:27:35 2019 -0700
@@ -0,0 +1,21 @@
+<!doctype html>
+<html>
+  <head>
+    <title>collector</title>
+    <meta charset="utf-8">
+    <script src="/lib/polymer/1.0.9/webcomponentsjs/webcomponents.min.js"></script>
+    <script src="/lib/require/require-2.3.3.js"></script>
+    <script src="/rdf/common_paths_and_ns.js"></script>
+
+    <link rel="stylesheet" href="/rdf/browse/style.css">
+
+    <script type="module" src="static/state.js"></script>
+  </head>
+  <body class="rdfBrowsePage">
+    <h1>collector</h1>
+
+    <p><a href="/rdf/browse/?graph=/sse_collector/graph/home">output for graph/home</a></p>
+
+   <collector-state></collector-state>
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/collector/static/state.js	Wed Sep 25 17:27:35 2019 -0700
@@ -0,0 +1,130 @@
+import { LitElement, TemplateResult, html, css } from '/lib/lit-element/2.2.0/lit-element-custom.js';
+
+class CollectorState extends LitElement {
+    static get properties() {
+        return {
+            latestState: { type: Object }
+        };
+    }
+    firstUpdated() {
+        this.latestState = {graphClients: {}};
+        this.refreshLoop();
+    }
+
+    refreshLoop() {
+        setTimeout(() => {
+            requestAnimationFrame(() => {
+                this.refresh();
+            });
+        }, 5000);
+    }
+
+    refresh() {
+        fetch('state')
+            .then((response) => {
+                return response.json();
+            })
+            .then((newState) => {
+                this.latestState = newState;
+                this.refreshLoop();
+            });
+    }
+
+    static get styles() {
+        return css`
+        :host {
+          display: inline-block;
+          border: 2px solid gray;
+          padding: 5px;
+        }`;
+    }
+
+    render() {
+        const sourcesTable = (clients) => {
+            const clientRow = (client) => {
+                const d = client.reconnectedPatchSource;
+                return html`
+                  <tr>
+                    <td><a href="/rdf/browse/?graph=${d.url}">[browse]</a> <a href="${d.url}">${d.url}</a></td>
+                    <td>${d.fullGraphReceived}</td>
+                    <td>${d.patchesReceived}</td>
+                    <td>${d.time.open}</td>
+                    <td>${d.time.fullGraph}</td>
+                    <td>${d.time.latestPatch}</td>
+                  </tr>
+                `;
+            };
+
+            return html`
+              <table>
+                <thead>
+                  <tr>
+                    <th>patch source</th>
+                    <th>full graph recv</th>
+                    <th>patches recv</th>
+                    <th>time open</th>
+                    <th>time fullGraph</th>
+                    <th>time latest patch</th>
+                  </tr>
+                </thead>
+                <tbody>
+                  ${clients.map(clientRow)}
+                </tbody>
+              </table>
+              `;
+        };
+
+        const handlersTable = (handlers) => {
+            const handlerRow = (d) => {
+                return html`
+                  <tr>
+                    <td>${d.created}</td>
+                    <td>${d.ageHours}</td>
+                    <td><a href="/rdf/browse/?graph=/sse_collector/graph/${d.streamId}">${d.streamId}</a></td>
+                    <td>${d.foafAgent}</td>
+                    <td>${d.userAgent}</td>
+                  </tr>
+                  `;
+            };
+
+            return html`
+              <table>
+                <thead>
+                  <tr>
+                    <th>created</th>
+                    <th>age hours</th>
+                    <th>stream</th>
+                    <th>foaf agent</th>
+                    <th>user agent</th>
+                  </tr>
+                </thead>
+                <tbody>
+                  ${handlers.map(handlerRow)}
+                </tbody>
+              </table>
+              `;
+        };
+
+        if (!this.latestState) {
+            return 'loading...';
+        }
+        const d = this.latestState.graphClients;
+        return html`
+          <div>
+            <p>
+              Graph: ${d.statements.len} statements
+            </p>
+
+            <p>
+              Sources:
+              ${sourcesTable(d.clients)}
+            </p>
+
+            <p>
+              Listening clients:
+              ${handlersTable(d.sseHandlers)}
+            </p>
+          </div>`;
+    }
+}
+customElements.define('collector-state', CollectorState);