diff --git a/hisysevent.yaml b/hisysevent.yaml index 38bcc4645907ba9c3c4bb41f214e6da1a9f306ae..31793347e7ae8b767788918b77774442b63b561a 100644 --- a/hisysevent.yaml +++ b/hisysevent.yaml @@ -17,6 +17,22 @@ SPAWN_CHILD_PROCESS_FAIL: __BASE: {type: FAULT, level: CRITICAL, desc: Spawn Child Process Fail} PROCESS_NAME: {type: STRING, desc: Process Name} ERROR_CODE: {type: INT32, desc: Error Code} + SPAWN_RESULT : {type: INT32, desc: Process Spawn Result} + +SPAWN_MESSAGE_TYPE: + __BASE: {type: BEHAVIOR, level: CRITICAL, desc: Spawn Socket Message Info} + MSG_TYPE: {type: INT32, desc: Message Type} + MSG_RESULT: {type: INT32, desc: Messge Result} + MSG_PID : {type: INT32, desc: Message Pid} + +SPAWN_KEY_EVENT: + __BASE: {type: BEHAVIOR, level: CRITICAL, desc: Spawn Key Event Finish} + EVENT_NAME: {type: STRING, desc: Event Name} + +SPAWN_PROCESS_INFO: + __BASE: {type: BEHAVIOR, level: CRITICAL, desc: Special Spawn Message Info} + PROCESS_NAME: {type: STRING, desc: Process Name} + PROCESS_FLAGS: {type: STRING, desc: Process Flags} SPAWN_PROCESS_DURATION: __BASE: {type: STATISTIC, level: CRITICAL, desc: Boot Process Duration} @@ -24,4 +40,9 @@ SPAWN_PROCESS_DURATION: MINDURATION: {type: INT64, desc: Min Spawn Process Duration} TOTALDURATION: {type: INT64, desc: Total Spawn Process Duration} EVENTCOUNT: {type: INT64, desc: Total Spawn Process Count} - STAGE: {type: STRING, desc: Boot Stage Or BootFinished Stage} \ No newline at end of file + STAGE: {type: STRING, desc: Boot Stage Or BootFinished Stage} + +SPAWN_FUNC_DURATION: + __BASE: {type: STATISTIC, level: CRITICAL, desc: Function Duration} + FUNC_NAME: {type: STRING, desc: Func Name} + DURATION: {type: INT64, desc: Function Duration} \ No newline at end of file diff --git a/modules/common/BUILD.gn b/modules/common/BUILD.gn index 7e678381ee77bb6cd431def2b3fdb9e30091579c..aac94158f837f081196f3600b0eeb38d62136eff 100644 --- a/modules/common/BUILD.gn +++ b/modules/common/BUILD.gn @@ -81,6 +81,13 @@ ohos_shared_library("appspawn_common") { defines += [ "APPSPAWN_SANDBOX_NEW" ] } + if (appspawn_report_event) { + defines += [ "APPSPAWN_HISYSEVENT" ] + external_deps += [ "hisysevent:libhisysevent" ] + include_dirs += [ "${appspawn_path}/modules/sysevent" ] + sources += [ "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp" ] + } + subsystem_name = "${subsystem_name}" part_name = "${part_name}" install_enable = true diff --git a/modules/common/appspawn_common.c b/modules/common/appspawn_common.c index 6ce56b278bdf850bffdb602b9da410848a4ed464..3358324ca2dc3e4bb69ca5c4d5a24645dba6b66a 100644 --- a/modules/common/appspawn_common.c +++ b/modules/common/appspawn_common.c @@ -47,6 +47,9 @@ #include "parameter.h" #include "securec.h" +#ifdef APPSPAWN_HISYSEVENT +#include "hisysevent_adapter.h" +#endif #ifdef CODE_SIGNATURE_ENABLE // for xpm #include "code_sign_attr_utils.h" #endif @@ -401,6 +404,56 @@ static int SpawnSetAppEnv(AppSpawnMgr *content, AppSpawningCtx *property) APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); return 0; } +#ifdef APPSPAWN_HISYSEVENT +#define MAX_DATA_SIZE 128 +static bool CheckReportMessage(AppSpawningCtx *property) +{ + if (CheckAppMsgFlagsSet(property, APP_FLAGS_COLD_BOOT) || + CheckAppMsgFlagsSet(property, APP_FLAGS_TSAN_ENABLED) || + CheckAppMsgFlagsSet(property, APP_FLAGS_ASANENABLED) || + CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE) || + CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX) || + CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_NETWORK)) { + return true; + } + return false; +} + +static int ReportProcessInfo(AppSpawnMgr *content, AppSpawningCtx *property) +{ + if (property == NULL || property->message == NULL) { + APPSPAWN_LOGE("Invalid parameters"); + return APPSPAWN_MSG_INVALID; + } + if (!CheckReportMessage(property)) { + return 0; + } + AppSpawnMsgFlags *msgFlags = (AppSpawnMsgFlags *)GetAppSpawnMsgInfo(property->message, TLV_MSG_FLAGS); + if (msgFlags == NULL || msgFlags->count <= 0) { + APPSPAWN_LOGE("Invalid Flags message"); + return APPSPAWN_MSG_INVALID; + } + char *extData = (char *)calloc(1, MAX_DATA_SIZE); + if (extData == NULL) { + APPSPAWN_LOGE("calloc failed %{public}d", MAX_DATA_SIZE); + return APPSPAWN_BUFFER_NOT_ENOUGH; + } + for (uint32_t i = 0; i < msgFlags->count; i++) { + int ret = snprintf_s(extData + strlen(extData), sizeof(extData) - strlen(extData), + sizeof(extData) - strlen(extData) -1, "%x,", msgFlags->flags[i]); + if (ret <= 0) { + free(extData); + APPSPAWN_LOGE("snprintf_s failed %{public}d, %{public}d", ret, errno); + return APPSPAWN_SYSTEM_ERROR; + } + } + + ReportChildProcessInfo(GetBundleName(property), extData); + free(extData); + return 0; +} + +#endif static int SpawnEnableCache(AppSpawnMgr *content, AppSpawningCtx *property) { @@ -589,6 +642,9 @@ MODULE_CONSTRUCTOR(void) AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_HIGHEST, SpawnGetSpawningFlag); AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_HIGHEST, SpawnInitSpawningEnv); AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_COMMON + 1, SpawnSetAppEnv); +#ifdef APPSPAWN_HISYSEVENT + AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_COMMON + 1, ReportProcessInfo); +#endif AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_HIGHEST, SpawnEnableCache); AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_PROPERTY, SpawnSetProperties); AddAppSpawnHook(STAGE_CHILD_POST_RELY, HOOK_PRIO_HIGHEST, SpawnComplete); diff --git a/modules/sandbox/sandbox_utils.cpp b/modules/sandbox/sandbox_utils.cpp index 1a89e6b0cda84809eb943b3ccea309780002c544..691dcc5026e0a57b38e99cfd29223cbec9bd3683 100644 --- a/modules/sandbox/sandbox_utils.cpp +++ b/modules/sandbox/sandbox_utils.cpp @@ -208,6 +208,10 @@ std::vector &SandboxUtils::GetJsonConfig(SandboxConfigType type) static void MakeDirRecursive(const std::string &path, mode_t mode) { +#ifdef APPSPAWN_HISYSEVENT + struct timespec startClock = {0}; + clock_gettime(CLOCK_MONOTONIC_COARSE, &startClock); +#endif size_t size = path.size(); if (size == 0) { return; @@ -223,6 +227,14 @@ static void MakeDirRecursive(const std::string &path, mode_t mode) return, "errno is %{public}d, mkdir %{public}s failed", errno, dir.c_str()); #endif } while (index < size); + +#ifdef APPSPAWN_HISYSEVENT + struct timespec endClock = {0}; + clock_gettime(CLOCK_MONOTONIC_COARSE, &endClock); + uint64_t diff = DiffTime(&startClock, &endClock); + APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, + ReportSpawnFuncDuration("MakeDirRecursive", diff)); +#endif } static bool CheckDirRecursive(const std::string &path) @@ -308,6 +320,9 @@ int32_t SandboxUtils::DoAppSandboxMountOnce(const char *originPath, const char * clock_gettime(CLOCK_MONOTONIC_COARSE, &mountEnd); uint64_t diff = DiffTime(&mountStart, &mountEnd); APPSPAWN_CHECK_ONLY_LOG(diff < MAX_MOUNT_TIME, "mount %{public}s time %{public}" PRId64 " us", originPath, diff); +#ifdef APPSPAWN_HISYSEVENT + APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, ReportSpawnFuncDuration("MOUNT", diff)); +#endif if (ret != 0) { APPSPAWN_LOGI("errno is: %{public}d, bind mount %{public}s to %{public}s", errno, originPath, destinationPath); std::string originPathStr = originPath == nullptr ? "" : originPath; @@ -1646,9 +1661,19 @@ int32_t SandboxUtils::ChangeCurrentDir(std::string &sandboxPackagePath, const st return ret; } -static inline int EnableSandboxNamespace(AppSpawningCtx *appProperty, uint32_t sandboxNsFlags) +static int EnableSandboxNamespace(AppSpawningCtx *appProperty, uint32_t sandboxNsFlags) { +#ifdef APPSPAWN_HISYSEVENT + struct timespec startClock = {0}; + clock_gettime(CLOCK_MONOTONIC_COARSE, &startClock); +#endif int rc = unshare(sandboxNsFlags); +#ifdef APPSPAWN_HISYSEVENT + struct timespec endClock = {0}; + clock_gettime(CLOCK_MONOTONIC_COARSE, &endClock); + uint64_t diff = DiffTime(&startClock, &endClock); + APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, ReportSpawnFuncDuration("unshare", diff)); +#endif APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", GetBundleName(appProperty)); if ((sandboxNsFlags & CLONE_NEWNET) == CLONE_NEWNET) { diff --git a/modules/sysevent/hisysevent_adapter.cpp b/modules/sysevent/hisysevent_adapter.cpp index 8e1dbad17a42251afd35f8ab1d8ed84fb044b0b0..a8d1ee2f299497025092bfe376dcb9767bb902b2 100644 --- a/modules/sysevent/hisysevent_adapter.cpp +++ b/modules/sysevent/hisysevent_adapter.cpp @@ -19,13 +19,30 @@ using namespace OHOS::HiviewDFX; namespace { -// event -constexpr const char* SPAWN_PROCESS_DURATION = "SPAWN_PROCESS_DURATION"; +// fail event constexpr const char* SPAWN_CHILD_PROCESS_FAIL = "SPAWN_CHILD_PROCESS_FAIL"; +// behavior event +constexpr const char* SPAWN_MESSAGE_TYPE = "SPAWN_MESSAGE_TYPE"; +constexpr const char* SPAWN_PROCESS_INFO = "SPAWN_PROCESS_INFO"; +constexpr const char* SPAWN_KEY_EVENT = "SPAWN_KEY_EVENT"; + +// statistic event +constexpr const char* SPAWN_PROCESS_DURATION = "SPAWN_PROCESS_DURATION"; +constexpr const char* SPAWN_FUNC_DURATION = "SPAWN_FUNC_DURATION"; + // param constexpr const char* PROCESS_NAME = "PROCESS_NAME"; constexpr const char* ERROR_CODE = "ERROR_CODE"; +constexpr const char* SPAWN_RESULT = "SPAWN_RESULT"; +constexpr const char* EVENT_NAME = "EVENT_NAME"; +constexpr const char* MSG_RESULT = "MSG_RESULT"; +constexpr const char* MSG_PID = "MSG_PID"; +constexpr const char* MSG_TYPE = "MSG_TYPE"; +constexpr const char* EXT_DATA = "EXT_DATA"; +constexpr const char* FUNC_NAME = "FUNC_NAME"; +constexpr const char* DURATION = "DURATION"; + constexpr const char* MAXDURATION = "MAXDURATION"; constexpr const char* MINDURATION = "MINDURATION"; constexpr const char* TOTALDURATION = "TOTALDURATION"; @@ -121,14 +138,48 @@ AppSpawnHisyseventInfo *InitHisyseventTimer(void) return hisyseventInfo; } -void ReportSpawnChildProcessFail(const char* processName, int32_t errorCode) +void ReportSpawnChildProcessFail(const char* processName, int32_t errorCode, int32_t spawnResult) { int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_CHILD_PROCESS_FAIL, HiSysEvent::EventType::FAULT, PROCESS_NAME, processName, - ERROR_CODE, errorCode); + ERROR_CODE, errorCode, + SPAWN_RESULT, spawnResult); + if (ret != 0) { + APPSPAWN_LOGE("ReportSpawnChildProcessFail error, ret: %{public}d", ret); + } +} + +void ReportSpawnMessageType(uint32_t msgType, int result, pid_t pid) +{ + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_MESSAGE_TYPE, + HiSysEvent::EventType::BEHAVIOR, + MSG_TYPE, msgType, + MSG_RESULT, result, + MSG_PID, pid); if (ret != 0) { - APPSPAWN_LOGE("HiSysEventWrite error, ret: %{public}d", ret); + APPSPAWN_LOGE("ReportSpawnMessageType error, ret: %{public}d", ret); + } +} + +void ReportKeyEvent(const char *eventName) +{ + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_KEY_EVENT, + HiSysEvent::EventType::BEHAVIOR, + EVENT_NAME, eventName); + if (ret != 0) { + APPSPAWN_LOGE("ReportKeyEvent error, ret: %{public}d", ret); + } +} + +void ReportChildProcessInfo(const char *processName, const char *data) +{ + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_PROCESS_INFO, + HiSysEvent::EventType::BEHAVIOR, + PROCESS_NAME, processName, + EXT_DATA, data); + if (ret != 0) { + APPSPAWN_LOGE("ReportChildProcessInfo error, ret: %{public}d", ret); } } @@ -142,7 +193,17 @@ void ReportSpawnProcessDuration(AppSpawnHisysevent *hisysevent, const char* stag EVENTCOUNT, hisysevent->eventCount, STAGE, stage); if (ret != 0) { - APPSPAWN_LOGE("HiSysEventWrite error, ret: %{public}d", ret); + APPSPAWN_LOGE("ReportSpawnProcessDuration error, ret: %{public}d", ret); + } +} + +void ReportSpawnFuncDuration(const char* funcName, uint64_t duration) +{ + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_FUNC_DURATION, + HiSysEvent::EventType::STATISTIC, + FUNC_NAME, funcName, DURATION, duration); + if (ret != 0) { + APPSPAWN_LOGE("ReportSpawnFuncDuration error, ret: %{public}d", ret); } } diff --git a/modules/sysevent/hisysevent_adapter.h b/modules/sysevent/hisysevent_adapter.h index 89f3fbacc5889a3a81a2edd6a9d75d801a29cb68..74cb70d1ff655ac9ae036cd8575fed14e91537cb 100644 --- a/modules/sysevent/hisysevent_adapter.h +++ b/modules/sysevent/hisysevent_adapter.h @@ -87,13 +87,22 @@ typedef struct { AppSpawnHisysevent bootEvent; // bootStage AppSpawnHisysevent manualEvent; // bootFinished } AppSpawnHisyseventInfo; +#define FUNC_REPORT_DURATION (10 * 1000) +#define SPAWN_REPORT_DURATION (100 * 1000) +#define UNLOCK_SUCCESS "UNLOCK_SUCCESS" AppSpawnHisyseventInfo *InitHisyseventTimer(void); AppSpawnHisyseventInfo *GetAppSpawnHisyseventInfo(void); void AddStatisticEventInfo(AppSpawnHisyseventInfo *hisyseventInfo, uint32_t duration, bool stage); void DeleteHisyseventInfo(AppSpawnHisyseventInfo *hisyseventInfo); -void ReportSpawnChildProcessFail(const char* processName, int32_t errorCode); +void ReportSpawnChildProcessFail(const char* processName, int32_t errorCode, int32_t spawnResult); +void ReportSpawnMessageType(uint32_t msgType, int result, pid_t pid); +void ReportKeyEvent(const char *eventName); + +void ReportChildProcessInfo(const char *processName, const char *data); +void ReportSpawnProcessDuration(AppSpawnHisysevent *hisysevent, const char* stage); +void ReportSpawnFuncDuration(const char* funcName, uint64_t duration); void ReportSpawnStatisticDuration(const TimerHandle taskHandle, void* content); #ifdef __cplusplus diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 954e9bc709707cb914640ba8d8a67cea13f7f1aa..a37f9088e3f283c4d2209b92cf135cccce533712 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -267,6 +267,11 @@ static int SendResponse(const AppSpawnConnection *connection, const AppSpawnMsg { APPSPAWN_LOGV("SendResponse connectionId: %{public}u result: 0x%{public}x pid: %{public}d", connection->connectionId, result, pid); +#ifdef APPSPAWN_HISYSEVENT + if (msg->msgType != MSG_APP_SPAWN) { + ReportSpawnMessageType(msg->msgType, result, pid); + } +#endif uint32_t bufferSize = sizeof(AppSpawnResponseMsg); BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), bufferSize); AppSpawnResponseMsg *buffer = (AppSpawnResponseMsg *)LE_GetBufferInfo(handle, NULL, &bufferSize); @@ -943,7 +948,7 @@ static void WaitChildDied(pid_t pid) APPSPAWN_LOGI("Child process %{public}s fail \'child crash \'pid %{public}d appId: %{public}d", processName, property->pid, property->client.id); #ifdef APPSPAWN_HISYSEVENT - ReportSpawnChildProcessFail(processName, ERR_APPSPAWN_CHILD_CRASH); + ReportSpawnChildProcessFail(processName, ERR_APPSPAWN_CHILD_CRASH, APPSPAWN_CHILD_CRASH); #endif if (property->client.id == g_lastDiedAppId + 1) { g_crashTimes++; @@ -958,7 +963,7 @@ static void WaitChildDied(pid_t pid) if (g_crashTimes >= MAX_CRASH_TIME) { APPSPAWN_LOGW("Continuous failures in spawning the app, restart appspawn"); #ifdef APPSPAWN_HISYSEVENT - ReportSpawnChildProcessFail(processName, ERR_APPSPAWN_MAX_FAILURES_EXCEEDED); + ReportKeyEvent("APPSPAWN_MAX_FAILURES_EXCEEDED"); #endif StopAppSpawn(); } @@ -977,7 +982,7 @@ static void WaitChildTimeout(const TimerHandle taskHandle, void *context) kill(property->pid, SIGKILL); } #ifdef APPSPAWN_HISYSEVENT - ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_TIMEOUT); + ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_TIMEOUT, APPSPAWN_SPAWN_TIMEOUT); #endif SendResponse(property->message->connection, &property->message->msgHeader, APPSPAWN_SPAWN_TIMEOUT, 0); DeleteAppSpawningCtx(property); @@ -993,7 +998,7 @@ static int ProcessChildFdCheck(int fd, AppSpawningCtx *property) if (result != 0) { #ifdef APPSPAWN_HISYSEVENT - ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_FAIL); + ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_FAIL, result); #endif SendResponse(property->message->connection, &property->message->msgHeader, result, property->pid); DeleteAppSpawningCtx(property); @@ -1038,6 +1043,8 @@ static void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_ if (appspawnMgr != NULL) { AddStatisticEventInfo(appspawnMgr->hisyseventInfo, spawnProcessDuration, IsBootFinished()); } + uint64_t diff = DiffTime(&appInfo->spawnStart, &appInfo->spawnEnd); + APPSPAWN_CHECK_ONLY_EXPER(diff < SPAWN_REPORT_DURATION, ReportSpawnFuncDuration("SPAWNCHILD", diff)); #endif } @@ -1687,6 +1694,9 @@ static void ProcessAppSpawnLockStatusMsg(AppSpawnMsgNode *message) APPSPAWN_CHECK(ret == 0, return, "failed to set lockstatus param value ret %{public}d", ret); #ifndef APPSPAWN_SANDBOX_NEW if (strcmp(userLockStatus, "0") == 0) { +#ifdef APPSPAWN_HISYSEVENT + ReportKeyEvent(UNLOCK_SUCCESS); +#endif ServerStageHookExecute(STAGE_SERVER_LOCK, GetAppSpawnContent()); } #endif