1+ """
2+ Module pour l'analyse statistique d'un fichier log Apache.
3+ """
4+
5+ from collections import Counter
6+ from parse .fichier_log_apache import FichierLogApache
7+
8+
9+ class AnalyseurLogApache :
10+ """
11+ Représente un analysateur pour faire une analyse statistique d'un fichier
12+ log Apache et créer des statistiques à partir de ce dernier.
13+ Attributes:
14+ fichier (FichierLogApache): Le fichier de log Apache à analyser.
15+ nombre_par_top (int): Le nombre maximal d'éléments à inclure dans
16+ les statistiques des classements (tops).
17+ """
18+
19+ def __init__ (self , fichier_log_apache : FichierLogApache , nombre_par_top : int = 3 ):
20+ """
21+ Initialise un nouveau analysateur de fichier log Apache.
22+ Args:
23+ fichier_log_apache (FichierLogApache): Le fichier à analyser.
24+ nombre_par_top (int): Le nombre maximal d'éléments à inclure dans
25+ les statistiques des classements (tops). Par défaut, sa valeur est égale à ``3``.
26+ Raises:
27+ TypeError: Si l'argument ``fichier_log_apache`` n'est pas une instance de :class:`FichierLogApache`
28+ ou si l'argument ``nombre_par_top`` n'est pas un entier.
29+ ValueError: Si l'argument ``nombre_par_top`` est inférieur à ``0``.
30+ """
31+ if not isinstance (fichier_log_apache , FichierLogApache ):
32+ raise TypeError ("La représentation du fichier doit être de type FichierLogApache." )
33+ if not isinstance (nombre_par_top , int ) or isinstance (nombre_par_top , bool ):
34+ raise TypeError ("Le nombre par top doit être un entier." )
35+ if nombre_par_top < 0 :
36+ raise ValueError ("Le nombre par top doit être supérieur ou égale à 0." )
37+ self .fichier = fichier_log_apache
38+ self .nombre_par_top = nombre_par_top
39+
40+ def _get_repartition_elements (self ,
41+ liste_elements : list ,
42+ nom_elements : str ,
43+ mode_top_classement : bool = False ) -> list :
44+ """
45+ Retourne le top 'n' des éléments qui apparaissent le plus dans la liste.
46+ Args:
47+ liste_elements (list): La liste des éléments.
48+ nom_elements (str): Le nom des éléments.
49+ mode_top_classement (bool): Indique si la méthode doit retourner ou non le top
50+ 'n' des éléments les plus présents, où 'n' est égale à l'attribut
51+ :attr:`nombre_par_top`. Par défaut, ce mode est désactivé (valeur à ``False``).
52+ Returns:
53+ list: Une liste de dictionnaires contenant, pour chaque élément :
54+ - Sa valeur.
55+ - Son nombre total d'apparitions.
56+ - Son taux d'apparition dans la liste.
57+ La liste est triée dans l'ordre décroissant selon le nombre d'apparitions.
58+ Si ``mode_top_classement`` est défini à ``True``, elle contient au maximum
59+ :attr:`nombre_par_top` éléments, mais peut en contenir moins s'il y a moins
60+ de :attr:`nombre_par_top` éléments distincts.
61+ """
62+ if not isinstance (liste_elements , list ):
63+ raise TypeError ("La liste des éléments doit être une instance du type list." )
64+ if not isinstance (nom_elements , str ):
65+ raise TypeError ("Le nom des éléments doit être une chaîne de caractères" )
66+ if not isinstance (mode_top_classement , bool ):
67+ raise TypeError ("L'indication de l'activation du mode 'top_classement' doi être un booléen." )
68+
69+ total_elements = len (liste_elements )
70+ compteur_elements = Counter (liste_elements )
71+ top_elements = compteur_elements .most_common (self .nombre_par_top if mode_top_classement else None )
72+ return [
73+ {nom_elements : element , "total" : total , "taux" : total / total_elements * 100 }
74+ for element , total in top_elements
75+ ]
76+
77+ def get_analyse_complete (self ) -> dict :
78+ """
79+ Retourne l'analyse complète du fichier de log Apache.
80+ Returns:
81+ dict: L'analyse sous forme d'un dictionnaire.
82+ Le dictionnaire suit la structure suivante:
83+ - chemin: chemin du fichier
84+ - statistiques:
85+ - requetes:
86+ - top_urls: voir :meth:`get_top_urls`
87+ - repartition_code_statut_http: voir :meth:`get_total_par_code_statut_http`
88+ """
89+ return {
90+ "chemin" : self .fichier .chemin ,
91+ "statistiques" : {
92+ "total_entrees" : self .get_total_entrees (),
93+ "requetes" : {
94+ "top_urls" : self .get_top_urls (),
95+ "repartition_code_statut_http" : self .get_total_par_code_statut_http ()
96+ }
97+ }
98+ }
99+
100+ def get_total_entrees (self ) -> int :
101+ """
102+ Retourne le nombre total d'entrées dans le fichier.
103+ Returns:
104+ int: Le nombre total d'entrées.
105+ """
106+ return len (self .fichier .entrees )
107+
108+ def get_top_urls (self ) -> list :
109+ """
110+ Retourne le top :attr:`nombre_par_top` des urls les plus demandées.
111+ Returns:
112+ list: Une liste de dictionnaires où chaque clé contient :
113+ - url: L'URL demandée.
114+ - total: Le nombre total de fois où cette URL a été demandée.
115+ - taux: Le pourcentage de demandes correspondant à cette URL.
116+ La liste est triée dans l'ordre décroissant du nombre total d'apparitions.
117+ """
118+ return self ._get_repartition_elements (
119+ [entree .requete .url for entree in self .fichier .entrees ],
120+ "url" ,
121+ True
122+ )
123+
124+ def get_total_par_code_statut_http (self ) -> list :
125+ """
126+ Retourne la répartition des réponses par code de statut htpp retourné.
127+ Returns:
128+ list: Une liste de dictionnaires où chaque clé contient :
129+ - code: Le code de statut http.
130+ - total: Le nombre total de fois où ce code a été demandée.
131+ - taux: Le pourcentage de demandes correspondant à ce code.
132+ La liste est triée dans l'ordre décroissant du nombre total d'apparitions.
133+ """
134+ return self ._get_repartition_elements (
135+ [entree .reponse .code_statut_http for entree in self .fichier .entrees ],
136+ "code"
137+ )
0 commit comments