Lisatud bin kaust näidistega
This commit is contained in:
parent
ae9c681c6d
commit
4c1b365b06
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())
|
Loading…
Reference in New Issue
Block a user