Présentation de la propriété wrapper.filter.<x>.<n>

Les filtres sont une fonctionnalité très puissante qui permet d'ajouter un nouveau comportement à des applications existantes sans aucun codage. Ils fonctionnent en surveillant la sortie console d'une JVM à la recherche de séquences de texte. Lorsqu'elles sont trouvées, un nombre quelconque d'actions peut alors être entrepris.

Un exemple consiste à déclencher un redémarrage de la JVM chaque fois qu'une erreur spécifique se produit. Certaines applications ont des bogues connus où elles cessent de fonctionner une fois qu'elles se trouvent dans un certain état. Cette fonctionnalité permet de contourner de tels problèmes immédiatement jusqu'à ce qu'ils puissent être résolus dans l'application.

Les propriétés utilisées pour configurer les filtres sont décrites ci-dessous :

Au minimum, un filtre doit définir les propriétés wrapper.filter.trigger.<n> et wrapper.filter.action.<n>. Les autres sont facultatives.

Composant <n> :

Dans chaque filtre, le composant « <n> » du nom de la propriété est un nombre entier commençant à « 1 ». Par défaut, la numérotation doit être séquentielle, sans lacunes. La propriété wrapper.ignore_sequence_gaps peut éventuellement être définie pour autoriser des lacunes dans la séquence.

Le Wrapper analysera les filtres définis dans l'ordre croissant en utilisant leur numéro <n>. Dès qu'un filtre correspond, le processus s'arrêtera pour cette ligne de sortie.

Un certain nombre d'exemples d'utilisation se trouvent ci-dessous :

wrapper.filter.trigger.<n>

Compatibilité :3.0.0
Éditions :Édition ProfessionnelleÉdition StandardÉdition Community
Plateformes :WindowsMac OSXLinuxAlpine LinuxFreeBSDSolarisIBM z/Linux

Le déclencheur (trigger) peut être n'importe quelle chaîne, et la propriété suivante est requise pour sa configuration.

Exemple :
wrapper.filter.trigger.1=Error
wrapper.filter.action.1=RESTART

Espaces dans le déclencheur :

La chaîne filtrée peut contenir des espaces. Cependant, en raison de la façon dont les propriétés de configuration sont chargées en général, tout espace en début ou en fin de chaîne sera supprimé lors du chargement de la propriété.

Exemple :
wrapper.filter.trigger.1=  Restart me now.
wrapper.filter.action.1=RESTART

Caractères génériques :

À partir de la version 3.5.5 du Wrapper, il est désormais possible d'inclure des caractères génériques (« * » ou « ? ») dans le texte du déclencheur si la propriété wrapper.filter.allow_wildcards.<n> est également définie sur TRUE.

Les caractères génériques valides sont :

  • Un caractère '*', qui correspondra à « 0 » (zéro) ou plusieurs caractères.
  • Un caractère '?', qui correspondra à exactement un caractère.

NOTE

Les valeurs de déclencheur seront localisées quelque part dans une seule ligne de sortie, il n'est donc pas nécessaire de faire précéder ou suivre une valeur d'un caractère générique « * ». Veuillez noter que cela nuira en fait un peu aux performances de journalisation, car cela rend beaucoup plus difficile pour la correspondance de motifs de déterminer qu'un déclencheur donné N'EST PAS trouvé dans une ligne de sortie de journal.

wrapper.filter.action.<n>

Compatibilité :3.0.0
Éditions :Édition ProfessionnelleÉdition StandardÉdition Community
Plateformes :WindowsMac OSXLinuxAlpine LinuxFreeBSDSolarisIBM z/Linux

La spécification d'une action nécessite que la propriété suivante soit configurée. Si une action est omise, elle sera définie par défaut sur RESTART.

Exemple :
wrapper.filter.trigger.1=Error
wrapper.filter.action.1=RESTART

