1
0
mirror of https://github.com/armink/EasyLogger.git synced 2025-01-19 07:42:52 +08:00

1、【增加】flash log插件,实现日志的flash存储功能。

Signed-off-by: armink <armink.ztl@gmail.com>
This commit is contained in:
armink 2015-06-10 12:04:35 +08:00
parent 58ef4d7be0
commit b88104085a
6 changed files with 368 additions and 49 deletions

View File

@ -4,18 +4,25 @@
# 1. 介绍 # 1. 介绍
EasyLogger是一款超轻量级(ROM<1.6K, RAM<0.3k)高性能的C日志库非常适合对资源敏感的嵌入式软件相比log4czlog这些知名的C日志库EasyLogger的功能更加简单提供给用户的接口更少但上手会很快非常适合应用于小型的非嵌入式软件EasyLogger主要特性如下 EasyLogger是一款超轻量级(ROM<1.6K, RAM<0.3k)高性能的C日志库非常适合对资源敏感的嵌入式软件相比log4czlog这些知名的C日志库EasyLogger的功能更加简单提供给用户的接口更少但上手会很快更多实用功能支持以插件形式进行动态扩展非常适合应用于小型的非嵌入式软件EasyLogger主要特性如下
- 支持多种输出方式(终端、文件、串口、485、Flash... - 支持用户自定义输出方式(例如: 终端、文件、串口、485、Flash...
- 日志内容可包含级别、时间戳、线程、进程信息; - 日志内容可包含级别、时间戳、线程、进程信息;
- 日志输出被设计为线程安全的方式; - 日志输出被设计为线程安全的方式;
- 支持多种操作系统([RT-Thread](http://www.rt-thread.org/)、UCOS、Linux、Windows...),也支持裸机平台; - 支持多种操作系统([RT-Thread](http://www.rt-thread.org/)、UCOS、Linux、Windows...),也支持裸机平台;
- 日志支持 **RAW格式** ,可设定按 **标签** 进行过滤。 - 日志支持 **RAW格式** ,可设定按 **标签** 进行过滤;
- 扩展性强,支持已插件形式扩展新功能。
> 名词解释: > 名词解释:
1、RAW格式未经过格式化的原始日志。 1、RAW格式未经过格式化的原始日志。
2、标签在软件中可以按照文件、模块、功能等方面对需要打印的日志设定标签实现日志分类。 2、标签在软件中可以按照文件、模块、功能等方面对需要打印的日志设定标签实现日志分类。
EasyLogger目前支持的插件有
- 1. Flash Log: 使用[EasyFlash](https://github.com/armink/EasyFlash)库提供的无缝接口可以把日志直接存储在Flash中。
后续我还会提供更多插件。也非常欢迎大家设计、开发更多实用插件和功能一起来完善EasyLogger **([Github](https://github.com/armink/EasyLogger)|[OSChina](http://git.oschina.net/armink/EasyLogger)|[Coding](https://coding.net/u/armink/p/EasyLogger/git))** ,同时把它推广给更多有需要的朋友。
# 2. 使用 # 2. 使用
### 2.1 参数配置 ### 2.1 参数配置
@ -72,7 +79,9 @@ EasyLogger拥有过滤方式、输出格式、输出开关这些属性。
### 2.6 Demo ### 2.6 Demo
下图为在终端中输入命令来控制日志的输出及过滤器的设置更加直观的展示了EasyLogger各项功能。 ### 2.6.1 核心功能
下图为在终端中输入命令来控制日志的输出及过滤器的设置更加直观的展示了EasyLogger核心功能。
![easylogger](https://raw.githubusercontent.com/armink/EasyLogger/master/docs/images/EasyLoggerDemo.gif) ![easylogger](https://raw.githubusercontent.com/armink/EasyLogger/master/docs/images/EasyLoggerDemo.gif)
@ -80,7 +89,7 @@ EasyLogger拥有过滤方式、输出格式、输出开关这些属性。
# 3. 后期 # 3. 后期
- 1、Flash存储在[EasyFlash](https://github.com/armink/EasyFlash)中增加日志存储、读取功能让EasyLogger与其无缝对接。使日志可以更加容易的存储在 **非文件系统** 中,并具有历史日检索的功能; - ~~1、Flash存储在[EasyFlash](https://github.com/armink/EasyFlash)中增加日志存储、读取功能让EasyLogger与其无缝对接。使日志可以更加容易的存储在 **非文件系统** 中,~~并具有历史日检索的功能;
- 2、异步输出目前日志输出与用户代码之间是同步的方式这种方式虽然软件简单也不存在日志覆盖的问题。但在输出速度较低的平台下会由于增加日志功能而降低软件运行速度。所以后期会增加 **异步输出** 方式,关键字过滤也会放到异步输出中去; - 2、异步输出目前日志输出与用户代码之间是同步的方式这种方式虽然软件简单也不存在日志覆盖的问题。但在输出速度较低的平台下会由于增加日志功能而降低软件运行速度。所以后期会增加 **异步输出** 方式,关键字过滤也会放到异步输出中去;
- 3、日志助手开发跨平台的日志助手兼容Linux、Windows、Mac系统打开助手即可查看、过滤支持正则表达式、排序、保存日志等计划使用[NW.js](http://www.oschina.net/p/nwjs)框架; - 3、日志助手开发跨平台的日志助手兼容Linux、Windows、Mac系统打开助手即可查看、过滤支持正则表达式、排序、保存日志等计划使用[NW.js](http://www.oschina.net/p/nwjs)框架;
- 4、文件转档文件系统下支持文件按容量转档按时间区分 - 4、文件转档文件系统下支持文件按容量转档按时间区分

View File

@ -53,13 +53,13 @@ extern "C" {
/* output filter's keyword max length */ /* output filter's keyword max length */
#define ELOG_FILTER_KW_MAX_LEN 16 #define ELOG_FILTER_KW_MAX_LEN 16
/* EasyLogger software version number */ /* EasyLogger software version number */
#define ELOG_SW_VERSION "0.05.25" #define ELOG_SW_VERSION "0.06.09"
/* EasyLogger assert for developer. */ /* EasyLogger assert for developer. */
#define ELOG_ASSERT(EXPR) \ #define ELOG_ASSERT(EXPR) \
if (!(EXPR)) \ if (!(EXPR)) \
{ \ { \
elog_a("ELOG", "(%s) has assert failed at %s.\n", #EXPR, __FUNCTION__); \ elog_a("elog", "(%s) has assert failed at %s.\n", #EXPR, __FUNCTION__); \
while (1); \ while (1); \
} }
@ -75,6 +75,20 @@ typedef enum {
ELOG_FMT_LINE = 1 << 7, /**< line number */ ELOG_FMT_LINE = 1 << 7, /**< line number */
} ElogFmtIndex; } ElogFmtIndex;
/* output log's filter */
typedef struct {
uint8_t level;
char tag[ELOG_FILTER_TAG_MAX_LEN + 1];
char keyword[ELOG_FILTER_KW_MAX_LEN + 1];
} ElogFilter, *ElogFilter_t;
/* easy logger */
typedef struct {
ElogFilter filter;
size_t enabled_fmt_set;
bool output_enabled;
}EasyLogger, *EasyLogger_t;
/* EasyLogger error code */ /* EasyLogger error code */
typedef enum { typedef enum {
ELOG_NO_ERR, ELOG_NO_ERR,
@ -82,6 +96,7 @@ typedef enum {
/* elog.c */ /* elog.c */
ElogErrCode elog_init(void); ElogErrCode elog_init(void);
void elog_start(void);
void elog_set_output_enabled(bool enabled); void elog_set_output_enabled(bool enabled);
bool elog_get_output_enabled(void); bool elog_get_output_enabled(void);
void elog_set_fmt(size_t set); void elog_set_fmt(size_t set);

View File

@ -0,0 +1,59 @@
/*
* This file is part of the EasyLogger Library.
*
* Copyright (c) 2015, Armink, <armink.ztl@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Function: Is is an head file for flash log plugin. You can see all be called functions.
* Created on: 2015-06-05
*/
#ifndef __ELOG_FLASH_H__
#define __ELOG_FLASH_H__
#include "elog.h"
#ifdef __cplusplus
extern "C" {
#endif
/* EasyLogger flash save plugin's using buffer mode */
#define ELOG_FLASH_USING_BUF_MODE
/* EasyLogger flash save plugin's RAM buffer size */
#define ELOG_FLASH_BUF_SIZE 1024
/* EasyLogger flash save plugin's software version number */
#define ELOG_FLASH_SW_VERSION "0.06.09"
/* elog_flash.c */
ElogErrCode elog_flash_init(void);
void elog_flash_outout_all(void);
void elog_flash_set_filter(uint8_t level,const char *tag,const char *keyword);
void elog_flash_write(const char *log, size_t size);
void elog_flash_clean(void);
#ifdef ELOG_FLASH_USING_BUF_MODE
void elog_flash_flush(void);
#endif
/* elog_port.c */
void elog_flash_port_output(const char *output, size_t size);
void elog_flash_port_lock(void);
void elog_flash_port_unlock(void);
#ifdef __cplusplus
}
#endif
#endif /* __ELOG_FLASH_H__ */

View File

@ -21,6 +21,8 @@
*/ */
#include "elog.h" #include "elog.h"
/* @note If you don't use flash log plugin, you can delete this include. */
#include "elog_flash.h"
/** /**
* EasyLogger port initialize * EasyLogger port initialize
@ -30,8 +32,8 @@
ElogErrCode elog_port_init(void) { ElogErrCode elog_port_init(void) {
ElogErrCode result = ELOG_NO_ERR; ElogErrCode result = ELOG_NO_ERR;
//add your code here /* add your code here */
return result; return result;
} }
@ -39,38 +41,66 @@ ElogErrCode elog_port_init(void) {
* output log port interface * output log port interface
*/ */
void elog_port_output(const char *output, size_t size) { void elog_port_output(const char *output, size_t size) {
//add your code here /* add your code here */
}
/**
* output flash saved log port interface
*/
void elog_flash_port_output(const char *output, size_t size) {
/* If used flash log plugin, then you must implement this function. */
} }
/** /**
* output lock * output lock
*/ */
void elog_port_output_lock(void) { void elog_port_output_lock(void) {
//add your code here /* add your code here */
} }
/** /**
* output unlock * output unlock
*/ */
void elog_port_output_unlock(void) { void elog_port_output_unlock(void) {
//add your code here /* add your code here */
} }
/**
* flash log lock
*/
void elog_flash_port_lock(void) {
/* If used flash log plugin, then you must implement this function. */
}
/**
* flash log unlock
*/
void elog_flash_port_unlock(void) {
/* If used flash log plugin, then you must implement this function. */
}
/** /**
* get current time interface * get current time interface
* *
* @return current time * @return current time
*/ */
const char *elog_port_get_time(void) { const char *elog_port_get_time(void) {
//add your code here /* add your code here */
} }
/** /**
@ -79,9 +109,9 @@ const char *elog_port_get_time(void) {
* @return current process name * @return current process name
*/ */
const char *elog_port_get_p_info(void) { const char *elog_port_get_p_info(void) {
//add your code here /* add your code here */
} }
/** /**
@ -90,7 +120,7 @@ const char *elog_port_get_p_info(void) {
* @return current thread name * @return current thread name
*/ */
const char *elog_port_get_t_info(void) { const char *elog_port_get_t_info(void) {
//add your code here /* add your code here */
} }

View File

@ -25,26 +25,12 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
/* output log's filter */
typedef struct {
uint8_t level;
char tag[ELOG_FILTER_TAG_MAX_LEN + 1];
char keyword[ELOG_FILTER_KW_MAX_LEN + 1];
} ElogFilter, *ElogFilter_t;
/* easy logger */
typedef struct {
ElogFilter filter;
size_t enabled_fmt_set;
bool output_enabled;
}EasyLogger, *EasyLogger_t;
/* EasyLogger object */ /* EasyLogger object */
static EasyLogger elog; static EasyLogger elog;
/* log buffer */ /* log buffer */
static char log_buf[ELOG_BUF_SIZE] = { 0 }; static char log_buf[ELOG_BUF_SIZE] = { 0 };
/* log tag */ /* log tag */
static const char *tag = "ELOG"; static const char *tag = "elog";
/* level output info */ /* level output info */
static const char *level_output_info[] = { static const char *level_output_info[] = {
"A/", "A/",
@ -68,15 +54,18 @@ ElogErrCode elog_init(void) {
result = elog_port_init(); result = elog_port_init();
/* set level is ELOG_LVL_VERBOSE */ /* set level is ELOG_LVL_VERBOSE */
elog_set_filter_lvl(ELOG_LVL_VERBOSE); elog_set_filter_lvl(ELOG_LVL_VERBOSE);
return result;
}
/**
* EasyLogger start after initialize.
*/
void elog_start(void) {
/* enable output */ /* enable output */
elog_set_output_enabled(true); elog_set_output_enabled(true);
/* show version */
if (result == ELOG_NO_ERR) { elog_i(tag, "EasyLogger V%s is initialize success.", ELOG_SW_VERSION);
elog_d(tag, "EasyLogger V%s is initialize success.", ELOG_SW_VERSION);
} else {
elog_d(tag, "EasyLogger V%s is initialize fail.", ELOG_SW_VERSION);
}
return result;
} }
/** /**

217
easylogger/src/elog_flash.c Normal file
View File

@ -0,0 +1,217 @@
/*
* This file is part of the EasyLogger Library.
*
* Copyright (c) 2015, Armink, <armink.ztl@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Function: Save log to flash. Must use EasyFlash(https://github.com/armink/EasyFlash) library.
* Created on: 2015-06-05
*/
#include "elog_flash.h"
#include "flash.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define log_a(...) elog_a("elog.flash", __VA_ARGS__)
#define log_e(...) elog_e("elog.flash", __VA_ARGS__)
#define log_w(...) elog_w("elog.flash", __VA_ARGS__)
#define log_i(...) elog_i("elog.flash", __VA_ARGS__)
#define log_d(...) elog_d("elog.flash", __VA_ARGS__)
#define log_v(...) elog_v("elog.flash", __VA_ARGS__)
#ifdef ELOG_FLASH_USING_BUF_MODE
/* flash log buffer */
static char log_buf[ELOG_FLASH_BUF_SIZE] = { 0 };
/* current flash log buffer write position */
static size_t cur_buf_size = 0;
#endif
/* initialize OK flag */
static bool init_ok = false;
/**
* EasyLogger flash save 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
/* initialize OK */
init_ok = true;
return result;
}
/**
* Read and output all log which saved in flash. @note It will use filter. @see elog_flash_set_filter
*/
void elog_flash_outout_all(void) {
/* 128 bytes buffer */
uint32_t buf[32] = { 0 };
size_t log_total_size = flash_log_get_used_size();
size_t buf_szie = sizeof(buf);
size_t read_size = 0, read_overage_size = 0;
/* must be call this function after initialize OK */
ELOG_ASSERT(init_ok);
/* lock flash log buffer */
elog_flash_port_lock();
/* Output all flash saved log. It will use filter */
while (true) {
if (read_size + buf_szie < log_total_size) {
flash_log_read(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 - read_size) % 4 == 0) {
read_overage_size = 0;
} else {
read_overage_size = 4 - ((log_total_size - read_size) % 4);
}
flash_log_read(read_size, buf, log_total_size - read_size + read_overage_size);
elog_flash_port_output((const char*)buf, log_total_size - read_size);
//TODO CRLF <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫͳһ<CDB3><D2BB>ͷ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EAB6A8>
elog_flash_port_output("\r\n", 2);
break;
}
}
/* unlock flash log buffer */
elog_flash_port_unlock();
}
/**
* 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;
FlashErrCode result = FLASH_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 */
elog_flash_port_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 */
elog_flash_port_unlock();
/* write all buffered log to flash, cur_buf_size will reset */
elog_flash_flush();
/* lock flash log buffer */
elog_flash_port_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 = flash_log_write((uint32_t *) log, write_size_temp);
/* write last word alignment data */
if ((result == FLASH_NO_ERR) && (write_size_temp != size)) {
memcpy(write_overage_c, log + write_size_temp, size - write_size_temp);
flash_log_write((uint32_t *) write_overage_c, 4);
}
#endif
/* unlock flash log buffer */
elog_flash_port_unlock();
}
#ifdef ELOG_FLASH_USING_BUF_MODE
/**
* 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 */
elog_flash_port_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 */
flash_log_write((uint32_t *) log_buf, cur_buf_size + write_overage_size);
/* reset position */
cur_buf_size = 0;
/* unlock flash log buffer */
elog_flash_port_unlock();
}
#endif
/**
* clean all log which in flash and ram buffer
*/
void elog_flash_clean(void) {
FlashErrCode clean_result = FLASH_NO_ERR;
/* must be call this function after initialize OK */
ELOG_ASSERT(init_ok);
/* lock flash log buffer */
elog_flash_port_lock();
/* clean all log which in flash */
clean_result = flash_log_clean();
#ifdef ELOG_FLASH_USING_BUF_MODE
/* reset position */
cur_buf_size = 0;
#endif
/* unlock flash log buffer */
elog_flash_port_unlock();
if(clean_result == FLASH_NO_ERR) {
log_i("All logs which in flash is clean OK.");
} else {
log_e("Clean logs which in flash has an error!");
}
}