ofLog coloured output

I think ofLog console output could be coloured base on the log level. I’ve coded it for Windows and it looks like this:

I’ve coded it for windows, touching the ofLog.cpp file, it works for the following commands:

ofLog(OF_LOG_VERBOSE, "Verbose message");
ofLog(OF_LOG_WARNING, "Jon Snow knows nothing");
ofLog(OF_LOG_NOTICE, "Locke & Key rulez!");
ofLog(OF_LOG_ERROR, "Not so bad error");
ofLog(OF_LOG_FATAL_ERROR, "these aren't the droids you're looking for");

This is the code involved:

//ofLog.cpp line 272
void ofConsoleLoggerChannel::log(ofLogLevel level, const string & module, const char* format, va_list args){
	//thanks stefan!
	//http://www.ozzu.com/cpp-tutorials/tutorial-writing-custom-printf-wrapper-function-t89166.html

#ifdef _WIN32 || _WIN64
	HANDLE hConsole;
	hConsole = GetStdHandle(level < OF_LOG_ERROR ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
/*
bit 0 - foreground blue
bit 1 - foreground green
bit 2 - foreground red
bit 3 - foreground intensity

bit 4 - background blue
bit 5 - background green
bit 6 - background red
bit 7 - background intensity
*/
	switch (level)
	{
	case OF_LOG_VERBOSE:
		SetConsoleTextAttribute(hConsole, 15);
		break;
	case OF_LOG_NOTICE:
		SetConsoleTextAttribute(hConsole, 11);
		break;
	case OF_LOG_WARNING:
		SetConsoleTextAttribute(hConsole, 14);
		break;
	case OF_LOG_ERROR:
		SetConsoleTextAttribute(hConsole, 12);
		break;
	case OF_LOG_FATAL_ERROR:
		SetConsoleTextAttribute(hConsole, 192);
		break;
	case OF_LOG_SILENT:
		break;
	default:
		break;
	}
#endif

	FILE* out = level < OF_LOG_ERROR ? stdout : stderr;
	fprintf(out, "[%s] ", ofGetLogLevelName(level, true).c_str());
	if(module != ""){
		fprintf(out, "%s: ", module.c_str());
	}
#ifdef _WIN32 || _WIN64
	SetConsoleTextAttribute(hConsole, 15);
#endif
	vfprintf(out, format, args);
	fprintf(out, "\n");
}

What do you think? Needs per-platform coding, I think the system("color %d") call, would work for linux and maybe also mac? Maybe it isn’t a necessary feature but it comes in handy if you have too many messages.

Best!

3 Likes

I’ve coded linux/Mac snippets for this. Can anyone try this code to see if it works on those platforms? If all goes well I’ll try and make a contribution out of it.

PS: How to change console output color: Linux|Mac, Windows

//ofLog.cpp line 272
void ofConsoleLoggerChannel::log(ofLogLevel level, const string & module, const char* format, va_list args){
	//thanks stefan!
	//http://www.ozzu.com/cpp-tutorials/tutorial-writing-custom-printf-wrapper-function-t89166.html

#ifdef _WIN32 || _WIN64
	HANDLE hConsole;
	hConsole = GetStdHandle(level < OF_LOG_ERROR ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
/*
bit 0 - foreground blue
bit 1 - foreground green
bit 2 - foreground red
bit 3 - foreground intensity

bit 4 - background blue
bit 5 - background green
bit 6 - background red
bit 7 - background intensity
*/
	switch (level)
	{
	case OF_LOG_VERBOSE:
		SetConsoleTextAttribute(hConsole, 15);
		break;
	case OF_LOG_NOTICE:
		SetConsoleTextAttribute(hConsole, 11);
		break;
	case OF_LOG_WARNING:
		SetConsoleTextAttribute(hConsole, 14);
		break;
	case OF_LOG_ERROR:
		SetConsoleTextAttribute(hConsole, 12);
		break;
	case OF_LOG_FATAL_ERROR:
		SetConsoleTextAttribute(hConsole, 192);
		break;
	case OF_LOG_SILENT:
		break;
	default:
		break;
	}
#endif
#ifdef __linux__ || TARGET_OS_MAC
	switch (level)
	{
	case OF_LOG_VERBOSE:
		cout << "\033[37m";
		break;
	case OF_LOG_NOTICE:
		cout << "\033[36m";
		break;
	case OF_LOG_WARNING:
		cout << "\033[33m";
		break;
	case OF_LOG_ERROR:
		cout << "\033[31m";
		break;
	case OF_LOG_FATAL_ERROR:
		cout << "\033[1m\033[31m";
		break;
	case OF_LOG_SILENT:
		break;
	default:
		break;
	}
#endif

	FILE* out = level < OF_LOG_ERROR ? stdout : stderr;
	fprintf(out, "[%s] ", ofGetLogLevelName(level, true).c_str());
	if(module != ""){
		fprintf(out, "%s: ", module.c_str());
	}
#ifdef _WIN32 || _WIN64
	SetConsoleTextAttribute(hConsole, 15);
#endif
#ifdef __linux__ || TARGET_OS_MAC
	cout << "\033[0m";
#endif
	vfprintf(out, format, args);
	fprintf(out, "\n");
}

@chuckleplant I am interested in coloured console outputs. I just tried your snippet on osx and it did not work. I will check the ofLog class later and give it another try. Is this still working for you?

Still works but this is only for Windows I’m afraid. There must be a similar way to do it for OSX, on a previous message I linked this, but never tried. If you please tell! :smiley:

the ofxUnitTests addon has a log channel that does this for osx and linux

I just streamed \033[37m to the console and the color changed, so i guess it should not be too hard to get this working on osx too.

The only reason not to implement this on every platform would be performance, logging can get heavy real quick.

@arturo Thanks for the hint. I will go with this for now.
@chuckleplant I am aware of the performance issue, it just does not matter for my project.
I do not think this should be the default, but having this in a little addon is quite useful.

Thanks a lot.