]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/ws.cc
2 Copyright (C) 2002 - 2007 PowerDNS.COM BV
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License version 2
6 as published by the Free Software Foundation
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include "webserver.hh"
23 #include "arguments.hh"
25 #include <boost/format.hpp>
29 StatWebServer::StatWebServer()
32 d_min10
=d_min5
=d_min1
=0;
35 void StatWebServer::go()
38 pthread_create(&d_tid
, 0, threadHelper
, this);
39 pthread_create(&d_tid
, 0, statThreadHelper
, this);
42 void StatWebServer::statThread()
46 d_queries
.submit(S
.read("udp-queries"));
47 d_cachehits
.submit(S
.read("packetcache-hit"));
48 d_cachemisses
.submit(S
.read("packetcache-miss"));
49 d_qcachehits
.submit(S
.read("query-cache-hit"));
50 d_qcachemisses
.submit(S
.read("query-cache-miss"));
55 L
<<Logger::Error
<<"Webserver statThread caught an exception, dying"<<endl
;
60 void *StatWebServer::statThreadHelper(void *p
)
62 StatWebServer
*sws
=static_cast<StatWebServer
*>(p
);
64 return 0; // never reached
68 void *StatWebServer::threadHelper(void *p
)
70 StatWebServer
*sws
=static_cast<StatWebServer
*>(p
);
72 return 0; // never reached
75 void printtable(ostringstream
&ret
, const string
&ringname
, const string
&title
, int limit
=10)
79 vector
<pair
<string
,int> >ring
=S
.getRing(ringname
);
81 for(vector
<pair
<string
,int> >::const_iterator i
=ring
.begin(); i
!=ring
.end();++i
) {
87 ret
<<"<table border=1><tr><td colspan=3 bgcolor=#0000ff>"
88 "<a href=?ring="<<ringname
<<"><font color=#ffffff>Top-"<<limit
<<" of ";
89 ret
<<entries
<<": "<<title
<<"</a></td>"<<endl
;
91 ret
<<"<tr><td colspan=3><table bgcolor=#ff0000 width=100%><tr><td align=left>"
92 "<a href=?resetring="<<ringname
<<"><font color=#ffffff>Reset</a></td>";
93 ret
<<"<td align=right>Resize: ";
95 int sizes
[]={10,100,500,1000,10000,500000,0};
96 for(int i
=0;sizes
[i
];++i
) {
97 if(S
.getRingSize(ringname
)!=sizes
[i
])
98 ret
<<"<a href=?resizering="<<ringname
<<"&size="<<sizes
[i
]<<">"<<sizes
[i
]<<"</a> ";
100 ret
<<"("<<sizes
[i
]<<") ";
102 ret
<<"</td></table>"<<endl
;
106 for(vector
<pair
<string
,int> >::const_iterator i
=ring
.begin();limit
&& i
!=ring
.end();++i
,--limit
) {
107 ret
<<"<tr><td>"<<i
->first
<<"</td><td>"<<i
->second
<<"</td><td align=right>"<< StatWebServer::makePercentage(i
->second
*100.0/tot
)<<"</td>"<<endl
;
110 ret
<<"<tr><td colspan=3></td></tr>"<<endl
;
112 ret
<<"<tr><td><b>Rest:</b></td><td><b>"<<tot
-printed
<<"</b></td><td align=right><b>"<< StatWebServer::makePercentage((tot
-printed
)*100.0/tot
)<<"</b></td>"<<endl
;
114 ret
<<"<tr><td><b>Total:</b></td><td><b>"<<tot
<<"</td><td align=right><b>100%</b></td>";
115 ret
<<"</table><p>"<<endl
;
118 void StatWebServer::printvars(ostringstream
&ret
)
120 ret
<<"<table border=1><tr><td colspan=3 bgcolor=#0000ff><font color=#ffffff>Variables</td>"<<endl
;
123 vector
<string
>entries
=S
.getEntries();
124 for(vector
<string
>::const_iterator i
=entries
.begin();i
!=entries
.end();++i
) {
125 ret
<<"<tr><td>"<<*i
<<"</td><td>"<<S
.read(*i
)<<"</td><td>"<<S
.getDescrip(*i
)<<"</td>"<<endl
;
129 void StatWebServer::printargs(ostringstream
&ret
)
131 ret
<<"<table border=1><tr><td colspan=3 bgcolor=#0000ff><font color=#ffffff>Arguments</td>"<<endl
;
133 vector
<string
>entries
=arg().list();
134 for(vector
<string
>::const_iterator i
=entries
.begin();i
!=entries
.end();++i
) {
135 ret
<<"<tr><td>"<<*i
<<"</td><td>"<<arg()[*i
]<<"</td><td>"<<arg().getHelp(*i
)<<"</td>"<<endl
;
139 string
StatWebServer::makePercentage(const double& val
)
141 return (boost::format("%.01f%%") % val
).str();
144 string
StatWebServer::indexfunction(const map
<string
,string
> &varmap
, void *ptr
, bool *custom
)
147 StatWebServer
*sws
=static_cast<StatWebServer
*>(ptr
);
148 map
<string
,string
>rvarmap
=varmap
;
149 if(!rvarmap
["resetring"].empty()){
151 S
.resetRing(rvarmap
["resetring"]);
152 return "HTTP/1.1 301 Moved Permanently\nLocation: /\nConnection: close\n\n";
154 if(!rvarmap
["resizering"].empty()){
156 S
.resizeRing(rvarmap
["resizering"], atoi(rvarmap
["size"].c_str()));
157 return "HTTP/1.1 301 Moved Permanently\nLocation: /\nConnection: close\n\n";
162 ret
<<"<html><head><title>PowerDNS Operational Monitor</title></head><body bgcolor=#ffffff>"<<endl
;
166 if(!arg()["config-name"].empty())
167 ret
<<"["<<arg()["config-name"]<<"]";
168 if(rvarmap
["ring"].empty())
169 ret
<<"PDNS "VERSION
" Main Page</h2>"<<endl
;
171 ret
<<"Details page</h2><a href=/>Back to main page</a><p>"<<endl
;
173 time_t passed
=time(0)-s_starttime
;
176 ret
<<humanDuration(passed
)<<endl
;
179 ret
<<"Queries/second, 1, 5, 10 minute averages: "<<setprecision(3)<<
180 sws
->d_queries
.get1()<<", "<<
181 sws
->d_queries
.get5()<<", "<<
182 sws
->d_queries
.get10()<<". Max queries/second: "<<sws
->d_queries
.getMax()<<
185 if(sws
->d_cachemisses
.get10()+sws
->d_cachehits
.get10()>0)
186 ret
<<"Cache hitrate, 1, 5, 10 minute averages: "<<
187 makePercentage((sws
->d_cachehits
.get1()*100.0)/((sws
->d_cachehits
.get1())+(sws
->d_cachemisses
.get1())))<<", "<<
188 makePercentage((sws
->d_cachehits
.get5()*100.0)/((sws
->d_cachehits
.get5())+(sws
->d_cachemisses
.get5())))<<", "<<
189 makePercentage((sws
->d_cachehits
.get10()*100.0)/((sws
->d_cachehits
.get10())+(sws
->d_cachemisses
.get10())))<<
192 if(sws
->d_qcachemisses
.get10()+sws
->d_qcachehits
.get10()>0)
193 ret
<<"Backend query cache hitrate, 1, 5, 10 minute averages: "<<setprecision(2)<<
194 makePercentage((sws
->d_qcachehits
.get1()*100.0)/((sws
->d_qcachehits
.get1())+(sws
->d_qcachemisses
.get1())))<<", "<<
195 makePercentage((sws
->d_qcachehits
.get5()*100.0)/((sws
->d_qcachehits
.get5())+(sws
->d_qcachemisses
.get5())))<<", "<<
196 makePercentage((sws
->d_qcachehits
.get10()*100.0)/((sws
->d_qcachehits
.get10())+(sws
->d_qcachemisses
.get10())))<<
199 ret
<<"Backend query load, 1, 5, 10 minute averages: "<<setprecision(3)<<
200 sws
->d_qcachemisses
.get1()<<", "<<
201 sws
->d_qcachemisses
.get5()<<", "<<
202 sws
->d_qcachemisses
.get10()<<". Max queries/second: "<<sws
->d_qcachemisses
.getMax()<<
205 ret
<<"Total queries: "<<S
.read("udp-queries")<<". Question/answer latency: "<<S
.read("latency")/1000.0<<"ms<p>"<<endl
;
206 if(rvarmap
["ring"].empty()) {
207 vector
<string
>entries
=S
.listRings();
208 for(vector
<string
>::const_iterator i
=entries
.begin();i
!=entries
.end();++i
)
209 printtable(ret
,*i
,S
.getRingTitle(*i
));
212 if(arg().mustDo("webserver-print-arguments"))
216 printtable(ret
,rvarmap
["ring"],S
.getRingTitle(rvarmap
["ring"]),100);
218 ret
<<"</body></html>"<<endl
;
223 void StatWebServer::launch()
226 WebServer
ws(arg()["webserver-address"], arg().asNum("webserver-port"),arg()["webserver-password"]);
228 ws
.registerHandler("",&indexfunction
);
232 L
<<Logger::Error
<<"StatWebserver thread caught an exception, dying"<<endl
;