Jump to content

custom logging system


photo

Recommended Posts

Hi

Is there any way to redirect unigine logs to our own logging system? I need to create unified logging.
So, the ideal would be something like a registration log handler or functor.

                                                                                                                 thank you  Aargh

Link to comment

Hi Morbid

Yes that is the target state. Our app is already using its log system, and it would be perfect if we could even connect unigine logging to it.

As I wrote above, something like redirecting logs would be ideal.

                                                                                                                                aargh

Edited by aargh
Link to comment

Hi

Thanks, it works perfectly, only it can't catch messages from engine start to the interpreter's start.

If it was similar to a callback on the Log class....   ;-)

                                                                                                                    aargh

Link to comment

Hi

Extra effort doesn't matter if there's a way to do it. Please add more details.

If I understand it correctly, it will be redirecting stdout to file or named pipe

                                                                                                          aargh

Link to comment

Hello aargh,

Yes, stdout can be redirected to file or pipe. There's nothing Unigine specific here. This snippet seems to be working for Windows:

#include <windows.h>
#include <io.h>
#include <functional>
#include <iostream>

#define STDOUT_FILENO 1
#define STDERR_FILENO 2

enum StdHandleToRedirect
{
	STDOUT, STDERR
};

class StdRedirect
{
public:
	/// Assumes the specified handle is still assigned to the default FILENO (STDOUT_FILENO/STDERR_FILENO)
	/// TODO allow redirection in every case
	/// callback will run in a new thread and will be notified of any character input to
	/// the specified std handle
	StdRedirect(StdHandleToRedirect h, std::function<void(char)> callback): callback(callback)
	{
		CreatePipe(&readablePipeEnd, &writablePipeEnd, 0, 0);
		SetStdHandle(h == STDOUT ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE, writablePipeEnd);

		// Redirect (TODO: ERROR CHECKING)
		int writablePipeEndFileStream = _open_osfhandle((long)writablePipeEnd, 0);
		FILE *writablePipeEndFile = NULL;
		writablePipeEndFile = _fdopen(writablePipeEndFileStream, "wt");
		_dup2(_fileno(writablePipeEndFile), h == STDOUT ? STDOUT_FILENO : STDERR_FILENO);

		CreateThread(0, 0, (LPTHREAD_START_ROUTINE)stdreader, this, 0, 0);
	}

	// TODO implement destructor, cleanup, reset

private:
	// DWORD (WINAPI *PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter)
	static void WINAPI stdreader(StdRedirect *redirector)
	{
		while (1)
		{
			char c;
			DWORD read;
			::fflush(NULL); // force current stdout to become readable
			// TODO add error handling
			ReadFile(redirector->readablePipeEnd, (void *)& c, 1, &read, 0); // this blocks until input is available
			if (read == 1)
				redirector->callback(c);
		}
	}

	HANDLE readablePipeEnd, writablePipeEnd;
	const std::function<void(char)> callback;
};
Unigine::String buf;
std::function<void(char)> toOutputDebugString = [&](char x)
{
	buf.append(x);
};
StdRedirect so(STDOUT, toOutputDebugString);
StdRedirect se(STDERR, toOutputDebugString);

 

  • Like 1
Link to comment

Hi

Thank you. This is fantastic reply.

                                                 aargh

  • Like 1
Link to comment
×
×
  • Create New...