1 /*
2  * Copyright (c) 2024 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 #include "daily_config.h"
16 
17 #include "hiview_logger.h"
18 #include "parameter_ex.h"
19 
20 namespace OHOS {
21 namespace HiviewDFX {
22 DEFINE_LOG_TAG("DailyController");
23 namespace {
24 constexpr int64_t INVALID_INT = -1;
25 constexpr int32_t TYPE_FAULT = 1;
26 constexpr int32_t TYPE_STATISTIC = 2;
27 constexpr int32_t TYPE_SECURITY = 3;
28 constexpr int32_t TYPE_BEHAVIOR = 4;
29 }
30 
DailyConfig(const std::string & configPath)31 DailyConfig::DailyConfig(const std::string& configPath)
32 {
33     isValid_ = Parse(configPath);
34 }
35 
Parse(const std::string & configPath)36 bool DailyConfig::Parse(const std::string& configPath)
37 {
38     auto root = CJsonUtil::ParseJsonRoot(configPath);
39     if (root == nullptr) {
40         HIVIEW_LOGW("failed to parse config file=%{public}s", configPath.c_str());
41         return false;
42     }
43     std::string version = Parameter::GetVersionStr();
44     auto config = CJsonUtil::GetObjectValue(root, version);
45     if (config == nullptr) {
46         HIVIEW_LOGW("failed to parse config file=%{public}s, version=%{public}s",
47             configPath.c_str(), version.c_str());
48         cJSON_Delete(root);
49         return false;
50     }
51     bool ret = ParseCommonThreshold(config) && ParseCustomThreshold(config);
52     cJSON_Delete(root);
53     return ret;
54 }
55 
ParseCommonThreshold(const cJSON * config)56 bool DailyConfig::ParseCommonThreshold(const cJSON* config)
57 {
58     const std::string comKey = "Common";
59     auto comConfig = CJsonUtil::GetObjectValue(config, comKey);
60     if (comConfig == nullptr) {
61         HIVIEW_LOGW("failed to parse common config");
62         return false;
63     }
64 
65     const std::unordered_map<std::string, int32_t> configMap = {
66         {"FAULT", TYPE_FAULT}, {"STATISTIC", TYPE_STATISTIC},
67         {"SECURITY", TYPE_SECURITY}, {"BEHAVIOR", TYPE_BEHAVIOR}
68     };
69     for (const auto& [key, value] : configMap) {
70         int32_t configValue = CJsonUtil::GetIntValue(comConfig, key, INVALID_INT);
71         if (configValue < 0) {
72             HIVIEW_LOGW("failed to parse common config, key=%{public}s", key.c_str());
73             return false;
74         }
75         commonThresholds_[value] = configValue;
76         HIVIEW_LOGD("parse common config, key=%{public}s, value=%{public}d", key.c_str(), configValue);
77     }
78     return true;
79 }
80 
ParseCustomThreshold(const cJSON * config)81 bool DailyConfig::ParseCustomThreshold(const cJSON* config)
82 {
83     const std::string customKey = "Custom";
84     auto customConfig = CJsonUtil::GetObjectValue(config, customKey);
85     if (customConfig == nullptr) {
86         HIVIEW_LOGW("failed to parse custom config");
87         return false;
88     }
89 
90     auto childConfig = customConfig->child;
91     while (childConfig) {
92         if (!ParseThresholdOfDomain(childConfig)) {
93             return false;
94         }
95         childConfig = childConfig->next;
96     }
97     return true;
98 }
99 
ParseThresholdOfDomain(const cJSON * config)100 bool DailyConfig::ParseThresholdOfDomain(const cJSON* config)
101 {
102     if (!cJSON_IsObject(config)) {
103         HIVIEW_LOGW("failed to parse domain config");
104         return false;
105     }
106 
107     std::string domain = config->string;
108     if (domain.empty()) {
109         HIVIEW_LOGW("failed to parse the domain");
110         return false;
111     }
112 
113     HIVIEW_LOGD("start to parse domain=%{public}s", domain.c_str());
114     auto childConfig = config->child;
115     while (childConfig) {
116         std::string name;
117         int32_t threshold = 0;
118         if (!ParseThresholdOfName(childConfig, name, threshold)) {
119             return false;
120         }
121         customThresholds_[std::make_pair(domain, name)] = threshold;
122         childConfig = childConfig->next;
123     }
124     return true;
125 }
126 
ParseThresholdOfName(const cJSON * config,std::string & name,int32_t & threshold)127 bool DailyConfig::ParseThresholdOfName(const cJSON* config, std::string& name, int32_t& threshold)
128 {
129     if (config->string == nullptr || strlen(config->string) == 0) {
130         HIVIEW_LOGW("failed to parse the name");
131         return false;
132     }
133     name = std::string(config->string);
134 
135     int32_t value = static_cast<int32_t>(config->valuedouble);
136     if (value < 0) {
137         HIVIEW_LOGW("failed to parse the value=%{public}d of name=%{public}s", value, name.c_str());
138         return false;
139     }
140     threshold = value;
141     HIVIEW_LOGD("parse name=%{public}s, value=%{public}d", name.c_str(), value);
142     return true;
143 }
144 
GetThreshold(const std::string & domain,const std::string name,int32_t type) const145 int32_t DailyConfig::GetThreshold(const std::string& domain, const std::string name, int32_t type) const
146 {
147     auto keyPair = std::make_pair(domain, name);
148     if (customThresholds_.find(keyPair) != customThresholds_.end()) {
149         return customThresholds_.at(keyPair);
150     }
151 
152     if (commonThresholds_.find(type) != commonThresholds_.end()) {
153         return commonThresholds_.at(type);
154     }
155 
156     return 0;
157 }
158 
IsValid() const159 bool DailyConfig::IsValid() const
160 {
161     return isValid_;
162 }
163 } // namespace HiviewDFX
164 } // namespace OHOS
165