[Bleeding] Custom logging

reptor

06-07-2008 00:42:08

Hello,

What would be the best way to direct log messages coming from NxOgre to my own log?

I have my own Log object. I can direct Ogre3D and CEGUI log messages pretty easily to my own Log object, which then writes them to my own log file in my chosen format. I don't want other log files (at least not for a release version).

As examples,

with Ogre3D I can do class OgreLogListener: public Ogre::LogListener {...

With CEGUI I can do class CeguiLogListener: public CEGUI::Logger {..

...and both of them have functions which re-direct the log messages into my own Log object which then formats the messages as I wish and then writes them to the one single log file.


After looking at the NxOgre source code I am afraid that it would require modification of the NxOgre to accomplish this.

So do you have any tips how to accomplish it with NxOgre? Am I wrong and is there an easy way to do it without modifying NxOgre? Have I missed something important while reading NxOgre source code?

I think it is an important thing to have. The application must be able to control what the user of the application will be seeing, log file included.

betajaen

06-07-2008 09:18:19

Finally. Someone who wants to enquire into the Error Reporting system! Actually; It's just as easy to plugin your Log class into NxOgre as it is to Ogre or CEGUI.

First of all you need to make your Log class inherit "NxOgre::ErrorReporter", then implement these functions

void startReporting();
void report(const ErrorReport&);
void stopReporting();


startReporting and stopReporting are called when the ErrorReporter is added and removed to the list of ErrorReporters, I use it to create the header and footer HTML of the log HTML, but you can leave the function empty if so wish.

report is where the magic happens, with an attached ErrorReport (see NxOgreError.h) which gives you all the details required to add to your log. Not all ErrorReports are errors, some are Warnings or Debug information.

Once you have setup your Log class and made an instance to it, then just add it to the Error class.

mWorld->getPhysXDriver()->getError()->addReporter(myLog, false);

false is for the Error class to not to delete myLog when it shuts down. Most cases you don't want that, but for simple applications you may do.

And that's it.

Oh; if you don't want NxOgre to log to any file except your own then add this to your world constructor params "use-log: no";

reptor

06-07-2008 12:53:36

Thanks for the info. OK so it can be done without modifying NxOgre... that is good news. I should've been reading the source code more carefully.

I will have to try it soon but first... Formula One British Grand Prix!

reptor

08-07-2008 15:54:19

I use Visual C++ 2008 Express Edition.
Ogre3D 1.4.9
PhysX 2.8.1
NxOgre 1.0'21

If I use
NxOgre::Error::getInstance()->addReporter(mNxOgreLogListener, false);
It compiles fine but I will get a linker error:

Linking...
LINK : bin/debug/garage.exe not found or not built by the last incremental link; performing full link
Creating library bin/debug/garage.lib and object bin/debug/garage.exp
PhysicsWorld.obj : error LNK2001: unresolved external symbol "private: static class NxOgre::Error * NxOgre::Error::mError" (?mError@Error@NxOgre@@0PAV12@A)
bin/debug/garage.exe : fatal error LNK1120: 1 unresolved externals

It doesn't seem to matter if I use it before or after creating the NxOgre::World. The error comes both times. But I suspect the location of it has no relevance to this error? The source code file which has the code for creating NxOgre and my custom log object includes NxOgre.h. The file of mNxOgreLogListener (which is derived from NxOgre::ErrorReporter) includes NxOgreError.h.

If I comment that line out then it links without errors, and the application runs normally.

As an alternative I found that I can use this:

mWorld->getPhysXDriver()->getError()->addReporter( mNxOgreLogListener, false );

I do things in this sequence now:

1) create NxOgre::World
2) create class NxOgreLogListener: public NxOgre::ErrorReporter {
3) mWorld->getPhysXDriver()->getError()->addReporter( mNxOgreLogListener, true );

It works but the result is only partial as I see it.

As this is done after mWorld (NxOgre::World) has been created, this means that there are some log messages that will not be catched into my own log. I get NxOgre log messages into my own log now, but not the "NxOgre::PhysXDriver::_dumpVersionsToConsole" part when I compare to what I get to the NxOgre.html log file. This is a problem as I see it. This means that every NxOgre log message that can happen during creation of the NxOgre::World and whatever it includes, is not directed to my own log object.

As an example, Ogre3D requires that my custom log object is created and added to Ogre::LogManager as a listener before I create Ogre::Root if I want to get all log messages into my own log. As reference this is what Ogre3D documentation says about it:

http://www.ogre3d.org/docs/api/html/cla ... l#_details
By default, Root will instantiate a LogManager (which becomes the Singleton instance) on construction, and will create a default log based on the Root construction parameters. If you want more control, for example redirecting log output right from the start or suppressing debug output, you need to create a LogManager yourself before creating a Root instance, then create a default log. Root will detect that you've created one yourself and won't create one of its own, thus using all your logging preferences from the first instance.

Can we achieve that I get also the NxOgre log messages from the creation of the NxOgre::World into my own log?

It is not entirely clear to me in what order I should have been using this:
NxOgre::Error::getInstance()->addReporter(mNxOgreLogListener, false);

and the creation of the NxOgre::World, I am not sure if it is possible to catch also the log messages also from the creation of the NxOgre::World into my own log or not. By reading the NxOgre source code, I came to a conclusion that I can not create the NxOgre::Error by myself.

I hope this explanation isn't too messy :) I think the main points are:

1) What is the exact order in which things need to be created in order to get all of the NxOgre log messages into my own log.

2) Is it possible at all with the current design of NxOgre to get all of the NxOgre log messages into my own log.

3) Why the code line you gave me gives me a linker error. This left me puzzled if it would actually be possible to catch all NxOgre log messages to my own log, if only that line of code would work.

betajaen

08-07-2008 16:40:39

1. You have it. The Error singleton is created during the constructor, so you can only have access to it; after World has been created.

2. Yes, read below.

3. The mError singleton thing declaration must be missing from the NxOgreError.cpp.

____

Now; I can ask you. There are two ways to capture all of the ErrorReports, I'll let you decide on how it should be implemented.

a) Add a param to PhysXParams to not to initialise PhysX straight away but initialize it when a function is called; Allowing you to sneak in and register your ErrorReporter.

b) Add a param to attach the pointer of your ErrorReporter; it may replace the mUseLog param, or extend it to an enum.

reptor

08-07-2008 17:06:58

I think that it could be better to add a param to attach the pointer of the custom ErrorReporter.

It doesn't necessarily have to replace the mUseLog parameter. Both can exist. Then we can direct the log messages to our own log and have the NxOgre.html log file as well, someone might want to do this perhaps.

But it's your decision :)

betajaen

08-07-2008 17:30:42

No. It would have to be an enum to remain consistent.

enum FirstErrorReporter
{
FER_NONE,
FER_NXOGRE_LOG, // <-- Default value
FER_CUSTOM
};

FirstErrorReporter mFirstErrorReporter;
ErrorReporter mCustomFirstErrorReporterPtr;


"first-error-reporter: log"

I'll add it later.

reptor

08-07-2008 20:07:30

OK :)