├── .gitignore
├── screenshot.png
├── .travis.yml
├── psd3.min.css
├── status.css
├── README.md
├── status.html
├── psd3.min.js
├── updatedata.js
├── watcher.cpp
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | watcher
2 | test.json
3 | nginx.log
4 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sjtug/nginx-simple-watcher/master/screenshot.png
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: cpp
2 | before_install:
3 | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
4 | - sudo apt-get -qq update
5 | - sudo apt-get install gcc-5 g++-5 -y
6 | - export CXX="g++-5" CC="gcc-5"
7 | script:
8 | - $CXX -std=c++14 -Wall -Wextra -Werror -O2 watcher.cpp -o watcher -pthread
9 |
--------------------------------------------------------------------------------
/psd3.min.css:
--------------------------------------------------------------------------------
1 | .psd3Tooltip,text{pointer-events:none}.psd3Tooltip p,text{font-family:sans-serif}text{font-size:12px}g.arc path:hover{fill:orange}.psd3Tooltip{position:absolute;max-width:150px;height:auto;padding:10px;background-color:#fff;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;-webkit-box-shadow:4px 4px 10px rgba(0,0,0,.4);-moz-box-shadow:4px 4px 10px rgba(0,0,0,.4);box-shadow:4px 4px 10px rgba(0,0,0,.4)}.psd3Hidden{display:none}.psd3Tooltip p{margin:0;font-size:16px;line-height:20px}
--------------------------------------------------------------------------------
/status.css:
--------------------------------------------------------------------------------
1 | ul.pure-menu-list>li
2 | {
3 | display: inline-block;
4 | vertical-align: middle;
5 | padding: 0;
6 | margin: 0;
7 | height: 100%;
8 | position: relative;
9 | }
10 |
11 | ul.pure-menu-list>li:hover
12 | {
13 | background-color: #ddd;
14 | }
15 |
16 | ul.pure-menu-list>li>a
17 | {
18 | color: #777;
19 | white-space: nowrap;
20 | display: block;
21 | text-decoration: none;
22 | padding: .5em 1em;
23 | }
24 |
25 | table
26 | {
27 | text-align: center;
28 | }
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #Nginx-Simple-Watcher 
2 |
3 | A zero-extra-dependency C++14 nginx server watcher providing CPU usage, mem usage, latest nginx logs and hottest directories, all in JSON format.
4 |
5 | A simple static web frontend is also provided.
6 |
7 | *Linux3.2+ only.*
8 | ## Compile
9 | Use any compiler that has support for C++14.
10 |
11 | ```
12 | g++ -std=c++14 -O2 watcher.cpp -o watcher -pthread
13 | ```
14 |
15 | ## Usage
16 | ```
17 | ./watcher nginx_access_log_path sleep_second serve_content_root output_json_path
18 | ```
19 |
20 | Then copy `status.html`, `updatedata.js`, `status.css`, `psd3.min.css`, `psd3.min.js` to the same directory as the json's.
21 |
22 | ## Screenshot
23 |
24 | 
25 |
26 | ## Output Format
27 | ```json
28 | {
29 | "cpu":
30 | [
31 | ["time_1", 10.1],
32 | ["time_2", 29]
33 | ],
34 | "mem":
35 | {
36 | "realUsed":
37 | [
38 | ["time_1", 1234],
39 | ["time_2", 1300]
40 | ],
41 | "used":
42 | [
43 | ["time_1", 2300],
44 | ["time_2", 2400]
45 | ]
46 | },
47 | "nginx":
48 | {
49 | "data":
50 | [
51 | {
52 | "path": "/test/",
53 | "method": "GET",
54 | "status": 200,
55 | "time": "time_1"
56 | }
57 | ]
58 | },
59 | "hotDir":
60 | [
61 | {
62 | "count": 22,
63 | "name": "/",
64 | "drilldown":
65 | [
66 | {
67 | "count": 11,
68 | "name": "archlinux/",
69 | "drilldown": []
70 | }
71 | ]
72 | }
73 | ]
74 | }
75 | ```
76 |
77 | Modify `NginxLogEntryParser` to meet your nginx access log format!
78 |
79 | ## License
80 | This project is under GPLv3 license, see `LICENSE` for details.
81 |
82 | `json.hpp` is from https://github.com/nlohmann/json, which is licensed under the MIT license.
83 |
84 | `psd3.min.css` and `psd3.min.js` are from https://github.com/pshivale/psd3, which is also licensed under MIT license.
85 |
86 | > This program is free software: you can redistribute it and/or modify
87 | it under the terms of the GNU General Public License as published by
88 | the Free Software Foundation, either version 3 of the License, or
89 | (at your option) any later version.
90 |
91 | > This program is distributed in the hope that it will be useful,
92 | but WITHOUT ANY WARRANTY; without even the implied warranty of
93 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
94 | GNU General Public License for more details.
95 |
96 | > You should have received a copy of the GNU General Public License
97 | along with this program. If not, see .
98 |
--------------------------------------------------------------------------------
/status.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Server Status
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
Server Status
15 |
16 | Last update:
17 |
18 |
19 |
24 |
29 |
30 | Disk space:
31 | GiB used.
32 | GiB available.
33 |
34 |
35 |
39 |
40 |
41 |
Nginx recent log
42 |
43 |
44 |
47 |
50 |
51 |
52 |
53 | |
54 | |
55 | |
56 | |
57 |
58 |
59 |
60 |
61 |
62 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/psd3.min.js:
--------------------------------------------------------------------------------
1 | var psd3=psd3||{};psd3.Graph=function(i){var t=this;this.config=i,this.defaults={width:400,height:400,value:"value",inner:"inner",label:function(i){return i.data.value},tooltip:function(i){return void 0!==t.config.value?i[t.config.value]:i.value},transition:"linear",transitionDuration:1e3,donutRadius:0,gradient:!1,colors:d3.scale.category20(),labelColor:"black",drilldownTransition:"linear",drilldownTransitionDuration:0,stroke:"white",strokeWidth:2,highlightColor:"orange"};for(var n in this.defaults)this.defaults.hasOwnProperty(n)&&(i.hasOwnProperty(n)||(i[n]=this.defaults[n]))};
2 | var psd3=psd3||{};psd3.Pie=function(t){psd3.Graph.call(this,t),this.zoomStack=[];var i="top";void 0!==this.config.heading&&void 0!==this.config.heading.pos&&(i=this.config.heading.pos),"top"==i&&this.setHeading(),this.drawPie(t.data),"bottom"==i&&this.setHeading()},psd3.Pie.prototype=Object.create(psd3.Graph.prototype),psd3.Pie.prototype.constructor=psd3.Pie,psd3.Pie.prototype.findMaxDepth=function(t){if(null===t||void 0===t||t.length<1)return 0;for(var i,e=0,n=0;ne&&(e=o)}return i=1+e},psd3.Pie.prototype.setHeading=function(){void 0!==this.config.heading&&d3.select("#"+this.config.containerId).append("div").style("text-align","center").style("width",""+this.config.width+"px").style("padding-top","20px").style("padding-bottom","20px").append("strong").text(this.config.heading.text)},psd3.Pie.prototype.mouseover=function(t){d3.select("#"+_this.tooltipId).style("left",d3.event.clientX+window.scrollX+"px").style("top",d3.event.clientY+window.scrollY+"px").select("#value").html(_this.config.tooltip(t.data,_this.config.label)),d3.select("#"+_this.tooltipId).classed("psd3Hidden",!1),d3.select(t.path).style("fill",_this.config.highlightColor)},psd3.Pie.prototype.mouseout=function(t){d3.select("#"+_this.tooltipId).classed("psd3Hidden",!0),d3.select(t.path).style("fill",t.fill)},psd3.Pie.prototype.drawPie=function(t){if(!(null===t||void 0===t||t.length<1)){_this=this,_this.arcIndex=0;var i=d3.select("#"+_this.config.containerId).append("svg").attr("id",_this.config.containerId+"_svg").attr("width",_this.config.width).attr("height",_this.config.height);_this.tooltipId=_this.config.containerId+"_tooltip";var e=d3.select("#"+_this.config.containerId).append("div").attr("id",_this.tooltipId).attr("class","psd3Hidden psd3Tooltip");e.append("p").append("span").attr("id","value").text("100%");var n;n=_this.config.width>_this.config.height?_this.config.width/2:_this.config.height/2;var o=_this.config.donutRadius,s=_this.findMaxDepth(t),a=o+(n-o)/s,r=a-o;_this.draw(i,n,t,t,t.length,o,a,r,0,7920/7/180,[0,0])}},psd3.Pie.prototype.customArcTween=function(t){var i={startAngle:t.startAngle,endAngle:t.startAngle},e=d3.interpolate(i,t);return function(i){return t.arc(e(i))}},psd3.Pie.prototype.textTransform=function(t){return"translate("+t.arc.centroid(t)+")"},psd3.Pie.prototype.textTitle=function(t){return t.data[_this.config.value]},psd3.Pie.prototype.draw=function(t,i,e,n,o,s,a,r,d,h,c){if(_this=this,!(null===e||void 0===e||e.length<1)){psd3.Pie.prototype.textText=function(t){return _this.config.label(t)};var l=d3.layout.pie();l.sort(null),l.value(function(t){return t[_this.config.value]}),l.startAngle(d).endAngle(h);for(var p=[],g=0;g
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include