|
log file for game |
William Labbett
Member #4,486
March 2004
|
Need some advice on how to deal with the log file in my game. The way I do things at the moment is : #ifdef USE_LOG_FILE logfile << "some message about something.\n"; #endif So the code only runs if there's a define for USE_LOG_FILE in a header somewhere. What I'm thinking of doing instead is :- if(use_log) { logfile << "........\n"; } Where the use_log is a variable set in the config file for the game. This way means that the code is always run, even if it's just checking the if condition. Is this way an acceptable way to do things ? I prefer it because it means the log file doesn't have to get created.
|
LennyLen
Member #5,313
December 2004
|
William Labbett said: Is this way an acceptable way to do things ? Certainly. The checks aren't going to affect the game performance, and it means the logs can easily be enabled after the application has already been deployed, which is not possible when using the preprocessor method. The only downside is that if the logs are never needed, the executable will be bigger than necessary. But the additional size is most likely insignificant, so this is a mostly moot point. Quote: I prefer it because it means the log file doesn't have to get created. That applies to both methods.
|
William Labbett
Member #4,486
March 2004
|
Thanks.
|
Slartibartfast
Member #8,789
June 2007
|
William Labbett said: #ifdef USE_LOG_FILE This is usually done like: #ifdef USE_LOG_FILE #define LOG(blah) logfile<<(blah) #else #define LOG(blah) #endif ... LOG(".....\n");
Quote: if(use_log) Also nice. You could similarly stick that into an inlined function and have an easier time typing it; You can even use varargs to make it behave more like you'd expect a logging function to behave. Though maybe I'm saying obvious things. ---- |
beoran
Member #12,636
March 2011
|
And an example in plain C: 1/*
2Log file example with allegro config file use.
3Compile with gcc on Linux:
4
5gcc forum_2.c -I /usr/local/include -L /usr/local/lib -lallegro_color -lallegro_font -lallegro_ttf -lallegro -o forum2
6
7Make an app.ini file in the executable file's directory that contains
8log=app.log and the log will be written to app.log. If the config value is
9empty, no logging takes place.
10*/
11
12#include <allegro5/allegro.h>
13#include <stdio.h>
14#include <stdarg.h>
15
16
17#define APP_CONFIG_NAME "app.ini"
18
19FILE * log_open() {
20 FILE * result;
21 ALLEGRO_CONFIG * config;
22 const char * logname;
23 config = al_load_config_file(APP_CONFIG_NAME);
24 if (!config) return NULL;
25 logname = al_get_config_value(config, NULL, "log");
26 if (logname) {
27 result = fopen(logname, "at");
28 }
29 al_destroy_config(config);
30 return result;
31}
32
33void log_close(FILE * logfile) {
34 if(logfile) fclose(logfile);
35}
36
37void log_log(FILE * logfile, char * format, ...) {
38 va_list ap;
39 if (!logfile) return;
40 va_start(ap, format);
41 vfprintf(logfile, format, ap);
42 va_end(ap);
43 fflush(logfile);
44}
45
46
47int main (void) {
48 FILE * logfile = log_open();
49 log_log(logfile, "This will be logged, but only if app.ini specifies it.\n"); log_log(logfile, "And with arguments: %d, %f\n", 11, 20.13);
50 log_close(logfile);
51 return 0;
52}
|
LennyLen
Member #5,313
December 2004
|
beoran said: And an example in plain C: That looks almost identical to mine, except that I add a timestamp to each line as it is written to the log.
|
beoran
Member #12,636
March 2011
|
Yeah, LennyLen, and with some changes and a macro or two you can get _LINE_ and _FILE_ in there as well. Just flex it to your own needs. |
Luiji99
Member #12,254
September 2010
|
Also very useful, but not vital since you can gleam it from __FILE__ and __LINE__, is __func__. However, __func__ is C99 and MSVC calls it __FUNCTION__. Luckily, Allegro 5 is awesome and will automatically define __func__ as __FUNCTION__ for MSVC and will simply define it to "???" where not supported. I'd recommend log lines like: __FILE__:__LINE__:__func__: Super important message I.e. kernel.c:1924:farbiktubennagen: Holy shit look a dog!!!!! Programming should be fun. That's why I hate Java. |
GullRaDriel
Member #3,861
September 2003
|
I like these threads. Pinned ! "Code is like shit - it only smells if it is not yours" |
Thomas Fjellstrom
Member #476
June 2000
|
Luiji99 said: Also very useful, but not vital since you can gleam it from _FILE_ and _LINE_, is _func_. However, _func_ is C99 and MSVC calls it __FUNCTION__. GCC also has __FUNCTION__ it also has __PRETTY_FUNCTION__ which helps out with C++ somewhat. -- |
William Labbett
Member #4,486
March 2004
|
Thanks for the help guys. I like if(use_log) { logfile << "Initialising tertiary subsystem 3.\n"; } It's super simple. If I have to use conditional includes then there's two versions of the program, one which can do logs and another that can't. I'd rather have one program that can do both depending on config file. I think I'll do LOG(x) (if(use_log) logfile << x << "\n";)
|
Luiji99
Member #12,254
September 2010
|
That type of #define is good, too. In fact, I'd definitely recommend that over two executables considering you want it to be enabled/disabled by the user. You could still use #define LOG(x) (use_log ? logfile << __FILE__ << ":" __LINE__ ":" << __PRETTY_FUNCTION__ << ": " << (x) : (void) 0) I'm pretty sure that putting an if statement in parenthesis is invalid. You will have to use the tertiary operator like boolean_value ? true_execution : (void) 0, as most implementations of assert do. Programming should be fun. That's why I hate Java. |
Audric
Member #907
January 2001
|
The general issue of "; in macro?" is solved by a construct, seemingly ugly but fully working: |
Luiji99
Member #12,254
September 2010
|
bamccaig
Member #7,536
July 2006
|
1class Logger
2{
3 bool enabled_;
4 std::ofstream log_;
5public:
6 Logger():
7 enabled_(false)
8 {
9 }
10
11 Logger(const std::string & file, bool enabled = true):
12 enabled_(enabled)
13 log_(file, ios::base::app)
14 {
15 }
16
17 // ... etc ...
18
19 const Logger & operator<<(const std::string & arg) const
20 {
21 if(this->enabled_)
22 {
23 this->log_ /* etc ... */ << arg << std::endl;
24 }
25
26 return *this;
27 }
28};
(Untested, but you get the idea...)
-- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
Edgar Reynaldo
Major Reynaldo
May 2007
|
I second bamccaig, although I abstract my log even further to point to any ostream and then OutputLog() retrieves a reference. OutputLog() << "Write this to the log ...." << endl; It doesn't allow for disabling the log but I usually only use the log for diagnostic purposes. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|