/** * set log filter all parameter * * @param level level * @param tag tag * @param keyword keyword */ void elog_set_filter(uint8_t level, const char *tag, const char *keyword) { ELOG_ASSERT(level <= ELOG_LVL_VERBOSE); elog_set_filter_lvl(level); elog_set_filter_tag(tag); elog_set_filter_kw(keyword); }
/** * get format enabled * * @param level level * @param set format set * * @return enable or disable */ static bool get_fmt_enabled(uint8_t level, size_t set) { ELOG_ASSERT(level <= ELOG_LVL_VERBOSE); if (elog.enabled_fmt_set[level] & set) { return true; } else { return false; } }
/** * Write log to flash. The flash write use buffer mode. * * @param log log * @param size log size */ void elog_flash_write(const char *log, size_t size) { #ifdef ELOG_FLASH_USING_BUF_MODE size_t write_size = 0, write_index = 0; #else size_t write_size_temp = 0; EfErrCode result = EF_NO_ERR; /* write some '\r' for word alignment */ char write_overage_c[4] = { '\r', '\r', '\r', '\r' }; #endif /* must be call this function after initialize OK */ ELOG_ASSERT(init_ok); /* lock flash log buffer */ log_buf_lock(); #ifdef ELOG_FLASH_USING_BUF_MODE while (true) { if (cur_buf_size + size > ELOG_FLASH_BUF_SIZE) { write_size = ELOG_FLASH_BUF_SIZE - cur_buf_size; memcpy(log_buf + cur_buf_size, log + write_index, write_size); write_index += write_size; size -= write_size; cur_buf_size += write_size; /* unlock flash log buffer */ log_buf_unlock(); /* write all buffered log to flash, cur_buf_size will reset */ elog_flash_flush(); /* lock flash log buffer */ log_buf_lock(); } else { memcpy(log_buf + cur_buf_size, log + write_index, size); cur_buf_size += size; break; } } #else /* calculate the word alignment write size */ write_size_temp = size / 4 * 4; /* write log to flash */ result = ef_log_write((uint32_t *) log, write_size_temp); /* write last word alignment data */ if ((result == EF_NO_ERR) && (write_size_temp != size)) { memcpy(write_overage_c, log + write_size_temp, size - write_size_temp); ef_log_write((uint32_t *) write_overage_c, 4); } #endif /* unlock flash log buffer */ log_buf_unlock(); }
/** * Elog demo */ static void test_elog(void) { /* output all saved log from flash */ elog_flash_output_all(); /* test log output for all level */ log_a("Hello EasyLogger!"); log_e("Hello EasyLogger!"); log_w("Hello EasyLogger!"); log_i("Hello EasyLogger!"); log_d("Hello EasyLogger!"); log_v("Hello EasyLogger!"); elog_raw("Hello EasyLogger!"); /* trigger assert. Now will run elog_user_assert_hook. All log information will save to flash. */ ELOG_ASSERT(0); }
/** * EasyLogger flash log plugin initialize. * * @return result */ ElogErrCode elog_flash_init(void) { ElogErrCode result = ELOG_NO_ERR; /* buffer size must be word alignment */ ELOG_ASSERT(ELOG_FLASH_BUF_SIZE % 4 == 0) #ifdef ELOG_FLASH_USING_BUF_MODE /* initialize current flash log buffer write position */ cur_buf_size = 0; #endif /* port initialize */ elog_flash_port_init(); /* initialize OK */ init_ok = true; return result; }
/** * write all buffered log to flash */ void elog_flash_flush(void) { size_t write_overage_size = 0; /* must be call this function after initialize OK */ ELOG_ASSERT(init_ok); /* lock flash log buffer */ log_buf_lock(); /* flash write is word alignment */ if (cur_buf_size % 4 != 0) { write_overage_size = 4 - (cur_buf_size % 4); } /* fill '\r' for word alignment */ memset(log_buf + cur_buf_size, '\r', write_overage_size); /* write all buffered log to flash */ ef_log_write((uint32_t *) log_buf, cur_buf_size + write_overage_size); /* reset position */ cur_buf_size = 0; /* unlock flash log buffer */ log_buf_unlock(); }
/** * Read and output log which saved in flash. * * @param index index for saved log. * Minimum index is 0. * Maximum index is log used flash total size - 1. * @param size */ void elog_flash_outout(size_t index, size_t size) { /* 128 bytes buffer */ uint32_t buf[32] = { 0 }; size_t log_total_size = ef_log_get_used_size(); size_t buf_szie = sizeof(buf); size_t read_size = 0, read_overage_size = 0; if (index + size > log_total_size) { log_i("The output position and size is out of bound. The max size is %d.", log_total_size); return; } /* must be call this function after initialize OK */ ELOG_ASSERT(init_ok); /* lock flash log buffer */ log_buf_lock(); /* Output all flash saved log. It will use filter */ while (true) { if (index + read_size + buf_szie < log_total_size) { ef_log_read(index + read_size, buf, buf_szie); elog_flash_port_output((const char*)buf, buf_szie); read_size += buf_szie; } else { /* flash read is word alignment */ if ((log_total_size - index - read_size) % 4 == 0) { read_overage_size = 0; } else { read_overage_size = 4 - ((log_total_size - index - read_size) % 4); } ef_log_read(index + read_size - read_overage_size, buf, log_total_size - index - read_size + read_overage_size); elog_flash_port_output((const char*) buf + read_overage_size, log_total_size - index - read_size); /* output newline sign */ elog_flash_port_output(ELOG_NEWLINE_SIGN, strlen(ELOG_NEWLINE_SIGN)); break; } } /* unlock flash log buffer */ log_buf_unlock(); }
/** * clean all log which in flash and ram buffer */ void elog_flash_clean(void) { EfErrCode clean_result = EF_NO_ERR; /* must be call this function after initialize OK */ ELOG_ASSERT(init_ok); /* lock flash log buffer */ log_buf_lock(); /* clean all log which in flash */ clean_result = ef_log_clean(); #ifdef ELOG_FLASH_USING_BUF_MODE /* reset position */ cur_buf_size = 0; #endif /* unlock flash log buffer */ log_buf_unlock(); if(clean_result == EF_NO_ERR) { log_i("All logs which in flash is clean OK."); } else { log_e("Clean logs which in flash has an error!"); } }
/** * set output enable or disable * * @param enabled TRUE: enable FALSE: disable */ void elog_set_output_enabled(bool enabled) { ELOG_ASSERT((enabled == false) || (enabled == true)); elog.output_enabled = enabled; }
/** * output the log * * @param level level * @param tag tag * @param file file name * @param func function name * @param line line number * @param format output format * @param ... args * */ void elog_output(uint8_t level, const char *tag, const char *file, const char *func, const long line, const char *format, ...) { size_t tag_len = strlen(tag), log_len = 0, newline_len = strlen(ELOG_NEWLINE_SIGN), slog_len = 0; char line_num[ELOG_LINE_NUM_MAX_LEN + 1] = { 0 }; char tag_sapce[ELOG_FILTER_TAG_MAX_LEN / 2 + 1] = { 0 }; va_list args; int fmt_result; ELOG_ASSERT(level <= ELOG_LVL_VERBOSE); /* check output enabled */ if (!elog.output_enabled) { return; } /* level filter */ if (level > elog.filter.level) { return; } else if (!strstr(tag, elog.filter.tag)) { /* tag filter */ //TODO 可以考虑采用KMP及朴素模式匹配字符串,提升性能 return; } slog.level = level; strncpy(slog.tag, tag, sizeof(tag) - 1); /* args point to the first variable parameter */ va_start(args, format); /* lock output */ output_lock(); /* package level info */ if (get_fmt_enabled(level, ELOG_FMT_LVL)) { log_len += elog_strcpy(log_len, log_buf + log_len, level_output_info[level]); } /* package tag info */ if (get_fmt_enabled(level, ELOG_FMT_TAG)) { log_len += elog_strcpy(log_len, log_buf + log_len, tag); /* if the tag length is less than 50% ELOG_FILTER_TAG_MAX_LEN, then fill space */ if (tag_len <= ELOG_FILTER_TAG_MAX_LEN / 2) { memset(tag_sapce, ' ', ELOG_FILTER_TAG_MAX_LEN / 2 - tag_len); log_len += elog_strcpy(log_len, log_buf + log_len, tag_sapce); } log_len += elog_strcpy(log_len, log_buf + log_len, " "); } /* package time, process and thread info */ if (get_fmt_enabled(level, ELOG_FMT_TIME | ELOG_FMT_P_INFO | ELOG_FMT_T_INFO)) { log_len += elog_strcpy(log_len, log_buf + log_len, "["); /* package time info */ if (get_fmt_enabled(level, ELOG_FMT_TIME)) { strncpy(slog.time, elog_port_get_time(), sizeof(slog.time) - 1); log_len += elog_strcpy(log_len, log_buf + log_len, slog.time); if (get_fmt_enabled(level, ELOG_FMT_P_INFO | ELOG_FMT_T_INFO)) { log_len += elog_strcpy(log_len, log_buf + log_len, " "); } } /* package process info */ if (get_fmt_enabled(level, ELOG_FMT_P_INFO)) { log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_p_info()); if (get_fmt_enabled(level, ELOG_FMT_T_INFO)) { log_len += elog_strcpy(log_len, log_buf + log_len, " "); } } /* package thread info */ if (get_fmt_enabled(level, ELOG_FMT_T_INFO)) { log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_t_info()); } log_len += elog_strcpy(log_len, log_buf + log_len, "] "); } /* package file directory and name, function name and line number info */ if (get_fmt_enabled(level, ELOG_FMT_DIR | ELOG_FMT_FUNC | ELOG_FMT_LINE)) { log_len += elog_strcpy(log_len, log_buf + log_len, "("); /* package time info */ if (get_fmt_enabled(level, ELOG_FMT_DIR)) { log_len += elog_strcpy(log_len, log_buf + log_len, file); if (get_fmt_enabled(level, ELOG_FMT_FUNC)) { log_len += elog_strcpy(log_len, log_buf + log_len, " "); } else if (get_fmt_enabled(level, ELOG_FMT_LINE)) { log_len += elog_strcpy(log_len, log_buf + log_len, ":"); } } /* package process info */ if (get_fmt_enabled(level, ELOG_FMT_FUNC)) { log_len += elog_strcpy(log_len, log_buf + log_len, func); if (get_fmt_enabled(level, ELOG_FMT_LINE)) { log_len += elog_strcpy(log_len, log_buf + log_len, ":"); } } /* package thread info */ if (get_fmt_enabled(level, ELOG_FMT_LINE)) { //TODO snprintf资源占用可能较高,待优化 snprintf(line_num, ELOG_LINE_NUM_MAX_LEN, "%ld", line); log_len += elog_strcpy(log_len, log_buf + log_len, line_num); } log_len += elog_strcpy(log_len, log_buf + log_len, ")"); } /* add space and colon sign */ if (log_len != 0) { log_len += elog_strcpy(log_len, log_buf + log_len, ": "); } /* package other log data to buffer. '\0' must be added in the end by vsnprintf. */ fmt_result = vsnprintf(log_buf + log_len, ELOG_BUF_SIZE - log_len - newline_len + 1, format, args); slog_len += strlen(format); vsnprintf(slog.lograw, sizeof(slog.lograw) - slog_len - 1, format, args); va_end(args); /* keyword filter */ if (!strstr(log_buf, elog.filter.keyword)) { //TODO 可以考虑采用KMP及朴素模式匹配字符串,提升性能 /* unlock output */ output_unlock(); return; } /* package newline sign */ if ((fmt_result > -1) && (fmt_result + log_len + newline_len <= ELOG_BUF_SIZE)) { log_len += fmt_result; log_len += elog_strcpy(log_len, log_buf + log_len, ELOG_NEWLINE_SIGN); } else { /* copy newline sign */ strcpy(log_buf - newline_len, ELOG_NEWLINE_SIGN); } /* output log */ elog_port_output(log_buf, log_len); /* unlock output */ output_unlock(); }
/** * set log filter's level * * @param level level */ void elog_set_filter_lvl(uint8_t level) { ELOG_ASSERT(level <= ELOG_LVL_VERBOSE); elog.filter.level = level; }
/** * set log output format. only enable or disable * * @param level level * @param set format set */ void elog_set_fmt(uint8_t level, size_t set) { ELOG_ASSERT(level <= ELOG_LVL_VERBOSE); elog.enabled_fmt_set[level] = set; }