afritz1 / OpenTESArena

Open-source re-implementation of The Elder Scrolls: Arena.
MIT License
988 stars 68 forks source link

Log console output to a file #86

Closed Thunderforge closed 1 year ago

Thunderforge commented 7 years ago

OpenTESArena writes warning messages, error reports, and other information to the console via the Debug class. This has several major downsides:

I recommend that we write all of this console output to a log file in order to solve these problems. We can still write to the console as well if desired.

Unfortunately, there isn't an SDL_GetLogPath() or anything. The recommended log locations for each platform are:

We would need to determine the proper location based on the platform.

afritz1 commented 7 years ago

It could probably go next to the options folder via SDL_GetPrefPath(), but the problem with that is that it's a "global" file, so it's affected by all instances of the program, and it'd only be reliable for the most recently run instance. Unless... it would have a timestamp as a unique identifier. That might work.

Thunderforge commented 7 years ago

Most apps that I see either clear the log out at the beginning of a session (this is what OpenMW does), so I'm not sure that timestamps are really necessary since I'm guessing you won't have two versions of OpenTESArena running simultaneously. I suppose we could use SDL_GetPrefPath() in a pinch, but the downside of using that is since it's not in an expected place, it won't be picked up by the Mac (and Linux?) console viewers.

afritz1 commented 7 years ago

I'd like to avoid adding platform-specific paths to the program, and try to keep them based on user settings instead. I'm not sure a path in options.txt would work well though, because it would need to be edited for each platform both in the repository and in release builds.

Thunderforge commented 7 years ago

Looks like there is already some preliminary work for logging in the Debug class, like an unused LOG_FILENAME String constant and the__file__ parameter. Would this system work with what you were planning?

afritz1 commented 7 years ago

LOG_FILENAME was just something I thought would be needed eventually (like now, I guess). It's not used yet though.

The __file__ parameters are always just __FILE__ received from the debug macros. They say the name of the file the debug macro is in, so it isn't related to logging.

afritz1 commented 7 years ago

See Platform::getLogPath() in Platform.cpp, commit 914f7000925871900f2bc834b098ec76fea888e4.

I think the next step is to have the Debug methods that write to console also append to some new log.txt file. That log.txt file will be cleared on program start-up. If the user wants to store previous print-outs, then they can just copy the file.

abelsromero commented 7 years ago

Wouldn't it be easier to use some logging library? I had some bad times using custom logging solutions and then realizing that on top of writing to a file, you want it to be fast, thread safe, non blocking, etc..

afritz1 commented 7 years ago

Oh, I didn't plan on having that big of a scope for message logging yet. Just for warnings and errors, which happen infrequently. Maybe when IO performance becomes a problem, then using a custom library will be necessary?

Thunderforge commented 7 years ago

I've had similar experiences as @abelsromero and would prefer that we use a logging library from the start. As the project grows, be relying on log files more and more to diagnose bugs that users are having. If we need to add it in eventually, I'd rather just add it in now.

afritz1 commented 7 years ago

I did some quick searching and found a couple C++ logging libraries. I'd like for it to be a single header file, preferably designed for C++11. I'll look more into it later today.

Thunderforge commented 7 years ago

Easylogging++ seems to fit your requirement of being only a single header file and C++. Every other framework I see is multiple files, but have benefits by being very fast and/or crash-proof.

Thunderforge commented 7 years ago

Just found out that SDL has a built-in logging framework. Does that serve our purposes?

abelsromero commented 7 years ago

Just found out that SDL has a built-in logging framework. Does that serve our purposes?

Seems like a good option

afritz1 commented 7 years ago

Maybe. I see SDL_LogSetOutputFunction, which lets us override the default SDL logging function, but overall I don't see how it's different from my existing Debug class. I don't see any kind of extra features like speed, thread-safety, or anything. It looks like it just offers a basic interface for logging with different priorities, unless I'm missing something?

afritz1 commented 1 year ago

Added log file support to the Debug class in 0d7c9352b1f87ef3a29a2a69208a720261eb0bbf and checked that it works on Windows, macOS, and Linux. It also deletes the oldest log upon passing 10 files. It's blocking but the engine writes so little that I'm not worried, and if it does need improvement, I can add a std::thread.