LOG管理模块

1. 设计一个log管理模块,主要支持

a. 全局log等级自定义

b. 支持模块独立log等级自定义

2. 设计思路

通过链表结构,来维护不同模块的  tag名称和log等级

3. 设计代码

主要 arch_log.h, arch_log.c,list.h,有依赖编译不过,参考设计思路

arch_log.h

#ifndef _ARCH_LOG_H_
#define _ARCH_LOG_H_

#include "arch_os.h"
#include "list.h"

#define     LOG_DEBUG       0
#define     LOG_INFO        1
#define     LOG_WARN        2
#define     LOG_ERROR       3

#define     LOG_LEVEL       LOG_INFO



typedef struct {
    list_head_t iter;                   /* list header */
    char tag_name[30];                  /* log tag name */
    int tag_level;                      /* log tag level */

} log_list_t;


/**
 * @func: LOG模块-初始化
 * @return {*}
 */
void arch_log_init();

/**
 * @func: 已二进制形式输出
 * @parm: tag:模块标识,level:打印等级, header:打印头, data:打印数据, len:打印数据长度
 * @return {*}
 */
void arch_log_print_hex(const char *tag, int level, const char *header, void *data, int len);

/**
 * @func: LOG模块-设置优先级
 * @parm: tag:模块标识, level:模块优先级
 * @return {*}
 */
int arch_log_level_set(const char *tag, int level);

/**
 * @func: LOG模块-输出
 * @parm: tag:模块标识, tag_is_need:是否打印模块标识, level:模块优先级, str:打印内容
 * @return {*}
 */
int arch_log_printf(const char *tag, int tag_is_need, int level, const char *str, ...);


#define ESP_LOGD(tag, str, ...)                 arch_log_printf(tag, 1, LOG_DEBUG, str"\n", ##__VA_ARGS__)
#define ESP_LOGI(tag, str, ...)                 arch_log_printf(tag, 1, LOG_INFO, str"\n", ##__VA_ARGS__)
#define ESP_LOGW(tag, str, ...)                 arch_log_printf(tag, 1, LOG_WARN, str"\n", ##__VA_ARGS__)
#define ESP_LOGE(tag, str, ...)                 arch_log_printf(tag, 1, LOG_ERROR, str"\n", ##__VA_ARGS__)

#define ESP_LOGD1(tag, str, ...)                arch_log_printf(tag, 0, LOG_DEBUG, str, ##__VA_ARGS__)
#define ESP_LOGI1(tag, str, ...)                arch_log_printf(tag, 0, LOG_INFO, str, ##__VA_ARGS__)
#define ESP_LOGW1(tag, str, ...)                arch_log_printf(tag, 0, LOG_WARN, str, ##__VA_ARGS__)
#define ESP_LOGE1(tag, str, ...)                arch_log_printf(tag, 0, LOG_ERROR, str, ##__VA_ARGS__)

#define ESP_LOGD_HEX(tag, header, str, ...)     arch_log_print_hex(tag, LOG_DEBUG, header, str, ##__VA_ARGS__);
#define ESP_LOGI_HEX(tag, header, str, ...)     arch_log_print_hex(tag, LOG_INFO, header, str, ##__VA_ARGS__);
#define ESP_LOGW_HEX(tag, header, str, ...)     arch_log_print_hex(tag, LOG_WARN, header, str, ##__VA_ARGS__);
#define ESP_LOGE_HEX(tag, header, str, ...)     arch_log_print_hex(tag, LOG_ERROR, header, str, ##__VA_ARGS__);



#endif  //_ARCH_LOG_H_

arch_log.c

#include "arch_log.h"
#include "list.h"

static int log_level = 0;
static list_head_t list_tag = {0};


void arch_log_print_hex(const char* tag, int level, const char *header, void *data, int len)
{
    switch(level) {

    case LOG_DEBUG: {
        if(header != NULL) {
            ESP_LOGD1(tag, "%s\n", header);
        }
        for (int i = 0; i < len; i++) {
            ESP_LOGD1(tag, "0x%02x, ", *(unsigned char *)(data + i));
        }
        ESP_LOGD1(tag, "\n");
        break;
    }

    case LOG_INFO: {
        if(header != NULL) {
            ESP_LOGI1(tag, "%s\n", header);
        }
        for (int i = 0; i < len; i++) {
            ESP_LOGI1(tag, "0x%02x, ", *(unsigned char *)(data + i));
        }
        ESP_LOGI1(tag, "\n");
        break;
    }

    case LOG_WARN: {
        if(header != NULL) {
            ESP_LOGW1(tag, "%s\n", header);
        }
        for (int i = 0; i < len; i++) {
            ESP_LOGW1(tag, "0x%02x, ", *(unsigned char *)(data + i));
        }
        ESP_LOGW1(tag, "\n");
        break;
    }

    case LOG_ERROR: {
        if(header != NULL) {
            ESP_LOGE1(tag, "%s\n", header);
        }
        for (int i = 0; i < len; i++) {
            ESP_LOGE1(tag, "0x%02x, ", *(unsigned char *)(data + i));
        }
        ESP_LOGE1(tag, "\n");
        break;
    }

    default:
        break;

    }

}

