1#pragma once
  2
  3#include "ggml.h" // for ggml_log_level
  4
  5#define LOG_CLR_TO_EOL  "\033[K\r"
  6#define LOG_COL_DEFAULT "\033[0m"
  7#define LOG_COL_BOLD    "\033[1m"
  8#define LOG_COL_RED     "\033[31m"
  9#define LOG_COL_GREEN   "\033[32m"
 10#define LOG_COL_YELLOW  "\033[33m"
 11#define LOG_COL_BLUE    "\033[34m"
 12#define LOG_COL_MAGENTA "\033[35m"
 13#define LOG_COL_CYAN    "\033[36m"
 14#define LOG_COL_WHITE   "\033[37m"
 15
 16#ifndef __GNUC__
 17#    define LOG_ATTRIBUTE_FORMAT(...)
 18#elif defined(__MINGW32__) && !defined(__clang__)
 19#    define LOG_ATTRIBUTE_FORMAT(...) __attribute__((format(gnu_printf, __VA_ARGS__)))
 20#else
 21#    define LOG_ATTRIBUTE_FORMAT(...) __attribute__((format(printf, __VA_ARGS__)))
 22#endif
 23
 24#define LOG_LEVEL_DEBUG  4
 25#define LOG_LEVEL_INFO   3
 26#define LOG_LEVEL_WARN   2
 27#define LOG_LEVEL_ERROR  1
 28#define LOG_LEVEL_OUTPUT 0 // output data from tools
 29
 30#define LOG_DEFAULT_DEBUG LOG_LEVEL_DEBUG
 31#define LOG_DEFAULT_LLAMA LOG_LEVEL_INFO
 32
 33enum log_colors {
 34    LOG_COLORS_AUTO     = -1,
 35    LOG_COLORS_DISABLED = 0,
 36    LOG_COLORS_ENABLED  = 1,
 37};
 38
 39// needed by the LOG_TMPL macro to avoid computing log arguments if the verbosity lower
 40// set via common_log_set_verbosity()
 41extern int common_log_verbosity_thold;
 42
 43void common_log_set_verbosity_thold(int verbosity); // not thread-safe
 44
 45void common_log_default_callback(enum ggml_log_level level, const char * text, void * user_data);
 46
 47// the common_log uses an internal worker thread to print/write log messages
 48// when the worker thread is paused, incoming log messages are discarded
 49struct common_log;
 50
 51struct common_log * common_log_init();
 52struct common_log * common_log_main(); // singleton, automatically destroys itself on exit
 53void                common_log_pause (struct common_log * log); // pause  the worker thread, not thread-safe
 54void                common_log_resume(struct common_log * log); // resume the worker thread, not thread-safe
 55void                common_log_free  (struct common_log * log);
 56
 57LOG_ATTRIBUTE_FORMAT(3, 4)
 58void common_log_add(struct common_log * log, enum ggml_log_level level, const char * fmt, ...);
 59
 60// defaults: file = NULL, colors = false, prefix = false, timestamps = false
 61//
 62// regular log output:
 63//
 64//   ggml_backend_metal_log_allocated_size: allocated buffer, size =  6695.84 MiB, ( 6695.91 / 21845.34)
 65//   llm_load_tensors: ggml ctx size =    0.27 MiB
 66//   llm_load_tensors: offloading 32 repeating layers to GPU
 67//   llm_load_tensors: offloading non-repeating layers to GPU
 68//
 69// with prefix = true, timestamps = true, the log output will look like this:
 70//
 71//   0.00.035.060 D ggml_backend_metal_log_allocated_size: allocated buffer, size =  6695.84 MiB, ( 6695.91 / 21845.34)
 72//   0.00.035.064 I llm_load_tensors: ggml ctx size =    0.27 MiB
 73//   0.00.090.578 I llm_load_tensors: offloading 32 repeating layers to GPU
 74//   0.00.090.579 I llm_load_tensors: offloading non-repeating layers to GPU
 75//
 76// D - debug   (stderr, V = LOG_DEFAULT_DEBUG)
 77// I - info    (stdout, V = LOG_DEFAULT_INFO)
 78// W - warning (stderr, V = LOG_DEFAULT_WARN)
 79// E - error   (stderr, V = LOG_DEFAULT_ERROR)
 80// O - output  (stdout, V = LOG_DEFAULT_OUTPUT)
 81//
 82
 83void common_log_set_file      (struct common_log * log, const char * file); // not thread-safe
 84void common_log_set_colors    (struct common_log * log, log_colors colors); // not thread-safe
 85void common_log_set_prefix    (struct common_log * log, bool prefix);       // whether to output prefix to each log
 86void common_log_set_timestamps(struct common_log * log, bool timestamps);   // whether to output timestamps in the prefix
 87void common_log_flush         (struct common_log * log);                    // flush all pending log messages
 88
 89// helper macros for logging
 90// use these to avoid computing log arguments if the verbosity of the log is higher than the threshold
 91//
 92// for example:
 93//
 94//   LOG_DBG("this is a debug message: %d\n", expensive_function());
 95//
 96// this will avoid calling expensive_function() if LOG_DEFAULT_DEBUG > common_log_verbosity_thold
 97//
 98
 99#define LOG_TMPL(level, verbosity, ...) \
100    do { \
101        if ((verbosity) <= common_log_verbosity_thold) { \
102            common_log_add(common_log_main(), (level), __VA_ARGS__); \
103        } \
104    } while (0)
105
106#define LOG(...)             LOG_TMPL(GGML_LOG_LEVEL_NONE, LOG_LEVEL_OUTPUT, __VA_ARGS__)
107#define LOGV(verbosity, ...) LOG_TMPL(GGML_LOG_LEVEL_NONE, verbosity,        __VA_ARGS__)
108
109#define LOG_DBG(...) LOG_TMPL(GGML_LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG,  __VA_ARGS__)
110#define LOG_INF(...) LOG_TMPL(GGML_LOG_LEVEL_INFO,  LOG_LEVEL_INFO,   __VA_ARGS__)
111#define LOG_WRN(...) LOG_TMPL(GGML_LOG_LEVEL_WARN,  LOG_LEVEL_WARN,   __VA_ARGS__)
112#define LOG_ERR(...) LOG_TMPL(GGML_LOG_LEVEL_ERROR, LOG_LEVEL_ERROR,  __VA_ARGS__)
113#define LOG_CNT(...) LOG_TMPL(GGML_LOG_LEVEL_CONT,  LOG_LEVEL_INFO,   __VA_ARGS__) // same as INFO
114
115#define LOG_INFV(verbosity, ...) LOG_TMPL(GGML_LOG_LEVEL_INFO,  verbosity, __VA_ARGS__)
116#define LOG_WRNV(verbosity, ...) LOG_TMPL(GGML_LOG_LEVEL_WARN,  verbosity, __VA_ARGS__)
117#define LOG_ERRV(verbosity, ...) LOG_TMPL(GGML_LOG_LEVEL_ERROR, verbosity, __VA_ARGS__)
118#define LOG_DBGV(verbosity, ...) LOG_TMPL(GGML_LOG_LEVEL_DEBUG, verbosity, __VA_ARGS__)
119#define LOG_CNTV(verbosity, ...) LOG_TMPL(GGML_LOG_LEVEL_CONT,  verbosity, __VA_ARGS__)