[component] Add ulog logger basic component.

This commit is contained in:
armink 2018-10-30 09:00:30 +08:00
parent 7fd434e2f7
commit 12a803bcc9
9 changed files with 2141 additions and 0 deletions

View File

@ -46,4 +46,184 @@ config RT_USING_RYM
bool "Enable Ymodem"
default n
config RT_USING_ULOG
bool "Enable ulog"
default n
if RT_USING_ULOG
if !ULOG_USING_SYSLOG
choice
prompt "The static output log level."
default ULOG_OUTPUT_LVL_DEBUG
help
When the log level is less than this option and it will stop output.
These log will not compile into ROM when using LOG_X api.
NOTE: It's not available on syslog mode.
config ULOG_OUTPUT_LVL_ASSERT
bool "Assert"
config ULOG_OUTPUT_LVL_ERROR
bool "Error"
config ULOG_OUTPUT_LVL_WARNING
bool "Warning"
config ULOG_OUTPUT_LVL_INFO
bool "Information"
config ULOG_OUTPUT_LVL_DEBUG
bool "Debug"
endchoice
endif
if ULOG_USING_SYSLOG
choice
prompt "The static output log level."
default ULOG_OUTPUT_LVL_DEBUG
help
When the log level is less than this option and it will stop output.
These log will not compile into ROM when using LOG_X api.
NOTE: It's not available on syslog mode.
config ULOG_OUTPUT_LVL_EMERG
bool "EMERG"
config ULOG_OUTPUT_LVL_ALERT
bool "ALERT"
config ULOG_OUTPUT_LVL_CRIT
bool "CRIT"
config ULOG_OUTPUT_LVL_ERROR
bool "ERR"
config ULOG_OUTPUT_LVL_WARNING
bool "WARNING"
config ULOG_OUTPUT_LVL_NOTICE
bool "NOTICE"
config ULOG_OUTPUT_LVL_INFO
bool "INFO"
config ULOG_OUTPUT_LVL_DEBUG
bool "DEBUG"
endchoice
endif
config ULOG_OUTPUT_LVL
int
default 0 if ULOG_OUTPUT_LVL_ASSERT
default 0 if ULOG_OUTPUT_LVL_EMERG
default 1 if ULOG_OUTPUT_LVL_ALERT
default 2 if ULOG_OUTPUT_LVL_CRIT
default 3 if ULOG_OUTPUT_LVL_ERROR
default 4 if ULOG_OUTPUT_LVL_WARNING
default 5 if ULOG_OUTPUT_LVL_NOTICE
default 6 if ULOG_OUTPUT_LVL_INFO
default 7 if ULOG_OUTPUT_LVL_DEBUG
default 7
config ULOG_USING_ISR_LOG
bool "Enable ISR log."
default n
help
The log output API can using in ISR (Interrupt Service Routines) also.
config ULOG_ASSERT_ENABLE
bool "Enable assert check."
default y
config ULOG_LINE_BUF_SIZE
int "The log's max width."
default 128
help
The buffer size for every line log.
config ULOG_USING_ASYNC_OUTPUT
bool "Enable async output mode."
default n
help
When enable asynchronous output mode. The log output is not immediately and the log will stored to buffer.
The another thread (Such as idle) will read the buffer and output the log. So it will using more RAM.
if ULOG_USING_ASYNC_OUTPUT
config ULOG_ASYNC_OUTPUT_BUF_SIZE
int "The async output buffer size."
default 2048
config ULOG_ASYNC_OUTPUT_BY_THREAD
bool "Enable async output by thread."
default y
help
This thread will output the asynchronous logs. The logs can output by other user thread when this option is disable.
if ULOG_ASYNC_OUTPUT_BY_THREAD
config ULOG_ASYNC_OUTPUT_THREAD_STACK
int "The async output thread stack size."
default 1024
config ULOG_ASYNC_OUTPUT_THREAD_PRIORITY
int "The async output thread stack priority."
range 0 RT_THREAD_PRIORITY_MAX
default 30
endif
endif
menu "log format"
config ULOG_OUTPUT_FLOAT
bool "Enable float number support."
select RT_USING_LIBC
default n
help
The default formater is using rt_vsnprint and it not supported float number.
When enable this option then it will enable libc. The formater will change to vsnprint on libc.
if !ULOG_USING_SYSLOG
config ULOG_USING_COLOR
bool "Enable color log."
default y
help
The log will has different color by level.
endif
config ULOG_OUTPUT_TIME
bool "Enable time information."
default y
config ULOG_TIME_USING_TIMESTAMP
bool "Enable timestamp format for time."
default n
select RT_USING_LIBC
depends on ULOG_OUTPUT_TIME
config ULOG_OUTPUT_LEVEL
bool "Enable level information."
default y
config ULOG_OUTPUT_TAG
bool "Enable tag information."
default y
config ULOG_OUTPUT_THREAD_NAME
bool "Enable thread information."
default n
endmenu
config ULOG_BACKEND_USING_CONSOLE
bool "Enable console backend."
default y
help
The low level output using rt_kprintf().
config ULOG_USING_FILTER
bool "Enable runtime log filter."
default n
help
It will enable the log filter.
Such as level filter, log tag filter, log kw filter and tag's level filter.
config ULOG_USING_SYSLOG
bool "Enable syslog format log and API."
select ULOG_OUTPUT_TIME
select ULOG_USING_FILTER
default n
config ULOG_SW_VERSION_NUM
int
default 0x00100
help
sfotware module version number
endif
endmenu

