27 septembre 2012

Lister les utilisateurs HRaSpace actifs

Encore une donnée que l'on aimerait voir sur la console d'administration ...

Ci joint un SELECT permettant de connaître la liste des utilisateurs HRaSpace actifs dans les 10 dernières minutes :

Exemple Oracle
select USERID,max(TSACTI) from MX10 group by USERID having max(TSACTI) + 1/24/6 > SYSDATE

Exemple DB2
select USERID,max(TSACTI) from MX10 group by USERID having max(TSACTI) + 10 minutes > CURRENT_TIMESTAMP

Pour connaître la liste des utilisateurs connectés, remplacer le délai de 10 minutes par le délai d'inactivité maximum (par défaut 30 minutes, sauf si vous avez paramétré une ligne OP_TIMEOUT en table PP15).

26 septembre 2012

Tracer les consultations en LG10 avec BNE

Vous avez bien lu ... Il est possible depuis HRv7 de tracer les consultations de données faites depuis HRaSpace en table LG10 (en temps normal ces traces sont utilisées lors des mises à jour).

Après exécution du contexte TBP068 de BNE, la variable UT-TEECLG est consultée par le squelette.
  • Si UT-TEECLG est positionnée à 1 par traitement, on trace l'affichage de l'information,
  • Si UT-TEECLG est positionnée à 2, on trace l'affichage de chacune des occurrences.

