Advertisement
RefresherTowel

Custom Debugging Log File Generator in GML

Nov 13th, 2020 (edited)
3,350
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*** Custom Debugging Log File Generator ***
  2. This set of scripts replaces show_debug_message() in GML and creates a custom log file that holds a lot more information than a simple show_debug_message(). Here's an example output of a log file:
  3.  
  4.  
  5.  
  6.  
  7.  
  8. ********* THE LOG FILE *********/
  9.  
  10. -- SPECS START --
  11.  
  12. Logfile Name: Y:\Spaceslingers_Steam_Version_6AE9EECB_YYC\\Log\log_14112020133855.logfile
  13. Log Time: 14-11-2020(13h-38m-55s)
  14. Game Version: 0.95 // This is the game version you've entered under the Options settings in GMS
  15. OS Version: 655360
  16. OS Language: en
  17. OS Region: AU
  18. OS Data: // Read this page for info on the below numbers: http://127.0.0.1:51290/index.html?page=source%2f_build/3_scripting%2f4_gml_reference%2fmiscellaneous%2fos_get_info.html
  19. 838866018
  20. bd496841-475e-4ff4-8ce2-da95a970930e
  21. 4318
  22. 072B1308
  23. 072B04FC
  24. 5121
  25. 2189754368
  26. 161
  27. NVIDIA GeForce GTX 960
  28. 0
  29. Working Dir: Y:\Spaceslingers_Steam_Version_6AE9EECB_YYC\
  30. Steam User: euphoria_syndrome
  31. Steam User ID: 111111111111111
  32. Steam Account Cloud Enabled: 1
  33. Steam Game Cloud Enabled: 1
  34. Steam Cloud Quota Available: 4992948
  35. Steam Available Languages: english
  36. Steam Current Game Language: english
  37. Steam User Logged On: 1
  38.  
  39. -- SPECS END --
  40.  
  41.  
  42. --- LOG START ---
  43.  
  44. ** Running Time 418 ** // 418 milliseconds since the game was booted
  45. This is an info log. // INFO -- Callstack:
  46. >>gml_Object_master_Create_0:159 // Called from an object called master, in the Create Event at line 159
  47.  
  48. ** Running Time 423 **
  49. This is an error log. // ERROR -- Callstack:
  50. >>gml_Object_master_Create_0:160 // Called from an object called master, in the Create Event at line 160
  51.  
  52. ** Running Time 428 **
  53. This is an error log inside a script named load_steam_save(). // ERROR -- Callstack:
  54. >>>>gml_Script_load_steam_save:5 // Called from inside a script called load_steam_save at line 5
  55. >>gml_Object_master_Create_0:162 // load_steam_save script was called from an object called master, in the Create Event at line 162
  56.  
  57. ** Running Time 591 **
  58. This is a log in another object called obj_title. // ERROR -- Callstack:
  59. >>gml_Object_obj_title_Create_0:4 // Called from an object called obj_title, in the Create Event at line 4
  60.  
  61. --- LOG END ---
  62.  
  63. /********* END OF LOG FILE *********
  64.  
  65.  
  66.  
  67.  
  68.  
  69. As you can see, it gathers information about the computer itself so you can see what specs the player is running, and it gives you the error/info message you were asking for alongside the callstack where it was generated. It requires 3 scripts to function properly, log_ini(), log() [which is the replacement for show_debug_message()] and log_quit() [this one is not entirely necessary, but it'll show you if the user quit the game on purpose or if the game completed crashed].
  70.  
  71. The log_ini() script takes a single argument, which is whether to turn a global boolean called global.debug on or off. If global.debug is set to true, then alongside the log file, GMS will also output a show_debug_message() with the same info to your console. If it's false, the only the log file will be created. Run log_ini in whatever object is first created in the game.
  72.  
  73.  
  74.  
  75.  
  76.  
  77. ********* START OF log_ini() SCRIPT *********/
  78.  
  79. ///@function log_ini(debug_mode);
  80. ///@description Initialises the log file
  81. ///@param {bool} debug_mode
  82.  
  83. global.debug = argument0;
  84.  
  85. var _time = string(current_day)+"-"+string(current_month)+"-"+string(current_year)+"("+string(current_hour)+"h-"+string(current_minute)+"m-"+string(current_second)+"s)"; // The time the log file was generated
  86. var _filekey = string(current_day)+string(current_month)+string(current_year)+string(current_hour)+string(current_minute)+string(current_second);
  87. var _fname = "log_"+string(_filekey)+".logfile"; // The logfile name is based off what time it was created.
  88. global.logfile_name = working_directory+"\\Log\\"+_fname; // Change this if you want the logfile to be stored somewhere other than a folder called Log
  89. var _game_version = global.version;
  90. var _os_version = os_version;
  91. var _os_lang = os_get_language();
  92. var _os_region = os_get_region();
  93. var _os_map = os_get_info();
  94. var _map_data = [];
  95. if (_os_map != -1) {
  96.     var size, key, i;
  97.     size = ds_map_size(_os_map);
  98.     key = ds_map_find_first(_os_map);
  99.    for (i = 0; i < size - 1; i++;) {
  100.         _map_data[i] = ds_map_find_value(_os_map, key);
  101.         key = ds_map_find_next(_os_map, key);
  102.     }
  103.     ds_map_destroy(_os_map);
  104. }
  105. var _str =  "-- SPECS START --\n\n"+
  106.             "Logfile Name: "+string(global.logfile_name)+"\n"+
  107.             "Log Time: "+string(_time)+"\n"+
  108.             "Game Version: "+string(_game_version)+"\n"+
  109.             "OS Version: "+string(_os_version)+"\n"+
  110.             "OS Language: "+string(_os_lang)+"\n"+
  111.             "OS Region: "+string(_os_region)+"\n"+
  112.             "OS Data: \n";
  113.  
  114. for (var i=0;i<array_length_1d(_map_data);i++) {
  115.     _str += string(_map_data[i])+"\n";
  116. }
  117.  
  118. _str += "Working Dir: "+string(working_directory)+"\n";
  119.  
  120. // This next section is only necessary if you are using Steam and need info on the Steam player
  121.  
  122. if (steam_initialised()) {
  123.     _str +=     "Steam User: "+string(steam_get_persona_name())+"\n"+
  124.                 "Steam User ID: "+string(steam_get_user_steam_id())+"\n"+
  125.                 "Steam Account Cloud Enabled: "+string(steam_is_cloud_enabled_for_account())+"\n"+
  126.                 "Steam Game Cloud Enabled: "+string(steam_is_cloud_enabled_for_app())+"\n"+
  127.                 "Steam Cloud Quota Available: "+string(steam_get_quota_free())+"\n"+
  128.                 "Steam Available Languages: "+string(steam_available_languages())+"\n"+
  129.                 "Steam Current Game Language: "+string(steam_current_game_language())+"\n"+
  130.                 "Steam User Logged On: "+string(steam_is_user_logged_on());
  131. }
  132.  
  133. // Steam info section ended
  134.  
  135. _str += "\n\n-- SPECS END --\n\n\n--- LOG START ---\n";
  136.  
  137. var file = file_text_open_write(global.logfile_name);
  138. file_text_write_string(file,_str);
  139. file_text_writeln(file);
  140. file_text_close(file);
  141.  
  142. /********* END OF log_ini(debug_mode) SCRIPT *********
  143.  
  144.  
  145.  
  146.  
  147.  
  148. The next script is the log(text,log_type) script, which is the meat and potatoes of the script set. Use it in place of show_debug_message(). It takes two arguments, text, which is the text you want displayed for this log line and log_type, which is an enum and lets you differentiate between actual errors and things you want to keep track of. By default the enum has two values: log_type.INFO and log_type.ERROR but you could add more to the enum if you wanted. Call it like this: log("This is the text you want saved to the log",log_type.INFO) from anywhere you want after log_ini(debug_mode) has been called. If debug_mode is true, this will also trigger a show_debug_message() with the contents, but if not it won't.
  149.  
  150.  
  151.  
  152.  
  153.  
  154. ********* START OF log(text,log_type) SCRIPT *********/
  155.  
  156. ///@function log(msg,type);
  157. ///@description Logs an entry into the debug list
  158. ///@param {string} msg The message to log
  159. ///@param {enum} type The type of entry
  160.  
  161. enum log_type { // Add enums below if you want to have different log_types
  162.     INFO,
  163.     ERROR
  164. }
  165.  
  166. var msg = argument0;
  167. var type = argument1;
  168. var type_str = "";
  169. var log_str = "";
  170. var _ctime = string(current_time);
  171.  
  172. switch (type) { // If you've added enums, then also add a case for the enum with what text to call it
  173.     case log_type.INFO:
  174.         type_str = "INFO";
  175.     break;
  176.     case log_type.ERROR:
  177.         type_str = "ERROR";
  178.     break;
  179. }
  180.  
  181. log_str = "** Running Time "+string(_ctime)+" **\n"+msg+"
  182. log_str += " -- Callstack:";
  183. var _stack = debug_get_callstack();
  184. var _stacklen = array_length_1d(_stack)-1;
  185. for (var i=1;i<_stacklen;i++) {
  186.     log_str += "\n";
  187.     repeat ((_stacklen)-i) {
  188.         log_str += ">>";
  189.     }
  190.     log_str += string(_stack[i]);
  191. }
  192.  
  193. log_str += "\n";
  194. var file = file_text_open_append(global.logfile_name);
  195. if (file_exists(global.logfile_name)) {
  196.     file_text_write_string(file,log_str);
  197.     file_text_writeln(file);
  198.     file_text_close(file);
  199.     if (global.debug) {
  200.         show_debug_message(log_str);
  201.     }
  202. }
  203. else { // This only triggers if the log file is not writeable for some reason. Never happened to me
  204.     file = file_text_open_write(working_directory+"\\Logfile_not_found.logfile");
  205.     if (file_exists(working_directory+"\\Logfile_not_found.logfile")) {
  206.         file_text_write_string(file,"Tried to write to "+string(global.logfile_name)+" and file was not accessible. Original log error was:\n\n"+log_str);
  207.     }
  208.     file_text_close(file);
  209. }
  210.  
  211. /********* END OF log(text,log_type) SCRIPT *********
  212.  
  213.  
  214.  
  215.  
  216.  
  217. Then finally we have the log_quit() script, which is simply a closer to the log file so that you know if the game ended naturally through the Game End Event or if it crashed to desktop. Call it from a persistent object in the Game End Event.
  218.  
  219.  
  220.  
  221.  
  222.  
  223. ********* START OF log_quit() SCRIPT *********/
  224.  
  225. ///@function log_quit();
  226. ///@description Adds a closer to the log file
  227.  
  228. var _str = "--- LOG END ---";
  229.  
  230. var file = file_text_open_append(global.logfile_name);
  231. file_text_write_string(file,_str);
  232. file_text_writeln(file);
  233. file_text_close(file);
  234.  
  235. /********* END OF log_quit() SCRIPT *********
  236.  
  237.  
  238.  
  239.  
  240. That's it. Add these files as scripts named appropriately and start using log() instead of show_debug_message() and you'll be able to store much more information about anything potentially going wrong that you're checking for. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement