• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 
16 #include "fault_logger_config.h"
17 
18 #include <algorithm>
19 #include <limits>
20 
21 #ifndef is_ohos_lite
22 #include "cJSON.h"
23 #endif
24 
25 #include "dfx_log.h"
26 #include "dfx_socket_request.h"
27 #include "file_ex.h"
28 
29 namespace OHOS {
30 namespace HiviewDFX {
31 
32 namespace {
33 #ifndef is_ohos_lite
34 constexpr const char* FAULTLOGGER_CONFIG_TAG = "FAULT_LOGGER_CONFIG";
35 constexpr const char* const CONFIG_FILE_PATH = "/system/etc/faultloggerd_config.json";
36 constexpr int32_t KB_TO_B = 10;
37 constexpr int32_t MAX_NUM_INT32 = std::numeric_limits<int32_t>::max();
38 
39 constexpr const char* const OVER_TIME_FILE_DELETE_ACTIVE = "ACTIVE";
40 constexpr const char* const OVER_SIZE_ACTION_DELETE = "DELETE";
41 
GetStringValueFromJson(const cJSON * json,std::string defaultValue="")42 std::string GetStringValueFromJson(const cJSON* json, std::string defaultValue = "")
43 {
44     if (!cJSON_IsString(json)) {
45         return defaultValue;
46     }
47     return json->valuestring;
48 }
49 
GetInt32ValueFromJson(const cJSON * json,int32_t defaultValue=0)50 int32_t GetInt32ValueFromJson(const cJSON* json, int32_t defaultValue = 0)
51 {
52     if (!cJSON_IsNumber(json)) {
53         return defaultValue;
54     }
55     return json->valueint;
56 }
57 
ParseSingleFileConfig(const cJSON * tempFile,std::vector<SingleFileConfig> & singleFileConfigs)58 void ParseSingleFileConfig(const cJSON* tempFile,  std::vector<SingleFileConfig>& singleFileConfigs)
59 {
60     if (tempFile == nullptr) {
61         DFXLOGE("%{public}s :: failed to Parse TempFileConfig", FAULTLOGGER_CONFIG_TAG);
62         return;
63     }
64     auto& tempFileConfig = singleFileConfigs.emplace_back();
65     tempFileConfig.type = GetInt32ValueFromJson(cJSON_GetObjectItem(tempFile, "type"));
66     tempFileConfig.fileNamePrefix = GetStringValueFromJson(cJSON_GetObjectItem(tempFile, "fileNamePrefix"));
67     int32_t maxFileSize = std::clamp(GetInt32ValueFromJson(cJSON_GetObjectItem(tempFile, "maxSingleFileSizeInKB")),
68                                      0, MAX_NUM_INT32);
69     tempFileConfig.maxSingleFileSize = static_cast<uint64_t>(maxFileSize) << KB_TO_B;
70     int32_t fileExistTime = GetInt32ValueFromJson(cJSON_GetObjectItem(tempFile, "fileExistTimeInSecond"), -1);
71     tempFileConfig.fileExistTime = std::clamp(fileExistTime, -1, MAX_NUM_INT32);
72     int32_t keeFileCount = GetInt32ValueFromJson(cJSON_GetObjectItem(tempFile, "keepFileCount"), -1);
73     tempFileConfig.keepFileCount = std::clamp(keeFileCount, -1, MAX_NUM_INT32);
74     int32_t maxFileCount = GetInt32ValueFromJson(cJSON_GetObjectItem(tempFile, "maxFileCount"), -1);
75     tempFileConfig.maxFileCount = std::clamp(maxFileCount, tempFileConfig.keepFileCount, MAX_NUM_INT32);
76     if (GetStringValueFromJson(cJSON_GetObjectItem(tempFile, "overTimeFileDeleteType")) ==
77         OVER_TIME_FILE_DELETE_ACTIVE) {
78         tempFileConfig.overTimeFileDeleteType = OverTimeFileDeleteType::ACTIVE;
79     }
80     if (GetStringValueFromJson(cJSON_GetObjectItem(tempFile, "overFileSizeAction")) ==
81         OVER_SIZE_ACTION_DELETE) {
82         tempFileConfig.overFileSizeAction = OverFileSizeAction::DELETE;
83     }
84 }
85 
ParseDirectoryConfig(const cJSON * json,DirectoryConfig & directoryConfig)86 void ParseDirectoryConfig(const cJSON* json, DirectoryConfig& directoryConfig)
87 {
88     if (json == nullptr) {
89         DFXLOGE("%{public}s :: failed to Parse directoryConfig", FAULTLOGGER_CONFIG_TAG);
90         return;
91     }
92     directoryConfig.tempFilePath = GetStringValueFromJson(cJSON_GetObjectItem(json, "tempFilePath"));
93     int32_t maxFileSize = std::clamp(GetInt32ValueFromJson(cJSON_GetObjectItem(json, "maxTempFilesSizeInKB")),
94                                      0, MAX_NUM_INT32);
95     directoryConfig.maxTempFilesSize = static_cast<uint64_t>(maxFileSize) << KB_TO_B;
96     int32_t configClearTime = GetInt32ValueFromJson(cJSON_GetObjectItem(json, "fileClearTimeAfterBootInSecond"));
97     directoryConfig.fileClearTimeAfterBoot = std::clamp(configClearTime, 0, MAX_NUM_INT32);
98     auto* tempFiles = cJSON_GetObjectItem(json, "tempFiles");
99     if (tempFiles != nullptr && cJSON_IsArray(tempFiles)) {
100         int arraySize = cJSON_GetArraySize(tempFiles);
101         for (int i = 0; i < arraySize; i++) {
102             ParseSingleFileConfig(cJSON_GetArrayItem(tempFiles, i), directoryConfig.singleFileConfigs);
103         }
104     }
105 }
106 #endif
107 
108 #ifdef FAULTLOGGERD_TEST
InitFaultloggerTestConfig(DirectoryConfig & directoryConfig)109 void InitFaultloggerTestConfig(DirectoryConfig& directoryConfig)
110 {
111     directoryConfig.tempFilePath = "/data/test/faultloggerd/temp";
112     constexpr uint64_t maxTempFilesSize = 10ull << 10; // 10KB
113     directoryConfig.maxTempFilesSize = maxTempFilesSize;
114     constexpr int32_t fileClearTimeAfterBoot = 3; // 3S
115     directoryConfig.fileClearTimeAfterBoot = fileClearTimeAfterBoot;
116     directoryConfig.singleFileConfigs = {
117         {
118             .type = FaultLoggerType::CPP_CRASH,
119             .fileNamePrefix = "cppcrash",
120             .maxSingleFileSize = 5 << 10, // 5KB
121             .fileExistTime = 60,
122             .keepFileCount = 5,
123             .maxFileCount = 7
124         },
125         {
126             .type = FaultLoggerType::JS_HEAP_SNAPSHOT,
127             .fileNamePrefix = "jsheap",
128             .maxSingleFileSize = 5 << 10, // 5KB
129             .overFileSizeAction = OverFileSizeAction::DELETE,
130             .fileExistTime = 3,
131             .overTimeFileDeleteType = OverTimeFileDeleteType::ACTIVE,
132             .keepFileCount = 5,
133             .maxFileCount = 7
134         },
135         {
136             .type = FaultLoggerType::LEAK_STACKTRACE,
137             .fileNamePrefix = "leakstack",
138             .overTimeFileDeleteType = OverTimeFileDeleteType::ACTIVE,
139             .keepFileCount = -1,
140             .maxFileCount = 2,
141         }
142     };
143 }
144 #endif
145 }
146 
GetInstance()147 FaultLoggerConfig& FaultLoggerConfig::GetInstance()
148 {
149     static FaultLoggerConfig faultLoggerConfig;
150     return faultLoggerConfig;
151 }
152 
153 #ifndef is_ohos_lite
FaultLoggerConfig()154 FaultLoggerConfig::FaultLoggerConfig()
155 {
156     std::string content;
157     OHOS::LoadStringFromFile(CONFIG_FILE_PATH, content);
158     cJSON* json = cJSON_Parse(content.c_str());
159     if (json == nullptr) {
160         DFXLOGE("%{public}s :: failed to parse json from the content of file(%{public}s).",
161                 FAULTLOGGER_CONFIG_TAG, CONFIG_FILE_PATH);
162     }
163     ParseDirectoryConfig(json, directoryConfig_);
164     cJSON_Delete(json);
165 #ifdef FAULTLOGGERD_TEST
166     InitFaultloggerTestConfig(directoryConfig_);
167 #endif
168 }
169 #else
FaultLoggerConfig()170 FaultLoggerConfig::FaultLoggerConfig()
171 {
172     directoryConfig_.tempFilePath = "/data/log/faultlog/temp";
173     constexpr uint64_t maxTempFilesSize = 2ull << 30; // 2GB
174     directoryConfig_.maxTempFilesSize = maxTempFilesSize;
175     constexpr int32_t fileClearTimeAfterBoot = 300; // 300s
176     directoryConfig_.fileClearTimeAfterBoot = fileClearTimeAfterBoot;
177     directoryConfig_.singleFileConfigs = {
178         {
179             .type = FaultLoggerType::CPP_CRASH,
180             .fileNamePrefix = "cppcrash",
181             .maxSingleFileSize = 2 << 20, // 2M
182             .keepFileCount = 20,
183             .maxFileCount = 40
184         },
185         {
186             .type = FaultLoggerType::CPP_STACKTRACE,
187             .fileNamePrefix = "stacktrace",
188             .maxSingleFileSize = 2 << 20, // 2M
189             .keepFileCount = 20,
190             .maxFileCount = 40
191         },
192         {
193             .type = FaultLoggerType::LEAK_STACKTRACE,
194             .fileNamePrefix = "leakstack",
195             .maxSingleFileSize = 512 << 10, // 512K
196             .fileExistTime = 60, // 60s
197             .keepFileCount = 20,
198             .maxFileCount = 40
199         },
200         {
201             .type = FaultLoggerType::JIT_CODE_LOG,
202             .fileNamePrefix = "jitcode",
203             .maxSingleFileSize = 128 << 10, // 128K
204             .fileExistTime = 60, // 60s
205             .keepFileCount = 20,
206             .maxFileCount = 40
207         }
208     };
209 #ifdef FAULTLOGGERD_TEST
210     InitFaultloggerTestConfig(directoryConfig_);
211 #endif
212 }
213 #endif
214 
GetTempFileConfig() const215 const DirectoryConfig& FaultLoggerConfig::GetTempFileConfig() const
216 {
217     return directoryConfig_;
218 }
219 } // namespace HiviewDFX
220 } // namespace OHOS
221