From 04819714be166d4085d7e253cb5aeac26997884b Mon Sep 17 00:00:00 2001 From: acidumirae Date: Sun, 11 Dec 2022 11:50:01 +0800 Subject: [PATCH] GELF remote logging to graylog --- wrenchboard/build/wrenchboard_api.cc | 1 + wrenchboard/etc/wrenchboard_api.conf | 2 +- wrenchboard/src/core/clog.cc | 98 +++++++++++-------------- wrenchboard/src/core/wrenchboard.cc | 43 ++++++++++- wrenchboard/src/core/wrenchboard_api.cc | 78 +++++++++++++++----- wrenchboard/src/include/clog.h | 10 +-- 6 files changed, 153 insertions(+), 79 deletions(-) diff --git a/wrenchboard/build/wrenchboard_api.cc b/wrenchboard/build/wrenchboard_api.cc index ac0f95e5..f59634b4 100644 --- a/wrenchboard/build/wrenchboard_api.cc +++ b/wrenchboard/build/wrenchboard_api.cc @@ -62,6 +62,7 @@ PHP_METHOD(WrenchBoard, __construct) SET_ENV( "HTTP_X_FORWARDED_FOR" ); } zend_string_release(_server); + intern->wrenchboard->logMessage("Constructor finished"); } } diff --git a/wrenchboard/etc/wrenchboard_api.conf b/wrenchboard/etc/wrenchboard_api.conf index 01844a15..81c516d9 100644 --- a/wrenchboard/etc/wrenchboard_api.conf +++ b/wrenchboard/etc/wrenchboard_api.conf @@ -148,7 +148,7 @@ logger: host = "10.0.0.112"; port = 12201L; file = 0L; - level = "DEBUG"; # 3L; + level = "FLOG_MAX"; # 0 - ERROR # 1 - WARNING # 2 - INFO diff --git a/wrenchboard/src/core/clog.cc b/wrenchboard/src/core/clog.cc index 20228656..787d16bc 100644 --- a/wrenchboard/src/core/clog.cc +++ b/wrenchboard/src/core/clog.cc @@ -1,13 +1,20 @@ #include "clog.h" #include "cfg.h" #include "php_wrenchboard_log.h" + #include +#include +#include +#include + using namespace gelfcpp::output; TLogLevel global_log_level = FLOG_MAX; // By default log everything -GelfUDPOutput graylog(CfgReadChar("logger.host"), CfgReadLong("logger.port")); +GelfUDPOutput *graylog; +using Decorator = gelfcpp::decorator::StaticDecoratorSet; +Decorator decorator; void logfmt( TLogLevel level, const char * format, ... ) { if (level > global_log_level) { @@ -36,24 +43,13 @@ void logfmt( TLogLevel level, const char * format, ... ) { va_end (args); // Graylog if (strlen(buffer) > 0) { - if (false) { - FILE_LOG(logERROR) << "graylog is null!" ; + if (graylog) { + GELF_MESSAGE(*graylog)(decorator) + (buffer) + ("pid", getpid()) + ("loglevel", FILELog::ToString(level).c_str()); } else { - gelfcpp::GelfMessageStream stream(graylog); - if (stream) { - stream.Send(graylog) = gelfcpp::GelfMessageBuilder() - (CurrentTimeStamp()) - ("level", FILELog::ToString(level).c_str()) - ("pid", getpid()) - (buffer); - } else { - FILE_LOG(logERROR) << "GelfMessageStream failed!" ; - } - GELF_MESSAGE(graylog) - (CurrentTimeStamp()) - ("level", FILELog::ToString(level).c_str()) - ("pid", getpid()) - (buffer); + FILE_LOG(logERROR) << "graylog is null!" ; } } else { FILE_LOG(logERROR) << "buffer length is " << strlen(buffer) ; @@ -79,45 +75,39 @@ void logfmt( TLogLevel level, const char * format, ... ) { } */ -void GraylogStream(std::string raw) { -/* +void GraylogStream(TLogLevel level, std::string raw) { + if (!graylog) { + std::cerr << "graylog is null!"; // We cannot use log here as it will go recursive + return; // Not initialized, yet? + } if (!raw.empty()) { - GELF_MESSAGE(graylog) - (CurrentTimeStamp()) + /* GELF_MESSAGE(*graylog)(decorator) + (raw.c_str()); ("pid", getpid()) - ("level", "FLOG_MAX") - (raw.c_str()); + ("loglevel", "FLOG_MAX"); */ + + std::string marker ("]: "); + + std::size_t found = raw.find(marker); + if (found != std::string::npos) { + std::string msg = raw.substr (found + 3); + std::string levelString = FILELog::ToString(level); + + if (!msg.empty()) { + GELF_MESSAGE(*graylog)(decorator) + (msg.c_str()) + ("pid", getpid()) + ("loglevel", levelString.c_str()); + } else { + std::cerr << "Message is empty!"; + } + } else { + std::cerr << "Marker '" << marker << "' was not found!"; + } + // */ + } else { + std::cerr << "Raw message is empty!"; } -*/ - std::string marker1 ("]: "); - std::string marker2 (" ["); - std::string marker3 (" "); - - std::size_t found = raw.find(marker1); - if (found != std::string::npos) { - std::string msg = raw.substr (found + 3); - std::string level ("FLOG_MAX"); - - found = raw.find(marker2); - if (found != std::string::npos) { - std::string str = raw.substr(0, found - 1); - boost::trim_right(str); - found = str.find(marker3); - /* while (found != std::string::npos) { - level = str.substr(found); - found = str.find(marker3); - } // */ - } - - if (!msg.empty()) { - GELF_MESSAGE(graylog) - (CurrentTimeStamp()) - ("pid", getpid()) - ("level", level.c_str()) - (msg.c_str()); - } - } - // */ } // */ diff --git a/wrenchboard/src/core/wrenchboard.cc b/wrenchboard/src/core/wrenchboard.cc index e989018e..100cd860 100644 --- a/wrenchboard/src/core/wrenchboard.cc +++ b/wrenchboard/src/core/wrenchboard.cc @@ -12,6 +12,14 @@ #include #include +#include +#include +#include + +extern gelfcpp::output::GelfUDPOutput *graylog; +using Decorator = gelfcpp::decorator::StaticDecoratorSet; +extern Decorator decorator; + WrenchBoard::WrenchBoard() { // Read config @@ -19,7 +27,8 @@ WrenchBoard::WrenchBoard() { this->logFile = CfgReadLong("logger.file"); // global_log_level = static_cast(CfgReadLong("logger.level")); - global_log_level = FILELog().FromString(CfgReadChar("logger.level")); + const char *logLevel = CfgReadChar("logger.level"); + global_log_level = FILELog::FromString(logLevel); FILELog().SetReportingLevel(global_log_level); // Open log @@ -27,6 +36,18 @@ WrenchBoard::WrenchBoard() { this->pFile = fopen(WRENCHBOARD_LOG, "a"); Output2FILE::Stream() = pFile; } + + const char *logHost = CfgReadChar("logger.host"); + long logPort = CfgReadLong("logger.port"); + + // Instantiate remote logger (GELF) + graylog = new gelfcpp::output::GelfUDPOutput(logHost, logPort); + std::string msg = "Instantiate remote logger (GELF)"; + GELF_MESSAGE(*graylog)(decorator) + (msg.c_str()) + ("pid", getpid()) + ("loglevel", logLevel); + //*/ FILE_LOG(logINFO) << "WRENCHBOARD is starting..."; logfmt(logINFO, "Version from config: %s", CfgReadChar("version")); @@ -78,6 +99,22 @@ long WrenchBoard::cfgReadLong(const char *parameter) { void WrenchBoard::logMessage(const char *message) { FILE_LOG(logINFO) << message; + + const char* remote_addr = std::getenv( "REMOTE_ADDR" ); + const char* server_name = std::getenv( "SERVER_NAME" ); + const char* http_cookie = std::getenv( "HTTP_COOKIE" ); + const char* query_string = std::getenv( "QUERY_STRING" ); + // const char* http_x_ff = std::getenv( "HTTP_X_FORWARDED_FOR" ); + + GELF_MESSAGE(*graylog)(decorator) + ("Environment variables") + ("pid", getpid()) + ("loglevel", global_log_level) + ("REMOTE_ADDR", remote_addr) + ("SERVER_NAME", server_name) + ("HTTP_COOKIE", http_cookie) + ("QUERY_STRING", query_string); + // ("HTTP_X_FORWARDED_FOR", http_x_ff); } WrenchBoard::~WrenchBoard() { @@ -92,5 +129,9 @@ WrenchBoard::~WrenchBoard() { fclose(this->pFile); } // */ } + // clean-up GELF + if (graylog) { + delete graylog; + } } diff --git a/wrenchboard/src/core/wrenchboard_api.cc b/wrenchboard/src/core/wrenchboard_api.cc index 5cd353c9..656d6348 100644 --- a/wrenchboard/src/core/wrenchboard_api.cc +++ b/wrenchboard/src/core/wrenchboard_api.cc @@ -62,6 +62,7 @@ PHP_METHOD(WrenchBoard, __construct) SET_ENV( "HTTP_X_FORWARDED_FOR" ); } zend_string_release(_server); + intern->wrenchboard->logMessage("Constructor finished"); } } @@ -73,10 +74,15 @@ PHP_METHOD(WrenchBoard, wrenchboard_api) wrenchboard_object *intern; CVars input, output; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", ¶m, ¶m_out) == FAILURE) { + /* if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", ¶m, ¶m_out) == FAILURE) { // Bad parameters RETURN_NULL(); - } + } */ + // https://wiki.php.net/rfc/fast_zpp + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_ARRAY_EX(param, 0, 1) + Z_PARAM_ARRAY_EX(param_out, 0, 1) + ZEND_PARSE_PARAMETERS_END(); intern = Z_TSTOBJ_P(id); if(intern != NULL) { @@ -119,25 +125,33 @@ PHP_METHOD(WrenchBoard, wrenchboard_api) const int out_size = output.size(); // 200 const int out_value_size = 200; char out_key[out_value_size], out_value[out_value_size]; - if (!output.empty()) { - array_init(param_out); + + if (!output.empty()) { + // array_init(param_out); // deferences variable & nothing comes out :( // for ( i=output.begin(); i != output.end() && jfirst.c_str(), i->second.c_str() ); strsafecpy( out_key, i->first.c_str(), out_value_size ); strsafecpy( out_value, i->second.c_str(), out_value_size ); - //add_assoc_string( param_out, out_key, out_value); - add_assoc_string_ex( param_out, out_key, strlen(out_key), out_value); + if (strlen(out_key)>0) { + /* + char *str; + str = estrdup(i->second.c_str()); + add_assoc_string( param_out, out_key, str, 0); + */ + //add_assoc_string( param_out, out_key, out_value); + add_assoc_string_ex( param_out, out_key, strlen(out_key), out_value); + } //SAFE_STRING - //efree(out_value); - output.erase(output.begin()); - } - } + //efree(out_value); + output.erase(output.begin()); + } + //RETURN_ZVAL(param_out, 0, 0); // Possible workaround to return array + } logfmt( logDEBUG, "About to return %ld", retval ); - RETURN_LONG(retval); } @@ -214,13 +228,41 @@ PHP_METHOD(WrenchBoard, logMessage) RETURN_FALSE; } +// ------------------------------------------------------------------ // ------------------------------------------------------------------ + +// https://www.phpinternalsbook.com/php7/extensions_design/php_functions.html +// https://github.com/php/php-src/blob/master/Zend/zend_builtin_functions_arginfo.h + +// ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) + // ZEND_ARG_INFO(pass_by_ref, name) + // ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) + // ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) + // ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) + // ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) + // ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) +// ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_void, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_string, 0, 0, 1) + ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_api, 0, 0, 2) + //ZEND_ARG_TYPE_INFO(1, in, IS_ARRAY, 0) + //ZEND_ARG_TYPE_INFO(1, out, IS_ARRAY, 0) + ZEND_ARG_ARRAY_INFO(1, in, 0) + ZEND_ARG_ARRAY_INFO(1, out, 0) +ZEND_END_ARG_INFO() + // ------------------------------------------------------------------ // ------------------------------------------------------------------ const zend_function_entry wrenchboard_methods[] = { - PHP_ME(WrenchBoard, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(WrenchBoard, wrenchboard_api, NULL, ZEND_ACC_PUBLIC) - PHP_ME(WrenchBoard, cfgReadChar, NULL, ZEND_ACC_PUBLIC) - PHP_ME(WrenchBoard, cfgReadLong, NULL, ZEND_ACC_PUBLIC) - PHP_ME(WrenchBoard, logMessage, NULL, ZEND_ACC_PUBLIC) + PHP_ME(WrenchBoard, __construct, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(WrenchBoard, wrenchboard_api, arginfo_api, ZEND_ACC_PUBLIC) + PHP_ME(WrenchBoard, cfgReadChar, arginfo_string, ZEND_ACC_PUBLIC) + PHP_ME(WrenchBoard, cfgReadLong, arginfo_string, ZEND_ACC_PUBLIC) + PHP_ME(WrenchBoard, logMessage, arginfo_string, ZEND_ACC_PUBLIC) PHP_FE_END }; diff --git a/wrenchboard/src/include/clog.h b/wrenchboard/src/include/clog.h index 34028bc9..83b3cecb 100644 --- a/wrenchboard/src/include/clog.h +++ b/wrenchboard/src/include/clog.h @@ -17,14 +17,14 @@ #include #include -inline std::string NowTime(); -inline gelfcpp::decorator::CurrentTimestamp CurrentTimeStamp(); -void GraylogStream(std::string raw); - enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4, logSQL, FLOG_MAX}; extern TLogLevel global_log_level; +inline gelfcpp::decorator::CurrentTimestamp CurrentTimeStamp(); +inline std::string NowTime(); +void GraylogStream(TLogLevel level, std::string raw); + void logfmt( TLogLevel level, const char * format, ... ); template @@ -71,7 +71,7 @@ Log::~Log() } // Graylog - GraylogStream(os.str()); + GraylogStream(currentLevel, os.str()); os << std::endl;