Les actions possibles sont :

  • DEBUG (Depuis la ver. 3.5.0) :

    provoquera l'enregistrement d'un message de débogage. Cela n'est vraiment utile que pour aider à comprendre quand l'action est déclenchée.

  • STATS (Depuis la ver. 3.5.52, éditions Standard et Professional) :

    affichera les statistiques de performance.

  • DUMP (Depuis la ver. 3.3.6) :

    invoquera un vidage des threads (thread dump).

  • GC (Depuis la ver. 3.5.7) :

    invoquera un balayage complet du ramasse-miettes (garbage collection) dans la JVM. Sachez que le faire fréquemment peut affecter les performances de la JVM, car un balayage complet entraînera souvent le gel de tous les threads pendant la durée du GC.

  • RESTART :

    arrêtera la JVM actuelle, puis relancera une nouvelle invocation.

  • SHUTDOWN :

    arrêtera la JVM ainsi que le Wrapper.

  • USER_<n> (Depuis la ver. 3.5.0, édition Professional) :

    provoquera le déclenchement d'un événement défini par l'utilisateur. Cela peut être soit l'envoi d'un e-mail, soit l'exécution d'une commande système externe. La commande peut aller de l'exécution d'opérations de nettoyage à l'émission d'un piège SNMP.

  • PAUSE (Depuis la ver. 3.5.0) :

    mettra en pause l'application Java si la pause est activée et que la JVM est en cours d'exécution. Consultez la propriété wrapper.pausable pour plus de détails.

  • RESUME (Depuis la ver. 3.5.0) :

    reprendra l'application Java si elle est dans un état de pause. Cela peut être utilisé si la JVM n'est pas arrêtée lorsqu'elle est en pause. Consultez la propriété wrapper.pausable pour plus de détails.

  • SUSPEND_TIMEOUTS_<n> (Depuis la ver. 3.5.40, éditions Standard et Professional) :

    Indique au Wrapper de suspendre tous les délais d'attente utilisés lorsque la JVM ne répond pas. <n> spécifie le nombre de secondes pendant lesquelles les délais d'attente doivent être suspendus, et doit être compris dans la plage 1-3600 (1 h). Cela peut être utilisé si l'application Java doit effectuer une tâche bloquante longue et éviter que le Wrapper considère l'application comme ne répondant pas.

    Les délais d'attente peuvent également être suspendus via d'autres propriétés d'action, le fichier de commandes ou la méthode Java WrapperManager.suspendTimeouts().

    Si plusieurs demandes de suspension des délais d'attente sont effectuées, le nombre de secondes spécifié par chaque demande ne sera pas additionné. Au lieu de cela, le temps nouvellement spécifié replacera le temps de suspension restant s'il est plus long, et sera ignoré dans le cas contraire.

  • RESUME_TIMEOUTS (Depuis la ver. 3.5.40, éditions Standard et Professional) :

    Indique au Wrapper de reprendre tous les délais d'attente précédemment suspendus.

    Les délais d'attente peuvent également être repris via d'autres propriétés d'action, le fichier de commandes ou la méthode Java WrapperManager.resumeTimeouts().

  • NONE :

    est utile car il empêchera tout déclencheur avec un numéro plus élevé d'être déclenché.

Enchaînement de plusieurs actions :

À partir de la version 3.5.0 du Wrapper, il est possible de spécifier plus d'une action en les séparant par un espace ou une virgule. Lorsque plus d'une action est spécifiée, elles seront exécutées en succession rapide dans l'ordre spécifié.

En correspondance avec le déclencheur, l'exemple suivant effectuera un vidage des threads, puis redémarrera la JVM.

Exemple :
wrapper.filter.trigger.1=Error
wrapper.filter.action.1=DUMP,RESTART

wrapper.filter.allow_wildcards.<n>

Compatibilité :3.5.5
Éditions :Édition ProfessionnelleÉdition StandardÉdition Community
Plateformes :WindowsMac OSXLinuxAlpine LinuxFreeBSDSolarisIBM z/Linux

Si elle est définie sur TRUE, cette propriété indique au Wrapper de traiter tous les caractères génériques trouvés dans wrapper.filter.trigger.<n> pour le filtre. Voir : exemple d'utilisation ci-dessous pour plus de détails

Exemple :
wrapper.filter.allow_wildcards.1=TRUE

NOTE

Ce n'est pas si grave, mais la recherche d'un déclencheur contenant un caractère générique peut être un peu plus gourmande en processeur. Cela est particulièrement vrai avec de longues lignes de sortie lorsque les caractères génériques du déclencheur se trouvent vers le début du déclencheur. Plusieurs caractères génériques dans le même déclencheur ralentiront également les choses, car le Wrapper doit essayer toutes les combinaisons possibles pour voir si le motif correspond.

wrapper.filter.message.<n>

Compatibilité :3.5.0
Éditions :Édition ProfessionnelleÉdition StandardÉdition Community
Plateformes :WindowsMac OSXLinuxAlpine LinuxFreeBSDSolarisIBM z/Linux