void arch_log_init()
{
    printf("lyh add -> enter control init\n");

    INIT_LIST_HEAD(&list_tag);

    arch_log_level_set("all", LOG_LEVEL);
}


int arch_log_level_set(const char *tag, int level)
{
    log_list_t *node = NULL;

    /* set all the log tag level */
    if(strncmp("all", tag, strlen(tag)) == 0) {
        log_level = level;

        /* reset all the log list */
        list_for_each_entry(node, &list_tag, iter, log_list_t) {
            node->tag_level = level;
        }
        return 0;
    }

    /* set log tag in tag list */
    list_for_each_entry(node, &list_tag, iter, log_list_t)
    {
        // printf("lyh add -> tag_name = %s\n", node->tag_name);
        if (strncmp(node->tag_name, tag, strlen(tag)) == 0) {
            printf("lyh add -> tag is already save, rewrite level = %d\n", level);
            node->tag_level = level;
            return 0;
        }
    }

    printf("lyh add -> tag is not save, create new node!\n");

    /* create the new tag to tag list */
    log_list_t *log_tag = calloc(1, sizeof(log_list_t));
    if(log_tag == NULL) {
        printf("lyh add -> log_tag calloc failed\n");
        return -1;
    }

    log_tag->tag_level = level;
    memcpy(log_tag->tag_name, tag, strlen(tag));

    list_add_tail(&log_tag->iter, &list_tag);

    return 0;
}


int arch_log_printf(const char *tag, int tag_is_need, int level, const char *str, ...)
{
    int tag_is_print = 0;
    int tag_is_save = 0;
    log_list_t *node = NULL;

    /* judging the printing level from the tag list */
    list_for_each_entry(node, &list_tag, iter, log_list_t)
    {
        if (strncmp(node->tag_name, tag, strlen(tag)) == 0) {
            if (level >= node->tag_level) {
                tag_is_print = 1;
            }
            tag_is_save = 1;
            break;
        }
    }

    /* judging the printing level */
    if (level >= log_level && tag_is_save == 0) {
        tag_is_print = 1;
    }

    /* print log */
    if(tag_is_print) {
        char customer_buf[512] = {0};
        va_list ap;
        uint32_t tag_len = 0;

        if (tag_is_need) {
            tag_len = strlen(tag) + strlen(": ");
            if ((tag_len > 0) && (tag_len < 64)) {
                snprintf(customer_buf, sizeof(customer_buf), "%s%s", tag, ": ");
            }
        }

        va_start(ap, str);
        int len = vsnprintf(customer_buf + tag_len, sizeof(customer_buf) - tag_len, str, ap);
        va_end(ap);

        hal_trace_output((unsigned char *)customer_buf, len + tag_len + 1);
    }

    return 0;
}

list.h

#ifndef __LIST_H__
#define __LIST_H__

#if defined ( __CC_ARM   )
#ifndef inline
#define inline			__inline
#endif
#endif

/*
 * Simple doubly linked list implementation.
 *
 * Some of the internal functions ("__xxx") are useful when
 * manipulating whole lists rather than single entries, as
 * sometimes we already know the next/prev entries and we can
 * generate better code by using them directly rather than
 * using the generic single-entry routines.
 */

typedef struct list_head {
	struct list_head *next, *prev;
}list_head_t;


#define INIT_LIST_HEAD(ptr) do { \
	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

/*
 * Insert a new entry between two known consecutive entries. 
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_add(struct list_head *nw,
			      struct list_head *prev,
			      struct list_head *next)
{
	next->prev = nw;
	nw->next = next;
	nw->prev = prev;
	prev->next = nw;
}

/**
 * list_add - add a new entry
 * @new: new entry to be added
 * @head: list head to add it after
 *
 * Insert a new entry after the specified head.
 * This is good for implementing stacks.
 */
static inline void list_add(struct list_head *nw, struct list_head *head)
{
	__list_add(nw, head, head->next);
}

