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 <fstream>
12 : #include <iostream>
13 : #include <mutex>
14 : #include <nlohmann/json.hpp>
15 : #include <sstream>
16 : #include <exception>
17 : #include <securec.h>
18 : #include "mmpa/mmpa_api.h"
19 : #include "dlog_pub.h"
20 : #include "base/err_msg.h"
21 : #include "base/err_mgr.h"
22 : #include "error_manager.h"
23 :
24 : #define GE_MODULE_NAME static_cast<int32_t>(GE)
25 :
26 : template <typename TI, typename TO>
27 97 : inline TO* PtrToPtr(TI* const ptr)
28 : {
29 97 : return reinterpret_cast<TO*>(ptr);
30 : }
31 :
32 : template <typename TI, typename TO>
33 377 : inline const TO* PtrToPtr(const TI* const ptr)
34 : {
35 377 : return reinterpret_cast<const TO*>(ptr);
36 : }
37 :
38 : namespace {
39 : const std::string kParamCheckErrorSuffix = "8888";
40 : class GeLog {
41 : public:
42 26 : static uint64_t GetTid()
43 : {
44 : #ifdef __GNUC__
45 26 : thread_local static const uint64_t tid = static_cast<uint64_t>(syscall(__NR_gettid));
46 : #else
47 : thread_local static const uint64_t tid = static_cast<uint64_t>(GetCurrentThreadId());
48 : #endif
49 26 : return tid;
50 : }
51 : };
52 :
53 28452 : inline bool IsLogEnable(const int32_t module_name, const int32_t log_level)
54 : {
55 28452 : const int32_t enable = CheckLogLevel(module_name, log_level);
56 : // 1:enable, 0:disable
57 28452 : return (enable == 1);
58 : }
59 :
60 391 : std::string CurrentTimeFormatStr()
61 : {
62 391 : std::string time_str;
63 391 : auto now = std::chrono::system_clock::now();
64 391 : auto milli_seconds = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
65 391 : auto micro_seconds = std::chrono::time_point_cast<std::chrono::microseconds>(now);
66 391 : const auto now_t = std::chrono::system_clock::to_time_t(now);
67 391 : const std::tm* tm_now = std::localtime(&now_t);
68 391 : if (tm_now == nullptr) {
69 0 : return time_str;
70 : }
71 :
72 391 : constexpr int32_t year_base = 1900;
73 391 : constexpr size_t kMaxTimeLen = 128U;
74 391 : constexpr int64_t kOneThousandMs = 1000L;
75 391 : error_message::char_t format_time[kMaxTimeLen] = {};
76 782 : (void)snprintf_s(
77 : format_time, kMaxTimeLen, kMaxTimeLen - 1U, "%04d-%02d-%02d-%02d:%02d:%02d.%03ld.%03ld",
78 391 : tm_now->tm_year + year_base, tm_now->tm_mon + 1, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min,
79 391 : tm_now->tm_sec, milli_seconds.time_since_epoch().count() % kOneThousandMs,
80 391 : micro_seconds.time_since_epoch().count() % kOneThousandMs);
81 391 : time_str = format_time;
82 391 : return time_str;
83 0 : }
84 : } // namespace
85 :
86 : #define GELOGE(fmt, ...) \
87 : do { \
88 : dlog_error( \
89 : GE_MODULE_NAME, "%" PRIu64 " %s: %s" fmt, GeLog::GetTid(), &__FUNCTION__[0], \
90 : ErrorManager::GetInstance().GetLogHeader().c_str(), ##__VA_ARGS__); \
91 : } while (false)
92 :
93 : #define GELOGW(fmt, ...) \
94 : do { \
95 : if (IsLogEnable(GE_MODULE_NAME, DLOG_WARN)) { \
96 : dlog_warn(GE_MODULE_NAME, "%" PRIu64 " %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \
97 : } \
98 : } while (false)
99 :
100 : #define GELOGI(fmt, ...) \
101 : do { \
102 : if (IsLogEnable(GE_MODULE_NAME, DLOG_INFO)) { \
103 : dlog_info(GE_MODULE_NAME, "%" PRIu64 " %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \
104 : } \
105 : } while (false)
106 :
107 : #define GELOGD(fmt, ...) \
108 : do { \
109 : if (IsLogEnable(GE_MODULE_NAME, DLOG_DEBUG)) { \
110 : dlog_debug(GE_MODULE_NAME, "%" PRIu64 " %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \
111 : } \
112 : } while (false)
113 :
114 : namespace {
115 8 : int32_t ReportInnerErrorMessage(
116 : const char* file_name, const char* func, uint32_t line, const char* error_code, const char* format,
117 : va_list arg_list)
118 : {
119 8 : std::vector<char> buf(LIMIT_PER_MESSAGE, '\0');
120 8 : auto ret = vsprintf_s(buf.data(), LIMIT_PER_MESSAGE, format, arg_list);
121 8 : if (ret < 0) {
122 3 : GELOGE("[Check][Param] FormatErrorMessage failed, ret:%d, file:%s, line:%u", ret, file_name, line);
123 3 : return -1;
124 : }
125 5 : ret = sprintf_s(
126 5 : buf.data() + ret, LIMIT_PER_MESSAGE - static_cast<size_t>(ret), "[FUNC:%s][FILE:%s][LINE:%u]", func,
127 10 : error_message::TrimPath(std::string(file_name)).c_str(), line);
128 5 : if (ret < 0) {
129 1 : GELOGE("[Check][Param] FormatErrorMessage failed, ret:%d, file:%s, line:%u", ret, file_name, line);
130 1 : return -1;
131 : }
132 :
133 20 : return ErrorManager::GetInstance().ReportInterErrMessage(error_code, std::string(buf.data()));
134 8 : }
135 :
136 44 : std::unique_ptr<error_message::char_t[]> CreateUniquePtrFromString(const std::string& str)
137 : {
138 44 : const size_t buf_size = str.empty() ? 1U : (str.size() + 1U);
139 44 : auto uni_ptr = std::make_unique<error_message::char_t[]>(buf_size);
140 44 : if (uni_ptr == nullptr) {
141 0 : return nullptr;
142 : }
143 :
144 44 : if (str.empty()) {
145 11 : uni_ptr[0U] = '\0';
146 : } else {
147 : // 当src size < dst size时,strncpy_s会在末尾str.size()位置添加'\0'
148 33 : if (strncpy_s(uni_ptr.get(), str.size() + 1, str.c_str(), str.size()) != EOK) {
149 0 : return nullptr;
150 : }
151 : }
152 44 : return uni_ptr;
153 44 : }
154 :
155 66 : void ClearMessageContainerByWorkId(
156 : std::map<uint64_t, std::vector<ErrorManager::ErrorItem>>& message_container, const uint64_t work_stream_id)
157 : {
158 : const std::map<uint64_t, std::vector<ErrorManager::ErrorItem>>::const_iterator err_iter =
159 66 : message_container.find(work_stream_id);
160 66 : if (err_iter != message_container.cend()) {
161 45 : (void)message_container.erase(err_iter);
162 : }
163 66 : }
164 :
165 739 : std::vector<ErrorManager::ErrorItem>& GetOrCreateMessageContainerByWorkId(
166 : std::map<uint64_t, std::vector<ErrorManager::ErrorItem>>& message_container, uint64_t work_id)
167 : {
168 739 : auto iter = message_container.find(work_id);
169 739 : if (iter == message_container.end()) {
170 62 : (void)message_container.emplace(work_id, std::vector<ErrorManager::ErrorItem>());
171 62 : iter = message_container.find(work_id);
172 : }
173 1478 : return iter->second;
174 : }
175 : } // namespace
176 :
177 : namespace error_message {
178 : // first stage
179 : const std::string kInitialize = "INIT";
180 : const std::string kModelCompile = "COMP";
181 : const std::string kModelLoad = "LOAD";
182 : const std::string kModelExecute = "EXEC";
183 : const std::string kFinalize = "FINAL";
184 :
185 : // SecondStage
186 : // INITIALIZE
187 : const std::string kParser = "PARSER";
188 : const std::string kOpsProtoInit = "OPS_PRO";
189 : const std::string kSystemInit = "SYS";
190 : const std::string kEngineInit = "ENGINE";
191 : const std::string kOpsKernelInit = "OPS_KER";
192 : const std::string kOpsKernelBuilderInit = "OPS_KER_BLD";
193 : // MODEL_COMPILE
194 : const std::string kPrepareOptimize = "PRE_OPT";
195 : const std::string kOriginOptimize = "ORI_OPT";
196 : const std::string kSubGraphOptimize = "SUB_OPT";
197 : const std::string kMergeGraphOptimize = "MERGE_OPT";
198 : const std::string kPreBuild = "PRE_BLD";
199 : const std::string kStreamAlloc = "STM_ALLOC";
200 : const std::string kMemoryAlloc = "MEM_ALLOC";
201 : const std::string kTaskGenerate = "TASK_GEN";
202 : // COMMON
203 : const std::string kOther = "DEFAULT";
204 :
205 : #ifdef __GNUC__
206 6 : std::string TrimPath(const std::string& str)
207 : {
208 6 : if (str.find_last_of('/') != std::string::npos) {
209 0 : return str.substr(str.find_last_of('/') + 1U);
210 : }
211 6 : return str;
212 : }
213 : #else
214 : std::string TrimPath(const std::string& str)
215 : {
216 : if (str.find_last_of('\\') != std::string::npos) {
217 : return str.substr(str.find_last_of('\\') + 1U);
218 : }
219 : return str;
220 : }
221 : #endif
222 :
223 1 : int32_t FormatErrorMessage(char_t* str_dst, size_t dst_max, const char_t* format, ...)
224 : {
225 : int32_t ret;
226 : va_list arg_list;
227 :
228 1 : va_start(arg_list, format);
229 1 : ret = vsprintf_s(str_dst, dst_max, format, arg_list);
230 : (void)arg_list;
231 1 : va_end(arg_list);
232 1 : if (ret < 0) {
233 0 : GELOGE("[Check][Param] FormatErrorMessage failed, ret:%d, pattern:%s", ret, format);
234 : }
235 1 : return ret;
236 : }
237 :
238 0 : void ReportInnerError(
239 : const char_t* file_name, const char_t* func, uint32_t line, const std::string error_code, const char_t* format, ...)
240 : {
241 : va_list arg_list;
242 0 : va_start(arg_list, format);
243 0 : (void)ReportInnerErrorMessage(file_name, func, line, error_code.c_str(), format, arg_list);
244 0 : va_end(arg_list);
245 0 : return;
246 : }
247 : } // namespace error_message
248 :
249 : namespace {
250 : #ifdef __GNUC__
251 : constexpr const error_message::char_t* const kErrorCodePath = "../conf/error_manager/error_code.json";
252 : constexpr const error_message::char_t* const kSeparator = "/";
253 : #else
254 : const error_message::char_t* const kErrorCodePath = "..\\conf\\error_manager\\error_code.json";
255 : const error_message::char_t* const kSeparator = "\\";
256 : #endif
257 :
258 : constexpr uint64_t kLength = 2UL;
259 :
260 60645 : void Ltrim(std::string& s)
261 : {
262 60645 : (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](const error_message::char_t c) -> bool {
263 71206 : return static_cast<bool>(std::isspace(static_cast<uint8_t>(c)) == 0);
264 : }));
265 60645 : }
266 :
267 60645 : void Rtrim(std::string& s)
268 : {
269 121290 : (void)s.erase(
270 60645 : std::find_if(
271 60645 : s.rbegin(), s.rend(),
272 60711 : [](const error_message::char_t c) -> bool {
273 60711 : return static_cast<bool>(std::isspace(static_cast<uint8_t>(c)) == 0);
274 : })
275 : .base(),
276 : s.end());
277 60645 : }
278 :
279 : /// @ingroup domi_common
280 : /// @brief trim space
281 60645 : void Trim(std::string& s)
282 : {
283 60645 : Rtrim(s);
284 60645 : Ltrim(s);
285 60645 : }
286 :
287 : /// @brief Obtain error manager self library path
288 : /// @return store liberror_manager.so path
289 21 : std::string GetSelfLibraryDir(void)
290 : {
291 21 : mmDlInfo dl_info{nullptr, nullptr, nullptr, nullptr, 0, 0, 0};
292 21 : if (mmDladdr(reinterpret_cast<void*>(GetSelfLibraryDir), &dl_info) != EN_OK) {
293 0 : const error_message::char_t* error = mmDlerror();
294 0 : error = (error == nullptr) ? "" : error;
295 0 : GELOGW("Failed to read the shared library file path! reason:%s", error);
296 0 : return std::string();
297 : } else {
298 21 : std::string so_path = dl_info.dli_fname;
299 21 : error_message::char_t path[MMPA_MAX_PATH] = {};
300 21 : if (so_path.length() >= static_cast<size_t>(MMPA_MAX_PATH)) {
301 0 : GELOGW("The shared library file path is too long!");
302 0 : return std::string();
303 : }
304 21 : if (mmRealPath(so_path.c_str(), &(path[0]), MMPA_MAX_PATH) != EN_OK) {
305 0 : GELOGW("Failed to get realpath of %s, reason:%s", so_path.c_str(), strerror(errno));
306 0 : return std::string();
307 : }
308 :
309 21 : so_path = &(path[0]);
310 21 : so_path = so_path.substr(0U, so_path.rfind(kSeparator) + 1U);
311 21 : return so_path;
312 21 : }
313 : }
314 :
315 : // split string
316 27106 : std::vector<std::string> SplitByDelim(const std::string& str, const error_message::char_t delim)
317 : {
318 27106 : std::vector<std::string> elems;
319 :
320 27106 : if (str.empty()) {
321 3366 : elems.emplace_back("");
322 3366 : return elems;
323 : }
324 :
325 23740 : std::stringstream ss(str);
326 23740 : std::string item;
327 :
328 84385 : while (getline(ss, item, delim)) {
329 60645 : Trim(item);
330 60645 : elems.push_back(item);
331 : }
332 23740 : const auto str_size = str.size();
333 23740 : if ((str_size > 0U) && (str[str_size - 1U] == delim)) {
334 0 : elems.emplace_back("");
335 : }
336 :
337 23740 : return elems;
338 23740 : }
339 : } // namespace
340 :
341 : thread_local error_message::Context ErrorManager::error_context_ = {0UL, "", "", ""};
342 :
343 : /// @brief Obtain ErrorManager instance
344 : /// @return ErrorManager instance
345 835 : ErrorManager& ErrorManager::GetInstance()
346 : {
347 835 : static ErrorManager instance;
348 835 : return instance;
349 : }
350 :
351 : /// @brief init
352 : /// @param [in] path: current so path
353 : /// @return int 0(success) -1(fail)
354 23 : int32_t ErrorManager::Init(const std::string path)
355 : {
356 23 : const std::string file_path = path + kErrorCodePath;
357 23 : GELOGI("Begin to init, path is %s", path.c_str());
358 : // error_map_由ParseJsonFormatString内部持mutex_保护, 此处不再持锁:
359 : // 一方面避免文件IO在临界区内执行, 另一方面避免与ParseJsonFormatString的加锁递归
360 23 : const int32_t ret = ParseJsonFile(file_path);
361 23 : if (ret != 0) {
362 23 : GELOGW("[Parse][File]Parse config file:%s failed", file_path.c_str());
363 23 : return -1;
364 : }
365 0 : is_init_.store(true, std::memory_order_release);
366 0 : return 0;
367 23 : }
368 :
369 : /// @brief init
370 : /// @return int 0(success) -1(fail)
371 1 : int32_t ErrorManager::Init() { return Init(GetSelfLibraryDir()); }
372 :
373 409 : int32_t ErrorManager::EnsureInitialized()
374 : {
375 409 : if (is_init_.load(std::memory_order_acquire)) {
376 391 : return 0;
377 : }
378 18 : const std::unique_lock<std::mutex> lck(init_mutex_);
379 18 : if (is_init_.load(std::memory_order_relaxed)) {
380 0 : return 0;
381 : }
382 18 : return Init(GetSelfLibraryDir());
383 18 : }
384 :
385 5 : int32_t ErrorManager::Init(error_message::ErrorMsgMode error_mode)
386 : {
387 5 : if (error_mode >= error_message::ErrorMsgMode::ERR_MSG_MODE_MAX) {
388 3 : GELOGE("[Init][Error]error mode is invalid %u", error_mode);
389 3 : return -1;
390 : }
391 2 : const int32_t ret = Init(GetSelfLibraryDir());
392 2 : if (ret != 0) {
393 2 : return -1;
394 : }
395 0 : error_mode_.store(error_mode, std::memory_order_release);
396 0 : return 0;
397 : }
398 :
399 37 : int32_t ErrorManager::ReportInterErrMessage(const std::string error_code, const std::string& error_msg)
400 : {
401 37 : std::string report_time = CurrentTimeFormatStr();
402 37 : constexpr uint64_t kMaxWorkSize = 1000UL;
403 37 : if (EnsureInitialized() != 0) {
404 8 : GELOGI("ErrorManager has not been initialized, can't report error_message.");
405 8 : return -1;
406 : }
407 29 : if (!IsInnerErrorCode(error_code)) {
408 2 : GELOGE("[Report][Error]error_code %s is not internal error code", error_code.c_str());
409 2 : return -1;
410 : }
411 :
412 27 : const std::unique_lock<std::mutex> lck(mutex_);
413 27 : if (error_context_.work_stream_id == 0UL) {
414 2 : if (error_message_per_work_id_.size() > kMaxWorkSize) {
415 1 : GELOGW(
416 : "[Report][Error]error_code %s, error work_stream total size exceed %lu, skip record",
417 : error_code.c_str(), kMaxWorkSize);
418 1 : return -1;
419 : }
420 1 : GenWorkStreamIdDefault();
421 : }
422 :
423 26 : GELOGI(
424 : "report error_message, error_code:%s, work_stream_id:%lu, error_mode:%u", error_code.c_str(),
425 : error_context_.work_stream_id, static_cast<uint32_t>(error_mode_.load(std::memory_order_relaxed)));
426 :
427 26 : auto& error_messages = GetErrorMsgContainer(error_context_.work_stream_id);
428 26 : auto& warning_messages = GetWarningMsgContainer(error_context_.work_stream_id);
429 :
430 26 : if (error_messages.size() > kMaxWorkSize) {
431 1 : GELOGW(
432 : "[Report][Error]error_code %s, error work_stream_id:%lu item size exceed %lu, skip record",
433 : error_code.c_str(), error_context_.work_stream_id, kMaxWorkSize);
434 1 : return -1;
435 : }
436 :
437 25 : std::string tmp = error_msg;
438 25 : if (error_mode_.load(std::memory_order_acquire) == error_message::ErrorMsgMode::PROCESS_MODE) {
439 8 : tmp += "[THREAD:" + std::to_string(mmGetTid()) + "]";
440 : }
441 :
442 175 : ErrorManager::ErrorItem item = {error_code, "", tmp, "", "", {}, report_time};
443 25 : if (error_code[0UL] == 'W') {
444 10 : const auto it = find(warning_messages.begin(), warning_messages.end(), item);
445 20 : if (it == warning_messages.end()) {
446 10 : warning_messages.emplace_back(item);
447 : }
448 : } else {
449 15 : const auto it = find(error_messages.begin(), error_messages.end(), item);
450 30 : if (it == error_messages.end()) {
451 15 : error_messages.emplace_back(item);
452 : }
453 : }
454 25 : return 0;
455 37 : }
456 :
457 : /// @brief report error message
458 : /// @param [in] error_code: error code
459 : /// @param [in] args_map: parameter map
460 : /// @return int 0(success) -1(fail)
461 346 : int32_t ErrorManager::ReportErrMessage(const std::string error_code, const std::map<std::string, std::string>& args_map)
462 : {
463 346 : std::string report_time = CurrentTimeFormatStr();
464 346 : if (EnsureInitialized() != 0) {
465 8 : GELOGI("ErrorManager has not been initialized, can't report error_message.");
466 8 : return 0;
467 : }
468 :
469 338 : if (error_context_.work_stream_id == 0UL) {
470 11 : GenWorkStreamIdDefault();
471 : }
472 :
473 338 : GELOGI(
474 : "report error_message, error_code:%s, work_stream_id:%lu, error_mode:%u.", error_code.c_str(),
475 : error_context_.work_stream_id, static_cast<uint32_t>(error_mode_.load(std::memory_order_relaxed)));
476 : // error_map_可能被ParseJsonFormatString并发改写, 此处必须持锁查找并整体拷贝出配置,
477 : // 不能在锁外继续持有指向map内部的引用
478 338 : ErrorInfoConfig error_info;
479 : {
480 338 : const std::unique_lock<std::mutex> lock(mutex_);
481 338 : const std::map<std::string, ErrorManager::ErrorInfoConfig>::const_iterator iter = error_map_.find(error_code);
482 338 : if (iter == error_map_.cend()) {
483 2 : GELOGW("[Report][Warning]error_code %s is not registered", error_code.c_str());
484 2 : return -1;
485 : }
486 336 : error_info = iter->second;
487 338 : }
488 336 : std::string error_message = error_info.error_message;
489 1010 : for (const std::string& arg : error_info.arg_list) {
490 345 : if (arg.empty()) {
491 4 : GELOGI("arg is null");
492 4 : break;
493 : }
494 341 : const auto arg_it = args_map.find(arg);
495 341 : if (arg_it == args_map.end()) {
496 2 : GELOGE("[Report][Error]error_code: %s, arg %s does not exist in map", error_code.c_str(), arg.c_str());
497 3 : return -1;
498 : }
499 339 : const std::string& arg_value = arg_it->second;
500 339 : const auto index = error_message.find("%s");
501 339 : if (index == std::string::npos) {
502 1 : GELOGE(
503 : "[Report][Error]error_code: %s, %s location in error_message is not found", error_code.c_str(),
504 : arg.c_str());
505 1 : return -1;
506 : }
507 338 : (void)error_message.replace(index, kLength, arg_value);
508 : }
509 :
510 333 : const std::unique_lock<std::mutex> lock(mutex_);
511 333 : auto& error_messages = GetErrorMsgContainer(error_context_.work_stream_id);
512 333 : auto& warning_messages = GetWarningMsgContainer(error_context_.work_stream_id);
513 :
514 333 : if (error_mode_.load(std::memory_order_acquire) == error_message::ErrorMsgMode::PROCESS_MODE) {
515 8 : error_message += "[THREAD:" + std::to_string(mmGetTid()) + "]";
516 : }
517 : ErrorManager::ErrorItem error_item = {
518 : error_code, error_info.error_title, error_message, error_info.possible_cause, error_info.solution, args_map,
519 333 : report_time};
520 333 : if (error_code[0UL] == 'W') {
521 11 : const auto it = find(warning_messages.begin(), warning_messages.end(), error_item);
522 22 : if (it == warning_messages.end()) {
523 11 : warning_messages.emplace_back(error_item);
524 : }
525 : } else {
526 322 : const auto it = find(error_messages.begin(), error_messages.end(), error_item);
527 644 : if (it == error_messages.end()) {
528 19 : error_messages.emplace_back(error_item);
529 : }
530 : }
531 333 : return 0;
532 346 : }
533 :
534 8 : int32_t ErrorManager::ReportErrMsgWithoutTpl(const std::string& error_code, const std::string& errmsg)
535 : {
536 8 : std::string report_time = CurrentTimeFormatStr();
537 8 : if (EnsureInitialized() != 0) {
538 1 : GELOGI("ErrorManager has not been initialized, can't report error_message.");
539 1 : return -1;
540 : }
541 :
542 7 : if (error_context_.work_stream_id == 0UL) {
543 1 : GenWorkStreamIdDefault();
544 : }
545 :
546 7 : auto final_error_code = error_code;
547 7 : if (!IsUserDefinedErrorCode(final_error_code)) {
548 5 : GELOGW(
549 : "[Report] Current error code is [%s], suggest using the recommended U segment. "
550 : "The error code EU0000 is reported!",
551 : final_error_code.c_str());
552 5 : final_error_code = "EU0000";
553 : }
554 :
555 7 : GELOGI(
556 : "report error_message, error_code:%s, work_stream_id:%lu, error_mode:%u.", error_code.c_str(),
557 : error_context_.work_stream_id, static_cast<uint32_t>(error_mode_.load(std::memory_order_relaxed)));
558 :
559 7 : const std::unique_lock<std::mutex> lock(mutex_);
560 7 : auto& error_messages = GetErrorMsgContainer(error_context_.work_stream_id);
561 :
562 49 : ErrorItem error_item{final_error_code, "", errmsg, "", "", {}, report_time};
563 7 : const auto it = find(error_messages.begin(), error_messages.end(), error_item);
564 14 : if (it == error_messages.end()) {
565 7 : error_messages.emplace_back(error_item);
566 : }
567 7 : return 0;
568 8 : }
569 :
570 4 : void ErrorManager::AssembleInnerErrorMessage(
571 : const std::vector<ErrorItem>& error_messages, const std::string& first_code, std::stringstream& err_stream) const
572 : {
573 4 : std::string current_code_print = first_code;
574 4 : const bool IsErrorId = IsParamCheckErrorId(first_code);
575 12 : for (auto& item : error_messages) {
576 6 : if (!IsParamCheckErrorId(item.error_id)) {
577 2 : current_code_print = item.error_id;
578 2 : break;
579 : }
580 : }
581 4 : err_stream << current_code_print << ": Internal error!" << std::endl;
582 4 : bool print_traceback_once = false;
583 14 : for (auto& item : error_messages) { // Display the first non 8888 error code
584 6 : if (IsParamCheckErrorId(item.error_id) && IsErrorId) {
585 4 : err_stream << " " << item.error_message << std::endl;
586 4 : continue;
587 : }
588 2 : current_code_print == " " ?
589 0 : (err_stream << current_code_print << " " << item.error_message << std::endl) :
590 4 : (err_stream << current_code_print << "[PID: " << std::to_string(mmGetPid()) << "] " << item.report_time
591 4 : << " " << item.error_title << "(" << item.error_id << "): "
592 4 : << " " << item.error_message << std::endl);
593 :
594 2 : current_code_print = " ";
595 2 : if (!print_traceback_once) {
596 2 : err_stream << "TraceBack (most recent call last):" << std::endl;
597 2 : print_traceback_once = true;
598 : }
599 : }
600 4 : }
601 :
602 36 : std::string ErrorManager::GetErrorMessage()
603 : {
604 36 : const auto& error_messages = GetRawErrorMessages();
605 36 : if (error_messages.empty()) {
606 30 : return "";
607 : }
608 :
609 21 : std::stringstream err_stream;
610 21 : std::string first_code = error_messages[0UL].error_id;
611 48 : for (const auto& item : error_messages) {
612 23 : if (!IsInnerErrorCode(item.error_id)) {
613 17 : first_code = item.error_id;
614 34 : err_stream << "[PID: " << std::to_string(mmGetPid()) << "] " << item.report_time << " " << item.error_title
615 34 : << "(" << first_code << "): " << item.error_message << std::endl;
616 17 : if (!item.possible_cause.empty() && item.possible_cause != "N/A") {
617 1 : err_stream << " Possible Cause: " << item.possible_cause << std::endl;
618 : }
619 17 : if (!item.solution.empty() && item.solution != "N/A") {
620 5 : err_stream << " Solution: " << item.solution << std::endl;
621 : }
622 17 : break;
623 : }
624 : }
625 21 : if (IsInnerErrorCode(first_code)) {
626 4 : AssembleInnerErrorMessage(error_messages, first_code, err_stream);
627 : } else {
628 17 : bool print_traceback_once = false;
629 66 : for (const auto& item : error_messages) {
630 32 : if (first_code == item.error_id && error_messages[0].error_message == item.error_message) {
631 18 : continue;
632 : }
633 14 : if (!print_traceback_once) {
634 6 : err_stream << "TraceBack (most recent call last):" << std::endl;
635 6 : print_traceback_once = true;
636 : }
637 14 : err_stream << " " << item.error_message << std::endl;
638 : }
639 : }
640 21 : const std::unique_lock<std::mutex> lck(mutex_);
641 21 : ClearErrorMsgContainer(error_context_.work_stream_id);
642 21 : return err_stream.str();
643 36 : }
644 :
645 15 : std::string ErrorManager::GetWarningMessage()
646 : {
647 15 : GELOGI(
648 : "current work_stream_id:%lu, error_mode:%u", error_context_.work_stream_id,
649 : static_cast<uint32_t>(error_mode_.load(std::memory_order_relaxed)));
650 15 : const std::unique_lock<std::mutex> lck(mutex_);
651 15 : auto& warning_messages = GetWarningMsgContainer(error_context_.work_stream_id);
652 :
653 15 : std::stringstream warning_stream;
654 45 : for (auto& item : warning_messages) {
655 30 : warning_stream << "[PID: " << std::to_string(mmGetPid()) << "] " << item.report_time << " " << item.error_title
656 30 : << "(" << item.error_id << "): " << item.error_message << std::endl;
657 : }
658 15 : ClearWarningMsgContainer(error_context_.work_stream_id);
659 30 : return warning_stream.str();
660 15 : }
661 :
662 : /// @brief output error message
663 : /// @param [in] handle: print handle
664 : /// @return int 0(success) -1(fail)
665 2 : int32_t ErrorManager::OutputErrMessage(int32_t handle)
666 : {
667 2 : std::string err_msg = GetErrorMessage();
668 2 : if (err_msg.empty()) {
669 2 : std::stringstream err_stream;
670 2 : err_stream << "E19999: Internal error!" << std::endl;
671 : err_stream << " "
672 2 : << "Unknown error occurred. Please check the log." << std::endl;
673 2 : err_msg = err_stream.str();
674 2 : }
675 :
676 2 : if (handle <= fileno(stderr)) {
677 1 : std::cout << err_msg << std::endl;
678 : } else {
679 1 : const mmSsize_t ret = mmWrite(
680 1 : handle, const_cast<error_message::char_t*>(err_msg.c_str()), static_cast<uint32_t>(err_msg.length()));
681 1 : if (ret == -1) {
682 1 : GELOGE("[Write][File]fail, reason:%s", strerror(errno));
683 1 : return -1;
684 : }
685 : }
686 1 : return 0;
687 2 : }
688 :
689 : /// @brief output message
690 : /// @param [in] handle: print handle
691 : /// @return int 0(success) -1(fail)
692 1 : int32_t ErrorManager::OutputMessage(int32_t handle)
693 : {
694 1 : const std::string warning_msg = GetWarningMessage();
695 1 : std::cout << warning_msg << std::endl;
696 1 : handle = 0;
697 1 : return handle;
698 1 : }
699 :
700 24 : int32_t ErrorManager::ParseJsonFile(const std::string path)
701 : {
702 24 : GELOGD("Begin to parse json file, path is %s", path.c_str());
703 24 : nlohmann::json json_file;
704 24 : const int32_t status = ReadJsonFile(path, &json_file);
705 24 : if (status != 0) {
706 23 : GELOGW("[Read][JsonFile]file path is %s", path.c_str());
707 23 : return -1;
708 : }
709 1 : return ParseJsonFormatString(PtrToPtr<nlohmann::json, void>(&json_file));
710 24 : }
711 : /// @brief parse json file
712 : /// @param [in] handle: json handle
713 : /// @return int 0(success) -1(fail)
714 377 : int32_t ErrorManager::ParseJsonFormatString(const void* const handle, uint32_t priority)
715 : {
716 377 : GELOGD("Begin to parse json string");
717 : // 本接口是公开接口, RegisterFormatErrorMessage会在运行期由任意线程调用, 必须持锁改写error_map_
718 377 : const std::unique_lock<std::mutex> lck(mutex_);
719 : try {
720 377 : const nlohmann::json* const json_file = PtrToPtr<void, nlohmann::json>(handle);
721 377 : if (json_file->find("error_info_list") == json_file->end()) {
722 2 : GELOGW("[Check][Config]The message of error_info_list is not found");
723 2 : return -1;
724 : }
725 375 : const nlohmann::json& error_list_json = json_file->at("error_info_list");
726 375 : if (error_list_json.is_null() || !error_list_json.is_array()) {
727 1 : GELOGW("[Check][Config]The message of error_info_list is not found or "
728 : "the message of error_info_list is not array");
729 1 : return -1;
730 : }
731 27480 : for (const auto& error_json : error_list_json) {
732 27107 : ErrorInfoConfig error_info;
733 27107 : error_info.error_id = error_json["ErrCode"];
734 27106 : error_info.error_message = error_json["ErrMessage"];
735 27106 : if (error_json.contains("errTitle")) {
736 24032 : error_info.error_title = error_json["errTitle"];
737 : }
738 27106 : if (error_json.contains("suggestion")) {
739 11162 : error_info.possible_cause = error_json["suggestion"]["Possible Cause"];
740 11162 : error_info.solution = error_json["suggestion"]["Solution"];
741 : }
742 27106 : error_info.arg_list = SplitByDelim(error_json["Arglist"], ',');
743 27106 : error_info.priority = priority;
744 27106 : auto it = error_map_.find(error_info.error_id);
745 27106 : if (it == error_map_.cend()) {
746 715 : (void)error_map_.emplace(error_info.error_id, error_info);
747 715 : GELOGD("add error_code %s success", error_info.error_id.c_str());
748 : } else {
749 26391 : if (it->second.priority < error_info.priority) {
750 0 : it->second = error_info;
751 0 : GELOGD(
752 : "Update error_code %s success, current priority[%u] is greater than saved priority[%u]",
753 : error_info.error_id.c_str(), priority, it->second.priority);
754 : } else {
755 26391 : GELOGD(
756 : "No need update error_code %s, due to current priority[%u] is less than "
757 : "or equal to saved priority[%u]",
758 : error_info.error_id.c_str(), priority, it->second.priority);
759 : }
760 : }
761 27107 : }
762 1 : } catch (const nlohmann::json::exception& e) {
763 1 : GELOGW("[Parse][JsonFile]exception message: %s", e.what());
764 1 : return -1;
765 1 : }
766 373 : return 0;
767 377 : }
768 :
769 : /// @brief read json file
770 : /// @param [in] file_path: json path
771 : /// @param [in] handle: print handle
772 : /// @return int 0(success) -1(fail)
773 98 : int32_t ErrorManager::ReadJsonFile(const std::string& file_path, void* const handle)
774 : {
775 98 : if (file_path.empty()) {
776 1 : GELOGW("[Read][JsonFile]path %s is not valid", file_path.c_str());
777 1 : return -1;
778 : }
779 97 : nlohmann::json* const json_file = PtrToPtr<void, nlohmann::json>(handle);
780 97 : if (json_file == nullptr) {
781 1 : GELOGW("[Check][Param]JsonFile is nullptr");
782 1 : return -1;
783 : }
784 96 : const error_message::char_t* const file = file_path.data();
785 96 : if ((mmAccess2(file, M_F_OK)) != EN_OK) {
786 23 : GELOGW("[Read][JsonFile] %s does not exist, error %s", file_path.c_str(), strerror(errno));
787 23 : return -1;
788 : }
789 :
790 73 : std::ifstream ifs(file_path);
791 73 : if (!ifs.is_open()) {
792 0 : GELOGW("[Read][JsonFile]Open %s failed", file_path.c_str());
793 0 : return -1;
794 : }
795 :
796 73 : const std::string content((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
797 : try {
798 74 : *json_file = nlohmann::json::parse(content.c_str(), content.c_str() + content.size());
799 1 : } catch (const nlohmann::json::exception& e) {
800 1 : GELOGW("[Read][JsonFile]Parse json fail. path: %s, exception message: %s.", file_path.c_str(), e.what());
801 1 : ifs.close();
802 1 : return -1;
803 1 : }
804 :
805 72 : ifs.close();
806 72 : GELOGD("Read json file success");
807 72 : return 0;
808 73 : }
809 :
810 : /// @brief report error message
811 : /// @param [in] error_code: error code
812 : /// @param [in] vector parameter key, vector parameter value
813 : /// @return int 0(success) -1(fail)
814 4 : void ErrorManager::ATCReportErrMessage(
815 : const std::string error_code, const std::vector<std::string>& key, const std::vector<std::string>& value)
816 : {
817 4 : if (EnsureInitialized() != 0) {
818 0 : GELOGI("ErrorManager has not been initialized, can't report error_message.");
819 0 : return;
820 : }
821 4 : std::map<std::string, std::string> args_map;
822 4 : if (key.empty()) {
823 2 : (void)ErrorManager::GetInstance().ReportErrMessage(error_code, args_map);
824 2 : } else if (key.size() == value.size()) {
825 2 : for (size_t i = 0UL; i < key.size(); ++i) {
826 1 : (void)args_map.insert(std::make_pair(key[i], value[i]));
827 : }
828 1 : (void)ErrorManager::GetInstance().ReportErrMessage(error_code, args_map);
829 : } else {
830 1 : GELOGW("ATCReportErrMessage wrong, vector key and value size is not equal");
831 : }
832 4 : }
833 :
834 : /// @brief report graph compile failed message such as error code and op_name in mustune case
835 : /// @param [in] msg: failed message map, key is error code, value is op_name
836 : /// @param [out] classified_msg: classified_msg message map, key is error code, value is op_name vector
837 4 : void ErrorManager::ClassifyCompileFailedMsg(
838 : const std::map<std::string, std::string>& msg, std::map<std::string, std::vector<std::string>>& classified_msg)
839 : {
840 8 : for (const auto& itr : msg) {
841 4 : GELOGD("msg is error_code:%s, op_name:%s", itr.first.c_str(), itr.second.c_str());
842 4 : const auto err_code_itr = classified_msg.find(itr.first);
843 4 : if (err_code_itr == classified_msg.end()) {
844 9 : (void)classified_msg.emplace(itr.first, std::vector<std::string>{itr.second});
845 : } else {
846 1 : std::vector<std::string>& op_name_list = err_code_itr->second;
847 1 : op_name_list.emplace_back(itr.second);
848 : }
849 : }
850 7 : }
851 :
852 : /// @brief report graph compile failed message such as error code and op_name in mustune case
853 : /// @param [in] root_graph_name: root graph name
854 : /// @param [in] msg: failed message map, key is error code, value is op_name
855 : /// @return int 0(success) -1(fail)
856 4 : int32_t ErrorManager::ReportMstuneCompileFailedMsg(
857 : const std::string& root_graph_name, const std::map<std::string, std::string>& msg)
858 : {
859 4 : if (EnsureInitialized() != 0) {
860 0 : GELOGI("ErrorManager has not been initialized, can't report error_message.");
861 0 : return 0;
862 : }
863 4 : if (msg.empty() || root_graph_name.empty()) {
864 2 : GELOGW(
865 : "Msg or root graph name is empty, msg size is %zu, root graph name is %s", msg.size(),
866 : root_graph_name.c_str());
867 2 : return -1;
868 : }
869 2 : GELOGD("Report graph:%s compile failed msg", root_graph_name.c_str());
870 2 : const std::unique_lock<std::mutex> lock(mutex_);
871 2 : const auto itr = compile_failed_msg_map_.find(root_graph_name);
872 2 : if (itr != compile_failed_msg_map_.end()) {
873 1 : std::map<std::string, std::vector<std::string>>& classified_msg = itr->second;
874 1 : ClassifyCompileFailedMsg(msg, classified_msg);
875 : } else {
876 1 : std::map<std::string, std::vector<std::string>> classified_msg;
877 1 : ClassifyCompileFailedMsg(msg, classified_msg);
878 1 : (void)compile_failed_msg_map_.emplace(root_graph_name, classified_msg);
879 1 : }
880 2 : return 0;
881 2 : }
882 :
883 : /// @brief get graph compile failed message in mustune case
884 : /// @param [in] graph_name: graph name
885 : /// @param [out] msg_map: failed message map, key is error code, value is op_name list
886 : /// @return int 0(success) -1(fail)
887 4 : int32_t ErrorManager::GetMstuneCompileFailedMsg(
888 : const std::string& graph_name, std::map<std::string, std::vector<std::string>>& msg_map)
889 : {
890 4 : if (EnsureInitialized() != 0) {
891 0 : GELOGI("ErrorManager has not been initialized, can't report error_message.");
892 0 : return 0;
893 : }
894 4 : if (!msg_map.empty()) {
895 2 : GELOGW("msg_map is not empty, exist msg");
896 2 : return -1;
897 : }
898 2 : const std::unique_lock<std::mutex> lock(mutex_);
899 2 : const auto iter = compile_failed_msg_map_.find(graph_name);
900 2 : if (iter == compile_failed_msg_map_.end()) {
901 1 : GELOGW("can not find graph, name is:%s", graph_name.c_str());
902 1 : return -1;
903 : } else {
904 1 : auto& compile_failed_msg = iter->second;
905 1 : msg_map.swap(compile_failed_msg);
906 1 : (void)compile_failed_msg_map_.erase(graph_name);
907 : }
908 1 : GELOGI("get graph:%s compile result msg success", graph_name.c_str());
909 :
910 1 : return 0;
911 2 : }
912 :
913 385 : std::vector<ErrorManager::ErrorItem>& ErrorManager::GetErrorMsgContainerByWorkId(uint64_t work_id)
914 : {
915 385 : return GetOrCreateMessageContainerByWorkId(error_message_per_work_id_, work_id);
916 : }
917 :
918 354 : std::vector<ErrorManager::ErrorItem>& ErrorManager::GetWarningMsgContainerByWorkId(uint64_t work_id)
919 : {
920 354 : return GetOrCreateMessageContainerByWorkId(warning_messages_per_work_id_, work_id);
921 : }
922 :
923 404 : std::vector<ErrorManager::ErrorItem>& ErrorManager::GetErrorMsgContainer(uint64_t work_stream_id)
924 : {
925 404 : return (error_mode_.load(std::memory_order_acquire) == error_message::ErrorMsgMode::INTERNAL_MODE) ?
926 384 : GetErrorMsgContainerByWorkId(work_stream_id) :
927 20 : error_message_process_;
928 : }
929 :
930 374 : std::vector<ErrorManager::ErrorItem>& ErrorManager::GetWarningMsgContainer(uint64_t work_stream_id)
931 : {
932 374 : return (error_mode_.load(std::memory_order_acquire) == error_message::ErrorMsgMode::INTERNAL_MODE) ?
933 354 : GetWarningMsgContainerByWorkId(work_stream_id) :
934 20 : warning_messages_process_;
935 : }
936 :
937 15 : void ErrorManager::GenWorkStreamIdDefault()
938 : {
939 : // system getpid and gettid is always successful
940 15 : const int32_t pid = mmGetPid();
941 15 : const int32_t tid = mmGetTid();
942 :
943 15 : constexpr uint64_t kPidOffset = 100000UL;
944 15 : const uint64_t work_stream_id =
945 15 : static_cast<uint64_t>(static_cast<uint32_t>(pid) * kPidOffset) + static_cast<uint64_t>(tid);
946 15 : error_context_.work_stream_id = work_stream_id;
947 15 : }
948 :
949 1 : void ErrorManager::GenWorkStreamIdBySessionGraph(const uint64_t session_id, const uint64_t graph_id)
950 : {
951 1 : constexpr uint64_t kSessionIdOffset = 100000UL;
952 1 : const uint64_t work_stream_id = (session_id * kSessionIdOffset) + graph_id;
953 1 : error_context_.work_stream_id = work_stream_id;
954 :
955 1 : const std::unique_lock<std::mutex> lck(mutex_);
956 1 : ClearErrorMsgContainerByWorkId(work_stream_id);
957 1 : ClearWarningMsgContainerByWorkId(work_stream_id);
958 1 : }
959 :
960 1 : void ErrorManager::GenWorkStreamIdWithSessionIdGraphId(const uint64_t session_id, const uint64_t graph_id)
961 : {
962 1 : constexpr uint64_t kSessionIdOffset = 100000UL;
963 1 : const uint64_t work_stream_id = (session_id * kSessionIdOffset) + graph_id;
964 1 : error_context_.work_stream_id = work_stream_id;
965 1 : }
966 :
967 54 : void ErrorManager::ClearErrorMsgContainerByWorkId(const uint64_t work_stream_id)
968 : {
969 54 : return ClearMessageContainerByWorkId(error_message_per_work_id_, work_stream_id);
970 : }
971 :
972 12 : void ErrorManager::ClearWarningMsgContainerByWorkId(const uint64_t work_stream_id)
973 : {
974 12 : return ClearMessageContainerByWorkId(warning_messages_per_work_id_, work_stream_id);
975 : }
976 :
977 58 : void ErrorManager::ClearErrorMsgContainer(const uint64_t work_stream_id)
978 : {
979 58 : if (error_mode_.load(std::memory_order_acquire) == error_message::ErrorMsgMode::PROCESS_MODE) {
980 6 : error_message_process_.clear();
981 : } else {
982 52 : ClearErrorMsgContainerByWorkId(work_stream_id);
983 : }
984 58 : }
985 :
986 15 : void ErrorManager::ClearWarningMsgContainer(const uint64_t work_stream_id)
987 : {
988 15 : if (error_mode_.load(std::memory_order_acquire) == error_message::ErrorMsgMode::PROCESS_MODE) {
989 4 : warning_messages_process_.clear();
990 : } else {
991 11 : ClearWarningMsgContainerByWorkId(work_stream_id);
992 : }
993 15 : }
994 :
995 26 : const std::string& ErrorManager::GetLogHeader()
996 : {
997 26 : if ((error_context_.first_stage == "") && (error_context_.second_stage == "")) {
998 26 : error_context_.log_header = "";
999 : } else {
1000 0 : error_context_.log_header = "[" + error_context_.first_stage + "][" + error_context_.second_stage + "]";
1001 : }
1002 26 : return error_context_.log_header;
1003 : }
1004 :
1005 3 : error_message::Context& ErrorManager::GetErrorManagerContext()
1006 : {
1007 : // son thread need set father thread work_stream_id, but work_stream_id cannot be zero
1008 : // so GenWorkStreamIdDefault here directly
1009 3 : if (error_context_.work_stream_id == 0UL) {
1010 1 : GenWorkStreamIdDefault();
1011 : }
1012 3 : return error_context_;
1013 : }
1014 :
1015 4 : void ErrorManager::SetErrorContext(error_message::Context error_context)
1016 : {
1017 4 : error_context_.work_stream_id = error_context.work_stream_id;
1018 8 : error_context_.first_stage = std::move(error_context.first_stage);
1019 8 : error_context_.second_stage = std::move(error_context.second_stage);
1020 8 : error_context_.log_header = std::move(error_context.log_header);
1021 4 : }
1022 :
1023 0 : void ErrorManager::SetStage(const std::string& first_stage, const std::string& second_stage)
1024 : {
1025 0 : error_context_.first_stage = first_stage;
1026 0 : error_context_.second_stage = second_stage;
1027 0 : }
1028 :
1029 83 : bool ErrorManager::IsInnerErrorCode(const std::string& error_code) const
1030 : {
1031 83 : const std::string kInterErrorCodePrefix = "9999";
1032 83 : if (!IsValidErrorCode(error_code)) {
1033 7 : return false;
1034 : } else {
1035 76 : return (error_code.substr(2U, 4U) == kInterErrorCodePrefix) || IsParamCheckErrorId(error_code);
1036 : }
1037 83 : }
1038 :
1039 : // 这里只做简单校验, 校验是非内部错误码、非预定义错误码的6位字符串即可
1040 13 : bool ErrorManager::IsUserDefinedErrorCode(const std::string& error_code)
1041 : {
1042 13 : if (!IsValidErrorCode(error_code) || IsInnerErrorCode(error_code)) {
1043 7 : return false;
1044 : }
1045 :
1046 6 : if (EnsureInitialized() != 0) {
1047 1 : GELOGI("ErrorManager has not been initialized, can't verify error code.");
1048 1 : return false;
1049 : }
1050 :
1051 5 : const std::unique_lock<std::mutex> lck(mutex_);
1052 5 : if (error_map_.find(error_code) != error_map_.end()) {
1053 2 : GELOGW("Report error_code:[%s] is predefined error code, suggested use U error code", error_code.c_str());
1054 2 : return false;
1055 : }
1056 3 : return true;
1057 5 : }
1058 :
1059 83 : bool ErrorManager::IsParamCheckErrorId(const std::string& error_code) const
1060 : {
1061 83 : return (error_code.substr(2U, 4U) == kParamCheckErrorSuffix);
1062 : }
1063 :
1064 1 : int32_t ErrorManager::SetRawErrorMessages(const std::vector<ErrorItem>& items)
1065 : {
1066 1 : const std::unique_lock<std::mutex> lck(mutex_);
1067 1 : if (error_context_.work_stream_id == 0UL) {
1068 1 : GenWorkStreamIdDefault();
1069 : }
1070 :
1071 1 : GELOGI("Set error_message, work_stream_id:%lu.", error_context_.work_stream_id);
1072 1 : auto& error_messages = GetErrorMsgContainer(error_context_.work_stream_id);
1073 2 : (void)error_messages.insert(error_messages.end(), items.begin(), items.end());
1074 1 : return 0;
1075 1 : }
1076 :
1077 37 : std::vector<error_message::ErrorItem> ErrorManager::GetRawErrorMessages()
1078 : {
1079 37 : GELOGI("current work_stream_id:%lu", error_context_.work_stream_id);
1080 37 : const std::unique_lock<std::mutex> lck(mutex_);
1081 37 : auto error_items = GetErrorMsgContainer(error_context_.work_stream_id);
1082 37 : ClearErrorMsgContainer(error_context_.work_stream_id);
1083 37 : return error_items;
1084 37 : }
1085 :
1086 : namespace error_message {
1087 308 : int32_t RegisterFormatErrorMessage(const char_t* error_msg, size_t error_msg_len)
1088 : {
1089 308 : nlohmann::json j;
1090 : try {
1091 310 : j = nlohmann::json::parse(error_msg, error_msg + error_msg_len);
1092 2 : } catch (const nlohmann::json::parse_error& e) {
1093 2 : return -1;
1094 2 : }
1095 306 : GELOGI("RegisterFormatErrorMessage, try to register error message");
1096 : // User registration error codes have high priority than those defined in the json file,
1097 : // set priority to 1 here.
1098 306 : return ErrorManager::GetInstance().ParseJsonFormatString(PtrToPtr<nlohmann::json, void>(&j), 1);
1099 308 : }
1100 :
1101 6 : int32_t ReportInnerErrMsg(
1102 : const char* file_name, const char* func, uint32_t line, const char* error_code, const char* format, ...)
1103 : {
1104 : va_list arg_list;
1105 6 : va_start(arg_list, format);
1106 6 : const auto ret = ReportInnerErrorMessage(file_name, func, line, error_code, format, arg_list);
1107 6 : va_end(arg_list);
1108 6 : return ret;
1109 : }
1110 :
1111 9 : int32_t ReportUserDefinedErrMsg(const char* error_code, const char* format, ...)
1112 : {
1113 : va_list arg_list;
1114 9 : std::vector<char> buf(LIMIT_PER_MESSAGE, '\0');
1115 9 : va_start(arg_list, format);
1116 9 : const auto ret = vsprintf_s(buf.data(), LIMIT_PER_MESSAGE, format, arg_list);
1117 9 : if (ret < 0) {
1118 1 : GELOGE("[Check][Param] Format error message failed, ret:%d", ret);
1119 1 : return -1;
1120 : }
1121 :
1122 40 : return ErrorManager::GetInstance().ReportErrMsgWithoutTpl(error_code, std::string(buf.data()));
1123 9 : }
1124 :
1125 11 : int32_t ReportPredefinedErrMsg(
1126 : const char* error_code, const std::vector<const char*>& key, const std::vector<const char*>& value)
1127 : {
1128 11 : if (key.size() != value.size()) {
1129 1 : GELOGE(
1130 : "[Check][Param] ReportPredefinedErrMsg failed, vector key size:[%zu] and value size:[%zu] is not equal",
1131 : key.size(), value.size());
1132 1 : return -1;
1133 : }
1134 10 : std::map<std::string, std::string> args_map;
1135 28 : for (size_t i = 0UL; i < key.size(); ++i) {
1136 18 : (void)args_map.insert(std::make_pair(key[i], value[i]));
1137 : }
1138 20 : return ErrorManager::GetInstance().ReportErrMessage(error_code, args_map);
1139 10 : }
1140 :
1141 1 : int32_t ReportPredefinedErrMsg(const char* error_code) { return ReportPredefinedErrMsg(error_code, {}, {}); }
1142 :
1143 1 : int32_t ErrMgrInit(ErrorMessageMode error_mode)
1144 : {
1145 1 : return ErrorManager::GetInstance().Init(static_cast<error_message::ErrorMsgMode>(error_mode));
1146 : }
1147 :
1148 1 : ErrorManagerContext GetErrMgrContext()
1149 : {
1150 1 : auto ctx = ErrorManager::GetInstance().GetErrorManagerContext();
1151 1 : ErrorManagerContext error_context{};
1152 1 : error_context.work_stream_id = ctx.work_stream_id;
1153 2 : return error_context;
1154 1 : }
1155 :
1156 3 : void SetErrMgrContext(ErrorManagerContext error_context)
1157 : {
1158 3 : Context ctx;
1159 3 : ctx.work_stream_id = error_context.work_stream_id;
1160 6 : return ErrorManager::GetInstance().SetErrorContext(ctx);
1161 3 : }
1162 :
1163 23 : unique_const_char_array GetErrMgrErrorMessage()
1164 : {
1165 23 : return CreateUniquePtrFromString(ErrorManager::GetInstance().GetErrorMessage());
1166 : }
1167 :
1168 9 : unique_const_char_array GetErrMgrWarningMessage()
1169 : {
1170 9 : return CreateUniquePtrFromString(ErrorManager::GetInstance().GetWarningMessage());
1171 : }
1172 :
1173 1 : std::vector<ErrMsgRawItem> GetErrMgrRawErrorMessages()
1174 : {
1175 1 : std::vector<ErrMsgRawItem> raw_items;
1176 1 : auto error_items = ErrorManager::GetInstance().GetRawErrorMessages();
1177 3 : for (const auto& item : error_items) {
1178 1 : ErrMsgRawItem raw_item;
1179 1 : raw_item.error_id = CreateUniquePtrFromString(item.error_id);
1180 1 : raw_item.error_title = CreateUniquePtrFromString(item.error_title);
1181 1 : raw_item.error_message = CreateUniquePtrFromString(item.error_message);
1182 1 : raw_item.possible_cause = CreateUniquePtrFromString(item.possible_cause);
1183 1 : raw_item.solution = CreateUniquePtrFromString(item.solution);
1184 4 : for (const auto& arg : item.args_map) {
1185 3 : raw_item.args_key.emplace_back(CreateUniquePtrFromString(arg.first));
1186 3 : raw_item.args_value.emplace_back(CreateUniquePtrFromString(arg.second));
1187 : }
1188 1 : raw_item.report_time = CreateUniquePtrFromString(item.report_time);
1189 1 : raw_items.emplace_back(std::move(raw_item));
1190 1 : }
1191 1 : return raw_items;
1192 1 : }
1193 : } // namespace error_message
1194 :
1195 : extern "C" {
1196 3 : int32_t RegisterFormatErrorMessageForC(const char* error_msg, unsigned long error_msg_len)
1197 : {
1198 3 : if (error_msg == nullptr) {
1199 1 : GELOGE("[Check][Param] error_msg is null");
1200 1 : return -1;
1201 : }
1202 : try {
1203 2 : return error_message::RegisterFormatErrorMessage(error_msg, error_msg_len);
1204 0 : } catch (const std::exception& e) {
1205 0 : GELOGE("[Check][Exception] RegisterFormatErrorMessageForC caught exception: %s", e.what());
1206 0 : return -1;
1207 0 : } catch (...) {
1208 0 : GELOGE("[Check][Exception] RegisterFormatErrorMessageForC caught unknown exception");
1209 0 : return -1;
1210 0 : }
1211 : }
1212 :
1213 8 : int32_t ReportPredefinedErrMsgForC(const char* error_code, const char** key, const char** value, unsigned long arg_num)
1214 : {
1215 8 : if (error_code == nullptr) {
1216 1 : GELOGE("[Check][Param] error_code is null");
1217 1 : return -1;
1218 : }
1219 7 : if ((arg_num != 0U) && ((key == nullptr) || (value == nullptr))) {
1220 3 : GELOGE("[Check][Param] Argument arrays are null when arg_num:[%lu]", arg_num);
1221 3 : return -1;
1222 : }
1223 :
1224 9 : for (size_t i = 0U; i < arg_num; ++i) {
1225 7 : if ((key[i] == nullptr) || (value[i] == nullptr)) {
1226 2 : GELOGE("[Check][Param] Argument array contains null entry at index:[%zu]", i);
1227 2 : return -1;
1228 : }
1229 : }
1230 :
1231 : try {
1232 2 : std::vector<const char*> key_vec;
1233 2 : std::vector<const char*> value_vec;
1234 2 : key_vec.reserve(arg_num);
1235 2 : value_vec.reserve(arg_num);
1236 5 : for (size_t i = 0U; i < arg_num; ++i) {
1237 3 : key_vec.push_back(key[i]);
1238 3 : value_vec.push_back(value[i]);
1239 : }
1240 2 : return error_message::ReportPredefinedErrMsg(error_code, key_vec, value_vec);
1241 2 : } catch (const std::exception& e) {
1242 0 : GELOGE("[Check][Exception] ReportPredefinedErrMsgForC caught exception: %s", e.what());
1243 0 : return -1;
1244 0 : } catch (...) {
1245 0 : GELOGE("[Check][Exception] ReportPredefinedErrMsgForC caught unknown exception");
1246 0 : return -1;
1247 0 : }
1248 : }
1249 :
1250 6 : int32_t ReportInnerErrMsgForC(
1251 : const char* file_name, const char* func, uint32_t line, const char* error_code, const char* format, ...)
1252 : {
1253 6 : if ((file_name == nullptr) || (func == nullptr) || (error_code == nullptr) || (format == nullptr)) {
1254 4 : GELOGE("[Check][Param] file_name or func or error_code or format is null");
1255 4 : return -1;
1256 : }
1257 :
1258 : va_list arg_list;
1259 2 : va_start(arg_list, format);
1260 2 : int32_t ret = -1;
1261 : try {
1262 2 : ret = ReportInnerErrorMessage(file_name, func, line, error_code, format, arg_list);
1263 0 : } catch (const std::exception& e) {
1264 0 : GELOGE("[Check][Exception] ReportInnerErrMsgForC caught exception: %s", e.what());
1265 0 : } catch (...) {
1266 0 : GELOGE("[Check][Exception] ReportInnerErrMsgForC caught unknown exception");
1267 0 : }
1268 2 : va_end(arg_list);
1269 2 : return ret;
1270 : }
1271 : } // extern "C"
|