jeudi 11 juillet 2024

L'administration d'une solution Mulesoft / Administering a Mulesoft solution


Le but de cet article est d'expliquer comment peut-on administrer une application Mulesoft ou un ensemble d'applications Mulesoft. Bien que le Control Pane fourni par CloudHub propose de nombreuses pages de configuration / consultation - en particulier pour les logs - elle ne permet pas de répondre rapidement aux questions très liées au domaine traité,  telles que: "pourquoi ma commande CI234325 n'a été importée dans SAP" ou "Est-ce que le fichier MVTOPT_1243.csv a été traité ?". Sans développement adapté, répondre à ce type de question nécessite une investigation - et de l'archéologie dans les logs - rarement négligeable en terme de temps passé.

Il n'est donc pas raisonnable de se contenter des fonctions fournies en standard par l'outil, il faut l'accompagner de fonctionnalités d'administration spécifiques, qu'il faut développer en parallèle des fonctionnalités qui portent la valeur métier. Certains rétorqueront qu'une utilisation soignée des logs peut palier au problème et ils auraient raison... et tort. Raison, car en effet, toutes les informations nécessaires pour alimenter un outil d'investigation peuvent s'y trouver et tort, car les meilleures logs au monde ont quand même besoin d'un outil sophistiqué pour pouvoir être exploitées efficacement. Les logs (comme on le verra plus loin) sont effectivement une solution technique à notre problème, mais en partie seulement.

