diff --git a/Makefile b/Makefile index 6bbd2fa78..22ac4dbe5 100644 --- a/Makefile +++ b/Makefile @@ -332,7 +332,7 @@ OBJS += ggml-alloc.o llama.o: llama.cpp ggml.h ggml-alloc.h ggml-cuda.h ggml-metal.h llama.h $(CXX) $(CXXFLAGS) -c $< -o $@ -common.o: common/common.cpp common/common.h +common.o: common/common.cpp common/common.h common/log.h $(CXX) $(CXXFLAGS) -c $< -o $@ console.o: common/console.cpp common/console.h @@ -351,7 +351,7 @@ clean: # Examples # -main: examples/main/main.cpp build-info.h ggml.o llama.o common.o common/log.h console.o grammar-parser.o $(OBJS) +main: examples/main/main.cpp build-info.h ggml.o llama.o common.o console.o grammar-parser.o $(OBJS) $(CXX) $(CXXFLAGS) $(filter-out %.h,$^) -o $@ $(LDFLAGS) @echo @echo '==== Run ./main -h for help. ====' diff --git a/common/common.cpp b/common/common.cpp index 53002ba30..454a9aea4 100644 --- a/common/common.cpp +++ b/common/common.cpp @@ -462,6 +462,7 @@ bool gpt_params_parse(int argc, char ** argv, gpt_params & params) { } } else if (arg == "-h" || arg == "--help") { gpt_print_usage(argc, argv, default_params); + log_print_usage(); exit(0); } else if (arg == "--random-prompt") { params.random_prompt = true; @@ -501,6 +502,23 @@ bool gpt_params_parse(int argc, char ** argv, gpt_params & params) { std::istreambuf_iterator(), std::back_inserter(params.grammar) ); + // Parse args for logging parameters + } else if ( log_param_single_parse( argv[i] ) ) { + // Do nothing, log_param_single_parse automatically does it's thing + // and returns if a match was found and parsed. + } else if ( log_param_pair_parse( /*check_but_dont_parse*/ true, argv[i] ) ) { + // We have a matching known parameter requiring an argument, + // now we need to check if there is anything after this argv + // and flag invalid_param or parse it. + if (++i >= argc) { + invalid_param = true; + break; + } + if( !log_param_pair_parse( /*check_but_dont_parse*/ false, argv[i-1], argv[i]) ) { + invalid_param = true; + break; + } + // End of Parse args for logging parameters } else { fprintf(stderr, "error: unknown argument: %s\n", arg.c_str()); gpt_print_usage(argc, argv, default_params); diff --git a/common/common.h b/common/common.h index 17d271e67..b3abc6ea2 100644 --- a/common/common.h +++ b/common/common.h @@ -4,6 +4,8 @@ #include "llama.h" +#include "log.h" + #include #include #include diff --git a/common/log.h b/common/log.h index 0f18c7c03..4e4100468 100644 --- a/common/log.h +++ b/common/log.h @@ -1,13 +1,10 @@ #pragma once -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - #include #include #include #include +#include // -------------------------------- // @@ -94,10 +91,37 @@ #define LOG_TEE_TARGET stderr #endif +// Utility to obtain "pid" like unique process id and use it when creating log files. +inline std::string log_get_pid() +{ + static std::string pid; + if (pid.empty()) [[unlikely]] + { + // std::this_thread::get_id() is the most portable way of obtaining a "process id" + // it's not the same as "pid" but is unique enough to solve multiple instances + // trying to write to the same log. + std::stringstream ss; + ss << std::this_thread::get_id(); + pid = ss.str(); + } + + return pid; +} + +// Utility function for generating log file names with unique id based on thread id. +// invocation with LOG_FILENAME_GENERATOR( "llama", "log" ) creates a string "llama..log" +// where the number is a runtime id of the current thread. + +#define LOG_FILENAME_GENERATOR(log_file_basename, log_file_extension) _log_filename_generator(log_file_basename, log_file_extension) + +// INTERNAL, DO NOT USE +inline std::string _log_filename_generator(std::string log_file_basename, std::string log_file_extension) +{ + return std::string().append(log_file_basename).append(".").append(log_get_pid()).append(".").append(log_file_extension); +} + #ifndef LOG_DEFAULT_FILE_NAME -// TODO: This should get a wrapper -// to let others have custom log names with automatic unique id -#define LOG_DEFAULT_FILE_NAME std::string().append("llama.").append(log_get_pid()).append(".log") +#define LOG_DEFAULT_FILE_NAME LOG_FILENAME_GENERATOR("llama", "log") #endif // Utility for turning #define values into string literals @@ -197,23 +221,6 @@ enum LogTriState // #define LOG_TEE(...) _LOG_TEE(__VA_ARGS__, '\0') -// Utility to obtain "pid" like unique process id and use it when creating log files. -inline std::string log_get_pid() -{ - static std::string pid; - if (pid.empty()) [[unlikely]] - { - // std::this_thread::get_id() is the most portable way of obtaining a "process id" - // it's not the same as "pid" but is unique enough to solve multiple instances - // trying to write to the same log. - std::stringstream ss; - ss << std::this_thread::get_id(); - pid = ss.str(); - } - - return pid; -} - // INTERNAL, DO NOT USE inline FILE *_log_handler1(bool change = false, LogTriState disable = LogTriStateSame, std::string filename = LOG_DEFAULT_FILE_NAME, FILE *target = nullptr) { @@ -355,4 +362,97 @@ inline FILE *log_set_target(std::string filename) { return _log_handler1(true, L inline FILE *log_set_target(FILE *target) { return _log_handler2(true, LogTriStateSame, target); } // INTERNAL, DO NOT USE -inline FILE *log_handler() { return _log_handler1(); } \ No newline at end of file +inline FILE *log_handler() { return _log_handler1(); } + +inline void log_test() +{ + std::cerr << "LOGDBG: LOGTEST" << std::endl; + + log_disable(); + LOG("01 Hello World to nobody, because logs are disabled!\n") + log_enable(); + LOG("02 Hello World to default output, which is \"%s\" ( Yaaay, arguments! )!\n", LOG_STRINGIZE(LOG_TARGET)) + LOG_TEE("03 Hello World to **both** default output and " LOG_TEE_TARGET_STRING "!\n") + log_set_target(stderr); + LOG("04 Hello World to stderr!\n") + LOG_TEE("05 Hello World TEE with double printing to stderr prevented!\n") + log_set_target(LOG_DEFAULT_FILE_NAME); + LOG("06 Hello World to default log file!\n") + log_set_target(stdout); + LOG("07 Hello World to stdout!\n") + log_set_target(LOG_DEFAULT_FILE_NAME); + LOG("08 Hello World to default log file again!\n") + log_disable(); + LOG("09 Hello World _1_ into the void!\n") + log_enable(); + LOG("10 Hello World back from the void ( you should not see _1_ in the log or the output )!\n") + log_disable(); + log_set_target("llama.anotherlog.log"); + LOG("11 Hello World _2_ to nobody, new target was selected but logs are still disabled!\n") + log_enable(); + LOG("12 Hello World this time in a new file ( you should not see _2_ in the log or the output )?\n") + log_set_target("llama.yetanotherlog.log"); + LOG("13 Hello World this time in yet new file?\n") + log_set_target(LOG_FILENAME_GENERATOR("llama_autonamed", "log")); + LOG("14 Hello World in log with generated filename!\n") + + //exit(0); +} + +inline bool log_param_single_parse(std::string param) +{ + std::cerr << "LOGDBG: single param: " << param << std::endl; + + if (std::string("--log-test").compare(param) == 0) + { + log_test(); + return true; + } + else if (std::string("--log-disable").compare(param) == 0) + { + log_disable(); + return true; + } + else if (std::string("--log-enable").compare(param) == 0) + { + log_enable(); + return true; + } + + std::cerr << "LOGDBG: single param NO MATCH " << param << std::endl; + + return false; +} + +inline bool log_param_pair_parse(bool check_but_dont_parse, std::string param, std::string next = std::string()) +{ + std::cerr << "LOGDBG: pair param: " << param << "/" << next << std::endl; + + if (std::string("--log-file").compare(param) == 0) + { + if( check_but_dont_parse ) + { + return true; + } + log_set_target(LOG_FILENAME_GENERATOR(next.empty() ? "unnamed" : next, "log")); + return true; + } + + std::cerr << "LOGDBG: pair param NO MATCH " << param << "/" << next << std::endl; + + return false; +} + +inline void log_print_usage() +{ + fprintf(stdout, "log options:\n"); + /* + fprintf(stdout, " -h, --help show this help message and exit\n"); + // spacing + fprintf(stdout, "__-param----------------Description\n");*/ + fprintf(stdout, " --log-test Run simple logging test\n"); + fprintf(stdout, " --log-disable Disable trace logs\n"); + fprintf(stdout, " --log-enable Enable trace logs\n"); + fprintf(stdout, " --log-file Specify a log filename (without extension)\n"); + fprintf(stdout, " Log file will be tagged with unique ID and written as \"..log\"\n"); /* */ +} diff --git a/examples/main/main.cpp b/examples/main/main.cpp index 3bcb551b4..8dcb48186 100644 --- a/examples/main/main.cpp +++ b/examples/main/main.cpp @@ -3,11 +3,8 @@ #define _GNU_SOURCE #endif -//#define LOG_TARGET log_handler("asd") -//#define LOG_NO_TIMESTAMPS #include "common.h" -#include "log.h" #include "console.h" #include "llama.h" #include "build-info.h" @@ -59,35 +56,10 @@ void sigint_handler(int signo) { #endif int main(int argc, char ** argv) { + LOG("Log start - start of main()\n") + gpt_params params; - log_disable(); - LOG("01 Hello World to nobody, because logs are disabled!\n") - log_enable(); - LOG("02 Hello World to default output, which is \"%s\" ( Yaaay, arguments! )!\n", LOG_STRINGIZE(LOG_TARGET)) - LOG_TEE("03 Hello World to **both** default output and " LOG_TEE_TARGET_STRING "!\n") - log_set_target(stderr); - LOG("04 Hello World to stderr!\n") - LOG_TEE("05 Hello World TEE with double printing to stderr prevented!\n") - log_set_target(LOG_DEFAULT_FILE_NAME); - LOG("06 Hello World to default log file!\n") - log_set_target(stdout); - LOG("07 Hello World to stdout!\n") - log_set_target(LOG_DEFAULT_FILE_NAME); - LOG("08 Hello World to default log file again!\n") - log_disable(); - LOG("09 Hello World _1_ into the void!\n") - log_enable(); - LOG("10 Hello World back from the void ( you should not see _1_ in the log or the output )!\n") - log_disable(); - log_set_target("llama.anotherlog.log"); - LOG("11 Hello World _2_ to nobody, new target was selected but logs are still disabled!\n") - log_enable(); - LOG("12 Hello World this time in a new file ( you should not see _2_ in the log or the output )?\n") - log_set_target("llama.yetanotherlog.log"); - LOG("13 Hello World this time in yet new file?\n") - - if (gpt_params_parse(argc, argv, params) == false) { return 1; } @@ -851,5 +823,7 @@ int main(int argc, char ** argv) { } llama_backend_free(); + LOG("Log end - end of main()\n") + return 0; }