diff options
author | haohuang <haohuang@codeaurora.org> | 2019-09-16 16:03:09 +0800 |
---|---|---|
committer | haohuang <haohuang@codeaurora.org> | 2019-11-29 16:28:04 +0800 |
commit | d71529af0f5b103cdbe2679148bd7268cb4713b8 (patch) | |
tree | 37acfdeb4fb01c87982bbd8b18f168898bd5f4f2 | |
parent | a43430218337739c0c1143dc55474d1036d50558 (diff) | |
download | gps-d71529af0f5b103cdbe2679148bd7268cb4713b8.tar.gz |
Logging buffer implemented by skip list
Use skip list to implement a log buffer,
log sentences will be inserted into this buffer
once the log print function is called. the
buffer will be dumped when GNSS process
crash/killed or send SIGUSR1 signal manually.
Change-Id: I5e23cdf30c263fa59108070c9dbfd95c49c2e9b6
CRs-Fixed: 2571326
-rw-r--r-- | etc/gps.conf | 21 | ||||
-rw-r--r-- | utils/Android.mk | 3 | ||||
-rw-r--r-- | utils/LogBuffer.cpp | 167 | ||||
-rw-r--r-- | utils/LogBuffer.h | 95 | ||||
-rw-r--r-- | utils/Makefile.am | 2 | ||||
-rw-r--r-- | utils/SkipList.h | 158 | ||||
-rw-r--r-- | utils/loc_cfg.cpp | 10 | ||||
-rw-r--r-- | utils/loc_log.cpp | 50 | ||||
-rw-r--r-- | utils/log_util.h | 62 | ||||
-rw-r--r-- | utils/msg_q.c | 2 |
10 files changed, 530 insertions, 40 deletions
diff --git a/etc/gps.conf b/etc/gps.conf index 47aa8ef..1d4e233 100644 --- a/etc/gps.conf +++ b/etc/gps.conf @@ -322,3 +322,24 @@ CP_MTLR_ES=0 # and QCSR SS5 hardware receiver. # By default QTI GNSS receiver is enabled. # GNSS_DEPLOYMENT = 0 + +################################################## +## LOG BUFFER CONFIGURATION +################################################## +#LOG_BUFFER_ENABLED, 1=enable, 0=disable +#*_LEVEL_TIME_DEPTH, maximum time depth of level * +#in log buffer, unit is second +#*_LEVEL_MAX_CAPACITY, maximum numbers of level * +#log print sentences in log buffer +LOG_BUFFER_ENABLED = 0 +E_LEVEL_TIME_DEPTH = 600 +E_LEVEL_MAX_CAPACITY = 50 +W_LEVEL_TIME_DEPTH = 500 +W_LEVEL_MAX_CAPACITY = 100 +I_LEVEL_TIME_DEPTH = 400 +I_LEVEL_MAX_CAPACITY = 200 +D_LEVEL_TIME_DEPTH = 30 +D_LEVEL_MAX_CAPACITY = 300 +V_LEVEL_TIME_DEPTH = 200 +V_LEVEL_MAX_CAPACITY = 400 + diff --git a/utils/Android.mk b/utils/Android.mk index 88ad487..57d485d 100644 --- a/utils/Android.mk +++ b/utils/Android.mk @@ -27,7 +27,8 @@ LOCAL_SRC_FILES += \ MsgTask.cpp \ loc_misc_utils.cpp \ loc_nmea.cpp \ - LocIpc.cpp + LocIpc.cpp \ + LogBuffer.cpp # Flag -std=c++11 is not accepted by compiler when LOCAL_CLANG is set to true LOCAL_CFLAGS += \ diff --git a/utils/LogBuffer.cpp b/utils/LogBuffer.cpp new file mode 100644 index 0000000..1bb6f0f --- /dev/null +++ b/utils/LogBuffer.cpp @@ -0,0 +1,167 @@ +/* Copyright (c) 2019 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "LogBuffer.h" +#include <utils/Log.h> + +#define LOG_TAG "LocSvc_LogBuffer" + +namespace loc_util { + +LogBuffer* LogBuffer::mInstance; +struct sigaction LogBuffer::mOriSigAction[NSIG]; +struct sigaction LogBuffer::mNewSigAction; +mutex LogBuffer::sLock; + +LogBuffer* LogBuffer::getInstance() { + if (mInstance == nullptr) { + lock_guard<mutex> guard(sLock); + if (mInstance == nullptr) { + mInstance = new LogBuffer(); + } + } + return mInstance; +} + +LogBuffer::LogBuffer(): mLogList(TOTAL_LOG_LEVELS), + mConfigVec(TOTAL_LOG_LEVELS, ConfigsInLevel(TIME_DEPTH_THRESHOLD_MINIMAL_IN_SEC, + MAXIMUM_NUM_IN_LIST, 0)) { + loc_param_s_type log_buff_config_table[] = + { + {"E_LEVEL_TIME_DEPTH", &mConfigVec[0].mTimeDepthThres, NULL, 'n'}, + {"E_LEVEL_MAX_CAPACITY", &mConfigVec[0].mMaxNumThres, NULL, 'n'}, + {"W_LEVEL_TIME_DEPTH", &mConfigVec[1].mTimeDepthThres, NULL, 'n'}, + {"W_LEVEL_MAX_CAPACITY", &mConfigVec[1].mMaxNumThres, NULL, 'n'}, + {"I_LEVEL_TIME_DEPTH", &mConfigVec[2].mTimeDepthThres, NULL, 'n'}, + {"I_LEVEL_MAX_CAPACITY", &mConfigVec[2].mMaxNumThres, NULL, 'n'}, + {"D_LEVEL_TIME_DEPTH", &mConfigVec[3].mTimeDepthThres, NULL, 'n'}, + {"D_LEVEL_MAX_CAPACITY", &mConfigVec[3].mMaxNumThres, NULL, 'n'}, + {"V_LEVEL_TIME_DEPTH", &mConfigVec[4].mTimeDepthThres, NULL, 'n'}, + {"V_LEVEL_MAX_CAPACITY", &mConfigVec[4].mMaxNumThres, NULL, 'n'}, + }; + loc_read_conf(LOC_PATH_GPS_CONF_STR, log_buff_config_table, + sizeof(log_buff_config_table)/sizeof(log_buff_config_table[0])); + registerSignalHandler(); +} + +void LogBuffer::append(string& data, int level, uint64_t timestamp) { + lock_guard<mutex> guard(mLock); + pair<uint64_t, string> item(timestamp, data); + mLogList.append(item, level); + mConfigVec[level].mCurrentSize++; + + while ((timestamp - mLogList.front(level).first) > mConfigVec[level].mTimeDepthThres || + mConfigVec[level].mCurrentSize > mConfigVec[level].mMaxNumThres) { + mLogList.pop(level); + mConfigVec[level].mCurrentSize--; + } +} + +//Dump the log buffer of specific level, level = -1 to dump all the levels in log buffer. +void LogBuffer::dump(std::function<void(stringstream&)> log, int level) { + lock_guard<mutex> guard(mLock); + list<pair<pair<uint64_t, string>, int>> li; + if (-1 == level) { + li = mLogList.dump(); + } else { + li = mLogList.dump(level); + } + ALOGE("Begining of dump, buffer size: %d", (int)li.size()); + stringstream ln; + ln << "dump log buffer, level[" << level << "]" << ", buffer size: " << li.size() << endl; + log(ln); + for_each (li.begin(), li.end(), [&, this](const pair<pair<uint64_t, string>, int> &item){ + stringstream line; + line << "["<<item.first.first << "] "; + line << "Level " << mLevelMap[item.second] << ": "; + line << item.first.second << endl; + if (log != nullptr) { + log(line); + } + }); + ALOGE("End of dump"); +} + +void LogBuffer::dumpToAdbLogcat() { + dump([](stringstream& line){ + ALOGE("%s", line.str().c_str()); + }); +} + +void LogBuffer::dumpToLogFile(string filePath) { + ALOGE("Dump GPS log buffer to file: %s", filePath.c_str()); + fstream s; + s.open(filePath, std::fstream::out | std::fstream::app); + dump([&s](stringstream& line){ + s << line.str(); + }); + s.close(); +} + +void LogBuffer::flush() { + mLogList.flush(); +} + +void LogBuffer::registerSignalHandler() { + ALOGE("Singal handler registered"); + mNewSigAction.sa_sigaction = &LogBuffer::signalHandler; + mNewSigAction.sa_flags = SA_SIGINFO; + sigemptyset(&mNewSigAction.sa_mask); + + sigaction(SIGINT, &mNewSigAction, &mOriSigAction[SIGINT]); + sigaction(SIGKILL, &mNewSigAction, &mOriSigAction[SIGKILL]); + sigaction(SIGSEGV, &mNewSigAction, &mOriSigAction[SIGSEGV]); + sigaction(SIGABRT, &mNewSigAction, &mOriSigAction[SIGABRT]); + sigaction(SIGTRAP, &mNewSigAction, &mOriSigAction[SIGTRAP]); + sigaction(SIGUSR1, &mNewSigAction, &mOriSigAction[SIGUSR1]); +} + +void LogBuffer::signalHandler(const int code, siginfo_t *const si, void *const sc) { + ALOGE("[Gnss Log buffer]Singal handler, signal ID: %d", code); + + //Dump the log buffer to adb logcat + mInstance->dumpToAdbLogcat(); + + //Dump the log buffer to file + time_t now = time(NULL); + struct tm *curr_time = localtime(&now); + char path[50]; + snprintf(path, 50, LOG_BUFFER_FILE_PATH "gpslog_%d%d%d-%d%d%d.log", + (1900 + curr_time->tm_year), ( 1 + curr_time->tm_mon), curr_time->tm_mday, + curr_time->tm_hour, curr_time->tm_min, curr_time->tm_sec); + + mInstance->dumpToLogFile(path); + + //Process won't be terminated if SIGUSR1 is recieved + if (code != SIGUSR1) { + mOriSigAction[code].sa_sigaction(code, si, sc); + } +} + +} diff --git a/utils/LogBuffer.h b/utils/LogBuffer.h new file mode 100644 index 0000000..8d90439 --- /dev/null +++ b/utils/LogBuffer.h @@ -0,0 +1,95 @@ +/* Copyright (c) 2019 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOG_BUFFER_H +#define LOG_BUFFER_H + +#include "SkipList.h" +#include "log_util.h" +#include <loc_cfg.h> +#include <loc_pla.h> +#include <string> +#include <sstream> +#include <ostream> +#include <fstream> +#include <time.h> +#include <mutex> +#include <signal.h> +#include <thread> +#include <functional> + +//default error level time depth threshold, +#define TIME_DEPTH_THRESHOLD_MINIMAL_IN_SEC 60 +//default maximum log buffer size +#define MAXIMUM_NUM_IN_LIST 50 +//file path of dumped log buffer +#define LOG_BUFFER_FILE_PATH "/data/vendor/location/" + +namespace loc_util { + +class ConfigsInLevel{ +public: + uint32_t mTimeDepthThres; + uint32_t mMaxNumThres; + int mCurrentSize; + + ConfigsInLevel(uint32_t time, int num, int size): + mTimeDepthThres(time), mMaxNumThres(num), mCurrentSize(size) {} +}; + +class LogBuffer { +private: + static LogBuffer* mInstance; + static struct sigaction mOriSigAction[NSIG]; + static struct sigaction mNewSigAction; + static mutex sLock; + + SkipList<pair<uint64_t, string>> mLogList; + vector<ConfigsInLevel> mConfigVec; + mutex mLock; + + const vector<string> mLevelMap {"E", "W", "I", "D", "V"}; + +public: + static LogBuffer* getInstance(); + void append(string& data, int level, uint64_t timestamp); + void dump(std::function<void(stringstream&)> log, int level = -1); + void dumpToAdbLogcat(); + void dumpToLogFile(string filePath); + void flush(); +private: + LogBuffer(); + void registerSignalHandler(); + static void signalHandler(const int code, siginfo_t *const si, void *const sc); + +}; + +} + +#endif diff --git a/utils/Makefile.am b/utils/Makefile.am index 9a9c67e..72c7872 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -23,6 +23,7 @@ libgps_utils_la_h_sources = \ LocThread.h \ LocTimer.h \ LocIpc.h \ + SkipList.h\ loc_misc_utils.h \ loc_nmea.h \ gps_extended_c.h \ @@ -42,6 +43,7 @@ libgps_utils_la_c_sources = \ LocTimer.cpp \ LocThread.cpp \ LocIpc.cpp \ + LogBuffer.cpp \ MsgTask.cpp \ loc_misc_utils.cpp \ loc_nmea.cpp diff --git a/utils/SkipList.h b/utils/SkipList.h new file mode 100644 index 0000000..afaa1a6 --- /dev/null +++ b/utils/SkipList.h @@ -0,0 +1,158 @@ +/* Copyright (c) 2019 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOC_SKIP_LIST_H +#define LOC_SKIP_LIST_H + +#include <stdlib.h> +#include <list> +#include <vector> +#include <iostream> +#include <algorithm> + +using namespace std; + +namespace loc_util { + +template <typename T, + template<typename elem, typename Allocator = std::allocator<elem>> class container = list> +class SkipNode { +public: + typedef typename container<SkipNode<T, container>>::iterator NodeIterator; + + int mLevel; + T mData; + NodeIterator mNextInLevel; + + SkipNode(int level, T& data): mLevel(level), mData(data) {} +}; + +template <typename T> +class SkipList { + using NodeIterator = typename SkipNode<T>::NodeIterator; +private: + list<SkipNode<T>> mMainList; + vector<NodeIterator> mHeadVec; + vector<NodeIterator> mTailVec; +public: + SkipList(int totalLevels); + void append(T& data, int level); + void pop(int level); + void pop(); + T front(int level); + int size(); + void flush(); + list<pair<T, int>> dump(); + list<pair<T, int>> dump(int level); +}; + +template <typename T> +SkipList<T>::SkipList(int totalLevels): mHeadVec(totalLevels, mMainList.end()), + mTailVec(totalLevels, mMainList.end()) {} + +template <typename T> +void SkipList<T>::append(T& data, int level) { + if ( level < 0 || level >= mHeadVec.size()) { + return; + } + + SkipNode<T> node(level, data); + node.mNextInLevel = mMainList.end(); + mMainList.push_back(node); + auto iter = --mMainList.end(); + if (mHeadVec[level] == mMainList.end()) { + mHeadVec[level] = iter; + } else { + (*mTailVec[level]).mNextInLevel = iter; + } + mTailVec[level] = iter; +} + +template <typename T> +void SkipList<T>::pop(int level) { + if (mHeadVec[level] == mMainList.end()) { + return; + } + + if ((*mHeadVec[level]).mNextInLevel == mMainList.end()) { + mTailVec[level] = mMainList.end(); + } + + auto tmp_iter = (*mHeadVec[level]).mNextInLevel; + mMainList.erase(mHeadVec[level]); + mHeadVec[level] = tmp_iter; +} + +template <typename T> +void SkipList<T>::pop() { + pop(mMainList.front().mLevel); +} + +template <typename T> +T SkipList<T>::front(int level) { + return (*mHeadVec[level]).mData; +} + +template <typename T> +int SkipList<T>::size() { + return mMainList.size(); +} + +template <typename T> +void SkipList<T>::flush() { + mMainList.clear(); + for (int i = 0; i < mHeadVec.size(); i++) { + mHeadVec[i] = mMainList.end(); + mTailVec[i] = mMainList.end(); + } +} + +template <typename T> +list<pair<T, int>> SkipList<T>::dump() { + list<pair<T, int>> li; + for_each(mMainList.begin(), mMainList.end(), [&](SkipNode<T> &item) { + li.push_back(make_pair(item.mData, item.mLevel)); + }); + return li; +} + +template <typename T> +list<pair<T, int>> SkipList<T>::dump(int level) { + list<pair<T, int>> li; + auto head = mHeadVec[level]; + while (head != mMainList.end()) { + li.push_back(make_pair((*head).mData, (*head).mLevel)); + head = (*head).mNextInLevel; + } + return li; +} + +} + +#endif diff --git a/utils/loc_cfg.cpp b/utils/loc_cfg.cpp index 8baf8ca..432095e 100644 --- a/utils/loc_cfg.cpp +++ b/utils/loc_cfg.cpp @@ -59,13 +59,15 @@ static uint32_t DEBUG_LEVEL = 0xff; static uint32_t TIMESTAMP = 0; static uint32_t DATUM_TYPE = 0; static bool sVendorEnhanced = true; +static uint32_t sLogBufferEnabled = 0; /* Parameter spec table */ static const loc_param_s_type loc_param_table[] = { - {"DEBUG_LEVEL", &DEBUG_LEVEL, NULL, 'n'}, - {"TIMESTAMP", &TIMESTAMP, NULL, 'n'}, - {"DATUM_TYPE", &DATUM_TYPE, NULL, 'n'}, + {"DEBUG_LEVEL", &DEBUG_LEVEL, NULL, 'n'}, + {"TIMESTAMP", &TIMESTAMP, NULL, 'n'}, + {"DATUM_TYPE", &DATUM_TYPE, NULL, 'n'}, + {"LOG_BUFFER_ENABLED", &sLogBufferEnabled, NULL, 'n'}, }; static const int loc_param_num = sizeof(loc_param_table) / sizeof(loc_param_s_type); @@ -429,6 +431,7 @@ void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_ta { FILE *conf_fp = NULL; + log_buffer_init(false); if((conf_fp = fopen(conf_file_name, "r")) != NULL) { LOC_LOGD("%s: using %s", __FUNCTION__, conf_file_name); @@ -441,6 +444,7 @@ void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_ta } /* Initialize logging mechanism with parsed data */ loc_logger_init(DEBUG_LEVEL, TIMESTAMP); + log_buffer_init(sLogBufferEnabled); } /*============================================================================= diff --git a/utils/loc_log.cpp b/utils/loc_log.cpp index ab28998..2c6a3fa 100644 --- a/utils/loc_log.cpp +++ b/utils/loc_log.cpp @@ -31,11 +31,13 @@ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> #include <sys/time.h> #include "log_util.h" #include "loc_log.h" #include "msg_q.h" #include <loc_pla.h> +#include "LogBuffer.h" #define BUFFER_SIZE 120 @@ -179,35 +181,6 @@ char *loc_get_time(char *time_string, size_t buf_size) return time_string; } - -/*=========================================================================== -FUNCTION loc_logger_init - -DESCRIPTION - Initializes the state of DEBUG_LEVEL and TIMESTAMP - -DEPENDENCIES - N/A - -RETURN VALUE - None - -SIDE EFFECTS - N/A -===========================================================================*/ -void loc_logger_init(unsigned long debug, unsigned long timestamp) -{ - loc_logger.DEBUG_LEVEL = debug; -#ifdef TARGET_BUILD_VARIANT_USER - // force user builds to 2 or less - if (loc_logger.DEBUG_LEVEL > 2) { - loc_logger.DEBUG_LEVEL = 2; - } -#endif - loc_logger.TIMESTAMP = timestamp; -} - - /*=========================================================================== FUNCTION get_timestamp @@ -236,3 +209,22 @@ char * get_timestamp(char *str, unsigned long buf_size) return str; } +/*=========================================================================== + +FUNCTION log_buffer_insert + +DESCRIPTION + Insert a log sentence with specific level to the log buffer. + +RETURN VALUE + N/A + +===========================================================================*/ +void log_buffer_insert(char *str, unsigned long buf_size, int level) +{ + timespec tv; + clock_gettime(CLOCK_BOOTTIME, &tv); + uint64_t elapsedTime = (uint64_t)tv.tv_sec + (uint64_t)tv.tv_nsec/1000000000; + string ss = str; + loc_util::LogBuffer::getInstance()->append(ss, level, elapsedTime); +} diff --git a/utils/log_util.h b/utils/log_util.h index 192baeb..13c08bc 100644 --- a/utils/log_util.h +++ b/utils/log_util.h @@ -30,9 +30,13 @@ #ifndef __LOG_UTIL_H__ #define __LOG_UTIL_H__ +#include <stdbool.h> + #if defined (USE_ANDROID_LOGGING) || defined (ANDROID) // Android and LE targets with logcat support #include <utils/Log.h> +#include <unistd.h> +#include <sys/syscall.h> #elif defined (USE_GLIB) // LE targets with no logcat support @@ -41,6 +45,7 @@ #include <sys/types.h> #include <sys/time.h> #include <unistd.h> +#include <sys/syscall.h> #ifndef LOG_TAG #define LOG_TAG "GPS_UTILS" @@ -90,18 +95,20 @@ typedef struct loc_logger_s { unsigned long DEBUG_LEVEL; unsigned long TIMESTAMP; + bool LOG_BUFFER_ENABLE; } loc_logger_s_type; + /*============================================================================= * * EXTERNAL DATA * *============================================================================*/ -extern loc_logger_s_type loc_logger; // Logging Improvements extern const char *loc_logger_boolStr[]; +extern loc_logger_s_type loc_logger; extern const char *boolStr[]; extern const char VOID_RET[]; extern const char FROM_AFW[]; @@ -117,8 +124,49 @@ extern const char EXIT_ERROR_TAG[]; * MODULE EXPORTED FUNCTIONS * *============================================================================*/ -extern void loc_logger_init(unsigned long debug, unsigned long timestamp); +inline void loc_logger_init(unsigned long debug, unsigned long timestamp) +{ + loc_logger.DEBUG_LEVEL = debug; +#ifdef TARGET_BUILD_VARIANT_USER + // force user builds to 2 or less + if (loc_logger.DEBUG_LEVEL > 2) { + loc_logger.DEBUG_LEVEL = 2; + } +#endif + loc_logger.TIMESTAMP = timestamp; +} + +inline void log_buffer_init(bool enabled) { + loc_logger.LOG_BUFFER_ENABLE = enabled; +} + extern char* get_timestamp(char* str, unsigned long buf_size); +extern void log_buffer_insert(char *str, unsigned long buf_size, int level); + +/*============================================================================= + * + * LOGGING BUFFER MACROS + * + *============================================================================*/ +#ifndef LOG_NDEBUG +#define LOG_NDEBUG 0 +#endif +#define TOTAL_LOG_LEVELS 5 +#define LOGGING_BUFFER_MAX_LEN 1024 +#define IF_LOG_BUFFER_ENABLE if (loc_logger.LOG_BUFFER_ENABLE) +#define INSERT_BUFFER(flag, level, format, x...) \ +{ \ + IF_LOG_BUFFER_ENABLE { \ + if (flag == 0) { \ + char timestr[32]; \ + get_timestamp(timestr, sizeof(timestr)); \ + char log_str[LOGGING_BUFFER_MAX_LEN]; \ + snprintf(log_str, LOGGING_BUFFER_MAX_LEN, "%s %d %ld %s :" format "\n", \ + timestr, getpid(), syscall(SYS_gettid), LOG_TAG==NULL ? "": LOG_TAG, ##x);\ + log_buffer_insert(log_str, sizeof(log_str), level); \ + } \ + } \ +} #ifndef DEBUG_DMN_LOC_API @@ -133,11 +181,11 @@ extern char* get_timestamp(char* str, unsigned long buf_size); #define IF_LOC_LOGD if((loc_logger.DEBUG_LEVEL >= 4) && (loc_logger.DEBUG_LEVEL <= 5)) #define IF_LOC_LOGV if((loc_logger.DEBUG_LEVEL >= 5) && (loc_logger.DEBUG_LEVEL <= 5)) -#define LOC_LOGE(...) IF_LOC_LOGE { ALOGE(__VA_ARGS__); } -#define LOC_LOGW(...) IF_LOC_LOGW { ALOGW(__VA_ARGS__); } -#define LOC_LOGI(...) IF_LOC_LOGI { ALOGI(__VA_ARGS__); } -#define LOC_LOGD(...) IF_LOC_LOGD { ALOGD(__VA_ARGS__); } -#define LOC_LOGV(...) IF_LOC_LOGV { ALOGV(__VA_ARGS__); } +#define LOC_LOGE(...) IF_LOC_LOGE { ALOGE(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 0, __VA_ARGS__);} +#define LOC_LOGW(...) IF_LOC_LOGW { ALOGW(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 1, __VA_ARGS__);} +#define LOC_LOGI(...) IF_LOC_LOGI { ALOGI(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 2, __VA_ARGS__);} +#define LOC_LOGD(...) IF_LOC_LOGD { ALOGD(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 3, __VA_ARGS__);} +#define LOC_LOGV(...) IF_LOC_LOGV { ALOGV(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 4, __VA_ARGS__);} #else /* DEBUG_DMN_LOC_API */ diff --git a/utils/msg_q.c b/utils/msg_q.c index 2d49b4a..3383960 100644 --- a/utils/msg_q.c +++ b/utils/msg_q.c @@ -26,6 +26,8 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// Uncomment to log verbose logs +#define LOG_NDEBUG 1 #define LOG_TAG "LocSvc_utils_q" #include <stdio.h> #include <stdlib.h> |