Creating of logging system

Started by
14 comments, last by cozzie 7 years, 5 months ago

Do you keep an eye out on both 'streams', or do you combine logging information for API's and your own framework?

It can be valuable to have the (time) order in which all operations occurred. This is mainly true in a multithreading, and/or networking environment.

Advertisement
OK, clear. But that doesn't answer the question :)

Would you combine logging for your own framework/engine and the API's/VSdebugger output?

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

In an ideal world, APIs wouldn't produce any logging output without you having the ability to configure it.

In the real world where APIs don't respect that, redirecting stdout and stderr is standard (and UNIX fans may argue that is in fact the preferred method).

If you can easily get everything in one file, and those files aren't too big to work with, do so. If not, have multiple files.

Would you combine logging for your own framework/engine and the API's/VSdebugger output?

My preference is to have those outputs active at the same time. In your case were you are using Easlyogging++, you can just add OutputDebugString in their code right next to where it prints it out.

As a bonus, you could add an option for command line (or ini file) to turn outputs off. This way, you can disable file out, but keep VC++ output or vice versa. It's a nice to have but strictly not necessary.

Making a game is hard. Speaking from personal experienced, it is easy to get sidetracked and spend time on that sort of things. Stay focus and stay on track :)

Thanks, this really helps in going further

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

For who's interested/ reuse, I've been playing around with Easylogging++ and with a minor tweak (read further on) it does the following for me:

Debug:

- outputs LOG(INFO), LOG(ERROR) and LOG(DEBUG) to both the filestream and the VS debugger output

-- the VS debugger output reacts on the configuration parameter: "TO_STANDARD_OUTPUT"

Release:

- outputs only LOG(INFO) and LOG(ERROR) to only the filestream

You also have the easy possibility to create own 'loggers' / aka identifying your own systems in the logging output.

This is the only tweak you have to do in the Easylogging++ header:


// ORIGINAL

                    if (m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(m_data->logMessage()->level())) 
					{
						if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput))
							m_data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, m_data->logMessage()->level());
						
						ELPP_COUT << ELPP_COUT_LINE(logLine);
                    }

// TWEAKED

                    if (m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(m_data->logMessage()->level())) 
					{
						if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput))
							m_data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, m_data->logMessage()->level());
						
						ELPP_COUT << ELPP_COUT_LINE(logLine);
						#ifdef _DEBUG
						OutputDebugStringA(logLine.c_str());
						#endif
                    }

With the example code:


#define  ELPP_NO_DEFAULT_LOG_FILE 
#define _ELPP_THREAD_SAFE

#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
	// register new logger
	el::Logger* rendererLogger = el::Loggers::getLogger("Renderer");
	if(rendererLogger == nullptr) { } // handle error here
	
	// Load configuration from file
    el::Configurations conf("mylog.conf");
    // Reconfigure single logger
    el::Loggers::reconfigureLogger("default", conf);
    // Actually reconfigure all loggers instead
    el::Loggers::reconfigureAllLoggers(conf);
    // Now all the loggers will use configuration from file

	
	LOG(DEBUG) << "My first debug log line!";
	CLOG(INFO, "Renderer") << "My first info log line!";
	LOG(ERROR) << "My first error log line!";

    return 1;
}

And config file:


* GLOBAL:
   FORMAT               =  "%datetime [%level] [%logger] %msg"
   FILENAME             =  "logs/your.log"
   ENABLED              =  true
   TO_FILE              =  true
   TO_STANDARD_OUTPUT   =  true
   MILLISECONDS_WIDTH   =  2
   PERFORMANCE_TRACKING =  true
   MAX_LOG_FILE_SIZE    =  2097152 ## 2MB - Comment starts with two hashes (##)
   LOG_FLUSH_THRESHOLD  =  100 ## Flush after every 100 logs
* DEBUG:
   FORMAT               =  "%datetime [%level] [%logger] %msg File:%fbase,Line:%line,Func:%func"

Sample output:


2016-11-10 21:00:17,12 [DEBUG] [default] My first debug log line! File:main.cpp,Line:30,Func:int __stdcall WinMain(struct HINSTANCE__ *,struct HINSTANCE__ *,char *,int)
2016-11-10 21:00:17,13 [INFO ] [Renderer] My first info log line!
2016-11-10 21:00:17,14 [ERROR] [default] My first error log line!

All in all, a nice and flexible solution with gives be best of both worlds (which in this case I was looking for).

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

This topic is closed to new replies.

Advertisement