Cet article traite du diagramme technique dans les projets de Data Engineering, examinant des solutions telles que Google Slides et draw.io. Il met en lumière les défis d’alignement et conclut par une réflexion sur la simplification de ce processus.
Dans un projet de Data Engineering, pour avoir une représentation complète du projet un diagramme technique résumant l’intégralité du pipeline est nécessaire. Comment créer rapidement et facilement un diagramme technique qui résume le data pipeline d’un projet ? C’est une question qui se pose fréquemment quand vient le moment de représenter son pipeline. Il est possible de le faire directement sur Google Slides en insérant des formes et des flèches, mais cela peut vite devenir pénible quand il faut redimensionner les différentes parties, les faire bouger ensemble ou aligner le texte. Il existe aussi des outils, comme draw.io, qui facilitent la création de diagramme en liant les différentes parties, cependant les problèmes d’alignement persistent et le pipeline sera réalisé uniquement avec des formes.
Pour éviter tous ces problèmes et limitations, il est possible d’utiliser le package Diagrams qui, en quelques lignes de code, va produire un diagramme technique facilement lisible. De plus, le fait de créer un diagramme technique avec du code permet de réutiliser ce qui a été fait et si plusieurs personnes travaillent en collaboration sur un même diagramme, cela permet de facilement utiliser un outil de version control.
Nous allons voir dans le détail que Diagram est un outil flexible qui permet de produire des diagrammes techniques facilement tout en gardant une certaine clarté pour les lecteurs. Nous allons voir étape par étape comment utiliser ce package et ses fonctionnalités.
Pour pouvoir utiliser le package diagrams, il est nécessaire d’avoir Python 3.6 ou une version supérieure. Ensuite, il faudra installer GraphViz car c’est ce qui permet d’afficher les graphiques. Vous pourrez trouver GraphViz dans la section « Getting Started » du github du projet Diagram.
Ensuite vous pourrez installer la librairie diagrams avec votre gestionnaire de package, et alors vous serez prêt pour commencer à créer de magnifiques diagrammes.
Pour ma part j’ai installé le package avec pip
pip install diagrams
Dans ce package il y a 4 éléments différents :
Les 3 premiers éléments sont caractérisés respectivement par une classe. Concernant les nœuds il existe de nombreuses classes proposées par différents fournisseurs comme AWS, Azure ou GCP pour les clouds ou encore Kubernetes. Vous pouvez retrouver l’ensemble des classes dans la documentation officielle du package.
Enfin, ces 4 éléments sont liés : en effet un diagramme est constitué de nœuds qui peuvent être rassemblés entre eux dans des groupes et qui sont reliés entre eux par des liens. Il faudra donc importer les classes nécessaires afin de pouvoir représenter correctement votre diagramme d’architecture.
Maintenant, essayons de coder un premier diagramme pour comprendre les bases du package.
from
diagrams
import
Diagram
from
diagrams.aws.analytics
import
Glue, Quicksight
from
diagrams.aws.database
import
RDS
from
diagrams.aws.management
import
Cloudwatch
from
diagrams.aws.storage
import
S3
with
Diagram('Pipeline - Global Overview', filename='Diagramm/Pipeline_GO', show=True, direction="LR"):
db = RDS('RDS Database')
jobs = Glue('ETL')
log = Cloudwatch('Logging')
bucket = S3('S3 Buckets')
dashboard = Quicksight('Dashboard')
db >> jobs >> bucket >> dashboard
jobs >> log
Ce diagramme décrit un pipeline de data engineering, utilisant une table contenue dans une base de données RDS, traité via l’ETL AWS Glue. Les résultats du traitement sont stockés dans un bucket S3 et les logs dans Cloudwatch. Enfin un dashboard Quicksight est branché sur le bucket S3.
Regardons en détail ce premier morceau de code. Nous importons tout d’abord la classe Diagram, qui est nécessaire pour produire un diagramme. Ensuite, nous importons quelques classes de nœuds du fournisseur AWS, par exemple RDS, Glue, etc.
On crée alors un nouveau Diagram avec le nom ‘Pipeline – Global Overview’. Comme nous avons renseigné le paramètre filename, le diagramme va être enregistré à l’emplacement indiqué, attention le chemin indiqué est un chemin relatif (la racine sera la même que celle de l’emplacement où le code est exécuté, par exemple si le code est lancé depuis le bureau, le diagramme sera enregistré sur le bureau) et non un chemin absolu. Le paramètre show étant égal à True, Python va ouvrir immédiatement le diagramme après l’exécution du code. Le paramètre direction indique dans quel sens va être construit le graphique, ici il sera de gauche à droite (from Left to Right), qui est le paramètre par défaut. Les autres options sont de droite à gauche (RL), de haut en bas (TB) et de bas en haut (BT). À l’intérieur du diagramme, on crée plusieurs nœuds, avec les classes que nous avons importées. Pour créer un lien entre deux nœuds, il faut ajouter ‘>>’ entre les deux nœuds si on souhaite que la flèche aille de gauche à droite ou ‘<<‘ le cas échéant.
Afin de terminer avec toutes les classes du package, essayons un diagramme un peu plus complexe intégrant des clusters.
from
diagrams
import
Diagram, Cluster
from
diagrams.aws.analytics
import
Glue, Quicksight
from
diagrams.aws.database
import
RDS
from
diagrams.aws.management
import
Cloudwatch
from
diagrams.aws.storage
import
S3
with
Diagram('Pipeline - Global Overview', filename='Diagramm/Pipeline_GO', show=True, direction="LR"):
db = RDS('RDS Database')
with
Cluster('AWS Glue (ETL) \n Data Engineering\n (Filter, join, rename...)'):
jobs = [Glue('Job1'), Glue('Job2')]
log = Cloudwatch('Logging')
bucket = S3('S3 Buckets')
dashboard = Quicksight('Dashboard')
db >> jobs >> bucket >> dashboard
jobs >> log
Ce diagramme décrit le même pipeline que le précédent, la seule différence est qu’ici il y a deux Jobs qui sont représentés dans AWS Glue.
L’utilité première des Cluster est de regrouper dans un même sous-ensemble des éléments semblables.
La deuxième utilité que je trouve aux clusters est de pouvoir délimiter de façon encore plus claire les différentes parties du pipeline, comme le montre l’exemple suivant :
from
diagrams
import
Diagram, Cluster
from
diagrams.aws.analytics
import
Glue, Quicksight
from
diagrams.aws.database
import
RDS
from
diagrams.aws.management
import
Cloudwatch
from
diagrams.aws.storage
import
S3
with
Diagram('Pipeline - Global Overview', filename='Diagramm/Pipeline_GO', show=True, direction="LR"):
with
Cluster('RDS'):
db = RDS('PostgreSQL BDD\n stored in RDS')
with
Cluster('AWS Glue (ETL)'):
jobs = Glue('Data Engineering\n (Filter,\n join,\n rename..)')
with
Cluster('Cloudwatch'):
log = Cloudwatch('Monitoring Scripts')
with
Cluster('S3'):
bucket = S3('S3 Buckets\n to store\n AWS Glue outputs')
with
Cluster('Quicksight'):
dashboard = Quicksight('Dashboard\n for monitoring')
db >> jobs >> bucket >> dashboard
jobs >> log
Le code va produire encore une fois le même diagramme, mais l’apparence sera différente, en effet chaque partie d’AWS qui a été utilisée sera encore plus clairement identifiée.
Maintenant que l’on sait utiliser les diagrammes, les clusters, les edges et les nodes, intéressons-nous à la personnalisation. Il y a deux objets personnalisables : les nodes et les edges.
Regardons en premier lieu comment personnaliser les edges. Il y a 3 paramètres de personnalisation : la couleur, le style et le label. La couleur par défaut est le gris, mais si vous souhaitez paramétrer une autre couleur, les couleurs sont celles utilisées par le package matplotlib que vous pouvez retrouver ici</a >.
Ensuite, il est possible de jouer sur le style et il y en a 4 de disponibles :
Il n’est pas possible de combiner des styles différents, i.e. avoir une ligne faite de tirets en gras.
Enfin, il est possible de rajouter un label sur un Edge si on souhaite expliciter ce que représente cet Edge.
Voyons voir ce que cela donne en code.
from
diagrams
import
Diagram, Cluster, Edge
from
diagrams.aws.analytics
import
Glue, Quicksight
from
diagrams.aws.database
import
RDS
from
diagrams.aws.management
import
Cloudwatch
from
diagrams.aws.storage
import
S3
def
arrow(color='black', style='line', label=None):
"""
Function to define the edge between the part of the diagram
:param color: the color of the edge, could be any color
:type color: str
:param style: the style of the edge, could be dashed, dotted, bold or line (default)
:type style: str
:param label: the text you want to show on the edge
:type label: str
:return: Edge object with the different parameters we set up
:type: Edge()
"""
return
Edge(color=color, style=style, label=label)
with
Diagram('Pipeline - Global Overview', filename='Diagramm/Pipeline_GO', show=True, direction="LR"):
with
Cluster('RDS'):
db = RDS('PostgreSQL BDD\n stored in RDS')
with
Cluster('AWS Glue (ETL)'):
jobs = Glue('Data Engineering\n (Filter,\n join,\n rename..)')
with
Cluster('Cloudwatch'):
log = Cloudwatch('Monitoring Scripts')
with
Cluster('S3'):
bucket = S3('S3 Buckets\n to store\n AWS Glue outputs')
with
Cluster('Quicksight'):
dashboard = Quicksight('Dashboard\n for monitoring')
db_mycharlotte >> arrow(color='red', style='bold') >> jobs >> arrow(color='red', style='bold') >> \
bucket >> arrow(color='red', style='bold') >> dashboard
jobs >> arrow(color='hotpink', style='dashed') >> log
Ici, j’ai créé une fonction, arrow(), qui produit par défaut une flèche noire en gras, que je préfère à la flèche par défaut du package. J’utilise ensuite cette fonction pour définir les différentes flèches que je souhaite avoir dans mon graphique. Quand on souhaite personnaliser un Edge, il faut explicitement le marquer dans le schéma du diagramme entre les deux nœuds concernés. Ici j’ai souhaité que les Edges du pipeline soient en rouge et en gras, sauf la flèche pour les logs qui est en rose et en pointillés. On peut voir cela dans les deux dernières lignes du code.
Abordons le deuxième point, la personnalisation des Nodes. Qu’est-ce que cela signifie ? La personnalisation des nodes, c’est afficher un Node avec une image qui n’est pas déjà pré-enregistrée dans la banque d’image du package et donc créer un Node qui n’existe pas.
Vous souhaitez représenter l’envoi d’un mail en cas d’erreur ? Cela n’est pas dans les options disponibles sur le package, mais il vous suffit de télécharger une image représentant un e-mail et en utilisant le Node Custom(), vous pourrez intégrer ce nouveau Node à votre diagramme. Il existe donc de nombreuses possibilités de Nodes et la seule limite est votre imagination.
from
diagrams
import
Diagram, Cluster, Edge
from
diagrams.aws.analytics
import
Glue, Quicksight
from
diagrams.aws.database
import
RDS
from
diagrams.aws.management
import
Cloudwatch
from
diagrams.aws.storage
import
S3
with
Diagram('Pipeline - Global Overview', filename='Diagramm/Pipeline_GO', show=True, direction="LR"):
with
Cluster('RDS'):
db = RDS('PostgreSQL BDD\n stored in RDS')
with
Cluster('AWS Glue (ETL)'):
jobs = Glue('Data Engineering\n (Filter,\n join,\n rename..)')
with
Cluster('Cloudwatch'):
log = Cloudwatch('Monitoring Scripts')
with
Cluster('S3'):
bucket = S3('S3 Buckets\n to store\n AWS Glue outputs')
with
Cluster('Quicksight'):
dashboard = Quicksight('Dashboard\n for monitoring')
with
Cluster('Devs'):
houcem = Custom('Houcem\n Lead DS', '.../Custom/houcem.png')
nico = Custom('Nico\n DS', '.../Custom/nico.png')
dev = [nico, houcem]
db >> arrow(color='red', style='bold') >> jobs >> arrow(color='red', style='bold') >> bucket >> \
arrow(color='red', style='bold') >> dashboard jobs >> arrow(color='hotpink', style='dashed') >> log
houcem >> arrow(color='sandybrown', style='dotted') >> jobs
houcem >> arrow(color='sandybrown', style='dotted') >> log
nico >> arrow(color='blue', style='dotted') >> jobs
nico >> arrow(color='blue', style='dotted') >> log
nico >> arrow(color='blue', style='dotted') >> bucket
nico >> arrow(color='blue', style='dotted') >> dashboard
Ici, j’ai choisi de représenter les développeurs qui ont travaillé sur ce projet en spécifiant sur quelles parties du pipeline ils sont intervenus. Pour que ça soit plus visuel, j’ai créé deux nouveaux Nodes avec les photos des développeurs et ainsi, on identifie clairement qui contacter en cas de soucis sur le pipeline.
Enfin une fois que l’on maîtrise les différentes fonctionnalités du package, on peut produire des diagrammes très fournis. En voici un exemple :
from
diagrams
import
Diagram, Cluster, Edge
from
diagrams.aws.analytics
import
Glue, GlueCrawlers, GlueDataCatalog, Quicksight
from
diagrams.aws.database
import
RDS
from
diagrams.aws.management
import
Cloudwatch
from
diagrams.aws.storage
import
S3, SimpleStorageServiceS3Object, SimpleStorageServiceS3BucketWithObjects
from
diagrams.custom
import
Custom
with
Diagram('Pipeline - Global Overview', filename='Diagramm/Pipeline_GO', show=True, direction="LR"):
with
Cluster('RDS'):
db_mycharlotte = RDS('PostgreSQL BDD\n stored in RDS')
with
Cluster('AWS Glue'):
crawler = GlueCrawlers('Glue\n Crawler')
data_catalog = GlueDataCatalog('Glue\n DataCatalog')
jobs = Glue('Glue Jobs')
with
Cluster('Jobs'):
job = [Glue('Job for\n Activity\n transformation'),
Glue('Job for\n Appointment\n transformation')]
with
Cluster('Cloudwatch'):
log = Cloudwatch('\n\n\nMonitoring Scripts')
with
Cluster('S3'):
bucket = SimpleStorageServiceS3BucketWithObjects('S3 Buckets\n to store\n AWS Glue outputs')
with
Cluster('Objects within S3 bucket'):
obj = [SimpleStorageServiceS3Object('Output from \nActivity\n Transformation Job'),
SimpleStorageServiceS3Object('Output from \nAppointment\n Transformation Job')]
with
Cluster('Quicksight'):
dashboard = Quicksight('Dashboard\n for monitoring')
with
Cluster('Devs'):
houcem = Custom('Houcem\n Lead DS', '.../Custom/houcem.png')
nico = Custom('Nico\n DS', '.../Custom/nico2.png')
dev = [nico, houcem]
db >> arrow(color='red') >> data_catalog
db << arrow(color='purple', style='dotted', label='Connect DB ') << crawler >> \
arrow(color='purple', style='dotted', label='to AWS Glue') >> data_catalog >> arrow(color='red') >> \
jobs >> arrow(color='purple') >> job
job >> arrow(color='hotpink', style='dashed') >> log
job >> arrow(color='red') >> bucket >> arrow(color='darkgreen') >> \
obj >> arrow(color='red') >> dashboard
houcem >> arrow(color='sandybrown', style='dotted') >> jobs
houcem >> arrow(color='sandybrown', style='dotted') >> log
nico >> arrow(color='blue', style='dotted') >> jobs
nico >> arrow(color='blue', style='dotted') >> log
nico >> arrow(color='blue', style='dotted') >> bucket
nico >> arrow(color='blue', style='dotted') >> dashboard
On remarque tout d’abord que le code est quand même plus complexe que sur les différents diagrammes précédents. Ensuite, concernant le diagramme en lui-même, il donne un vrai aperçu détaillé du pipeline de traitement de la donnée depuis la base de données jusqu’au dashboard le tout dans l’environnement AWS.
Diagrams est un package qui permet de représenter des pipelines à travers des diagrammes, et cela, avec facilité et flexibilité. Si vous souhaitez avoir plus d’informations et utiliser des commandes plus avancées, je vous conseille de regarder le github du projet Diagrams et particulièrement dans la section Issues.
NB : Cet article a été librement inspiré par l’article Create Beautiful Architecture Diagrams with Python écrit par Dylan Roy et disponible ici