La propriété wrapper.filter.message.<n> peut être utilisée pour contrôler le message affiché à l'utilisateur lorsqu'un déclencheur est activé. Cela peut être très utile pour expliquer à l'utilisateur ce qui se passe. La valeur par défaut est « Filter trigger matched ».

Exemple :
wrapper.filter.trigger.1=java.lang.OutOfMemoryError
wrapper.filter.action.1=RESTART
wrapper.filter.message.1=The JVM has run out of memory.

Exemples d'utilisation :

Dans cette section, nous vous montrerons plusieurs exemples d'utilisation des déclencheurs. Les filtres fonctionnent en surveillant la sortie console de la JVM. Pour qu'un déclencheur soit activé par une exception, l'application Java doit imprimer le message filtré sur la console.

Correspondance simple

Dans de nombreux cas, vous pouvez souhaiter déclencher une action en réponse à un message existant dans la sortie de votre application.

Dans cet exemple, nous voulons déclencher sur toutes les occurrences du mot « Error » et provoquer un redémarrage de la JVM.

Exemple :
wrapper.filter.trigger.1=Error
wrapper.filter.action.1=RESTART
Exemple de sortie du Wrapper :
jvm 1    | The next line should cause the Wrapper to restart the JVM:
jvm 1    |   Error
wrapper  | Filter trigger matched.  Restarting JVM.
wrapper  | Launching a JVM...
jvm 2    | WrapperManager: Initializing...

Caractères génériques

Dans certains cas, vous ne connaissez pas la chaîne exacte avec laquelle vous allez effectuer la correspondance, il est donc souvent très utile de pouvoir configurer un déclencheur contenant des caractères génériques pouvant être utilisés pour effectuer la correspondance.

Exemple :
wrapper.filter.trigger.1=Head*Tail-?
wrapper.filter.allow_wildcards.1=TRUE
wrapper.filter.action.1=RESTART
Exemple de sortie du Wrapper :
jvm 1    | The next line should cause the Wrapper to restart the JVM:
jvm 1    |   Head a bunch of stuff, then Tail-1 and some more stuff.
wrapper  | Filter trigger matched.  Restarting JVM.
wrapper  | Launching a JVM...
jvm 2    | WrapperManager: Initializing...

Enchaînement de plusieurs actions

À partir de la version 3.5.0 du Wrapper, il est possible de spécifier plus d'une action en les séparant par un espace ou une virgule. Lorsque plus d'une action est spécifiée, elles seront exécutées en succession rapide dans l'ordre spécifié.

L'exemple suivant effectuera un vidage des threads, puis redémarrera la JVM en réponse à la détection d'un message « user error » dans la sortie console.

Exemple :
wrapper.filter.trigger.1=User Error
wrapper.filter.action.1=DUMP,RESTART
Exemple de sortie du Wrapper :
jvm 1    | The next line should cause the Wrapper to restart the JVM:
jvm 1    |   User Error
wrapper  | Filter trigger matched.  Requesting thread dump.
wrapper  | Dumping JVM state.
wrapper  | Filter trigger matched.  Restarting JVM.
jvm 1    | Full thread dump Java HotSpot(TM) Client VM (1.5.0_24-149 mixed mode, sharing):
jvm 1    | 
jvm 1    | "WrapperSimpleAppMain" prio=5 tid=0x0100f400 nid=0x86c600 waiting on condition [0xb0e8e000..0xb0e8ed90]
jvm 1    | 	at java.lang.Thread.sleep(Native Method)
jvm 1    | ...
jvm 1    | "Exception Catcher Thread" prio=10 tid=0x01001910 nid=0x80ac00 runnable 
wrapper  | Launching a JVM...
jvm 2    | WrapperManager: Initializing...

Correspondance avec exceptions

Dans de nombreux cas, vous voudrez écrire une logique pour déclencher à partir d'un morceau de texte, mais découvrirez ensuite que dans certains contextes, vous souhaitez les ignorer. Le déclencheur sera traité dans l'ordre de « <n> ». Une fois qu'une correspondance est trouvée, toutes les autres seront ignorées. Cela permet de configurer des exceptions de correspondance.

Dans cet exemple, nous voulons déclencher sur toutes les occurrences du mot « Error » et redémarrer la JVM, sauf lorsqu'il est trouvé dans « IgnoreError ».

