Si tu jettes un oeil dans la config de jeedom on retrouve cette période de lissage qui s’oppose à la durée d’un paquet.
Je pense que cette période de calcul pour min/max/moyenne correspond à la durée utilisée lorsque tu demande à afficher les statistiques dans un widget, cf case du dessus « afficher les statistiques sur les widgets ». ca n’a rien à vois avec le mode de lissage et les paquets d’archivage
Si c’est le cas, ce n’est pas très clair ni dans la config, ni dans la doc
Historique des commandes
- Afficher les statistiques sur les widgets : Permet d’afficher les statistiques sur les widgets. Il faut que le widget soit compatible, ce qui est le cas pour la plupart. Il faut aussi que la commande soit de type numérique.
- Période de calcul pour min, max, moyenne (en heures) : Période de calcul des statistiques (24h par défaut). Il n’est pas possible de mettre moins d’une heure.
- Période de calcul pour la tendance (en heures) : Période de calcul des tendances (2h par défaut). Il n’est pas possible de mettre moins d’une heure.
- Délai avant archivage (en heures) : Indique le délai avant que Jeedom n’archive une donnée (24h par défaut). C’est-à-dire que les données historisées doivent avoir plus de 24h pour être archivées (pour rappel, l’archivage va soit moyenner, soit prendre le maximum ou le minimum de la donnée sur une période qui correspond à la taille des paquets).
- Archiver par paquet de (en heures) : Ce paramètre donne justement la taille des paquets (1h par défaut). Cela signifie par exemple que Jeedom va prendre des périodes de 1h, moyenner et stocker la nouvelle valeur calculée en supprimant les valeurs moyennées.
- Seuil de calcul de tendance basse : Cette valeur indique la valeur à partir de laquelle Jeedom indique que la tendance est à la baisse. Il doit être négatif (par défaut -0.1).
- Seuil de calcul de tendance haut : Même chose pour la hausse.
- Période d’affichage des graphiques par défaut : Période qui est utilisée par défaut lorsque vous voulez afficher l’historique d’une commande. Plus la période est courte, plus Jeedom sera rapide pour afficher le graphique demandé.
Je ne vois pas ce qui n’ets pas clair. Les 3 premiers et les 3 derniers items n’ont rien à voir avec l’archivage. Il est donc inutile d’en tenir compte. Les seuls qui concernent l’archivage et qui ont donc un sens dans ce post sont ceux qui ont archive dans le titre (et qui sont sur la même ligne dans la config) :
- Délai avant archivage (en heures) : Indique le délai avant que Jeedom n’archive une donnée (24h par défaut). C’est-à-dire que les données historisées doivent avoir plus de 24h pour être archivées (pour rappel, l’archivage va soit moyenner, soit prendre le maximum ou le minimum de la donnée sur une période qui correspond à la taille des paquets).
- Archiver par paquet de (en heures) : Ce paramètre donne justement la taille des paquets (1h par défaut). Cela signifie par exemple que Jeedom va prendre des périodes de 1h, moyenner et stocker la nouvelle valeur calculée en supprimant les valeurs moyennées.
Et je ne parle que de ceux là dans mon tuto au niveau config générale
Norbert
Merci pour cet échange. Ca m’a permis de comprendre la subtilité de ce paramètre Période de calcul pour min, max, moyenne (en heures) qui ne concerne pas l’archivage.
Excellent article. Merci
Salut @ngrataloup et merci pour ce partage super intéressant.
Je te propose juste une petite évolution principalement sur la forme. J’ai rajouté l’affichage des paramètres en tête des logs et l’affichage des chiffres avec un séparateur de millier sur ceux qui me semblaient pertinent pour faciliter la lecture.
Cela donne ça par exemple:
[2024-10-30 07:13:18][SCENARIO] ┌──────────── Logs bloc code - version du 31/10/2024 07:00
[2024-10-30 07:13:18][SCENARIO] |
[2024-10-30 07:13:18][SCENARIO] | -------- PARAMETRES
[2024-10-30 07:13:18][SCENARIO] |
[2024-10-30 07:13:18][SCENARIO] | Seuil alerte 24h : 50
[2024-10-30 07:13:18][SCENARIO] | Seuil nb lignes archivées : 50 000
[2024-10-30 07:13:18][SCENARIO] | Seuil taille table : 200 MB
[2024-10-30 07:13:18][SCENARIO] | Seuil nb lignes table : 2 000 000
[2024-10-30 07:13:18][SCENARIO] | Nb de commandes récupérées : 10
[2024-10-30 07:13:18][SCENARIO] |
[2024-10-30 07:13:18][SCENARIO] | -------- TACHE D'ARCHIVAGE
[2024-10-30 07:13:18][SCENARIO] |
[2024-10-30 07:13:18][SCENARIO] | Actif : 1
[2024-10-30 07:13:18][SCENARIO] | Statut : stop
[2024-10-30 07:13:18][SCENARIO] | Last run : 2024-10-30 06:29:50
[2024-10-30 07:13:18][SCENARIO] |
[2024-10-30 07:13:18][SCENARIO] | -------- RESUME
[2024-10-30 07:13:18][SCENARIO] |
[2024-10-30 07:13:18][SCENARIO] | Table historyArch : Taille -> 320MB , nb lignes -> 3 269 563
[2024-10-30 07:13:18][SCENARIO] | /!\ Table Anormalement grosse, taille superieure au seuil (320MB)
[2024-10-30 07:13:18][SCENARIO] | /!\ Table Anormalement grosse, Nb de lignes superieur au seuil (3 269 563 lignes)
[2024-10-30 07:13:18][SCENARIO] | Table event : Taille -> 9MB , nb lignes -> 249
[2024-10-30 07:13:18][SCENARIO] | Table history : Taille -> 6MB , nb lignes -> 35 618
[2024-10-30 07:13:18][SCENARIO] | Table cmd : Taille -> 4MB , nb lignes -> 5 855
[2024-10-30 07:13:18][SCENARIO] | Table jeelink_master : Taille -> 0MB , nb lignes -> 0
Le code modifié si tu veux en tenir compte:
$version = '31/10/2024 07:00' ;
$scenario->setLog('┌──────────── Logs bloc code - version du '.$version);
$scenario->setLog('| ');
$seuilalert24h = 50 ; // Seuil d'alerte pour le nb de ligne générées /24h pour une commande : 50 par defaut
$seuilArch = 50000 ; // Seuil d'alerte pour le nb de ligne archivées pour une commande : 50000 par defaut
$topXCmd = 10 ; // Recupere seulement les X commandes les plus volumineuses : 10 par defaut
$seuilTailleTable = 200 ; // Seuil alerte en MB pour la taille d'une table : 200 MB par defaut
$seuilNbLigneTable = 2000000 ; // Seuil alerte pour le nb de lignes d'une table : 2 000 000 par defaut
$scenario->setLog('| -------- PARAMETRES');
$scenario->setLog('| ');
$scenario->setLog('| Seuil alerte 24h : '.$seuilalert24h);
$scenario->setLog('| Seuil nb lignes archivées : '.number_format($seuilArch,0,',',' '));
$scenario->setLog('| Seuil taille table : '.$seuilTailleTable.' MB');
$scenario->setLog('| Seuil nb lignes table : '.number_format($seuilNbLigneTable,0,',',' '));
$scenario->setLog('| Nb de commandes récupérées : '.$topXCmd);
$scenario->setLog('| ');
// ANALYSE DU CRON D'ARCHIVAGE :
$archCron = cron::byClassAndFunction('history','archive') ;
$scenario->setLog('| -------- TACHE D\'ARCHIVAGE');
$scenario->setLog('| ');
$scenario->setLog('| Actif : '.$archCron->getEnable());
if ( !$archCron->getEnable() ) $scenario->setLog('| /!\ Tache d\'archivage inactive, pensez à l\'activer') ;
$scenario->setLog('| Statut : '.$archCron->getState());
if ( $archCron->getState() == 'error' ) $scenario->setLog('| /!\ Tache d\'archivage en erreur') ;
$scenario->setLog('| Last run : '.$archCron->getLastRun());
$scenario->setLog('| ');
// RESUME
$sql_resume = "SELECT table_name AS `Table`, round(((data_length + index_length) / 1024 / 1024)) as `MB`,table_rows as `Ligne` FROM information_schema.TABLES WHERE table_schema='jeedom' ORDER BY MB DESC LIMIT 5" ;
$results_resume = DB::Prepare($sql_resume, NULL, DB::FETCH_TYPE_ALL);
$scenario->setLog('| -------- RESUME');
$scenario->setLog('| ');
foreach ($results_resume as $result_resume) {
$table = $result_resume['Table'];
$taille = $result_resume['MB'];
$nblign = $result_resume['Ligne'];
$scenario->setLog('| Table '.$table.' : Taille -> '.$taille.'MB , nb lignes -> '.number_format($nblign,0,',',' '));
if ( $taille >= $seuilTailleTable || $nblign >= $seuilNbLigneTable ) $scenario->setLog('| /!\ Table Anormalement grosse, taille superieure au seuil ('.$taille.'MB)') ;
if ( $nblign >= $seuilNbLigneTable ) $scenario->setLog('| /!\ Table Anormalement grosse, Nb de lignes superieur au seuil ('.number_format($nblign,0,',',' ').' lignes)') ;
}
// ANALYSE DES EQUIPEMENT
$scenario->setLog('| ');
$scenario->setLog('| -------- COMMANDES AVEC DONNEES VOLUMINEUSES');
$scenario->setLog('| ');
$sql = 'SELECT arch.cmd_id id, count(arch.value) as countarch FROM historyArch arch GROUP BY arch.cmd_id ORDER BY countarch DESC LIMIT '.$topXCmd;
$results = DB::Prepare($sql, NULL, DB::FETCH_TYPE_ALL);
foreach ($results as $result) {
$id = $result['id'];
$nb_arch = $result['countarch'];
$sql_cmddesc = 'SELECT cmd.id cmd_id, cmd.name cmd, eqLogic.name equipement,object.name objectname, cmd.eqType plugin, count(*) as counthist FROM cmd LEFT JOIN eqLogic ON cmd.eqLogic_id = eqLogic.id LEFT JOIN object ON eqLogic.object_id = object.id LEFT JOIN history ON cmd.id = history.cmd_id WHERE cmd.id = '.$id.' GROUP BY history.cmd_id ';
$results_cmd = DB::Prepare($sql_cmddesc, NULL, DB::FETCH_TYPE_ALL);
// recherche de la premiere date d'historique
$sql_firstHist = 'SELECT datetime FROM historyArch WHERE cmd_id = '.$id.' ORDER BY datetime ASC LIMIT 1' ;
$results_dateHist = DB::Prepare($sql_firstHist, NULL, DB::FETCH_TYPE_ALL);
foreach ($results_dateHist as $result_dateHist) {
$now_date = new DateTime("now");
$diff = time() - strtotime($result_dateHist['datetime']);
$diff_in_day = floor($diff / 86400);
$nb_valeurParJour = round($nb_arch / $diff_in_day);
}
foreach ($results_cmd as $result_cmd) {
$object = $result_cmd['objectname'] ;
$equipement = $result_cmd['equipement'] ;
$cmd = $result_cmd['cmd'] ;
$plugin = $result_cmd['plugin'] ;
$nb_hist = $result_cmd['counthist'] ;
if (date('H') <= 5 ) $timestamp_archivage = mktime(5, 0, 0, date("m") , date("d")-1, date("Y"));
else $timestamp_archivage = mktime(5, 0, 0, date("m") , date("d"), date("Y"));
// recup de la config de la commande
$conf_histo = cmd::byId($id)->getIsHistorized() ;
$conf_histoMode = cmd::byId($id)->getConfiguration('historizeMode') ;
if ( $conf_histoMode == '' || $conf_histoMode == 'none' ) $conf_histoMode = 'aucun' ;
$conf_histopurge = cmd::byId($id)->getConfiguration('historyPurge') ;
if ( $conf_histopurge == '' || $conf_histopurge == 'none' ) $conf_histopurge = 'aucun' ;
$nb_hist24h = round($nb_hist * 86400 / ( time() - $timestamp_archivage)) ;
$scenario->setLog('| '.$plugin.' -> #['. $object .']['.$equipement.']['.$cmd.']# (id : '.$id.')');
if ( $nb_hist24h >= $seuilalert24h && $conf_histoMode == 'aucun' && $conf_histopurge == 'aucun' ) $scenario->setLog('| /!\ PB DE PARAMETRAGE, nb de valeur par 24h important ('. number_format($nb_hist24h,0,',',' ').') et aucun lissage ni aucune purge paramétrés');
if ( $nb_arch >= $seuilArch ) $scenario->setLog('| /!\ PB DE PARAMETRAGE, nb de valeur archivéess trop importantes ('. number_format($nb_arch,0,',',' ').'), superieur à '.number_format($seuilArch,0,',',' '));
$scenario->setLog('| Configuration : historisé -> '.$conf_histo.' , lissage -> '. $conf_histoMode . ' , purge -> '. $conf_histopurge ) ;
$scenario->setLog('| Historique : '.$nb_hist.' valeurs (estimation sur 24h : '.$nb_hist24h.')' );
$scenario->setLog('| Archives : '.$nb_arch.' valeurs depuis '.$diff_in_day.' jours ('.$nb_valeurParJour.' valeurs par jour en moyenne)');
$scenario->setLog('|');
}
}
// ANALYSE DES EQUIPEMENT
$scenario->setLog('| -------- COMMANDES AVEC DONNEES ALPHANUMERIQUES');
$scenario->setLog('| ');
$sql = "SELECT cmd_id id, sum(LENGTH(value)) countarch FROM historyArch WHERE value REGEXP '[a-z;A-Z]' GROUP BY cmd_id ORDER BY countarch DESC LIMIT ".$topXCmd;
$results = DB::Prepare($sql, NULL, DB::FETCH_TYPE_ALL);
foreach ($results as $result) {
$id = $result['id'];
$nb_arch = $result['countarch'];
$sql_cmddesc = 'SELECT cmd.id cmd_id, cmd.name cmd, eqLogic.name equipement,object.name objectname, cmd.eqType plugin, sum(LENGTH(history.value)) as counthist FROM cmd LEFT JOIN eqLogic ON cmd.eqLogic_id = eqLogic.id LEFT JOIN object ON eqLogic.object_id = object.id LEFT JOIN history ON cmd.id = history.cmd_id WHERE cmd.id = '.$id.' GROUP BY history.cmd_id ';
$results_cmd = DB::Prepare($sql_cmddesc, NULL, DB::FETCH_TYPE_ALL);
// recherche de la premiere date d'historique
$sql_firstHist = 'SELECT datetime FROM historyArch WHERE cmd_id = '.$id.' ORDER BY datetime ASC LIMIT 1' ;
$results_dateHist = DB::Prepare($sql_firstHist, NULL, DB::FETCH_TYPE_ALL);
foreach ($results_dateHist as $result_dateHist) {
$now_date = new DateTime("now");
$diff = time() - strtotime($result_dateHist['datetime']);
$diff_in_day = floor($diff / 86400);
$nb_valeurParJour = round($nb_arch / $diff_in_day);
}
foreach ($results_cmd as $result_cmd) {
$object = $result_cmd['objectname'] ;
$equipement = $result_cmd['equipement'] ;
$cmd = $result_cmd['cmd'] ;
$plugin = $result_cmd['plugin'] ;
$nb_hist = $result_cmd['counthist'] ;
if ( $nb_hist == '' ) $nb_hist = 0 ;
if (date('H') <= 5 ) $timestamp_archivage = mktime(5, 0, 0, date("m") , date("d")-1, date("Y"));
else $timestamp_archivage = mktime(5, 0, 0, date("m") , date("d"), date("Y"));
// recup de la config de la commande
$conf_histo = cmd::byId($id)->getIsHistorized() ;
$conf_histoMode = cmd::byId($id)->getConfiguration('historizeMode') ;
if ( $conf_histoMode == '' || $conf_histoMode == 'none' ) $conf_histoMode = 'aucun' ;
$conf_histopurge = cmd::byId($id)->getConfiguration('historyPurge') ;
if ( $conf_histopurge == '' || $conf_histopurge == 'none' ) $conf_histopurge = 'aucun' ;
$nb_hist24h = round($nb_hist * 86400 / ( time() - $timestamp_archivage)) ;
$scenario->setLog('| '.$plugin.' -> #['. $object .']['.$equipement.']['.$cmd.']# (id : '.$id.')');
if ( $nb_hist24h >= $seuilalert24h && $conf_histoMode == 'aucun' && $conf_histopurge == 'aucun' ) $scenario->setLog('| /!\ PB DE PARAMETRAGE, nb de valeur par 24h important ('. number_format($nb_hist24h,0,',',' ').') et aucun lissage ni aucune purge paramétrés');
if ( $nb_arch >= $seuilArch ) $scenario->setLog('| /!\ PB DE PARAMETRAGE, nb de valeur archivéess trop importantes ('. number_format($nb_arch,0,',',' ').'), superieur à '.$seuilArch);
$scenario->setLog('| Configuration : historisé -> '.$conf_histo.' , lissage -> '. $conf_histoMode . ' , purge -> '. $conf_histopurge ) ;
$scenario->setLog('| Historique : '.$nb_hist.' caractères (estimation sur 24h : '.$nb_hist24h.')' );
$scenario->setLog('| Archives : '.$nb_arch.' caractères depuis '.$diff_in_day.' jours ('.$nb_valeurParJour.' caractères par jour en moyenne)');
$scenario->setLog('|');
}
}
$scenario->setLog('└───────────────────────────');
Merci encore pour le partage
Merci, c’est intégré dans le poste initial
Pourquoi ne pas intégrer ces explications dans la doc ? Je pense ça pourrait être utile à beaucoup.
Idem le programme pourrait être intégrer au core comme une fonctionnalité d’analyse
Merci en tout cas
Salut @ngrataloup
J’ai posé ton code dans un bloc code d’un scenario vierge, je l’exécute, mais çà ne me genere pas de log dans la liste des log ? une idée ?
Bonjour.
Il faut lire le log du scénario où il est exécuté.
Justement je ne le trouve pas !
Je devrais me retrouver avec un log test-archivage dans la liste des logs non ?
Bonjour,
Non : le log d’un scénario est accessible depuis la page du scénario.
Il y a un bouton en haut à droite (coupé sur ta 1ère capture). Sinon raccourci CTRL+L.
Ne pas hésiter à se référer à la documentation.
J’étais persuader que l’ensemble des fichiers de log apparaissait visible dans la partie log.
Je n’ai pas penser à aller voir dans le petit bouton log du scenario en lui même !
Merci pour l’astuce, et en effet çà fonctionne
Merci beaucoup pour ce tuto.
Question: est il possible de configurer un temps particulier sur lequel est effectué le calcul (min, max ou moy) pour une commande ? En fait j’aimerais pouvoir faire une moyenne sur une journée pour certaines commandes et à 1h pour d’autres.
Merci
Je ne croîs pas que ce soit personnalisable par commande. Cette temporalité est lié à la notion de « archiver par paquet de » dans les paramétrages généraux.
Par contre, rien ne t’empêche de faire un virtuel qui récupère le max, le min ou la moyenne sur la journée pour certaines commandes, 1 seule valeur sur la journée, donc quelque soit la valeur de « archiver par paquet de », tu conservera ta valeur sur la journée
ça marche, merci
cyril
Bonjour,
une petite réponse pour un grand MERCI.
merci à @ngrataloup pour :
-le script d’origine qui remonte les problèmes.
-le moyen de refaire un archivage pour les valeurs déjà archivées (Voir ce thread).
-plus globalement le partage d’informations
merci aux autres contributeurs aussi !
Je suis sur pi3b+ (sur carte SD) et sans avoir de soucis particulier, j’essaye maintenant de rester attentif à l’utilisation des ressources pour éviter d’avoir à changer de matériel / réinstaller.
Grace à ce scénario et, aux actions qui vont bien, j’ai :
Diviser par 14 le nombre de lignes dans la table historyarch :
Je suis passé de 9.5 Millions de lignes à 700 000 lignes
Avant :
-------- RESUME
Table historyArch : Taille → 434MB , nb lignes → 9 552 040
/!\ Table Anormalement grosse, taille superieure au seuil (434MB)
/!\ Table Anormalement grosse, Nb de lignes superieur au seuil (9 552 040 lignes)
Après :
-------- RESUME
Table historyArch : Taille → 33MB , nb lignes → 694 892
Le ressenti global n’est pas une franche amélioration (même si certaines page s’affichent plus rapidement) mais j’ai :
-Réduis mon temps de sauvegarde
-Réduis de 40% la taille de la sauvegarde : passé de 130Mo à 85 Mo
(oui c’est pas beaucoup, je sais…)
-Surtout beaucoup appris sur l’archivage des données
(j’avoue la perte d’historique en début d’année 2025 sur les vieilles versions m’a forcé à mieux comprendre cet archivage. voir ce thread Janvier 2025 perte historique anciennes versions
(au passage j’ai regardé et découvert la page santé et fait des ajustements, swapiness par exemple)
Bonne journée !
Tu n’avais pas non plus une base énorme. J’ai vu passé des base à plus de 2Go …
Par contre, une petite mise à jour de Jeedom s’impose … 4.2.21, on en voit plus beaucoup, idem pour debian 10
NOrbert