Il fut un temps où me demandait régulièrement de générer des rapports de santé qu’il fallait envoyer quotidiennement par mail. Vous me direz : il est fou, pourquoi créer des script de reporting alors qu’il suffit de deux mot dans son moteur de recherche préféré pour obtenir tout ce qu’il faut !
A cela je répondrait :
- Parce que je fais ce que je veux et j’aime le challenge 🙂
- Souvent le contenu est top mais la mise en page plutôt décevante
Comme vous l’avez vous dans mon article précédent, il est très facile de créer un module PowerShell. Alors pourquoi ne pas se faire un module custom pour générer de beaux rapports HTML ? C’est ce que j’ai fait avec le module wks_htmlReporting.
Comment faire du HTML en PowerShell ?
PowerShell permet facilement de générer du code HTML simple et notamment de convenir des objets en table HTML : ConvertTo-HTML. Par défaut la cmd-let génère le code complet d’une page HTML. Si on lui fournit un objet en entrée, il va l’intégrer dans un tableau. Voici un exemple :
Get-Service | ConvertTo-Html
Mais pour le coup, c’est pas trop sexy 🙁
Heureusement, on peut faire beaucoup mieux :
- Intégrer une CSS pour la mise en page
- Intégrer des modules Javascript pour rendre les page un peu plus dynamiques
Comment faire des graphiques ?
Le plus simple est de demander de l’aide 🙂
Il faut que la page HTML soit autonome, donc un seul fichier et pas de traitement côté serveurs. Ca limite les options. La conclusion logique est : Javascript !
Je suis donc parti sur l’utilisation de Bootstrap et Chart.js. Je vous invite à jeter un œil sur leurs sites respectifs. Techniquement on procédera comme suit:
- Le script powershell ajoute les liens vers les sources JS dans le Header et charge les données au format JSON dans le fichier HTML
- Bootstrap va gérer la mise en page HTML (pagination des tableaux, colorisation automatique, etc.)
- Char.js s’occupera de faire des jolis camembert et autres donuts (ça donne faim …)
Comment utiliser la librairie de Kévin ?
Fonctionnement du module et architecture du rapport
Le module se base sur une approche orientée objet afin de fournir de la flexibilité dans son utilisation.
On dispose de 3 classes :
- htmlReport : qui représente un rapport dans sa globalité. Une fois complété avec le contenu souhaité, il ne reste plus qu’à générer le code HTML ou le fichier selon l’usage souhaité
- htmlSection : un htmlReport se compose de sections (chapitres). On y regroupe des données qui ont un lien entre elles. Par exemple des graphiques accompagnés du tableau avec les informations détaillées. Une section dispose aussi d’un titre qui sert à délimiter la section dans le rapport.
- htmlItem : il s’agit des éléments unitaires qui composent les htmlSection. Ce sont des graphiques, des arborescences, des notifications ou encore des tableaux.
Installer le module PowerShell
Rien de plus facile, il est publié dans la PowerShell Gallery
Install-module wks_htmlReporting
Créer un rapport simple
Voici un exemple avec la liste des services Windows du poste local.
# Initialize script
$filename = "$($env:temp)\wks_htmlReporting.html"
# Generate simple data
$services = get-service |select status, name, DisplayName
# Create a section
$section1 = new-htmlSection "Services Windows" -foldable -folded
# Adds a simple table to the section
$section1 |add-htmlSectionItem -itemList (
new-htmlItemTable -dataset $services
)
# Creates a Report
$report = new-htmlReport -title "Rapport sur les services Windows" `
-subtitle "Feature demonstration of the <b>wks_htmlReporting</b> module" `
# Add section to report
$report |add-htmlReportSection -sectionList ($section1)
# Export report to HTML file
$report.toFile($filename)
On obtient alors un rapport avec un seul paragraphe et une table. Néanmoins, de base on a :
- Un paragraphe qui se déplie lorsqu’on clique dessus
- Un tableau avec pagination
- Une fonction de recherche (filtrage les résultats)
Pas mal pour un début ?
Ajouter des graphiques
Faire un tableau c’est bien mais moi les rapports je préfère les regarder, pas les lires 🙁
Je veux des graphiques ! Allez, qu’à cela ne tienne, on va ajouter des Items dans la Section.
Je reprends le script précédent pour ajouter mes graphiques :
# Define output report file
$filename = "$($env:temp)\wks_htmlReporting.html"
# Generate simple data
$services = get-service -ea SilentlyContinue |select name, DisplayName, @{N="Status";E={$_.Status.toString()}}
# Create a section
$section1 = new-htmlSection "Services Windows" -foldable
# create hashtable with data to display
$dataChart1 = @{}; ($services |group status |select name, count) |% { $dataChart1[$_.name] = $_.count }
# generate chart item
$chart1 = new-htmlItemChart -title "Répartition des services par status" `
-data $dataChart1 `
-chartType 'doughnut'
# create table
$table = new-htmlItemTable -dataset $services
# force item line break in report to have the table below the graphs ;)
add-htmlItemNewRowAfter -item $chart1
# Generate section
$section1 |add-htmlSectionItem -itemList ($chart1, $table)
# Creates a Report
$report = new-htmlReport -title "Rapport sur les services Windows" `
-subtitle "Feature demonstration of the <b>wks_htmlReporting</b> module" `
# Add section to report
$report |add-htmlReportSection -sectionList ($section1)
# Export report to HTML file
$report.toFile($filename)
#& $filename
Pour ajouter un graphique, on créé un objet htmlItem supplémentaire de type Chart. La seule subtilité est que les données qui servent au graphique doivent être fournies sous forme de HashTable. C’est ce que je fais en créant la variable $dataChart1.
Parmi les type de graphique supportés, il y a :
- bar
- pie
- doughnut
Alors, ça commence à ressembler à un vrai rapport, non ?
Ajouter un filtrage automatique des données
Maintenant qu’on a un graphique qui synthétise des éléments du tableau juste en dessous, je me suis dit : on n’est pas trop mal, mais ce serait bien de pouvoir cliquer sur le graphique afin de filtrer automatiquement le tableau. N’est-ce pas ?
Et bien rien de plus simple, il suffit d’ajouter les paramètres à l’item Chart afin de référencer l’item Table et le champ à filtrer… Ah, je vous ait perdu. Regardez l’exemple, c’est hyper intuitif en fait 😉 Il suffit d’ajouter 3 paramètre quand on créé le htlmItemChart :
# Define output report file
$filename = "$($env:temp)\wks_htmlReporting.html"
# Generate simple data
$services = get-service -ea SilentlyContinue |select name, DisplayName, @{N="Status";E={$_.Status.toString()}}
# Create a section
$section1 = new-htmlSection "Services Windows" -foldable
# create hashtable with data to display
$dataChart1 = @{}; ($services |group status |select name, count) |% { $dataChart1[$_.name] = $_.count }
# create table
$table = new-htmlItemTable -dataset $services
# generate chart item
$chart1 = new-htmlItemChart -title "Répartition des services par status" `
-data $dataChart1 `
-chartType 'doughnut' `
-linkedTableId $table.id `
-linkedFieldName 'Status' `
-linkedTableExactMatch
# force item line break in report to have the table below the graphs ;)
add-htmlItemNewRowAfter -item $chart1
# Generate section
$section1 |add-htmlSectionItem -itemList ($chart1, $table)
# Creates a Report
$report = new-htmlReport -title "Rapport sur les services Windows" `
-subtitle "Feature demonstration of the <b>wks_htmlReporting</b> module" `
# Add section to report
$report |add-htmlReportSection -sectionList ($section1)
# Export report to HTML file
$report.toFile($filename)
#& $filename
Les points à noter sont :
- création du tableau avant le graphique (pour récupérer son ID au moment de créer le graphique)
- ajout des paramètres linkedTableId, linkedFieldName, linkedTableExactMatch
- attention la valeur du paramètre linkedFieldName est sensible à la case … javascript oblige !
Bon c’est pas du grafana, c’est c’est cool non !
Conclusion
Voilà pour le usages simple du module wks_htmlReporting.
Je vous donne rendez-vous dans mon prochain article pour les usages un peu plus exotiques 😉