Exemple :
wrapper.filter.trigger.1=IgnoreError
wrapper.filter.action.1=NONE
wrapper.filter.trigger.2=Error
wrapper.filter.action.2=RESTART
Exemple de sortie du Wrapper :
jvm 1    | The next line should be ignored:
jvm 1    |   IgnoreError
jvm 1    | 
jvm 1    | The next line should cause the Wrapper to restart the JVM:
jvm 1    |   Error
wrapper  | Filter trigger matched.  Restarting JVM.
wrapper  | Launching a JVM...
jvm 2    | WrapperManager: Initializing...

Détection d'OutOfMemoryError

NOTE

À partir de la version 3.5.16 du Wrapper, le modèle de fichier de configuration par défaut du Wrapper a été mis à jour afin qu'un redémarrage dû à un filtre OutOfMemoryError correspondant ne soit plus déclenché par défaut si l'utilisateur active la sortie -verbose:class.

En rassemblant tout cela, nous pouvons créer un filtre pour détecter chaque fois qu'une OutOfMemoryError est levée dans une stack trace.

La façon la plus simple de le faire est la suivante :

Exemple :
wrapper.filter.trigger.1=java.lang.OutOfMemoryError
wrapper.filter.action.1=RESTART

Cela peut poser le problème que si le nom de la classe est affiché à un autre emplacement inattendu, un redémarrage involontaire pourrait être déclenché. Un exemple de cela est lorsque l'argument -XX:+PrintClassHistogram a été passé à la JVM, Java produira un histogramme très utile de toutes les classes chargées, indiquant combien d'instances sont actuellement en mémoire. Lorsque Java affiche le compte pour la classe OutOfMemoryError, le déclencheur ci-dessus provoquera le redémarrage de la JVM.

Exemple :
jvm 1    |  186:             6            384  sun.reflect.generics.repository.MethodRepository
jvm 1    |  187:             8            384  java.lang.OutOfMemoryError
wrapper  | The JVM has run out of memory.  Restarting JVM.
jvm 1    |  188:             8            384  java.io.OutputStreamWriter
jvm 1    |  189:             1            376  java.awt.Checkbox

Pour contourner cela, il est possible de configurer des exceptions. Cependant, si nous savons que nous voulons uniquement déclencher sur la classe OutOfMemoryError lorsqu'elle est affichée dans une stack trace, nous pouvons utiliser les caractères génériques pour produire un motif plus ciblé.

Exemple :
wrapper.filter.trigger.1=Exception in thread "*" java.lang.OutOfMemoryError
wrapper.filter.allow_wildcards.1=TRUE
wrapper.filter.action.1=RESTART
wrapper.filter.message.1=The JVM has run out of memory.
Exemple de sortie du Wrapper :
jvm 1    | Mention the java.lang.OutOfMemoryError exception (Not triggered)
jvm 1    | 
jvm 1    | Now thow a new java.lang.OutOfMemoryError to invoke a stack trace:
jvm 1    | Exception in thread "MyApp-Main" java.lang.OutOfMemoryError
wrapper  | The JVM has run out of memory.  Restarting JVM.
jvm 1    |      at com.myapp.Main.doSomething(Main.java:321)
jvm 1    |      at com.myapp.Main.main(Main.java:654)
wrapper  | Launching a JVM...
jvm 2    | WrapperManager: Initializing...

Il reste cependant un cas où vous pourriez obtenir un faux positif. Si l'utilisateur affiche l'intégralité de la configuration du Wrapper, par exemple, vous verrez alors une sortie comme la suivante :

Exemple de sortie du Wrapper :
jvm 1    |   wrapper.filter.trigger.1=Exception in thread "*" java.lang.OutOfMemoryError
wrapper  | The JVM has run out of memory.  Restarting JVM.

Ce n'est, bien sûr, pas ce que vous voulez. Vous pouvez éviter cela en effectuant une correspondance de texte brut sur le même texte SANS les caractères génériques activés, comme suit :

Exemple :
wrapper.filter.trigger.1=Exception in thread "*" java.lang.OutOfMemoryError
wrapper.filter.action.1=NONE

wrapper.filter.trigger.2=Exception in thread "*" java.lang.OutOfMemoryError
wrapper.filter.allow_wildcards.2=TRUE
wrapper.filter.action.2=RESTART
wrapper.filter.message.2=The JVM has run out of memory.