View File

@ -0,0 +1,16 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
path = [cwd]
if GetDepend('ULOG_BACKEND_USING_CONSOLE'):
src += ['backend/console_be.c']
if GetDepend('ULOG_USING_SYSLOG'):
path += [cwd + '/syslog']
src += Glob('syslog/*.c')
group = DefineGroup('Utilities', src, depend = ['RT_USING_ULOG'], CPPPATH = path)
Return('group')

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-09-04 armink the first version
*/
#include <rthw.h>
#include <ulog.h>
#ifdef ULOG_BACKEND_USING_CONSOLE
#if defined(ULOG_ASYNC_OUTPUT_BY_THREAD) && ULOG_ASYNC_OUTPUT_THREAD_STACK < 384
#error "The thread stack size must more than 384 when using async output by thread (ULOG_ASYNC_OUTPUT_BY_THREAD)"
#endif
static struct ulog_backend console;
void ulog_console_backend_output(struct ulog_backend *backend, rt_uint32_t level, const char *tag, rt_bool_t is_raw,
const char *log, size_t len)
{
rt_device_t dev = rt_console_get_device();
#ifdef RT_USING_DEVICE
if (dev == RT_NULL)
{
rt_hw_console_output(log);
}
else
{
rt_uint16_t old_flag = dev->open_flag;
dev->open_flag |= RT_DEVICE_FLAG_STREAM;
rt_device_write(dev, 0, log, len);
dev->open_flag = old_flag;
}
#else
rt_hw_console_output(log);
#endif
}
int ulog_console_backend_init(void)
{
console.output = ulog_console_backend_output;
ulog_backend_register(&console, "console", RT_TRUE);
return 0;
}
INIT_COMPONENT_EXPORT(ulog_console_backend_init);
#endif /* ULOG_BACKEND_USING_CONSOLE */

View File

