Skip to content

Commit

Permalink
Keep the file handle open for future write operations for extra perfo…
Browse files Browse the repository at this point in the history
…rmance
  • Loading branch information
kala13x committed Aug 18, 2023
1 parent be8246f commit 83baf33
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 24 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ slog_enable(SLOG_TRACE);
slog_disable(SLOG_FLAGS_ALL);
```

Deinitialization needed only if the thread safety flag is greater than zero (nTdSafe > 0) while initialization.
Deinitialization needed only if the `nTdSafe` and/or `nKeepOpen` flags are greater than zero while initialization.
```c
slog_destroy();
```
Function destroys the mutex context and resets thread safety flag to zero.
Function destroys the mutex context, closes output file and resets thread safety flag to zero.


### Print and log something in the file
Expand Down Expand Up @@ -177,6 +177,7 @@ logCallback | slog_cb_t | NULL | Log callback function to
pCallbackCtx | void* | NULL | User data pointer passed to log callback.
eColorFormat | slog_coloring_t | SLOG_COLORING_TAG | Output coloring format control.
eDateControl | slog_date_ctrl_t | SLOG_TIME_ONLY | Time and date control in log output.
nKeepOpen | uint8_t | 0 (disabled) | Keep the file handle open for future writes.
nTraceTid | uint8_t | 0 (disabled) | Trace thread ID and display in output.
nToScreen | uint8_t | 1 (enabled) | Enable or disable screen logging.
nNewLine | uint8_t | 1 (enabled) | Enable or disable new line ending.
Expand All @@ -197,6 +198,7 @@ slgCfg.eColorFormat = SLOG_COLORING_TAG;
slgCfg.eDateControl = SLOG_TIME_ONLY;
strcpy(slgCfg.sFileName, "myproject");
strcpy(slgCfg.sFilePath, "./logs/");
slgCfg.nKeepOpen = 1;
slgCfg.nTraceTid = 1;
slgCfg.nToScreen = 1;
slgCfg.nNewLine = 1;
Expand Down
4 changes: 3 additions & 1 deletion example/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ int main()
greet();

/* Initialize slog and allow only error and not tagged output */
slog_init("example", nLogFlags, 0);
slog_init("example", SLOG_FLAGS_ALL, 0);
slog_config_get(&cfg);

/* Disable time and date in output */
Expand Down Expand Up @@ -100,6 +100,7 @@ int main()
/* Enable file logger and color the whole log output instead of coloring only tags*/
cfg.eColorFormat = SLOG_COLORING_FULL;
cfg.nToFile = 1;
cfg.nKeepOpen = 1;
slog_config_set(&cfg);

/* Print message and save log in the file */
Expand Down Expand Up @@ -131,5 +132,6 @@ int main()
slog_trace();
slog_debug("Above we traced source location without output message");

slog_destroy();
return 0;
}
77 changes: 66 additions & 11 deletions src/slog.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@
#endif

typedef struct slog {
unsigned int nTdSafe:1;
pthread_mutex_t mutex;
slog_config_t config;
uint8_t nStartDay;
uint8_t nTdSafe;
FILE *pLogFile;
} slog_t;

typedef struct XLogCtx {
Expand Down Expand Up @@ -161,6 +163,35 @@ static const char* slog_get_color(slog_flag_t eFlag)
return SLOG_EMPTY;
}

static void slog_close_file()
{
if (g_slog.pLogFile != NULL)
{
fclose(g_slog.pLogFile);
g_slog.pLogFile = NULL;
}
}

static uint8_t slog_open_file(const slog_config_t *pCfg, const slog_date_t *pDate)
{
slog_close_file();

char sFilePath[SLOG_PATH_MAX + SLOG_NAME_MAX + SLOG_DATE_MAX];
snprintf(sFilePath, sizeof(sFilePath), "%s/%s-%04d-%02d-%02d.log",
pCfg->sFilePath, pCfg->sFileName, pDate->nYear, pDate->nMonth, pDate->nDay);

g_slog.pLogFile = fopen(sFilePath, "a");
if (g_slog.pLogFile == NULL)
{
printf("<%s:%d> %s: [ERROR] Failed to open file: %s (%s)\n",
__FILE__, __LINE__, __func__, sFilePath, strerror(errno));

return 0;
}

return 1;
}

uint16_t slog_get_usec()
{
struct timeval tv;
Expand Down Expand Up @@ -236,10 +267,18 @@ static void slog_display_message(const slog_context_t *pCtx, const char *pInfo,
size_t nLength = 0;
char *pLog = NULL;

nLength += asprintf(&pLog, "%s%s%s%s%s", pInfo, pSeparator, pMessage, pReset, pNewLine);
nLength += asprintf(&pLog, "%s%s%s%s%s", pInfo,
pSeparator, pMessage, pReset, pNewLine);

if (pLog != NULL)
{
nCbVal = pCfg->logCallback(pLog, nLength, pCtx->eFlag, pCfg->pCallbackCtx);
nCbVal = pCfg->logCallback (
pLog,
nLength,
pCtx->eFlag,
pCfg->pCallbackCtx
);

free(pLog);
}
}
Expand All @@ -253,15 +292,15 @@ static void slog_display_message(const slog_context_t *pCtx, const char *pInfo,
if (!pCfg->nToFile || nCbVal < 0) return;
const slog_date_t *pDate = &pCtx->date;

char sFilePath[SLOG_PATH_MAX + SLOG_NAME_MAX + SLOG_DATE_MAX];
snprintf(sFilePath, sizeof(sFilePath), "%s/%s-%04d-%02d-%02d.log",
pCfg->sFilePath, pCfg->sFileName, pDate->nYear, pDate->nMonth, pDate->nDay);
if ((g_slog.pLogFile == NULL ||
g_slog.nStartDay != pDate->nDay) &&
!slog_open_file(pCfg, pDate)) return;

FILE *pFile = fopen(sFilePath, "a");
if (pFile == NULL) return;
fprintf(g_slog.pLogFile, "%s%s%s%s%s", pInfo,
pSeparator, pMessage, pReset, pNewLine);

fprintf(pFile, "%s%s%s%s%s", pInfo, pSeparator, pMessage, pReset, pNewLine);
fclose(pFile);
if (pCfg->nFlush) fflush(g_slog.pLogFile);
if (!pCfg->nKeepOpen) slog_close_file();
}

static int slog_create_info(const slog_context_t *pCtx, char* pOut, size_t nSize)
Expand All @@ -275,7 +314,7 @@ static int slog_create_info(const slog_context_t *pCtx, char* pOut, size_t nSize
if (pCfg->eDateControl == SLOG_TIME_ONLY)
{
snprintf(sDate, sizeof(sDate), "%02d:%02d:%02d.%03d ",
pDate->nHour,pDate->nMin, pDate->nSec, pDate->nUsec);
pDate->nHour, pDate->nMin, pDate->nSec, pDate->nUsec);
}
else if (pCfg->eDateControl == SLOG_DATE_FULL)
{
Expand Down Expand Up @@ -378,6 +417,15 @@ void slog_config_get(slog_config_t *pCfg)
void slog_config_set(slog_config_t *pCfg)
{
slog_lock(&g_slog);
slog_config_t *pOldCfg = &g_slog.config;

if (strncmp(pOldCfg->sFilePath, pCfg->sFilePath, sizeof(pOldCfg->sFilePath)) ||
strncmp(pOldCfg->sFileName, pCfg->sFileName, sizeof(pOldCfg->sFileName)))
{
/* Log function will open it again */
slog_close_file();
}

g_slog.config = *pCfg;
slog_unlock(&g_slog);
}
Expand Down Expand Up @@ -458,6 +506,7 @@ void slog_init(const char* pName, uint16_t nFlags, uint8_t nTdSafe)
pCfg->sSeparator[1] = '\0';
pCfg->sFilePath[0] = '.';
pCfg->sFilePath[1] = '\0';
pCfg->nKeepOpen = 0;
pCfg->nTraceTid = 0;
pCfg->nToScreen = 1;
pCfg->nNewLine = 1;
Expand All @@ -470,6 +519,9 @@ void slog_init(const char* pName, uint16_t nFlags, uint8_t nTdSafe)
const char *pFileName = (pName != NULL) ? pName : SLOG_NAME_DEFAULT;
snprintf(pCfg->sFileName, sizeof(pCfg->sFileName), "%s", pFileName);

g_slog.pLogFile = NULL;
g_slog.nStartDay = 0;

#ifdef WIN32
/* Enable color support */
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
Expand All @@ -487,9 +539,12 @@ void slog_init(const char* pName, uint16_t nFlags, uint8_t nTdSafe)
void slog_destroy()
{
slog_lock(&g_slog);

memset(&g_slog.config, 0, sizeof(g_slog.config));
g_slog.config.pCallbackCtx = NULL;
g_slog.config.logCallback = NULL;
slog_close_file();

slog_unlock(&g_slog);

if (g_slog.nTdSafe)
Expand Down
21 changes: 11 additions & 10 deletions src/slog.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extern "C" {
/* SLog version information */
#define SLOG_VERSION_MAJOR 1
#define SLOG_VERSION_MINOR 8
#define SLOG_BUILD_NUM 31
#define SLOG_BUILD_NUM 32

/* Supported colors */
#define SLOG_COLOR_NORMAL "\x1B[0m"
Expand Down Expand Up @@ -156,14 +156,15 @@ typedef struct SLogConfig {
slog_cb_t logCallback; // Log callback to collect logs
void* pCallbackCtx; // Data pointer passed to log callback

uint8_t nTraceTid; // Trace thread ID and display in output
uint8_t nToScreen; // Enable screen logging
uint8_t nNewLine; // Enable new line ending
uint8_t nUseHeap; // Use dynamic allocation
uint8_t nToFile; // Enable file logging
uint8_t nIndent; // Enable indentations
uint8_t nFlush; // Flush stdout after screen log
uint16_t nFlags; // Allowed log level flags
uint8_t nKeepOpen; // Keep file handle open for next file writes
uint8_t nTraceTid; // Trace thread ID and display in output
uint8_t nToScreen; // Enable screen logging
uint8_t nNewLine; // Enable new line ending
uint8_t nUseHeap; // Use dynamic allocation
uint8_t nToFile; // Enable file logging
uint8_t nIndent; // Enable indentations
uint8_t nFlush; // Flush stdout after screen log
uint16_t nFlags; // Allowed log level flags

char sSeparator[SLOG_NAME_MAX]; // Separator between info and log
char sFileName[SLOG_NAME_MAX]; // Output file name for logs
Expand All @@ -184,7 +185,7 @@ void slog_disable(slog_flag_t eFlag);

void slog_init(const char* pName, uint16_t nFlags, uint8_t nTdSafe);
void slog_display(slog_flag_t eFlag, const char *pFormat, ...);
void slog_destroy(); // Required only if the slog_init() called with nTdSafe > 0
void slog_destroy(); // Required only if (nTdSafe > 0 || nKeepOpen > 0)

#ifdef __cplusplus
}
Expand Down

0 comments on commit 83baf33

Please sign in to comment.