Le blog tech de Nicolas Steinmetz (Time Series, IoT, Web, Ops, Data)
Suite de notre épopée :
A l’issue du précédent billet, depuis le WarpStudio et en stockant les données dans la sandbox, nous avons manipuler les données pour :
Cependant, cela n’est pas parfait :
Nous allons voir aujourd’hui comment rappatrier les données générées dans sa propre instance Warp 10.
Pour commencer du bon pied et être sur que tout le monde est au même niveau, nous allons regénérer les prévisions et chaque prévision sera alors stockée dans une sériée dédiée. Cela nous permet d’avoir notre jeu de données de départ. On doit pouvoir sauver directement nos données dans une base distante, mais pour simplifier le tutoriel, nous allons le faire en deux étapes.
'<read token>' 'readToken' STORE
'<write token>' 'writeToken' STORE
// Récupération des séries 2017 > 2020
[ $readToken 'expense' { 'company' '=cerenit' } '2016-12-01T00:00:00Z' '2021-01-01T00:00:00Z' ] FETCH
0 GET
'exp' STORE
[ $readToken 'revenue' { 'company' '=cerenit' } '2016-12-01T00:00:00Z' '2021-01-01T00:00:00Z' ] FETCH
0 GET
'revenue' STORE
[ $readToken 'result' { 'company' '=cerenit' } '2016-12-01T00:00:00Z' '2021-01-01T00:00:00Z' ] FETCH
0 GET
'result' STORE
// Prévision sur les 12 prochains mois avec AUTO
// On n'a pas besoin d'afficher les données
// Donc plus besoin de les stocker sous forme de variable avec utilisation de la fonction STORE
// Par contre, on veut perstister les données en base
// ce qui se fait avec UPDATE et l'utilsation d'un token en écriture
[ $result mapper.todouble 0 0 0 ] MAP
AUTO 12 FORECAST.ADDVALUES
"auto_result" RENAME
$writeToken UPDATE
[ $revenue mapper.todouble 0 0 0 ] MAP
AUTO 12 FORECAST.ADDVALUES
"auto_revenue" RENAME
$writeToken UPDATE
[ $exp mapper.todouble 0 0 0 ] MAP
AUTO 12 FORECAST.ADDVALUES
"auto_expense" RENAME
$writeToken UPDATE
# Prévisions avec SAUTO
[ $result mapper.todouble 0 0 0 ] MAP
12 SAUTO 12 FORECAST.ADDVALUES
"sauto_result" RENAME
$writeToken UPDATE
[ $revenue mapper.todouble 0 0 0 ] MAP
12 SAUTO 12 FORECAST.ADDVALUES
"sauto_revenue" RENAME
$writeToken UPDATE
[ $exp mapper.todouble 0 0 0 ] MAP
12 SAUTO 12 FORECAST.ADDVALUES
"sauto_expense" RENAME
$writeToken UPDATE
Si nous vouulons vérifier que vos données sont bien en base, il faut utiliser FETCH :
// Ex de FETCH avec la série auto_revenue
'<read token>' 'readToken' STORE
[ $readToken 'auto_revenue' { 'company' '=cerenit' } '2016-12-01T00:00:00Z' '2022-01-01T00:00:00Z' ] FETCH
0 GET
Attaquons maintenant la grande traversée des données vers mon instance Warp 10.
Alors on pourrait simplement migrer les données à coup de “curl in/curl out” mais l’idée ici est plus d’illustrer les interactions possibles entre des instances Warp 10.
Pour exécuter du warpscrip sur une instance distante, il faut utiliser la fonction REXEC
Cette exécution distante est désactivée par défaut, il faut donc activer cette extension:
Dans /path/to/warp10/etc/conf.d/70--extensions.conf
, nous avons :
// REXEC
#warpscript.extension.rexec = io.warp10.script.ext.rexec.RexecWarpScriptExtension
#warpscript.rexec.endpoint.patterns = .*
// REXEC connect timeout in ms (default = 0, no timeout)
#warpscript.rexec.timeout.connect = 3600000
// REXEC read timeout in ms (default = 0, no timeout)
#warpscript.rexec.timeout.read = 3600000
Décommentons ces lignes et relançons warp 10.
Pour valider que REXEC est bien activé, depuis le studio, nous pouvons faire un test simple:
'2 2 +' 'https://warp10.url:port/api/v0/exec' REXEC
La réponse est 4.
Attention, il faut choisir votre instance comme endpoint dans la liste déroulante du studio. Si vous êtes sur le endpoint de la sandbox, vous auez le message d’erreur suivant :
https://sandbox.senx.io/api/v0/exec
line #2: Exception at ''2%202%20+' 'https://warp10.url:port/api/v0/exec' =>REXEC<=' in section [TOP] (REXEC encountered a forbidden URL 'http://warp10.url:port/api/v0/exec')
En effet, depuis la Sandbox, il n’est pas possible d’accéder à n’importe quelle machine par mesure de sécurité.
Dans le studio, à partir de maintenant, il doit être configuré pour utliiser votre instance Warp 10 comme endpoint.
Le test simple étant fonctionnel, passons à un test un peu plus compliqué, à savoir recupérer nos données hébergées depuis la sandbox en lecture pour le moment.
// tokens pour la sandbox
'<sandboxReadToken>' 'sandboxReadToken' STORE
'<sandboxWriteToken>' 'sandoxWriteToken' STORE
// Url de la sandbox
'https://sandbox.senx.io/api/v0/exec' 'url' STORE
// On introduit ici la notion de template - comme on va vouloir récupérer plusieurs séries avec les mêmes paramètres
// Autant automatiser un peu et s'appuyer sur une boucle ! :-)
// On crée donc un TEMPLATE pour la fonction FETCH qui va récupérer un token en écriture
// et un nom de classe permettant de récupérer nos GTS.
// Rappel le <' ... '> permet de faire des strings en multi-lignes
// On stocke le template sous la forme d'une variable fetchTpl.
<'
{
'token' '{{ remoteReadToken }}'
'class' '{{ remoteClass }}'
'labels' {}
'start' '2016-12-01T00:00:00Z'
'end' '2022-01-31T00:00:00Z'
} FETCH
'>
'fetchTpl' STORE
// Avec la fonction TEMPLATE, on remplace les clés par leurs valeurs en fournissant le template
// et un dictionnaire à la fonction.
$fetchTpl
{ 'remoteReadToken' $sandboxReadToken 'remoteClass' 'revenue' } TEMPLATE
// Execution de la requête distante avec REXECZ
// La différence avec REXEC est qu'une compression est appliquée sur la réponse à la requête
$url REXECZ
// La liste de GTS issue de FETCH ne contient qu'une liste, on prend donc la première
0 GET
// Stockage sous la forme d'une variable
'revenueGTS' STORE
// Affichage de la série
$revenueGTS
Si vous allez dans l’onglet dataviz, vous pouvez constater que vos données issues de la sandbox mais qui ont transité via votre instance sont bien disponibles.
Si nous commençons par une seule série :
// tokens de l'instance
'<instanceReadToken>' 'instanceReadToken' STORE
'<instanceWriteToken>' 'instanceWriteToken' STORE
// tokens pour la sandbox
'<sandboxReadToken>' 'sandboxReadToken' STORE
'<sandboxWriteToken>' 'sandoxWriteToken' STORE
// Url de la sandbox
'https://sandbox.senx.io/api/v0/exec' 'url' STORE
// Template de code warpscript
<'
{
'token' '{{ remoteReadToken }}'
'class' '{{ remoteClass }}'
'labels' {}
'start' '2016-12-01T00:00:00Z'
'end' '2022-01-31T00:00:00Z'
} FETCH
'>
'fetchTpl' STORE
// Substitution des variables
$fetchTpl
{ 'remoteReadToken' $sandboxReadToken 'remoteClass' 'revenue' } TEMPLATE
// Exécution de la requête
$url REXECZ
// La liste de GTS issue de FETCH ne contient qu'une liste, on prend donc la première
0 GET
// Il faut renommer "localement" la série avant de pouvoir la stocker dans l'instance
// Peut éviter de mauvaises manipulations que l'on pourrait regretter :-)
"revenue" RENAME
// Persistance des données
$instanceWriteToken UPDATE
Il y a quelques occurences de “revenue” en dur dans le code, il va falloir améliorer cela.
Et maintenant, traitons nos 9 series d’un coup
// tokens de l'instance
'<instanceReadToken>' 'instanceReadToken' STORE
'<instanceWriteToken>' 'instanceWriteToken' STORE
// tokens pour la sandbox
'<sandboxReadToken>' 'sandboxReadToken' STORE
'<sandboxWriteToken>' 'sandoxWriteToken' STORE
// Url de la sandbox
'https://sandbox.senx.io/api/v0/exec' 'url' STORE
// Template de code warpscript
<'
{
'token' '{{ remoteReadToken }}'
'class' '{{ remoteClass }}'
'labels' {}
'start' '2016-12-01T00:00:00Z'
'end' '2022-01-31T00:00:00Z'
} FETCH
'>
'fetchTpl' STORE
// Création d'une liste avec nos 9 séries
// C'est cette liste que nous allons passer ensuite dans une MACRO.
// Cette MACRO va être exécutée sur chaque élément de la liste via l'utilisation de la fonction LMAP
// https://www.warp10.io/doc/LMAP
[ 'revenue' 'exp' 'result' 'auto_revenue' 'auto_result' 'auto_expense' 'sauto_revenue' 'sauto_result' 'sauto_expense' ]
// Début de la MACRO
<%
// On récupère la valeur de la liste que l'on stocke sous la forme d'une variable
'remoteClass' STORE
// Substitution des valeurs de template
$fetchTpl
{ 'remoteReadToken' $sandboxReadToken 'remoteClass' $remoteClass } TEMPLATE
// Exécution distante de la requête
$url REXECZ
// On récupère ici une liste de GTS - plutôt que d'en extraire la GTS comme précédemment
// on va garder une liste de GTS à 1 élément, mais ce qui permet à nouveau d'utiliser la fonction LMAP
// Sur chaque entrée de la liste, une seconde macro est appliquée
// Le contenu de notre macro consiste à utliser la fonction RENAME
// '+' RENAME, cela revient à renommer la GTS en prenant le même nom que celui qui est fourni
// '+x' RENAME aurait ajouté un x au nom de la série
// Il reste l'index de la liste à traiter - soit on le supprime avec DROP
//<% DROP '+' RENAME %> LMAP
// Soit on passe F comme 3ème argument à LMAP - cela permet d'ignorer cet index
// <% '+' RENAME %> F LMAP
// Prenons la seconde forme :
<% '+' RENAME %> F LMAP
// Toutes nos séries ont été correctement renommées !
// On persiste la GTS dans la base locale
$instanceWriteToken UPDATE
%>
// Fin de la MACRO
// Application de la fonction LMAP pour que notre macro soit exécutée sur chaque élément de la liste.
// Comme on ne veut que les valeurs de la liste et pas les index, on positionne aussi F
// comme 3ème argument à LMAP
F LMAP
Et voilà, nos données ont été récupérées de la Sandbox et stockées dans notre instance locale.
Une version alternative - dans mes données, je peux tricher et ne filtrer que sur le label company
avec pour valeur cerenit
:
// tokens de l'instance
'<instanceReadToken>' 'instanceReadToken' STORE
'<instanceWriteToken>' 'instanceWriteToken' STORE
// tokens pour la sandbox
'<sandboxReadToken>' 'sandboxReadToken' STORE
'<sandboxWriteToken>' 'sandoxWriteToken' STORE
// Url de la sandbox
'https://sandbox.senx.io/api/v0/exec' 'url' STORE
// Warpscript template
<'
{
'token' '{{ remoteReadToken }}'
'class' '~.*'
'labels' { 'company' 'cerenit' }
'start' '2016-12-01T00:00:00Z'
'end' '2022-01-31T00:00:00Z'
} FETCH
'>
'fetchTpl' STORE
// Substitution dans le template
$fetchTpl
{ 'remoteReadToken' $sandboxReadToken } TEMPLATE
// Execution de la requête
$url REXECZ
// Renommage des séries
<% '+' RENAME %> F LMAP
// Presistence des données
$instanceWriteToken UPDATE
Bravo si vous m’avez suivi jusqu’ici, nous avons pu voir l’utilisation de :
REXEC
et REXECZ
LMAP
et une MACRO
TEMPLATE
Nous verrons dans un prochain épisode :