158310b49fc8a7a713b922319a849a419858db79eDan Albert/* 258310b49fc8a7a713b922319a849a419858db79eDan Albert * Copyright (C) 2015 The Android Open Source Project 358310b49fc8a7a713b922319a849a419858db79eDan Albert * 458310b49fc8a7a713b922319a849a419858db79eDan Albert * Licensed under the Apache License, Version 2.0 (the "License"); 558310b49fc8a7a713b922319a849a419858db79eDan Albert * you may not use this file except in compliance with the License. 658310b49fc8a7a713b922319a849a419858db79eDan Albert * You may obtain a copy of the License at 758310b49fc8a7a713b922319a849a419858db79eDan Albert * 858310b49fc8a7a713b922319a849a419858db79eDan Albert * http://www.apache.org/licenses/LICENSE-2.0 958310b49fc8a7a713b922319a849a419858db79eDan Albert * 1058310b49fc8a7a713b922319a849a419858db79eDan Albert * Unless required by applicable law or agreed to in writing, software 1158310b49fc8a7a713b922319a849a419858db79eDan Albert * distributed under the License is distributed on an "AS IS" BASIS, 1258310b49fc8a7a713b922319a849a419858db79eDan Albert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1358310b49fc8a7a713b922319a849a419858db79eDan Albert * See the License for the specific language governing permissions and 1458310b49fc8a7a713b922319a849a419858db79eDan Albert * limitations under the License. 1558310b49fc8a7a713b922319a849a419858db79eDan Albert */ 1658310b49fc8a7a713b922319a849a419858db79eDan Albert 17ac3f7d9a78f9024563cc47f62206c6e3475778ddSpencer Low#ifdef _WIN32 18ac3f7d9a78f9024563cc47f62206c6e3475778ddSpencer Low#include <windows.h> 19ac3f7d9a78f9024563cc47f62206c6e3475778ddSpencer Low#endif 20ac3f7d9a78f9024563cc47f62206c6e3475778ddSpencer Low 214f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include "android-base/logging.h" 2258310b49fc8a7a713b922319a849a419858db79eDan Albert 237a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert#include <libgen.h> 247a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert 257a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert// For getprogname(3) or program_invocation_short_name. 267a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert#if defined(__ANDROID__) || defined(__APPLE__) 277a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert#include <stdlib.h> 287a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert#elif defined(__GLIBC__) 297a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert#include <errno.h> 307a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert#endif 317a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert 3258310b49fc8a7a713b922319a849a419858db79eDan Albert#include <iostream> 3358310b49fc8a7a713b922319a849a419858db79eDan Albert#include <limits> 3458310b49fc8a7a713b922319a849a419858db79eDan Albert#include <sstream> 3558310b49fc8a7a713b922319a849a419858db79eDan Albert#include <string> 36b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert#include <utility> 3758310b49fc8a7a713b922319a849a419858db79eDan Albert#include <vector> 3858310b49fc8a7a713b922319a849a419858db79eDan Albert 395c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#ifndef _WIN32 405c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#include <mutex> 415c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#endif 425c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 434f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include "android-base/macros.h" 444f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include "android-base/strings.h" 457dfb61dcdca8ee597f23b9acc365fb140b353fffDan Albert#include "cutils/threads.h" 4658310b49fc8a7a713b922319a849a419858db79eDan Albert 4758310b49fc8a7a713b922319a849a419858db79eDan Albert// Headers for LogMessage::LogLine. 4858310b49fc8a7a713b922319a849a419858db79eDan Albert#ifdef __ANDROID__ 4958310b49fc8a7a713b922319a849a419858db79eDan Albert#include <android/set_abort_message.h> 5058310b49fc8a7a713b922319a849a419858db79eDan Albert#include "cutils/log.h" 5158310b49fc8a7a713b922319a849a419858db79eDan Albert#else 5258310b49fc8a7a713b922319a849a419858db79eDan Albert#include <sys/types.h> 5358310b49fc8a7a713b922319a849a419858db79eDan Albert#include <unistd.h> 5458310b49fc8a7a713b922319a849a419858db79eDan Albert#endif 5558310b49fc8a7a713b922319a849a419858db79eDan Albert 56c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes// For gettid. 57c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#if defined(__APPLE__) 58c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED 59c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <stdint.h> 60c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <stdlib.h> 61c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <sys/syscall.h> 62c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <sys/time.h> 63c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <unistd.h> 64c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#elif defined(__linux__) && !defined(__ANDROID__) 65c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <syscall.h> 66c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <unistd.h> 67c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#elif defined(_WIN32) 68c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#include <windows.h> 69c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#endif 70c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes 719dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsen#if defined(_WIN32) 729dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsentypedef uint32_t thread_id; 739dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsen#else 749dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsentypedef pid_t thread_id; 759dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsen#endif 769dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsen 779dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsenstatic thread_id GetThreadId() { 78c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#if defined(__BIONIC__) 79c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes return gettid(); 80c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#elif defined(__APPLE__) 81c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes return syscall(SYS_thread_selfid); 82c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#elif defined(__linux__) 83c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes return syscall(__NR_gettid); 84c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#elif defined(_WIN32) 85c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes return GetCurrentThreadId(); 86c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes#endif 87c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes} 88c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes 895c19040b06b5bb61731e24ea6777c237dc23145dDan Albertnamespace { 905c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#ifndef _WIN32 915c19040b06b5bb61731e24ea6777c237dc23145dDan Albertusing std::mutex; 925c19040b06b5bb61731e24ea6777c237dc23145dDan Albertusing std::lock_guard; 935c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 945c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#if defined(__GLIBC__) 955c19040b06b5bb61731e24ea6777c237dc23145dDan Albertconst char* getprogname() { 965c19040b06b5bb61731e24ea6777c237dc23145dDan Albert return program_invocation_short_name; 975c19040b06b5bb61731e24ea6777c237dc23145dDan Albert} 985c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#endif 995c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 1005c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#else 1015c19040b06b5bb61731e24ea6777c237dc23145dDan Albertconst char* getprogname() { 1025c19040b06b5bb61731e24ea6777c237dc23145dDan Albert static bool first = true; 1035c19040b06b5bb61731e24ea6777c237dc23145dDan Albert static char progname[MAX_PATH] = {}; 1045c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 1055c19040b06b5bb61731e24ea6777c237dc23145dDan Albert if (first) { 106bdab59a8613c732df5d746328ff2268be8da13abSpencer Low CHAR longname[MAX_PATH]; 107bdab59a8613c732df5d746328ff2268be8da13abSpencer Low DWORD nchars = GetModuleFileNameA(nullptr, longname, arraysize(longname)); 108bdab59a8613c732df5d746328ff2268be8da13abSpencer Low if ((nchars >= arraysize(longname)) || (nchars == 0)) { 109bdab59a8613c732df5d746328ff2268be8da13abSpencer Low // String truncation or some other error. 110bdab59a8613c732df5d746328ff2268be8da13abSpencer Low strcpy(progname, "<unknown>"); 111bdab59a8613c732df5d746328ff2268be8da13abSpencer Low } else { 112bdab59a8613c732df5d746328ff2268be8da13abSpencer Low strcpy(progname, basename(longname)); 113bdab59a8613c732df5d746328ff2268be8da13abSpencer Low } 1145c19040b06b5bb61731e24ea6777c237dc23145dDan Albert first = false; 1155c19040b06b5bb61731e24ea6777c237dc23145dDan Albert } 1165c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 1175c19040b06b5bb61731e24ea6777c237dc23145dDan Albert return progname; 1185c19040b06b5bb61731e24ea6777c237dc23145dDan Albert} 1195c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 1205c19040b06b5bb61731e24ea6777c237dc23145dDan Albertclass mutex { 1215c19040b06b5bb61731e24ea6777c237dc23145dDan Albert public: 1225c19040b06b5bb61731e24ea6777c237dc23145dDan Albert mutex() { 123bdab59a8613c732df5d746328ff2268be8da13abSpencer Low InitializeCriticalSection(&critical_section_); 1245c19040b06b5bb61731e24ea6777c237dc23145dDan Albert } 1255c19040b06b5bb61731e24ea6777c237dc23145dDan Albert ~mutex() { 126bdab59a8613c732df5d746328ff2268be8da13abSpencer Low DeleteCriticalSection(&critical_section_); 1275c19040b06b5bb61731e24ea6777c237dc23145dDan Albert } 1285c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 1295c19040b06b5bb61731e24ea6777c237dc23145dDan Albert void lock() { 130bdab59a8613c732df5d746328ff2268be8da13abSpencer Low EnterCriticalSection(&critical_section_); 1315c19040b06b5bb61731e24ea6777c237dc23145dDan Albert } 1325c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 1335c19040b06b5bb61731e24ea6777c237dc23145dDan Albert void unlock() { 134bdab59a8613c732df5d746328ff2268be8da13abSpencer Low LeaveCriticalSection(&critical_section_); 1355c19040b06b5bb61731e24ea6777c237dc23145dDan Albert } 1365c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 1375c19040b06b5bb61731e24ea6777c237dc23145dDan Albert private: 138bdab59a8613c732df5d746328ff2268be8da13abSpencer Low CRITICAL_SECTION critical_section_; 1395c19040b06b5bb61731e24ea6777c237dc23145dDan Albert}; 1405c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 1415c19040b06b5bb61731e24ea6777c237dc23145dDan Alberttemplate <typename LockT> 1425c19040b06b5bb61731e24ea6777c237dc23145dDan Albertclass lock_guard { 1435c19040b06b5bb61731e24ea6777c237dc23145dDan Albert public: 1445c19040b06b5bb61731e24ea6777c237dc23145dDan Albert explicit lock_guard(LockT& lock) : lock_(lock) { 1455c19040b06b5bb61731e24ea6777c237dc23145dDan Albert lock_.lock(); 1465c19040b06b5bb61731e24ea6777c237dc23145dDan Albert } 1475c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 1485c19040b06b5bb61731e24ea6777c237dc23145dDan Albert ~lock_guard() { 1495c19040b06b5bb61731e24ea6777c237dc23145dDan Albert lock_.unlock(); 1505c19040b06b5bb61731e24ea6777c237dc23145dDan Albert } 1515c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 1525c19040b06b5bb61731e24ea6777c237dc23145dDan Albert private: 1535c19040b06b5bb61731e24ea6777c237dc23145dDan Albert LockT& lock_; 1545c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 1555c19040b06b5bb61731e24ea6777c237dc23145dDan Albert DISALLOW_COPY_AND_ASSIGN(lock_guard); 1565c19040b06b5bb61731e24ea6777c237dc23145dDan Albert}; 1575c19040b06b5bb61731e24ea6777c237dc23145dDan Albert#endif 1585c19040b06b5bb61731e24ea6777c237dc23145dDan Albert} // namespace 1595c19040b06b5bb61731e24ea6777c237dc23145dDan Albert 16058310b49fc8a7a713b922319a849a419858db79eDan Albertnamespace android { 16158310b49fc8a7a713b922319a849a419858db79eDan Albertnamespace base { 16258310b49fc8a7a713b922319a849a419858db79eDan Albert 1637df6b5fc79a0f4521d171280cd431640ac567d27Josh Gaostatic auto& logging_lock = *new mutex(); 16458310b49fc8a7a713b922319a849a419858db79eDan Albert 165b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert#ifdef __ANDROID__ 1667df6b5fc79a0f4521d171280cd431640ac567d27Josh Gaostatic auto& gLogger = *new LogFunction(LogdLogger()); 167b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert#else 1687df6b5fc79a0f4521d171280cd431640ac567d27Josh Gaostatic auto& gLogger = *new LogFunction(StderrLogger); 169b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert#endif 170b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert 1717a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albertstatic bool gInitialized = false; 17258310b49fc8a7a713b922319a849a419858db79eDan Albertstatic LogSeverity gMinimumLogSeverity = INFO; 1737df6b5fc79a0f4521d171280cd431640ac567d27Josh Gaostatic auto& gProgramInvocationName = *new std::unique_ptr<std::string>(); 17458310b49fc8a7a713b922319a849a419858db79eDan Albert 175765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer LowLogSeverity GetMinimumLogSeverity() { 176765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low return gMinimumLogSeverity; 177765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low} 178765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low 1797a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albertstatic const char* ProgramInvocationName() { 1807a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert if (gProgramInvocationName == nullptr) { 1817a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert gProgramInvocationName.reset(new std::string(getprogname())); 1827a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert } 18358310b49fc8a7a713b922319a849a419858db79eDan Albert 1847a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert return gProgramInvocationName->c_str(); 18558310b49fc8a7a713b922319a849a419858db79eDan Albert} 18658310b49fc8a7a713b922319a849a419858db79eDan Albert 187b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertvoid StderrLogger(LogId, LogSeverity severity, const char*, const char* file, 188b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert unsigned int line, const char* message) { 189bdab59a8613c732df5d746328ff2268be8da13abSpencer Low static const char log_characters[] = "VDIWEF"; 190bdab59a8613c732df5d746328ff2268be8da13abSpencer Low static_assert(arraysize(log_characters) - 1 == FATAL + 1, 191bdab59a8613c732df5d746328ff2268be8da13abSpencer Low "Mismatch in size of log_characters and values in LogSeverity"); 192b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert char severity_char = log_characters[severity]; 1937a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n", ProgramInvocationName(), 194c1fd492ac5c14a42acfbbd9b47ed178fbf1378d3Elliott Hughes severity_char, getpid(), GetThreadId(), file, line, message); 195b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert} 196b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert 197b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert 198b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert#ifdef __ANDROID__ 199b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan AlbertLogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) { 200b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert} 201b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert 202b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertstatic const android_LogPriority kLogSeverityToAndroidLogPriority[] = { 203b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, 204b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, 205b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert}; 206b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertstatic_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1, 207b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert "Mismatch in size of kLogSeverityToAndroidLogPriority and values " 208b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert "in LogSeverity"); 209b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert 210b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertstatic const log_id kLogIdToAndroidLogId[] = { 211b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert LOG_ID_MAX, LOG_ID_MAIN, LOG_ID_SYSTEM, 212b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert}; 213b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertstatic_assert(arraysize(kLogIdToAndroidLogId) == SYSTEM + 1, 214b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert "Mismatch in size of kLogIdToAndroidLogId and values in LogId"); 215b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert 216b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertvoid LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag, 217b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert const char* file, unsigned int line, 218b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert const char* message) { 219b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert int priority = kLogSeverityToAndroidLogPriority[severity]; 220b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert if (id == DEFAULT) { 221b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert id = default_log_id_; 222b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert } 223b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert 224b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert log_id lg_id = kLogIdToAndroidLogId[id]; 225b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert 226b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert if (priority == ANDROID_LOG_FATAL) { 227b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert __android_log_buf_print(lg_id, priority, tag, "%s:%u] %s", file, line, 228b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert message); 229b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert } else { 230b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert __android_log_buf_print(lg_id, priority, tag, "%s", message); 231b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert } 232b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert} 233b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert#endif 234b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert 235b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertvoid InitLogging(char* argv[], LogFunction&& logger) { 236b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert SetLogger(std::forward<LogFunction>(logger)); 237b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert InitLogging(argv); 238b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert} 239b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert 24058310b49fc8a7a713b922319a849a419858db79eDan Albertvoid InitLogging(char* argv[]) { 2417a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert if (gInitialized) { 24258310b49fc8a7a713b922319a849a419858db79eDan Albert return; 24358310b49fc8a7a713b922319a849a419858db79eDan Albert } 24458310b49fc8a7a713b922319a849a419858db79eDan Albert 2457a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert gInitialized = true; 2467a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert 24758310b49fc8a7a713b922319a849a419858db79eDan Albert // Stash the command line for later use. We can use /proc/self/cmdline on 248363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low // Linux to recover this, but we don't have that luxury on the Mac/Windows, 249363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low // and there are a couple of argv[0] variants that are commonly used. 25058310b49fc8a7a713b922319a849a419858db79eDan Albert if (argv != nullptr) { 2517a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert gProgramInvocationName.reset(new std::string(basename(argv[0]))); 25258310b49fc8a7a713b922319a849a419858db79eDan Albert } 2537a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert 25458310b49fc8a7a713b922319a849a419858db79eDan Albert const char* tags = getenv("ANDROID_LOG_TAGS"); 25558310b49fc8a7a713b922319a849a419858db79eDan Albert if (tags == nullptr) { 25658310b49fc8a7a713b922319a849a419858db79eDan Albert return; 25758310b49fc8a7a713b922319a849a419858db79eDan Albert } 25858310b49fc8a7a713b922319a849a419858db79eDan Albert 25947328c96d91ca71b57b8976df2df1fe51579a955Dan Albert std::vector<std::string> specs = Split(tags, " "); 26058310b49fc8a7a713b922319a849a419858db79eDan Albert for (size_t i = 0; i < specs.size(); ++i) { 26158310b49fc8a7a713b922319a849a419858db79eDan Albert // "tag-pattern:[vdiwefs]" 26258310b49fc8a7a713b922319a849a419858db79eDan Albert std::string spec(specs[i]); 26358310b49fc8a7a713b922319a849a419858db79eDan Albert if (spec.size() == 3 && StartsWith(spec, "*:")) { 26458310b49fc8a7a713b922319a849a419858db79eDan Albert switch (spec[2]) { 26558310b49fc8a7a713b922319a849a419858db79eDan Albert case 'v': 26658310b49fc8a7a713b922319a849a419858db79eDan Albert gMinimumLogSeverity = VERBOSE; 26758310b49fc8a7a713b922319a849a419858db79eDan Albert continue; 26858310b49fc8a7a713b922319a849a419858db79eDan Albert case 'd': 26958310b49fc8a7a713b922319a849a419858db79eDan Albert gMinimumLogSeverity = DEBUG; 27058310b49fc8a7a713b922319a849a419858db79eDan Albert continue; 27158310b49fc8a7a713b922319a849a419858db79eDan Albert case 'i': 27258310b49fc8a7a713b922319a849a419858db79eDan Albert gMinimumLogSeverity = INFO; 27358310b49fc8a7a713b922319a849a419858db79eDan Albert continue; 27458310b49fc8a7a713b922319a849a419858db79eDan Albert case 'w': 27558310b49fc8a7a713b922319a849a419858db79eDan Albert gMinimumLogSeverity = WARNING; 27658310b49fc8a7a713b922319a849a419858db79eDan Albert continue; 27758310b49fc8a7a713b922319a849a419858db79eDan Albert case 'e': 27858310b49fc8a7a713b922319a849a419858db79eDan Albert gMinimumLogSeverity = ERROR; 27958310b49fc8a7a713b922319a849a419858db79eDan Albert continue; 28058310b49fc8a7a713b922319a849a419858db79eDan Albert case 'f': 28158310b49fc8a7a713b922319a849a419858db79eDan Albert gMinimumLogSeverity = FATAL; 28258310b49fc8a7a713b922319a849a419858db79eDan Albert continue; 28358310b49fc8a7a713b922319a849a419858db79eDan Albert // liblog will even suppress FATAL if you say 's' for silent, but that's 28458310b49fc8a7a713b922319a849a419858db79eDan Albert // crazy! 28558310b49fc8a7a713b922319a849a419858db79eDan Albert case 's': 28658310b49fc8a7a713b922319a849a419858db79eDan Albert gMinimumLogSeverity = FATAL; 28758310b49fc8a7a713b922319a849a419858db79eDan Albert continue; 28858310b49fc8a7a713b922319a849a419858db79eDan Albert } 28958310b49fc8a7a713b922319a849a419858db79eDan Albert } 29058310b49fc8a7a713b922319a849a419858db79eDan Albert LOG(FATAL) << "unsupported '" << spec << "' in ANDROID_LOG_TAGS (" << tags 29158310b49fc8a7a713b922319a849a419858db79eDan Albert << ")"; 29258310b49fc8a7a713b922319a849a419858db79eDan Albert } 29358310b49fc8a7a713b922319a849a419858db79eDan Albert} 29458310b49fc8a7a713b922319a849a419858db79eDan Albert 295b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albertvoid SetLogger(LogFunction&& logger) { 2965c19040b06b5bb61731e24ea6777c237dc23145dDan Albert lock_guard<mutex> lock(logging_lock); 297b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert gLogger = std::move(logger); 298b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert} 299b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert 300bdab59a8613c732df5d746328ff2268be8da13abSpencer Lowstatic const char* GetFileBasename(const char* file) { 301363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low // We can't use basename(3) even on Unix because the Mac doesn't 302363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low // have a non-modifying basename. 303bdab59a8613c732df5d746328ff2268be8da13abSpencer Low const char* last_slash = strrchr(file, '/'); 304363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low if (last_slash != nullptr) { 305363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low return last_slash + 1; 306363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low } 307363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low#if defined(_WIN32) 308363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low const char* last_backslash = strrchr(file, '\\'); 309363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low if (last_backslash != nullptr) { 310363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low return last_backslash + 1; 311363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low } 312363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low#endif 313363af568b8491af1a4256b09b04cfa8a0606d8ccSpencer Low return file; 314bdab59a8613c732df5d746328ff2268be8da13abSpencer Low} 315bdab59a8613c732df5d746328ff2268be8da13abSpencer Low 31658310b49fc8a7a713b922319a849a419858db79eDan Albert// This indirection greatly reduces the stack impact of having lots of 31758310b49fc8a7a713b922319a849a419858db79eDan Albert// checks/logging in a function. 31858310b49fc8a7a713b922319a849a419858db79eDan Albertclass LogMessageData { 31958310b49fc8a7a713b922319a849a419858db79eDan Albert public: 3200c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert LogMessageData(const char* file, unsigned int line, LogId id, 321765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low LogSeverity severity, int error) 322bdab59a8613c732df5d746328ff2268be8da13abSpencer Low : file_(GetFileBasename(file)), 3230c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert line_number_(line), 3240c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert id_(id), 3250c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert severity_(severity), 326765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low error_(error) { 32758310b49fc8a7a713b922319a849a419858db79eDan Albert } 32858310b49fc8a7a713b922319a849a419858db79eDan Albert 32958310b49fc8a7a713b922319a849a419858db79eDan Albert const char* GetFile() const { 33058310b49fc8a7a713b922319a849a419858db79eDan Albert return file_; 33158310b49fc8a7a713b922319a849a419858db79eDan Albert } 33258310b49fc8a7a713b922319a849a419858db79eDan Albert 33358310b49fc8a7a713b922319a849a419858db79eDan Albert unsigned int GetLineNumber() const { 33458310b49fc8a7a713b922319a849a419858db79eDan Albert return line_number_; 33558310b49fc8a7a713b922319a849a419858db79eDan Albert } 33658310b49fc8a7a713b922319a849a419858db79eDan Albert 33758310b49fc8a7a713b922319a849a419858db79eDan Albert LogSeverity GetSeverity() const { 33858310b49fc8a7a713b922319a849a419858db79eDan Albert return severity_; 33958310b49fc8a7a713b922319a849a419858db79eDan Albert } 34058310b49fc8a7a713b922319a849a419858db79eDan Albert 3410c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert LogId GetId() const { 3420c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert return id_; 3430c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert } 3440c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert 34558310b49fc8a7a713b922319a849a419858db79eDan Albert int GetError() const { 34658310b49fc8a7a713b922319a849a419858db79eDan Albert return error_; 34758310b49fc8a7a713b922319a849a419858db79eDan Albert } 34858310b49fc8a7a713b922319a849a419858db79eDan Albert 34958310b49fc8a7a713b922319a849a419858db79eDan Albert std::ostream& GetBuffer() { 35058310b49fc8a7a713b922319a849a419858db79eDan Albert return buffer_; 35158310b49fc8a7a713b922319a849a419858db79eDan Albert } 35258310b49fc8a7a713b922319a849a419858db79eDan Albert 35358310b49fc8a7a713b922319a849a419858db79eDan Albert std::string ToString() const { 35458310b49fc8a7a713b922319a849a419858db79eDan Albert return buffer_.str(); 35558310b49fc8a7a713b922319a849a419858db79eDan Albert } 35658310b49fc8a7a713b922319a849a419858db79eDan Albert 35758310b49fc8a7a713b922319a849a419858db79eDan Albert private: 35858310b49fc8a7a713b922319a849a419858db79eDan Albert std::ostringstream buffer_; 35958310b49fc8a7a713b922319a849a419858db79eDan Albert const char* const file_; 36058310b49fc8a7a713b922319a849a419858db79eDan Albert const unsigned int line_number_; 3610c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert const LogId id_; 36258310b49fc8a7a713b922319a849a419858db79eDan Albert const LogSeverity severity_; 36358310b49fc8a7a713b922319a849a419858db79eDan Albert const int error_; 36458310b49fc8a7a713b922319a849a419858db79eDan Albert 36558310b49fc8a7a713b922319a849a419858db79eDan Albert DISALLOW_COPY_AND_ASSIGN(LogMessageData); 36658310b49fc8a7a713b922319a849a419858db79eDan Albert}; 36758310b49fc8a7a713b922319a849a419858db79eDan Albert 3680c055863ebb57c3446897e89c2c39a67442c1be4Dan AlbertLogMessage::LogMessage(const char* file, unsigned int line, LogId id, 36958310b49fc8a7a713b922319a849a419858db79eDan Albert LogSeverity severity, int error) 370765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low : data_(new LogMessageData(file, line, id, severity, error)) { 37158310b49fc8a7a713b922319a849a419858db79eDan Albert} 37258310b49fc8a7a713b922319a849a419858db79eDan Albert 37358310b49fc8a7a713b922319a849a419858db79eDan AlbertLogMessage::~LogMessage() { 37458310b49fc8a7a713b922319a849a419858db79eDan Albert // Finish constructing the message. 37558310b49fc8a7a713b922319a849a419858db79eDan Albert if (data_->GetError() != -1) { 37658310b49fc8a7a713b922319a849a419858db79eDan Albert data_->GetBuffer() << ": " << strerror(data_->GetError()); 37758310b49fc8a7a713b922319a849a419858db79eDan Albert } 37858310b49fc8a7a713b922319a849a419858db79eDan Albert std::string msg(data_->ToString()); 37958310b49fc8a7a713b922319a849a419858db79eDan Albert 380765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low { 381765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low // Do the actual logging with the lock held. 382765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low lock_guard<mutex> lock(logging_lock); 383765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low if (msg.find('\n') == std::string::npos) { 3840c055863ebb57c3446897e89c2c39a67442c1be4Dan Albert LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetId(), 385765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low data_->GetSeverity(), msg.c_str()); 386765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low } else { 387765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low msg += '\n'; 388765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low size_t i = 0; 389765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low while (i < msg.size()) { 390765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low size_t nl = msg.find('\n', i); 391765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low msg[nl] = '\0'; 392765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetId(), 393765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low data_->GetSeverity(), &msg[i]); 394765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low i = nl + 1; 395765ae6bcfc62148de629f68315fdf8cd1bc35342Spencer Low } 39658310b49fc8a7a713b922319a849a419858db79eDan Albert } 39758310b49fc8a7a713b922319a849a419858db79eDan Albert } 39858310b49fc8a7a713b922319a849a419858db79eDan Albert 39958310b49fc8a7a713b922319a849a419858db79eDan Albert // Abort if necessary. 40058310b49fc8a7a713b922319a849a419858db79eDan Albert if (data_->GetSeverity() == FATAL) { 40158310b49fc8a7a713b922319a849a419858db79eDan Albert#ifdef __ANDROID__ 40258310b49fc8a7a713b922319a849a419858db79eDan Albert android_set_abort_message(msg.c_str()); 40358310b49fc8a7a713b922319a849a419858db79eDan Albert#endif 40458310b49fc8a7a713b922319a849a419858db79eDan Albert abort(); 40558310b49fc8a7a713b922319a849a419858db79eDan Albert } 40658310b49fc8a7a713b922319a849a419858db79eDan Albert} 40758310b49fc8a7a713b922319a849a419858db79eDan Albert 40858310b49fc8a7a713b922319a849a419858db79eDan Albertstd::ostream& LogMessage::stream() { 40958310b49fc8a7a713b922319a849a419858db79eDan Albert return data_->GetBuffer(); 41058310b49fc8a7a713b922319a849a419858db79eDan Albert} 41158310b49fc8a7a713b922319a849a419858db79eDan Albert 4120c055863ebb57c3446897e89c2c39a67442c1be4Dan Albertvoid LogMessage::LogLine(const char* file, unsigned int line, LogId id, 413b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert LogSeverity severity, const char* message) { 4147a87d0597476c4d87b71d46b8b8af756dc736cb3Dan Albert const char* tag = ProgramInvocationName(); 415b547c85b5b9d7fc565e47a5d0c734c3a66af242aDan Albert gLogger(id, severity, tag, file, line, message); 41658310b49fc8a7a713b922319a849a419858db79eDan Albert} 41758310b49fc8a7a713b922319a849a419858db79eDan Albert 41858310b49fc8a7a713b922319a849a419858db79eDan AlbertScopedLogSeverity::ScopedLogSeverity(LogSeverity level) { 41958310b49fc8a7a713b922319a849a419858db79eDan Albert old_ = gMinimumLogSeverity; 42058310b49fc8a7a713b922319a849a419858db79eDan Albert gMinimumLogSeverity = level; 42158310b49fc8a7a713b922319a849a419858db79eDan Albert} 42258310b49fc8a7a713b922319a849a419858db79eDan Albert 42358310b49fc8a7a713b922319a849a419858db79eDan AlbertScopedLogSeverity::~ScopedLogSeverity() { 42458310b49fc8a7a713b922319a849a419858db79eDan Albert gMinimumLogSeverity = old_; 42558310b49fc8a7a713b922319a849a419858db79eDan Albert} 42658310b49fc8a7a713b922319a849a419858db79eDan Albert 42758310b49fc8a7a713b922319a849a419858db79eDan Albert} // namespace base 42858310b49fc8a7a713b922319a849a419858db79eDan Albert} // namespace android 429