aargh Posted May 23, 2019 Share Posted May 23, 2019 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
morbid Posted May 24, 2019 Share Posted May 24, 2019 Hello aargh, May I ask you to elaborate on this? How do you see a final result? As a new log file where you can see all UNIGINE log messages and messages from your application? Thanks. How to submit a good bug report --- FTP server for test scenes and user uploads: ftp://files.unigine.com user: upload password: 6xYkd6vLYWjpW6SN Link to comment
aargh Posted May 24, 2019 Author Share Posted May 24, 2019 (edited) 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 May 24, 2019 by aargh Link to comment
morbid Posted May 27, 2019 Share Posted May 27, 2019 You can add a callback for any message and implement desired logic for custom console or log file: https://developer.unigine.com/en/docs/2.8/api/library/engine/class.console?rlang=cpp#addOutputCallback_OutputCallback_void_ptr Thanks! How to submit a good bug report --- FTP server for test scenes and user uploads: ftp://files.unigine.com user: upload password: 6xYkd6vLYWjpW6SN Link to comment
aargh Posted May 27, 2019 Author Share Posted May 27, 2019 1 hour ago, morbid said: You can add a callback for any message and implement desired logic for custom console or log file: https://developer.unigine.com/en/docs/2.8/api/library/engine/class.console?rlang=cpp#addOutputCallback_OutputCallback_void_ptr Thanks! Thanks for the pointer, I'll try. Link to comment
aargh Posted May 27, 2019 Author Share Posted May 27, 2019 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
morbid Posted May 27, 2019 Share Posted May 27, 2019 Do you need this info as well? How to submit a good bug report --- FTP server for test scenes and user uploads: ftp://files.unigine.com user: upload password: 6xYkd6vLYWjpW6SN Link to comment
aargh Posted May 28, 2019 Author Share Posted May 28, 2019 On 5/27/2019 at 10:06 AM, morbid said: Do you need this info as well? Yes it would be useful Link to comment
morbid Posted June 3, 2019 Share Posted June 3, 2019 I've checked with the engine team. You can't get these messages (from engine start to the interpreter's start) with standard API. In theory, you can take them through stdout, but it will require some extra effort from your side. Thanks. How to submit a good bug report --- FTP server for test scenes and user uploads: ftp://files.unigine.com user: upload password: 6xYkd6vLYWjpW6SN Link to comment
aargh Posted June 3, 2019 Author Share Posted June 3, 2019 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
andrey-kozlov Posted June 4, 2019 Share Posted June 4, 2019 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); 1 Link to comment
aargh Posted June 4, 2019 Author Share Posted June 4, 2019 Hi Thank you. This is fantastic reply. aargh 1 Link to comment
Recommended Posts