Récupérer la mémoire utilisée par une JVM sous Websphere 8.5.5 avec wsadmin

Scripting en jython

Si vous avez suivi mes dernières aventures, vous savez que je travaille énormément sur Websphere en ce moment et plus particulièrement sur la partie wsadmin de websphere, à savoir la partie scripting. Mes anciens articles sur websphere.

Coeur du script : la récupération de la valeur de la mémoire utilisée par notre JVM. Pensez à remplacer xxServer par le nom de votre JVM.

perfName = AdminControl.completeObjectName ('type=Perf,process=xxServer,*')
perfOName = AdminControl.makeObjectName (perfName)
sigs = ['javax.management.ObjectName', 'java.lang.Boolean']
jvmName = AdminControl.completeObjectName ('type=JVM,process=xxServer,*')
params = [AdminControl.makeObjectName (jvmName), java.lang.Boolean ('false')]
jvmStats=AdminControl.invoke_jmx (perfOName, 'getStatsObject', params, sigs)
UsedMemory=jvmStats.getStatistic( 'UsedMemory').getCount()
print UsedMemory

Comment appeler ce bout de script ? Il faut appeler le script wsadmin.sh de websphere qui lui, déroulera le script ci-dessus. Les paramètres de wsadmin sont détaillés dans cet article.

#!/bin/bash

"$WAS_ROOT/bin/wsadmin.sh" $ADMIN_OPT -lang jython -f `dirname $0`/usedMemory.py

Ensuite on peut faire une boucle pour afficher la valeur de la mémoire utilisée toutes les 5 secondes, avec en prime la date :

import sys
import time
import re

count=3
while count > 0 :
## MAIN
 perfName = AdminControl.completeObjectName ('type=Perf,process=xxServer,*')
 perfOName = AdminControl.makeObjectName (perfName)
 sigs = ['javax.management.ObjectName', 'java.lang.Boolean']
 jvmName = AdminControl.completeObjectName ('type=JVM,process=xxServer,*')
 params = [AdminControl.makeObjectName (jvmName), java.lang.Boolean ('false')]
 jvmStats=AdminControl.invoke_jmx (perfOName, 'getStatsObject', params, sigs)
 UsedMemory=jvmStats.getStatistic( 'UsedMemory').getCount()
 now = time.localtime(time.time())
 print time.strftime("%d/%m/%y %H:%M:%S", now),";",UsedMemory
 time.sleep(5)

Sources : 

Python : Date et parsing de texte

Programmation en python

Pour les besoins d’un script en python, j’ai besoin de petits bouts de code. En effet, suite à mon article sur websphere, j’ai besoin de parser des résultats et de les stocker dans un fichier texte. On va voir ensemble comment procéder.

Récupération de la date du jour :

import time
# Obtenir l'heure et la date locale
now = time.localtime(time.time())

print time.strftime("%y/%m/%d %H:%M", now)
date en python

ça affiche :

16/09/09 09:07

Ensuite, ce que je veux faire, c’est parser la ligne ci-dessous et récupérer uniquement la valeur de UsedMemory :

jvmRuntimeModule | HeapSize=524288;;;; FreeMemory=205940;;;; UsedMemory=318347;;;; UpTime=1356524;;;; ProcessCpuUsage=0;;;;

Je vous rappelle comme j’avais fait en ksh pour parser :

cat resultat | grep UsedMemory | awk -F"=" ' { print $4 }' | awk -F";" ' { print $1 }'
Parsing en ksh

On va décomposer étape par étape, je vais commencer par utiliser la commande split et lui indiquer divers séparateurs. Je l’avais déjà utilisé lors d’un précédent article, mais bon, ça fait déjà 4 ans et demi !

import re

example = "jvmRuntimeModule | HeapSize=524288;;;; FreeMemory=205940;;;; UsedMemory=318347;;;; UpTime=1356524;;;; ProcessCpuUsage=0;;;;"

parts = example.split()
print parts[4]
other = parts[4].split('=')
print other[1]
fin = other[1].split(';')
print fin[0]
parsing step by step

Voilà le résultat :

UsedMemory=318347;;;;
318347;;;;
318347

Optimisation de code

C’est un code qui fonctionne, me direz-vous, mais peut-on faire ça en deux lignes au lieu de trois ?

import re

example = "jvmRuntimeModule | HeapSize=524288;;;; FreeMemory=205940;;;; UsedMemory=318347;;;; UpTime=1356524;;;; ProcessCpuUsage=0;;;;"

partie = example.split(';')
print partie[8]
valeur = partie[8].split('=')
print valeur[1]

Résultat :

 UsedMemory=318347
318347

Il faut tout de même que je teste la présence de UsedMemory :

import re

example = "jvmRuntimeModule | HeapSize=524288;;;; FreeMemory=205940;;;; UsedMemory=318347;;;; UpTime=1356524;;;; ProcessCpuUsage=0;;;;"
if "UsedMemory" in example:
 partie = example.split(';')
 print partie[8].split('=')[1]

Si on revient à mon code initial, il faut que j’écrive sur la même ligne la date et la valeur d’UsedMemory. Pour l’instant, le code ci-dessous ne fonctionne pas !

for stat in statsList:
  if "UsedMemory" in str(stat):
   now = time.localtime(time.time())
   partie = stat.split(';')
   print time.strftime("%d/%m/%y %H:%M", now) , partie[8].split('=')[1]
   time.sleep(5)
Belle erreur python !

 

Traceback (innermost last):
  File "<string>", line 64, in ?