/**
 * list_add_tail - add a new entry
 * @new: new entry to be added
 * @head: list head to add it before
 *
 * Insert a new entry before the specified head.
 * This is useful for implementing queues.
 */
static inline void list_add_tail(struct list_head *nw, struct list_head *head)
{
	__list_add(nw, head->prev, head);
}

/*
 * Delete a list entry by making the prev/next entries
 * point to each other.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
	next->prev = prev;
	prev->next = next;
}

/**
 * list_del - deletes entry from list.
 * @entry: the element to delete from the list.
 * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
 */
static inline void list_del(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	entry->next = (void *) 0;
	entry->prev = (void *) 0;
}

/**
 * list_del_init - deletes entry from list and reinitialize it.
 * @entry: the element to delete from the list.
 */
static inline void list_del_init(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	INIT_LIST_HEAD(entry); 
}

/**
 * list_move - delete from one list and add as another's head
 * @list: the entry to move
 * @head: the head that will precede our entry
 */
static inline void list_move(struct list_head *list, struct list_head *head)
{
        __list_del(list->prev, list->next);
        list_add(list, head);
}

/**
 * list_move_tail - delete from one list and add as another's tail
 * @list: the entry to move
 * @head: the head that will follow our entry
 */
static inline void list_move_tail(struct list_head *list,
				  struct list_head *head)
{
        __list_del(list->prev, list->next);
        list_add_tail(list, head);
}

/**
 * list_empty - tests whether a list is empty
 * @head: the list to test.
 */
static inline int list_empty(struct list_head *head)
{
	return head->next == head;
}

static inline void __list_splice(struct list_head *list,
				 struct list_head *head)
{
	struct list_head *first = list->next;
	struct list_head *last = list->prev;
	struct list_head *at = head->next;

	first->prev = head;
	head->next = first;

	last->next = at;
	at->prev = last;
}

/**
 * list_splice - join two lists
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice(struct list_head *list, struct list_head *head)
{
	if (!list_empty(list))
		__list_splice(list, head);
}

/**
 * list_splice_init - join two lists and reinitialise the emptied list.
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 *
 * The list at @list is reinitialised
 */
static inline void list_splice_init(struct list_head *list,
				    struct list_head *head)
{
	if (!list_empty(list)) {
		__list_splice(list, head);
		INIT_LIST_HEAD(list);
	}
}

/**
 * list_entry - get the struct for this entry
 * @ptr:	the &struct list_head pointer.
 * @type:	the type of the struct this is embedded in.
 * @member:	the name of the list_struct within the struct.
 */
#define list_entry(ptr, type, member) \
	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

/**
* list_first_entry - get the first element from a list
* @ptr:        the list head to take the element from.
* @type:       the type of the struct this is embedded in.
* @member:     the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/

#define list_first_entry(ptr, type, member) \
        list_entry((ptr)->next, type, member)


#define	list_last_entry(ptr, type, field) \
        list_entry((ptr)->prev, type, field)

/**
 * list_for_each	-	iterate over a list
 * @pos:	the &struct list_head to use as a loop counter.
 * @head:	the head for your list.
 */
#define list_for_each(pos, head) \
	for (pos = (head)->next; pos != (head); \
        	pos = pos->next)
/**
 * list_for_each_prev	-	iterate over a list backwards
 * @pos:	the &struct list_head to use as a loop counter.
 * @head:	the head for your list.
 */
#define list_for_each_prev(pos, head) \
	for (pos = (head)->prev; pos != (head); \
        	pos = pos->prev)
        	
/**
 * list_for_each_safe	-	iterate over a list safe against removal of list entry
 * @pos:	the &struct list_head to use as a loop counter.
 * @n:		another &struct list_head to use as temporary storage
 * @head:	the head for your list.
 */
#define list_for_each_safe(pos, n, head) \
	for (pos = (head)->next, n = pos->next; pos != (head); \
		pos = n, n = pos->next)

/**
 * list_for_each_entry	-	iterate over list of given type
 * @pos:	the type * to use as a loop counter.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_entry(pos, head, member, type)				\
	for (pos = list_entry((head)->next, type, member);	\
	     &pos->member != (head); 					\
	     pos = list_entry(pos->member.next, type, member))

/**
 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @pos:	the type * to use as a loop counter.
 * @n:		another type * to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_entry_safe(pos, n, head, member, type)			\
	for (pos = list_entry((head)->next, type, member),	\
		n = list_entry(pos->member.next, type, member);	\
	     &pos->member != (head); 					\
	     pos = n, n = list_entry(n->member.next, type, member))

#endif

你可能感兴趣的:(设计开发,c++,数据结构,算法)