From e3db9822b93eaeff226fa22a965cc6c29068abac Mon Sep 17 00:00:00 2001 From: Taka Date: Tue, 30 Jul 2019 04:37:14 +0000 Subject: [PATCH] Updated logging for the VASSAL shim. --- .../webapp/config/logging.yaml.example | 11 +++- vasl_templates/webapp/vassal.py | 55 +++++++++++------- vassal-shim/release/vassal-shim.jar | Bin 28219 -> 28367 bytes vassal-shim/src/vassal_shim/AnalyzeNode.java | 4 +- vassal-shim/src/vassal_shim/VassalShim.java | 10 +++- 5 files changed, 53 insertions(+), 27 deletions(-) diff --git a/vasl_templates/webapp/config/logging.yaml.example b/vasl_templates/webapp/config/logging.yaml.example index 452f6bc..fbc7381 100644 --- a/vasl_templates/webapp/config/logging.yaml.example +++ b/vasl_templates/webapp/config/logging.yaml.example @@ -27,6 +27,15 @@ loggers: vasl_mod: level: "WARNING" handlers: [ "file" ] - vassal_shim: + update_vsav: + level: "WARNING" + handlers: [ "file" ] + analyze_vsav: + level: "WARNING" + handlers: [ "file" ] + webdriver: + level: "WARNING" + handlers: [ "file" ] + roar: level: "WARNING" handlers: [ "file" ] diff --git a/vasl_templates/webapp/vassal.py b/vasl_templates/webapp/vassal.py index bc371f3..a2a199d 100644 --- a/vasl_templates/webapp/vassal.py +++ b/vasl_templates/webapp/vassal.py @@ -7,6 +7,7 @@ import subprocess import traceback import re import logging +import pprint import base64 import time import xml.etree.cElementTree as ET @@ -18,8 +19,6 @@ from vasl_templates.webapp.config.constants import BASE_DIR, IS_FROZEN from vasl_templates.webapp.utils import TempFile, SimpleError from vasl_templates.webapp.webdriver import WebDriver -_logger = logging.getLogger( "vassal_shim" ) - SUPPORTED_VASSAL_VERSIONS = [ "3.2.15" ,"3.2.16", "3.2.17" ] SUPPORTED_VASSAL_VERSIONS_DISPLAY = "3.2.15-.17" @@ -35,13 +34,16 @@ def update_vsav(): #pylint: disable=too-many-statements vsav_filename = request.json[ "filename" ] snippets = request.json[ "snippets" ] + # initialize + logger = logging.getLogger( "update_vsav" ) + # update the VASL scenario file try: # get the VSAV data (we do this inside the try block so that the user gets shown # a proper error dialog if there's a problem decoding the base64 data) vsav_data = base64.b64decode( vsav_data ) - _logger.info( "Updating VSAV (#bytes=%d): %s", len(vsav_data), vsav_filename ) + logger.info( "Updating VSAV (#bytes=%d): %s", len(vsav_data), vsav_filename ) with TempFile() as input_file: @@ -50,17 +52,17 @@ def update_vsav(): #pylint: disable=too-many-statements input_file.close() fname = app.config.get( "UPDATE_VSAV_INPUT" ) # nb: for diagnosing problems if fname: - _logger.debug( "Saving a copy of the VSAV data: %s", fname ) + logger.debug( "Saving a copy of the VSAV data: %s", fname ) with open( fname, "wb" ) as fp: fp.write( vsav_data ) with TempFile() as snippets_file: # save the snippets in a temp file - xml = _save_snippets( snippets, snippets_file ) + xml = _save_snippets( snippets, snippets_file, logger ) snippets_file.close() fname = app.config.get( "UPDATE_VSAV_SNIPPETS" ) # nb: for diagnosing problems if fname: - _logger.debug( "Saving a copy of the snippets: %s", fname ) + logger.debug( "Saving a copy of the snippets: %s", fname ) with open( fname, "wb" ) as fp: ET.ElementTree( xml ).write( fp ) @@ -77,7 +79,7 @@ def update_vsav(): #pylint: disable=too-many-statements vsav_data = fp.read() fname = app.config.get( "UPDATE_VSAV_RESULT" ) # nb: for diagnosing problems if fname: - _logger.debug( "Saving a copy of the updated VSAV: %s", fname ) + logger.debug( "Saving a copy of the updated VSAV: %s", fname ) with open( app.config.get("UPDATE_VSAV_RESULT"), "wb" ) as fp: fp.write( vsav_data ) # read the report @@ -85,10 +87,10 @@ def update_vsav(): #pylint: disable=too-many-statements except Exception as ex: #pylint: disable=broad-except - return VassalShim.translate_vassal_shim_exception( ex ) + return VassalShim.translate_vassal_shim_exception( ex, logger ) # return the results - _logger.debug( "Updated the VSAV file OK: elapsed=%.3fs", time.time()-start_time ) + logger.info( "Updated the VSAV file OK: elapsed=%.3fs", time.time()-start_time ) # NOTE: We adjust the recommended save filename to encourage users to not overwrite the original file :-/ vsav_filename = os.path.split( vsav_filename )[1] return jsonify( { @@ -103,7 +105,7 @@ def update_vsav(): #pylint: disable=too-many-statements }, } ) -def _save_snippets( snippets, fp ): #pylint: disable=too-many-locals +def _save_snippets( snippets, fp, logger ): #pylint: disable=too-many-locals """Save the snippets in a file. NOTE: We save the snippets as XML because Java :-/ @@ -143,7 +145,7 @@ def _save_snippets( snippets, fp ): #pylint: disable=too-many-locals img = webdriver.get_snippet_screenshot( snippet_id, snippet_info["content"] ) width, height = img.size elapsed_time = time.time() - start_time - _logger.debug( "Generated screenshot for %s (%.3fs): %dx%d", + logger.debug( "Generated screenshot for %s (%.3fs): %dx%d", snippet_id, elapsed_time, width, height ) # FUDGE! There's something weird going on in VASSAL e.g. "" gives us something @@ -187,12 +189,15 @@ def analyze_vsav(): vsav_data = request.json[ "vsav_data" ] vsav_filename = request.json[ "filename" ] + # initialize + logger = logging.getLogger( "analyze_vsav" ) + try: # get the VSAV data (we do this inside the try block so that the user gets shown # a proper error dialog if there's a problem decoding the base64 data) vsav_data = base64.b64decode( vsav_data ) - _logger.info( "Analyzing VSAV (#bytes=%d): %s", len(vsav_data), vsav_filename ) + logger.info( "Analyzing VSAV (#bytes=%d): %s", len(vsav_data), vsav_filename ) with TempFile() as input_file: @@ -201,7 +206,7 @@ def analyze_vsav(): input_file.close() fname = app.config.get( "ANALYZE_VSAV_INPUT" ) # nb: for diagnosing problems if fname: - _logger.debug( "Saving a copy of the VSAV data: %s", fname ) + logger.debug( "Saving a copy of the VSAV data: %s", fname ) with open( fname, "wb" ) as fp: fp.write( vsav_data ) @@ -214,10 +219,13 @@ def analyze_vsav(): except Exception as ex: #pylint: disable=broad-except - return VassalShim.translate_vassal_shim_exception( ex ) + return VassalShim.translate_vassal_shim_exception( ex, logger ) # return the results - _logger.debug( "Analyzed the VSAV file OK: elapsed=%.3fs\n%s", time.time()-start_time, report ) + logger.info( "Analyzed the VSAV file OK: elapsed=%.3fs\n%s", + time.time() - start_time, + pprint.pformat( report, indent=2, width=120 ) + ) return jsonify( report ) def _parse_analyze_report( fname ): @@ -289,6 +297,9 @@ class VassalShim: def _run_vassal_shim( self, *args ): #pylint: disable=too-many-locals """Run the VASSAL shim.""" + # initialize + logger = logging.getLogger( "vassal_shim" ) + # prepare the command java_path = app.config.get( "JAVA_PATH" ) if not java_path: @@ -319,7 +330,7 @@ class VassalShim: timeout = None # run the VASSAL shim - _logger.debug( "Running VASSAL shim (timeout=%s): %s", str(timeout), " ".join(args2) ) + logger.info( "Running VASSAL shim (timeout=%s): %s", str(timeout), " ".join(args2) ) start_time = time.time() # NOTE: We can't use pipes to capture the output here when we're frozen on Windows ("invalid handle" errors), # I suspect because we freeze the application using --noconsole, which causes problems when @@ -352,7 +363,7 @@ class VassalShim: buf2.close() stderr = open( buf2.name, "r", encoding="utf-8" ).read() elapsed_time = time.time() - start_time - _logger.debug( "- Completed OK: %.3fs", elapsed_time ) + logger.info( "- Completed OK: %.3fs", elapsed_time ) # check the result stderr = stderr.replace( "Warning: Could not get charToByteConverterClass!", "" ).strip() @@ -365,7 +376,7 @@ class VassalShim: # saved the scenario successfully and exited cleanly; any output on stderr means that some part # of VASSAL barfed as it was trying to start up and can (hopefully) be safely ignored. if stderr: - _logger.info( "VASSAL shim stderr output:\n%s", stderr ) + logger.warning( "VASSAL shim stderr output:\n%s", stderr ) if proc.returncode != 0: raise VassalShimError( proc.returncode, stdout, stderr ) return stdout @@ -381,11 +392,11 @@ class VassalShim: return boards_dir @staticmethod - def translate_vassal_shim_exception( ex ): + def translate_vassal_shim_exception( ex, logger ): """Convert an exception thrown by the VassalShim to a JSON response to return to the caller.""" if isinstance( ex, VassalShimError ): - _logger.error( "VASSAL shim error: rc=%d", ex.retcode ) + logger.error( "VASSAL shim error: rc=%d", ex.retcode ) if ex.retcode != 0: return jsonify( { "error": "Unexpected return code from the VASSAL shim: {}".format( ex.retcode ), @@ -403,10 +414,10 @@ class VassalShim: "

