Dispatch table; server statistics
This commit is contained in:
parent
ef5c9c061a
commit
ea0d0e7681
|
@ -0,0 +1,54 @@
|
|||
(* Copyright 2012 Tony Garnock-Jones <tonygarnockjones@gmail.com>. *)
|
||||
|
||||
(* This file is part of Ocamlmsg. *)
|
||||
|
||||
(* Ocamlmsg is free software: you can redistribute it and/or modify it *)
|
||||
(* under the terms of the GNU General Public License as published by the *)
|
||||
(* Free Software Foundation, either version 3 of the License, or (at your *)
|
||||
(* option) any later version. *)
|
||||
|
||||
(* Ocamlmsg is distributed in the hope that it will be useful, but *)
|
||||
(* WITHOUT ANY WARRANTY; without even the implied warranty of *)
|
||||
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *)
|
||||
(* General Public License for more details. *)
|
||||
|
||||
(* You should have received a copy of the GNU General Public License *)
|
||||
(* along with Ocamlmsg. If not, see <http://www.gnu.org/licenses/>. *)
|
||||
|
||||
type t =
|
||||
| Num of float
|
||||
| Str of string
|
||||
| Arr of t list
|
||||
| Rec of (string * t) list
|
||||
|
||||
let escape_re = Str.regexp "\""
|
||||
let escape_char s =
|
||||
match s with
|
||||
| "\"" -> "\\\""
|
||||
| _ -> failwith ("Unexpected JSON char to escape: " ^ s)
|
||||
let escape s = Str.global_substitute escape_re escape_char s
|
||||
|
||||
let str_to_string s =
|
||||
"\"" ^ escape s ^ "\""
|
||||
|
||||
let rec to_string j =
|
||||
match j with
|
||||
| Num f ->
|
||||
if float_of_int (int_of_float f) = f
|
||||
then string_of_int (int_of_float f)
|
||||
else string_of_float f
|
||||
| Str s ->
|
||||
str_to_string s
|
||||
| Arr js ->
|
||||
"[" ^ String.concat "," (List.map to_string js) ^ "]"
|
||||
| Rec kvs ->
|
||||
"{" ^ String.concat "," (List.map kv_to_string kvs) ^ "}"
|
||||
|
||||
and kv_to_string (k, v) =
|
||||
str_to_string k ^ ":" ^ to_string v
|
||||
|
||||
let resp code reason j =
|
||||
Httpd.resp_generic code reason
|
||||
[Httpd.content_type_header_name, "application/json"]
|
||||
(Httpd.Fixed (to_string j))
|
||||
let resp_ok j = resp 200 "OK" j
|
29
ui_main.ml
29
ui_main.ml
|
@ -17,8 +17,23 @@
|
|||
|
||||
open Html
|
||||
|
||||
let dispatch_table = ref []
|
||||
|
||||
let register_dispatcher (prefix, handler) =
|
||||
dispatch_table := (prefix, handler) :: !dispatch_table
|
||||
|
||||
let handle_dynamic_req r =
|
||||
Httpd.http_error_html 500 "Not yet implemented" []
|
||||
let rec search_table table =
|
||||
match table with
|
||||
| [] ->
|
||||
Httpd.http_error_html 404 "Not found"
|
||||
[Html.tag "p" [] [Html.text ("No route for URL path "^r.Httpd.path)]]
|
||||
| (prefix, handler) :: rest ->
|
||||
if Util.starts_with r.Httpd.path prefix
|
||||
then handler r
|
||||
else search_table rest
|
||||
in
|
||||
search_table !dispatch_table
|
||||
|
||||
let handle_req r =
|
||||
if Util.starts_with r.Httpd.path "/_"
|
||||
|
@ -34,5 +49,17 @@ let start (s, peername) =
|
|||
(Httpd.main handle_req)
|
||||
(s, peername)
|
||||
|
||||
let boot_time = Unix.time ()
|
||||
let api_server_stats r =
|
||||
Json.resp_ok (Json.Rec
|
||||
["connection_count", Json.Num (float_of_int !Connections.connection_count);
|
||||
"boot_time", Json.Num boot_time;
|
||||
"uptime", Json.Num (Unix.time () -. boot_time)])
|
||||
|
||||
let register_api_hooks () =
|
||||
List.iter register_dispatcher
|
||||
["/_/server_stats", api_server_stats]
|
||||
|
||||
let init () =
|
||||
register_api_hooks ();
|
||||
ignore (Util.create_thread "HTTP listener" None (Net.start_net "HTTP" 5678) start)
|
||||
|
|
|
@ -1,9 +1,48 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Ocamlmsg</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<link rel="stylesheet" type="text/css" href="ui.css">
|
||||
<script type="text/javascript" src="jquery-1.7.2.min.js"></script>
|
||||
<script type="text/javascript" src="ui_main.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Ocamlmsg</h1>
|
||||
<p>Welcome to Ocamlmsg.</p>
|
||||
<div id="page">
|
||||
<div id="header">
|
||||
<div class="mainmenu">
|
||||
<ul>
|
||||
<li><a href="/">Main page</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<h1>Ocamlmsg</h1>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Server Status</th>
|
||||
<td id="server_ok"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Server statistics</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Connection count</th>
|
||||
<td id="server_stats_connection_count"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Boot time</th>
|
||||
<td id="server_stats_boot_time"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Uptime</th>
|
||||
<td id="server_stats_uptime"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script>$(document).ready(ui_main);</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,347 @@
|
|||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #4B4B61;
|
||||
}
|
||||
|
||||
body, th, td, input, textarea {
|
||||
font-family: 'Lora', Georgia;
|
||||
font-size: 10pt;
|
||||
color: #4B4B61;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: 'Mako', Georgia;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
margin-top: 0.5em;
|
||||
color: #C11C51;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
h1 a, h2 a, h3 a {
|
||||
color: #C11C51;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
p, ul, ol {
|
||||
margin-top: 1em;
|
||||
line-height: 1.2em;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
ul ul {
|
||||
margin-top: 0.5em;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
ul p {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
margin-bottom: 0.5em;
|
||||
margin-left: 3em;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin-left: 3em;
|
||||
margin-right: 3em;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #ff8827;
|
||||
}
|
||||
|
||||
hr {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#page {
|
||||
width: 630px;
|
||||
margin: 0 auto;
|
||||
background: #FFFFFF;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#header {
|
||||
padding-bottom: 2px;
|
||||
border-bottom: solid #4B4B61 1px;
|
||||
}
|
||||
|
||||
#header h2 {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#header a {
|
||||
font-variant: small-caps;
|
||||
}
|
||||
|
||||
.historylinks {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.historylinks.bottom {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.footnotes {
|
||||
border-top: dashed #4B4B61 1px;
|
||||
font-size: 0.8em;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 0;
|
||||
padding-top: 0;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
padding-bottom: 15px;
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.content h1 {
|
||||
margin: 0;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 5px;
|
||||
text-align: left;
|
||||
font-size: 24pt;
|
||||
}
|
||||
|
||||
.content .entry_footer {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
float: left;
|
||||
width: 150px;
|
||||
padding-top: 30px;
|
||||
padding-right: 10px;
|
||||
padding-bottom: 0px;
|
||||
padding-left: 10px;
|
||||
text-align: left;
|
||||
|
||||
border-left: solid #A5A5AF 1px;
|
||||
margin-left: -1px;
|
||||
}
|
||||
|
||||
.sidebar ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
font-size: 1.5em;
|
||||
color: #C11C51;
|
||||
}
|
||||
|
||||
.sidebar li {
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.sidebar li ul {
|
||||
padding-top: 0.5em;
|
||||
padding-left: 10px;
|
||||
font-size: 0.7em;
|
||||
}
|
||||
|
||||
.sidebar li li {
|
||||
}
|
||||
|
||||
.sidebar li a { color: #FF8827; }
|
||||
.sidebar li li a { color: #C11C51; }
|
||||
|
||||
.sidebar a:hover {
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#footer {
|
||||
background: #FFFFFF;
|
||||
padding-top: 0.5em;
|
||||
margin-bottom: 1em;
|
||||
border-top: solid #4B4B61 1px;
|
||||
}
|
||||
|
||||
#footer p {
|
||||
text-align: center;
|
||||
font-size: 8pt;
|
||||
color: #dd2865;
|
||||
}
|
||||
|
||||
div.sitemap_subcategory {
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
.sitemap_categorylink {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pinkborder {
|
||||
border: solid #C11C51 1px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.rightfloat, .leftfloat {
|
||||
margin: 0.3em;
|
||||
}
|
||||
|
||||
a img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.imagecenter {
|
||||
text-align: center;
|
||||
margin: 0.3em;
|
||||
}
|
||||
|
||||
.leftfloat {
|
||||
float: left;
|
||||
margin-left: 0px;
|
||||
margin-right: 1em;
|
||||
}
|
||||
.rightfloat {
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.topspace {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
table {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 0.5em;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: normal;
|
||||
color: #C11C51;
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.mainmenu ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.mainmenu ul li {
|
||||
display: inline;
|
||||
float: right;
|
||||
text-align: center;
|
||||
margin-left: 0.5em;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 0.5em;
|
||||
margin-top: 0.5em;
|
||||
background-color: #eeeeee;
|
||||
color: black;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
sup {
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
.lshift_archive_dateline {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.lshift_archive_explanation {
|
||||
text-align: center;
|
||||
padding-bottom: 1em;
|
||||
margin-bottom: 1em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.lshift_archive .right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.lshift_archive blockquote {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.lshift_archive table {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-top: solid #C11C51 2px;
|
||||
border-bottom: solid #C11C51 2px;
|
||||
}
|
||||
|
||||
.lshift_archive td, .lshift_archive th {
|
||||
font-size: 100%;
|
||||
padding: 0.1em 0.2em;
|
||||
}
|
||||
|
||||
.lshift_archive th {
|
||||
text-align: center;
|
||||
border-bottom: solid #C11C51 1px;
|
||||
}
|
||||
|
||||
.lshift_archive .center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.lshift_archive hr {
|
||||
display: block;
|
||||
border: none;
|
||||
border-top: dashed #4B4B61 1px;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.lshift_archive_comment_heading {
|
||||
padding-top: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.lshift_archive .blog_comment_header {
|
||||
color: #C11C51;
|
||||
font-family: 'Lora', Georgia;
|
||||
font-style: italic;
|
||||
font-size: 10pt;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.lshift_archive .blog_comment {
|
||||
margin-left: 2em;
|
||||
border-left: solid #ff8827 1px;
|
||||
padding-left: 1em;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
.server_ok {
|
||||
width: 100px;
|
||||
background: green;
|
||||
}
|
||||
|
||||
.server_not_ok {
|
||||
width: 100px;
|
||||
background: red;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
function refresh_server_stats() {
|
||||
$.getJSON("/_/server_stats", function (data) {
|
||||
$("#server_ok")[0].className = "server_ok";
|
||||
$("#server_stats_connection_count").text(data.connection_count);
|
||||
$("#server_stats_boot_time").text(new Date(data.boot_time * 1000));
|
||||
$("#server_stats_uptime").text(data.uptime + " seconds");
|
||||
}).error(function () {
|
||||
$("#server_ok")[0].className = "server_not_ok";
|
||||
});
|
||||
}
|
||||
|
||||
function ui_main() {
|
||||
refresh_server_stats();
|
||||
setInterval(refresh_server_stats, 5000);
|
||||
}
|
Loading…
Reference in New Issue