1 #ifndef DALI_INTEGRATION_DEBUG_H
2 #define DALI_INTEGRATION_DEBUG_H
5 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
28 #include <dali/public-api/common/vector-wrapper.h>
29 #include <dali/public-api/object/property-map.h>
32 #include <dali/public-api/common/dali-common.h>
34 // Using Debug namespace alias shortens the log usage significantly
42 } // namespace Integration
44 namespace Debug = Dali::Integration::Log;
55 #if defined(DEBUG_ENABLED)
57 // Less opaque types for debugger
58 typedef std::vector<Dali::Property::Value> DebugPropertyValueArray;
59 using DebugIndexValuePair = std::pair<Property::Index, Property::Value>;
60 using DebugStringValueContainer = std::vector<Dali::StringValuePair>;
61 using DebugIndexValueContainer = std::vector<DebugIndexValuePair>;
63 struct DebugPropertyValueMap
65 DebugStringValueContainer stringValues;
66 DebugIndexValueContainer intValues;
69 // Fake globals for gdb typedefs
70 extern Dali::DebugPropertyValueArray gValueArray;
71 extern Dali::DebugPropertyValueMap gValueMap;
87 * Used by logging macros to log a message along with function/class name
88 * @param level debug level
89 * @param format string format
91 DALI_CORE_API void LogMessage(enum DebugPriority level, const char* format, ...);
94 * typedef for the logging function.
96 using LogFunction = void (*)(DebugPriority, std::string&);
99 * A log function has to be installed for every thread that wants to use logging.
100 * This should be done by the adaptor.
101 * The log function can be different for each thread.
102 * @param logFunction the log function to install
103 * @param logOpts the log options to save in thread
105 DALI_CORE_API void InstallLogFunction(const LogFunction& logFunction);
108 * A log function has to be uninstalled for every thread that wants to use logging.
109 * The log function can be different for each thread.
111 DALI_CORE_API void UninstallLogFunction();
113 /********************************************************************************
114 * Error/Warning macros. *
115 ********************************************************************************/
118 * Provides unfiltered logging for global error level messages
120 #define DALI_LOG_ERROR(format, ...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugError, "%s " format, __FUNCTION__, ##__VA_ARGS__)
122 #define DALI_LOG_ERROR_NOFN(format, ...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugError, format, ##__VA_ARGS__)
124 #define DALI_LOG_WARNING_NOFN(format, ...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugWarning, format, ##__VA_ARGS__)
127 * Provides unfiltered logging for fps monitor
129 #define DALI_LOG_FPS(format, ...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ##__VA_ARGS__)
132 * Provides unfiltered logging for update status
134 #define DALI_LOG_UPDATE_STATUS(format, ...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ##__VA_ARGS__)
137 * Provides unfiltered logging for render information
139 #define DALI_LOG_RENDER_INFO(format, ...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ##__VA_ARGS__)
142 * Provides unfiltered logging for release
144 #define DALI_LOG_RELEASE_INFO(format, ...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ##__VA_ARGS__)
149 * Provides unfiltered logging for global warning level messages
151 #define DALI_LOG_WARNING(format, ...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugWarning, "%s " format, ASSERT_LOCATION, ##__VA_ARGS__)
153 #else // DEBUG_ENABLED
155 // Don't warn on release build
156 #define DALI_LOG_WARNING(format, ...)
160 /********************************************************************************
162 ********************************************************************************/
167 * Enumeration of logging levels.
168 * Used by the filters to provide multiple log levels.
169 * In general, the higher the value, the more debug is available for that filter.
180 * The Filter object is used by the DALI_LOG_INFO macro and others to determine if the logging
181 * should take place, and routes the logging via the platform abstraction's LogMessage.
183 * It provides a logging level. If this is set to zero, then DALI_LOG_INFO won't log anything.
184 * It provides the ability to turn tracing on or off.
187 class DALI_CORE_API Filter
190 using FilterList = std::list<Filter*>;
191 using FilterIter = std::list<Filter*>::iterator;
195 * Test if the filter is enabled for the given logging level
196 * @param[in] level - the level to test.
197 * @return true if this level of logging is enabled.
199 bool IsEnabledFor(LogLevel level)
201 return level != Debug::NoLogging && level <= mLoggingLevel;
205 * Test if trace is enabled for this filter.
206 * @return true if trace is enabled;
208 bool IsTraceEnabled()
210 return mTraceEnabled;
214 * Enable tracing on this filter.
218 mTraceEnabled = true;
222 * Disable tracing on this filter.
226 mTraceEnabled = false;
230 * Set the log level for this filter. Setting to a higher value than Debug::General also
233 void SetLogLevel(LogLevel level)
235 mLoggingLevel = level;
239 * Perform the logging for this filter.
241 void Log(LogLevel level, const char* format, ...);
244 * Create a new filter whose debug level and trace can be modified through the use of an
245 * environment variable.
247 * @param[in] level The default log level
248 * @param[in] trace The default trace level. If true, function tracing is on.
249 * @param[in] environmentVariableName The environment variable name used in order to change the
250 * log level or trace.
252 * @info To modify logg level/trace at runtime, you can should define your filter as shown below:
255 * Debug::Filter* filter = Debug::Filter::New( Debug::NoLogging, false, "FILTER_ENV" );
258 * And to use it when running an executable:
260 * FILTER_ENV=3 dali-demo // LogLevel Verbose, Trace using default
261 * FILTER_ENV=1,true dali-demo // LogLevel Concise, Trace ON
262 * FILTER_ENV=2,false dali-demo // LogLevel General, Trace OFF
263 * FILTER_ENV=0,true dali-demo // LogLevel NoLogging, Trace ON
266 static Filter* New(LogLevel level, bool trace, const char* environmentVariableName);
269 * Enable trace on all filters.
271 static void EnableGlobalTrace();
274 * Disable trace on all filters.
276 static void DisableGlobalTrace();
279 * Set log level for all filters.
281 * @param[in] level The log level
283 static void SetGlobalLogLevel(LogLevel level);
288 * @param[in] level - the highest log level.
289 * @param[in] trace - whether this filter allows tracing.
291 Filter(LogLevel level, bool trace)
292 : mLoggingLevel(level),
293 mTraceEnabled(trace),
298 static FilterList* GetActiveFilters();
301 // High level filters. If these filters are too broad for your current requirement, then
302 // you can add a filter to your own class or source file. If you do, use Filter::New()
303 // to tell this class about it.
305 static Filter* gRender;
306 static Filter* gResource;
307 static Filter* gGLResource;
308 static Filter* gObject;
309 static Filter* gImage;
310 static Filter* gModel;
311 static Filter* gNode;
312 static Filter* gElement;
313 static Filter* gActor;
314 static Filter* gShader;
317 LogLevel mLoggingLevel;
324 #define DALI_LOG_FILTER_SET_LEVEL(filter, level) filter->SetLogLevel(level)
325 #define DALI_LOG_FILTER_ENABLE_TRACE(filter) filter->EnableTrace()
326 #define DALI_LOG_FILTER_DISABLE_TRACE(filter) filter->DisableTrace()
330 #define DALI_LOG_FILTER_SET_LEVEL(filter, level)
331 #define DALI_LOG_FILTER_ENABLE_TRACE(filter)
332 #define DALI_LOG_FILTER_DISABLE_TRACE(filter)
336 /********************************************************************************
337 * General Logging macros *
338 ********************************************************************************/
342 #define DALI_LOG_INFO(filter, level, format, ...) \
343 if(filter && filter->IsEnabledFor(level)) \
345 filter->Log(level, format, ##__VA_ARGS__); \
348 #define DALI_LOG_STREAM(filter, level, stream) \
349 if(filter && filter->IsEnabledFor(level)) \
351 std::ostringstream o; \
352 o << stream << std::endl; \
353 filter->Log(level, "%s", o.str().c_str()); \
356 #else // DEBUG_ENABLED
358 #define DALI_LOG_INFO(filter, level, format, ...)
359 #define DALI_LOG_STREAM(filter, level, stream)
361 #endif // DEBUG_ENABLED
363 /********************************************************************************
365 ********************************************************************************/
368 * These macros allow the instrumentation of methods. These translate into calls
369 * to LogMessage(DebugInfo).
374 class DALI_CORE_API TraceObj
377 TraceObj(Filter* filter, const char* fmt, ...);
381 std::string mMessage;
385 #define DALI_LOG_TRACE_METHOD_FMT(filter, format, ...) \
386 Dali::Integration::Log::TraceObj debugTraceObj(filter, "%s: " format, ASSERT_LOCATION, ##__VA_ARGS__)
388 #define DALI_LOG_TRACE_METHOD(filter) \
389 Dali::Integration::Log::TraceObj debugTraceObj(filter, ASSERT_LOCATION)
391 #else // DEBUG_ENABLED
393 #define DALI_LOG_TRACE_METHOD_FMT(filter, format, ...)
394 #define DALI_LOG_TRACE_METHOD(filter)
398 /********************************************************************************
399 * Extra object debug *
400 ********************************************************************************/
405 * Warning, this macro changes the current scope, so should usually be put at the
406 * end of the class definition.
408 * Suggest that the value is usually set to the object's name.
409 * Warning - this will increase the size of the object for a debug build.
411 #define DALI_LOG_OBJECT_STRING_DECLARATION \
413 std::string mDebugString;
416 * Print all the actor tree names
418 #define DALI_LOG_ACTOR_TREE(node) \
420 std::stringstream branch; \
421 Node* tempNode = node; \
424 branch << "<" << tempNode->mDebugString << ">::"; \
425 tempNode = tempNode->GetParent(); \
427 DALI_LOG_ERROR_NOFN("Actor tree: %s\n", branch.str().c_str()); \
431 * Allows one object to set another object's debug string
433 #define DALI_LOG_SET_OBJECT_STRING(object, string) (object->mDebugString = string)
436 * Allows one object to set another object's std::string easily
438 #define DALI_LOG_FMT_OBJECT_STRING(object, fmt, ...) (object->mDebugString = FormatToString(fmt, ##__VA_ARGS__))
441 * Allows one object to get another object's debug string
443 #define DALI_LOG_GET_OBJECT_STRING(object) (object->mDebugString)
446 * Get the C string (for use in formatted logging)
448 #define DALI_LOG_GET_OBJECT_C_STR(object) (object->mDebugString.c_str())
451 * Filtered logging of the object's debug string
453 #define DALI_LOG_OBJECT(filter, object) DALI_LOG_INFO(filter, Debug::General, object->mDebugString)
455 #else // DEBUG_ENABLED
457 #define DALI_LOG_OBJECT_STRING_DECLARATION
458 #define DALI_LOG_ACTOR_TREE(node)
459 #define DALI_LOG_SET_OBJECT_STRING(object, string)
460 #define DALI_LOG_FMT_OBJECT_STRING(object, fmt, ...)
461 #define DALI_LOG_GET_OBJECT_STRING(object)
462 #define DALI_LOG_GET_OBJECT_C_STR(object) ""
463 #define DALI_LOG_OBJECT(filter, object)
467 /********************************************************************************
468 * Time instrumentation *
469 ********************************************************************************/
471 #if defined(DEBUG_ENABLED)
473 void GetNanoseconds(uint64_t& timeInNanoseconds);
475 #define DALI_LOG_TIMER_START(timeVariable) \
476 uint64_t timeVariable##1; \
477 Debug::GetNanoseconds(timeVariable##1);
479 #define DALI_LOG_TIMER_END(timeVariable, filter, level, preString) \
480 uint64_t timeVariable##2; \
481 Debug::GetNanoseconds(timeVariable##2); \
482 DALI_LOG_INFO(filter, level, preString " %ld uSec\n", ((timeVariable##2 - timeVariable##1) / 1000));
484 #else // DEBUG_ENABLED
486 #define DALI_LOG_TIMER_START(timeVariable)
487 #define DALI_LOG_TIMER_END(timeVariable, filter, level, preString)
492 } // namespace Integration
495 #endif // DALI_INTEGRATION_DEBUG_H