inc/c_logging/xlogging.h (156 lines of code) (raw):

// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. #ifndef XLOGGING_H #define XLOGGING_H #ifdef __cplusplus #include <cstdio> #else #include <stdio.h> #endif #if defined _MSC_VER && defined LOGERROR_CAPTURES_STACK_TRACES #ifdef __cplusplus #include <cstring> #else #include <string.h> // for memcpy, strlen #endif #endif // defined _MSC_VER && defined LOGERROR_CAPTURES_STACK_TRACES #include "macro_utils/macro_utils.h" #ifdef LOGERROR_CAPTURES_STACK_TRACES #include "c_logging/logging_stacktrace.h" #endif #define LOG_SIZE_REGULAR 4096 /*in bytes - a message is not expected to exceed this size in bytes, if it does, only LOG_SIZE_REGULAR characters are retained*/ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define LOG_CATEGORY_VALUES \ AZ_LOG_CRITICAL, \ AZ_LOG_ERROR, \ AZ_LOG_WARNING, \ AZ_LOG_INFO, \ AZ_LOG_VERBOSE MU_DEFINE_ENUM(LOG_CATEGORY, LOG_CATEGORY_VALUES) #if defined _MSC_VER #define FUNC_NAME __FUNCDNAME__ #else #define FUNC_NAME __func__ #endif typedef void(*LOGGER_LOG)(LOG_CATEGORY log_category, const char* file, const char* func, int line, unsigned int options, const char* format, ...); typedef void(*LOGGER_LOG_GETLASTERROR)(const char* file, const char* func, int line, const char* format, ...); typedef void(*LOGGER_LOG_GETERRORNO)(const char* file, const char* func, int line, const char* format, ...); #define MESSAGE_BUFFER_SIZE 260 #define LOG_LINE 0x01 /*no logging is useful when time and fprintf are mocked*/ #ifdef NO_LOGGING #define LOG(...) #define LogCritical(...) #define LogError(...) #define LogWarning(...) #define LogInfo(...) #define LogVerbose(...) #define LogLastError(...) #define LogErrorNo(...) #define xlogging_get_log_function() NULL #define xlogging_set_log_function(...) #define LogErrorWinHTTPWithGetLastErrorAsString(...) #else /* NO_LOGGING */ // In order to make sure that the compiler evaluates the arguments and issues an error if they do not conform to printf // specifications, we call printf with the format and __VA_ARGS__. Since C && operator is shortcircuiting no actual runtime call to printf is performed. #if defined _MSC_VER #ifndef LOGERROR_CAPTURES_STACK_TRACES #define LOG(log_category, log_options, format, ...) \ { \ (void)(0 && printf(format, ##__VA_ARGS__)); \ { \ LOGGER_LOG logger_function = xlogging_get_log_function(); \ if (logger_function != NULL) \ { \ logger_function(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, ##__VA_ARGS__); \ } \ } \ } #else /*LOGERROR_CAPTURES_STACK_TRACES is defined*/ #define LOG(log_category, log_options, format, ...) \ MU_C2(LOG_,log_category)(log_category, log_options, format, ##__VA_ARGS__) \ #define LOG_AZ_LOG_WITH_STACK(log_category, log_options, format, ...) \ { \ (void)(0 && printf(format, ##__VA_ARGS__)); \ { \ LOGGER_LOG logger_function = xlogging_get_log_function(); \ if (logger_function != NULL) \ { \ getStackAsString(stackAsString, sizeof(stackAsString)); \ size_t formatSize = strlen(format); \ if (formatSize + sizeof(STACK_PRINT_FORMAT) + 1 > FORMAT_MAX_CHARACTERS) \ { /*skipping stack printing*/ \ logger_function(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, ##__VA_ARGS__); \ } \ else \ { \ (void)memcpy(formatWithStack, format, formatSize); \ (void)memcpy(formatWithStack + formatSize, STACK_PRINT_FORMAT, sizeof(STACK_PRINT_FORMAT)); \ logger_function(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, formatWithStack, ##__VA_ARGS__, stackAsString); \ } \ } \ } \ } #define LOG_AZ_LOG_WITHOUT_STACK(log_category, log_options, format, ...) \ { \ (void)(0 && printf(format, ##__VA_ARGS__)); \ { \ LOGGER_LOG logger_function = xlogging_get_log_function(); \ if (logger_function != NULL) \ { \ logger_function(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, ##__VA_ARGS__); \ } \ } \ } #define LOG_AZ_LOG_CRITICAL(log_category, log_options, format, ...) \ LOG_AZ_LOG_WITH_STACK(log_category, log_options, format, ##__VA_ARGS__) #define LOG_AZ_LOG_ERROR(log_category, log_options, format, ...) \ LOG_AZ_LOG_WITH_STACK(log_category, log_options, format, ##__VA_ARGS__) #define LOG_AZ_LOG_WARNING(log_category, log_options, format, ...) \ LOG_AZ_LOG_WITH_STACK(log_category, log_options, format, ##__VA_ARGS__) #define LOG_AZ_LOG_INFO(log_category, log_options, format, ...) \ LOG_AZ_LOG_WITHOUT_STACK(log_category, log_options, format, ##__VA_ARGS__) #define LOG_AZ_LOG_VERBOSE(log_category, log_options, format, ...) \ LOG_AZ_LOG_WITHOUT_STACK(log_category, log_options, format, ##__VA_ARGS__) #endif /*LOGERROR_CAPTURES_STACK_TRACES */ #else /* _MSC_VER */ #define LOG(log_category, log_options, format, ...) { (void)(0 && printf(format, ##__VA_ARGS__)); { LOGGER_LOG logger_function = xlogging_get_log_function(); if (logger_function != NULL) logger_function(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, ##__VA_ARGS__); } } #endif /* _MSC_VER */ #ifdef WIN32 void xlogging_LogErrorWinHTTPWithGetLastErrorAsStringFormatter(int errorMessageID); #endif /* WIN32 */ #if defined _MSC_VER void xlogging_set_log_function_GetLastError(LOGGER_LOG_GETLASTERROR log_function); LOGGER_LOG_GETLASTERROR xlogging_get_log_function_GetLastError(void); #define LogLastError(FORMAT, ...) do{ (void)(0 && printf(FORMAT, ##__VA_ARGS__)); LOGGER_LOG_GETLASTERROR logger_function = xlogging_get_log_function_GetLastError(); if(logger_function != NULL) logger_function(__FILE__, FUNC_NAME, __LINE__, FORMAT, ##__VA_ARGS__); }while((void)0,0) #define LogCritical(FORMAT, ...) do{ LOG(AZ_LOG_CRITICAL, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0) #define LogError(FORMAT, ...) do{ LOG(AZ_LOG_ERROR, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0) #define LogWarning(FORMAT, ...) do{ LOG(AZ_LOG_WARNING, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0) #define LogInfo(FORMAT, ...) do{LOG(AZ_LOG_INFO, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0) #define LogVerbose(FORMAT, ...) do{LOG(AZ_LOG_VERBOSE, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0) #define LogErrorWinHTTPWithGetLastErrorAsString(FORMAT, ...) do { \ int errorMessageID = GetLastError(); \ LogError(FORMAT, ##__VA_ARGS__); \ xlogging_LogErrorWinHTTPWithGetLastErrorAsStringFormatter(errorMessageID); \ } while((void)0,0) #else // _MSC_VER void xlogging_set_log_function_GetErrorNo(LOGGER_LOG_GETERRORNO log_function); LOGGER_LOG_GETERRORNO xlogging_get_log_function_GetErrorNo(void); #define LogErrorNo(FORMAT, ...) do{ (void)(0 && printf(FORMAT, ##__VA_ARGS__)); LOGGER_LOG_GETERRORNO logger_function = xlogging_get_log_function_GetErrorNo(); if(logger_function != NULL) logger_function(__FILE__, FUNC_NAME, __LINE__, FORMAT, ##__VA_ARGS__); }while((void)0,0) #define LogCritical(FORMAT, ...) do{ LOG(AZ_LOG_CRITICAL, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0) #define LogError(FORMAT, ...) do{ LOG(AZ_LOG_ERROR, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0) #define LogWarning(FORMAT, ...) do{ LOG(AZ_LOG_WARNING, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0) #define LogInfo(FORMAT, ...) do{LOG(AZ_LOG_INFO, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0) #define LogVerbose(FORMAT, ...) do{LOG(AZ_LOG_VERBOSE, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0) #ifdef WIN32 // Included when compiling on Windows but not with MSVC, e.g. with MinGW. #define LogErrorWinHTTPWithGetLastErrorAsString(FORMAT, ...) do { \ int errorMessageID = GetLastError(); \ LogError(FORMAT, ##__VA_ARGS__); \ xlogging_LogErrorWinHTTPWithGetLastErrorAsStringFormatter(errorMessageID); \ } while((void)0,0) #endif // WIN32 #endif // _MSC_VER void xlogging_set_log_function(LOGGER_LOG log_function); LOGGER_LOG xlogging_get_log_function(void); #endif /* NO_LOGGING */ #ifdef __cplusplus } // extern "C" #endif /* __cplusplus */ #endif /* XLOGGING_H */