Debugger Mapserver

Author:Jeff McKenna
Contact:jmckenna at gatewaygeomatics.com
Last Updated:

02-07-2013

Introduction

Quand vous développez une application pour Internet, vous rencontrerez inévitablement parmi les problèmes cerains liés à votre environnement. Le but de ce guide est de vous assister dans la localisation du problème avec votre application MapServer.

Etapes pour activer le debug Mapserver

A partir de la version de MapServer 5.0, vous êtes capables de contrôler les niveaux d’information de debug/log retournés par MapServer, et aussi contrôler l’emplacement du fichier de log en sortie.

En termes techniques, il y a plusieurs appels à msDebug() à différents endroits dans le code de MapServer qui génère une information qui peut s’avérer utile pour optimiser et débugger des applications.

Etape 1: définir la variable MS_ERRORFILE

La variable MS_ERRORFILE est utilisée pour spécifier la sortie des messages de debug de MapServer. Vous pouvez passer les valeurs suivantes à MS_ERRORFILE :

[filename]

Chemin complet et nom d’un fichier de log pour récupérer les messages de debug de Mapserver. N’importe quelle extension de fichier peut-être utilisée mais .log ou .txt sont recommandés. Le fichier sera créé si il n’existe pas déjà.

A partir de MapServer 6.0, un nom de fichier avec un chemin relatif peut être passé par la directive CONFIG MS_ERRORFILE, et dans ce cas, le nom du fichier est relatif à l’emplacement du mapfile. Notez que définir MS_ERRORFILE via une variable d’environnement nécessite toujours un chemin absolu étant donné qu’il n’y a pas de mapfile pour définir un chemin relatif.

stderr

Utiliser ceci pour envoyer des messages de debug MapServer au fichier de log du serveur web (c’est à dire “standard error”). Si vous utilisez Apache, vos messages de debug seront placés dans le fichier error_log de Apache. Si vous utilisez Microsoft IIS, vos messages de debug seront envoyées à stdout (c’est à dire le navigateur), ainsi son utilisation est déconseillée. Avec IIS, il est recommandé de renvoyer la sortie directe vers un fichier à la place.

stdout

Utiliser ceci pour envoyer les messages de debug Mapserver vers la sortie standard (c’est à dire le navigateur) combiné avec le reste de la sortie de Mapserver.

windowsdebug

Utilisez ceci pour envoyer des messages de debug MapServer à l’API OutputDebugString de Windows, permettant l’utilisation de programmes externes comme debugview de SysInternals pour afficher la sortie de debug.

Via le Mapfile

La manière recommandée de définir la variable MS_ERRORFILE est dans votre mapfile, à l’intérieur de l’objet MAP, comme:

MAP
  ...
  CONFIG "MS_ERRORFILE" "/ms4w/tmp/ms_error.txt"
  ...
  LAYER
    ...
  END
END

Via une variable d’environnement

Vous pouvez aussi définir la variable MS_ERRORFILE comme variable d’environnement sur votre système. Les utilisateurs Apache peuvent définir la variable d’environnement dans le fichier httpd.conf de Apache, comme ceci :

SetEnv MS_ERRORFILE "/ms4w/tmp/ms_error.txt"

Les utilisateurs Windows peuvent de manière alternative définir la variable d’environnement via les Propriétés du système; mais assurez vous de définir la variable d’environnement dans SYSTEM.

Note

Si les deux variables d’environnement MS_ERRORFILE et CONFIG MS_ERRORFILE sont définies,alors la directive CONFIG à la précédence.

Etape 2: définir le niveau de DEBUG

Vous pouvez récupérer divers types de de messages de debug en configurant le paramètre DEBUG dans le Mapfile. Vous pouvez placer le paramètre DEBUG dans n’importe quel bloc LAYER dans le mapfile pour les informations de debug spécifiques aux couches, ou à la place, définissez le une seule fois dans l’objet MAP pour obtenir les informations de debug générales. Utilisez la valeur du paramètre DEBUG pour définir le type d’information retournée, comme cela suit:

Niveaux de DEBUG

Level 0

Erreurs seulement (DEBUG OFF, ou DEBUG 0)

