Skip to content

Commit 46113fd

Browse files
Added MINILOG_RAW_OUTPUT option and threadNames config param
1 parent 07f5ed3 commit 46113fd

File tree

3 files changed

+160
-109
lines changed

3 files changed

+160
-109
lines changed

CMakeLists.txt

+6
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,19 @@ cmake_minimum_required(VERSION 3.10)
33
project(minilog CXX C)
44

55
option(MINILOG_BUILD_EXAMPLE "Build example" ON)
6+
option(MINILOG_RAW_OUTPUT "Do not apply extra formatting" OFF)
67

78
message(STATUS "MINILOG_BUILD_EXAMPLE = ${MINILOG_BUILD_EXAMPLE}")
9+
message(STATUS "MINILOG_RAW_OUTPUT = ${MINILOG_RAW_OUTPUT}")
810

911
set(CMAKE_CXX_STANDARD 14)
1012
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1113
add_library(minilog minilog.cpp minilog.h)
1214

15+
if(MINILOG_RAW_OUTPUT)
16+
target_compile_definitions(minilog PUBLIC "-DMINILOG_RAW_OUTPUT=1")
17+
endif()
18+
1319
if(MINILOG_BUILD_EXAMPLE)
1420
set(CMAKE_CXX_STANDARD 20)
1521
add_executable(minilog_example example.cpp)

minilog.cpp

+73-44
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,12 @@ bool minilog::initialize(const char* fileName, const minilog::LogConfig& cfg)
146146
if (logFile)
147147
deinitialize();
148148

149-
logFile = fopen(fileName, "w");
149+
if (fileName) {
150+
logFile = fopen(fileName, "w");
150151

151-
if (!logFile)
152-
return false;
152+
if (!logFile)
153+
return false;
154+
}
153155

154156
minilog::threadNameSet(cfg.mainThreadName);
155157

@@ -158,8 +160,7 @@ bool minilog::initialize(const char* fileName, const minilog::LogConfig& cfg)
158160
if (cfg.htmlLog)
159161
writeHTMLIntro(cfg.htmlPageTitle, cfg.htmlPageHeader);
160162

161-
if (cfg.writeIntro)
162-
{
163+
if (cfg.writeIntro) {
163164
log(minilog::Log, "minilog: initializing ...");
164165
log(minilog::Log, "minilog: log file: %s", fileName);
165166
}
@@ -302,6 +303,68 @@ const char* minilog::threadNameGet()
302303
return ctx->threadName ? ctx->threadName : "";
303304
}
304305

