diff options
-rw-r--r-- | debian/changelog | 7 | ||||
-rw-r--r-- | debian/control | 2 | ||||
-rw-r--r-- | libcommon/tempfile.cpp | 14 | ||||
-rw-r--r-- | libcommon/tempfile.h | 3 | ||||
-rw-r--r-- | plugins/statistics/Makefile | 4 | ||||
-rw-r--r-- | plugins/statistics/statistics.cpp | 48 | ||||
-rw-r--r-- | plugins/webbox/webbox.cpp | 3 | ||||
-rw-r--r-- | plugins/weblog/weblog.cpp | 2 |
8 files changed, 71 insertions, 12 deletions
diff --git a/debian/changelog b/debian/changelog index 954078d..8075e41 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +webserver (1.12) unstable; urgency=medium + + * Add gnuplot generated statistics in statistics plugin + * End articles with square + + -- Roland Reichwein <rr@antcom.de> Sat, 19 Dec 2020 11:36:46 +0100 + webserver (1.11) unstable; urgency=medium * Bugfix: ZIP download in webbox was broken diff --git a/debian/control b/debian/control index 5ea967d..9738e34 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,7 @@ Homepage: http://www.reichwein.it/webserver/ Package: webserver Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, zip +Depends: ${shlibs:Depends}, ${misc:Depends}, zip, gnuplot Provides: httpd Homepage: http://www.reichwein.it/webserver/ Description: Web server diff --git a/libcommon/tempfile.cpp b/libcommon/tempfile.cpp index c30bb57..f425db2 100644 --- a/libcommon/tempfile.cpp +++ b/libcommon/tempfile.cpp @@ -14,10 +14,15 @@ fs::path Tempfile::GetPath() const return m_path; } -Tempfile::Tempfile() { +Tempfile::Tempfile(const std::filesystem::path& extension) +{ try { - char name[] = "/tmp/tempfileXXXXXX.zip"; - int fd = mkstemps(name, 4); + fs::path path { fs::temp_directory_path() / "tempfileXXXXXX"}; + if (!extension.empty()) + path += extension; + + fs::path::string_type name{path.native()}; + int fd = mkstemps(name.data(), extension.native().size()); if (fd == -1) std::runtime_error("mkstemps: "s + strerror(errno)); close(fd); @@ -27,7 +32,8 @@ Tempfile::Tempfile() { } } -Tempfile::~Tempfile() { +Tempfile::~Tempfile() +{ try { fs::remove_all(m_path); } catch (const std::exception& ex) { diff --git a/libcommon/tempfile.h b/libcommon/tempfile.h index 5938fb9..b9839a7 100644 --- a/libcommon/tempfile.h +++ b/libcommon/tempfile.h @@ -9,7 +9,8 @@ class Tempfile public: std::filesystem::path GetPath() const; - Tempfile(); + // extension: e.g. ".zip" + Tempfile(const std::filesystem::path& extension = std::filesystem::path{}); ~Tempfile(); }; diff --git a/plugins/statistics/Makefile b/plugins/statistics/Makefile index 8e8a6f7..34c0229 100644 --- a/plugins/statistics/Makefile +++ b/plugins/statistics/Makefile @@ -28,8 +28,8 @@ SRC=$(PROGSRC) all: $(PROJECTNAME).so -$(PROJECTNAME).so: $(SRC:.cpp=.o) - $(CXX) $(CXXFLAGS) $^ -shared $(LIBS) -o $@ +$(PROJECTNAME).so: ../../libcommon/libcommon.a $(SRC:.cpp=.o) + $(CXX) $(LDFLAGS) $^ -shared $(LDLIBS) $(LIBS) -o $@ ../../libcommon/libcommon.a: cd ../.. && $(MAKE) libcommon/libcommon.a 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; diff --git a/plugins/webbox/webbox.cpp b/plugins/webbox/webbox.cpp index d19f428..26d49c8 100644 --- a/plugins/webbox/webbox.cpp +++ b/plugins/webbox/webbox.cpp @@ -5,7 +5,6 @@ #include "libcommon/file.h" #include "libcommon/stringutil.h" - #include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/split.hpp> @@ -511,7 +510,7 @@ protected: return HttpStatus("500", "Change path error: "s + ex.what(), p); } - Tempfile tempfile; // guards this path, removing file afterwards via RAII + Tempfile tempfile{".zip"}; // guards this path, removing file afterwards via RAII arglist = "/usr/bin/zip -r - "s + arglist + " > "s + tempfile.GetPath().string(); diff --git a/plugins/weblog/weblog.cpp b/plugins/weblog/weblog.cpp index a64ee1b..c26a4fe 100644 --- a/plugins/weblog/weblog.cpp +++ b/plugins/weblog/weblog.cpp @@ -302,7 +302,7 @@ namespace { HtmlPage htmlPage{GetRequestParam, "<h1>"s + metaData.at("Subject") + "</h1>" "<div class=\"date\">" + metaData.at("Date") + "</div>" - "<br/><br/>"s + data}; + "<br/><br/>"s + data + "<br/>□"}; return htmlPage; } catch (const std::exception& ex) { |