inc/azure_c_shared_utility/xlogging.h (181 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 <cstdlib>
#else
#include <stdlib.h>
#endif
#include "azure_macro_utils/macro_utils.h"
#include "azure_c_shared_utility/agenttime.h"
#include "azure_c_shared_utility/optimize_size.h"
#ifdef LOGERROR_CAPTURES_STACK_TRACES
#include "azure_c_shared_utility/logging_stacktrace.h"
#endif
#if defined(ESP8266_RTOS)
#include "c_types.h"
#endif
#if defined(ARDUINO_ARCH_ESP8266)
#include "esp8266/azcpgmspace.h"
#endif
#ifdef __cplusplus
/* Some compilers do not want to play by the standard, specifically ARM CC */
#include <cstdio>
#else
#include <stdio.h>
#endif /* __cplusplus */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef TIZENRT
#undef LOG_INFO
#endif
typedef enum LOG_CATEGORY_TAG
{
AZ_LOG_ERROR,
AZ_LOG_INFO,
AZ_LOG_TRACE
} LOG_CATEGORY;
#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, ...);
#define TEMP_BUFFER_SIZE 1024
#define MESSAGE_BUFFER_SIZE 260
#define LOG_NONE 0x00
#define LOG_LINE 0x01
/*no logging is useful when time and fprintf are mocked*/
#ifdef NO_LOGGING
#define LOG(...)
#define LogInfo(...)
#define LogBinary(...)
#define LogError(...)
#define LogLastError(...)
#define xlogging_get_log_function() NULL
#define xlogging_set_log_function(...)
#define LogErrorWinHTTPWithGetLastErrorAsString(...)
#define UNUSED(x) (void)(x)
#elif (defined MINIMAL_LOGERROR)
#define LOG(...)
#define LogInfo(...)
#define LogBinary(...)
#define LogError(...) printf("error %s: line %d\n",__FILE__,__LINE__);
#define xlogging_get_log_function() NULL
#define xlogging_set_log_function(...)
#define LogErrorWinHTTPWithGetLastErrorAsString(...)
#define UNUSED(x) (void)(x)
#elif defined(ESP8266_RTOS)
#define LogInfo(FORMAT, ...) do { \
static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = FORMAT; \
printf(flash_str, ##__VA_ARGS__); \
printf("\n");\
} while((void)0,0)
#define LogError LogInfo
#define LOG(log_category, log_options, FORMAT, ...) { \
static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = (FORMAT); \
printf(flash_str, ##__VA_ARGS__); \
printf("\r\n"); \
}
#else /* NOT ESP8266_RTOS */
// 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
// ignore warning C4127
#define LOG(log_category, log_options, format, ...) \
{ \
(void)(0 && printf(format, __VA_ARGS__)); \
{ \
LOGGER_LOG l = xlogging_get_log_function(); \
if (l != NULL) \
{ \
l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, __VA_ARGS__); \
} \
} \
}
#else /*LOGERROR_CAPTURES_STACK_TRACES is defined*/
#define STACK_PRINT_FORMAT "\nStack:\n%s"
#define LOG(log_category, log_options, format, ...) MU_C3(LOG,_,log_category)(log_category, log_options, format, __VA_ARGS__)
#define LOG_AZ_LOG_ERROR(log_category, log_options, format, ...) \
{ \
(void)(0 && printf(format, __VA_ARGS__)); \
{ \
LOGGER_LOG l = xlogging_get_log_function(); \
if (l != NULL) \
{ \
char* stackAsString = getStackAsString(); \
if (stackAsString == NULL) \
{ \
l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, __VA_ARGS__); \
} \
else \
{ \
char* formatWithStack; \
size_t formatSize = strlen(format); \
size_t mallocSize = formatSize + sizeof("STACK_PRINT_FORMAT"); \
if (mallocSize < formatSize || /* int overflow check */ \
(formatWithStack = (char*)logging_malloc(mallocSize)) == NULL) \
{ \
l(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)); \
l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, formatWithStack, __VA_ARGS__, stackAsString); \
logging_free(formatWithStack); \
} \
logging_free(stackAsString); \
} \
} \
} \
}
#define LOG_AZ_LOG_TRACE LOG_AZ_LOG_INFO
#define LOG_AZ_LOG_INFO(log_category, log_options, format, ...) \
{ \
(void)(0 && printf(format, __VA_ARGS__)); \
{ \
LOGGER_LOG l = xlogging_get_log_function(); \
if (l != NULL) \
{ \
l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, __VA_ARGS__); \
} \
} \
}
#endif /*LOGERROR_CAPTURES_STACK_TRACES*/
#else
#define LOG(log_category, log_options, format, ...) { (void)(0 && printf(format, ##__VA_ARGS__)); { LOGGER_LOG l = xlogging_get_log_function(); if (l != NULL) l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, ##__VA_ARGS__); } }
#endif
#if defined _MSC_VER
#define LogInfo(FORMAT, ...) do{LOG(AZ_LOG_INFO, LOG_LINE, FORMAT, __VA_ARGS__); }while((void)0,0)
#else
#define LogInfo(FORMAT, ...) do{LOG(AZ_LOG_INFO, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0)
#endif
#ifdef WIN32
extern void xlogging_LogErrorWinHTTPWithGetLastErrorAsStringFormatter(int errorMessageID);
#endif
#if defined _MSC_VER
extern void xlogging_set_log_function_GetLastError(LOGGER_LOG_GETLASTERROR log_function);
extern LOGGER_LOG_GETLASTERROR xlogging_get_log_function_GetLastError(void);
#define LogLastError(FORMAT, ...) do{ LOGGER_LOG_GETLASTERROR l = xlogging_get_log_function_GetLastError(); if(l!=NULL) l(__FILE__, FUNC_NAME, __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 LogErrorWinHTTPWithGetLastErrorAsString(FORMAT, ...) do { \
int errorMessageID = GetLastError(); \
LogError(FORMAT, __VA_ARGS__); \
xlogging_LogErrorWinHTTPWithGetLastErrorAsStringFormatter(errorMessageID); \
} while((void)0,0)
#else // _MSC_VER
#define LogError(FORMAT, ...) do{ LOG(AZ_LOG_ERROR, 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
extern void LogBinary(const char* comment, const void* data, size_t size);
extern void xlogging_set_log_function(LOGGER_LOG log_function);
extern LOGGER_LOG xlogging_get_log_function(void);
#endif /* NOT ESP8266_RTOS */
#ifdef __cplusplus
} // extern "C"
#endif /* __cplusplus */
#endif /* XLOGGING_H */