mirror of https://github.com/nirenjan/pinelog.git
Initial commit
commit
45762f497c
|
@ -0,0 +1,37 @@
|
|||
# Compiled object files
|
||||
*.o
|
||||
|
||||
# Generated objects (source, executables, tarballs, etc.)
|
||||
|
||||
# Vim swap files
|
||||
.*.swp
|
||||
|
||||
# Autotools objects
|
||||
.deps
|
||||
.dirstamp
|
||||
.libs
|
||||
ar-lib
|
||||
autom4te.cache
|
||||
m4
|
||||
compile
|
||||
config.*
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.la
|
||||
*.lo
|
||||
*.m4
|
||||
stamp-h1
|
||||
tap-driver.sh
|
||||
test-driver
|
||||
*.log
|
||||
*.trs
|
||||
*.pc
|
||||
|
||||
# Build directory
|
||||
/build/
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 Nirenjan Krishnan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,6 @@
|
|||
Pinelog - a lightweight logging API
|
||||
===================================
|
||||
|
||||
Pinelog is a lightweight logging API for C programs that's designed to be
|
||||
included in your program source code. Parameters for Pinelog are configured at
|
||||
build time by means of preprocessor flags.
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Pinelog lightweight logging library
|
||||
*
|
||||
* Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "pinelog.h"
|
||||
|
||||
/**********************************************************************
|
||||
* Global variables
|
||||
*********************************************************************/
|
||||
|
||||
/** Stream buffer */
|
||||
static FILE *output_stream = NULL;
|
||||
|
||||
/** Default logging level */
|
||||
static int log_level = LOG_LVL_ERROR;
|
||||
|
||||
/* Initialize defaults */
|
||||
void log_init_defaults(void)
|
||||
{
|
||||
output_stream = stdout;
|
||||
log_level = LOG_LVL_ERROR;
|
||||
}
|
||||
|
||||
int log_set_output_stream(FILE *stream)
|
||||
{
|
||||
if (stream == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* If current output stream is not stdout or stderr, then close it */
|
||||
if (output_stream != stdout && output_stream != stderr) {
|
||||
fclose(output_stream);
|
||||
}
|
||||
|
||||
setlinebuf(stream);
|
||||
output_stream = stream;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int log_set_output_file(const char *file)
|
||||
{
|
||||
FILE *stream;
|
||||
if (file == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
stream = fopen(file, "w");
|
||||
if (stream == NULL) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
return log_set_output_stream(stream);
|
||||
}
|
||||
|
||||
int log_get_level(void)
|
||||
{
|
||||
return log_level;
|
||||
}
|
||||
|
||||
int log_set_level(int level)
|
||||
{
|
||||
if (level < LOG_LVL_NONE || level > LOG_LVL_TRACE) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
log_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Configure logging parameters
|
||||
*********************************************************************/
|
||||
#ifndef PINELOG_SHOW_DATE
|
||||
#define PINELOG_SHOW_DATE 0
|
||||
#endif
|
||||
|
||||
#ifndef PINELOG_SHOW_LEVEL
|
||||
#define PINELOG_SHOW_LEVEL 0
|
||||
#endif
|
||||
|
||||
#ifndef PINELOG_SHOW_BACKTRACE
|
||||
#define PINELOG_SHOW_BACKTRACE 0
|
||||
#endif
|
||||
|
||||
/**********************************************************************
|
||||
* Configure level strings
|
||||
*********************************************************************/
|
||||
#ifndef PINELOG_FATAL
|
||||
#define PINELOG_FATAL "FATAL"
|
||||
#endif
|
||||
|
||||
#ifndef PINELOG_ERROR
|
||||
#define PINELOG_ERROR "ERROR"
|
||||
#endif
|
||||
|
||||
#ifndef PINELOG_WARNING
|
||||
#define PINELOG_WARNING "WARNING"
|
||||
#endif
|
||||
|
||||
#ifndef PINELOG_INFO
|
||||
#define PINELOG_INFO "INFO"
|
||||
#endif
|
||||
|
||||
#ifndef PINELOG_DEBUG
|
||||
#define PINELOG_DEBUG "DEBUG"
|
||||
#endif
|
||||
|
||||
#ifndef PINELOG_TRACE
|
||||
#define PINELOG_TRACE "TRACE"
|
||||
#endif
|
||||
|
||||
/**********************************************************************
|
||||
* Log the message to the output stream
|
||||
*********************************************************************/
|
||||
void log_message(int level, const char *file, int line, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
/* Don't log anything if the level is not severe enough */
|
||||
if (level > log_level || level < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cap the log level */
|
||||
if (level > LOG_LVL_TRACE) {
|
||||
level = LOG_LVL_TRACE;
|
||||
}
|
||||
|
||||
/* Validate and set output stream */
|
||||
if (output_stream == NULL) {
|
||||
output_stream = stdout;
|
||||
}
|
||||
|
||||
#if PINELOG_SHOW_DATE
|
||||
do {
|
||||
time_t t;
|
||||
struct tm *tmp;
|
||||
char date_string[20];
|
||||
t = time(NULL);
|
||||
tmp = localtime(&t);
|
||||
strftime(date_string, sizeof(date_string), "%F %T ", tmp);
|
||||
fputs(date_string, out_stream);
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
#if PINELOG_SHOW_LEVEL
|
||||
do {
|
||||
static const char *level_strings[] = {
|
||||
PINELOG_FATAL,
|
||||
PINELOG_ERROR,
|
||||
PINELOG_WARNING,
|
||||
PINELOG_INFO,
|
||||
PINELOG_DEBUG,
|
||||
PINELOG_TRACE,
|
||||
};
|
||||
|
||||
fputs(level_strings[level], out_stream);
|
||||
fputs(": ", out_stream);
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if PINELOG_SHOW_BACKTRACE
|
||||
fprintf(out_stream, "%s:%d ", file, line);
|
||||
#endif
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(output_stream, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Pinelog lightweight logging library
|
||||
*
|
||||
* Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file logging.h
|
||||
* @brief Logging utility library
|
||||
*
|
||||
* This file contains the prototypes for the pinelog logging library
|
||||
* used by any programs that need to log messages.
|
||||
*
|
||||
* @author Nirenjan Krishnan (nirenjan@nirenjan.org)
|
||||
*/
|
||||
#ifndef LOGGING_H
|
||||
#define LOGGING_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Logging levels
|
||||
*
|
||||
* The log levels indicate the lowest severity level that will actually be
|
||||
* logged to the logging framework.
|
||||
*/
|
||||
enum {
|
||||
/** No messages will be logged */
|
||||
LOG_LVL_NONE = -1,
|
||||
|
||||
/** Only fatal messages will be logged */
|
||||
LOG_LVL_FATAL,
|
||||
|
||||
/** Error messages. This is the default log level */
|
||||
LOG_LVL_ERROR,
|
||||
|
||||
/** Warning messages */
|
||||
LOG_LVL_WARNING,
|
||||
|
||||
/** Informational messages */
|
||||
LOG_LVL_INFO,
|
||||
|
||||
/** Debug messages */
|
||||
LOG_LVL_DEBUG,
|
||||
|
||||
/** Trace messages */
|
||||
LOG_LVL_TRACE,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize the logging library and set the defaults
|
||||
*/
|
||||
void log_init_defaults(void);
|
||||
|
||||
/**
|
||||
* @brief Set the output stream. Must be a FILE pointer.
|
||||
*
|
||||
* @param[in] stream Pointer to the output stream
|
||||
*
|
||||
* @returns 0 on success, EINVAL if the pointer is not valid.
|
||||
*/
|
||||
int log_set_output_stream(FILE *stream);
|
||||
|
||||
/**
|
||||
* @brief Set the output file.
|
||||
*
|
||||
* @param[in] file Filename to write to
|
||||
*
|
||||
* @returns 0 on success, EINVAL if the filename pointer is not valid, other
|
||||
* error if the file could not be opened for writing.
|
||||
*/
|
||||
int log_set_output_file(const char *file);
|
||||
|
||||
/**
|
||||
* @brief Set the logging level
|
||||
*
|
||||
* @param[in] level Level to filter
|
||||
*
|
||||
* @returns 0 on success, EINVAL if the level is not valid
|
||||
*/
|
||||
int log_set_level(int level);
|
||||
|
||||
/**
|
||||
* @brief Get the logging level
|
||||
*
|
||||
* @returns the configured logging level
|
||||
*/
|
||||
int log_get_level(void);
|
||||
|
||||
/**
|
||||
* @brief Log a message to the logger
|
||||
*
|
||||
* This is the actual function that logs the message. The application should
|
||||
* never need to call this directly, but instead, should always use the
|
||||
* \code LOG_* macros.
|
||||
*
|
||||
* @param[in] level Level to log the message at
|
||||
* @param[in] fmt Format string
|
||||
*
|
||||
* @returns None
|
||||
*/
|
||||
void log_message(int level, const char *file, int line, const char *fmt, ...);
|
||||
|
||||
#define LOG_FATAL(fmt, ...) do { \
|
||||
if (LOG_LVL_FATAL <= log_get_level()) { \
|
||||
log_message(LOG_LVL_FATAL, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_ERROR(fmt, ...) do { \
|
||||
if (LOG_LVL_ERROR <= log_get_level()) { \
|
||||
log_message(LOG_LVL_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LOG_WARN(fmt, ...) do { \
|
||||
if (LOG_LVL_WARNING <= log_get_level()) { \
|
||||
log_message(LOG_LVL_WARNING, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LOG_INFO(fmt, ...) do { \
|
||||
if (LOG_LVL_INFO <= log_get_level()) { \
|
||||
log_message(LOG_LVL_INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LOG_DEBUG(fmt, ...) do { \
|
||||
if (LOG_LVL_DEBUG <= log_get_level()) { \
|
||||
log_message(LOG_LVL_DEBUG, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LOG_TRACE(fmt, ...) do { \
|
||||
if (LOG_LVL_TRACE <= log_get_level()) { \
|
||||
log_message(LOG_LVL_TRACE, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !defined LOGGING_H
|
Loading…
Reference in New Issue