Au niveau 0, seulement les appels msSetError() sont loggués au MS_ERRORFILE. Pas de sortie msDebug() du tout. C’est le comportement par défaut et correspond au comportement original de MS_ERRORFILE dans MapServer 4.x

Level 1

Erreurs et notifications (DEBUG ON, ou DEBUG 1)

Le niveau 1 inclut toutes les sorties du niveau Level 0 avec les avertissements msDebug() à propos de des erreurs communes, des assertions échouées ou des situations d’erreur non-fatales (c’est à dire les valeurs manquantes ou invalides pour certains paramètres, les shapefiles manquants dans l’index de tuiles, les erreurs de délai depuis les serveurs distants WMS/WFS servers, etc.)

Level 2

Optimisation de la carte (DEBUG 2)

Le niveau 2 inclut toutes les sorties du niveau 1 avec les notifications et les informations de timing, utiles pour optimiser les mapfiles et les applications. C’est le niveau de debug minimal recommandé

Level 3

Debug verbeux (DEBUG 3)

Tout le niveau 2 avec quelques sorties de debug utiles pour diagnostiquer des problèmes comme les URLs de connexion WMS qui sont appelées, les appels de connexion aux bases de données, etc.

Level 4

Debug très verbeux (DEBUG 4)

Level 3 avec encore plus de détails...

Level 5

Debug très très verbeux (DEBUG 5)

Le niveau 4 plus toutes les sorties msDebug() qui pourraient être utiles plus aux développeurs qu’aux utilisateurs.

Exemple de Mapfile: Debug au niveau du bloc MAP

L’exemple suivant est la méthode recommandée pour définir le paramètre DEBUG au niveau du bloc MAP:

MAP
  ...
  CONFIG "MS_ERRORFILE" "/ms4w/tmp/ms_error.txt"
  DEBUG 5
  ...
  LAYER
    ...
  END
END

Exemple de Mapfile: Debug au niveau du bloc LAYER

L’exemple suivant est la méthode recommandée pour définir le paramètre DEBUG pour une couche:

MAP
  ...
  CONFIG "MS_ERRORFILE" "/ms4w/tmp/ms_error.txt"
  ...
  LAYER
    DEBUG 5
    ...
  END
END

La variable d’environnement MS_DEBUGLEVEL

Au lieu de définir le niveau de DEBUG dans chacun de vos mapfiles, vous pouvez aussi définir le niveau de manière globale en utilisant la variable d’environnement MS_DEBUGLEVEL.

Quand elle est définie, cette valeur est utilisée comme la valeur de debug par défaut pour tous les objets MAP et LAYER quand ils sont chargés par le parseur de mapfile. Cette option définit aussi le niveau de debug pour n’importe quel appel msDebug() effectué en dehors du contexte d’un objet MAP ou LAYER, par exemple, pour des instructions de debug relative à l’initialisation avant qu’un mapfile soit chargé. Si une valeur DEBUG est spécifiée aussi dans le mapfile au niveau d’un objet MAP ou LAYER alors la valeur locale (dans le mapfile) a la précédence sur la valeur provenant de la variable d’environnement.

Les utilisateurs Apache peuvent définir la variable d’environnement dans le fichier httpd.conf Apache, comme ceci :

SetEnv MS_DEBUGLEVEL 5

Les utilisateurs Windows peuvent de manière alternative définir la variable d’environnement via les Propriétés du système; mais assurez vous de définir la variable d’environnement dans SYSTEM.

Etape 3: activer CPL_DEBUG (optionnel)

MapServer repose sur la bibliothèque GDAL pour accéder à la plupart des types de données, alors vous pouvez avoir l’idée d’activer le debugging GDAL, pour éventuellement récupérer plus d’information sur comment GDAL accède à vos fichiers. Cela peut être très utile lors de problèmes d’accès à des fichiers raster ou des tables PostGIS. Vous pouvez activer cette option GDAL en réglant la variable CPL_DEBUG dans votre mapfile, dans l’objet MAP de cette manière:

MAP
  ...
  CONFIG "CPL_DEBUG" "ON"
  ...
  LAYER
    ...
  END