A noter :
  • La trace est effectuée par le programme BNE. Il s'agit donc des données envoyées par le serveur HR au poste client. En conséquence :
  • Le client hr-rich-client standard appelle les dossiers par paquet (la taille du paquet est paramétrable dans chaque page Web, cf. item "Dossiers demandés par transaction" dans l'onglet "Définition"),
  • On trace donc des données que l'utilisateur a demandées, mais pas nécessairement qu'il a effectivement consultées.

Quelques précautions d'usage :
  • Les tables **LG10 peuvent devenir extrêmement volumineuse et perturber les performances de l'application,
  • L'activation des traces doit toujours se faire de manière ciblée : lister les cas d'usage nécessitant des traces, conditionnez les,
  • Purger régulièrement les tables **LG10 des traces obsolètes.

Extrait du squelette BNE
708900*N8DBG.    NOTE *ECRITURE DANS LA TABLE LG10        *.            P005
709000 F8DBG.    IF    UT-TEECLG NOT = ZERO                             P005
709100           AND   W-WPD1-TYINFO NOT = "S"                          P010
709200           NEXT SENTENCE ELSE GO TO     F8DBG-FN.                 P010
709300*N8DBK.    NOTE *CONSERVATION INFO                  *.            P005
709400 F8DBK.    IF    PE-CDINFO = "1"                                  P005
709500           AND   UT-TEECLG = "1"                                  P020
709600           NEXT SENTENCE ELSE GO TO     F8DBK-FN.                 P020
709700*PE INFO.                                                         P020
709800     MOVE        " " TO LG10-GRLG10-ARR.                          P035
709900     MOVE        1 TO W-WP00-LGINFS.                              P036
710000     PERFORM     F9Z THRU F9Z-FN.                                 P040
710100 F8DBK-FN. EXIT.                                                  P040
710200*N8DBN.    NOTE *CONSERVATION TOUTES OCCURRENCES    *.            P005
710300 F8DBN.    IF    UT-TEECLG = "2"                                  P005
710400           NEXT SENTENCE ELSE GO TO     F8DBN-FN.                 P005
710500     MOVE        1-ZONINF TO S-ZONINF.                            P020
710600     MOVE        1-CDINFO TO S-CDINFO.                            P030
710700     MOVE        1-CDSTDO TO S-CDSTDO.                            P040
710800     PERFORM     F9YIG THRU F9YIG-FN.                             P050
710900     MOVE        S-ZONTRI TO LG10-ZONTRI.                         P060
711000     MOVE        S-ZONINF TO LG10-GRLG10-ARR.                     P070
711100     MOVE        W-WPD1-LGINFS TO W-WP00-LGINFS.                  P080
711200     PERFORM     F9Z THRU F9Z-FN.                                 P090
711300 F8DBN-FN. EXIT.                                                  P090


Merci Nicolas pour l'information.

24 septembre 2012

Eclater un fichier (de bordereaux) avec la commande awk

Il est fréquent qu'il faille découper un fichier en plusieurs morceaux (interfaces, éditions). Pour cela c'est la commande "grep" qui est la plus souvent utilisée.

Exemple : avec le fichier de bordereaux ${FIC} suivant,

000000000HRMYI11                                  *FZD00                       0HRMYI11
000000000HRMYI12                                  *FZD00                       0HRMYI12
000000000HRMYI21                                  *FZD00                       0HRMYI21
000000000HRMYI22                                  *FZD00                       0HRMYI22
000000000HRMYI31                                  *FZD00                       0HRMYI31
000000000HRMYI32                                  *FZD00                       0HRMYI32
000000000HRMYI41                                  *FZD00                       0HRMYI41


Si l'on souhaite éclater le fichier suivant suivant le code du répertoire réglementaire (YI1, YI2, ... en colonne 13 sur 3 caractères) il est nécessaire :
  • De lister les valeurs du code (découpage, tri et élimination des doublons) :
   cut -c13-15 ${FIC} | sort -u
  • De boucler pour chaque valeur de code
   while ... do ... done
  • D'extraire les bordereaux pour chacun des codes dans un fichier ${FIC}.${CODE}
   grep "^000000000HRM${CODE:-   }" ${FIC} > ${FIC}.${CODE}
        NB : ${CODE:-   } permet d'attribuer par défaut la valeur "   " à CODE

Soit :
rm -f  ${FIC}.* # Purge prealable
cut -c13-15 ${FIC} | sort -u | while read CODE
do
   grep "^000000000HRM${CODE:-   }" ${FIC} > ${FIC}.${CODE}
done

L'inconvénient est qu'il faut exécuter la commande "grep" autant de fois qu'il y a de valeur au critère d'éclatement. Quand le fichier est volumineux, le traitement peut être long (si un grep met 1 minutes, 10 greps prendront 10 minutes).

Une solution : la commande awk. Celle ci permet d'obtenir le même résultat en une passe :

rm -f  ${FIC}.* # Purge prealable
awk "{CODE=substr(\$0,13,3); print \$0 > \"$FIC.\"CODE }" ${FIC}

  • CODE=substr permet d'extraire les caractères 13 à 15 de chaque bordereaux et de les stocker dans la variable CODE,
  • print $0 écrit le bordereau,
  • > "$FIC."CODE redirige l'écriture dans des fichiers suffixés par CODE,
  • Tout est dans l'utilisation de quotes doubles pour que les variables Unix dans le script awk soient interprétées, et dans la mise en place des caractères "\" protégeant les champs et les quotes propres au "awk"...

21 septembre 2012

Supprimer des processus consommateurs sur le système Unix


La commande "ps" permet de lister les processus actifs. Ceux consommateurs de puissance on un "C" supérieur à zéro. Ceux TRES consommateurs ont un "C"proche de 100.

Exemple avec les processus du compte Unix "hradev" (utilisez "ps -efl" pour les voir tous) :
ps -flu hradev
F S UID         PID    PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
0 S hradev      998       1  0  79   0 - 589377 387239 05:45 ?       00:00:31 /usr/local/java/jre1.5.0_22/bin/...
1 S hradev      5498      1 
0  76   0 - 12487 339348 05:45 ?        00:00:00 AP0
0 R hradev      8115  20450 
0  76   0 -   732 -      10:09 pts/1    00:00:00 ps -flu hradev
4 S hradev      20450 20449 
0  75   0 -   581 -      08:12 pts/1    00:00:00 -pdksh
0 S hradev      28408 30058 
0  76   0 - 12208 354116 10:00 ?        00:00:01 /hradev/bin/RTSDGN TYBXBHR
0 S hradev      30058     1 
0  76   0 - 593166 322567 05:45 ?       00:00:24 /usr/local/java/jre1.5.0/bin/...

Pour repérer les processus très consommateurs, filtrez sur la colonne "C" :

ps -efl | awk '($6 != 0) {print $0}'
F S UID        PID  PPID  C  PRI  NI ADDR SZ WCHAN  STIME TTY      TIME       CMD
0 R hraqua    21895 21867 99  87   2 -  1400 -      Sep19 ?        1-15:30:47 awk -v FicIn=/hraqua/txt...


On voit ici un processus de hraqua actif depuis 1 jour et 15 heures ... On peut penser qu'il s'agit d'un processus "fou". S'en assurer auprès des développeurs et administrateurs avant de décider de le supprimer.

La commande vmstat indique une consommation CPU par la machine d'environ 25% (additionner les CPU user et sys - ne pas considérer la 1ère ligne qui est une moyenne) :

vmstat 2 5
procs -----------memory----------   ---swap-- -----io---- --system-- ----cpu----
 r  b   swpd   free   buff  cache     si   so    bi    bo   in    cs us sy id wa
 1  0 358952 958104  49420 13338560    2    2   376   328    6     4 15 10 65 10
 1  0 358952 954488  51716 13338864    0    0     0   776 1175  2955 14
12 72  2
 1  0 358952 954552  51812 13338768    0    0     0   358 1030  2859 13
12 74  1
 1  0 358952 954488  51900 13338680    0    0     0   322 1034  2845 13
12 74  0
 1  0 358952 954680  51988 13338592    0    0     8   336 1054  2912
13 12 73  2

On tue avec hraqua le processus fou :
kill 21895

La CPU est libérée :
vmstat 2 10
procs -----------memory----------   ---swap-- -----io---- --system-- ----cpu----
 r  b   swpd   free   buff  cache     si   so    bi    bo   in    cs us sy id wa
 1  0 358952 952592  54268 13340472    2    2   376   328    6     4 15 10 65 10
 0  0 358952 952528  54356 13340644    0    0     4   270 1038  2744 
0  0 98  2
 0  0 358952 952592  54436 13340564    0    0     0   270 1031  2699 
3  0 96  1
 0  0 358952 952560  54516 13340484    0    0     0   242 1030  2701 
0  0 99  1
 0  0 358952 952432  54604 13340656    0    0     0   216 1034  2653  0 
0 99  1


20 septembre 2012

EXCLU CAR CE DOSSIER OU UN AUTRE DU MEME EMPLOYE EST SELECTIONNE DANS UN CALCUL DE PAIE CONCURRENT

Ce message apparaît avec HRv7. Il signifie qu'un autre calcul de paie K3W a déjà sélectionné ce dossier.

Toutefois, si certains de vos dossiers sont systématiquement exclus de la paie :
  • Contrôlez qu'une paie n'est pas déjà en cours,
  • Si une paie tourne, mettez vous d'accord avec son instigateur,
  • Si cette paie est en boucle, tuez la (sous Unix, commande kill) puis passez à l'étape suivante,
  • S'il n'y a pas de K3W actives, contrôlez la table TP33. S'il existe des occurrences avec POPULS valorisé à "K3W", nettoyez les :

DELETE FROM TP33 WHERE POPULS='K3W'

19 septembre 2012

Lancer des calculs de paie en parallèle

Sur les systèmes Unix, un processus est lié à un processeur. Aussi un batch consommateur n'utilisera qu'une partie de la puissance de la machine, ceci au détriment de son temps de traitement. Si l'applicatif le permet, il peut donc être avantageux de "couper" le batch en plusieurs et d'exécuter ceux ci en parallèle. Cette problématique est particulièrement vraie pour le calcul de paie dès que l'on possède plus de 10.000 dossiers actifs.

Depuis HRv7, avec la chaine de paie K3W et le stockage des résultats dans les tables du PRDB, paralléliser le calcul est très simple :
  • créez n dossiers de demandes "Opération" pour K3W, et dans chacune d'entre elles, 
  • indiquez un "identifiant de job" différent (il sert de suffixe au fichiers de travail - sans cela vous rencontrerez des erreurs de type "file locked"),
  • précisez des populations de travail complémentaires mais disjointes (sans quoi vous aurez des messages "EXCLU CAR CE DOSSIER OU UN AUTRE DU MEME EMPLOYE EST SELECTIONNE DANS UN CALCUL DE PAIE CONCURRENT"),
  • soumettez les demandes.
L'ordre de sélection des populations de travail peut être basé sur un critère fonctionnel (par exemple sur la codification des matricules, le statut, la société ...) ou technique : il est assez pratique de prendre comme critère le NUDOSS lui même : on précise via la fonction MODULO dans quelle population un dossier est traité.

Exemple :
  • Population 1 sur 2 : NUDOSS pairs
SELECT NUDOSS FROM ZY00 WHERE MOD(NUDOSS,2)=0
  • Population 2 sur 2 : NUDOSS impairs
SELECT NUDOSS FROM ZY00 WHERE MOD(NUDOSS,2)=1 


14 septembre 2012

Analyser les temps de traitement des fonctions Cobol avec le "Profiler"

Cobol offre un analyseur de temps de traitement. Ci joint un lien vers un article de la Micro Focus Community.

Pour l'activer il faut compiler l'exécutable avec une option particulière, lancer le traitement puis extraire les résultats obtenus :
  • Modifier le .profile pour exporter, dans en fin de chapitre "VARIABLES D'ENVIRONNEMENT COBOL" la variable COBPRFDIR=$TMPDIR
  • Faites une RBZ du programme à analyser avec conservation des sources
Conservation des fichiers de compilation (0/1)  [0]: 1
  • Dans $TMP contrôlez la présence des fichiers *.idy et *.cbl
  • Retrouvez (dans le log de la RBZ) et adaptez la commande de compilation Cobol "cob"  pour y ajouter l'option -C PROFILE
  • Recompilez le programme (exemple avec FFCALDBI) avec l'option -C PROFILE
cob32 -C nolist -vz -C ASSIGN=EXTERNAL ... -C COPYLIST -C NORESEQ -C PROFILE -U /hradev/txt/tmp/FFCALDBI.cbl
  • Copiez le généré (suffixe ".so" en général - consulter ${SUFMOD}) dans $SIGACS/prod/gnt
  • Conservez le fichier *.idy dans $TMP
  • Si le programme concerné est un programme TP, faites un arrêt / démarrage de OpenHR,
  • Exécutez votre traitement,
Une fois l'exécution du programme terminée, un fichier *.ipf est créé dans $TMPDIR,
  • Pour en lire les données, utilisez la commande cobprof (ici avec une limitation a 25 lignes) :

cobprof FFCALDBI.ipf +LIST | head -25

Total time:    1517240 milliseconds.      Module called once.
% time      time   entries  ms/entry      paragraph
-------------------------------------------------------------------------------
 45.35    688110        26     26466      UTTDP424-XB0B0LEC-XY
 10.99    166750 308687680         0      UTTBPUUU-XB0BBL5J-NC
 10.87    164900 308678970         0      UTTBPUUU-XB0BBL5J-NE
 10.51    159450 308678970         0      UTTBPUUU-XB0BBL5J-NC-900
 10.32    156650 308678970         0      UTTBPUUU-XB0BBL5J-NE-FN
  5.90     89460       151       592      GIP-ECR-01
  0.95     14400  26188434         0      UTTBPUUU-XB0BBL5J-AF
  0.94     14280  26192800         0      UTTBPUUU-XB0BBL5J-AE
  0.93     14150  26188434         0      UTTBPUUU-XB0BBL5J-AE-900
  0.92     13930       340        41      GIPLEC-01
  0.78     11890  26188434         0      UTTBPUUU-XB0BBL5J-AF-FN
  0.13      1950     22757         0      F8LCD
  0.12      1770      5550         0      RECHJOUR-01
  0.09      1410       150         9      VALCOND-DS3
  0.07      1020   1587369         0      RECH-ZYX3-01
  0.06       920      8710         0      UTTBPUUU-XB0BBL5J-PA
  0.06       910       150         6      TRICOND
  0.05       820   1582719         0      RECH-ZYX3-02
  0.04       560       150         4      F5025-2
  0.04       550         1       550      F-SGR2-01-TDP401


NB : En cas de message "Open Fail on .idy for FFCALDBI.idy", c'est que le fichier *.idy a été perdu. Pour pouvoir utiliser cobprof il vous faut le recréer (commande cob).

Vous trouverez :
  • Total time : temps CPU total
  • paragraph : fonction cobol concernée,
  • %time : pourcentage du temps total d'exécution passé dans ladite fonction,
  • time : temps en ms
  • entries : nombre de passages dans la fonction
  • ms/entry : temps moyen par passage

Notez le "Module called once" : le programme a été exécuté une seule fois (les statistiques sont cumulées à chaque exécution - si vous ne souhaitez pas cela, vous devez supprimer/renommer le *.ipf avant chaque exécution).

Si une fonction appelle un sous programme, le temps de ce sous programme est comptabilisé dans la fonction - sauf si ce sous programme est lui même compilé avec l'option "PROFILE".

La validité des résultats fournis par cet utilitaire est toutefois sujette à caution ... En effet, dans mon exemple :
  • UTTDP424-XB0B0LEC-XY est une fonction "vide" qui ne fait qu'un "perform" vers UTTBPUUU-XB0BBL5J ... qu'elle prenne 688 secondes pour 26 appels n'est pas compréhensible,
  • et si le temps attribué à cette fonction cumule celui des fonctions performées, pourquoi voit-on alors plus bas des références à ces même fonctions UTTBPUUU-XB0BBL5J ?
  • Mode "Profiler" activé le traitement complet dure 28 minutes, mais une fois ce mode désactivé (recompilation sans l'option -C PROFILE) le temps de traitement passe à 3 minutes !
  • En fait le mode "Profiler" semble extrêmement sensible aux boucles (ici 300.000 passages dans chacune des fonctions UTTBPUUU-XB0BBL5J-NC/NE...) et ralentit significativement le traitement ...

En conclusion, si ce Cobprof vous donne la cause de vos problèmes de performance, tant mieux ... Mais regardez son analyse avec circonspection.

  • Limitez son usage a des cas de "simples" (ex : un seul dossier traité).
  • Contrôlez que les temps de traitement avec / sans le mode "Profiler" est inchangé.

PS : Pour supprimer ce mode "Profile", refaites une RBZ sur le module concerné.