Lisatud bin kaust näidistega
This commit is contained in:
		
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | *.pyc | ||||||
|  | raport/top.svg | ||||||
|  | raport/raport*.html | ||||||
|  | raport/bar.svg | ||||||
|  | raport/bar.png | ||||||
							
								
								
									
										79
									
								
								bin/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								bin/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | |||||||
|  | # Skriptide kasutamine | ||||||
|  |  | ||||||
|  | Allolevates näidetes on programmid käivitatud nii et | ||||||
|  | kaust milles skript paikneb on lisatud ```PATH``` keskkonnamuutujasse: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | PATH=/tee/kaustani/logide-parsimine/bin:$PATH | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Näiteks kodukataloogis bin kausta puhul: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | PATH=~/bin:$PATH | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Skripti käisitsi alla laadimisel ja kausta paigutamisel tuleb anda ka käivitamise õigsed, näiteks: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | chmod +x ~/bin/top2 | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Selleks et PATH muutujasse automaatselt näiteks ~/bin kaust lisataks võib ```~/.bashrc``` faili lisada ```PATH=~/bin/:$PATH```. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # top2 | ||||||
|  |  | ||||||
|  | Bashis kirjutatud skript mis parsib standardsisendist ning kuvab tulemused standardväljundisse | ||||||
|  |  | ||||||
|  | Käivitamiseks: | ||||||
|  |  | ||||||
|  | (cat access.log; zcat access.log.1.gz) | top2 | ||||||
|  |  | ||||||
|  | # top4 | ||||||
|  |  | ||||||
|  | Pythonis kirjutatud skript mis leiab enim külastatud URL-id. | ||||||
|  |  | ||||||
|  | Käivitamiseks: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | cat access.log  | top4 | head | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | # top5 | ||||||
|  |  | ||||||
|  | Leiab top 5 enim külastatud URL-i, päringuid teinud IP aadressi ning enim kasutatud veebilehitsejat. | ||||||
|  |  | ||||||
|  | Käivitamiseks, nii et veateated kirjutatakse ```errors``` faili | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | cat access.log  | top4 2>errors | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | # filter2 | ||||||
|  |  | ||||||
|  | Python programm kaustast Apache logisid otsimiseks ning nende seest | ||||||
|  | alguse kuupäeva/kellaaja ning ajavahemiku järgi logikirjete otsimiseks. | ||||||
|  |  | ||||||
|  | Käsk võtab kolm argumenti: | ||||||
|  |  | ||||||
|  | * tee logide kaustani | ||||||
|  | * otsitava ajavahemiku alguse kuupäev/kellaaeg, kujul "YYYY-MM-DD HH:MM:SS" | ||||||
|  | * ajavahemik minutites | ||||||
|  |  | ||||||
|  | Käivitamiseks: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | filter2 /tee/logide/kaustani "2015-12-12 18:25:10" 10 | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Käsurea analoog teatavate mööndustega on järgnev: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | grep -E '12/Dec/2015:18:(2[5-9]|3[0-5])' -r /tee/logide/kaustani | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Pythoni variandi põhilised erisused: | ||||||
|  |  | ||||||
|  | * Jooksvalt pakib lahti .gz lõpulised failid | ||||||
|  | * Jätab vahele failid mille sees otsitavat ajavahemikku kindlasti ei ole | ||||||
							
								
								
									
										61
									
								
								bin/filter2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										61
									
								
								bin/filter2
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | #!/usr/bin/python | ||||||
|  | # encoding: utf-8 | ||||||
|  | import os | ||||||
|  | import re | ||||||
|  | import gzip | ||||||
|  | import sys | ||||||
|  | from datetime import datetime, timedelta | ||||||
|  |  | ||||||
|  | try: | ||||||
|  |     dir_logs = sys.argv[1] | ||||||
|  | except IndexError: | ||||||
|  |     dir_logs = "/var/log" | ||||||
|  |  | ||||||
|  | try: | ||||||
|  |     scope_begin = datetime.strptime(sys.argv[2], "%Y-%m-%d %H:%M:%S") | ||||||
|  | except IndexError: | ||||||
|  |     scope_begin = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) | ||||||
|  |  | ||||||
|  | try: | ||||||
|  |     duration = int(sys.argv[3]) | ||||||
|  | except IndexError: | ||||||
|  |     duration = 5 | ||||||
|  |  | ||||||
|  | scope_end = scope_begin + timedelta(minutes=duration) | ||||||
|  | sys.stderr.write("Otsin logikirjeid vahemikus %s kuni %s kaustast %s\n" % (scope_begin, scope_end, dir_logs)) | ||||||
|  |  | ||||||
|  | RE_LOG_ENTRY = "(?P<remote_addr>.+?) - (?P<username>.+?) \[(?P<timestamp>.+?)\] \"(?P<verb>[A-Z]+) (?P<path>.+) HTTP/1.[01]\" (?P<status>\d+) (?P<size>\d+) \"(?P<referrer>.+?)\" \"(?P<agent>.+?)\"" | ||||||
|  |  | ||||||
|  | # os.walk käib rekursiivselt kataloogipuu läbi | ||||||
|  | for root, dirs, files in os.walk(dir_logs): | ||||||
|  |     # iga kausta kohta (root) on kättesaadav alamkataloogide nimekiri (dirs) | ||||||
|  |     # ning failide nimekiri (files) | ||||||
|  |     for filename in files: | ||||||
|  |         if filename.startswith("access.log"): | ||||||
|  |             path = os.path.join(root, filename) | ||||||
|  |             file_end = datetime.fromtimestamp( | ||||||
|  |                 os.stat(path).st_mtime) | ||||||
|  |             if scope_begin > file_end: | ||||||
|  |                 sys.stderr.write("Jätan vahele %s faili kuna logifaili lõpp oli %s\n" % | ||||||
|  |                     (path, file_end)) | ||||||
|  |                 continue | ||||||
|  |  | ||||||
|  |             file_start = None | ||||||
|  |             with gzip.open(path) if path.endswith(".gz") else open(path) as fh: | ||||||
|  |                 for line in fh: | ||||||
|  |                     m = re.match(RE_LOG_ENTRY, line) | ||||||
|  |                     if not m: | ||||||
|  |                         continue | ||||||
|  |                     dt = datetime.strptime(m.group("timestamp")[:-6], "%d/%b/%Y:%H:%M:%S") | ||||||
|  |                     if not file_start: # loeme esimest rida sellest failist | ||||||
|  |                         file_start = dt | ||||||
|  |                         if scope_end < file_start: | ||||||
|  |                             sys.stderr.write("Jätan vahele %s faili kuna logifaili algus oli %s\n" % (path, file_start)) | ||||||
|  |                             # Hüppa ridade lugemise tsükklist välja, järgmise faili juurde | ||||||
|  |                             break | ||||||
|  |                         else: | ||||||
|  |                             sys.stderr.write("Otsin logikirjeid failist %s\n" % path) | ||||||
|  |                     if dt > scope_end: | ||||||
|  |                         break | ||||||
|  |                     if dt > scope_begin: | ||||||
|  |                         print line.strip() | ||||||
							
								
								
									
										11
									
								
								bin/top2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								bin/top2
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | # Käivitamiseks: cat access.log | python top | ||||||
|  | echo "Enim külastatud URL-id:" | ||||||
|  | cat \ | ||||||
|  |  | awk -F \" '{ print $2}' \ | ||||||
|  |  | cut -d ' ' -f 2- \ | ||||||
|  |  | sort \ | ||||||
|  |  | uniq -c \ | ||||||
|  |  | sort -n -r \ | ||||||
|  |  | head | ||||||
							
								
								
									
										68
									
								
								bin/top4
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										68
									
								
								bin/top4
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | #!/usr/bin/python | ||||||
|  | # encoding: utf-8 | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | Skript: | ||||||
|  |  | ||||||
|  |   PATH=path/to/bin:$PATH | ||||||
|  |   cat access.log | top4 | head | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | # Loo tühi dict tüüpi objekt, siia korjame kokku URL -> mitu korda külastati vastendused | ||||||
|  | hits = {} | ||||||
|  |  | ||||||
|  | try: | ||||||
|  |     import sys | ||||||
|  |     filename = sys.argv[1] | ||||||
|  |     if filename.endswith(".gz"): | ||||||
|  |         import gzip | ||||||
|  |         stream = gzip.open(filename) | ||||||
|  |     else: | ||||||
|  |         stream = open(filename) | ||||||
|  | except IndexError: | ||||||
|  |     stream = sys.stdin | ||||||
|  |     sys.stderr.write("Loen standardsisendist...\n") | ||||||
|  |  | ||||||
|  | # Käi ridahaaval fail läbi | ||||||
|  | for line in stream: | ||||||
|  |  | ||||||
|  |     # Kui rea sees ei esine sõnet GET siis jäta vahele | ||||||
|  |     if "GET" not in line: | ||||||
|  |         # Hüppa järgmise tsükli algusse | ||||||
|  |         continue | ||||||
|  |  | ||||||
|  |     # Rea sees oli GET, nüüd võime proovida lõpikuda rida tühikute järgi massiiviks | ||||||
|  |     fields = line.split() | ||||||
|  |  | ||||||
|  |     # Massiivi indeksid algavad nullist, seitsmenda tulba indeks on 6 | ||||||
|  |     path = fields[6] | ||||||
|  |  | ||||||
|  |     # Kontrollime kas URL on juba võtmena kasutuses dict objektis | ||||||
|  |     if path in hits: | ||||||
|  |         # Kui on siis lisame ühe juurde | ||||||
|  |         hits[path] = hits[path] + 1 | ||||||
|  |     else: | ||||||
|  |         # Kui ei ole siis määra väärtuseks 1 | ||||||
|  |         hits[path] = 1 | ||||||
|  |  | ||||||
|  | # Kuna dict tüüpi objekti ei saa sorteerida tuleb ta kõigepealt viia sorteeritavale kujule | ||||||
|  | # nagu nt list: | ||||||
|  | hits = hits.items() | ||||||
|  |  | ||||||
|  | # Nüüd hits on massiiv kahestest massiividest (path, count) | ||||||
|  | # Sellise asja sorteerimiseks saab kasutada list objekti funktsiooni sort | ||||||
|  | # Sorteerimisel on vaja ette anda ka funktsioon mis nopib välja asja mille järgi sorteerida | ||||||
|  | # See on siin argument nimega key, millele on väärtuseks antud | ||||||
|  | # nimetu (anonüümne, lambda) funktsioon mis massiivi iga elemendi (path, count) | ||||||
|  | # kohta tagastab count negatiivse väärtuse | ||||||
|  | hits.sort(key=lambda (path,count):-count) | ||||||
|  |  | ||||||
|  | # Massiiv on nüüd sorteeritud, esimese 10 vaste kuvamiseks saame massiviist võtta alammassiivi [:10] | ||||||
|  | # Süntaks [algus:lõpp] kehtib samamoodi nii massiividel (list, tuple) kui ka sõnedel | ||||||
|  | # Kui algus jäetakse vahele asendatakse see algusega | ||||||
|  | # Kui lõpp jäetakse vahele asendatakse see lõpuga | ||||||
|  | # Indeksid võivad negatiivsed olla | ||||||
|  | for path, count in hits: | ||||||
|  |     print "% 9d %s" % (count, path) | ||||||
|  |  | ||||||
							
								
								
									
										51
									
								
								bin/top5
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										51
									
								
								bin/top5
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | #!/usr/bin/python | ||||||
|  | # encoding: utf-8 | ||||||
|  |  | ||||||
|  | import argparse | ||||||
|  | import re | ||||||
|  | from datetime import datetime, timedelta | ||||||
|  | import sys | ||||||
|  | from collections import Counter | ||||||
|  |  | ||||||
|  | hits = Counter() # IP-d kust tuldi | ||||||
|  | urls = Counter() # URL-id mida külastati | ||||||
|  | agents = Counter() # User agent mida kasutati külastamisel | ||||||
|  |  | ||||||
|  | RE_LOG_ENTRY = "(?P<remote_addr>.+?) - (?P<username>.+?) \[(?P<timestamp>.+?) \+\d\d\d\d\] \"(?P<verb>[A-Z]+) (?P<path>.+) HTTP/1.[01]\" (?P<status>\d+) (?P<size>\d+) \"(?P<referrer>.+?)\" \"(?P<agent>.+?)\"" | ||||||
|  |  | ||||||
|  | for line in sys.stdin: | ||||||
|  |     m = re.match(RE_LOG_ENTRY, line) | ||||||
|  |     if not m: | ||||||
|  |         sys.stderr.write("Ei suutnud parsida rida: %s" % line) | ||||||
|  |         continue | ||||||
|  |  | ||||||
|  |     # Ignoreeri localhostist ja sisevõrgust pärinevaid päringuid (a'la nagios) | ||||||
|  |     if m.group("remote_addr").startswith("127.") or m.group("remote_addr").startswith("192.168."): | ||||||
|  |         continue | ||||||
|  |  | ||||||
|  |     # Jäta vahele OPTIONS päringud | ||||||
|  |     if m.group("verb") not in ("GET", "POST"): | ||||||
|  |         continue | ||||||
|  |  | ||||||
|  |     # Jäta vahele botid ja otsingumootorid | ||||||
|  |     if re.search("(crawler|spider|Nuhk|Googlebot|yahoo|yandex)", m.group("agent")): | ||||||
|  |         continue | ||||||
|  |  | ||||||
|  |     dt = datetime.strptime(m.group("timestamp"), "%d/%b/%Y:%H:%M:%S") | ||||||
|  |     hits[m.group("remote_addr")] += 1 | ||||||
|  |     urls[m.group("path")] += 1 | ||||||
|  |     agents[m.group("agent")] += 1 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | print "Top 5 enim külastatud URL-i veebiserveris:" | ||||||
|  | for path, count in urls.most_common(5): | ||||||
|  |     sys.stdout.write("% 9d %s\n" % (count, path)) | ||||||
|  | print | ||||||
|  | print "Top 5 enim külastusi teinud IP aadressid:" | ||||||
|  | for remote_addr, count in hits.most_common(5): | ||||||
|  |     sys.stdout.write("% 9d %s\n" % (count, remote_addr)) | ||||||
|  | print | ||||||
|  | print "Top 5 enim kasutatud veebilehitsejad/OS-id:" | ||||||
|  | for user_agent, count in agents.most_common(5): | ||||||
|  |     sys.stdout.write("% 9d %s\n" % (count, user_agent)) | ||||||
|  |  | ||||||
| @@ -1,7 +1,42 @@ | |||||||
| # Apache logide parsija | # Apache logide parsija | ||||||
|  |  | ||||||
| Komplektne näide kuidas Apache2 logisid parsida ning raporteerida huvitavamad killud: | Failis ```main.py``` on näide kuidas Apache2 logisid parsida ning raporteerida huvitavamad killud: | ||||||
|  |  | ||||||
| * Parsib Apache logifaili kirjed ApacheLogParser klassi abil mis on kirjeldatud failis log_parsers.py | * Parsib Apache logifaili kirjed ApacheLogParser klassi abil mis on kirjeldatud failis log_parsers.py | ||||||
| * Värvib kaardi faili BlankMap-World6.svg ning salvestab top.svg faili sisse | * Laadib ```requests``` mooduli abil alla BlankMap-World6.svg, värvib selle ära ```lxml``` mooduli abil ning salvestab top.svg faili sisse | ||||||
| * Genereerib Bootstrap baasil koostatud veebilehe mallist template.html faili raport.html | * Genereerib Bootstrap baasil koostatud veebilehe mallist template.html faili raport.html | ||||||
|  |  | ||||||
|  | Sõltuvuste paigladamiseks: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | apt install -y python-jinja2 python-lxml python-pygal python-geoip python-numpy python-matplotlib | ||||||
|  | dnf install -y python-jinja2 python-lxml python-pygal python2-GeoIP python2-numpy python2-matplotlib | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Käivitamiseks | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | (cat /path/to/access.log; zcat /path/to/access.log.1.gz) | python main.py | ||||||
|  | (cat /path/to/access.log; zcat /path/to/access.log.[12].gz) | python main.py | ||||||
|  | (cat /path/to/access.log; zcat /path/to/access.log.[1-5].gz) | python main.py | ||||||
|  | (cat /path/to/access.log; zcat /path/to/access.log.*.gz) | python main.py | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | # Java rakenduste stack trace'de kokku korjaja | ||||||
|  |  | ||||||
|  | Failis ```main2.py``` on näide kuidas Java rakenduse logikirjetest stack trace'd kokku koguda: | ||||||
|  |  | ||||||
|  | * Ühisosa Apache logide parsijaga on ```GenericParser``` klass milles sisaldub üldine logide parsimise loogika | ||||||
|  |  | ||||||
|  | Sõltuvuste paigladamiseks: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | apt install -y python-jinja2 | ||||||
|  | dnf install -y python-jinja2 | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Käivitamiseks: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | cat blah.log | python main2.py > raport2.html | ||||||
|  | ``` | ||||||
|   | |||||||
| @@ -15,37 +15,53 @@ class GenericParser(object): | |||||||
|         line_count = 0 |         line_count = 0 | ||||||
|         event_count = 0 |         event_count = 0 | ||||||
|         for line in self.fh: |         for line in self.fh: | ||||||
|             byte_count += len(line) # loenda baite |             # Loenda logikirjete arv ja maht | ||||||
|  |             byte_count += len(line) | ||||||
|             line_count += 1 |             line_count += 1 | ||||||
|  |  | ||||||
|             if not line.strip(): # jäta vahele tühjad read |             # Normaliseeri reavahetused | ||||||
|  |             line = line.replace("\r\n", "\n") | ||||||
|  |  | ||||||
|  |             # Jäta vahele tühjad read | ||||||
|  |             if not line.strip(): | ||||||
|                 continue |                 continue | ||||||
|  |  | ||||||
|  |             # Püüa regulaaravaldise järgi rida tükkideks võtta | ||||||
|             m = re.match(self.RE_LOG_ENTRY, line) |             m = re.match(self.RE_LOG_ENTRY, line) | ||||||
|  |  | ||||||
|  |             # Kui rida klappis regexiga | ||||||
|             if m: |             if m: | ||||||
|  |                 # Väljasta eelmine kokku kleebitud logikirje | ||||||
|                 if log_entry: |                 if log_entry: | ||||||
|                     if self.errors_only and not self.is_serious(log_entry): |                     # Kui vaja filtreerida, välista logikirjed mis ei ole veateatega seotud | ||||||
|                         continue |                     if not self.errors_only or self.is_serious(log_entry): | ||||||
|                     stack_trace = "\n".join(multiline_message.split("\n")[1:]) |  | ||||||
|                         event_count += 1 |                         event_count += 1 | ||||||
|                     row = \ |  | ||||||
|                         datetime.strptime(log_entry.get("timestamp"), self.TIMESTAMP_FORMAT), \ |                         # yield teeb funktsioonist generaatori/iteraatori | ||||||
|                         log_entry, stack_trace, byte_count, line_count, event_count |                         # https://pythontips.com/2013/09/29/the-python-yield-keyword-explained/ | ||||||
|                     # See teeb funktsioonist generaatori/iteraatori |                         yield datetime.strptime(log_entry.get("timestamp"), self.TIMESTAMP_FORMAT), \ | ||||||
|                     yield row |                             log_entry, multiline_message, byte_count, line_count, event_count | ||||||
|                 multiline_message = line |  | ||||||
|  |  | ||||||
|  |                 # Alusta järgmise sõnumi kokku kleepimist | ||||||
|  |                 multiline_message = m.group("message") | ||||||
|                 log_entry = m.groupdict() |                 log_entry = m.groupdict() | ||||||
|             else: |  | ||||||
|  |             elif line.startswith("\t") or line.startswith("Caused by") or line.startswith("org."): | ||||||
|                 multiline_message += line |                 multiline_message += line | ||||||
|  |  | ||||||
|  |             else: | ||||||
|  |                 sys.stderr.write("Ei suutnud parsida rida:" + line) | ||||||
|  |  | ||||||
| class JavaLogParser(GenericParser): | class JavaLogParser(GenericParser): | ||||||
|     TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S.%f" |     TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S.%f" | ||||||
|     RE_LOG_ENTRY = "(?P<timestamp>.+?) (?P<severity>[A-Z]+) 1 --- \[(?P<thread>.+)\](?P<class>.+) +: (?P<message>.+)" |     RE_LOG_ENTRY = "(?P<timestamp>.+?) +(?P<severity>[A-Z]+) 1 --- \[(?P<thread>.+)\](?P<class>.+?) *: (?P<message>.+)" | ||||||
|  |  | ||||||
|     def is_serious(self, log_entry): |     def is_serious(self, log_entry): | ||||||
|         return log_entry.get("severity") == "ERROR" |         return log_entry.get("severity") == "ERROR" | ||||||
|  |  | ||||||
| class ApacheLogParser(GenericParser): | class ApacheLogParser(GenericParser): | ||||||
|     RE_LOG_ENTRY = "(?P<remote_addr>.+?) - (?P<username>.+?) \[(?P<timestamp>.+?) \+\d\d\d\d\] \"(?P<verb>[A-Z]+) (?P<path>.+) HTTP/1.[01]\" (?P<status>\d+) (?P<size>\d+) \"(?P<referrer>.+?)\" \"(?P<user_agent>.+?)\"" |     RE_LOG_ENTRY = "(?P<remote_addr>.+?) - (?P<username>.+?) \[(?P<timestamp>.+?) \+\d\d\d\d\] \"(?P<message>(?P<verb>[A-Z]+) (?P<path>.+) HTTP/1.[01])\" (?P<status>\d+) (?P<size>\d+) \"(?P<referrer>.+?)\" \"(?P<user_agent>.+?)\"" | ||||||
|     TIMESTAMP_FORMAT = "%d/%b/%Y:%H:%M:%S" |     TIMESTAMP_FORMAT = "%d/%b/%Y:%H:%M:%S" | ||||||
|  |  | ||||||
|     def is_serious(self, log_entry): |     def is_serious(self, log_entry): | ||||||
|   | |||||||
| @@ -1,21 +1,6 @@ | |||||||
| #!/usr/bin/python | #!/usr/bin/python | ||||||
| # encoding: utf-8 | # encoding: utf-8 | ||||||
|  |  | ||||||
| """ |  | ||||||
| Sõltuvuste paigladamiseks: |  | ||||||
|  |  | ||||||
|   apt install -y python-jinja2 python-lxml python-pygal python-geoip python-numpy python-matplotlib |  | ||||||
|   dnf install -y python-jinja2 python-lxml python-pygal python2-GeoIP python2-numpy python2-matplotlib |  | ||||||
|  |  | ||||||
| Käivitamiseks |  | ||||||
|  |  | ||||||
|   (cat /path/to/access.log; zcat /path/to/access.log.1.gz) | python main.py |  | ||||||
|   (cat /path/to/access.log; zcat /path/to/access.log.[12].gz) | python main.py |  | ||||||
|   (cat /path/to/access.log; zcat /path/to/access.log.[1-5].gz) | python main.py |  | ||||||
|   (cat /path/to/access.log; zcat /path/to/access.log.*.gz) | python main.py |  | ||||||
|  |  | ||||||
| """ |  | ||||||
|  |  | ||||||
| import GeoIP | import GeoIP | ||||||
| import re | import re | ||||||
| import sys | import sys | ||||||
| @@ -42,6 +27,7 @@ for timestamp, log_entry, stack_trace, byte_count, line_count, event_count in Ap | |||||||
|     if int(log_entry.get("status")) < 400: # 2xx ja 3xx arvestamiseks |     if int(log_entry.get("status")) < 400: # 2xx ja 3xx arvestamiseks | ||||||
|         hits_per_path[log_entry.get("path")] += 1 |         hits_per_path[log_entry.get("path")] += 1 | ||||||
|     hits_per_remote_addr[log_entry.get("remote_addr")] += 1 |     hits_per_remote_addr[log_entry.get("remote_addr")] += 1 | ||||||
|  |     if "bot" not in log_entry.get("user_agent").lower(): | ||||||
|         hits_per_user_agent[log_entry.get("user_agent")] += 1 |         hits_per_user_agent[log_entry.get("user_agent")] += 1 | ||||||
|     hits_per_country[country_code] += 1 |     hits_per_country[country_code] += 1 | ||||||
|     hits_per_date[timestamp.date()] += 1 |     hits_per_date[timestamp.date()] += 1 | ||||||
| @@ -64,13 +50,26 @@ buf = requests.get("https://upload.wikimedia.org/wikipedia/commons/0/03/BlankMap | |||||||
|  |  | ||||||
| # Parsi XML puu | # Parsi XML puu | ||||||
| map_document = etree.fromstring(buf) | map_document = etree.fromstring(buf) | ||||||
|  |  | ||||||
|  | # Iga riigikoodi ja sellest riigist pärit päringute arvu kohta | ||||||
| for country, count in hits_per_country.items(): | for country, count in hits_per_country.items(): | ||||||
|     if not country: |     if not country: | ||||||
|         # Mõni IP ei pruukinud laheneda riigikoodiks (sisevõrk jms) |         # Mõni IP ei pruukinud laheneda riigikoodiks (sisevõrk jms) | ||||||
|         continue |         continue | ||||||
|  |  | ||||||
|  |     # Interpoleeri päringute arv vahemikust 0 ... maksimaalsete päringutega riik | ||||||
|  |     # vahemikku 180 (sinakas toon) ... 0 (punane) | ||||||
|  |     # võrdväärne rida: hue = 180 - 180 * count / max(hits_per_country.values()) | ||||||
|     hue = interp(count, [0, max(hits_per_country.values())], [180, 0]) |     hue = interp(count, [0, max(hits_per_country.values())], [180, 0]) | ||||||
|  |  | ||||||
|  |     # Nopi rekursiivselt dokumendist välja kõik elemendid mille 'id' attribuut on riigikoodiga | ||||||
|  |     # Kaardis vastab sellele küll ainult üks <g> ehk grupi element | ||||||
|     for element in map_document.xpath("//*[@id='%s']" % country.lower()): |     for element in map_document.xpath("//*[@id='%s']" % country.lower()): | ||||||
|  |         # Lisa CSS-i stiili attribuut <g> elemendile taustavärvi muutmiseks | ||||||
|         element.set("style", "fill:hsl(%.2f, 60%%, 60%%)" % hue) |         element.set("style", "fill:hsl(%.2f, 60%%, 60%%)" % hue) | ||||||
|  |  | ||||||
|  |         # Polügonid mis on grupi sees, neilt eemalda attribuut 'class' mille | ||||||
|  |         # abil pannakse vaikimisi hall värv külge | ||||||
|         for subelement in element: |         for subelement in element: | ||||||
|             subelement.attrib.pop("class", "") |             subelement.attrib.pop("class", "") | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								raport/main2.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								raport/main2.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | #!/usr/bin/python | ||||||
|  | # encoding: utf-8 | ||||||
|  |  | ||||||
|  | import GeoIP | ||||||
|  | import re | ||||||
|  | import sys | ||||||
|  | from collections import Counter | ||||||
|  | from log_parsers import JavaLogParser | ||||||
|  |  | ||||||
|  | sys.stderr.write("Loen standardsisendist...\n") | ||||||
|  | errors = Counter() | ||||||
|  | for timestamp, log_entry, stack_trace, byte_count, line_count, event_count in JavaLogParser(sys.stdin, errors_only=True): | ||||||
|  |     errors[stack_trace] += 1 | ||||||
|  |  | ||||||
|  | from jinja2 import Template | ||||||
|  | import codecs | ||||||
|  |  | ||||||
|  | HTML_TEMPLATE = u"""<!DOCTYPE> | ||||||
|  | <html> | ||||||
|  |   <head> | ||||||
|  |     <title>Apache logide raport</title> | ||||||
|  |     <meta charset="utf-8"/> | ||||||
|  |     <link href="https://getbootstrap.com/docs/4.1/dist/css/bootstrap.min.css" rel="stylesheet"/> | ||||||
|  |     <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" crossorigin="anonymous"></script> | ||||||
|  |     <script src="https://getbootstrap.com/docs/4.1/dist/js/bootstrap.min.js"></script> | ||||||
|  |   </head> | ||||||
|  |   <body> | ||||||
|  |       <div class="container"> | ||||||
|  |         {% for stack_trace, count in errors.items() %} | ||||||
|  |           <div class="row mt-3"> | ||||||
|  |             <div class="md-12"> | ||||||
|  |               {{ count }} korda esinenud viga | ||||||
|  |               <button class="btn btn-primary" type="button" data-toggle="collapse" | ||||||
|  |                 data-target="#stack-{{ loop.index }}">Stack trace</button> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |           <div class="row"> | ||||||
|  |             <div class="md-12"> | ||||||
|  |               <div id="stack-{{ loop.index }}" class="collapse"> | ||||||
|  |                 <pre>{{ stack_trace }}</pre> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |         {% endfor %} | ||||||
|  |       </div> | ||||||
|  |   </body> | ||||||
|  | </html> | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | template = Template(HTML_TEMPLATE) | ||||||
|  | print template.render(locals()) | ||||||
		Reference in New Issue
	
	Block a user