Prenons un peu de hauteur: à qui et à quoi sert un outil d'investigation 

  1. Qui ? essentiellement deux types d'intervenants:
    • le Support Niveau 2 (c'est à dire la personne qui doit localiser OU le problème a eu lieu) 
    • l'exploitant, qui doit s'assurer que les flux inter-applicatifs fonctionnent correctement.
  2. Quoi ? 
    • Répondre aux questions très concrètes posées plus haut, 
    • vérifier le bon fonctionnement du système, 
    • lancer des commandes pour assurer ce bon fonctionnement.

Pour qu'un tel outil soit vraiment utile et utilisable, il faut:

Qu'il soit unique : si le support niveau 2 doit farfouiller dans les logs de dix outils différents il risque de consommer beaucoup de temps à consulter ceux qui ne sont pour rien dans l'incident. S'il n'a qu'un outil, il saura immédiatement où l'incident a eu lieu.

Qu'il soit efficace : c'est à dire qu'il propose :

  • un filtre sur mot clé, généralement l'identifiant d'un objet fonctionnel (la commande, le produit,  le client) ou technique (le fichier d'import MVTOPT_1243.csv)
  • d'ordonner les lignes récupérées 
  • de mettre en exergue les informations les plus pertinentes
  • d'alerter en cas de dysfonctionnement grave
  • de surveiller l'usage de certaines ressources ou de détecter la présence ou l'absence d'artefacts ou de services
  • des méthodes simples d'intervention pour relancer un flux ou apporter une correction

On voit ici que les fonctionnalités demandées sont peu ou prou celles offertes par une base de données. Notons que si les fonctionnalités de recherches sont plus puissantes, le travail d'investigation s'en trouvera encore davantage faciliter.

En bref, une solution d'administration est composée des trois éléments donnés dans le schéma ci-dessous:

  • les applications Mulesoft qui alimentent le système en notifications,
  • une base de données (au sens général: un outil capable de conserver de l'information et de la structurer, pas forcément un SGBD)
  • un outil de consultation des notifications collectées capable aussi d'emmètre des commandes à destination des serveurs Mulesoft.


Les applications Mulesoft alimentent la base de données au fur et à mesure de l'exécution des API et des flux. Le support de niveau 2 ainsi que l'exploitation utilise l'outil de consultation pour vérifier l'état du système ou identifier la cause d'un incident. Notons qu'un tel système peut être utilisé par d'autres composantes du SI que Mulesoft et qu'il est même très utile que ce soit le cas: cela permet de suivre le déroulement d'un processus de l'entreprise de manière transversale aux outils.

Quelles informations conserver et comment doivent elles être structurées ? Je propose le principe suivant (vu chez un de nos clients et qui s'est révélé particulièrement efficace). La structure d'une notification est la suivante:

  • Un identifiant de session (ou de identifiant de transaction)
  • Le type et l'identifiant de l'objet technique/fonctionnel concerné par la notification 
  • La date (estampille temporelle a la milliseconde) ou la notification a été émise
  • La source (= instance Mulesoft ou outil tiers) à l'origine de la notification
  • L'opération en cours (sachant qu'une session/transaction peut être une succession de ces opérations)
  • Une zone d'information plus générale.

La structure des notifications fait penser à celle de logs et effectivement certains logs peuvent être utilisées pour implémenter des notifications. Nous verrons dans la suite de ce document que plusieurs solutions de monitoring existantes utilisent ce type d'implémentation (ELK, Titanium).

L'identifiant de session (identifiant généralement un processus métier) est le liant entre les différents objets impliqués dans le processus (par exemple, le fichier csv et les commandes décrites dans le fichier csv que l'on crée) et pour cette raison, c'est un élément essentiel pour reconstruire l'historique de transactions complexes.

La partie information peut contenir n'importe quel type d'information, mais nous avons avantage à ce que cette information soit structurée (XML, JSON) car cela permet de construire des filtres plus sophistiquées.

Dressons une liste des implémentations les plus courantes:

ELK

C'est un peu la solution par défaut. Elle consiste à rapatrier les logs de Mulesoft (et des autres outils) à l'aide de Logstash, de les stocker dans une base Elastic Search et d'utiliser ensuite Kibana pour l'exploiter. Ces trois outils sont proposés en Open Source.


Les avantages de la solution sont :

  • Solution de référence du marché
  • Solution de référence de l’éditeur MULESOFT
  • Compétences disponibles sur le marché
  • Outillage disponible et éprouvé Open Source
  • Utilise les LOG Mulesoft
  • Utilise les LOG des autres outils du SI
  • Peut être utile même si aucune fonction de support/monitoring n’a été développée
  • Intégration avec les logs de DEBUG/TRACE
Elle présente cependant quelques inconvénients:
  • Les compétences ELK sont très techniques et chères
  • La maintenance d’une solution ELK est hors de portée d’un client non technique
  • Le coût d’une installation ELK est non négligeable
  • La maîtrise de Kibana est essentielle pour proposer un service adapté
  • Infrastructure ELK dédiée requise (Cloud ou OnPremise)
  • Ne répond pas au problématiques d’intervention/correction (=> Dev d’une API et d’une collection POSTMAN dediée)
C'est en général la solution qui sera choisie par les DSI disposant d'un personnel vraiment technique et qui ont déjà installé ELK pour d'autres portions de leur SI. 

Titanium

Titanium est une offre optionnelle de Mulesoft qui propose diverses services et mises à disposition de davantage de ressources (place disque notamment). Elle s'accompagne de services supplémentaire d'exploitation de logs à partir du contrôle Pane, qui couvre en grande partie les besoins sus-cités.




Parmi les avantages, on compte:
  • Solution éditeur Clé en main
  • Utilise les LOG Mulesoft
  • Pas de coût d’installation,  de configuration 
  • Pas d’infrastructure dédiée
  • Pas de maintenance donc autonomie du client
  • Parfaitement intégrée dans la contrôle Pane
  • Peut être utile même si aucune fonction de support/monitoring n’a été développée
  • Intégration avec les logs de DEBUG/INFO
et pour les inconvénients :
  • Coût de l’extension Titanium
  • Service très « générique » non configurable
  • Ne répond pas au problématiques d’intervention/correction (=> Dev d’une API et d’une collection POSTMAN dédiée)
  • Ne sais pas utiliser les LOG des autres pièces du SI
  • Peut nécessiter le développement d’un API de LOG sur Mulesoft à mettre à la disposition des autres pièces du SI
C'est finalement une solution très facile d'accès pour ceux qui n'ont pas les moyens de construire/installer/maintenir une solution, c'est à dire beaucoup d'entreprise de taille petites ou moyenne dont l'informatique n'est pas le métier.

Solution "faite maison"

Il est bien sûr possible de se construire soi-même une solution à partir des outils logiciels du marché (SGBDR, Postman, ...). Cela peut paraître à priori une option à éviter, développer et maintenir soit même une solution d'infrastructure est rarement conseillé. Cependant, mon expérience montre que notre client le mieux "équipé" pour assurer un monitoring efficace l'est grâce à une solution de ce type. En limitant configuration et développement au minimum, cela peut faire sens.



Avantages:
  • Répond à toutes les problématiques (surveillance, investigation, intervention)
  • Permet l’implémentation de solutions de monitoring très adaptées et très efficaces
  • Ne nécessite que des compétences technique MULESOFT (et POSTMAN) « basiques »
  • Peut venir en complément d’une autre solution (pour la partie intervention notamment)
Inconvénients
  • Coût de la mise en place (tout est à faire…)
  • Maintenance de la solution (généralement hors de portée d’un Client)
  • Nécessite une infrastructure dédiée (en Cloud ou onPremise)
  • Instrumentation spécifique du code Mulesoft
  • Pas de possibilité de l’intégrer « automatiquement » aux LOG Mulesoft et des autres pièces du SI
  • Peut nécessiter le développement d’un API de LOG sur Mulesoft à mettre à la disposition des autres pièces du SI
C'est la solution de ceux qui ont une bonne maîtrise technique et qui préfèrent investir dans la fabrication d'un outil plutôt que de passer ensuite du temps dans l'archéologie de logs. Son adaptabilité à votre contexte en fait une solution vraiment efficace si vous savez rester sages dans l'effort de réalisation. 

Une solution de monitoring du marché

Il existe des solutions de monitoring/exploitation sur le marché et qui vont de zéro à l'infini, que ce soit en terme de fonctionnalités ou de prix. La plupart des grandes entreprises en sont équipées et exigent des nouvelles solutions qu'elle viennent s'y intégrer.


En voici les avantages:
  • Permet une gestion très intégré des actions de monitoring et d’exploitation
  • Très adaptée aux problématiques des (très) grands clients 
  • Offre un panel riche de fonctionnalités
Et les inconvénients: 
  • Très structurant pour le SI du Client (en fait, cette solution n’est possible – et devient obligatoire – que si le client a DÉJÀ mis en place une solution de ce type.
  • Coût (cependant noter qu’il existe des solution Open Source)
  • Fonctionnalités et expérience entièrement dépendante de l’outil
  • Installation et configuration entièrement dépendante de l’outil (ce n'est parfois pas évident de trouver des compétences sur le marché)
En conclusion

Le type de la solution qui vous mettrez en oeuvre dépend beaucoup de votre contexte (le métier de votre entreprise est elle proche de l'informatique ? Quelle est la taille de votre entreprise ? Disposez vous déja d'outils de ce type ? etc). Généralement,  le choix vous sera dictée par votre environnement. Le point majeur à retenir est qu'une solution quelle qu'elle soit est indispensable à moyen ou long terme. Si vous pouvez passer votre phase d'Hypercare en consultant des logs et en surveillant votre système avec l'attention d'un mère, vous risquez vite de vous épuiser si vous ne vous outillez pas.
_________________________________________________________________________

The purpose of this article is to explain how to administer a Mulesoft application or a set of Mulesoft applications. Although the Control Pane provided by CloudHub offers a number of configuration / consultation pages - particularly for logs - it does not provide a quick answer to questions that are very closely related to the domain being dealt with, such as: "Why has my CI234325 command not been imported into SAP?" or "Has the MVTOPT_1243.csv file been processed? Without appropriate development, answering this type of question requires investigation - and archaeology in the logs - which is rarely negligible in terms of time spent.

It is therefore unreasonable to be satisfied with the functions provided as standard by the tool. It must be accompanied by specific administration functions, which must be developed in parallel with the functions that deliver business value. Some will argue that careful use of logs can solve the problem, and they would be right... and wrong. Right, because in fact all the information needed to feed an investigation tool can be found there and wrong, because the best logs in the world still need a sophisticated tool to be exploited effectively. Logs (as we shall see later) are indeed a technical solution to our problem, but only in part.

Let's take a step back: who and what is the purpose of an investigative tool? 

  • Who? Essentially two types of stakeholder:
    • Level 2 Support (i.e. the person who has to locate WHERE the problem occurred) 
    • the operator, who must ensure that the inter-application flows function correctly.

  • What does this mean? 
    • Answering the very specific questions posed above, 
    • check that the system is working properly 
    • issue commands to ensure that the system is working properly.

For such a tool to be truly useful and usable, it needs to be..:

It must be unique: if level 2 support has to rummage through the logs of ten different tools, it runs the risk of spending a lot of time consulting those that had nothing to do with the incident. If it only has one tool, it will know immediately where the incident took place.

It must be efficient: in other words, it must offer :

  • a keyword filter, generally the identifier of a functional object (the order, the product, the customer) or a technical object (the MVTOPT_1243.csv import file)
  • order the lines retrieved 
  • highlight the most relevant information
  • alert in the event of a serious malfunction
  • monitor the use of certain resources or detect the presence or absence of artefacts or services
  • simple intervention methods to restart a flow or make a correction

We can see here that the functions required are more or less the same as those offered by a database. Note that if the search functions are more powerful, the investigation work will be even easier.

In short, an administration solution is made up of the three elements shown in the diagram below:

  • the Mulesoft applications that feed the system with notifications,
  • a database (in the general sense: a tool capable of storing information and structuring it, not necessarily a DBMS)
  • a tool for consulting the notifications collected, also capable of issuing commands to the Mulesoft servers

Mulesoft applications feed the database as APIs and flows are executed. Level 2 support and operations use the consultation tool to check the status of the system or identify the cause of an incident. It should be noted that such a system can be used by IS components other than Mulesoft, and that it is even very useful for this to be the case: it enables the progress of a company process to be monitored across all the tools.

What information should be kept and how should it be structured? I suggest the following principle (seen with one of our customers and which has proved particularly effective). The structure of a notification is as follows:

  • A session identifier (or transaction identifier)
  • The type and identifier of the technical/functional object concerned by the notification 
  • The date (time stamp to the millisecond) on which the notification was issued
  • The source (= Mulesoft instance or third-party tool) of the notification
  • The current operation (bearing in mind that a session/transaction can be a succession of these operations)
  • A more general information area.

The structure of the notifications is reminiscent of that of logs, and indeed some logs can be used to implement notifications. We will see later in this document that several existing monitoring solutions use this type of implementation (ELK, Titanium).

The session identifier (generally identifying a business process) is the link between the various objects involved in the process (for example, the csv file and the commands described in the csv file that is created) and for this reason it is an essential element for reconstructing the history of complex transactions.

The information part can contain any type of information, but it is to our advantage if this information is structured (XML, JSON) as this allows us to build more sophisticated filters.

Here's a list of the most common implementations:

ELK

This is more or less the default solution. It involves retrieving logs from Mulesoft (and other tools) using Logstash, storing them in an Elastic Search database and then using Kibana to exploit it. These three tools are offered as Open Source.

The advantages of the solution are :
  • Market benchmark solution
  • MULESOFT's benchmark solution
  • Skills available on the market
  • Available and proven Open Source tools
  • Uses Mulesoft LOGs
  • Uses the LOGs of other IS tools
  • Can be useful even if no support/monitoring function has been developed
  • Integration with DEBUG/TRACE logs
However, it does have a few drawbacks:
  • ELK skills are highly technical and expensive
  • The maintenance of an ELK solution is out of reach for a non-technical customer
  • The cost of an ELK installation is not negligible
  • Expertise in Kibana is essential to offer a suitable service
  • Dedicated ELK infrastructure required (Cloud or OnPremise)
  • Does not address intervention/correction issues (=> Dev of an API and a dedicated POSTMAN collection)
This is generally the solution chosen by IT Departments with truly technical staff who have already installed ELK for other parts of their IS. 

Titanium

Titanium is an optional offer from Mulesoft that provides various services and more resources (disk space in particular). It is accompanied by additional logging services based on Pane control, which largely covers the above-mentioned needs.

Benefits include
  • Turnkey editor solution
  • Uses Mulesoft LOGs
  • No installation or configuration costs 
  • No dedicated infrastructure
  • No maintenance, so customer autonomy
  • Perfectly integrated into Pane control
  • Can be useful even if no support/monitoring function has been developed
  • Integration with DEBUG/INFO logs
and for the disadvantages :
  • Cost of the Titanium extension
  • Very generic, non-configurable service
  • Does not address intervention/correction issues (=> Dev of an API and a dedicated POSTMAN collection)
  • Does not know how to use LOGs from other parts of the IS
  • May require the development of a LOG API on Mulesoft to be made available to other parts of the IS
In the end, it's a solution that's very easy to access for those who don't have the resources to build/install/maintain a solution, i.e. many small and medium-sized businesses whose core business isn't IT.

Home-made solutions

It is of course possible to build your own solution using off-the-shelf software tools (RDBMS, Postman, etc.). On the face of it, this may seem like an option to be avoided, as developing and maintaining an infrastructure solution yourself is rarely advisable. However, my experience shows that our customer who is best 'equipped' to ensure effective monitoring is thanks to a solution of this type. By keeping configuration and development to a minimum, this can make sense.



The benefits:
  • Responds to all issues (monitoring, investigation, intervention)
  • Allows the implementation of highly adapted and effective monitoring solutions
  • Requires only "basic" MULESOFT (and POSTMAN) technical skills
  • Can be used in conjunction with another solution (particularly for intervention)
Disadvantages
  • Cost of implementation (everything has to be done...)
  • Maintenance of the solution (generally out of reach for a customer)
  • Requires a dedicated infrastructure (Cloud or onPremise)
  • Specific instrumentation for Mulesoft code
  • Cannot be "automatically" integrated with Mulesoft LOGs and other parts of the IS
  • May require the development of a LOG API on Mulesoft to be made available to other parts of the IS
This is the solution for those with a good technical command who prefer to invest in the manufacture of a tool rather than spend time on the archaeology of logs. Its adaptability to your context makes it a truly effective solution if you know how to be wise in the effort involved. 

A monitoring solution on the market

There are monitoring/operating solutions on the market, ranging from zero to infinity, both in terms of functionality and price. Most large companies are equipped with them and require new solutions to integrate with them.

Here are the advantages:
  • Allows highly integrated management of monitoring and operational actions
  • Highly adapted to the needs of (very) large customers 
  • Offers a rich range of functions
And the disadvantages: 
  • Very structuring for the customer's IS (in fact, this solution is only possible - and becomes compulsory - if the customer has ALREADY implemented a solution of this type.
  • Cost (although it should be noted that there are Open Source solutions)
  • Functionality and experience entirely dependent on the tool
  • Installation and configuration entirely dependent on the tool (it is sometimes difficult to find skills on the market)
In conclusion

The type of solution you implement will depend very much on your context (is your company's business IT-related? How big is your company? Do you already have tools of this type? etc). Generally, the choice will be dictated by your environment. The main point to remember is that a solution of any kind is essential in the medium or long term. If you can get through your Hypercare phase by consulting logs and monitoring your system with the attention of a mother, you run the risk of running out of steam if you don't get the tools you need.


dimanche 24 mars 2024

Transformer un contenu YAML en JAVA properties et vice versa / Transforming YAML content into JAVA properties and vice versa

Dans Mulesoft, deux formats sont privilégiés pour définir des propriétés: YAML et JAVA properties. L'amusant (enfin, pour ceux que le challenge tente...), c'est que selon l'outil, c'est l'un ou l'autre format qui est utilisé. Par exemple, sur Anypoint Studio, YAML est privilégié. Sur la console d'administration CloudHub, c'est Java Properties. Question: est-il possible de passer facilement de l'un à l'autre, par un petit script DataWeave ? Un exemple bien utile serait de pouvoir transformer la configuration en YAML d'une application en en ensemble de propriétés JAVA que l'on viendrait copier/coller dans les paramètres de l'onglet "settings" d'une application sur CloudHub.

On parle de passer de çà:

sftp:
host: "localhost"
port: "8081"

salesforce:
"token": "fghhgghjhgffddgghh"
"credentials":
"user": "Tintin"
"password": "VGFDZE"

à çà:

sftp.host = localhost
sftp.port = 8081
salesforce.token = fghhgghjhgffddgghh
salesforce.credentials.user = Tintin
salesforce.credentials.password = VGFDZE

Le script qui permet de le faire est le suivant:

%dw 2.0
output text/plain
fun yaml2json(o)=flatten (o pluck (v, k)-> (
v pluck (v2, k2)-> if ((typeOf(v2) as String)=='Object')
yaml2json((k ++ "." ++ k2):v2)
else
(k ++ "." ++ k2):v2
)
) reduce (l, a={})->(a ++ l)
fun json2Properties(o) = (o pluck {key:$$, value:$})
reduce (l, a="")-> a ++ (l["key"] ++ " = " ++ l["value"] ++ "\n")
---
json2Properties(yaml2json(payload))

Le principe consiste à prendre JSON comme format pivot, mais en réduisant la structure à un unique objets, dont les noms de chaque champ est son chemin dans la structure. Il s'agit donc d'obtenir la valeur suivante:

{
"sftp.host": "localhost",
"sftp.port": "8081",
"salesforce.token": "fghhgghjhgffddgghh",
"salesforce.credentials.user": "Tintin",
"salesforce.credentials.password": "VGFDZE"
}

Toute la magie est dans la fonction récursive yaml2json: la partie centrale (les deux pluck et le if ... else) agrège les noms des différents champs par le signe point, la partie périphérique (flatten et la reduction) aplatit la structure.

La fonction json2Properties construit une chaîne de caractères au format JAVA properties c'est à dire en concaténant toutes les lignes par un retour chariot et en associant clé et valeur à l'aide du signe égal. Pour que le résultat apparaisse proprement, il faut que le format de sortie du script soit défini comme: "plain/text".

Ce qu'on à fait dans un sens, peut-on le refaire dans l'autre ? La réponse est affirmative évidemment. Le script à utiliser est le suivant:

%dw 2.0
output application/yaml
fun field(o, v, i) = if (o[v.keys[i]] == null) (
o ++ if (i==sizeOf(v.keys)-1)
(v.keys[i]):v.value
else
(v.keys[i]):field({}, v, i+1)
) else (
o - v.keys[i] ++ (v.keys[i]):field(o[v.keys[i]], v, i+1)
)
fun prop2json(p) = p splitBy "\n"
map ($ splitBy "=")
map { keys: trim($[0]) splitBy ".", value: trim($[1]) }
reduce (v, a={}) -> field(a, v, 0)
---
prop2json(payload)

Cette fois une seule étape suffit car DataWeave reconnait le format YAML. Il suffit donc de construire la structure idoine (fonction prop2json) et de demander une sortie au format "application/yaml". La fonction procède en deux temps: elle construit une structure ou chaque association clé/valeur est structuré en autant d'objets associant un tableau des segments de clé et la valeur (c'est tout le début du contenu de la fonction) pour obtenir cela:

[
{
"keys": [
"sftp",
"host"
],
"value": "localhost"
},
{
"keys": [
"sftp",
"port"
],
"value": "8081"
},
{
"keys": [
"salesforce",
"token"
],
"value": "fghhgghjhgffddgghh"
},
{
"keys": [
"salesforce",
"credentials",
"user"
],
"value": "Tintin"
},
{
"keys": [
"salesforce",
"credentials",
"password"
],
"value": "VGFDZE"
}
]

Ce formatage est suivi par une réduction qui construit la structure arborescente en utilisant pour cela une fonction récursive "field". Le "if" extérieur de la fonction field" sépare le cas ou le segment rencontré n'est pas déjà présent dans la structure, du cas ou l'est. Le "if" intérieur sépare le cas ou la valeur rencontrée est de type primitif de celui ou c'est un objet (qui doit être être traité dans une nouvelle étape de la récursion). 
______________________________________________________________________

In Mulesoft, there are two preferred formats for defining properties: YAML and JAVA properties. The funny thing (well, for those who are up for a challenge...) is that, depending on the tool, one or the other format is used. On Anypoint Studio, for example, YAML is the preferred format. On the CloudHub administration console, Java Properties is used. Question: is it possible to switch easily from one to the other, using a small DataWeave script? A useful example would be to be able to transform an application's YAML configuration into a set of JAVA properties that you could be copy/paste'd into the settings tab of an application on CloudHub.

We're talking about starting with this:

sftp:
host: "localhost"
port: "8081"

salesforce:
"token": "fghhgghjhgffddgghh"
"credentials":
"user": "Tintin"
"password": "VGFDZE"

to obtain this:

sftp.host = localhost
sftp.port = 8081
salesforce.token = fghhgghjhgffddgghh
salesforce.credentials.user = Tintin
salesforce.credentials.password = VGFDZE

The script to do this is as follows:

%dw 2.0
output text/plain
fun yaml2json(o)=flatten (o pluck (v, k)-> (
v pluck (v2, k2)-> if ((typeOf(v2) as String)=='Object')
yaml2json((k ++ "." ++ k2):v2)
else
(k ++ "." ++ k2):v2
)
) reduce (l, a={})->(a ++ l)
fun json2Properties(o) = (o pluck {key:$$, value:$})
reduce (l, a="")-> a ++ (l["key"] ++ " = " ++ l["value"] ++ "\n")
---
json2Properties(yaml2json(payload))

The principle is to use JSON as the pivot format, but reduce the structure to a single object, with the name of each field being its path through the structure. The aim is to obtain the following value:

{
"sftp.host": "localhost",
"sftp.port": "8081",
"salesforce.token": "fghhgghjhgffddgghh",
"salesforce.credentials.user": "Tintin",
"salesforce.credentials.password": "VGFDZE"
}

The magic is in the recursive yaml2json function: the central part (the two plucks and the if ... else) aggregates the names of the various fields using the dot sign, while the peripheral part (flatten and reduction) flattens the structure.

The json2Properties function constructs a string in JAVA properties format, i.e. concatenating all lines with a carriage return and associating key and value with the equal sign. For the result to be displayed correctly, the script output format must be defined as "plain/text".

Can you do the same thing in the other direction? The answer is yes, of course. The script to use is as follows:

%dw 2.0
output application/yaml
fun field(o, v, i) = if (o[v.keys[i]] == null) (
o ++ if (i==sizeOf(v.keys)-1)
(v.keys[i]):v.value
else
(v.keys[i]):field({}, v, i+1)
) else (
o - v.keys[i] ++ (v.keys[i]):field(o[v.keys[i]], v, i+1)
)
fun prop2json(p) = p splitBy "\n"
map ($ splitBy "=")
map { keys: trim($[0]) splitBy ".", value: trim($[1]) }
reduce (v, a={}) -> field(a, v, 0)
---
prop2json(payload)

This is a one-step process, as DataWeave recognizes the YAML format. All you need to do is build the appropriate structure (prop2json function) and request output in "application/yaml" format. The function proceeds in two stages: it builds a structure where each key/value association is structured into as many objects associating an array of key segments and the value (this is the very beginning of the function's content) to obtain this:

[
{
"keys": [
"sftp",
"host"
],
"value": "localhost"
},
{
"keys": [
"sftp",
"port"
],
"value": "8081"
},
{
"keys": [
"salesforce",
"token"
],
"value": "fghhgghjhgffddgghh"
},
{
"keys": [
"salesforce",
"credentials",
"user"
],
"value": "Tintin"
},
{
"keys": [
"salesforce",
"credentials",
"password"
],
"value": "VGFDZE"
}
]

This formatting is followed by a reduction that builds the tree structure, using a recursive "field" function. The outer "if" of the field function separates the case where the segment encountered is not already present in the structure, from the case where it is. The inner "if" separates the case where the encountered value is of primitive type from the case where it is an object (which must be processed in a new step of the recursion). 



vendredi 8 mars 2024

CONSIGNES: Defaulting

 Cet article regroupe les consignes concernant les valeurs à utiliser par défaut et que doivent suivre les développeurs de VISEO qui travaillent avec moi. Il m'a paru intéressant de les regrouper ici en un article afin qu'elles soient très largement disponibles.

Le "defaulting" de Mulesoft est en général très bon. Il y a néanmoins quelques trous dans la raquette et si vous suivez les consignes données ci-dessous vous vous éviterez bien des ennuis. Cet article a vocation à être régulièrement enrichi, au fur et à mesure de nos "découvertes". Commençons:


Reconnexion

C'est le defaulting de Mulesoft le plus étrange, provoquant, selon mon expérience 50% des bugs rencontrés en production. Par défaut, l'option de reconnexion est fixée par Anypoint Studio à "None", c'est à dire que si la connexion tombe (qu'elle soit HTTP, VM, Object Store, SFTP, etc, etc), elle ne pourra pas être rétablie. Un redémarrage du serveur est alors inévitable. Non seulement ce defaulting est aberrant, mais le fait même de simplement proposer cette option, nécessiterait une explication que je n'ai pas ! Cerise sur le gâteau, il existe une option "Standard" qui comme son nom l'indique ferait une excellente valeur par défaut! Bref, n'oubliez JAMAIS de changer cette option sur tous les objets de configuration (volet "Advanced"):


La valeur des autres paramètres est plus dépendante de votre contexte. Mais les valeurs fournies par Anypoint Studio sont généralement adaptées.
Si vous tentez de vous connecter avec un outil/ressource dont le fonctionnement peut présenter de longues périodes de panne, optez alors pour l'option "forever" en augmentant la valeur du paramètre fréquence à quelque chose de l'ordre de la minute afin d'éviter de mitrailler les systèmes, de requêtes:


J'insiste lourdement sur ce défaulting car il a tout du piège dangereux: en développement, voir en tests utilisateurs, tout semblera bien se passer, car le système ne restera probablement pas actif suffisamment longtemps pour que le connexion tombe. En production, en revanche, cela arrivera fatalement.

Si quelqu'un a une idée sur l'intérêt que peut avoir l'option "None", qu'il prenne contact avec moi. Je l'en remercie d'avance.

Replica Count

Mulesoft insiste, aussi bien dans la documentation, que dans les formations et les forums, sur le fait qu'il faut monter au moins 2 réplicas pour chaque application, afin de garantir une meilleure continuité de service. Je souscris pleinement à ce conseil. Mais pourtant, lorsque l'on déclare une instance, c'est systématiquement 1 réplica qui est proposé par défaut. Donc n'oubliez pas, même dans les environnements qui ne sont pas en production:
  1. de demander au moins 2 réplicas (c'est généralement suffisant)
  2. de cocher l'option "Run In Runtime Cluster Mode" (bas de la page) qui est décoché par défaut.





Sur CloudHub 1.0, c'est déjà une sage précaution. Sur CloudHub 2.0, c'est carrément une nécessité: car la persistance de VM et d'Object Store en dépend ! En effet, tout le contenu de ces deux mécanismes est perdu dès qu'il n'a plus d'instance active. Moralité, si vous redéployez, vous perdez tout ! Que de drames, de faux bugs et de suspicions ai-je rencontré sur les projets parce que les caches ou des données dynamiques de configuration "disparaissent" quand un développeur uploade une nouvelle version.  Mulesoft serait bien inspiré de modifier ce defaulting rapidement.

Le mode Cluster est indispensable avec CloudHub 2.0, non seulement pour assurer la persistence de VM et d'Object Store, mais aussi pour éviter que Mulesoft ne traite "en double" vos fichiers/SFTP et autres scheduler !

Si quelqu'un sait pourquoi Object Store et VM ne sont plus vraiment persistents, sachez que je suis demandeur d'une explication. Cette raison seule me fait préférer CloudHub 1.0 à 2.0 !

Primary Mode Only

Encore un defaulting Mulesoft que j'ai bien du mal à m'expliquer. Toutes Sources de type "On Event" (On new or updated file, On New Message, On New Email) proposent une option "Primary Mode Only" qui n'est jamais cochée par défaut. Noter que les Listeners proposent la même option. Dans le cas des Listeners, le defaulting de cette case à cocher est le bon, même si à l'occasion, il peut être utile ou nécessaire de la changer. 



Dans le cas des composants "On Event", il ne convient pas de systématiquement cocher cette option. Il ne faut le faire de manière systématique que dans le cas ou la simple consommation de la ressource ne provoque pas sa non disponibilité immédiate (comme sa disparition par exemple). C'est le cas en particulier des Sources de type "On New Or Updated File" des connecteurs File, FTP ou SFTP.

En effet, dans le cas de ces Sources, si deux instances Mulesoft sont susceptibles de traiter l'évènement, elles peuvent se faire concurrence. Ce qui revient à traiter l'évènement deux fois. Or dans la quasi totalité des cas, un double traitement entraine des dysfonctionnements. Il faut donc réserver cette fonction à une seule instance de serveur et donc cocher l'option "Primary Node Only".

_____________________________________________________________________

This article brings together the default values that VISEO developers working with me must follow. I thought it would be a good idea to group them together here in one article, so that they are widely available.
Mulesoft's defaulting is generally very good. There are a few holes in the system, however, and if you follow the instructions given below, you'll save yourself a lot of trouble. This article is intended to be regularly enriched, as and when we make "discoveries". Let's get started:

Reconnect

This is Mulesoft's strangest defaulting, causing, in my experience, 50% of the bugs encountered in production. By default, the reconnection option is set by Anypoint Studio to "None", i.e. if the connection drops (whether HTTP, VM, Object Store, SFTP, etc, etc), it cannot be re-established. A server restart is then inevitable. Not only is this defaulting aberrant, but the very fact of proposing this option would require an explanation that I don't have! The icing on the cake is that there is a "Standard" option which, as its name suggests, would make an excellent default value! In short, NEVER forget to change this option on all configuration objects ("Advanced" pane):



The values of the other parameters are more dependent on your context. However, the values provided by Anypoint Studio are generally appropriate.
If you're trying to connect with a tool/resource that may be subject to long periods of downtime, then you should opt for the "forever" option, increasing the value of the frequency parameter to something on the order of a minute, to avoid peppering systems with requests:


I'm insisting heavily on this defaulting because it's a dangerous trap: in development, or even in user testing, everything will seem to be going well, as the system will probably not remain active long enough for the connection to fall out. In production, on the other hand, this is bound to happen.

If anyone has any ideas about the usefulness of the "None" option, please get in touch with me. Thank you in advance.

Replica Count

In its documentation, training courses and forums, Mulesoft insists on the need to set up at least 2 replicas for each application, to guarantee better continuity of service. I fully subscribe to this advice. However, when an instance is declared, 1 replica is systematically proposed by default. So don't forget, even in non-production environments:
  1. request at least 2 replicas (this is generally sufficient)
  2. check the "Run In Runtime Cluster Mode" option (bottom of page), which is unchecked by default.





On CloudHub 1.0, this is already a wise precaution.On CloudHub 2.0, it's an absolute necessity: because VM and Object Store persistence depend on it!Indeed, all the content of these two mechanisms is lost as soon as there is no longer an active instance.If you redeploy, you lose everything! What drama, false bugs and suspicions I've encountered on projects because caches or dynamic configuration data "disappear" when a developer uploade a new version.  Mulesoft would be well advised to change this defaulting quickly.

Cluster mode is essential with CloudHub 2.0, not only to ensure VM and Object Store persistence, but also to prevent Mulesoft from "duplicating" your files/SFTP and other schedulers!

If anyone knows why Object Store and VM aren't really persistent anymore, I'd love to hear about it. This reason alone makes me prefer CloudHub 1.0 to 2.0!

Primary Mode Only

Another Mulesoft defaulting that I'm having trouble explaining to myself. All "On Event" Sources (On new or updated file, On New Message, On New Email) offer a "Primary Mode Only" option which is never checked by default.Note that Listeners offer the same option.In the case of Listener, the default setting of this checkbox is the correct one, although it may occasionally be useful or necessary to change it.



In the case of "On Event" components, this option should not be systematically checked. It should only be systematically ticked if the simple consumption of the resource does not result in its immediate non-availability (e.g. its disappearance).This is particularly the case for "On New Or Updated File" sources on File, FTP or SFTP connectors.

Indeed, in the case of these Sources, if two Mulesoft instances are likely to process the event, they can compete with each other. This means processing the event twice. In almost all cases, double processing leads to malfunctions. You should therefore reserve this function for a single server instance, and check the "Primary Node Only" option.



mercredi 6 mars 2024

Conserver une requête / Keep a query

Un problème assez commun que l'on doit traiter avec Mulesoft est la conservation de requêtes. De plus en plus souvent, nous connectons nos serveurs Mulesoft à des services qui délivrent des informations au fil de l'eau, au travers de ce qui est trop vite nommé des "Webhooks". Nous reparlerons prochainement des avantages et limites de telles architectures. Contentons nous aujourd'hui de répondre à une question: si je ne peut traiter dans l'immédiat une sollicitation pour une raison ou une autre (indisponibilité d'un service par exemple), comment puis-je m'assurer que je ne vais pas la perdre et pourrai la resoumettre plus tard ?

En fait, avec Mulesoft, c'est assez facile à implémenter en utilisant deux mécanismes:

  1. les queues de messages,
  2. les transactions (XA si nécessaires)

L'idée est simple : lorsque la requête est reçue,  elle est stockée dans une queue de messages. Un autre flux, sous transaction celui-là viendra consommer la requête transformée en message:

Voici la configuration du listener VM (pour la partie transaction):

Dans cet exemple, comme il n'est pas nécessaire d'effectuer de mises à jour distribuées, une transaction locale est suffisante. Mais votre cas peut nécessiter d'utiliser un mode de transaction plus puissant et passer en XA (2 phase commit).

Si le fait d'utiliser une queue de message pour conserver les requêtes est parfois identifié comme une solution de "replay" par les équipes que je côtoie, le mécanisme est plutôt vu comme un mécanisme de gestion d'erreur. Le principe adopté est:

  1. quand je reçois la requête, de façon synchrone, je tente de la traiter.
  2. si je rencontre un problème (partie gestion d'erreur) alors j'expédie la requête dans une queue de messages pour traitement ultérieur
  3. je mets en place un flux capable d'exploiter le contenu de cette queue de messages. Ce flux, globalement, suit le même principe qu'en 1.

C'est faire la même chose en plus compliqué (et donc en plus fragile). S'il n'y a pas de contre-indication pour passer systématiquement par un traitement asynchrone (ce qui est la plupart du temps le cas), simplifions : une requête entrante est systématiquement conservée dans la queue de message. On m'avance parfois un potentiel gain de performance : il est toujours pratiquement nul. Résumons: faites simple.

Second point: quelle système de queue de messages utiliser ? Réponse : quelque chose qui soit performant et fiable. C'est à dire, entre autres, qui puisse s'inscrire dans une transaction. Personnellement, j'utilise la plupart du temps VM. Dans le cas de CloubHub 1.0, ou onPremise, c'est parfaitement justifié. Pour CloudHub 2.0, avec l'abandon d'une "vraie" persistance pour VM et Object Store, c'est plus discutable. L'adoption de Anypoint MQ ne me parait pas pertinent : on ne peut l'inclure dans une transaction ce qui complexifie son utilisation dans notre cas. Reste l'utilisation d'un produit du marché, répondant à la norme Java JMS (comme RabbitMQ, Tibco, ...) : il faut acheter, installer, configurer. Bref, je dirai, par ordre de pertinence:

  1. Si on utilise CloudHub 1.0 ou OnPremise "Bare Metal" : VM
  2. Si on utilise CloudHub 2.0 (ou RuntimeFabric) et que la perte de messages n'est pas une catastrophe irréparable: VM en faisant bien attention à déclarer au minimum 2 instances (ce qui est une très saine précaution, bien au delà de l'utilisation de VM)
  3. Si le perte d'un message est potentiellement une catastrophe absolue: JSM.
  4. Si on aime les challenges techniques (et qu'on dispose par ailleurs du produit): Anypoint MQ avec l'implémentation d'un solide pattern de recouvrement (hors du propos de cet article).
Le dernier sujet est la prise en compte de l'impossibilité de traiter la requête, c'est à dire qu'en dépit de tentatives répétées, on ne peut réussir. Cela peut être du:
  1. au fait qu'une application ou une ressource reste indisponible (j'ai vu des instances SAP être off pendant des jours...)
  2. au fait que le message entrant est erroné et n'est pas traitable en l'état.

Dans les deux cas,  la solution consiste à rediriger le message vers une queue d'erreur généralement appelée Dead-End-Queue (DEQ) ou tout type de conservation équivalent.

VM permet de faire çà très facilement: il suffit d'indiquer le nombre maximum de tentatives que l'on souhaite. L'exception émise est MULE:REDELIVERY_EXHAUSTED :


Pousser un message vers un DEQ ou un système persistent est une chose. Etre en capacité d'exploiter cette DEQ en est une autre. Je vois trop souvent, des équipes implémenter une DEQ sans se préoccuper de la manière dont on l'utilisera. Cela devient effectivement une impasse ! C'est un vrai sujet en soi. Nous en reparlerons dans un prochain article.

____________________________________________________________________

A fairly common problem we have to deal with with Mulesoft is request retention. More and more often, we're connecting our Mulesoft servers to services that deliver information on the fly, through what are all too quickly dubbed "Webhooks". We'll come back to the advantages and limitations of such architectures shortly. For now, let's just answer one question: if I can't immediately process a request for one reason or another (unavailability of a service, for example), how can I be sure I won't lose it and be able to resubmit it later?

In fact, with Mulesoft, this is quite easy to implement, using two mechanisms:

  1. message queues,
  2. transactions (XA if necessary)

The idea is simple: when a request is received, it is stored in a message queue. Another flow, this one under a transaction, will consume the request transformed into a message:

Here's the VM listener configuration (for the transaction part):

In this example, as no distributed updates are required, a local transaction is sufficient. But your case may require you to use a more powerful transaction mode and switch to XA (2 phase commit).

While using a message queue to hold requests is sometimes identified as a "replay" solution by the teams I work with, the mechanism is seen more as an error management mechanism. The principle adopted is:

  1. when I receive the request, synchronously, I try to process it.
  2. if I encounter a problem (error handling part), I send the request to a message queue for further processing
  3. I set up a flow capable of exploiting the contents of this message queue. Overall, this flow follows the same principle as in 1.

It's doing the same thing, only more complicated (and therefore more fragile). If there's no reason to systematically use asynchronous processing (which is most of the time the case), let's simplify: an incoming request is systematically stored in the message queue. I'm sometimes told of a potential performance gain: it's always practically nil. To sum up: keep it simple.

Second point: which message queuing system to use? Answer: something that's efficient and reliable. That is, among other things, something that can be part of a transaction. Personally, I use VM most of the time. In the case of CloubHub 1.0, or onPremise, this is perfectly justified. For CloudHub 2.0, with the abandonment of "true" persistence for VM and Object Store, it's more questionable. Adopting Anypoint MQ doesn't seem relevant to me: you can't include it in a transaction, which complicates its use in our case. That leaves the use of an off-the-shelf product that complies with the Java JMS standard (such as RabbitMQ, Tibco, etc.): you have to buy, install and configure it. In short, in order of relevance:

  1. If using CloudHub 1.0 or OnPremise "Bare Metal": VM
  2. If using CloudHub 2.0 (or RuntimeFabric) and message loss is not an irreparable catastrophe: VM, taking care to declare at least 2 instances (which is a very healthy precaution, well beyond the use of VMs).
  3. If the loss of a message is potentially an absolute catastrophe: JSM.
  4. If you like technical challenges (and have the product at your disposal): Anypoint MQ with the implementation of a solid recovery pattern (outside the scope of this article).
      The last topic is the consideration of the impossibility of processing the query, i.e. that despite repeated attempts, we can't succeed. This may be due to:
      1. the fact that an application or resource remains unavailable (I've seen SAP instances be off for days...)
      2. the incoming message is erroneous and cannot be processed as it stands.
      In both cases, the solution is to redirect the message to an error queue, generally called Dead-End-Queue (DEQ), or any equivalent type of conservation.

      VM makes this very easy: all you have to do is specify the maximum number of retries you want. The exception is MULE:REDELIVERY_EXHAUSTED :

      Pushing a message to a persistent DEQ or system is one thing. Being able to exploit that DEQ is quite another. All too often, I see teams implementing a DEQ without thinking about how it will be used. This becomes a real dead end! It's a real subject in itself. We'll talk more about it in a future article.

      Pourquoi ce blog ? / Why this blog?

      Mulesoft est un ESB du monde Salesforce utilisé pour construire des flots permettant aux pièces logicielles d'un Système d'Informati...