2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/integration-api/debug.h>
29 // Fake globals for gdb typedefs
30 Dali::DebugPropertyValueArray gValueArray;
31 Dali::DebugPropertyValueMap gValueMap;
39 thread_local LogFunction gthreadLocalLogFunction = nullptr;
41 /* Forward declarations */
42 std::string FormatToString(const char* format, ...);
43 std::string ArgListToString(const char* format, va_list args);
45 void LogMessage(DebugPriority priority, const char* format, ...)
47 if(!gthreadLocalLogFunction)
53 va_start(arg, format);
54 std::string message = ArgListToString(format, arg);
57 gthreadLocalLogFunction(priority, message);
60 void InstallLogFunction(const LogFunction& logFunction)
62 // TLS stores a pointer to an object.
63 // It needs to be allocated on the heap, because TLS will destroy it when the thread exits.
65 gthreadLocalLogFunction = logFunction;
68 void UninstallLogFunction()
70 gthreadLocalLogFunction = nullptr;
75 /*Change false to true if trace is needed but don't commit to codeline*/
76 Filter* Filter::gRender = Filter::New(Debug::Concise, false, "LOG_RENDER");
77 Filter* Filter::gResource = Filter::New(Debug::Concise, false, "LOG_RESOURCE");
78 Filter* Filter::gGLResource = Filter::New(Debug::Concise, false, "LOG_GL_RESOURCE");
79 Filter* Filter::gObject = nullptr;
80 Filter* Filter::gImage = Filter::New(Debug::Concise, false, "LOG_IMAGE");
81 Filter* Filter::gModel = Filter::New(Debug::Concise, false, "LOG_MODEL");
82 Filter* Filter::gNode = nullptr;
83 Filter* Filter::gElement = nullptr;
84 Filter* Filter::gActor = Filter::New(Debug::Concise, false, "LOG_ACTOR");
85 Filter* Filter::gShader = Filter::New(Debug::Concise, false, "LOG_SHADER");
87 Filter::FilterList* Filter::GetActiveFilters()
89 static Filter::FilterList* activeFilters = new FilterList;
93 Filter* Filter::New(LogLevel level, bool trace, const char* environmentVariableName)
95 char* environmentVariableValue = getenv(environmentVariableName);
96 if(environmentVariableValue)
98 unsigned int envLevel(0);
99 char envTraceString(0);
100 sscanf(environmentVariableValue, "%u,%c", &envLevel, &envTraceString);
102 if(envLevel > Verbose)
106 level = LogLevel(envLevel);
108 // Just use 'f' and 't' as it's faster than doing full string comparisons
109 if(envTraceString == 't')
113 else if(envTraceString == 'f')
119 Filter* filter = new Filter(level, trace);
121 GetActiveFilters()->push_back(filter);
126 * Enable trace on all filters.
128 void Filter::EnableGlobalTrace()
130 for(FilterIter iter = GetActiveFilters()->begin(); iter != GetActiveFilters()->end(); iter++)
132 (*iter)->EnableTrace();
137 * Disable trace on all filters.
139 void Filter::DisableGlobalTrace()
141 for(FilterIter iter = GetActiveFilters()->begin(); iter != GetActiveFilters()->end(); iter++)
143 (*iter)->DisableTrace();
147 void Filter::SetGlobalLogLevel(LogLevel level)
149 for(FilterIter iter = GetActiveFilters()->begin(); iter != GetActiveFilters()->end(); iter++)
151 (*iter)->SetLogLevel(level);
155 void Filter::Log(LogLevel level, const char* format, ...)
157 if(level <= mLoggingLevel)
160 va_start(arg, format);
164 char* buffer = nullptr;
165 int numChars = asprintf(&buffer, " %-*c %s", mNesting, ':', format);
166 if(numChars >= 0) // No error
168 std::string message = ArgListToString(buffer, arg);
169 LogMessage(DebugInfo, message.c_str());
175 std::string message = ArgListToString(format, arg);
176 LogMessage(DebugInfo, message.c_str());
182 TraceObj::TraceObj(Filter* filter, const char* format, ...)
185 if(mFilter && mFilter->IsTraceEnabled())
188 va_start(arg, format);
189 mMessage = ArgListToString(format, arg);
192 LogMessage(DebugInfo, "Entr%-*c %s\n", mFilter->mNesting, ':', mMessage.c_str());
197 TraceObj::~TraceObj()
199 if(mFilter && mFilter->IsTraceEnabled())
201 if(mFilter->mNesting)
205 LogMessage(DebugInfo, "Exit%-*c %s\n", mFilter->mNesting, ':', mMessage.c_str());
209 #endif // DEBUG_ENABLED
211 std::string ArgListToString(const char* format, va_list args)
213 std::string str; // empty string
214 if(format != nullptr)
216 char* buffer = nullptr;
217 int err = vasprintf(&buffer, format, args);
218 if(err >= 0) // No error
227 std::string FormatToString(const char* format, ...)
230 va_start(arg, format);
231 std::string s = ArgListToString(format, arg);
238 void GetNanoseconds(uint64_t& timeInNanoseconds)
240 // Get the time of a monotonic clock since its epoch.
241 auto epoch = std::chrono::steady_clock::now().time_since_epoch();
243 auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(epoch);
245 timeInNanoseconds = static_cast<uint64_t>(duration.count());
248 #endif // DEBUG_ENABLED
252 } // namespace Integration