Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include <string>
12 : #include <memory>
13 : #include <climits>
14 : #include <dlfcn.h>
15 : #include "securec.h"
16 : #include "bqs_log.h"
17 : #include "bqs_feature_ctrl.h"
18 : #include "bqs_util.h"
19 :
20 : namespace bqs {
21 : constexpr const char *NPU_LOG_SO_NAME = "/runtime/lib64/libunified_dlog.so";
22 : constexpr const char *ALOG_SO_NAME = "/runtime/lib64/libascendalog.so";
23 : constexpr const uint32_t LOG_BUFFER_MAX = 1024U;
24 : void *hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_MAXID)];
25 : using CheckLogLevelFunc = int32_t (int32_t, int32_t);
26 : using DlogRecordFunc = void (int32_t, int32_t, const char *, ...);
27 : using DlogSetLevelFunc = int32_t (int32_t, int32_t, int32_t);
28 : using DlogSetAttrFunc = int32_t (LogAttr);
29 :
30 36 : HostQsLog &HostQsLog::GetInstance()
31 : {
32 : static HostQsLog instance;
33 36 : return instance;
34 : }
35 :
36 12 : void *HostQsLog::OpenLogSoOne(std::string ascendAicpuPath, const char *soName) const
37 : {
38 12 : std::string hostLogSoPath = ascendAicpuPath.append(soName);
39 12 : std::unique_ptr<char_t []> path(new (std::nothrow) char_t[PATH_MAX]);
40 12 : if (path == nullptr) {
41 0 : return nullptr;
42 : }
43 :
44 12 : auto eRet = memset_s(path.get(), PATH_MAX, 0, PATH_MAX);
45 12 : if (eRet != EOK) {
46 2 : return nullptr;
47 : }
48 :
49 10 : if (realpath(hostLogSoPath.data(), path.get()) == nullptr) {
50 4 : return nullptr;
51 : }
52 6 : void *logSoHandle = dlopen(path.get(), static_cast<int32_t>(
53 : static_cast<uint32_t>(RTLD_LAZY) | (static_cast<uint32_t>(RTLD_GLOBAL))));
54 6 : return logSoHandle;
55 12 : }
56 :
57 9 : void *HostQsLog::OpenLogSo() const
58 : {
59 9 : if (!bqs::FeatureCtrl::IsHostQs()) {
60 1 : return nullptr;
61 : }
62 8 : std::string ascendAicpuPath;
63 8 : bqs::GetEnvVal("ASCEND_AICPU_PATH", ascendAicpuPath);
64 8 : if (ascendAicpuPath.empty()) {
65 0 : return nullptr;
66 : }
67 8 : void *logSoHandle = OpenLogSoOne(ascendAicpuPath, NPU_LOG_SO_NAME);
68 8 : if (logSoHandle == nullptr) {
69 4 : logSoHandle = OpenLogSoOne(ascendAicpuPath, ALOG_SO_NAME);
70 : }
71 8 : if (logSoHandle != nullptr) {
72 4 : std::string funcName = "CheckLogLevel";
73 4 : hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_CHECKLOGLEVEL)] = dlsym(logSoHandle, funcName.c_str());
74 4 : funcName = "DlogRecord";
75 4 : hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_DLOGRECORD)] = dlsym(logSoHandle, funcName.c_str());
76 4 : funcName = "dlog_setlevel";
77 4 : hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_DLOGSETLEVEL)] = dlsym(logSoHandle, funcName.c_str());
78 4 : funcName = "DlogSetAttr";
79 4 : hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_DLOGSETATTR)] = dlsym(logSoHandle, funcName.c_str());
80 4 : }
81 8 : return logSoHandle;
82 8 : }
83 :
84 1 : void HostQsLog::LogPrintNormal(const int32_t moduleId, const int32_t level, const char *fmt, ...) const
85 : {
86 1 : if ((hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_CHECKLOGLEVEL)] != nullptr) &&
87 0 : (hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_DLOGRECORD)] != nullptr)) {
88 0 : CheckLogLevelFunc *checkLogLevel = PtrToPtr<void, CheckLogLevelFunc>(
89 : hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_CHECKLOGLEVEL)]);
90 0 : if (checkLogLevel(moduleId, level) != 1) {
91 0 : return;
92 : }
93 : char buffer[LOG_BUFFER_MAX];
94 : va_list args;
95 0 : va_start(args, fmt);
96 0 : vsnprintf_s(buffer, sizeof(buffer), LOG_BUFFER_MAX, fmt, args);
97 0 : va_end(args);
98 0 : DlogRecordFunc *dlogRecord = PtrToPtr<void, DlogRecordFunc>(
99 : hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_DLOGRECORD)]);
100 0 : dlogRecord(moduleId, level, buffer);
101 : }
102 : }
103 :
104 1 : void HostQsLog::LogPrintError(const int32_t moduleId, const char *fmt, ...) const
105 : {
106 1 : if (hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_DLOGRECORD)] != nullptr) {
107 : char buffer[LOG_BUFFER_MAX];
108 : va_list args;
109 0 : va_start(args, fmt);
110 0 : vsnprintf_s(buffer, sizeof(buffer), LOG_BUFFER_MAX, fmt, args);
111 0 : va_end(args);
112 0 : DlogRecordFunc *dlogRecord = PtrToPtr<void, DlogRecordFunc>(
113 : hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_DLOGRECORD)]);
114 0 : dlogRecord(moduleId, DLOG_ERROR, buffer);
115 : }
116 1 : }
117 :
118 1 : void HostQsLog::DlogSetLevel(const int32_t logLevel, const int32_t eventLevel) const
119 : {
120 1 : if (hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_DLOGSETLEVEL)] != nullptr) {
121 0 : DlogSetLevelFunc *dlogSetLevel = PtrToPtr<void, DlogSetLevelFunc>(
122 : hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_DLOGSETLEVEL)]);
123 0 : if (dlogSetLevel(-1, logLevel, eventLevel) != 0) {
124 0 : BQS_LOG_WARN_HOST("Set log level failed");
125 : }
126 : }
127 1 : }
128 :
129 1 : void HostQsLog::DlogSetAttr(const LogAttr logAttrInfo) const
130 : {
131 1 : if (hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_DLOGSETATTR)] != nullptr) {
132 0 : DlogSetAttrFunc *dlogSetAttr = PtrToPtr<void, DlogSetAttrFunc>(
133 : hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_DLOGSETATTR)]);
134 0 : if (dlogSetAttr(logAttrInfo) != 0) {
135 0 : BQS_LOG_WARN_HOST("Set log attr failed");
136 : }
137 : }
138 1 : }
139 :
140 2 : bool HostQsLog::CheckLogLevelHost(const int32_t moduleId, const int32_t logLevel) const
141 : {
142 2 : if (hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_CHECKLOGLEVEL)] != nullptr) {
143 1 : CheckLogLevelFunc *checkLogLevel = PtrToPtr<void, CheckLogLevelFunc>(
144 : hostQsFuncMap[static_cast<uint32_t>(QsLogFuncId::FUNC_CHECKLOGLEVEL)]);
145 1 : if (checkLogLevel(moduleId, logLevel) == 1) {
146 1 : return true;
147 : }
148 : }
149 1 : return false;
150 : }
151 :
152 7 : bool HostQsLog::CheckLogLevel(const int32_t moduleId, const int32_t logLevel) const
153 : {
154 7 : if (bqs::FeatureCtrl::IsHostQs()) {
155 3 : if (bqs::HostQsLog::GetInstance().CheckLogLevelHost(moduleId, logLevel)) {
156 2 : return true;
157 : }
158 : } else {
159 4 : if (CheckLogLevelAicpu(moduleId, logLevel)) {
160 4 : return true;
161 : }
162 : }
163 1 : return false;
164 : }
165 : }
166 :
167 : namespace {
168 : void *g_logSoHandle = nullptr;
169 : }
170 :
171 2 : static void __attribute__((constructor)) QsLogInit(void)
172 : {
173 2 : if (bqs::FeatureCtrl::IsHostQs()) {
174 0 : g_logSoHandle = bqs::HostQsLog::GetInstance().OpenLogSo();
175 : }
176 2 : }
177 :
178 2 : static void __attribute__((destructor)) QsLogUnInit(void)
179 : {
180 2 : if (g_logSoHandle != nullptr) {
181 0 : dlclose(g_logSoHandle);
182 : }
183 2 : }
|