END

Etape 4: activer PROJ_DEBUG (optionnel)

MapServer repose sur la bibliothèque PROJ.4 pour la gestion des projections, vous pouvez donc avoir envie d’activer le debugging de PROJ pour récupérer plus d’information directement de la bibliothèque PROJ. Vous pouvez activer cette option en réglant la variable PROJ_DEBUG dans votre fichier .map, au sein de l’objet MAP, ainsi :

MAP
  ...
  CONFIG "PROJ_DEBUG" "ON"
  ...
  LAYER
    ...
  END
END

Etape 5: tester votre Mapfile

Une fois défini MS_ERRORFILE et le niveau de DEBUG dans votre mapfile, vous devriez maintenant tester votre mapfile et lire le fichier de log généré.

Utiliser shp2img

The recommended way to test your mapfile is to use the MapServer commandline utility shp2img, to verify that your mapfile creates a valid map image. shp2img should be included in your MapServer installation (MS4W users need to execute setenv.bat before using the utility).

Vous pouvez configurer le niveau de DEBUG en passant les paramètres suivant à la ligne de commande shp2img :

Note

Si vous avez déjà défini MS_ERRORFILE dans votre mapfile, vous devez commenter ceci dans le but d’utiliser ces options de shp2img

Note

Lorsque vous utilisez shp2img pour débuguer, le paramètre STATUS de votre couche doit être à ON ou à DEFAULT. Si ce paramètre est définie à OFF, vous devez passer le nom de la couche dans la commande shp2img en utilisant la syntaxe “-l layername”.

-all_debug

Utiliser cette configuration pour définir le niveau de debug pour l’objet MAP et toutes les couches. C’est la manière recommandée de procéder.

shp2img -m spain.map -o test.png -all_debug 5

  msLoadMap(): 0.002s
  msDrawMap(): Layer 0 (spain provinces), 0.012s
  msDrawRasterLayerLow(orthophoto): entering.
  msDrawGDAL(): src=0,0,3540,2430, dst=188,48,1,1
  source raster PL (-793.394,-1712.627) for dst PL (188,48).
  msDrawGDAL(): red,green,blue,alpha bands = 1,2,3,0
  msDrawMap(): Layer 1 (orthophoto), 0.150s
  msDrawMap(): Layer 2 (urban areas), 0.004s
  msDrawMap(): Layer 3 (species at risk), 0.008s
  msDrawMap(): Layer 4 (populated places), 1.319s
  msDrawMap(): Drawing Label Cache, 0.014s
  msDrawMap() total time: 1.513s
  msSaveImage() total time: 0.039s
  msFreeMap(): freeing map at 0218C1A8.
  freeLayer(): freeing layer at 0218F5E0.
  freeLayer(): freeing layer at 030C33A0.
  freeLayer(): freeing layer at 030C3BC8.
  freeLayer(): freeing layer at 030C4948.
  freeLayer(): freeing layer at 030C7678.
  shp2img total time: 1.567s
-map_debug

Utiliser cette configuration pour définir le niveau de debug pour l’objet MAP uniquement.

shp2img -m spain.map -o test.png -map_debug 5

  msDrawMap(): Layer 0 (spain provinces), 0.012s
  msDrawRasterLayerLow(orthophoto): entering.
  msDrawMap(): Layer 1 (orthophoto), 0.144s
  msDrawMap(): Layer 2 (urban areas), 0.004s
  msDrawMap(): Layer 3 (species at risk), 0.008s
  msDrawMap(): Layer 4 (populated places), 1.323s
  msDrawMap(): Drawing Label Cache, 0.013s
  msDrawMap() total time: 1.511s
  msSaveImage() total time: 0.039s
  msFreeMap(): freeing map at 0205C1A8.
-layer_debug

Utiliser cette configuration pour définir le niveau de debug pour un seul objet LAYER.

shp2img -m spain.map -o test.png -layer_debug orthophoto 5

  msDrawRasterLayerLow(orthophoto): entering.
  msDrawGDAL(): src=0,0,3540,2430, dst=188,48,1,1
  source raster PL (-793.394,-1712.627) for dst PL (188,48).
  msDrawGDAL(): red,green,blue,alpha bands = 1,2,3,0
  msDrawMap(): Layer 1 (orthophoto), 0.151s
  freeLayer(): freeing layer at 02F23390.