306+
static void printMessageToConsole(minilog::eLogLevel level, const char* msg, const ThreadLogContext* ctx)
307+
{
308+
using namespace minilog;
309+
310+
if (level >= config.logLevelPrintToConsole) {
311+
if (config.coloredConsole) {
312+
#if OS_WINDOWS
313+
auto getAttr = [](minilog::eLogLevel level) -> WORD {
314+
switch (level) {
315+
case Paranoid:
316+
return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
317+
case Debug:
318+
return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
319+
case Log:
320+
return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
321+
case Warning:
322+
return FOREGROUND_RED | FOREGROUND_INTENSITY;
323+
case FatalError:
324+
return FOREGROUND_RED | FOREGROUND_INTENSITY;
325+
}
326+
return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
327+
};
328+
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), getAttr(level));
329+
#else
330+
if (level >= Warning)
331+
printf("\033[1;31m");
332+
#endif // OS_WINDOWS
333+
}
334+
335+
// clang-format off
336+
#if defined(MINILOG_RAW_OUTPUT)
337+
# define FORMATSTR_THREAD_NAME "(%s):%s"
338+
# define FORMATSTR_THREAD_ID "(%llu):%s"
339+
# define FORMATSTR_NO_THREAD "%s"
340+
#else
341+
# define FORMATSTR_THREAD_NAME "(%s):%s\n"
342+
# define FORMATSTR_THREAD_ID "(%llu):%s\n"
343+
# define FORMATSTR_NO_THREAD "%s\n"
344+
#endif
345+
// clang-format on
346+
347+
if (config.threadNames) {
348+
if (ctx->threadName) {
349+
printf(FORMATSTR_THREAD_NAME, ctx->threadName, msg);
350+
} else {
351+
printf(FORMATSTR_THREAD_ID, (unsigned long long)ctx->threadId, msg);
352+
}
353+
} else {
354+
printf(FORMATSTR_NO_THREAD, msg);
355+
}
356+
357+
if (config.coloredConsole) {
358+
#if OS_WINDOWS
359+
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
360+
#else
361+
if (level >= Warning)
362+
printf("\033[0m");
363+
#endif // OS_WINDOWS
364+
}
365+
}
366+
}
367+
305368
void minilog::log(eLogLevel level, const char* format, ...)
306369
{
307370
va_list args;
@@ -334,45 +397,7 @@ void minilog::log(eLogLevel level, const char* format, va_list args)
334397
ctx->hasLogsOnThisLevel[ctx->procsNestingLevel] = true;
335398

336399
writeMessageToLog(level, buffer, ctx);
337-
338-
if (level >= config.logLevelPrintToConsole)
339-
{
340-
if (config.coloredConsole)
341-
{
342-
#if OS_WINDOWS
343-
auto getAttr = [](minilog::eLogLevel level) -> WORD
344-
{
345-
switch (level) {
346-
case Paranoid: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
347-
case Debug: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
348-
case Log: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
349-
case Warning: return FOREGROUND_RED | FOREGROUND_INTENSITY;
350-
case FatalError: return FOREGROUND_RED | FOREGROUND_INTENSITY;
351-
}
352-
return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
353-
};
354-
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), getAttr(level));
355-
#else
356-
if (level >= Warning)
357-
printf("\033[1;31m");
358-
#endif // OS_WINDOWS
359-
}
360-
361-
if (ctx->threadName)
362-
printf("(%s):%s\n", ctx->threadName, buffer);
363-
else
364-
printf("(%llu):%s\n", (unsigned long long)ctx->threadId, buffer);
365-
366-
if (config.coloredConsole)
367-
{
368-
#if OS_WINDOWS
369-
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
370-
#else
371-
if (level >= Warning)
372-
printf("\033[0m");
373-
#endif // OS_WINDOWS
374-
}
375-
}
400+
printMessageToConsole(level, buffer, ctx);
376401

377402
invokeCallbacks(level, msg);
378403
}
@@ -401,6 +426,10 @@ void minilog::logRaw(eLogLevel level, const char* format, va_list args)
401426
ctx->hasLogsOnThisLevel[ctx->procsNestingLevel] = true;
402427

403428
writeMessageToLog(level, buffer, ctx);
429+
430+
#if defined(MINILOG_RAW_OUTPUT)
431+
printMessageToConsole(level, buffer, ctx);
432+
#endif // MINILOG_RAW_OUTPUT
404433
}
405434

406435
bool minilog::callstackPushProc(const char* name)

minilog.h

+81-65
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
#pragma once
22

33
/**
4-
minilog v1.0.2
4+
minilog v1.1.0
55
66
MIT License
7-
Copyright (c) 2021-2022 Sergey Kosarevsky
7+
Copyright (c) 2021-2023 Sergey Kosarevsky
8+
https://github.com/corporateshark/minilog
89
**/
910

1011
#if defined(MINILOG_ENABLE_VA_LIST)
@@ -13,80 +14,95 @@
1314

