diff options
author | Roland Reichwein <mail@reichwein.it> | 2020-12-20 16:52:47 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2020-12-20 16:52:47 +0100 |
commit | 73f0b597dec0705db01ed4eec7abaebc0295a243 (patch) | |
tree | 3599be15154a9eeaa09cb86e1918a13ac3a73bef /plugins/statistics/statistics.cpp | |
parent | ef63da27938ae091a341893c38e59d489888625a (diff) |
webserver 1.12: Added graphical statistics page (gnuplot generated)
Diffstat (limited to 'plugins/statistics/statistics.cpp')
-rw-r--r-- | plugins/statistics/statistics.cpp | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/plugins/statistics/statistics.cpp b/plugins/statistics/statistics.cpp index b1778f7..415369d 100644 --- a/plugins/statistics/statistics.cpp +++ b/plugins/statistics/statistics.cpp @@ -1,5 +1,8 @@ #include "statistics.h" +#include "libcommon/file.h" +#include "libcommon/tempfile.h" + #include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/split.hpp> #include <boost/coroutine2/coroutine.hpp> @@ -23,9 +26,48 @@ namespace { { SetResponseHeader("status", status); SetResponseHeader("content_type", "text/html"); + return status + " " + message; } + std::string statsPng(std::function<std::string(const std::string& key)>& GetServerParam, + std::function<plugin_interface_setter_type>& SetResponseHeader) + { + // Create PNG statistics via Gnuplot + std::string statistics{GetServerParam("statistics")}; + + Tempfile tempStats{".txt"}; // input data + File::setFile(tempStats.GetPath(), statistics); + + Tempfile tempPng{".png"}; // output + + Tempfile tempGnuplot{".gnuplot"}; + std::stringstream s; + s << "set terminal png truecolor\n"; + s << "set output " << tempPng.GetPath() << "\n"; // quotes added automatically for paths + s << "set title \"Webserver Throughput\"\n"; + s << "set xlabel \"Time\"\n"; + s << "set timefmt \"%s\"\n"; + s << "set format x \"%Y-%m-%d\"\n"; + s << "set xdata time\n"; + s << "set xtics rotate by 45 right\n"; + s << "set ylabel \"Bytes\"\n"; + s << "set datafile separator \",\"\n"; + s << "set grid\n"; + s << "set style fill solid\n"; + s << "plot " << tempStats.GetPath() << " using 1:($4+$5) with boxes title \"Bytes I/O\" lt rgb \"#1132A7\"\n"; + File::setFile(tempGnuplot.GetPath(), s.str()); + + int exit_code{system(("gnuplot "s + tempGnuplot.GetPath().generic_string()).c_str())}; + if (exit_code) { + std::cerr << "Error: gnuplot returned " << std::to_string(exit_code) << std::endl; + return HttpStatus("500", "Statistics error"s, SetResponseHeader); + } + + SetResponseHeader("content_type", "image/png"); + return File::getFile(tempPng.GetPath()); + } + // returns sum over specified column uint64_t getSum(const std::string& stats, size_t column) { @@ -95,9 +137,12 @@ std::string statistics_plugin::generate_page( if (target.size() && target.back() != '/' && fs::is_directory(path)) { std::string location{GetRequestParam("location") + "/"s}; SetResponseHeader("location", location); - return HttpStatus("301", "Correcting directory path", SetResponseHeader); + return HttpStatus("301", "Correcting directory path", SetResponseHeader); // 301 Moved Permanently } + if (path.filename() == "stats.png") + return statsPng(GetServerParam, SetResponseHeader); + try { SetResponseHeader("content_type", "text/html"); @@ -122,6 +167,7 @@ std::string statistics_plugin::generate_page( result += "<p>IPv6 fraction by bytes: "s + std::to_string(ipv6_fraction_by_bytes * 100) + "%</p>"; result += "<p>HTTPS fraction by requests: "s + std::to_string(https_fraction_by_requests * 100) + "%</p>"; result += "<p>HTTPS fraction by bytes: "s + std::to_string(https_fraction_by_bytes * 100) + "%</p>"; + result += "<p><img src=\"stats.png\"/></p>"; result += "<pre>"s + statistics + "</pre>"s; result += footer; |