Définir CPL_DEBUG

Dans la ligne de commande, exécuter ce qui suit

set CPL_DEBUG=ON

shp2img -m spain.map -o test.png -layer_debug orthophoto 5

  msDrawRasterLayerLow(orthophoto): entering.
  GDAL: GDALOpen(D:\ms4w\apps\spain\map/.\../data/ov172068_200904_c100u50x75c24n.jpg, this=0
  4059840) succeeds as JPEG.
  msDrawGDAL(): src=0,0,3540,2430, dst=188,48,1,1
  source raster PL (-793.394,-1712.627) for dst PL (188,48).
  msDrawGDAL(): red,green,blue,alpha bands = 1,2,3,0
  GDAL: GDALDefaultOverviews::OverviewScan()
  msDrawMap(): Layer 1 (orthophoto), 0.155s
  freeLayer(): freeing layer at 03113390.
  GDAL: GDALDeregister_GTiff() called.
Lire les erreurs retournées par shp2img

S’il y a un problème avec votre mapfile, shp2img devrait retourner le numéro de ligne dans votre mapfile qui cause le problème. Ce qui suit indique qu’il y a un soucis à la ligne 85 de mon mapfile :

getSymbol(): Symbol definition error. Parsing error near (truetype2):(line 85)

Si vous utilisez des INCLUDE dans vos mapfiles, il sera parfois plus difficile d’identifier le numéro de ligne, mais la plupart du temps, le numéro de ligne est utile.

Utiliser le programme CGI mapserv

Une autre manière pratique pour tester votre mapfile est d’appeler l’exécutable CGI mapserv par la ligne de commande, comme ce qui suit :

mapserv -nh "QUERY_STRING=map=/ms4w/apps/spain/map/spain.map&mode=map"

ON_MISSING_DATA

Si vous utilisez des tuiles indexées pour accéder à vos données, vous devez aussi considérer les paramètres de configuration ajoutés dans MapServer 5.4 qui vous permettent d’indiquer à MapServer comment traiter les données manquantes dans les tuiles indexées. Regardez le réglage ON_MISSING_DATA du paramètre CONFIG dans l’objet MAP pour plus d’info.

Indice

Vous pouvez vérifier les attributs dans un index de tuiles (tileindex) en exécutant la commande “ogrinfo -al” sur votre fichier de données

Etape 6: vérifier vos logs de serveur web

Une fois que vous avez vérifié qu’il n’y a pas de problèmes avec votre mapfile, vous devez ensuite vérifier les fichiers de log du serveur Web qui apporteront des informations vous permettant de vous rapprocher du problème.

Apache

Les utilisateurs Unix trouveront les fichiers error_log de Apache dans un chemin similaire à :

/var/log/apache2/

Les utilisateurs Windows trouveront habituellement les fichiers de log Apache dans un chemin similaire à :

C:\Program Files\Apache Group\Apache2\logs

MapServer for Windows (MS4W) users will find Apache’s log files at:

\ms4w\Apache\logs

Microsoft IIS

Les fichiers de log IIS log peuvent retrouvés par:

  1. Allez à Démarrer -> Panneau de configuration -> Outils d’administration

  2. Ouvrir le gestionnaire de “Internet Information Services (IIS)”

  3. Trouver votre site web dans l’arborescence sur la gauche.

  4. Faire un clic-droit dessus et choisir Propriétés.

  5. Sous l’onglet “Site web” vous verrez une option vers le bas précisant “Active Log Format”. Cliquez sur le bouton Propriétés.

    ../_images/iis-debug.png
  6. En bas de l’onglet Propriétés Générales, vous verrez une boîte qui contient le répertoire du fichier de log et le nom du fichier de log. Le chemin complet du log comprend le répertoire du fichier de log plus la première partie du nom du fichier de log, par exemple

    C:\WINDOWS\system32\LogFiles\W3SVC1\ex100507.log
    

