0
|
1 <!DOCTYPE html>
|
|
2 <html>
|
|
3 <head>
|
|
4 <title>collector</title>
|
|
5 <meta charset="utf-8" />
|
|
6 </head>
|
|
7 <body class="rdfBrowsePage">
|
|
8 <h1>collector</h1>
|
|
9
|
|
10 <p><a href="/rdf/browse/?graph=/sse_collector/graph/home">See output for graph/home</a></p>
|
|
11
|
|
12 <collector-state></collector-state>
|
|
13 <script type="module">
|
|
14 import { LitElement, html, css, customElement } from "https://cdn.skypack.dev/lit-element";
|
|
15 export class CollectorState extends LitElement {
|
|
16 static get properties() {
|
|
17 return {
|
|
18 latestState: { type: Object },
|
|
19 };
|
|
20 }
|
|
21
|
|
22 constructor() {
|
|
23 super();
|
|
24 }
|
|
25
|
|
26 firstUpdated() {
|
|
27 this.latestState = { graphClients: {} };
|
|
28 this.refresh();
|
|
29 }
|
|
30
|
|
31 delayedRefresh() {
|
|
32 setTimeout(() => {
|
|
33 requestAnimationFrame(() => {
|
|
34 this.refresh();
|
|
35 });
|
|
36 }, 5000);
|
|
37 }
|
|
38
|
|
39 refresh() {
|
|
40 fetch("state")
|
|
41 .then((response) => {
|
|
42 return response.json();
|
|
43 })
|
|
44 .then((newState) => {
|
|
45 this.latestState = newState;
|
|
46 this.delayedRefresh();
|
|
47 });
|
|
48 }
|
|
49
|
|
50 static get styles() {
|
|
51 return css`
|
|
52 :host {
|
|
53 display: inline-block;
|
|
54 border: 2px solid gray;
|
|
55 padding: 5px;
|
|
56 }
|
|
57 `;
|
|
58 }
|
|
59
|
|
60 render() {
|
|
61 const sourcesTable = (clients) => {
|
|
62 const clientRow = (client) => {
|
|
63 const d = client.reconnectedPatchSource;
|
|
64 const now = Date.now() / 1000;
|
|
65 const dispSec = (sec) =>
|
|
66 Math.abs(sec) > now - 1
|
|
67 ? "--"
|
|
68 : Math.abs(sec) > 3600
|
|
69 ? `${Math.round(sec / 3600)} hr`
|
|
70 : Math.abs(sec) > 60
|
|
71 ? `${Math.round(sec / 60)} min`
|
|
72 : `${Math.round(sec * 10) / 10} sec`;
|
|
73 return html`
|
|
74 <tr>
|
|
75 <td><a href="${d.url.replace("/events", "")}">[browse]</a> <a href="${d.url}">${d.url}</a></td>
|
|
76 <td>${d.fullGraphReceived}</td>
|
|
77 <td>${d.patchesReceived}</td>
|
|
78 <td>${dispSec(d.time.open - now)}</td>
|
|
79 <td>${dispSec(d.time.fullGraph - d.time.open)}</td>
|
|
80 <td>${dispSec(d.time.latestPatch - now)}</td>
|
|
81 </tr>
|
|
82 `;
|
|
83 };
|
|
84
|
|
85 return html`
|
|
86 <table>
|
|
87 <thead>
|
|
88 <tr>
|
|
89 <th>patch source</th>
|
|
90 <th>full graph recv</th>
|
|
91 <th>patches recv</th>
|
|
92 <th>time open (rel)</th>
|
|
93 <th>time fullGraph (after open)</th>
|
|
94 <th>time latest patch (rel)</th>
|
|
95 </tr>
|
|
96 </thead>
|
|
97 <tbody>
|
|
98 ${clients.map(clientRow)}
|
|
99 </tbody>
|
|
100 </table>
|
|
101 `;
|
|
102 };
|
|
103
|
|
104 const handlersTable = (handlers) => {
|
|
105 const handlerRow = (d) => {
|
|
106 return html`
|
|
107 <tr>
|
|
108 <td>${d.created}</td>
|
|
109 <td>${d.ageHours}</td>
|
|
110 <td><a href="/rdf/browse/?graph=/sse_collector/graph/${d.streamId}">${d.streamId}</a></td>
|
|
111 <td>${d.foafAgent}</td>
|
|
112 <td>${d.userAgent}</td>
|
|
113 </tr>
|
|
114 `;
|
|
115 };
|
|
116
|
|
117 return html`
|
|
118 <table>
|
|
119 <thead>
|
|
120 <tr>
|
|
121 <th>created</th>
|
|
122 <th>age hours</th>
|
|
123 <th>stream</th>
|
|
124 <th>foaf agent</th>
|
|
125 <th>user agent</th>
|
|
126 </tr>
|
|
127 </thead>
|
|
128 <tbody>
|
|
129 ${handlers.map(handlerRow)}
|
|
130 </tbody>
|
|
131 </table>
|
|
132 `;
|
|
133 };
|
|
134
|
|
135 if (!this.latestState) {
|
|
136 return "loading...";
|
|
137 }
|
|
138 const d = this.latestState.graphClients;
|
|
139 return html` <div>
|
|
140 <p>Graph: ${d.statements ? d.statements.len : 0} statements</p>
|
|
141
|
|
142 <p>Sources: ${sourcesTable(d.clients || [])}</p>
|
|
143
|
|
144 <p>Listening clients: ${handlersTable(d.sseHandlers || [])}</p>
|
|
145 </div>`;
|
|
146 }
|
|
147 }
|
|
148 customElements.define("collector-state", CollectorState);
|
|
149 </script>
|
|
150 </body>
|
|
151 </html>
|