#ifndef AWS_COMMON_LOGGING_H
#define AWS_COMMON_LOGGING_H
#include <aws/common/atomics.h>
#include <aws/common/common.h>
#include <aws/common/thread.h>
#define AWS_LOG_LEVEL_NONE 0
#define AWS_LOG_LEVEL_FATAL 1
#define AWS_LOG_LEVEL_ERROR 2
#define AWS_LOG_LEVEL_WARN 3
#define AWS_LOG_LEVEL_INFO 4
#define AWS_LOG_LEVEL_DEBUG 5
#define AWS_LOG_LEVEL_TRACE 6
enum aws_log_level {
AWS_LL_NONE = AWS_LOG_LEVEL_NONE,
AWS_LL_FATAL = AWS_LOG_LEVEL_FATAL,
AWS_LL_ERROR = AWS_LOG_LEVEL_ERROR,
AWS_LL_WARN = AWS_LOG_LEVEL_WARN,
AWS_LL_INFO = AWS_LOG_LEVEL_INFO,
AWS_LL_DEBUG = AWS_LOG_LEVEL_DEBUG,
AWS_LL_TRACE = AWS_LOG_LEVEL_TRACE,
AWS_LL_COUNT
};
typedef uint32_t aws_log_subject_t;
#define AWS_LOG_SUBJECT_STRIDE_BITS 10
#define AWS_LOG_SUBJECT_STRIDE (1U << AWS_LOG_SUBJECT_STRIDE_BITS)
#define AWS_LOG_SUBJECT_BEGIN_RANGE(x) ((x)*AWS_LOG_SUBJECT_STRIDE)
#define AWS_LOG_SUBJECT_END_RANGE(x) (((x) + 1) * AWS_LOG_SUBJECT_STRIDE - 1)
struct aws_log_subject_info {
aws_log_subject_t subject_id;
const char *subject_name;
const char *subject_description;
};
#define DEFINE_LOG_SUBJECT_INFO(id, name, desc) \
{ .subject_id = (id), .subject_name = (name), .subject_description = (desc) }
struct aws_log_subject_info_list {
struct aws_log_subject_info *subject_list;
size_t count;
};
enum aws_common_log_subject {
AWS_LS_COMMON_GENERAL = AWS_LOG_SUBJECT_BEGIN_RANGE(AWS_C_COMMON_PACKAGE_ID),
AWS_LS_COMMON_TASK_SCHEDULER,
AWS_LS_COMMON_THREAD,
AWS_LS_COMMON_MEMTRACE,
AWS_LS_COMMON_XML_PARSER,
AWS_LS_COMMON_IO,
AWS_LS_COMMON_BUS,
AWS_LS_COMMON_TEST,
AWS_LS_COMMON_JSON_PARSER,
AWS_LS_COMMON_LAST = AWS_LOG_SUBJECT_END_RANGE(AWS_C_COMMON_PACKAGE_ID)
};
struct aws_logger;
struct aws_log_formatter;
struct aws_log_channel;
struct aws_log_writer;
struct aws_logger_vtable {
int (*const log)(
struct aws_logger *logger,
enum aws_log_level log_level,
aws_log_subject_t subject,
const char *format,
...)
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
__attribute__((format(printf, 4, 5)))
#endif
;
enum aws_log_level (*const get_log_level)(struct aws_logger *logger, aws_log_subject_t subject);
void (*const clean_up)(struct aws_logger *logger);
int (*set_log_level)(struct aws_logger *logger, enum aws_log_level);
};
struct aws_logger {
struct aws_logger_vtable *vtable;
struct aws_allocator *allocator;
void *p_impl;
};
#define AWS_LOGF(log_level, subject, ...) \
{ \
AWS_ASSERT(log_level > 0); \
struct aws_logger *logger = aws_logger_get(); \
if (logger != NULL && logger->vtable->get_log_level(logger, (subject)) >= (log_level)) { \
logger->vtable->log(logger, log_level, subject, __VA_ARGS__); \
} \
}
#define AWS_LOGUF(logger, log_level, subject, ...) \
{ logger->vtable->log(logger, log_level, subject, __VA_ARGS__); }
#if !defined(AWS_STATIC_LOG_LEVEL) || (AWS_STATIC_LOG_LEVEL >= AWS_LOG_LEVEL_FATAL)
# define AWS_LOGF_FATAL(subject, ...) AWS_LOGF(AWS_LL_FATAL, subject, __VA_ARGS__)
#else
# define AWS_LOGF_FATAL(subject, ...)
#endif
#if !defined(AWS_STATIC_LOG_LEVEL) || (AWS_STATIC_LOG_LEVEL >= AWS_LOG_LEVEL_ERROR)
# define AWS_LOGF_ERROR(subject, ...) AWS_LOGF(AWS_LL_ERROR, subject, __VA_ARGS__)
#else
# define AWS_LOGF_ERROR(subject, ...)
#endif
#if !defined(AWS_STATIC_LOG_LEVEL) || (AWS_STATIC_LOG_LEVEL >= AWS_LOG_LEVEL_WARN)
# define AWS_LOGF_WARN(subject, ...) AWS_LOGF(AWS_LL_WARN, subject, __VA_ARGS__)
#else
# define AWS_LOGF_WARN(subject, ...)
#endif
#if !defined(AWS_STATIC_LOG_LEVEL) || (AWS_STATIC_LOG_LEVEL >= AWS_LOG_LEVEL_INFO)
# define AWS_LOGF_INFO(subject, ...) AWS_LOGF(AWS_LL_INFO, subject, __VA_ARGS__)
#else
# define AWS_LOGF_INFO(subject, ...)
#endif
#if !defined(AWS_STATIC_LOG_LEVEL) || (AWS_STATIC_LOG_LEVEL >= AWS_LOG_LEVEL_DEBUG)
# define AWS_LOGF_DEBUG(subject, ...) AWS_LOGF(AWS_LL_DEBUG, subject, __VA_ARGS__)
#else
# define AWS_LOGF_DEBUG(subject, ...)
#endif
#if !defined(AWS_STATIC_LOG_LEVEL) || (AWS_STATIC_LOG_LEVEL >= AWS_LOG_LEVEL_TRACE)
# define AWS_LOGF_TRACE(subject, ...) AWS_LOGF(AWS_LL_TRACE, subject, __VA_ARGS__)
#else
# define AWS_LOGF_TRACE(subject, ...)
#endif
struct aws_logger_pipeline {
struct aws_log_formatter *formatter;
struct aws_log_channel *channel;
struct aws_log_writer *writer;
struct aws_allocator *allocator;
struct aws_atomic_var level;
};
struct aws_logger_standard_options {
enum aws_log_level level;
const char *filename;
FILE *file;
};
AWS_EXTERN_C_BEGIN
AWS_COMMON_API
void aws_logger_set(struct aws_logger *logger);
AWS_COMMON_API
struct aws_logger *aws_logger_get(void);
AWS_COMMON_API
struct aws_logger *aws_logger_get_conditional(aws_log_subject_t subject, enum aws_log_level level);
AWS_COMMON_API
void aws_logger_clean_up(struct aws_logger *logger);
AWS_COMMON_API
int aws_logger_set_log_level(struct aws_logger *logger, enum aws_log_level level);
AWS_COMMON_API
int aws_log_level_to_string(enum aws_log_level log_level, const char **level_string);
AWS_COMMON_API
int aws_string_to_log_level(const char *level_string, enum aws_log_level *log_level);
AWS_COMMON_API
int aws_thread_id_t_to_string(aws_thread_id_t thread_id, char *buffer, size_t bufsz);
AWS_COMMON_API
const char *aws_log_subject_name(aws_log_subject_t subject);
AWS_COMMON_API
void aws_register_log_subject_info_list(struct aws_log_subject_info_list *log_subject_list);
AWS_COMMON_API
void aws_unregister_log_subject_info_list(struct aws_log_subject_info_list *log_subject_list);
AWS_COMMON_API
int aws_logger_init_standard(
struct aws_logger *logger,
struct aws_allocator *allocator,
struct aws_logger_standard_options *options);
AWS_COMMON_API
int aws_logger_init_from_external(
struct aws_logger *logger,
struct aws_allocator *allocator,
struct aws_log_formatter *formatter,
struct aws_log_channel *channel,
struct aws_log_writer *writer,
enum aws_log_level level);
AWS_COMMON_API
extern struct aws_logger_vtable g_pipeline_logger_owned_vtable;
AWS_COMMON_API
int aws_logger_init_noalloc(
struct aws_logger *logger,
struct aws_allocator *allocator,
struct aws_logger_standard_options *options);
AWS_EXTERN_C_END
#endif