1/* 2 * Copyright (c) 2020 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "hiview_output_log.h" 17#include "hiview_cache.h" 18#include "hiview_config.h" 19#include "hiview_def.h" 20#include "hiview_file.h" 21#include "hiview_log.h" 22#include "hiview_log_limit.h" 23#include "hiview_service.h" 24#include "hiview_util.h" 25#include "message.h" 26#include "ohos_types.h" 27#include "securec.h" 28 29#include <time.h> 30 31#define SINGLE_FMT_MAX_LEN 8 32#define FMT_CONVERT_TRMINATOR 2 33#define INI_CONVERT_DIVID_NUM 10 34 35static char g_logLevelInfo[HILOG_LV_MAX] = { 36 'N', // "NONE" 37 'D', // "DEBUG" 38 'I', // "INFO" 39 'W', // "WARN" 40 'E', // "ERROR" 41 'F' // "FATAL" 42}; 43 44#ifndef DISABLE_HILOG_CACHE 45static uint8 g_logCacheBuffer[LOG_STATIC_CACHE_SIZE]; 46#endif 47static HiviewCache g_logCache = { 48 .size = 0, 49 .buffer = NULL, 50}; 51static HiviewFile g_logFile = { 52 .path = HIVIEW_FILE_PATH_LOG, 53 .outPath = HIVIEW_FILE_OUT_PATH_LOG, 54 .pFunc = NULL, 55 .mutex = NULL, 56 .fhandle = -1, 57 .configSize = 0, 58}; 59 60typedef struct LogFlushInfo LogFlushInfo; 61struct LogFlushInfo { 62 HiviewMutexId_t mutex; 63}; 64static LogFlushInfo g_logFlushInfo; 65static HilogProc g_hilogOutputProc = NULL; 66 67typedef struct OutputLogInfo OutputLogInfo; 68struct OutputLogInfo { 69 HiviewMutexId_t mutex; 70}; 71static OutputLogInfo g_outputLogInfo; 72 73static int32 g_retryInitCount = 0; 74#define MAX_RETRY_COUNT 100 75 76/* Output the log to UART using plaintext. */ 77static void OutputLogRealtime(const Request *req); 78/* Output the log to FLASH using text. */ 79static void OutputLog2TextFile(const Request *req); 80/* Output the log to FLASH using binary. */ 81static void OutputLog2BinFile(const Request *req); 82static int32 LogCommonFmt(char *outStr, int32 outStrlen, const HiLogCommon *commonContentPtr); 83static int32 LogValuesFmt(char *desStrPtr, int32 desLen, const HiLogContent *logContentPtr); 84static int32 LogDebugValuesFmt(char *desStrPtr, int32 desLen, const HiLogContent *logContentPtr); 85static int32 LogValuesFmtHash(char *desStrPtr, int32 desLen, const HiLogContent *logContentPtr); 86 87void InitCoreLogOutput(void) 88{ 89 g_logFlushInfo.mutex = HIVIEW_MutexInit(); 90 g_outputLogInfo.mutex = HIVIEW_MutexInit(); 91#ifndef DISABLE_HILOG_CACHE 92 InitHiviewStaticCache(&g_logCache, LOG_CACHE, g_logCacheBuffer, sizeof(g_logCacheBuffer)); 93#endif 94 HiviewRegisterMsgHandle(HIVIEW_MSG_OUTPUT_LOG_TEXT_FILE, OutputLog2TextFile); 95 HiviewRegisterMsgHandle(HIVIEW_MSG_OUTPUT_LOG_BIN_FILE, OutputLog2BinFile); 96 HiviewRegisterMsgHandle(HIVIEW_MSG_OUTPUT_LOG_FLOW, OutputLogRealtime); 97} 98 99void InitLogOutput(void) 100{ 101 int8 opt = GETOPTION(g_hiviewConfig.outputOption); 102 if (opt == OUTPUT_OPTION_DEBUG || opt == OUTPUT_OPTION_FLOW) { 103 return; 104 } 105 HiviewFileType type = HIVIEW_LOG_TEXT_FILE; 106 if (opt == OUTPUT_OPTION_BIN_FILE) { 107 type = HIVIEW_LOG_BIN_FILE; 108 } 109 if (InitHiviewFile(&g_logFile, type, 110 (HIVIEW_LOG_FILE_SIZE / sizeof(HiLogContent)) * sizeof(HiLogContent)) == FALSE) { 111 HIVIEW_UartPrint("Open file[HIVIEW_LOG_BIN_FILE] failed."); 112 } 113 g_logFile.mutex = g_outputLogInfo.mutex; 114} 115 116void ClearLogOutput(void) 117{ 118 int8 opt = GETOPTION(g_hiviewConfig.outputOption); 119 if (g_logCache.usedSize > 0) { 120 if (opt == OUTPUT_OPTION_TEXT_FILE) { 121 OutputLog2TextFile(NULL); 122 } else if (opt == OUTPUT_OPTION_BIN_FILE) { 123 OutputLog2BinFile(NULL); 124 } 125 } 126 CloseHiviewFile(&g_logFile); 127} 128 129void OutputLog(const uint8 *data, uint32 len) 130{ 131 if (data == NULL) { 132 return; 133 } 134 135 HiLogContent *hiLogContent = (HiLogContent *)data; 136 if (g_hilogOutputProc != NULL) { 137 if (g_hilogOutputProc(hiLogContent, len) == TRUE) { 138 return; 139 } 140 } 141 142#ifdef DISABLE_HILOG_CACHE 143 boolean isDisableCache = TRUE; 144#else 145 boolean isDisableCache = FALSE; 146#endif 147 148#ifdef DISABLE_HILOG_LITE_PRINT_LIMIT 149 boolean isDisablePrintLimited = TRUE; 150#else 151 boolean isDisablePrintLimited = FALSE; 152#endif 153 boolean isLogLimited = LogIsLimited(hiLogContent->commonContent.module); 154 if (!isDisablePrintLimited && isLogLimited) { 155 // The console output adopts the same restriction strategy as the file output, 156 // and the log output to the file is restricted. 157 return; 158 } 159 160 int8 opt = GETOPTION(g_hiviewConfig.outputOption); 161 boolean isPrint = g_hiviewConfig.outputOption >= OUTPUT_OPTION_PRINT; 162 if (opt == OUTPUT_OPTION_DEBUG || isPrint || isDisableCache) { 163 char tempOutStr[LOG_FMT_MAX_LEN] = {0}; 164 if (LogContentFmt(tempOutStr, sizeof(tempOutStr), data) > 0) { 165 HIVIEW_UartPrint(tempOutStr); 166 } 167 } 168 169 if (opt == OUTPUT_OPTION_DEBUG || isDisableCache || isLogLimited) { 170 return; 171 } 172 173 /* When the init of kernel is not finished, data is cached in the cache. */ 174 if (g_hiviewConfig.hiviewInited == FALSE) { 175 if (WriteToCache(&g_logCache, data, len) != (int32)len) { 176 HIVIEW_UartPrint("Write log to cache failed."); 177 } 178 return; 179 } 180 181 boolean writeFail = FALSE; 182 if (WriteToCache(&g_logCache, (uint8 *)data, len) != (int32)len) { 183 HIVIEW_UartPrint("Hilog writeToCache error!\n"); 184 writeFail = TRUE; 185 } 186 if (g_logCache.usedSize >= HIVIEW_HILOG_FILE_BUF_SIZE) { 187 switch (opt) { 188 case OUTPUT_OPTION_TEXT_FILE: 189 HiviewSendMessage(HIVIEW_SERVICE, HIVIEW_MSG_OUTPUT_LOG_TEXT_FILE, 0); 190 break; 191 case OUTPUT_OPTION_BIN_FILE: 192 HiviewSendMessage(HIVIEW_SERVICE, HIVIEW_MSG_OUTPUT_LOG_BIN_FILE, 0); 193 break; 194 case OUTPUT_OPTION_FLOW: 195 HiviewSendMessage(HIVIEW_SERVICE, HIVIEW_MSG_OUTPUT_LOG_FLOW, 0); 196 break; 197 default: 198 break; 199 } 200 } 201 202 /* If the cache fails to be written, write the cache again. */ 203 if (writeFail) { 204 WriteToCache(&g_logCache, (uint8 *)data, len); 205 } 206} 207 208static void OutputLogRealtime(const Request *req) 209{ 210 HIVIEW_MutexLock(g_logFlushInfo.mutex); 211 HiLogContent logContent; 212 char tempOutStr[LOG_FMT_MAX_LEN] = {0}; 213 int32 len; 214 (void)req; 215 216 while (ReadFromCache(&g_logCache, (uint8 *)&(logContent.commonContent), 217 sizeof(HiLogCommon)) == sizeof(HiLogCommon)) { 218 if (logContent.commonContent.head != LOG_INFO_HEAD) { 219 DiscardCacheData(&g_logCache); 220 HIVIEW_UartPrint("Discard cache[LOG_CACHE] data."); 221 break; 222 } 223 len = logContent.commonContent.valueNumber * sizeof(uint32); 224 if (len > 0 && ReadFromCache(&g_logCache, (uint8 *)&(logContent.values), len) != len) { 225 continue; 226 } 227 len = LogContentFmt(tempOutStr, sizeof(tempOutStr), (uint8 *)&logContent); 228 if (len <= 0) { 229 continue; 230 } 231 HIVIEW_UartPrint(tempOutStr); 232 } 233 HIVIEW_MutexUnlock(g_logFlushInfo.mutex); 234} 235 236static void OutputLog2TextFile(const Request *req) 237{ 238 HIVIEW_MutexLock(g_logFlushInfo.mutex); 239 HiLogContent logContent; 240 char tempOutStr[LOG_FMT_MAX_LEN] = {0}; 241 242 if (g_logCache.usedSize < sizeof(HiLogCommon)) { 243 HIVIEW_MutexUnlock(g_logFlushInfo.mutex); 244 return; 245 } 246 247 int32 len; 248 while (ReadFromCache(&g_logCache, (uint8 *)&(logContent.commonContent), 249 sizeof(HiLogCommon)) == sizeof(HiLogCommon)) { 250 if (logContent.commonContent.head != LOG_INFO_HEAD) { 251 DiscardCacheData(&g_logCache); 252 HIVIEW_UartPrint("Discard cache[LOG_CACHE] data."); 253 break; 254 } 255 len = logContent.commonContent.valueNumber * sizeof(uint32); 256 if (len > 0 && ReadFromCache(&g_logCache, (uint8 *)&(logContent.values), len) != len) { 257 continue; 258 } 259 len = LogContentFmt(tempOutStr, sizeof(tempOutStr), (uint8 *)&logContent); 260 if (len > 0 && tempOutStr[len - 1] == '\0') { 261 // prevent writing '\0' character to file 262 len--; 263 } 264 if (g_logFile.fhandle < 0) { 265 if (g_retryInitCount < MAX_RETRY_COUNT) { 266 InitLogOutput(); 267 } 268 g_retryInitCount++; 269 } else { 270 // once success, clean retry count 271 g_retryInitCount = 0; 272 } 273 if (len > 0 && WriteToFile(&g_logFile, (uint8 *)tempOutStr, len) != len) { 274 g_hiviewConfig.writeFailureCount++; 275 } 276 } 277 HIVIEW_MutexUnlock(g_logFlushInfo.mutex); 278 if (req != NULL && req->msgValue == SYNC_FILE) { 279 HIVIEW_FileSync(g_logFile.fhandle); 280 } 281} 282 283static void OutputLog2BinFile(const Request *req) 284{ 285 HIVIEW_MutexLock(g_logFlushInfo.mutex); 286 HiLogCommon *pCommonContent = NULL; 287 uint16 len = 0; 288 uint16 valueLen; 289 uint8 *tmpBuffer = NULL; 290 uint16 outputSize = g_logCache.usedSize; 291 292 if (outputSize < sizeof(HiLogCommon)) { 293 HIVIEW_MutexUnlock(g_logFlushInfo.mutex); 294 return; 295 } 296 tmpBuffer = (uint8 *)HIVIEW_MemAlloc(MEM_POOL_HIVIEW_ID, outputSize); 297 if (tmpBuffer == NULL) { 298 HIVIEW_MutexUnlock(g_logFlushInfo.mutex); 299 return; 300 } 301 while (g_logCache.usedSize >= sizeof(HiLogCommon) && outputSize > (len + sizeof(HiLogCommon))) { 302 if (ReadFromCache(&g_logCache, tmpBuffer + len, sizeof(HiLogCommon)) != sizeof(HiLogCommon)) { 303 continue; 304 } 305 pCommonContent = (HiLogCommon *)(tmpBuffer + len); 306 len += sizeof(HiLogCommon); 307 if (pCommonContent->head != LOG_INFO_HEAD) { 308 DiscardCacheData(&g_logCache); 309 HIVIEW_UartPrint("Discard cache[LOG_CACHE] data."); 310 break; 311 } 312 valueLen = pCommonContent->valueNumber * sizeof(uint32); 313 if (valueLen > 0) { 314 if ((int32)len + (int32)valueLen > (int32)outputSize) { 315 DiscardCacheData(&g_logCache); 316 HIVIEW_UartPrint("Discard cache[LOG_CACHE] data."); 317 break; 318 } 319 if (ReadFromCache(&g_logCache, tmpBuffer + len, valueLen) != valueLen) { 320 continue; 321 } 322 len += valueLen; 323 } 324 } 325 if (g_logFile.fhandle < 0) { 326 if (g_retryInitCount < MAX_RETRY_COUNT) { 327 InitLogOutput(); 328 } 329 g_retryInitCount++; 330 } else { 331 // once success, clean retry count 332 g_retryInitCount = 0; 333 } 334 if (len > 0 && WriteToFile(&g_logFile, tmpBuffer, len) != len) { 335 g_hiviewConfig.writeFailureCount++; 336 HIVIEW_UartPrint("Failed to write log data."); 337 } 338 HIVIEW_MemFree(MEM_POOL_HIVIEW_ID, tmpBuffer); 339 HIVIEW_MutexUnlock(g_logFlushInfo.mutex); 340 if (req != NULL && req->msgValue == SYNC_FILE) { 341 HIVIEW_FileSync(g_logFile.fhandle); 342 } 343} 344 345uint32 GetLogFileSize(void) 346{ 347 return GetFileUsedSize(&g_logFile); 348} 349 350uint32 ReadLogFile(uint8 *buf, uint32 len) 351{ 352 if (buf == NULL) { 353 return 0; 354 } 355 uint32 usedSize = GetFileUsedSize(&g_logFile); 356 if (usedSize < len) { 357 len = usedSize; 358 } 359 if (ReadFromFile(&g_logFile, buf, len) != (int32)len) { 360 return 0; 361 } 362 363 return len; 364} 365 366int32 LogContentFmt(char *outStr, int32 outStrLen, const uint8 *pLogContent) 367{ 368 int32 len; 369 HiLogContent *logContentPtr = (HiLogContent *)pLogContent; 370 371 len = LogCommonFmt(outStr, outStrLen, &(logContentPtr->commonContent)); 372 boolean isHash = CHECK_HASH_FLAG(logContentPtr->commonContent.level); 373 if (len >= 0) { 374 if (isHash) { 375 len += LogValuesFmtHash(outStr + len, outStrLen - len, logContentPtr); 376 } else if (GETOPTION(g_hiviewConfig.outputOption) == OUTPUT_OPTION_DEBUG) { 377 len += LogDebugValuesFmt(outStr + len, outStrLen - len, logContentPtr); 378 } else { 379 len += LogValuesFmt(outStr + len, outStrLen - len, logContentPtr); 380 } 381 } 382 383 if (len < 0) { 384 return len; 385 } 386 387 if (len >= outStrLen - 1) { 388 outStr[outStrLen - TAIL_LINE_BREAK] = '\n'; 389 outStr[outStrLen - 1] = '\0'; 390 } else { 391 outStr[len++] = '\n'; 392 outStr[len++] = '\0'; 393 } 394 395 return len; 396} 397 398static int32 LogCommonFmt(char *outStr, int32 outStrLen, const HiLogCommon *commonContentPtr) 399{ 400 int32 ret; 401 time_t time; 402 uint32 month, day, hour, min, sec; 403 uint8_t level; 404 struct tm nowTime = {0}; 405 406 time = commonContentPtr->time; 407 localtime_r(&time, &nowTime); 408 month = nowTime.tm_mon + 1; 409 day = nowTime.tm_mday; 410 hour = nowTime.tm_hour; 411 min = nowTime.tm_min; 412 sec = nowTime.tm_sec; 413 level = CLEAR_HASH_FLAG(commonContentPtr->level); 414 if (level >= HILOG_LV_MAX) { 415 level = 0; 416 } 417 ret = snprintf_s(outStr, outStrLen, outStrLen - 1, "%02d-%02d %02d:%02d:%02d.%03d 0 %d %c %d/%s: ", 418 month, day, hour, min, sec, commonContentPtr->milli, commonContentPtr->task, g_logLevelInfo[level], 419 commonContentPtr->module, HiLogGetModuleName(commonContentPtr->module)); 420 421 return ret; 422} 423 424static int32 LogValuesFmt(char *desStrPtr, int32 desLen, const HiLogContent *logContentPtr) 425{ 426 int32 i; 427 int32 outLen = 0; 428 int32 len; 429 char fmtStr[SINGLE_FMT_MAX_LEN]; 430 uint32 valNum = logContentPtr->commonContent.valueNumber; 431 const char *fmt = logContentPtr->commonContent.fmt; 432 uint32 valueIndex = 0; 433 for (i = 0; fmt[i] != 0 && outLen < desLen;) { 434 if (fmt[i] != '%') { 435 desStrPtr[outLen++] = fmt[i++]; 436 continue; 437 } 438 if (fmt[i + 1] == '%') { 439 desStrPtr[outLen++] = fmt[i++]; 440 desStrPtr[outLen++] = fmt[i++]; 441 continue; 442 } 443 fmtStr[0] = fmt[i++]; 444 uint32 t = 1; 445 while (fmt[i] != 0 && t < sizeof(fmtStr) - 1) { 446 /* %s %ms %-ms %m.ns %-m.ns convert to %p */ 447 if ((fmt[i] == 's' || fmt[i] == 'S') && 448 (fmt[i - 1] == '%' || (fmt[i - 1] >= '0' && fmt[i - 1] <= '9'))) { 449 fmtStr[1] = 'p'; 450 fmtStr[FMT_CONVERT_TRMINATOR] = 0; 451 i++; 452 break; 453 } 454 if ((fmt[i] >= 'a' && fmt[i] <= 'z') || (fmt[i] >= 'A' && fmt[i] <= 'Z')) { 455 fmtStr[t++] = fmt[i++]; 456 fmtStr[t] = 0; 457 break; 458 } 459 fmtStr[t++] = fmt[i++]; 460 } 461 if (valueIndex < valNum) { 462 len = snprintf_s(&desStrPtr[outLen], desLen - outLen, desLen - outLen - 1, 463 fmtStr, logContentPtr->values[valueIndex]); 464 if (len < 0) { 465 break; 466 } 467 outLen += len; 468 valueIndex++; 469 } 470 } 471 472 return outLen; 473} 474 475static void RemovePrivacyFmt(const char* fmtStr, size_t fmtLen, char* arr, size_t arrLen) 476{ 477 static const char *publicStr = "{public}"; 478 static const char *privateStr = "{private}"; 479 static const int publicLen = 8; 480 static const int privateLen = 9; 481 size_t writePos = 0; 482 size_t pos = 0; 483 for (; pos < fmtLen; ++pos) { 484 arr[writePos++] = fmtStr[pos]; 485 if (fmtStr[pos] != '%') { 486 continue; 487 } 488 if (pos + 1 + publicLen < fmtLen && strncmp(fmtStr + pos + 1, publicStr, publicLen) == 0) { 489 pos += publicLen; 490 } else if (pos + 1 + privateLen < fmtLen && strncmp(fmtStr + pos + 1, privateStr, privateLen) == 0) { 491 pos += privateLen; 492 } 493 } 494 while (pos < fmtLen) { 495 arr[writePos++] = fmtStr[pos]; 496 } 497 arr[writePos] = 0; 498 return; 499} 500 501static int32 LogDebugValuesFmt(char *desStrPtr, int32 desLen, const HiLogContent *logContentPtr) 502{ 503 int32 ret = 0; 504 size_t fmtLen = strlen(logContentPtr->commonContent.fmt); 505 char *fmt = (char *)malloc((fmtLen + 1) * sizeof(char)); // 1: for '\0' 506 if (fmt == NULL) { 507 return -1; 508 } 509 memset_s(fmt, fmtLen + 1, 0, fmtLen + 1); 510 RemovePrivacyFmt(logContentPtr->commonContent.fmt, fmtLen, fmt, fmtLen); 511 switch (logContentPtr->commonContent.valueNumber) { 512 case LOG_MULTI_PARA_0: 513 ret = strncpy_s(desStrPtr, desLen, fmt, desLen - 1); 514 if (ret != EOK) { 515 ret = -1; 516 } else { 517 ret = strlen(fmt); 518 } 519 break; 520 case LOG_MULTI_PARA_1: 521 ret = snprintf_s(desStrPtr, desLen, desLen - 1, fmt, 522 logContentPtr->values[0]); 523 break; 524 case LOG_MULTI_PARA_2: 525 ret = snprintf_s(desStrPtr, desLen, desLen - 1, fmt, 526 logContentPtr->values[0], logContentPtr->values[1]); 527 break; 528 case LOG_MULTI_PARA_3: 529 ret = snprintf_s(desStrPtr, desLen, desLen - 1, fmt, 530 logContentPtr->values[0], logContentPtr->values[1], logContentPtr->values[LOG_MULTI_PARA_2]); 531 break; 532 case LOG_MULTI_PARA_4: 533 ret = snprintf_s(desStrPtr, desLen, desLen - 1, fmt, 534 logContentPtr->values[0], logContentPtr->values[1], logContentPtr->values[LOG_MULTI_PARA_2], 535 logContentPtr->values[LOG_MULTI_PARA_3]); 536 break; 537 case LOG_MULTI_PARA_5: 538 ret = snprintf_s(desStrPtr, desLen, desLen - 1, fmt, 539 logContentPtr->values[0], logContentPtr->values[1], logContentPtr->values[LOG_MULTI_PARA_2], 540 logContentPtr->values[LOG_MULTI_PARA_3], logContentPtr->values[LOG_MULTI_PARA_4]); 541 break; 542 case LOG_MULTI_PARA_MAX: 543 ret = snprintf_s(desStrPtr, desLen, desLen - 1, fmt, 544 logContentPtr->values[0], logContentPtr->values[1], logContentPtr->values[LOG_MULTI_PARA_2], 545 logContentPtr->values[LOG_MULTI_PARA_3], logContentPtr->values[LOG_MULTI_PARA_4], 546 logContentPtr->values[LOG_MULTI_PARA_5]); 547 break; 548 default: 549 break; 550 } 551 free(fmt); 552 return (ret < 0) ? (desLen - 1) : ret; 553} 554 555static int32 IntAppendStr(char* str, int32 num, char end) 556{ 557 int32 digits = 0; 558 if (num == 0) { 559 str[0] = '0'; 560 digits++; 561 str[1] = end; 562 return digits + 1; 563 } 564 int32 temp = num > 0 ? num : -num; 565 while (temp > 0) { 566 temp /= INI_CONVERT_DIVID_NUM; 567 digits++; 568 } 569 if (num < 0) { 570 str[0] = '-'; 571 temp = -num; 572 str++; 573 } else { 574 temp = num; 575 } 576 for (int32 i = digits - 1; i >= 0; i--) { 577 str[i] = temp % INI_CONVERT_DIVID_NUM + '0'; 578 temp /= INI_CONVERT_DIVID_NUM; 579 } 580 str[digits] = end; 581 if (num < 0) { 582 digits ++; 583 } 584 return digits + 1; 585} 586 587static int UIntAppendStr(char* str, uint32 num, char end) 588{ 589 int32 digits = 0; 590 if (num == 0) { 591 str[0] = '0'; 592 digits++; 593 str[1] = end; 594 return digits + 1; 595 } 596 uint32 temp = num; 597 while (temp > 0) { 598 temp /= INI_CONVERT_DIVID_NUM; 599 digits++; 600 } 601 temp = num; 602 for (int32 i = digits - 1; i >= 0; i--) { 603 str[i] = temp % INI_CONVERT_DIVID_NUM + '0'; 604 temp /= INI_CONVERT_DIVID_NUM; 605 } 606 str[digits] = end; 607 return digits + 1; 608} 609 610static int32 LogValuesFmtHash(char *desStrPtr, int32 desLen, const HiLogContent *logContentPtr) 611{ 612 int32 outLen = 0; 613 uint32 paraNum = logContentPtr->commonContent.valueNumber; 614 int32 ret = strncpy_s(&desStrPtr[outLen], desLen - outLen, "hash:", strlen("hash:")); 615 if (ret != 0) { 616 return -ret; 617 } 618 outLen += strlen("hash:"); 619 int32 len = UIntAppendStr(&desStrPtr[outLen], (uint32)logContentPtr->commonContent.fmt, ' '); 620 outLen += len; 621 ret = strncpy_s(&desStrPtr[outLen], desLen - outLen, "para:", strlen("para:")); 622 if (ret != 0) { 623 return -ret; 624 } 625 outLen += strlen("para:"); 626 for (uint32 i = 0; i < paraNum && i < LOG_MULTI_PARA_MAX; i++) { 627 len = IntAppendStr(&desStrPtr[outLen], (int32)logContentPtr->values[i], ' '); 628 outLen += len; 629 } 630 return outLen; 631} 632 633void FlushLog(boolean syncFlag) 634{ 635 int8 opt = GETOPTION(g_hiviewConfig.outputOption); 636 if (g_logCache.usedSize > 0) { 637 if (syncFlag == FALSE) { 638 switch (opt) { 639 case OUTPUT_OPTION_TEXT_FILE: 640 HiviewSendMessage(HIVIEW_SERVICE, HIVIEW_MSG_OUTPUT_LOG_TEXT_FILE, SYNC_FILE); 641 break; 642 case OUTPUT_OPTION_BIN_FILE: 643 HiviewSendMessage(HIVIEW_SERVICE, HIVIEW_MSG_OUTPUT_LOG_BIN_FILE, SYNC_FILE); 644 break; 645 case OUTPUT_OPTION_FLOW: 646 HiviewSendMessage(HIVIEW_SERVICE, HIVIEW_MSG_OUTPUT_LOG_FLOW, SYNC_FILE); 647 break; 648 default: 649 break; 650 } 651 } else { 652 Request request = {0}; 653 request.msgValue = SYNC_FILE; 654 switch (opt) { 655 case OUTPUT_OPTION_TEXT_FILE: 656 OutputLog2TextFile(&request); 657 break; 658 case OUTPUT_OPTION_BIN_FILE: 659 OutputLog2BinFile(&request); 660 break; 661 case OUTPUT_OPTION_FLOW: 662 OutputLogRealtime(NULL); 663 break; 664 default: 665 break; 666 } 667 } 668 } 669} 670 671void HiviewRegisterHilogProc(HilogProc func) 672{ 673 g_hilogOutputProc = func; 674} 675 676uint32 HiviewGetConfigOption(void) 677{ 678 return GETOPTION(g_hiviewConfig.outputOption); 679} 680 681void HiviewUnRegisterHilogProc(HilogProc func) 682{ 683 (void)func; 684 if (g_hilogOutputProc != NULL) { 685 g_hilogOutputProc = NULL; 686 } 687} 688 689void HiviewRegisterHiLogFileWatcher(FileProc func, const char *path) 690{ 691 if (func == NULL) { 692 return; 693 } 694 RegisterFileWatcher(&g_logFile, func, path); 695} 696 697void HiviewUnRegisterHiLogFileWatcher(FileProc func) 698{ 699 if (func == NULL) { 700 return; 701 } 702 UnRegisterFileWatcher(&g_logFile, func); 703} 704 705int HiLogFileProcImp(const char* dest, uint8 mode) 706{ 707 FlushLog(TRUE); 708 HIVIEW_MutexLock(g_logFlushInfo.mutex); 709 int ret = ProcFile(&g_logFile, dest, (FileProcMode)mode); 710 HIVIEW_MutexUnlock(g_logFlushInfo.mutex); 711 return ret; 712} 713 714void HiLogOutputFileLockImp(void) 715{ 716 HIVIEW_MutexLock(g_outputLogInfo.mutex); 717} 718 719void HiLogOutputFileUnLockImp(void) 720{ 721 HIVIEW_MutexUnlock(g_outputLogInfo.mutex); 722} 723