Ma comptabilité, une série temporelle comme les autres - partie 4 - dashboards


05/03/2021 warp10 timeseries comptabilité discovery dashboard

Suite de notre épopée :

Nous allons voir aujourd’hui comment présenter ces données à l’aide de Discovery, la solution de Dashboard as Code pour Warp 10 fournie par SenX.

Installation de Discovery

Tout est décrit dans le billet Truly Dynamic Dashboards as Code

Dans mon cas, warp 10 est dans une partition dédiée /srv/warp10 - warp 10 est donc installé dans /srv/warp10/warp10. C’est la valeur de $WARP10_HOME.

Pour la configuration du plugin HTTP, j’ai un fichier $WARP10_HOME/etc/conf.d/80-discovery.conf contenant :

# Load the HTTP Plugin
warp10.plugin.http = io.warp10.plugins.http.HTTPWarp10Plugin
# Define the directory where endpoint spec files will reside
http.dir = /srv/warp10/discovery
# Define the host and port the plugin should bind to
http.host = 127.0.0.1
http.port = 8081
# Expose the Directory and Store so FETCH requests can be performed via the plugin
egress.clients.expose = true

Le plugin HTTP sera donc accessible via une url de base en http://127.0.0.1:8081/

J’ai ensuite créé le fichier /srv/warp10/discovery/discovery.mc2/srv/warp01/discovery est la valeur associée à http.dir dans le fichier précédent.

{
  'path' '/discovery/'
  'prefix' true
  'parsePayload' true
  'macro' <%
    'cerenit/dashboards/' @senx/discovery/dispatcher
  %>
}

Ce fichier indique que :

  • Les dashboards seront disponibles à partir de l’url /discovery/<nom_du_dashboard> ou /discovery/<dossier_ou_arborescence>/<nom_du_dashboard>
  • Le dossier où seront les dashboards seront stockés dans $WARP10_HOME/macros/cerenit/dashboards. Il s’agira de fichier WarpScript ou Flows avec l’extension en .mc2.

