IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

Comment effectuer une moyenne ?


Sujet :

Langage Perl

  1. #21
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Hum, reprenons. Tu as une mesure toutes les cinq minutes, soit 12 fois par heure, ou 288 fois par jour ou 2304 sur une période de 8 jours. Cela représente un volume de données tout à fait raisonnable (je travaille quotidiennement sur des dizaines de millions de lignes et très régulièrement sur 20 à 50 fois plus).

    Ensuite, je ne sais plus très bien si tu veux une moyenne quotidienne ou une moyenne tous les huit jours, ou une moyenne quotidienne glissante sur huit jours, ou encore autre chose. Il faut bien clarifier le besoin. Et faire en sorte qu'il soit facile de changer changer ces paramètres si par exemple tu t'aperçois à l'usage que la période d'observation est trop longue (pas assez réactif) ou trop courte (moyenne assez erratique, pas assez lissée).

    Dans tous les cas, tu as besoin d'un script qui ajoute une mesure à ton fichier toutes les cinq minutes. A priori il peut se contenter d'ajouter en mode append, sans rien faire de plus.

    Ensuite, quand tu relis ton fichier pour faire une moyenne (une fois pas jour ou tous les huit jours ?), rien n'empêche de lire l'ensemble du fichier dans un tableau, de faire ta moyenne, de purger le tableau des éléments obsolètes dont tu n'auras plus besoin, et de réécrire le tableau ainsi élagué dans ton fichier à la place des anciennes données. Vu le volume des données, lire les données, calculer la moyenne et réécrire les données ne prendra qu'une fraction de seconde. Et ce n'est vraiment pas compliqué à mettre en place. Il n'y a aucune difficulté à mes yeux et je suis bien sûr prêt à t'aider si tu butes sur un obstacle.

    Il faut sans doute aussi prévoir un autre fichier pour stocker l'historique des moyennes (pour pouvoir faire tes graphiques).

    Pour l'instant, réfléchis bien à ton besoin exact et explicite-le. Précise en particulier la fréquence des moyennes et la taille de la fenêtre glissante.

    Bonne soirée.

  2. #22
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Vu la taille des données qui est relativement faible, n'y a-t-il pas un intérêt à travailler avec un sérialiseur de donnée (style Data::Dumper) :
    - pour enregistrer une nouvelle donnée toutes les 5mn, le script lit les données sérialisée (un tableau des valeurs par exemple), ajoute la nouvelle valeur à la fin du tableau (push) et supprime la première si le tableau dépasse la limite des valeurs pour la moyenne glissante (disons si le tableau dépasse 8*24*12 si on prend une moyenne glissante sur 8 jours), puis écrit le tableau sérialisé dans le script
    - pour calculer la moyenne glissante, il suffit alors de lire les données sérialisées et de diviser la somme des valeurs du tableau par sa taille (soit sum(@valeurs)/@valeurs)

    Pour lire et écrire des données à sérialiser avec Data::Dumper::Simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    use Data::Dumper::Simple;
     
    our @valeurs;
    my $fichier_valeurs = "valeurs.txt";
     
    # lire les données
    my $return = do "$fichier_valeurs";
    warn "Couldn't parse $fichier_valeurs: $@" if $@;
    warn "Couldn't do $fichier_valeurs: $!" unless defined $return;
     
    # traiter la nouvelle donnée (contenue par exemple dans $ARGV[0])
    push @valeurs, $ARGV[0];
    # réduire la taille du tableau au nombre de valeurs nécessaire à la moyenne glissante (disons que ce paramètre soit passé dans $ARGV[1])
    shift @valeurs while @valeurs > $ARGV[1];
     
    # écrire les données
    open my $DATA, ">", $fichier_valeurs or die "Can't open $fichier_valeurs for writing: $!";
    print { $DATA } Dumper(@valeurs);
    (je n'ai pas testé ce bout de code)
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  3. #23
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    135
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2014
    Messages : 135
    Points : 70
    Points
    70
    Par défaut
    Merci pour vos réponses !

    J'ai testé d'implémenter ton bout de code Philou, mais il me semble que je ne dispose pas de Data:umper::Simple (Can't locate Data/Dumper/Simple.pm in @INC) et je n'ai pas l'autorisation d'installer de nouveau paquet :/

    Concernant l'objectif de mon script pour clarifier la situation :
    Via mon script, je récupère une valeur toutes les 5', valeurs qui sont stocké dans un fichier (valeurs.txt).
    J'ai pour objectif d'effectuer une moyenne de ces valeurs. La moyenne doit se basé sur 8 jours, soit 2304 valeurs renseigné dans le fichier valeurs.txt.
    Par contre, je ne dois effectuer cette moyenne qu'au bout de ces 8 jours, pas avant. Tant que le tableau ne comporte pas 2304 valeurs l'a moyenne ne doit pas être faite.
    C'est pour cela que je dois mettre en place un système de purge de fichier/tableau doit-être mis en place au bout de ces 8 jours de délais.


    J'ai pour le moment lié mes valeurs de mon fichier dans un tableau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    open LIRE, 'valeurs.txt' || die "Erreur d'ouverture du fichier";
    while (<LIRE>){
    push @tab,$_
    }
     
    print "$_" foreach @tab;
    Je pense que la solution purge du fichier/tableau correspond plus à mes attendes.
    Par contre je ne sais pas comment fixé la longueur/taille de mon tableau à 2304 valeur pour ensuite le purger.

    J'ai essayé de le définir à un taille de 2304, mais cela ne fonctionne pas :/
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my @tab; 
    $tab[2304] =0;

    Merci encore de prendre de votre temps pour m'aider !

  4. #24
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par musha76 Voir le message
    Merci pour vos réponses !

    J'ai testé d'implémenter ton bout de code Philou, mais il me semble que je ne dispose pas de Data:umper::Simple (Can't locate Data/Dumper/Simple.pm in @INC) et je n'ai pas l'autorisation d'installer de nouveau paquet :/
    Dans ce cas, utilise simplement Data:: Dumper, il est forcément installé. Il faudra juste ajuster un peu la syntaxe.

    Citation Envoyé par musha76 Voir le message
    Concernant l'objectif de mon script pour clarifier la situation :
    Via mon script, je récupère une valeur toutes les 5', valeurs qui sont stocké dans un fichier (valeurs.txt).
    J'ai pour objectif d'effectuer une moyenne de ces valeurs. La moyenne doit se basé sur 8 jours, soit 2304 valeurs renseigné dans le fichier valeurs.txt.
    Par contre, je ne dois effectuer cette moyenne qu'au bout de ces 8 jours, pas avant. Tant que le tableau ne comporte pas 2304 valeurs l'a moyenne ne doit pas être faite.
    C'est pour cela que je dois mettre en place un système de purge de fichier/tableau doit-être mis en place au bout de ces 8 jours de délais.
    Donc, tu n'as pas besoin d'une moyenne glissante, mais juste d'une moyenne simple effectuée tous les huit jours. Du coup, quand tu fais une moyenne tu n'as pas besoin de garder quoi que ce soit dans le fichier. Le mécanisme de purge devient complètement élémentaire: recréer le fichier à vide.

    Voici sous le debugger un exemple dans lequel j'alimente un tableau avec 10 valeurs aléatoires puis fais une moyenne des 5 dernières:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
      DB<1>  @tableau = map { rand 20 } 1..10;  # alimentation de 10 valeurs aléatoires (juste pour avoir un exemple de tableau)
     
      DB<2> x \@tableau;  # affichage des 10 valeurs
    0  ARRAY(0x600500e48)
       0  17.1322857370433
       1  18.137516846827
       2  5.71155099274868
       3  19.2040321109188
       4  15.8002992000016
       5  7.89347585727199
       6  12.2725420193154
       7  14.3821294986462
       8  10.2155117921649
       9  2.41959472770304
      DB<3>  $sum += $_ for @tableau[$#tableau - 4 .. $#tableau];  # somme des 5 dernières valeurs
     
      DB<4> p $sum;
    47.1832538951016
      DB<5> $moyenne = $sum / 5; # calcul de la moyenne des 5 dernières valeurs
     
      DB<6> p $moyenne;  
    9.43665077902031
    Dans la pratique, il n'est pas garanti que tu aies exactement 2304 valeurs, car le traitement ne sera peut-être pas lancé exactement toujours à la même heure. D'autant plus que j'imagine que tu dis "8 jours" mais veux sans doute dire une semaine (donc, en fait, 7 jours). Il faudra donc ajuster quelques détails. Si tu comptes sur 12 * 24 * 7 valeurs, prendre toutes les valeurs présentes si le nombre présent est inférieur à cette valeur, et n'en prendre que ce nombre voulu s'il y en a un peu plus. Mais ce sont des détails que tu peux résoudre ensuite.

    Aussi, voici un moyen de lire directement ton fichier dans un tableau:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    my $fic = "fichier.txt";
    open my $fh, "<", $fic or die "Ouverture impossible de $fic en lecture !$";
    my @tableau = <$fic>;      # lit directement le contenu de $fic dans un tableau;
    close $fic;
    chomp @tableau; # suppression des retours à la ligne dans le tableau;
     
    # maintenant, calcul de la moyenne.
    # ...
     
    # recréation du fichier à vide:
    open my $fh, ">", $fic or die "Ouverture impossible de $fic en écriture !$";
    close $fh;

  5. #25
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    135
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2014
    Messages : 135
    Points : 70
    Points
    70
    Par défaut
    J'ai essayé les bouts de code mais tout n'a pas fonctionné :

    Pour l'instant je suis rendu à ouvrir le fichier et pousser une nouvelle valeur à la fin du tableau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    111 my $fic = "fichier.txt";
    112
    113 open my $fh, ">>", $fic or die "Erreur d'ouverture du fichier $fic en ajout";
    114 printf ($fh "$pue_hz\n" );
    115 close ($fh);
    116
    117 open $fh, "<", $fic or die "Erreur d'ouverture en écriture $fic";
    118 while (<$fh>){
    119 push @tab,$_
    120 }
    Je débute la programmation donc je ne sais pas réellement comment faire mais je sais formuler mon idée.


    En faite, ce qui me pose problème quand ce script c'est comment ajouter 2304 puis faire un moyenne de ces 2304 dans le même script, sachant qu'il sera lancé toutes les 5 minutes
    Voici ce que je veux faire, mais je ne sais pas si je peux raisonner comme cela :

    Tant que i<2304
    alors
    On ajoute une nouvelle valeur dans le fichier
    sinon
    On fait la moyenne (valeurs/2304)
    On efface le contenu du fichier

    Je vais me pencher sur cette boucle en attendant votre réponse

  6. #26
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    135
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2014
    Messages : 135
    Points : 70
    Points
    70
    Par défaut
    Finalement, je trouve le script trop compliqué à concevoir...

    Je pense avoir trouver une autres méthodes beaucoup plus simple.

    Dans un premier temps, lancer le script me permettant de récupérer les valeurs dans un fichier via cron.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #On ouvre le fichier et on ajoute une valeur au fichier
    open my $fh, ">>", $fic or die "Erreur d'ouverture du fichier $fic en ajout";
    printf ($fh "$pue_hz\n" );
    close ($fh);
    Dans un second temps, lancer le plugin nagios toutes les 691 000sec, soit 8 jours me permettant de lire le fichier contenant les valeurs, faire la moyenne des valeurs et purger le fichier contenant mes valeurs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    my $fic = "valeur_pue_hz.txt";
     
    #On effectue la moyenne
    my $sum =0;
    my $score =0;
     
    open my $fh, '<', $fic or die "Erreur d'ouverture du fichier $fic";
    while (my $line = <$fh>){
            $sum += $line;
            $score++;
    }
    my $moy = $sum / 5;
    $moy = sprintf ("%0.2f", $moy);
     
    #Code retour pour Centreon
    $code_retour = $plugin_nagios->check_threshold(
            check => $moy,
            warning => $plugin_nagios->opts->warning,
            critical => $plugin_nagios->opts->critical,
    );
     
    if ($code_retour =~ m/error/)
    {$code_retour = OK};
    $plugin_nagios->nagios_exit ($code_retour, "$moy $UNIT |$UNIT=$moy\n");
     
     
    #On purge le fichier
    open $fh, ">", $fic or die "Ouverture impossible de $fic en écriture !";
    close $fh;
    Je pense que c'est une meilleure solution par contre je rencontre 2 problèmes :
    le script ne se lance pas avec cron donc il faut que je regarde
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    */5 * * * * perl /application/app/nagios/libexec/valeur_pue_hz.pl
    Et mon autre problème c'est que lorsque le plugin nagios se lance, il effectue bien la moyenne mais ne purge pas le fichier. Comme si le script n'allait pas jusqu'au bout

  7. #27
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Je ne connais pas Nagios, mais il faut a priori faire la purge avant l'appel de:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $plugin_nagios->nagios_exit ...

  8. #28
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    135
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2014
    Messages : 135
    Points : 70
    Points
    70
    Par défaut
    Ce qui est embêtant, puis de suis obligé d'envoyé l'information à Nagios avant de purger le fichier

    Il y a-t-il un autre moyen pour purger automatiquement un fichier ?

  9. #29
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Encore une fois, je ne connais absolument pas Nagios, ni les plugins que l'on peut faire avec, ni le module Perl pour ces plugins, mais je suppose que l'appel de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $plugin_nagios->nagios_exit ...
    entraîne la fin de l'exécution du script. Dans ce cas, il n'y a aucune chance d'atteindre du code se trouvant plus loin.

    Il faudrait donc trouver moyen d'informer Nagios des valeurs trouvées sans faire de exit. De façon à pouvoir recréer le fichier à vide avant de sortir.

    L'autre possibilité, c'est de garder un fichier au moins deux fois plus gros que les valeurs sur lesquelles tu calcules ta moyenne et ne purger que les enregistrements très anciens. Par exemple, en supposant pour simplifier que tu aies besoin de 3000 lignes pour ta moyenne, tu gardes toujours les 9000 dernières lignes du fichier et n'efface que les lignes encore plus anciennes.

    Ou sinon, mettre le script Perl dans un lanceur en shell (ksh, bash ou autre). Au moment de l'exit, je suppose que le programme Perl s'arrête et rend la main au script shell qui peut alors recréer à vide le fichier. Du reste, ce sera peut-être plus facile de lancer un bash qu'un Perl depuis cron.

    Le script shell peut-être très simple, un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #!/usr/bin/bash
     
    perl script_perl.pl
     
    echo "" > ficher_stat.txt
    En ajoutant peut-être un test sur la valeur de retour du script Perl, s'il en renvoie une exploitable après un nagios_exit.

    PS: tu t'en es sans doute aperçu, mais je signale tout de même que tu as un bug dans ton code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    my $moy = $sum / 5;
    Il ne faut pas diviser par 5, mais par le nombre de valeurs.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Comment créer une somme dans un état?
    Par ivan rung dans le forum Access
    Réponses: 6
    Dernier message: 20/01/2006, 07h56
  2. [C#][ MSI] Comment effectuer une mise à jour d'application ?
    Par th3r1ddl3r dans le forum Windows Forms
    Réponses: 6
    Dernier message: 15/12/2005, 10h09
  3. Réponses: 4
    Dernier message: 19/10/2005, 09h20
  4. Réponses: 6
    Dernier message: 24/03/2005, 14h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo