log.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. /**
  2. * llama.cpp - commit 8962422b1c6f9b8b15f5aeaea42600bcc2d44177 - do not edit this file
  3. *
  4. * MIT License
  5. *
  6. * Copyright (c) 2023-2024 The ggml authors
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in all
  16. * copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  24. * SOFTWARE.
  25. */
  26. #pragma once
  27. #include <chrono>
  28. #include <cstring>
  29. #include <sstream>
  30. #include <iostream>
  31. #include <thread>
  32. #include <vector>
  33. #include <algorithm>
  34. #include <cinttypes>
  35. // --------------------------------
  36. //
  37. // Basic usage:
  38. //
  39. // --------
  40. //
  41. // The LOG() and LOG_TEE() macros are ready to go by default
  42. // they do not require any initialization.
  43. //
  44. // LOGLN() and LOG_TEELN() are variants which automatically
  45. // include \n character at the end of the log string.
  46. //
  47. // LOG() behaves exactly like printf, by default writing to a logfile.
  48. // LOG_TEE() additionally, prints to the screen too ( mimics Unix tee command ).
  49. //
  50. // Default logfile is named
  51. // "llama.<threadID>.log"
  52. // Default LOG_TEE() secondary output target is
  53. // stderr
  54. //
  55. // Logs can be dynamically disabled or enabled using functions:
  56. // log_disable()
  57. // and
  58. // log_enable()
  59. //
  60. // A log target can be changed with:
  61. // log_set_target( string )
  62. // creating and opening, or re-opening a file by string filename
  63. // or
  64. // log_set_target( FILE* )
  65. // allowing to point at stderr, stdout, or any valid FILE* file handler.
  66. //
  67. // --------
  68. //
  69. // End of Basic usage.
  70. //
  71. // --------------------------------
  72. // Specifies a log target.
  73. // default uses log_handler() with "llama.log" log file
  74. // this can be changed, by defining LOG_TARGET
  75. // like so:
  76. //
  77. // #define LOG_TARGET (a valid FILE*)
  78. // #include "log.h"
  79. //
  80. // or it can be simply redirected to stdout or stderr
  81. // like so:
  82. //
  83. // #define LOG_TARGET stderr
  84. // #include "log.h"
  85. //
  86. // The log target can also be redirected to a different function
  87. // like so:
  88. //
  89. // #define LOG_TARGET log_handler_different()
  90. // #include "log.h"
  91. //
  92. // FILE* log_handler_different()
  93. // {
  94. // return stderr;
  95. // }
  96. //
  97. // or:
  98. //
  99. // #define LOG_TARGET log_handler_another_one("somelog.log")
  100. // #include "log.h"
  101. //
  102. // FILE* log_handler_another_one(char*filename)
  103. // {
  104. // static FILE* logfile = nullptr;
  105. // (...)
  106. // if( !logfile )
  107. // {
  108. // fopen(...)
  109. // }
  110. // (...)
  111. // return logfile
  112. // }
  113. //
  114. #ifndef LOG_TARGET
  115. #define LOG_TARGET log_handler()
  116. #endif
  117. #ifndef LOG_TEE_TARGET
  118. #define LOG_TEE_TARGET stderr
  119. #endif
  120. // Utility for synchronizing log configuration state
  121. // since std::optional was introduced only in c++17
  122. enum LogTriState
  123. {
  124. LogTriStateSame,
  125. LogTriStateFalse,
  126. LogTriStateTrue
  127. };
  128. // Utility to obtain "pid" like unique process id and use it when creating log files.
  129. inline std::string log_get_pid()
  130. {
  131. static std::string pid;
  132. if (pid.empty())
  133. {
  134. // std::this_thread::get_id() is the most portable way of obtaining a "process id"
  135. // it's not the same as "pid" but is unique enough to solve multiple instances
  136. // trying to write to the same log.
  137. std::stringstream ss;
  138. ss << std::this_thread::get_id();
  139. pid = ss.str();
  140. }
  141. return pid;
  142. }
  143. // Utility function for generating log file names with unique id based on thread id.
  144. // invocation with log_filename_generator( "llama", "log" ) creates a string "llama.<number>.log"
  145. // where the number is a runtime id of the current thread.
  146. #define log_filename_generator(log_file_basename, log_file_extension) log_filename_generator_impl(LogTriStateSame, log_file_basename, log_file_extension)
  147. // INTERNAL, DO NOT USE
  148. inline std::string log_filename_generator_impl(LogTriState multilog, const std::string & log_file_basename, const std::string & log_file_extension)
  149. {
  150. static bool _multilog = false;
  151. if (multilog != LogTriStateSame)
  152. {
  153. _multilog = multilog == LogTriStateTrue;
  154. }
  155. std::stringstream buf;
  156. buf << log_file_basename;
  157. if (_multilog)
  158. {
  159. buf << ".";
  160. buf << log_get_pid();
  161. }
  162. buf << ".";
  163. buf << log_file_extension;
  164. return buf.str();
  165. }
  166. #ifndef LOG_DEFAULT_FILE_NAME
  167. #define LOG_DEFAULT_FILE_NAME log_filename_generator("llama", "log")
  168. #endif
  169. // Utility for turning #define values into string literals
  170. // so we can have a define for stderr and
  171. // we can print "stderr" instead of literal stderr, etc.
  172. #define LOG_STRINGIZE1(s) #s
  173. #define LOG_STRINGIZE(s) LOG_STRINGIZE1(s)
  174. #define LOG_TEE_TARGET_STRING LOG_STRINGIZE(LOG_TEE_TARGET)
  175. // Allows disabling timestamps.
  176. // in order to disable, define LOG_NO_TIMESTAMPS
  177. // like so:
  178. //
  179. // #define LOG_NO_TIMESTAMPS
  180. // #include "log.h"
  181. //
  182. #ifndef LOG_NO_TIMESTAMPS
  183. #ifndef _MSC_VER
  184. #define LOG_TIMESTAMP_FMT "[%" PRIu64 "] "
  185. #define LOG_TIMESTAMP_VAL , (std::chrono::duration_cast<std::chrono::duration<std::uint64_t>>(std::chrono::system_clock::now().time_since_epoch())).count()
  186. #else
  187. #define LOG_TIMESTAMP_FMT "[%" PRIu64 "] "
  188. #define LOG_TIMESTAMP_VAL , (std::chrono::duration_cast<std::chrono::duration<std::uint64_t>>(std::chrono::system_clock::now().time_since_epoch())).count()
  189. #endif
  190. #else
  191. #define LOG_TIMESTAMP_FMT "%s"
  192. #define LOG_TIMESTAMP_VAL ,""
  193. #endif
  194. #ifdef LOG_TEE_TIMESTAMPS
  195. #ifndef _MSC_VER
  196. #define LOG_TEE_TIMESTAMP_FMT "[%" PRIu64 "] "
  197. #define LOG_TEE_TIMESTAMP_VAL , (std::chrono::duration_cast<std::chrono::duration<std::uint64_t>>(std::chrono::system_clock::now().time_since_epoch())).count()
  198. #else
  199. #define LOG_TEE_TIMESTAMP_FMT "[%" PRIu64 "] "
  200. #define LOG_TEE_TIMESTAMP_VAL , (std::chrono::duration_cast<std::chrono::duration<std::uint64_t>>(std::chrono::system_clock::now().time_since_epoch())).count()
  201. #endif
  202. #else
  203. #define LOG_TEE_TIMESTAMP_FMT "%s"
  204. #define LOG_TEE_TIMESTAMP_VAL ,""
  205. #endif
  206. // Allows disabling file/line/function prefix
  207. // in order to disable, define LOG_NO_FILE_LINE_FUNCTION
  208. // like so:
  209. //
  210. // #define LOG_NO_FILE_LINE_FUNCTION
  211. // #include "log.h"
  212. //
  213. #ifndef LOG_NO_FILE_LINE_FUNCTION
  214. #ifndef _MSC_VER
  215. #define LOG_FLF_FMT "[%24s:%5d][%24s] "
  216. #define LOG_FLF_VAL , __FILE__, __LINE__, __FUNCTION__
  217. #else
  218. #define LOG_FLF_FMT "[%24s:%5ld][%24s] "
  219. #define LOG_FLF_VAL , __FILE__, (long)__LINE__, __FUNCTION__
  220. #endif
  221. #else
  222. #define LOG_FLF_FMT "%s"
  223. #define LOG_FLF_VAL ,""
  224. #endif
  225. #ifdef LOG_TEE_FILE_LINE_FUNCTION
  226. #ifndef _MSC_VER
  227. #define LOG_TEE_FLF_FMT "[%24s:%5d][%24s] "
  228. #define LOG_TEE_FLF_VAL , __FILE__, __LINE__, __FUNCTION__
  229. #else
  230. #define LOG_TEE_FLF_FMT "[%24s:%5ld][%24s] "
  231. #define LOG_TEE_FLF_VAL , __FILE__, (long)__LINE__, __FUNCTION__
  232. #endif
  233. #else
  234. #define LOG_TEE_FLF_FMT "%s"
  235. #define LOG_TEE_FLF_VAL ,""
  236. #endif
  237. // INTERNAL, DO NOT USE
  238. // USE LOG() INSTEAD
  239. //
  240. #if !defined(_MSC_VER) || defined(__INTEL_LLVM_COMPILER) || defined(__clang__)
  241. #define LOG_IMPL(str, ...) \
  242. do { \
  243. if (LOG_TARGET != nullptr) \
  244. { \
  245. fprintf(LOG_TARGET, LOG_TIMESTAMP_FMT LOG_FLF_FMT str "%s" LOG_TIMESTAMP_VAL LOG_FLF_VAL, __VA_ARGS__); \
  246. fflush(LOG_TARGET); \
  247. } \
  248. } while (0)
  249. #else
  250. #define LOG_IMPL(str, ...) \
  251. do { \
  252. if (LOG_TARGET != nullptr) \
  253. { \
  254. fprintf(LOG_TARGET, LOG_TIMESTAMP_FMT LOG_FLF_FMT str "%s" LOG_TIMESTAMP_VAL LOG_FLF_VAL "", ##__VA_ARGS__); \
  255. fflush(LOG_TARGET); \
  256. } \
  257. } while (0)
  258. #endif
  259. // INTERNAL, DO NOT USE
  260. // USE LOG_TEE() INSTEAD
  261. //
  262. #if !defined(_MSC_VER) || defined(__INTEL_LLVM_COMPILER) || defined(__clang__)
  263. #define LOG_TEE_IMPL(str, ...) \
  264. do { \
  265. if (LOG_TARGET != nullptr) \
  266. { \
  267. fprintf(LOG_TARGET, LOG_TIMESTAMP_FMT LOG_FLF_FMT str "%s" LOG_TIMESTAMP_VAL LOG_FLF_VAL, __VA_ARGS__); \
  268. fflush(LOG_TARGET); \
  269. } \
  270. if (LOG_TARGET != nullptr && LOG_TARGET != stdout && LOG_TARGET != stderr && LOG_TEE_TARGET != nullptr) \
  271. { \
  272. fprintf(LOG_TEE_TARGET, LOG_TEE_TIMESTAMP_FMT LOG_TEE_FLF_FMT str "%s" LOG_TEE_TIMESTAMP_VAL LOG_TEE_FLF_VAL, __VA_ARGS__); \
  273. fflush(LOG_TEE_TARGET); \
  274. } \
  275. } while (0)
  276. #else
  277. #define LOG_TEE_IMPL(str, ...) \
  278. do { \
  279. if (LOG_TARGET != nullptr) \
  280. { \
  281. fprintf(LOG_TARGET, LOG_TIMESTAMP_FMT LOG_FLF_FMT str "%s" LOG_TIMESTAMP_VAL LOG_FLF_VAL "", ##__VA_ARGS__); \
  282. fflush(LOG_TARGET); \
  283. } \
  284. if (LOG_TARGET != nullptr && LOG_TARGET != stdout && LOG_TARGET != stderr && LOG_TEE_TARGET != nullptr) \
  285. { \
  286. fprintf(LOG_TEE_TARGET, LOG_TEE_TIMESTAMP_FMT LOG_TEE_FLF_FMT str "%s" LOG_TEE_TIMESTAMP_VAL LOG_TEE_FLF_VAL "", ##__VA_ARGS__); \
  287. fflush(LOG_TEE_TARGET); \
  288. } \
  289. } while (0)
  290. #endif
  291. // The '\0' as a last argument, is a trick to bypass the silly
  292. // "warning: ISO C++11 requires at least one argument for the "..." in a variadic macro"
  293. // so we can have a single macro which can be called just like printf.
  294. // Main LOG macro.
  295. // behaves like printf, and supports arguments the exact same way.
  296. //
  297. #if !defined(_MSC_VER) || defined(__clang__)
  298. #define LOG(...) LOG_IMPL(__VA_ARGS__, "")
  299. #else
  300. #define LOG(str, ...) LOG_IMPL("%s" str, "", ##__VA_ARGS__, "")
  301. #endif
  302. // Main TEE macro.
  303. // does the same as LOG
  304. // and
  305. // simultaneously writes stderr.
  306. //
  307. // Secondary target can be changed just like LOG_TARGET
  308. // by defining LOG_TEE_TARGET
  309. //
  310. #if !defined(_MSC_VER) || defined(__clang__)
  311. #define LOG_TEE(...) LOG_TEE_IMPL(__VA_ARGS__, "")
  312. #else
  313. #define LOG_TEE(str, ...) LOG_TEE_IMPL("%s" str, "", ##__VA_ARGS__, "")
  314. #endif
  315. // LOG macro variants with auto endline.
  316. #if !defined(_MSC_VER) || defined(__clang__)
  317. #define LOGLN(...) LOG_IMPL(__VA_ARGS__, "\n")
  318. #define LOG_TEELN(...) LOG_TEE_IMPL(__VA_ARGS__, "\n")
  319. #else
  320. #define LOGLN(str, ...) LOG_IMPL("%s" str, "", ##__VA_ARGS__, "\n")
  321. #define LOG_TEELN(str, ...) LOG_TEE_IMPL("%s" str, "", ##__VA_ARGS__, "\n")
  322. #endif
  323. // INTERNAL, DO NOT USE
  324. inline FILE *log_handler1_impl(bool change = false, LogTriState append = LogTriStateSame, LogTriState disable = LogTriStateSame, const std::string & filename = LOG_DEFAULT_FILE_NAME, FILE *target = nullptr)
  325. {
  326. static bool _initialized = false;
  327. static bool _append = false;
  328. static bool _disabled = filename.empty() && target == nullptr;
  329. static std::string log_current_filename{filename};
  330. static FILE *log_current_target{target};
  331. static FILE *logfile = nullptr;
  332. if (change)
  333. {
  334. if (append != LogTriStateSame)
  335. {
  336. _append = append == LogTriStateTrue;
  337. return logfile;
  338. }
  339. if (disable == LogTriStateTrue)
  340. {
  341. // Disable primary target
  342. _disabled = true;
  343. }
  344. // If previously disabled, only enable, and keep previous target
  345. else if (disable == LogTriStateFalse)
  346. {
  347. _disabled = false;
  348. }
  349. // Otherwise, process the arguments
  350. else if (log_current_filename != filename || log_current_target != target)
  351. {
  352. _initialized = false;
  353. }
  354. }
  355. if (_disabled)
  356. {
  357. // Log is disabled
  358. return nullptr;
  359. }
  360. if (_initialized)
  361. {
  362. // with fallback in case something went wrong
  363. return logfile ? logfile : stderr;
  364. }
  365. // do the (re)initialization
  366. if (target != nullptr)
  367. {
  368. if (logfile != nullptr && logfile != stdout && logfile != stderr)
  369. {
  370. fclose(logfile);
  371. }
  372. log_current_filename = LOG_DEFAULT_FILE_NAME;
  373. log_current_target = target;
  374. logfile = target;
  375. }
  376. else
  377. {
  378. if (log_current_filename != filename)
  379. {
  380. if (logfile != nullptr && logfile != stdout && logfile != stderr)
  381. {
  382. fclose(logfile);
  383. }
  384. }
  385. logfile = fopen(filename.c_str(), _append ? "a" : "w");
  386. }
  387. if (!logfile)
  388. {
  389. // Verify whether the file was opened, otherwise fallback to stderr
  390. logfile = stderr;
  391. fprintf(stderr, "Failed to open logfile '%s' with error '%s'\n", filename.c_str(), std::strerror(errno));
  392. fflush(stderr);
  393. // At this point we let the init flag be to true below, and let the target fallback to stderr
  394. // otherwise we would repeatedly fopen() which was already unsuccessful
  395. }
  396. _initialized = true;
  397. return logfile ? logfile : stderr;
  398. }
  399. // INTERNAL, DO NOT USE
  400. inline FILE *log_handler2_impl(bool change = false, LogTriState append = LogTriStateSame, LogTriState disable = LogTriStateSame, FILE *target = nullptr, const std::string & filename = LOG_DEFAULT_FILE_NAME)
  401. {
  402. return log_handler1_impl(change, append, disable, filename, target);
  403. }
  404. // Disables logs entirely at runtime.
  405. // Makes LOG() and LOG_TEE() produce no output,
  406. // until enabled back.
  407. #define log_disable() log_disable_impl()
  408. // INTERNAL, DO NOT USE
  409. inline FILE *log_disable_impl()
  410. {
  411. return log_handler1_impl(true, LogTriStateSame, LogTriStateTrue);
  412. }
  413. // Enables logs at runtime.
  414. #define log_enable() log_enable_impl()
  415. // INTERNAL, DO NOT USE
  416. inline FILE *log_enable_impl()
  417. {
  418. return log_handler1_impl(true, LogTriStateSame, LogTriStateFalse);
  419. }
  420. // Sets target fir logs, either by a file name or FILE* pointer (stdout, stderr, or any valid FILE*)
  421. #define log_set_target(target) log_set_target_impl(target)
  422. // INTERNAL, DO NOT USE
  423. inline FILE *log_set_target_impl(const std::string & filename) { return log_handler1_impl(true, LogTriStateSame, LogTriStateSame, filename); }
  424. inline FILE *log_set_target_impl(FILE *target) { return log_handler2_impl(true, LogTriStateSame, LogTriStateSame, target); }
  425. // INTERNAL, DO NOT USE
  426. inline FILE *log_handler() { return log_handler1_impl(); }
  427. // Enable or disable creating separate log files for each run.
  428. // can ONLY be invoked BEFORE first log use.
  429. #define log_multilog(enable) log_filename_generator_impl((enable) ? LogTriStateTrue : LogTriStateFalse, "", "")
  430. // Enable or disable append mode for log file.
  431. // can ONLY be invoked BEFORE first log use.
  432. #define log_append(enable) log_append_impl(enable)
  433. // INTERNAL, DO NOT USE
  434. inline FILE *log_append_impl(bool enable)
  435. {
  436. return log_handler1_impl(true, enable ? LogTriStateTrue : LogTriStateFalse, LogTriStateSame);
  437. }
  438. inline void log_test()
  439. {
  440. log_disable();
  441. LOG("01 Hello World to nobody, because logs are disabled!\n");
  442. log_enable();
  443. LOG("02 Hello World to default output, which is \"%s\" ( Yaaay, arguments! )!\n", LOG_STRINGIZE(LOG_TARGET));
  444. LOG_TEE("03 Hello World to **both** default output and " LOG_TEE_TARGET_STRING "!\n");
  445. log_set_target(stderr);
  446. LOG("04 Hello World to stderr!\n");
  447. LOG_TEE("05 Hello World TEE with double printing to stderr prevented!\n");
  448. log_set_target(LOG_DEFAULT_FILE_NAME);
  449. LOG("06 Hello World to default log file!\n");
  450. log_set_target(stdout);
  451. LOG("07 Hello World to stdout!\n");
  452. log_set_target(LOG_DEFAULT_FILE_NAME);
  453. LOG("08 Hello World to default log file again!\n");
  454. log_disable();
  455. LOG("09 Hello World _1_ into the void!\n");
  456. log_enable();
  457. LOG("10 Hello World back from the void ( you should not see _1_ in the log or the output )!\n");
  458. log_disable();
  459. log_set_target("llama.anotherlog.log");
  460. LOG("11 Hello World _2_ to nobody, new target was selected but logs are still disabled!\n");
  461. log_enable();
  462. LOG("12 Hello World this time in a new file ( you should not see _2_ in the log or the output )?\n");
  463. log_set_target("llama.yetanotherlog.log");
  464. LOG("13 Hello World this time in yet new file?\n");
  465. log_set_target(log_filename_generator("llama_autonamed", "log"));
  466. LOG("14 Hello World in log with generated filename!\n");
  467. #ifdef _MSC_VER
  468. LOG_TEE("15 Hello msvc TEE without arguments\n");
  469. LOG_TEE("16 Hello msvc TEE with (%d)(%s) arguments\n", 1, "test");
  470. LOG_TEELN("17 Hello msvc TEELN without arguments\n");
  471. LOG_TEELN("18 Hello msvc TEELN with (%d)(%s) arguments\n", 1, "test");
  472. LOG("19 Hello msvc LOG without arguments\n");
  473. LOG("20 Hello msvc LOG with (%d)(%s) arguments\n", 1, "test");
  474. LOGLN("21 Hello msvc LOGLN without arguments\n");
  475. LOGLN("22 Hello msvc LOGLN with (%d)(%s) arguments\n", 1, "test");
  476. #endif
  477. }
  478. inline bool log_param_single_parse(const std::string & param)
  479. {
  480. if ( param == "--log-test")
  481. {
  482. log_test();
  483. return true;
  484. }
  485. if ( param == "--log-disable")
  486. {
  487. log_disable();
  488. return true;
  489. }
  490. if ( param == "--log-enable")
  491. {
  492. log_enable();
  493. return true;
  494. }
  495. if (param == "--log-new")
  496. {
  497. log_multilog(true);
  498. return true;
  499. }
  500. if (param == "--log-append")
  501. {
  502. log_append(true);
  503. return true;
  504. }
  505. return false;
  506. }
  507. inline bool log_param_pair_parse(bool check_but_dont_parse, const std::string & param, const std::string & next = std::string())
  508. {
  509. if ( param == "--log-file")
  510. {
  511. if (!check_but_dont_parse)
  512. {
  513. log_set_target(log_filename_generator(next.empty() ? "unnamed" : next, "log"));
  514. }
  515. return true;
  516. }
  517. return false;
  518. }
  519. inline void log_print_usage()
  520. {
  521. printf("log options:\n");
  522. /* format
  523. printf(" -h, --help show this help message and exit\n");*/
  524. /* spacing
  525. printf("__-param----------------Description\n");*/
  526. printf(" --log-test Run simple logging test\n");
  527. printf(" --log-disable Disable trace logs\n");
  528. printf(" --log-enable Enable trace logs\n");
  529. printf(" --log-file Specify a log filename (without extension)\n");
  530. printf(" --log-new Create a separate new log file on start. "
  531. "Each log file will have unique name: \"<name>.<ID>.log\"\n");
  532. printf(" --log-append Don't truncate the old log file.\n");
  533. printf("\n");
  534. }
  535. #define log_dump_cmdline(argc, argv) log_dump_cmdline_impl(argc, argv)
  536. // INTERNAL, DO NOT USE
  537. inline void log_dump_cmdline_impl(int argc, char **argv)
  538. {
  539. std::stringstream buf;
  540. for (int i = 0; i < argc; ++i)
  541. {
  542. if (std::string(argv[i]).find(' ') != std::string::npos)
  543. {
  544. buf << " \"" << argv[i] <<"\"";
  545. }
  546. else
  547. {
  548. buf << " " << argv[i];
  549. }
  550. }
  551. LOGLN("Cmd:%s", buf.str().c_str());
  552. }
  553. #define log_tostr(var) log_var_to_string_impl(var).c_str()
  554. inline std::string log_var_to_string_impl(bool var)
  555. {
  556. return var ? "true" : "false";
  557. }
  558. inline std::string log_var_to_string_impl(std::string var)
  559. {
  560. return var;
  561. }
  562. inline std::string log_var_to_string_impl(const std::vector<int> & var)
  563. {
  564. std::stringstream buf;
  565. buf << "[ ";
  566. bool first = true;
  567. for (auto e : var)
  568. {
  569. if (first)
  570. {
  571. first = false;
  572. }
  573. else
  574. {
  575. buf << ", ";
  576. }
  577. buf << std::to_string(e);
  578. }
  579. buf << " ]";
  580. return buf.str();
  581. }
  582. template <typename C, typename T>
  583. inline std::string LOG_TOKENS_TOSTR_PRETTY(const C & ctx, const T & tokens)
  584. {
  585. std::stringstream buf;
  586. buf << "[ ";
  587. bool first = true;
  588. for (const auto & token : tokens)
  589. {
  590. if (!first) {
  591. buf << ", ";
  592. } else {
  593. first = false;
  594. }
  595. auto detokenized = llama_token_to_piece(ctx, token);
  596. detokenized.erase(
  597. std::remove_if(
  598. detokenized.begin(),
  599. detokenized.end(),
  600. [](const unsigned char c) { return !std::isprint(c); }),
  601. detokenized.end());
  602. buf
  603. << "'" << detokenized << "'"
  604. << ":" << std::to_string(token);
  605. }
  606. buf << " ]";
  607. return buf.str();
  608. }
  609. template <typename C, typename B>
  610. inline std::string LOG_BATCH_TOSTR_PRETTY(const C & ctx, const B & batch)
  611. {
  612. std::stringstream buf;
  613. buf << "[ ";
  614. bool first = true;
  615. for (int i = 0; i < batch.n_tokens; ++i)
  616. {
  617. if (!first) {
  618. buf << ", ";
  619. } else {
  620. first = false;
  621. }
  622. auto detokenized = llama_token_to_piece(ctx, batch.token[i]);
  623. detokenized.erase(
  624. std::remove_if(
  625. detokenized.begin(),
  626. detokenized.end(),
  627. [](const unsigned char c) { return !std::isprint(c); }),
  628. detokenized.end());
  629. buf
  630. << "\n" << std::to_string(i)
  631. << ":token '" << detokenized << "'"
  632. << ":pos " << std::to_string(batch.pos[i])
  633. << ":n_seq_id " << std::to_string(batch.n_seq_id[i])
  634. << ":seq_id " << std::to_string(batch.seq_id[i][0])
  635. << ":logits " << std::to_string(batch.logits[i]);
  636. }
  637. buf << " ]";
  638. return buf.str();
  639. }
  640. #ifdef LOG_DISABLE_LOGS
  641. #undef LOG
  642. #define LOG(...) // dummy stub
  643. #undef LOGLN
  644. #define LOGLN(...) // dummy stub
  645. #undef LOG_TEE
  646. #define LOG_TEE(...) fprintf(stderr, __VA_ARGS__) // convert to normal fprintf
  647. #undef LOG_TEELN
  648. #define LOG_TEELN(...) fprintf(stderr, __VA_ARGS__) // convert to normal fprintf
  649. #undef LOG_DISABLE
  650. #define LOG_DISABLE() // dummy stub
  651. #undef LOG_ENABLE
  652. #define LOG_ENABLE() // dummy stub
  653. #undef LOG_ENABLE
  654. #define LOG_ENABLE() // dummy stub
  655. #undef LOG_SET_TARGET
  656. #define LOG_SET_TARGET(...) // dummy stub
  657. #undef LOG_DUMP_CMDLINE
  658. #define LOG_DUMP_CMDLINE(...) // dummy stub
  659. #endif // LOG_DISABLE_LOGS