diff --git a/src/log.cpp b/src/log.cpp index 9645b76..4eedeb7 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -48,10 +48,13 @@ namespace detail { static unsigned char abortOnCrit; -const char* log_prefix(const char* name, Level lvl) +const char* log_prep(logger& log, unsigned rawlvl) { - thread_local char prefix[64]; - // YYYY-mm-ddTHH:MM:SS.FffFffFff + auto lvl = (Level)(rawlvl&0xff); + if(!log.test(lvl)) + return nullptr; // don't log + + thread_local char prefix[80]; epicsTimeStamp now; size_t N; @@ -73,25 +76,24 @@ const char* log_prefix(const char* name, Level lvl) default: lname = "<\?\?\?>"; break; } - epicsSnprintf(prefix+N, sizeof(prefix)-N, " %s %s", lname, name); + int ret = epicsSnprintf(prefix+N, sizeof(prefix)-N, " %s %s", lname, log.name); + if(ret >=0 ) { + N += size_t(ret); + if(N>60) { + // prefix is too long (arbitrary), so move message content to next line + epicsSnprintf(prefix+N, sizeof(prefix)-N, "\n "); + } + } return prefix; } -void _log_printf(unsigned lvl, const char* fmt, ...) +static +void _log_vprintf(unsigned rawlvl, const char *fmt, va_list args) { - bool bt = lvl&0x1000; - auto L = Level(lvl&0xff); - auto abt = L==Level::Crit && abortOnCrit!=0; + errlogVprintf(fmt, args); - { - va_list args; - va_start(args, fmt); - errlogVprintf(fmt, args); - va_end(args); - } - - if(abt) { + if(Level(rawlvl&0xff)==Level::Crit && abortOnCrit!=0) { errlogFlush(); if(abortOnCrit==1) { // C abort, end process @@ -103,13 +105,30 @@ void _log_printf(unsigned lvl, const char* fmt, ...) cantProceed("CRITICAL ERROR\n"); } - } else if(bt) { + } else if(rawlvl&0x1000) { errlogFlush(); epicsStackTrace(); errlogFlush(); } } +void _log_printf(unsigned rawlvl, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + _log_vprintf(rawlvl, fmt, args); + va_end(args); +} + +void _log_printf_hex(unsigned rawlvl, const void *buf, size_t buflen, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + xerrlogHexPrintf(buf, buflen); + _log_vprintf(rawlvl, fmt, args); + va_end(args); +} + } // namespace detail namespace { diff --git a/src/pvxs/log.h b/src/pvxs/log.h index fbe0473..97aaacd 100644 --- a/src/pvxs/log.h +++ b/src/pvxs/log.h @@ -50,10 +50,13 @@ public: namespace detail { PVXS_API -const char* log_prefix(const char* name, Level lvl); +const char *log_prep(logger& log, unsigned lvl); PVXS_API -void _log_printf(unsigned lvl, const char* fmt, ...) EPICS_PRINTF_STYLE(2,3); +void _log_printf(unsigned rawlvl, const char *fmt, ...) EPICS_PRINTF_STYLE(2,3); + +PVXS_API +void _log_printf_hex(unsigned rawlvl, const void *buf, size_t buflen, const char *fmt, ...) EPICS_PRINTF_STYLE(4,5); } // namespace detail @@ -76,8 +79,8 @@ void xerrlogHexPrintf(const void *buf, size_t buflen); * @endcode */ #define log_printf(LOGGER, LVL, FMT, ...) do{ \ - if((LOGGER).test(LVL)) \ - ::pvxs::detail:: _log_printf(unsigned(LVL), "%s " FMT, ::pvxs::detail::log_prefix((LOGGER).name, LVL), __VA_ARGS__); \ + if(auto _log_prefix = ::pvxs::detail::log_prep(LOGGER, unsigned(LVL))) \ + ::pvxs::detail:: _log_printf(unsigned(LVL), "%s " FMT, _log_prefix, __VA_ARGS__); \ }while(0) /* A note about MSVC (legacy) pre-processor weirdness. @@ -98,19 +101,16 @@ void xerrlogHexPrintf(const void *buf, size_t buflen); * Thus FMT is explicitly matched in the following "outer" macros. */ +#define log_exc_printf(LOGGER, FMT, ...) log_printf(LOGGER, unsigned(::pvxs::Level::Crit)|0x1000, FMT, __VA_ARGS__) #define log_crit_printf(LOGGER, FMT, ...) log_printf(LOGGER, ::pvxs::Level::Crit, FMT, __VA_ARGS__) #define log_err_printf(LOGGER, FMT, ...) log_printf(LOGGER, ::pvxs::Level::Err, FMT, __VA_ARGS__) #define log_warn_printf(LOGGER, FMT, ...) log_printf(LOGGER, ::pvxs::Level::Warn, FMT, __VA_ARGS__) #define log_info_printf(LOGGER, FMT, ...) log_printf(LOGGER, ::pvxs::Level::Info, FMT, __VA_ARGS__) #define log_debug_printf(LOGGER, FMT, ...) log_printf(LOGGER, ::pvxs::Level::Debug, FMT, __VA_ARGS__) -#define log_exc_printf(LOGGER, FMT, ...) do{ \ - if((LOGGER).test(::pvxs::Level::Crit)) \ - ::pvxs::detail:: _log_printf(unsigned(::pvxs::Level::Crit)|0x1000, "%s " FMT, ::pvxs::detail::log_prefix((LOGGER).name, ::pvxs::Level::Crit), __VA_ARGS__); \ -}while(0) -#define log_hex_printf(LOGGER, LVL, BUF, BUFLEN, FMT, ...) do{ if((LOGGER).test(LVL)) { \ - xerrlogHexPrintf(BUF, BUFLEN); \ - errlogPrintf("%s " FMT, ::pvxs::detail::log_prefix((LOGGER).name, LVL), __VA_ARGS__); } \ +#define log_hex_printf(LOGGER, LVL, BUF, BUFLEN, FMT, ...) do{ \ + if(auto _log_prefix = ::pvxs::detail::log_prep(LOGGER, unsigned(LVL))) \ + ::pvxs::detail:: _log_printf_hex(unsigned(LVL), BUF, BUFLEN, "%s " FMT, _log_prefix, __VA_ARGS__);\ }while(0) //! Set level for a specific logger