41 // e.g. |
41 // e.g. |
42 // log_debug(logging)("message %d", i); |
42 // log_debug(logging)("message %d", i); |
43 // |
43 // |
44 // Note that these macros will not evaluate the arguments unless the logging is enabled. |
44 // Note that these macros will not evaluate the arguments unless the logging is enabled. |
45 // |
45 // |
46 #define log_error(...) (!log_is_enabled(Error, __VA_ARGS__)) ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Error> |
46 #define log_error(...) (!log_is_enabled(Error, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Error> |
47 #define log_warning(...) (!log_is_enabled(Warning, __VA_ARGS__)) ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Warning> |
47 #define log_warning(...) (!log_is_enabled(Warning, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Warning> |
48 #define log_info(...) (!log_is_enabled(Info, __VA_ARGS__)) ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Info> |
48 #define log_info(...) (!log_is_enabled(Info, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Info> |
49 #define log_debug(...) (!log_is_enabled(Debug, __VA_ARGS__)) ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Debug> |
49 #define log_debug(...) (!log_is_enabled(Debug, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Debug> |
50 #define log_trace(...) (!log_is_enabled(Trace, __VA_ARGS__)) ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Trace> |
50 #define log_trace(...) (!log_is_enabled(Trace, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Trace> |
51 |
51 |
52 // Macros for logging that should be excluded in product builds. |
52 // Macros for logging that should be excluded in product builds. |
53 // Available for levels Info, Debug and Trace. Includes test macro that |
53 // Available for levels Info, Debug and Trace. Includes test macro that |
54 // evaluates to false in product builds. |
54 // evaluates to false in product builds. |
55 #ifndef PRODUCT |
55 #ifndef PRODUCT |
56 #define log_develop_info(...) (!log_is_enabled(Info, __VA_ARGS__)) ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Info> |
56 #define log_develop_info(...) (!log_is_enabled(Info, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Info> |
57 #define log_develop_debug(...) (!log_is_enabled(Debug, __VA_ARGS__)) ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Debug> |
57 #define log_develop_debug(...) (!log_is_enabled(Debug, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Debug> |
58 #define log_develop_trace(...) (!log_is_enabled(Trace, __VA_ARGS__)) ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Trace> |
58 #define log_develop_trace(...) (!log_is_enabled(Trace, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Trace> |
59 #define log_develop_is_enabled(level, ...) log_is_enabled(level, __VA_ARGS__) |
59 #define log_develop_is_enabled(level, ...) log_is_enabled(level, __VA_ARGS__) |
60 #else |
60 #else |
61 #define DUMMY_ARGUMENT_CONSUMER(...) |
61 #define DUMMY_ARGUMENT_CONSUMER(...) |
62 #define log_develop_info(...) DUMMY_ARGUMENT_CONSUMER |
62 #define log_develop_info(...) DUMMY_ARGUMENT_CONSUMER |
63 #define log_develop_debug(...) DUMMY_ARGUMENT_CONSUMER |
63 #define log_develop_debug(...) DUMMY_ARGUMENT_CONSUMER |
64 #define log_develop_trace(...) DUMMY_ARGUMENT_CONSUMER |
64 #define log_develop_trace(...) DUMMY_ARGUMENT_CONSUMER |
65 #define log_develop_is_enabled(...) false |
65 #define log_develop_is_enabled(...) false |
66 #endif |
66 #endif |
67 |
67 |
68 // Convenience macro to test if the logging is enabled on the specified level for given tags. |
68 // Convenience macro to test if the logging is enabled on the specified level for given tags. |
69 #define log_is_enabled(level, ...) (Log<LOG_TAGS(__VA_ARGS__)>::is_level(LogLevel::level)) |
69 #define log_is_enabled(level, ...) (LogImpl<LOG_TAGS(__VA_ARGS__)>::is_level(LogLevel::level)) |
70 |
70 |
71 // |
71 // |
72 // Log class for more advanced logging scenarios. |
72 // Log class for more advanced logging scenarios. |
73 // Has printf-style member functions for each log level (trace(), debug(), etc). |
73 // Has printf-style member functions for each log level (trace(), debug(), etc). |
74 // |
74 // |
75 // Also has outputStream compatible API for the different log-levels. |
75 // Also has outputStream compatible API for the different log-levels. |
76 // The streams are resource allocated when requested and are accessed through |
76 // The streams are resource allocated when requested and are accessed through |
77 // calls to <level>_stream() functions (trace_stream(), debug_stream(), etc). |
77 // calls to <level>_stream() functions (trace_stream(), debug_stream(), etc). |
78 // |
78 // |
79 // Example usage: |
79 // Example usage: |
80 // LogHandle(logging) log; |
80 // Log(logging) log; |
81 // if (log.is_debug()) { |
81 // if (log.is_debug()) { |
82 // ... |
82 // ... |
83 // log.debug("result = %d", result).trace(" tracing info"); |
83 // log.debug("result = %d", result).trace(" tracing info"); |
84 // obj->print_on(log.debug_stream()); |
84 // obj->print_on(log.debug_stream()); |
85 // } |
85 // } |
86 // |
86 // |
87 #define LogHandle(...) Log<LOG_TAGS(__VA_ARGS__)> |
87 #define Log(...) LogImpl<LOG_TAGS(__VA_ARGS__)> |
88 |
88 |
89 template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag> |
89 template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag> |
90 class Log; |
90 class LogImpl; |
91 |
91 |
92 // Non-template helper class for implementing write-slowpath in cpp |
92 // Non-template helper class for implementing write-slowpath in cpp |
93 class LogWriteHelper : AllStatic { |
93 class LogWriteHelper : AllStatic { |
94 private: |
94 private: |
95 |
95 |
96 template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag> |
96 template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag> |
97 friend class Log; |
97 friend class LogImpl; |
98 |
98 |
99 ATTRIBUTE_PRINTF(6, 0) |
99 ATTRIBUTE_PRINTF(6, 0) |
100 static void write_large(LogTagSet& lts, |
100 static void write_large(LogTagSet& lts, |
101 LogLevelType level, |
101 LogLevelType level, |
102 const char* prefix, |
102 const char* prefix, |
106 va_list args); |
106 va_list args); |
107 }; |
107 }; |
108 |
108 |
109 template <LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG, LogTagType T3 = LogTag::__NO_TAG, |
109 template <LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG, LogTagType T3 = LogTag::__NO_TAG, |
110 LogTagType T4 = LogTag::__NO_TAG, LogTagType GuardTag = LogTag::__NO_TAG> |
110 LogTagType T4 = LogTag::__NO_TAG, LogTagType GuardTag = LogTag::__NO_TAG> |
111 class Log VALUE_OBJ_CLASS_SPEC { |
111 class LogImpl VALUE_OBJ_CLASS_SPEC { |
112 private: |
112 private: |
113 static const size_t LogBufferSize = 512; |
113 static const size_t LogBufferSize = 512; |
114 public: |
114 public: |
115 // Make sure no more than the maximum number of tags have been given. |
115 // Make sure no more than the maximum number of tags have been given. |
116 // The GuardTag allows this to be detected if/when it happens. If the GuardTag |
116 // The GuardTag allows this to be detected if/when it happens. If the GuardTag |
117 // is not __NO_TAG, the number of tags given exceeds the maximum allowed. |
117 // is not __NO_TAG, the number of tags given exceeds the maximum allowed. |
118 STATIC_ASSERT(GuardTag == LogTag::__NO_TAG); // Number of logging tags exceeds maximum supported! |
118 STATIC_ASSERT(GuardTag == LogTag::__NO_TAG); // Number of logging tags exceeds maximum supported! |
119 |
119 |
120 // Empty constructor to avoid warnings on MSVC about unused variables |
120 // Empty constructor to avoid warnings on MSVC about unused variables |
121 // when the log instance is only used for static functions. |
121 // when the log instance is only used for static functions. |
122 Log() { |
122 LogImpl() { |
123 } |
123 } |
124 |
124 |
125 static bool is_level(LogLevelType level) { |
125 static bool is_level(LogLevelType level) { |
126 return LogTagSetMapping<T0, T1, T2, T3, T4>::tagset().is_level(level); |
126 return LogTagSetMapping<T0, T1, T2, T3, T4>::tagset().is_level(level); |
127 } |
127 } |