1 /*
2 * Copyright (c) 2021-2023 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 "dfx_log.h"
17
18 #include <cstdarg>
19 #include <cstdio>
20 #include <fcntl.h>
21 #include <securec.h>
22 #include <unistd.h>
23 #include "dfx_define.h"
24
25 static int g_debugFd = INVALID_FD;
26 static LogLevel g_logLevel = LogLevel::LOG_INFO;
27
28 #ifdef DFX_LOG_DMESG
29 static int g_dmesgFd = INVALID_FD;
30
CloseDmesg()31 static void CloseDmesg()
32 {
33 if (g_dmesgFd > 0) {
34 close(g_dmesgFd);
35 g_dmesgFd = -1;
36 }
37 }
38
LogToDmesg(const LogLevel logLevel,const char * tag,const char * info)39 static void LogToDmesg(const LogLevel logLevel, const char *tag, const char *info)
40 {
41 static const char *LOG_LEVEL_STR[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" };
42 static const char *LOG_KLEVEL_STR[] = { "<7>", "<6>", "<4>", "<3>", "<3>" };
43 int dmesgLevel = static_cast<int>(logLevel) - LOG_DEBUG;
44
45 if (UNLIKELY(g_dmesgFd < 0)) {
46 g_dmesgFd = open("/dev/kmsg", O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
47 }
48 char buf[LOG_BUF_LEN] = {0};
49 #if is_ohos
50 if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%s[pid=%d %d][%s][%s]%s",
51 LOG_KLEVEL_STR[dmesgLevel], getprocpid(), getppid(), tag, LOG_LEVEL_STR[dmesgLevel], info) < 0) {
52 CloseDmesg();
53 return;
54 }
55 #else
56 if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%s[pid=%d %d][%s][%s]%s",
57 LOG_KLEVEL_STR[dmesgLevel], getpid(), getppid(), tag, LOG_LEVEL_STR[dmesgLevel], info) < 0) {
58 CloseDmesg();
59 return;
60 }
61 #endif
62
63 if (OHOS_TEMP_FAILURE_RETRY(write(g_dmesgFd, buf, strlen(buf))) < 0) {
64 CloseDmesg();
65 }
66 }
67 #endif
68
InitDebugFd(int fd)69 void InitDebugFd(int fd)
70 {
71 g_debugFd = fd;
72 }
73
CheckDebugLevel(void)74 bool CheckDebugLevel(void)
75 {
76 return LogLevel::LOG_DEBUG >= g_logLevel ? true : false;
77 }
78
SetLogLevel(const LogLevel logLevel)79 void SetLogLevel(const LogLevel logLevel)
80 {
81 g_logLevel = logLevel;
82 }
83
GetLogLevel(void)84 LogLevel GetLogLevel(void)
85 {
86 return g_logLevel;
87 }
88
DfxLogPrint(const LogLevel logLevel,const unsigned int domain,const char * tag,const char * fmt,...)89 int DfxLogPrint(const LogLevel logLevel, const unsigned int domain, const char* tag, const char *fmt, ...)
90 {
91 #ifndef DFX_LOG_UNWIND
92 if (logLevel < g_logLevel) {
93 return -1;
94 }
95 #endif
96 int ret = -1;
97 #if defined(DFX_LOG_HILOG_BASE) || defined(is_ohos_lite)
98 va_list args;
99 va_start(args, fmt);
100 ret = DfxLogPrintV(logLevel, domain, tag, fmt, args);
101 va_end(args);
102 #endif
103 return ret;
104 }
105
DfxLogPrintV(const LogLevel logLevel,const unsigned int domain,const char * tag,const char * fmt,va_list ap)106 int DfxLogPrintV(const LogLevel logLevel, const unsigned int domain, const char* tag, const char *fmt, va_list ap)
107 {
108 if ((logLevel < LogLevel::LOG_DEBUG) || (logLevel > LogLevel::LOG_FATAL)) {
109 return -1;
110 }
111
112 char buf[LOG_BUF_LEN] = {0};
113 int ret = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, fmt, ap);
114 if (ret == -1) {
115 return ret;
116 }
117 #ifdef DFX_LOG_HILOG_BASE
118 HiLogBasePrint(LOG_CORE, logLevel, domain, tag, "%{public}s", buf);
119 #else
120 HiLogPrint(LOG_CORE, logLevel, domain, tag, "%{public}s", buf);
121 #endif
122
123 #ifdef DFX_LOG_DMESG
124 LogToDmesg(logLevel, tag, buf);
125 #endif
126
127 if (g_debugFd != INVALID_FD) {
128 fprintf(stderr, "%s\n", buf);
129 }
130 return ret;
131 }