If this problem persists, try configuring a longer timeout." } ) if isinstance( ex, SimpleError ): - _logger.error( "VSAV update error: %s", ex ) + logger.error( "VSAV update error: %s", ex ) return jsonify( { "error": str(ex) } ) - _logger.error( "Unexpected VSAV update error: %s", ex ) + logger.error( "Unexpected VSAV update error: %s", ex ) return jsonify( { "error": str(ex), "stdout": traceback.format_exc(), diff --git a/vassal-shim/release/vassal-shim.jar b/vassal-shim/release/vassal-shim.jar index 54d9fc406ff783b512b08d109a8c337ecdf0c106..1fcfebbcb9cbc47e786d6802a23e369f5d245326 100644 GIT binary patch delta 13769 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%0D9F+ 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 Ls9_VW{uBN`3vDH$ delta 13604 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 Q7MMvL4k%E6t^Q;FAD{;0f&c&j diff --git a/vassal-shim/src/vassal_shim/AnalyzeNode.java b/vassal-shim/src/vassal_shim/AnalyzeNode.java index b9a6c31..dd0c0c0 100644 --- a/vassal-shim/src/vassal_shim/AnalyzeNode.java +++ b/vassal-shim/src/vassal_shim/AnalyzeNode.java @@ -13,8 +13,8 @@ public class AnalyzeNode { // initialize the AnalyzeNode this.name = name ; - this.count = 0 ; + this.count = 1 ; } - public void incrementCount() { ++count ; } + public int incrementCount() { return ++count ; } } diff --git a/vassal-shim/src/vassal_shim/VassalShim.java b/vassal-shim/src/vassal_shim/VassalShim.java index 3fa89e8..0a26594 100644 --- a/vassal-shim/src/vassal_shim/VassalShim.java +++ b/vassal-shim/src/vassal_shim/VassalShim.java @@ -151,6 +151,7 @@ public class VassalShim cmd.execute() ; // analyze the scenario + logger.info( "Analyzing scenario: " + scenarioFilename ) ; HashMap results = new HashMap() ; analyzeCommand( cmd, results ) ; @@ -814,6 +815,7 @@ public class VassalShim // analyze the command if ( cmd instanceof AddPiece ) { GamePiece target = ((AddPiece)cmd).getTarget() ; + logger.debug( "Found piece: " + cmd.getClass().getName() + " ; target=" + target.getClass().getName() ) ; // NOTE: Hideable's don't seem to be just a thing with old versions of VASSAL. We still get them // when adding a "46mm granatnik wz. 36" (GPID 2172) using VASL 6.4.4 :-/ This also seems to happen // with other 1/2" SW counters. @@ -824,9 +826,13 @@ public class VassalShim ) { int pos = target.getState().lastIndexOf( ";" ) ; String gpid = target.getState().substring( pos+1 ) ; - if ( ! results.containsKey( gpid ) ) + if ( ! results.containsKey( gpid ) ) { + logger.debug( "Found new GPID " + gpid + ": " + target.getName() ) ; results.put( gpid, new AnalyzeNode( target.getName() ) ) ; - results.get( gpid ).incrementCount() ; + } else { + int newCount = results.get( gpid ).incrementCount() ; + logger.debug( "Updating count for GPID " + gpid + ": #=" + newCount ) ; + } } }