diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2026-03-20 23:48:32 +0000 |
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2026-03-20 23:48:32 +0000 |
| commit | 05c47ab65e73b16887b7c7a1eb31acf6d364ef41 (patch) | |
| tree | 837a65e5460154a8c00c91519a8ea313445ad1dd | |
| parent | 0f5a0a8e2d43774288d4d6ea747278ca6e085a2a (diff) | |
| download | webstat-05c47ab65e73b16887b7c7a1eb31acf6d364ef41.tar.bz2 webstat-05c47ab65e73b16887b7c7a1eb31acf6d364ef41.tar.xz webstat-05c47ab65e73b16887b7c7a1eb31acf6d364ef41.zip | |
Add logging :-o
Adds virtual log function, real implementation writes to syslog.
Test implementation writes to BOOST_TEST_MESSAGE, perf implementation
discards.
Replaces existing prints to stderr and adds logs to all key points.
| -rw-r--r-- | src/ingestor.cpp | 28 | ||||
| -rw-r--r-- | src/ingestor.hpp | 1 | ||||
| -rw-r--r-- | src/webstat_logger_main.cpp | 16 | ||||
| -rw-r--r-- | test/perf-ingest.cpp | 11 | ||||
| -rw-r--r-- | test/test-ingest.cpp | 13 |
5 files changed, 59 insertions, 10 deletions
diff --git a/src/ingestor.cpp b/src/ingestor.cpp index 1de9ab9..fb592d7 100644 --- a/src/ingestor.cpp +++ b/src/ingestor.cpp @@ -109,8 +109,9 @@ namespace WebStat { } void - Ingestor::terminate(int) + Ingestor::terminate(int sigNo) { + log(LOG_NOTICE, "Caught sig %d, terminating", sigNo); terminated = true; curl_multi_wakeup(curl.get()); } @@ -154,7 +155,7 @@ namespace WebStat { } else { curlOperations.erase(msg->easy_handle); - std::println(std::cerr, "Failed to lookup CurlOperation"); + log(LOG_WARNING, "Failed to lookup CurlOperation"); } } } @@ -204,7 +205,8 @@ namespace WebStat { ingestLogLines(dbpool->get().get(), queuedLines); queuedLines.clear(); } - catch (const std::exception &) { + catch (const std::exception & excp) { + log(LOG_ERR, "Unhandled exception: %s, clearing known entity list", excp.what()); existingEntities.clear(); } } @@ -234,8 +236,12 @@ namespace WebStat { DB::TransactionScope dbtx {*dbconn}; const auto uninsertableLine = ToEntity<EntityType::UninsertableLine> {}(line); storeEntities(dbconn, {uninsertableLine}); + log(LOG_NOTICE, + "Failed to store parsed line and/or associated entties, but did store raw line, %u:%s", + std::get<Crc32Value>(uninsertableLine), line.c_str()); } - catch (const std::exception &) { + catch (const std::exception & excp) { + log(LOG_NOTICE, "Failed to store line in any form, DB connection lost? %s", excp.what()); throw originalError; } } @@ -243,6 +249,8 @@ namespace WebStat { else { linesDiscarded++; const auto unparsableLine = ToEntity<EntityType::UnparsableLine> {}(line); + log(LOG_NOTICE, "Failed to parse line, this is a bug: %u:%s", std::get<Crc32Value>(unparsableLine), + line.c_str()); storeEntities(dbconn, {unparsableLine}); } } @@ -263,10 +271,13 @@ namespace WebStat { if (fflush(parked.get()) == 0) { linesParked += queuedLines.size(); queuedLines.clear(); + return; } - else { - std::filesystem::remove(path); - } + std::filesystem::remove(path); + } + log(LOG_ERR, "Failed to park %zu queued lines:", queuedLines.size()); + for (const auto & line : queuedLines) { + log(LOG_ERR, "\t%.*s", static_cast<int>(line.length()), line.data()); } } @@ -280,7 +291,8 @@ namespace WebStat { job.currentRun->get(); job.lastRun = now; } - catch (const std::exception &) { + catch (const std::exception & excp) { + log(LOG_ERR, "Job run failed: %s", excp.what()); // Error, retry in half the frequency job.lastRun = now - (freq / 2); } diff --git a/src/ingestor.hpp b/src/ingestor.hpp index 94e0d5c..e890bcf 100644 --- a/src/ingestor.hpp +++ b/src/ingestor.hpp @@ -106,6 +106,7 @@ namespace WebStat { static void sigtermHandler(int); void terminate(int); + [[gnu::format(printf, 3, 4)]] virtual void log(int level, const char * msgfmt, ...) const = 0; using CurlOperations = std::map<CURL *, std::unique_ptr<CurlOperation>>; uint32_t hostnameId; diff --git a/src/webstat_logger_main.cpp b/src/webstat_logger_main.cpp index 39d794a..3eaa9f0 100644 --- a/src/webstat_logger_main.cpp +++ b/src/webstat_logger_main.cpp @@ -5,6 +5,7 @@ #include <iostream> #include <pq-connection.h> #include <sys/utsname.h> +#include <syslog.h> namespace { [[nodiscard]] @@ -17,6 +18,19 @@ namespace { } return uts; } + + class MainIngestor : public WebStat::Ingestor { + using Ingestor::Ingestor; + + void + log(int level, const char * msgfmt, ...) const override + { + va_list args; + va_start(args, msgfmt); + vsyslog(level, msgfmt, args); + va_end(args); + } + }; } #define LEXICAL_CAST_DURATION(UNIT) \ @@ -87,7 +101,7 @@ main(int argc, char ** argv) po::notify(optVars); try { - WebStat::Ingestor {getHostDetail(), std::move(settings)}.ingestLog(stdin); + MainIngestor {getHostDetail(), std::move(settings)}.ingestLog(stdin); return EXIT_SUCCESS; } catch (const std::exception & excp) { diff --git a/test/perf-ingest.cpp b/test/perf-ingest.cpp index c403349..cf0be0d 100644 --- a/test/perf-ingest.cpp +++ b/test/perf-ingest.cpp @@ -18,10 +18,19 @@ namespace { static const WebStat::MockDB mockdb; } + class PerfIngestor : public WebStat::Ingestor { + using Ingestor::Ingestor; + + void + log(int, const char *, ...) const override + { + } + }; + void doIngestFile(benchmark::State & state) { - WebStat::Ingestor ingestor {WebStat::getTestUtsName("perf-hostname"), + PerfIngestor ingestor {WebStat::getTestUtsName("perf-hostname"), std::make_shared<WebStat::MockDBPool>("webstat"), { .userAgentAPI = {}, diff --git a/test/test-ingest.cpp b/test/test-ingest.cpp index a1dc5e9..9ce48be 100644 --- a/test/test-ingest.cpp +++ b/test/test-ingest.cpp @@ -3,6 +3,7 @@ #include <boost/test/unit_test.hpp> #include "testing-util.hpp" +#include <cstdio> #include <selectcommandUtil.impl.h> #include <ingestor.hpp> @@ -217,6 +218,18 @@ public: } SPECIAL_MEMBERS_DELETE(TestIngestor); + + [[gnu::format(printf, 3, 4)]] void + log(int, const char * msgfmt, ...) const override + { + va_list args; + va_start(args, msgfmt); + std::unique_ptr<char, DeleteWith<&free>> msg; + BOOST_REQUIRE_GE(vasprintf(std::out_ptr(msg), msgfmt, args), 0); + va_end(args); + BOOST_REQUIRE(msg); + BOOST_TEST_MESSAGE(msg.get()); + } }; BOOST_FIXTURE_TEST_SUITE(I, TestIngestor); |