Vous pouvez aussi cocher le paramètre logs de visualisation des événements Windows, qui est localisé ici :

  1. Allez à Démarrer -> Panneau de configuration -> Outils d’administration

  2. Gestion de l’ordinateur

  3. Visualiseur d’événement

Avertissement

As mentioned previously, in IIS the MapServer stderr debug output is returned to the client instead of routed to the Web Server logs, so be sure to log the output to a file, by setting the following in your mapfile:

CONFIG "MS_ERRORFILE" "/ms4w/tmp/ms_error.txt"

Erreur CGI - L’application CGI définie ne fonctionne pas correctement et ne retourne pas les en-têtes HTTP complètes.

Cette erreur est souvent causée par l’absence de fichiers DLL. Vous devriez essayer d’exécuter la ligne de commande “mapserv -v, afin de s’assurer que MapServer charge correctement.

Etape 7: vérifier les paramétrages de votre application

Si vous avez vérifié que MapServer crée une image valide de la carte via shp2img, vous avez vérifié vos logs du serveur Web, alors vous devez porter votre attention sur des problèmes potentiels de mauvaises configurations de votre application. “Application” signifie ici comment vous affichez vos images de cartes sur la page Web, tel que OpenLayers.

PHP MapScript

Si vous utilisez PHP MapScript dans votre application, voici plusieurs notes pour le débogage :

1. Make sure your php.ini file is configured to show all errors, by setting:

display_errors = On
  1. Pour activer le débogage en PHP MapScript, si vous utilisez MapServer 5.6.0 ou plus récent, assurez-vous de définir ZEND_DEBUG dans les sources de PHP.

    Si vous utilisez MapServer < 5.6.0, alors:

    • ouvrir le fichier /mapscript/php3/php_mapscript.c

    • changer ce qui suit:

      #define ZEND_DEBUG 0
      
      to
      
      #define ZEND_DEBUG 1
      

Debugger MapServer en utilisant les outils de débuggage du compilateur

Lancer Mapserver dans GDB (Linux/Unix)

Auteur de la section : Frank Warmerdam

Compiler avec les informations de debug symboliques

Il n’est pas strictement nécessaire de compiler MapServer avec le debuggage activé afin d’utiliser GDB sous Linux, mais cela s’assure que des informations plus compréhensibles sont reportées au sein de GDB. Pour activer les informations symboliques complètes, utilisez l’option de configure –enable-debug. Notez que l’utilisation de cette option désactive l’optimisation et qu’elle ne doit pas être activée normalement utilisée pour les compilations de production où la performance est importante.

./configure --enable-debug <other switches>
make clean
make

Lancer dans le debugger

Pour exécuter mapserv ou bien shp2img, passez le nom de l’exécutable en tant qu’argument à la commande “gdb”. Si il n’est pas dans le chemin, vous devrez fournir le chemin complet vers l’exécutable.

gdb shp2img
GNU gdb (GDB) 7.0-ubuntu
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /wrk/home/warmerda/mapserver/shp2img...done.
(gdb)

Une fois que vous être dans l’invite “(gdb)”, vous pouvez lancer la commande avec les arguments que vous auriez normalement passés à l’exécutable mapserv ou shp2img.

(gdb) run -m test.map -o out.png
Starting program: /wrk/home/warmerda/mapserver/shp2img -m test.map -o out.png
[Thread debugging using libthread_db enabled]

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff67594a2 in JP2KAKDataset::Identify (poOpenInfo=0x0)
  at jp2kakdataset.cpp:962
962         if( poOpenInfo->nHeaderBytes < (int) sizeof(jp2_header) )
Current language:  auto
The current source language is "auto; currently c++".
(gdb)

Si le programme plante, vous obtiendrez généralement un rapport comme celui ci-dessus indiquant la fonction qui occasionne le crash et des informations minimalistes sur la cause. Il est souvent utile de demander une traceback pour voir quels fonctions amènent à la fonction qui a plantée. Pour cela, utilisez la commande “where”.

(gdb) where
#0  0x00007ffff67594a2 in JP2KAKDataset::Identify (poOpenInfo=0x0)
    at jp2kakdataset.cpp:962