TypeError: string member test needs char left operand

Recherche Google

Du coup, je fais une petite recherche sur Google et je tombe sur l’excellent site stackoverflow. Je rajoute au passage un séparateur ; entre mes différents champs, ce qui me génèrera du « pseudo csv ».

for stat in statsList:
  if stat.find('UsedMemory=') >= 0:
   now = time.localtime(time.time())
   partie = stat.split(';')
   print time.strftime("%d/%m/%y %H:%M", now),";",partie[8].split('=')[1]
   time.sleep(5)

Résultat :

09/09/16 10:29 ; 383886
09/09/16 10:29 ; 383886
09/09/16 10:29 ; 385079
...
09/09/16 10:31 ; 396919
09/09/16 10:31 ; 396919
09/09/16 10:31 ; 398375
09/09/16 10:31 ; 396919

Pour la partie écriture dans un fichier de logs, pour l’instant je vais utiliser ksh :)

Sources : 

Comment lancer un script jython sous websphere ?

Le jython, c’est du python pour Java. Vous pouvez lancer des scripts python à partir de l’utilitaire wsadmin.sh. Cet utilitaire vous permet de lancer n’importe quelle tâche d’administration : stop/startNode, stop/startServer ou encore des stop/startManager…

cheminDuWebsphere/bin/wsadmin.sh optionsDeConnexionAuWebsphere -lang jython -f test.jy
ou
cheminDuWebsphere/bin/wsadmin.sh optionsDeConnexionAuWebsphere -lang jython -f test.py

Les options de connexion au websphere sont notamment le login, le mot de passe, le port de connexion SOAP. Il peut y avoir d’autres paramètres, cela dépend de votre environnement.

Pour administrer un websphere vous disposez de tout un tas d’objets et de méthodes par exemple :
– pour afficher le nom de la cellule
print AdminControl.getCell()
– pour afficher le nom d’hôte, le nom du serveur
print AdminControl.getHost()
– pour installer une application, il faut fournir toute une série de paramètres puis lancer :
AdminApp.install(cheminDeLApplication, parametres)

Cet article est un aperçu de ce que vous pouvez faire en jython, je vous invite néanmoins à regarder les liens ci-dessous.

Sources :
https://www.vincentliefooghe.net/content/arr%C3%AAt-relance-lapplication-itim-ligne-commande
http://www.ibm.com/support/knowledgecenter/fr/SSAW57_8.5.5/com.ibm.websphere.nd.doc/ae/txml_script.html
http://www.ibm.com/support/knowledgecenter/fr/SSAW57_8.5.5/com.ibm.websphere.nd.doc/ae/cxml_jython.html
http://www.ibm.com/support/knowledgecenter/SSAW57_8.0.0/com.ibm.websphere.nd.doc/info/ae/ae/rxml_admincontrol.html
http://www.ibm.com/support/knowledgecenter/SSAW57_8.5.5/com.ibm.websphere.nd.doc/ae/rxml_taskoptions.html

Erreur python : IndexError: list index out of range

Comme vous le savez tous, je débute en python. Je ne programme pas vraiment mais il m’arrive de devoir déboguer des programmes écrits en python. Ce matin, une erreur m’énerve particulièrement :

IndexError: list index out of range

Voilà ce que ça donne avec la trace complète de l’erreur :

Traceback (most recent call last):
File « monScript.py », line 357, in ?
main()
File « monScript.py », line 349, in main
maFonction(monParam)
File « monScript.py », line 246, maFonction
maVariable = str(dataLigne[monChamp])
IndexError: list index out of range

Je comprends que le script souhaite accéder à un index qui n’existe pas. Mais pour en avoir le cœur net, je lance une petite recherche sur Google et je tombe sur les sites suivants :

(j’ai remplacé les noms de fichier, de variables et de fonction pour conserver un minimum de confidentialité)

POO en python, un exemple avec les fonctions search et compile

J’ai essayé de prendre en compte les remarques et conseils que j’ai eus via ce blog et via twitter. Un grand merci à : @Abd_fr, @Niyyou et @kiki67100.  Pour coder cette classe, j’ai utilisé l’IDE PyCharm, IDE que m’a conseillé @Abd_fr. Je peux dire qu’il y a un avant et après PyCharm.

J’ai essayé de partir de mon précédent article et de perfectionner un peu les choses. Comme je le dis souvent, ce n’est encore qu’un début. Passons à la pratique.

La classe ci-dessous contient deux méthodes :

  • une méthode qui affiche les arguments passés lors de l’instanciation de l’objet personne => print_args
  • une méthode qui recherche une ville précise dans l’adresse donnée lors de l’instanciation de l’objet personne
Vous remarquerez que j’ai importé le module re. C’est indispensable pour pouvoir utiliser les méthodes compile et search. J’ai déjà parlé de la méthode search dans un précédent article. 
import re
__author__ = 'FATIHA'
class MyIdentityClass (object):
    def __init__(self,_firstname,_lastname,_address):
        self._firstname=_firstname
        self._lastname=_lastname
        self._address=_address

    def print_args(self):
        print self._firstname
        print self._lastname
        print self._address

    def search_city (self,_city):
        pattern = re.compile(_city)
        if pattern.search(self._address):
            print "Yes"
        else:
            print "No"

personne=MyIdentityClass("michel","dupont","70 avenue Mozart, 75016 Paris")
personne.print_args()
personne.search_city("Paris")
personne.search_city("Londres")

Le résultat est le suivant :

michel
dupont
70 avenue Mozart, 75016 Paris
Yes
No