Avec ces deux fichiers, nous savons maintenant que :

  • nous accèderons aux dashboards via http://127.0.0.1:8081/discovery/<nom_du_dashboard>.
  • les dashboards seront des fichiers stockés dans ``$WARP10_HOME/macros/cerenit/dashboards`
  • donc le dashboard $WARP10_HOME/macros/cerenit/dashboards/mon_dashboard.mc2 sera accessible via http://127.0.0.1:8081/discovery/mon_dashboard.

Création du premier dashboard

Un dashboard se décompose en différentes parties. Celle contenant les données a le mot clé tiles et contient différente tile. Chaque tile affiche un graphique, un zone de texte, un titre ou tout composant warpView. Pour le reste, on s’appuiera sur le template par défaut.

Donc créeons un fichier $WARP10_HOME/macros/cerenit/dashboards/comptabilite/compta1.mc2 contenant :

<%
   {
     'tiles' [
       {
         'type' 'display'
         'w' 4 'h' 1 'x' 3 'y' 0
         'data' 'Compta - Exemple 1'
       }
       {
         'type' 'line'
         'w' 4 'h' 2 'x' 1 'y' 3
         'data' [
           @cerenit/accountancy/revenue
           'revenue' STORE
           $revenue
         ]
       }
       {
         'type' 'line'
         'w' 4 'h' 2 'x' 5 'y' 3
         'data' [
           @cerenit/accountancy/expense
           'expense' STORE
           $expense
         ]
       }
       {
         'type' 'line'
         'w' 4 'h' 2 'x' 3 'y' 5
         'data' [
           $revenue $expense -
         ]
       }
     ]
   }
   @senx/discovery/render
%>

Comme indiqué précédemment, je me focalise sur le contenu de tiles. La grille de présentation des dashboards est fixé à 12 colonnes par défaut.

Ici, je cherche donc à afficher 4 éléments :

  • Le premier élément est un bloc titre, contenant “Compta - Exemple 1”. Il est placé sur la 3ème item de la grille en parant de la gauche (valeur de x), il est en haut (valeur y de 0) et il occupe une largeur de 4 (valeur de w) et une hauteur de 1 (valeur de h),
  • les trois éléments suivants sont des graphiques de tyme “line” avec un positionnement pour deux les deux premiers soient sur une ligne et le dernier en dessous et plutôt centré par rapport aux deux premmiers.
  • le deuxième et troisième éléments font appels à des macros @cerenit/accountancy/xxx. Je pourrais mettre du code Warpscript directement dans le fichier comme dans l’exemple. Toutefois, le code exécuté dans le dashboard est visible dans le navigateur. Dans la mesure où mes requêtes pour récupérer les données demandent de l’authentification avec un passage de token, je déporte ce code dans une macro et je ne fais donc qu’appeler cette macro. Ainsi, le code sera généré coté serveur et seul le résultat sera retourné dans le navigateur.
  • le dernier élement illustre la capacité intéressante et différentiante de Discovery : on ne fait pas que décrire le dashboard avec du code, on peut aussi faire des opérations sur nos données. Ici je calcule dynamiquement le résultat à partir des données de chiffre d’affaires (revenue) et de dépenses (expense). J’aurais pu faire l’appel à une troisième macro comme les deux éléments précédents, mais vu que j’ai cette capacité de réaliser des opérations au sein d’un dashboard, pourquoi me priver ?
  • enfin, on appelle la fonction @senx/discovery/render pour générer le dashboard.

Revenons sur nos macros ; Warp 10 permet d’avoir des macros exécutées coté serveur. Ces macros peuvent être utiles pour créer/partager du code, elles peuvent prendre des paramètres en entrée si besoin et elles sont exécutées coté serveur. Dans notre cas, pour éviter que nos tokens se balladent dans le navigateur comme indiqué précédemment, c’est cette propriété qui va nous intéresser.

La macro @cerenit/accountancy/revenue se trouve donc dans le fichier $WARP10_HOME/macros/cerenit/accountancy/revenue.mc2 et contient :

<%
  {
    'name' 'cerenit/accountancy/revenue'
    'desc' 'Provide revenue'
  } INFO

  // Actual code
  SAVE 'context' STORE

  '<readToken>' 'readToken' STORE
  [ $readToken 'revenue' { 'company' '=cerenit' } NOW [ 2016 12 1 ] TSELEMENTS-> ] FETCH
  0 GET

  $context RESTORE
%>
'macro' STORE
$macro

Je ne vais pas m’étendre sur la rédaction des macros mais succintement :

  • Le permier bloc donne le nom de la macro et sa description
  • La suite indique le code qui va être réalisé - pour ma part, un FETCH sur la classe “revenue” pour la compagny “cerenit” du 01/12/2016 jusqu’à maintenant. Cette liste n’a qu’un élément que je récupère. C’est ce qui me sera retourné.

La macro @cerenit/accountancy/expense est sur le même modèle en remplaçant revenue par expense.

Ces deux macros nous retournent donc chacune une série temporelle sur la période 12/2016 jusqu’à ce jour : une pour le chiffre d’affaires, une pour les dépenses.

Si vous allez sur http://127.0.0.1:8081/discovery/comptabilite/compta1, vous verrez le dashboard suivant :

warp10

Le template par défaut est assez minimaliste et on note la présence d’un logo SenX. Je n’ai rien contre, mais comme c’est la compatabilité de mon entreprise que je présente, autant changer cet aspect des choses.

Ajustements graphiques

Pour continuer progressivement, nous allons :

  • Rajouter un titre et une description à notre dashboard en précisant les propriétés title et description en début de fichier
  • Rajouter un footer en bas de page en précisant la propriété footer
  • Supprimer le logo SenX en précisant la propriété template
  • Ajuster la position des blocs pour qu’ils soient centrés comme le reste des éléments

On met cela dans un nouveau fichier $WARP10_HOME/macros/cerenit/dashboards/comptabilite/compta2.mc2.

<%
   {
     'title' 'Comptabilité CerenIT'
     'description' 'Comptabilité CérénIT depuis 2016'
     'tiles' [
       {
         'type' 'display'
         'w' 4 'h' 1 'x' 4 'y' 0
         'data' 'Compta - Exemple 2'
       }
       {
         'title" "Chiffre d'affaires'
         'type' 'line'
         'w' 4 'h' 2 'x' 2 'y' 3
         'data' [
           @cerenit/accountancy/revenue
           'revenue' STORE
           $revenue
         ]
       }
       {
         'title' 'Dépenses'
         'type' 'line'
         'w' 4 'h' 2 'x' 6 'y' 3
         'data' [
           @cerenit/accountancy/expense
           'expense' STORE
           $expense
         ]
       }
       {
         'title' 'Résultat'
         'type' 'line'
         'w' 4 'h' 2 'x' 4 'y' 5
         'data' [
           $revenue $expense -
         ]
       }
     ]
     'footer' '<p style="text-align: center;">CérénIT &copy; 2021 - Réalisé avec Discovery et Warp 10 de SenX</p>'
     'template'
   <'
<!DOCTYPE html><html><head><title id="pageTitle"></title>
  {{{CSS}}}
  {{{HEAD}}}
</head>
<body>
<div class="heading">
  <div class="header"><h1 id="title" class="discovery-title"></h1><p id="desc" class="discovery-description"></p></div>
</div>
{{{HEADER}}}
{{{GRID}}}
{{{FOOTER}}}
{{{JS}}}
</body></html>
    '>
   }
   @senx/discovery/render
%>

Si les propriétés title, description et footer vont de soi, pour trouver comment supprimer le logo SenX, il m’a fallu lire le contenu de la macro @senx/discovery/html pour mieux comprendre les différents placehoders et leur fonctionnement.

Si vous allez sur http://127.0.0.1:8081/discovery/comptabilite/compta2, vous verrez le dashboard suivant :

warp10

A ce stade, on note que les propriétés title de chaque graphique n’est pas affiché. En dehors de ça, nous retrouvons bien tous nos éléments ajustés.

Néanmoins, cette lecture de @senx/discovery/html permet de voir que l’on a pas mal de points d’entrée pour rajouter des éléments spécifiques. Le tout sera de veiller à ne pas impacter les composants graphiques WarpView dans leur sémantique pour ne pas créer de dysfonctionnement.

Un petit coup de bar(re)

Pour finir ce tutoriel, nous allons :

  • lisser un peu ces lignes d’une part, en remplaçant le type de line à spline pour les trois graphiques déjà réalisés (pour les autres modes de réprésentation, voir les options de chart)
  • rajouter un histogramme avec le cumul annuel de nos données avec un chart de type bar.

On met cela dans un nouveau fichier $WARP10_HOME/macros/cerenit/dashboards/comptabilite/compta3.mc2.

<%
   {
     'title' 'Comptabilité CerenIT'
     'description' 'Comptabilité CérénIT depuis 2016'
     'tiles' [
       {
         'type' 'display'
         'w' 4 'h' 1 'x' 4 'y' 0
         'data' 'Compta - Exemple 3'
       }
       {
         'title' 'Chiffre d\'affaires'
         'type' 'spline'
         'w' 4 'h' 2 'x' 2 'y' 3
         'data' [
           @cerenit/accountancy/revenue
           'revenue' STORE
           $revenue
         ]
       }
       {
         'title' 'Dépenses'
         'type' 'spline'
         'w' 4 'h' 2 'x' 6 'y' 3
         'data' [
           @cerenit/accountancy/expense
           'expense' STORE
           $expense
         ]
       }
       {
         'title' 'Résultat'
         'type' 'spline'
         'w' 4 'h' 2 'x' 4 'y' 5
         'data' [
           $revenue $expense -
         ]
       }
       {
          'title' 'Consolidation annuelle'
          'type' 'bar'
          'w' 4 'h' 2 'x' 4 'y' 7
          'data' [
            [ $revenue bucketizer.sum ] @senx/cal/BUCKETIZE.byyear 1970 TIMESHIFT
            [ $expense bucketizer.sum ] @senx/cal/BUCKETIZE.byyear 1970 TIMESHIFT
            [ @cerenit/accountancy/result bucketizer.sum ] @senx/cal/BUCKETIZE.byyear 1970 TIMESHIFT
          ]
          'options' { 'timeMode' 'timestamp' }
       }
     ]
     'footer' '<p style="text-align: center;">CérénIT &copy; 2021 - Réalisé avec Discovery et Warp 10 de SenX</p>'
     'template'
   <'
<!DOCTYPE html><html><head><title id="pageTitle"></title>
  {{{CSS}}}
  {{{HEAD}}}
</head>
<body>
<div class="heading">
  <div class="header"><h1 id="title" class="discovery-title"></h1><p id="desc" class="discovery-description"></p></div>
</div>
{{{HEADER}}}
{{{GRID}}}
{{{FOOTER}}}
{{{JS}}}
</body></html>
    '>
   }
   @senx/discovery/render
%>

Pour ce dernier graphique, il est donc de type bar. Pour le détail des requêtes, je vous renvoie à la partie 2 qui explique cela. Dans notre cas, il faut juste veiller à passer une option supplémentaires pour que timeMode interprête la date issue de la requête comme un timestamp et non comme une date par défaut. D’autres options comme la gestion de la présentation en mode vertical/horizontal ou en mode “stacked” ou pas.

Si vous allez sur http://127.0.0.1:8081/discovery/comptabilite/compta3, vous verrez le dashboard suivant :

warp10

Pour résumer ce billet, nous aovns pu voir que :

  • Warp 10 dispose d’une solution de Dashboard avec Discovery
  • Comme on pouvait le voir dans le studio, à partir du moment où l’on a nos requêtes, il est aisé de les mettre dans des dashboards
  • Les macros permettent de ne pas exposer des tokens dans le navigateur et de faire des calculs cotés serveur
  • Il est possible de personnaliser l’apparence des dashboards - des points d’entrée et des mécanismes de surcharges sont à notre disposition pour en faire ce que l’on souhaite
  • Les composants WarpView sont assez riches et se configurent facilement

Syndication

Restez informé(s) de notre actualité en vous abonnant au flux du blog (Atom)

Nuage de tags

kubernetes docker influxdb timeseries traefik warp10 grafana ansible kafka postgres elasticsearch python aws sécurité terraform mysql redis tick cassandra cloud helm ovh docker-compose git ptsm swarm telegraf timescaledb rancher résilience test chronograf dashboard flux gcp gitlab hashicorp log machine-learning prometheus spark architecture arm confluent devops iac java ksql microservice monitoring s3 serverless vscode angularjs api bilan cert-manager cncf container cérénit dns gke graphql ingress javascript kapacitor opensource operator optimisation perspective pipeline podman raspberrypi service-mesh sql ssh stream warpscript windows comptabilité csp documentation elastic flows forecast hpkp influxace iot jenkins kafka-streams kibana kubedb lambda lean licence maesh maintenance mariadb microsoft mobile nginx nomad npm orientdb performance redhat registry rest rethinkdb reverse-proxy rook sauvegarde scaleway timescale vault vector agile apm automatisation azure bash big-data bigdatahebdo ceph certificat ci/cd cli cluster consul containerd continous-delivery continous-integration cookie data dataviz deployment diff fluxlang framework gdpr gitlab-ci grav hsts http/3 https hypriot hébergement influxdata influxdays istio jq json k3s lets-encrypt linux load-balancer longhorn meetup molecule mongodb nosql nvidia openebs openssh ovhcloud percona php pip postgresql reaper replication rootless rpi rsyslog runc scale secrets société solr sre systemd timezone tls virtualenv vitess vue.js wagtail warpfleet yarn accessibilité acme akka alerte alibaba amazon-emr amqp anomalie anonymisation anthos apache-pulsar ara arima arrow artefact audit bastion beam beat bounded-context branche brigade browser buildkit cahier-des-charges calico cassandra-reaper cd cdc cdk centos centralisation-de-logs certificats cgroups chart checklist chrome ci cilium cloud-init cloud-native cloud-storage clusterip cnab cni cockroachdb code codeurs-en-seine commit confluence conftest context continous-deployment conventional-commit coreos cors covid19 cqrs crash cri cron crontab csi csrf css curl d3.js daemonset data-engineer data-pipelining data.gouv.fr databricks datacenter date date-scientist ddd debezium debian delta deprek8 desktop devoxx dig discovery distributed-systems dive docker-app docker-hub docker-registry docker-swarm dockershim documentdb dog dokcer données-personnelles draft drop-in duration déploiement développement-du-site e-commerce ebs ec2 edge elassandra electron elk engineering entreprise ergonomie etcd event-sourcing faas facebook faisabilité falcor feature-policy fedora feed filebeat firebase firefox fish flash flask fleet flink fluentd formation foundation frontend fsync fullstack github gitignore glacier glowroot go golang google google-cloud-next gpg gpu grid géospatial hacker hadoop haproxy harbor hdfs header html html5 http hue ia iaac ibm immutable incident index indluxdata influxcloud infrastructure-as-code ingénierie inspec jquery jwt k3d k8s k9s kotlin kubeadm kubecon kubectl label laravel letsencrypt libssh linky linter liste-de-diffusion lmap loadbalancer logstash logstatsh loi mailing-list management maturité mesh mesos message metallb micro-service mot-de-passe mqtt multi-cloud médecine métrique network newsletter nodeport null object-storage observability observabilité opa opendata openhab openmetrics openshit openstack openweb over-engineering packaging pandas parquet partiql password persistent-volume-claim pipenv pod portainer portworx prediction prescience production promql prévision ptyhon publicité pubsub pulsar push pyenv pérénnité qualité quasardb quay questdb queue quic ram rambleed raml react recaptcha recherche redistimeseries reindex reinvent reliability remote-execution repository responsive revocation revue-de-code rexec rgpd rhel rkt rolespec root rpo rto rust rwd safe-harbor scalabilité scanner schema scp sdk search select serverless-architecture service service-account service-worker setuptools sftp sha1 sharding shell shipyard sidecar souveraineté-numérique spinnaker spécifications sri ssh-agent ssl stabilité stash statistique storage sudo superset suse sympa syslog-ng sérénité template tempo terracost terrascan test-unitaire tidb tiers timer timestream training transformation travail tsfr tsl ubuntu unikernel unit ux vendredi victoria-metrics vie-privée virtualbox virtualisation vm vnc volume voxxeddays vpc warpstudio web yaml yq yubikey