#1  0x00007ffff67596d2 in JP2KAKDataset::Open (poOpenInfo=0x7fffffffb6f0)
    at jp2kakdataset.cpp:1025
#2  0x00007ffff6913339 in GDALOpen (
    pszFilename=0x83aa60 "/home/warmerda/data/jpeg2000/spaceimaging_16bit_rgb.jp
2", eAccess=GA_ReadOnly) at gdaldataset.cpp:2170
#3  0x00007ffff69136bf in GDALOpenShared (
    pszFilename=0x83aa60 "/home/warmerda/data/jpeg2000/spaceimaging_16bit_rgb.jp
2", eAccess=GA_ReadOnly) at gdaldataset.cpp:2282
#4  0x0000000000563c2d in msDrawRasterLayerLow (map=0x81e450, layer=0x839140,
    image=0x83af90, rb=0x0) at mapraster.c:566
#5  0x000000000048928f in msDrawRasterLayer (map=0x81e450, layer=0x839140,
    image=0x83af90) at mapdraw.c:1390
#6  0x0000000000486a48 in msDrawLayer (map=0x81e450, layer=0x839140,
    image=0x83af90) at mapdraw.c:806
#7  0x00000000004858fd in msDrawMap (map=0x81e450, querymap=0) at mapdraw.c:459
#8  0x0000000000446410 in main (argc=5, argv=0x7fffffffd918) at shp2img.c:300
(gdb)

It may also be helpful to examine variables used in the line where the crash occurred. Use the print command for this.

(gdb) print poOpenInfo
$1 = (GDALOpenInfo *) 0x0

Dans ce cas nous voyons que le programme a planté parce que poOpenInfo est NULL (zéro). Inclure une traceback comme ci-dessus dans un rapport de bug peut aider les développeurs à s’approcher du problème plus rapidement, spécialement si c’est un problème difficile à reproduire pour les développeurs.

Debugger des anciennes versions de MapServer (avant la 5.0)

  1. Assurez-vous que Mapserver est compilé en mode debug (sous unix, c’est activé par ./configure –enable-debug).

    Vous pouvez vérifier que votre compilation a été faite en mode debug, en exécutant ce qui suit dans la ligne de commande (regardez si vous avez “DEBUG=MSDEBUG”):

    ./mapserv -v
    
      MapServer version 4.10.2 OUTPUT=GIF OUTPUT=PNG OUTPUT=WBMP
      OUTPUT=SVG SUPPORTS=PROJ SUPPORTS=FREETYPE SUPPORTS=WMS_SERVER
      SUPPORTS=WMS_CLIENT SUPPORTS=WCS_SERVER SUPPORTS=THREADS SUPPORTS=GEOS
      INPUT=EPPL7 INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE
      DEBUG=MSDEBUG
    
  2. Définir la variable MS_ERRORFILE dans votre mapfile, à l’intérieur de l’objet MAP, comme ceci :

    MAP
      ...
      CONFIG "MS_ERRORFILE" "/ms4w/tmp/ms_error.txt"
      ...
      LAYER
        ...
      END
    END
    
  3. Si vous n’utilisez pas la variable MS_ERRORFILE,vous pouvez utiliser le paramètre LOG dans l’objet WEB de votre mapfile, comme ceci :

     MAP
      ...
      WEB
        LOG "mapserver.log"
      END
      ...
      LAYER
        ...
      END
    END
    
  4. Spécifier DEBUG ON dans votre objet MAP object, ou dans vos objets LAYER, comme ceci :

     MAP
      ...
      WEB
        LOG "mapserver.log"
      END
      DEBUG ON
      ...
      LAYER
        ...
      END
    END
    
  5. Notez que seules les erreurs seront écrites dans les fichiers de log ; toutes les sorties DEBUG iront vers la sortie standard, dans le cas d’Apache c’est le fichier d’error_log d’Apache. Si vous utilisez Microsoft IIS, la sortie debug est envoyé vers stdout (i.e. le navigateur), assurez vous de supprimer le paramètre DEBUG ON si vous utilisez IIS sur un serveur de production.

.