@ -0,0 +1,260 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-09-07 armink the first version
*/
#include <stdarg.h>
#include <ulog.h>
#include <rthw.h>
#include "syslog.h"
#ifdef ULOG_OUTPUT_FLOAT
#include <stdio.h>
#endif
/*
* reference:
* http://pubs.opengroup.org/onlinepubs/7908799/xsh/syslog.h.html
* https://www.gnu.org/software/libc/manual/html_node/Submitting-Syslog-Messages.html
* http://man7.org/linux/man-pages/man3/syslog.3.html
*/
#ifdef ULOG_USING_SYSLOG
#ifndef ULOG_SYSLOG_IDENT_MAX_LEN
#define ULOG_SYSLOG_IDENT_MAX_LEN ULOG_FILTER_TAG_MAX_LEN
#endif
static char local_ident[ULOG_SYSLOG_IDENT_MAX_LEN + 1];
static int local_facility = LOG_USER;
static int local_option = LOG_USER;
static rt_bool_t is_open = RT_FALSE;
/**
* open connection to syslog
*
* @param ident is an arbitrary identification string which future syslog invocations will prefix to each message.
* @param option is not using on ulog.
* @param facility is the default facility code for this connection.
*/
void openlog(const char *ident, int option, int facility)
{
rt_base_t level;
ulog_init();
level = rt_hw_interrupt_disable();
rt_memset(local_ident, 0, sizeof(local_ident));
if (ident)
{
rt_strncpy(local_ident, ident, ULOG_SYSLOG_IDENT_MAX_LEN);
}
else
{
rt_strncpy(local_ident, "rtt", ULOG_SYSLOG_IDENT_MAX_LEN);
}
local_option = option;
if (facility)
{
local_facility = facility;
}
else
{
/* default facility is LOG_USER */
local_facility = LOG_USER;
}
/* output all level log */
setlogmask(LOG_UPTO(LOG_DEBUG));
is_open = RT_TRUE;
rt_hw_interrupt_enable(level);
}
/**
* This is functionally identical to syslog.
*
* @param priority log priority, can be generated by the macro LOG_MAKEPRI
* @param format log format
* @param args log arguments
*/
void vsyslog(int priority, const char *format, va_list args)
{
if (LOG_FAC(priority) == 0)
{
/* using local facility */
priority |= local_facility;
}
ulog_voutput(priority, local_ident, format, args);
}
/**
* generates a log message
*
* @param priority log priority, can be generated by the macro LOG_MAKEPRI
* @param format log format, like printf()
*/
void syslog(int priority, const char *format, ...)
{
va_list args;
if (!is_open)
{
openlog(0, 0, 0);
}
/* args point to the first variable parameter */
va_start(args, format);
vsyslog(priority, format, args);
va_end(args);
}
/**
* close the syslog
*/
void closelog(void)
{
ulog_deinit();
is_open = RT_FALSE;
}
/**
* set log priority mask
*
* @param mask The log priority mask which generate by macro LOG_MASK and LOG_UPTO.
*
* @return This function returns the previous log priority mask.
*/
int setlogmask(int mask)
{
static int old_mask = 0;
int return_mask = old_mask;
ulog_tag_lvl_filter_set(local_ident, mask);
old_mask = mask;
return return_mask;
}
static const char *get_month_str(uint8_t month)
{
switch(month)
{
case 1: return "Jan";
case 2: return "Feb";
case 3: return "Mar";
case 4: return "Apr";
case 5: return "May";
case 6: return "June";
case 7: return "July";
case 8: return "Aug";
case 9: return "Sept";
case 10: return "Oct";
case 11: return "Nov";
case 12: return "Dec";
default: return "Unknown";
}
}
RT_WEAK rt_size_t syslog_formater(char *log_buf, int level, const char *tag, const char *format, va_list args)
{
extern size_t ulog_strcpy(size_t cur_len, char *dst, const char *src);
rt_size_t log_len = 0, newline_len = rt_strlen(ULOG_NEWLINE_SIGN);
int fmt_result;
RT_ASSERT(log_buf);
RT_ASSERT(LOG_PRI(level) <= LOG_DEBUG);
RT_ASSERT(tag);
RT_ASSERT(format);
/* add time and priority (level) info */
{
time_t now = time(RT_NULL);
struct tm *tm, tm_tmp;
tm = gmtime_r(&now, &tm_tmp);
#ifdef ULOG_OUTPUT_LEVEL
rt_snprintf(log_buf + log_len, ULOG_LINE_BUF_SIZE - log_len, "<%d>%s%3d %02d:%02d:%02d", level,
get_month_str(tm->tm_mon + 1), tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, rt_tick_get() % 1000);
#else
rt_snprintf(log_buf + log_len, ULOG_LINE_BUF_SIZE - log_len, "%s%3d %02d:%02d:%02d",
get_month_str(tm->tm_mon + 1), tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, rt_tick_get() % 1000);
#endif /* ULOG_OUTPUT_LEVEL */
log_len += rt_strlen(log_buf + log_len);
}
#ifdef ULOG_OUTPUT_TAG
/* add identification (tag) info */
{
log_len += ulog_strcpy(log_len, log_buf + log_len, " ");
log_len += ulog_strcpy(log_len, log_buf + log_len, tag);
}
#endif /* ULOG_OUTPUT_TAG */
#ifdef ULOG_OUTPUT_THREAD_NAME
/* add thread info */
{
log_len += ulog_strcpy(log_len, log_buf + log_len, " ");
/* is not in interrupt context */
if (rt_interrupt_get_nest() == 0)
{
log_len += ulog_strcpy(log_len, log_buf + log_len, rt_thread_self()->name);
}
else
{
log_len += ulog_strcpy(log_len, log_buf + log_len, "ISR");
}
}
#endif /* ULOG_OUTPUT_THREAD_NAME */
log_len += ulog_strcpy(log_len, log_buf + log_len, ": ");
#ifdef ULOG_OUTPUT_FLOAT
fmt_result = vsnprintf(log_buf + log_len, ULOG_LINE_BUF_SIZE - log_len, format, args);
#else
fmt_result = rt_vsnprintf(log_buf + log_len, ULOG_LINE_BUF_SIZE - log_len, format, args);
#endif /* ULOG_OUTPUT_FLOAT */
/* calculate log length */
if ((log_len + fmt_result <= ULOG_LINE_BUF_SIZE) && (fmt_result > -1))
{
log_len += fmt_result;
}
else
{
/* using max length */
log_len = ULOG_LINE_BUF_SIZE;
}
/* overflow check and reserve some space for newline sign */
if (log_len + newline_len > ULOG_LINE_BUF_SIZE)
{
/* using max length */
log_len = ULOG_LINE_BUF_SIZE;
/* reserve some space for newline sign */
log_len -= newline_len;
}
/* package newline sign */
log_len += ulog_strcpy(log_len, log_buf + log_len, ULOG_NEWLINE_SIGN);
return log_len;
}
#endif /* ULOG_USING_SYSLOG */

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-09-07 armink the first version
*/
#ifndef _SYSLOG_H_
#define _SYSLOG_H_
#ifdef __cplusplus
extern "C" {
#endif
/*
* priorities/facilities are encoded into a single 32-bit quantity, where the
* bottom 3 bits are the priority (0-7) and the top 28 bits are the facility
* (0-big number). Both the priorities and the facilities map roughly
* one-to-one to strings in the syslogd(8) source code. This mapping is
* included in this file.
*
* priorities (these are ordered)
*/
#define LOG_EMERG 0 /* system is unusable */
#define LOG_ALERT 1 /* action must be taken immediately */
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */
#define LOG_PRIMASK 0x07
#define LOG_PRI(p) ((p) & LOG_PRIMASK)
#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
/* facility codes */
#define LOG_KERN (0<<3) /* kernel messages */
#define LOG_USER (1<<3) /* random user-level messages */
#define LOG_MAIL (2<<3) /* mail system */
#define LOG_DAEMON (3<<3) /* system daemons */
#define LOG_AUTH (4<<3) /* security/authorization messages */
#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
#define LOG_LPR (6<<3) /* line printer subsystem */
#define LOG_NEWS (7<<3) /* network news subsystem */
#define LOG_UUCP (8<<3) /* UUCP subsystem */
#define LOG_CRON (9<<3) /* clock daemon */
#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
/* other codes through 15 reserved for system use */
#define LOG_LOCAL0 (16<<3) /* reserved for local use */
#define LOG_LOCAL1 (17<<3) /* reserved for local use */
#define LOG_LOCAL2 (18<<3) /* reserved for local use */
#define LOG_LOCAL3 (19<<3) /* reserved for local use */
#define LOG_LOCAL4 (20<<3) /* reserved for local use */
#define LOG_LOCAL5 (21<<3) /* reserved for local use */
#define LOG_LOCAL6 (22<<3) /* reserved for local use */
#define LOG_LOCAL7 (23<<3) /* reserved for local use */
#define LOG_NFACILITIES 24 /* current number of facilities */
#define LOG_FACMASK 0x03f8 /* mask to extract facility part */
/* facility of pri */
#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)
/*
* arguments to setlogmask.
*/
#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */
#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */
/*
* Option flags for openlog.
*
* LOG_ODELAY no longer does anything.
* LOG_NDELAY is the inverse of what it used to be.
*/
#define LOG_PID 0x01 /* log the pid with each message */
#define LOG_CONS 0x02 /* log on the console if errors in sending */
#define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */
#define LOG_NDELAY 0x08 /* don't delay open */
#define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */
#define LOG_PERROR 0x20 /* log to stderr as well */
#include <stdarg.h>
void closelog(void);
void openlog(const char *ident, int option, int facility);
int setlogmask(int mask);
void syslog(int priority, const char *format, ...);
void vsyslog(int priority, const char *format, va_list args);
#ifdef __cplusplus
}
#endif
#endif /* _SYSLOG_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-08-25 armink the first version
*/
#ifndef _ULOG_H_
#define _ULOG_H_
#include <rtthread.h>
#include "ulog_def.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ULOG_VERSION_STR "0.1.0"
/*
* ulog init and deint
*/
int ulog_init(void);
void ulog_deinit(void);
/*
* output different level log by LOG_X API
*
* NOTE: The `LOG_TAG` and `LOG_LVL` must be defined before including the <ulog.h> when you want to use LOG_X API.
*
* #define LOG_TAG "example"
* #define LOG_LVL LOG_LVL_DBG
* #include <ulog.h>
*
* Then you can using LOG_X API to output log
*
* LOG_D("this is a debug log!");
* LOG_E("this is a error log!");
*/
#define LOG_E(...) ulog_e(LOG_TAG, __VA_ARGS__)
#define LOG_W(...) ulog_w(LOG_TAG, __VA_ARGS__)
#define LOG_I(...) ulog_i(LOG_TAG, __VA_ARGS__)
#define LOG_D(...) ulog_d(LOG_TAG, __VA_ARGS__)
#define LOG_RAW(...) ulog_raw(__VA_ARGS__)
/*
* backend register and unregister
*/
rt_err_t ulog_backend_register(ulog_backend_t backend, const char *name, rt_bool_t support_color);
rt_err_t ulog_backend_unregister(ulog_backend_t backend);
#ifdef ULOG_USING_FILTER
/*
* log filter setting
*/
int ulog_tag_lvl_filter_set(const char *tag, rt_uint32_t level);
rt_uint32_t ulog_tag_lvl_filter_get(const char *tag);
void ulog_global_filter_lvl_set(rt_uint32_t level);
void ulog_global_filter_tag_set(const char *tag);
void ulog_global_filter_kw_set(const char *keyword);
#endif /* ULOG_USING_FILTER */
/*
* flush all backends's log
*/
void ulog_flush(void);
#ifdef ULOG_USING_ASYNC_OUTPUT
/*
* asynchronous output API
*/
void ulog_async_output(void);
void ulog_async_waiting_log(rt_int32_t time);
#endif
/*
* dump the hex format data to log
*/
void ulog_hexdump(const char *name, rt_size_t width, rt_uint8_t *buf, rt_size_t size);
/*
* Another log output API. This API is difficult to use than LOG_X API.
*/
void ulog_voutput(rt_uint32_t level, const char *tag, const char *format, va_list args);
void ulog_output(rt_uint32_t level, const char *tag, const char *format, ...);
void ulog_raw(const char *format, ...);
#ifdef __cplusplus
}
#endif
#endif /* _ULOG_H_ */

