1 /*
2 * Copyright (c) 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 "hiview_log_config_manager.h"
17
18 #include <fstream>
19
20 #include "json/json.h"
21 #include "logger.h"
22
23 namespace OHOS {
24 namespace HiviewDFX {
25 namespace {
26 DEFINE_LOG_TAG("HiviewLogConfigManager");
27 constexpr char CONFIG_FILE_PATH[] = "/system/etc/hiview/log_type.json";
28 constexpr char FILE_PATH_KEY[] = "LOGPATH";
29 constexpr char READ_ONLY_KEY[] = "READONLY";
30
ParseJsonFile(const std::string & path)31 Json::Value ParseJsonFile(const std::string& path)
32 {
33 Json::Value jsonRoot;
34 std::ifstream fin(path, std::ifstream::binary);
35 #ifdef JSONCPP_VERSION_STRING
36 Json::CharReaderBuilder builder;
37 Json::CharReaderBuilder::strictMode(&builder.settings_);
38 JSONCPP_STRING errs;
39 if (!parseFromStream(builder, fin, &jsonRoot, &errs)) {
40 #else
41 Json::Reader reader(Json::Features::strictMode());
42 if (!reader.parse(fin, jsonRoot)) {
43 #endif
44 HIVIEW_LOGE("parse file failed, path: %{public}s.", path.c_str());
45 return Json::Value();
46 }
47 return jsonRoot;
48 }
49
50 inline bool IsStringMember(const Json::Value& jsonRoot, const std::string& key)
51 {
52 return jsonRoot.isObject() && jsonRoot.isMember(key) && jsonRoot[key].isString();
53 }
54
55 inline bool IsBoolMember(const Json::Value& jsonRoot, const std::string& key)
56 {
57 return jsonRoot.isObject() && jsonRoot.isMember(key) && jsonRoot[key].isBool();
58 }
59 }
60
GetConfigInfoByType(const std::string & type)61 std::shared_ptr<ConfigInfo> HiviewLogConfigManager::GetConfigInfoByType(const std::string& type)
62 {
63 std::lock_guard<std::mutex> lock(logMutex);
64 if (configInfos.find(type) != configInfos.end()) {
65 return configInfos[type];
66 }
67 return GetLogConfigFromFile(type);
68 }
69
GetLogConfigFromFile(const std::string & type)70 std::shared_ptr<ConfigInfo> HiviewLogConfigManager::GetLogConfigFromFile(const std::string& type)
71 {
72 HIVIEW_LOGI("read log config from file, type: %{public}s", type.c_str());
73 Json::Value jsonRoot = ParseJsonFile(CONFIG_FILE_PATH);
74 if (jsonRoot.empty() || !jsonRoot.isObject()) {
75 HIVIEW_LOGW("no valid log config file.");
76 return nullptr;
77 }
78 if (!jsonRoot.isMember(type)) {
79 HIVIEW_LOGW("no such type: %{public}s.", type.c_str());
80 return nullptr;
81 }
82 if (!IsStringMember(jsonRoot[type], FILE_PATH_KEY)) {
83 HIVIEW_LOGW("no file path tag.");
84 return nullptr;
85 }
86 std::string path(jsonRoot[type][FILE_PATH_KEY].asString());
87 if (path.empty()) {
88 HIVIEW_LOGW("path is empty.");
89 return nullptr;
90 }
91 if (path[path.size() - 1] != '/') {
92 path.append("/"); // add slash at end of dir for simple use
93 }
94 auto configInfoPtr = std::make_shared<ConfigInfo>(path);
95 if (IsBoolMember(jsonRoot[type], READ_ONLY_KEY)) {
96 configInfoPtr->isReadOnly = jsonRoot[type][READ_ONLY_KEY].asBool();
97 }
98 configInfos.insert(std::make_pair(type, configInfoPtr));
99 return configInfoPtr;
100 }
101 } // namespace HiviewDFX
102 } // namespace OHOS