Nigel Rantor / azure_c_shared_utility

Fork of azure_c_shared_utility by Azure IoT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers xlogging.h Source File

xlogging.h

00001 // Copyright (c) Microsoft. All rights reserved.
00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
00003 
00004 #ifndef XLOGGING_H
00005 #define XLOGGING_H
00006 
00007 #include "azure_c_shared_utility/agenttime.h"
00008 #include "azure_c_shared_utility/optimize_size.h"
00009 
00010 #if defined(ESP8266_RTOS)
00011 #include "c_types.h"
00012 #endif
00013 
00014 #if defined(ARDUINO_ARCH_ESP8266)
00015 #include "esp8266/azcpgmspace.h"
00016 #endif
00017 
00018 #ifdef __cplusplus
00019 #include <cstdio>
00020 extern "C" {
00021 #else
00022 #include <stdio.h>
00023 #endif /* __cplusplus */
00024 
00025 #ifdef TIZENRT
00026 #undef LOG_INFO
00027 #endif
00028 
00029 typedef enum LOG_CATEGORY_TAG
00030 {
00031     AZ_LOG_ERROR,
00032     AZ_LOG_INFO,
00033     AZ_LOG_TRACE
00034 } LOG_CATEGORY;
00035 
00036 #if defined _MSC_VER
00037 #define FUNC_NAME __FUNCDNAME__
00038 #else
00039 #define FUNC_NAME __func__
00040 #endif
00041 
00042 typedef void(*LOGGER_LOG)(LOG_CATEGORY log_category, const char* file, const char* func, int line, unsigned int options, const char* format, ...);
00043 typedef void(*LOGGER_LOG_GETLASTERROR)(const char* file, const char* func, int line, const char* format, ...);
00044 
00045 #define LOG_NONE 0x00
00046 #define LOG_LINE 0x01
00047 
00048 /*no logging is useful when time and fprintf are mocked*/
00049 #ifdef NO_LOGGING
00050 #define LOG(...)
00051 #define LogInfo(...)
00052 #define LogError(...)
00053 #define xlogging_get_log_function() NULL
00054 #define xlogging_set_log_function(...)
00055 #define LogErrorWinHTTPWithGetLastErrorAsString(...)
00056 #define UNUSED(x) (void)(x)
00057 #elif (defined MINIMAL_LOGERROR)
00058 #define LOG(...)
00059 #define LogInfo(...)
00060 #define LogError(...) printf("error %s: line %d\n",__FILE__,__LINE__);
00061 #define xlogging_get_log_function() NULL
00062 #define xlogging_set_log_function(...)
00063 #define LogErrorWinHTTPWithGetLastErrorAsString(...)
00064 #define UNUSED(x) (void)(x)
00065 
00066 #elif defined(ESP8266_RTOS)
00067 #define LogInfo(FORMAT, ...) do {    \
00068         static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = FORMAT;  \
00069         printf(flash_str, ##__VA_ARGS__);   \
00070         printf("\n");\
00071     } while((void)0,0)
00072     
00073 #define LogError LogInfo
00074 #define LOG(log_category, log_options, FORMAT, ...)  { \
00075         static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = (FORMAT); \
00076         printf(flash_str, ##__VA_ARGS__); \
00077         printf("\r\n"); \
00078 }
00079 
00080 
00081 #elif defined(ARDUINO_ARCH_ESP8266)
00082 /*
00083 The ESP8266 compiler doesn't do a good job compiling this code; it doesn't understand that the 'format' is
00084 a 'const char*' and moves it to RAM as a global variable, increasing the .bss size. So we create a
00085 specific LogInfo that explicitly pins the 'format' on the PROGMEM (flash) using a _localFORMAT variable
00086 with the macro PSTR.
00087 #define ICACHE_FLASH_ATTR   __attribute__((section(".irom0.text")))
00088 #define PROGMEM     ICACHE_RODATA_ATTR
00089 #define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];}))
00090 const char* __localFORMAT = PSTR(FORMAT);
00091 On the other hand, vsprintf does not support the pinned 'format' and os_printf does not work with va_list,
00092 so we compacted the log in the macro LogInfo.
00093 */
00094 #define LOG(log_category, log_options, FORMAT, ...) { \
00095         const char* __localFORMAT = PSTR(FORMAT); \
00096         os_printf(__localFORMAT, ##__VA_ARGS__); \
00097         os_printf("\r\n"); \
00098 }
00099 
00100 #define LogInfo(FORMAT, ...) { \
00101         const char* __localFORMAT = PSTR(FORMAT); \
00102         os_printf(__localFORMAT, ##__VA_ARGS__); \
00103         os_printf("\r\n"); \
00104 }
00105 #define LogError LogInfo
00106 
00107 #else /* !ARDUINO_ARCH_ESP8266 */
00108 
00109 #if defined _MSC_VER
00110 #define LOG(log_category, log_options, format, ...) { LOGGER_LOG l = xlogging_get_log_function(); if (l != NULL) l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, __VA_ARGS__); }
00111 #else
00112 #define LOG(log_category, log_options, format, ...) { LOGGER_LOG l = xlogging_get_log_function(); if (l != NULL) l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, ##__VA_ARGS__); } 
00113 #endif
00114 
00115 #if defined _MSC_VER
00116 #define LogInfo(FORMAT, ...) do{LOG(AZ_LOG_INFO, LOG_LINE, FORMAT, __VA_ARGS__); }while((void)0,0)
00117 #else
00118 #define LogInfo(FORMAT, ...) do{LOG(AZ_LOG_INFO, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0)
00119 #endif
00120 
00121 #if defined _MSC_VER
00122 
00123 #if !defined(WINCE)
00124 extern void xlogging_set_log_function_GetLastError(LOGGER_LOG_GETLASTERROR log_function);
00125 extern LOGGER_LOG_GETLASTERROR xlogging_get_log_function_GetLastError(void);
00126 #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)
00127 #endif
00128 
00129 #define LogError(FORMAT, ...) do{ LOG(AZ_LOG_ERROR, LOG_LINE, FORMAT, __VA_ARGS__); }while((void)0,0)
00130 #define TEMP_BUFFER_SIZE 1024
00131 #define MESSAGE_BUFFER_SIZE 260
00132 #define LogErrorWinHTTPWithGetLastErrorAsString(FORMAT, ...) do { \
00133                 DWORD errorMessageID = GetLastError(); \
00134                 char messageBuffer[MESSAGE_BUFFER_SIZE]; \
00135                 LogError(FORMAT, __VA_ARGS__); \
00136                 if (errorMessageID == 0) \
00137                 {\
00138                     LogError("GetLastError() returned 0. Make sure you are calling this right after the code that failed. "); \
00139                 } \
00140                 else\
00141                 {\
00142                     int size = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, \
00143                         GetModuleHandle("WinHttp"), errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), messageBuffer, MESSAGE_BUFFER_SIZE, NULL); \
00144                     if (size == 0)\
00145                     {\
00146                         size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), messageBuffer, MESSAGE_BUFFER_SIZE, NULL); \
00147                         if (size == 0)\
00148                         {\
00149                             LogError("GetLastError Code: %d. ", errorMessageID); \
00150                         }\
00151                         else\
00152                         {\
00153                             LogError("GetLastError: %s.", messageBuffer); \
00154                         }\
00155                     }\
00156                     else\
00157                     {\
00158                         LogError("GetLastError: %s.", messageBuffer); \
00159                     }\
00160                 }\
00161             } while((void)0,0)
00162 #else
00163 #define LogError(FORMAT, ...) do{ LOG(AZ_LOG_ERROR, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0)
00164 #endif
00165 
00166 extern void xlogging_set_log_function(LOGGER_LOG log_function);
00167 extern LOGGER_LOG xlogging_get_log_function(void);
00168 
00169 #endif /* ARDUINO_ARCH_ESP8266 */
00170 
00171 
00172     /**
00173      * @brief   Print the memory content byte pre byte in hexadecimal and as a char it the byte correspond to any printable ASCII chars.
00174      *
00175      *    This function prints the 'size' bytes in the 'buf' to the log. It will print in portions of 16 bytes, 
00176      *         and will print the byte as a hexadecimal value, and, it is a printable, this function will print 
00177      *         the correspondent ASCII character.
00178      *    Non printable characters will shows as a single '.'. 
00179      *    For this function, printable characters are all characters between ' ' (0x20) and '~' (0x7E).
00180      *
00181      * @param   buf  Pointer to the memory address with the buffer to print.
00182      * @param   size Number of bytes to print.
00183      */
00184     extern void xlogging_dump_buffer(const void* buf, size_t size);
00185 
00186 #ifdef __cplusplus
00187 }   // extern "C"
00188 #endif /* __cplusplus */
00189 
00190 #endif /* XLOGGING_H */