1415
namespace minilog
1516
{
16-
enum eLogLevel {
17-
Paranoid = 0,
18-
Debug = 1,
19-
Log = 2,
20-
Warning = 3,
21-
FatalError = 4
22-
};
23-
struct LogConfig {
24-
eLogLevel logLevel = minilog::Debug; // everything >= this level goes to the log file
25-
eLogLevel logLevelPrintToConsole = minilog::Log; // everything >= this level is printed to the console (cannot be lower than logLevel)
26-
bool forceFlush = true; // call fflush() after every log() and logRaw()
27-
bool writeIntro = true;
28-
bool writeOutro = true;
29-
bool coloredConsole = true; // apply colors to console output (Windows, escape sequences)
30-
bool htmlLog = false; // output everything as HTML instead of plain text
31-
const char* htmlPageTitle = "Minilog"; // just the title of the resulting HTML page
32-
const char* htmlPageHeader = nullptr; // override default HTML header
33-
const char* htmlPageFooter = nullptr; // override default HTML footer
34-
const char* mainThreadName = "MainThread"; // just the name of the thread which calls minilog::initialize()
35-
};
3617

37-
bool initialize(const char* fileName, const LogConfig& cfg); // non-thread-safe
38-
void deinitialize(); // non-thread-safe
18+
enum eLogLevel {
19+
Paranoid = 0,
20+
Debug = 1,
21+
Log = 2,
22+
Warning = 3,
23+
FatalError = 4
24+
};
25+
struct LogConfig {
26+
eLogLevel logLevel = minilog::Debug; // everything >= this level goes to the log file
27+
eLogLevel logLevelPrintToConsole = minilog::Log; // everything >= this level is printed to the console (cannot be lower than logLevel)
28+
bool forceFlush = true; // call fflush() after every log() and logRaw()
29+
bool writeIntro = true;
30+
bool writeOutro = true;
31+
bool coloredConsole = true; // apply colors to console output (Windows, escape sequences)
32+
bool htmlLog = false; // output everything as HTML instead of plain text
33+
bool threadNames = true; // prefix log messages with thread names
34+
const char* htmlPageTitle = "Minilog"; // just the title of the resulting HTML page
35+
const char* htmlPageHeader = nullptr; // override default HTML header
36+
const char* htmlPageFooter = nullptr; // override default HTML footer
37+
const char* mainThreadName = "MainThread"; // just the name of the thread which calls minilog::initialize()
38+
};
3939

40-
void log(eLogLevel level, const char* format, ...); // thread-safe
41-
void logRaw(eLogLevel level, const char* format, ...); // thread-safe
40+
bool initialize(const char* fileName, const LogConfig& cfg); // non-thread-safe
41+
void deinitialize(); // non-thread-safe
42+
43+
void log(eLogLevel level, const char* format, ...); // thread-safe
44+
void logRaw(eLogLevel level, const char* format, ...); // thread-safe
4245
#if defined(MINILOG_ENABLE_VA_LIST)
43-
void log(eLogLevel level, const char* format, va_list args); // thread-safe
44-
void logRaw(eLogLevel level, const char* format, va_list args); // thread-safe
45-
#endif // MINILOG_ENABLE_VA_LIST
46+
void log(eLogLevel level, const char* format, va_list args); // thread-safe
47+
void logRaw(eLogLevel level, const char* format, va_list args); // thread-safe
48+
#endif // MINILOG_ENABLE_VA_LIST
4649

47-
/// threads management
48-
void threadNameSet(const char* name); // thread-safe
49-
const char* threadNameGet(); // thread-safe
50-
51-
/// callstack management
52-
bool callstackPushProc(const char* name); // thread-safe
53-
void callstackPopProc(); // thread-safe
54-
unsigned int callstackGetNumProcs(); // thread-safe
55-
const char* callstackGetProc(unsigned int i); // thread-safe
56-
57-
/// set up custom callbacks
58-
struct LogCallback {
59-
typedef void (*callback_t)(void*, const char*);
60-
callback_t funcs[minilog::FatalError + 1] = {};
61-
void* userData = nullptr;
62-
};
63-
bool callbackAdd(const LogCallback& cb); // non-thread-safe
64-
void callbackRemove(void* userData); // non-thread-safe
65-
66-
/// RAII wrapper around callstackPushProc() and callstackPopProc()
67-
class CallstackScope {
68-
enum { kBufferSize = 256 };
69-
public:
70-
explicit CallstackScope(const char* funcName);
71-
explicit CallstackScope(const char* funcName, const char* format, ...);
72-
inline ~CallstackScope() { minilog::callstackPopProc(); }
73-
private:
74-
char buffer_[kBufferSize];
50+
/// threads management
51+
void threadNameSet(const char* name); // thread-safe
52+
const char* threadNameGet(); // thread-safe
53+
54+
/// callstack management
55+
bool callstackPushProc(const char* name); // thread-safe
56+
void callstackPopProc(); // thread-safe
57+
unsigned int callstackGetNumProcs(); // thread-safe
58+
const char* callstackGetProc(unsigned int i); // thread-safe
59+
60+
/// set up custom callbacks
61+
struct LogCallback {
62+
typedef void (*callback_t)(void*, const char*);
63+
callback_t funcs[minilog::FatalError + 1] = {};
64+
void* userData = nullptr;
65+
};
66+
bool callbackAdd(const LogCallback& cb); // non-thread-safe
67+
void callbackRemove(void* userData); // non-thread-safe
68+
69+
/// RAII wrapper around callstackPushProc() and callstackPopProc()
70+
class CallstackScope
71+
{
72+
enum {
73+
kBufferSize = 256
7574
};
75+
76+
public:
77+
explicit CallstackScope(const char* funcName);
78+
explicit CallstackScope(const char* funcName, const char* format, ...);
79+
inline ~CallstackScope() { minilog::callstackPopProc(); }
80+
81+
private:
82+
char buffer_[kBufferSize];
83+
};
7684
} // namespace minilog
7785

86+
// clang-format off
87+
#if defined(MINILOG_RAW_OUTPUT)
88+
# define MINILOG_LOG_PROC minilog::logRaw
89+
#else
90+
# define MINILOG_LOG_PROC minilog::log
91+
#endif // MINILOG_RAW_OUTPUT
92+
7893
#if !defined(MINILOG_DISABLE_HELPER_MACROS)
7994

8095
#if defined(__GNUC__) && !defined(EMSCRIPTEN) && !defined(__clang__)
81-
# define LLOGP(...) minilog::log(minilog::Paranoid, ##__VA_ARGS__)
82-
# define LLOGD(...) minilog::log(minilog::Debug, ##__VA_ARGS__)
83-
# define LLOGL(...) minilog::log(minilog::Log, ##__VA_ARGS__)
84-
# define LLOGW(...) minilog::log(minilog::Warning, ##__VA_ARGS__)
96+
# define LLOGP(...) MINILOG_LOG_PROC(minilog::Paranoid, ##__VA_ARGS__)
97+
# define LLOGD(...) MINILOG_LOG_PROC(minilog::Debug, ##__VA_ARGS__)
98+
# define LLOGL(...) MINILOG_LOG_PROC(minilog::Log, ##__VA_ARGS__)
99+
# define LLOGW(...) MINILOG_LOG_PROC(minilog::Warning, ##__VA_ARGS__)
85100
#else
86-
# define LLOGP(...) minilog::log(minilog::Paranoid, ## __VA_ARGS__)
87-
# define LLOGD(...) minilog::log(minilog::Debug, ## __VA_ARGS__)
88-
# define LLOGL(...) minilog::log(minilog::Log, ## __VA_ARGS__)
89-
# define LLOGW(...) minilog::log(minilog::Warning, ## __VA_ARGS__)
101+
# define LLOGP(...) MINILOG_LOG_PROC(minilog::Paranoid, ## __VA_ARGS__)
102+
# define LLOGD(...) MINILOG_LOG_PROC(minilog::Debug, ## __VA_ARGS__)
103+
# define LLOGL(...) MINILOG_LOG_PROC(minilog::Log, ## __VA_ARGS__)
104+
# define LLOGW(...) MINILOG_LOG_PROC(minilog::Warning, ## __VA_ARGS__)
90105
#endif
91106

92107
#endif // MINILOG_DISABLE_HELPER_MACROS
108+
// clang-format on

0 commit comments

Comments
 (0)