View File

@ -0,0 +1,189 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-08-25 armink the first version
*/
#ifndef _ULOG_DEF_H_
#define _ULOG_DEF_H_
#ifdef __cplusplus
extern "C" {
#endif
/* logger level, the number is compatible for syslog */
#define LOG_LVL_ASSERT 0
#define LOG_LVL_ERROR 3
#define LOG_LVL_WARNING 4
#define LOG_LVL_INFO 6
#define LOG_LVL_DBG 7
/* the output silent level and all level for filter setting */
#ifndef ULOG_USING_SYSLOG
#define LOG_FILTER_LVL_SILENT 0
#define LOG_FILTER_LVL_ALL 7
#else
#define LOG_FILTER_LVL_SILENT 1
#define LOG_FILTER_LVL_ALL 255
#endif /* ULOG_USING_SYSLOG */
/* compatible for rtdbg */
#undef LOG_D
#undef LOG_I
#undef LOG_W
#undef LOG_E
#undef LOG_RAW
#undef DBG_ERROR
#undef DBG_WARNING
#undef DBG_INFO
#undef DBG_LOG
#define DBG_ERROR LOG_LVL_ERROR
#define DBG_WARNING LOG_LVL_WARNING
#define DBG_INFO LOG_LVL_INFO
#define DBG_LOG LOG_LVL_DBG
#if !defined(LOG_TAG)
/* compatible for rtdbg */
#if defined(DBG_SECTION_NAME)
#define LOG_TAG DBG_SECTION_NAME
#else
#define LOG_TAG "NO_TAG"
#endif
#endif /* !defined(LOG_TAG) */
#if !defined(LOG_LVL)
/* compatible for rtdbg */
#if defined(DBG_LEVEL)
#define LOG_LVL DBG_LEVEL
#else
#define LOG_LVL LOG_LVL_DBG
#endif
#endif /* !defined(LOG_LVL) */
#if (LOG_LVL >= LOG_LVL_DBG) && (ULOG_OUTPUT_LVL >= LOG_LVL_DBG)
#define ulog_d(TAG, ...) ulog_output(LOG_LVL_DBG, TAG, __VA_ARGS__)
#else
#define ulog_d(TAG, ...)
#endif /* (LOG_LVL >= LOG_LVL_DBG) && (ULOG_OUTPUT_LVL >= LOG_LVL_DBG) */
#if (LOG_LVL >= LOG_LVL_INFO) && (ULOG_OUTPUT_LVL >= LOG_LVL_INFO)
#define ulog_i(TAG, ...) ulog_output(LOG_LVL_INFO, TAG, __VA_ARGS__)
#else
#define ulog_i(TAG, ...)
#endif /* (LOG_LVL >= LOG_LVL_INFO) && (ULOG_OUTPUT_LVL >= LOG_LVL_INFO) */
#if (LOG_LVL >= LOG_LVL_WARNING) && (ULOG_OUTPUT_LVL >= LOG_LVL_WARNING)
#define ulog_w(TAG, ...) ulog_output(LOG_LVL_WARNING, TAG, __VA_ARGS__)
#else
#define ulog_w(TAG, ...)
#endif /* (LOG_LVL >= LOG_LVL_WARNING) && (ULOG_OUTPUT_LVL >= LOG_LVL_WARNING) */
#if (LOG_LVL >= LOG_LVL_ERROR) && (ULOG_OUTPUT_LVL >= LOG_LVL_ERROR)
#define ulog_e(TAG, ...) ulog_output(LOG_LVL_ERROR, TAG, __VA_ARGS__)
#else
#define ulog_e(TAG, ...)
#endif /* (LOG_LVL >= LOG_LVL_ERROR) && (ULOG_OUTPUT_LVL >= LOG_LVL_ERROR) */
/* assert for developer. */
#ifdef ULOG_ASSERT_ENABLE
#define ULOG_ASSERT(EXPR) \
if (!(EXPR)) \
{ \
ulog_output(LOG_LVL_ASSERT, LOG_TAG, "(%s) has assert failed at %s:%ld.", #EXPR, __FUNCTION__, __LINE__); \
ulog_flush(); \
while (1); \
}
#else
#define ULOG_ASSERT(EXPR)
#endif
/* ASSERT API definition */
#if !defined(ASSERT)
#define ASSERT ULOG_ASSERT
#endif
/* compatible for elog */
#undef assert
#undef log_e
#undef log_w
#undef log_i
#undef log_d
#undef log_v
#undef ELOG_LVL_ASSERT
#undef ELOG_LVL_ERROR
#undef ELOG_LVL_WARN
#undef ELOG_LVL_INFO
#undef ELOG_LVL_DEBUG
#undef ELOG_LVL_VERBOSE
#define assert ASSERT
#define log_e LOG_E
#define log_w LOG_W
#define log_i LOG_I
#define log_d LOG_D
#define log_v LOG_D
#define log_raw LOG_RAW
#define ELOG_LVL_ASSERT LOG_LVL_ASSERT
#define ELOG_LVL_ERROR LOG_LVL_ERROR
#define ELOG_LVL_WARN LOG_LVL_WARNING
#define ELOG_LVL_INFO LOG_LVL_INFO
#define ELOG_LVL_DEBUG LOG_LVL_DBG
#define ELOG_LVL_VERBOSE LOG_LVL_DBG
/* setting static output log level */
#ifndef ULOG_OUTPUT_LVL
#define ULOG_OUTPUT_LVL LOG_LVL_DBG
#endif
/* buffer size for every line's log */
#ifndef ULOG_LINE_BUF_SIZE
#define ULOG_LINE_BUF_SIZE 128
#endif
/* output filter's tag max length */
#ifndef ULOG_FILTER_TAG_MAX_LEN
#define ULOG_FILTER_TAG_MAX_LEN 23
#endif
/* output filter's keyword max length */
#ifndef ULOG_FILTER_KW_MAX_LEN
#define ULOG_FILTER_KW_MAX_LEN 15
#endif
#ifndef ULOG_NEWLINE_SIGN
#define ULOG_NEWLINE_SIGN "\r\n"
#endif
#define ULOG_FRAME_MAGIC 0x10
struct ulog_frame
{
/* magic word is 0x10 ('lo') */
rt_uint32_t magic:8;
rt_uint32_t is_raw:1;
rt_uint32_t log_len:23;
rt_uint32_t level;
const char *log;
const char *tag;
};
typedef struct ulog_frame *ulog_frame_t;
struct ulog_backend
{
char name[RT_NAME_MAX];
rt_bool_t support_color;
void (*init) (struct ulog_backend *backend);
void (*output)(struct ulog_backend *backend, rt_uint32_t level, const char *tag, rt_bool_t is_raw, const char *log, size_t len);
void (*flush) (struct ulog_backend *backend);
void (*deinit)(struct ulog_backend *backend);
rt_slist_t list;
};
typedef struct ulog_backend *ulog_backend_t;
#ifdef __cplusplus
}
#endif
#endif /* _ULOG_DEF_H_ */

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-08-02 armink the first version
*/
#include <stdlib.h>
#include <rtthread.h>
#ifndef ULOG_USING_SYSLOG
#define LOG_TAG "example"
#define LOG_LVL LOG_LVL_DBG
#include <ulog.h>
#else
#include <syslog.h>
#endif /* ULOG_USING_SYSLOG */
void ulog_example(void)
{
int count = 0;
#ifdef ULOG_USING_SYSLOG
openlog("example1", 0, 0);
#endif
while (count++ < 50)
{
#ifndef ULOG_USING_SYSLOG
/* output different level log by LOG_X API */
LOG_D("LOG_D(%d): RT-Thread is an open source IoT operating system from China.", count);
LOG_I("LOG_I(%d): RT-Thread is an open source IoT operating system from China.", count);
LOG_W("LOG_W(%d): RT-Thread is an open source IoT operating system from China.", count);
LOG_E("LOG_E(%d): RT-Thread is an open source IoT operating system from China.", count);
ulog_d("test", "ulog_d(%d): RT-Thread is an open source IoT operating system from China.", count);
ulog_i("test", "ulog_i(%d): RT-Thread is an open source IoT operating system from China.", count);
ulog_w("test", "ulog_w(%d): RT-Thread is an open source IoT operating system from China.", count);
ulog_e("test", "ulog_e(%d): RT-Thread is an open source IoT operating system from China.", count);
#ifdef ULOG_USING_FILTER
if (count == 20)
{
/* Set the global filer level is INFO. All of DEBUG log will stop output */
ulog_global_filter_lvl_set(LOG_LVL_INFO);
/* Set the test tag's level filter's level is ERROR. The DEBUG, INFO, WARNING log will stop output. */
ulog_tag_lvl_filter_set("test", LOG_LVL_ERROR);
}
else if (count == 30)
{
/* Set the example tag's level filter's level is LOG_FILTER_LVL_SILENT, the log enter silent mode. */
ulog_tag_lvl_filter_set("example", LOG_FILTER_LVL_SILENT);
/* Set the test tag's level filter's level is WARNING. The DEBUG, INFO log will stop output. */
ulog_tag_lvl_filter_set("test", LOG_LVL_WARNING);
}
else if (count == 40)
{
/* Set the test tag's level filter's level is LOG_FILTER_LVL_ALL. All level log will resume output. */
ulog_tag_lvl_filter_set("test", LOG_FILTER_LVL_ALL);
/* Set the global filer level is LOG_FILTER_LVL_ALL. All level log will resume output */
ulog_global_filter_lvl_set(LOG_FILTER_LVL_ALL);
}
#endif /* ULOG_USING_FILTER */
#else
/* output different priority log by syslog API */
syslog(LOG_INFO, "syslog(%d) LOG_INFO: RT-Thread is an open source IoT operating system from China.", count);
syslog(LOG_DEBUG, "syslog(%d) LOG_DEBUG: RT-Thread is an open source IoT operating system from China.", count);
syslog(LOG_WARNING, "syslog(%d) LOG_WARNING: RT-Thread is an open source IoT operating system from China.", count);
syslog(LOG_ERR, "syslog(%d) LOG_ERR: RT-Thread is an open source IoT operating system from China.", count);
syslog(LOG_INFO | LOG_MAIL, "syslog(%d) LOG_INFO | LOG_MAIL: RT-Thread is an open source IoT operating system from China.", count);
syslog(LOG_DEBUG | LOG_DAEMON, "syslog(%d) LOG_DEBUG | LOG_DAEMON: RT-Thread is an open source IoT operating system from China.", count);
syslog(LOG_WARNING | LOG_AUTH, "syslog(%d) LOG_WARNING | LOG_AUTH: RT-Thread is an open source IoT operating system from China.", count);
syslog(LOG_ERR | LOG_SYSLOG, "syslog(%d) LOG_ERR | LOG_SYSLOG: RT-Thread is an open source IoT operating system from China.", count);
if (count == 20)
{
/* Set log priority mask. Only output ERR and WARNING log. */
setlogmask(LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING));
}
else if (count == 40)
{
/* Set log priority mask. The log which level is less than ERROR will stop output. */
setlogmask(LOG_UPTO(LOG_ERR));
}
#endif /* ULOG_USING_SYSLOG */
rt_thread_delay(rt_tick_from_millisecond(rand() % 1000));
}
}
MSH_CMD_EXPORT(ulog_example, run ulog example)