TL;DR: Caut o soluție lightweight pentru agregarea logs.
Practic, vreau ca ce apare în error.log pe mai multe site-uri/servere să fie trimis pe instanța mea de [insert-solution-here]. Dacă știe să prindă și erorile js din browser, cu atât mai bine
În momentul de față, pe site-urile clienților, folosesc:
datadog
new relic
sentry
Primele două sunt scumpe[1], iar pentru ce le folosim… sunt nejustificat de scumpe, mai ales că le folosim doar pentru agregarea logs
Sentry e abia descoperit, încă explorez ce poate și ce nu.
Prin urmare, caut ceva lejer[2], să pot pune pe un VPS modest, în așa fel încât să prind erorile ocazionale.
Sugestii?
nu au fost alese de mine, doar am aterizat pe proiect cu ele acolo. ↩︎
Graylog e destul de nice. Nu mai stiu acum cum e, dar in trecut, singura chestie mai meh era daca voiai sa faci ceva agregari de loguri mai complexe. Dar in rest, merge brici.
Am folosit majoritar logstash/kibana (ELK stack), dar nu sunt light.
In rest Splunk m-a impresionat cel mai mult, e atat de avansat incat trebuie sa inveti sa il folosesti, dar nu e ce cauti
Probabil poți să implementezi singur din câteva linii de python/php/whatever. Deschizi error.log, duci cursorul la sfarsit si astepti cu inotify sa apara modificari in fisier, Cand apare o notificare de modificare, citesti pana la EOF intr-un buffer si trimiti buffer-ul printr-o metoda oarecare (http, de ce nu) la vps-ul tau “agregator”. Mai ieftin si mai light nu exista
EDIT: După un pic de muncă de lămurire cu ChatGPT 4, mi-a dat si un scriptuleț care afișează liniile nou apărute în log, care cu requests ar putea fi trimise prin http unde avem noi chef să le colectăm.
import os
import sys
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class FileChangeHandler(FileSystemEventHandler):
def __init__(self, target_file):
self.target_file = target_file
self.last_position = self.get_initial_file_size()
def get_initial_file_size(self):
"""Obține dimensiunea fișierului în momentul inițial."""
return os.path.getsize(self.target_file)
def read_new_content(self):
with open(self.target_file, 'r') as file:
file.seek(self.last_position)
new_content = file.read()
self.last_position = file.tell()
return new_content
def on_modified(self, event):
if event.src_path == self.target_file:
new_content = self.read_new_content()
if new_content:
print(f"Modificări noi în {self.target_file}:")
print(new_content)
if __name__ == "__main__":
path = "./error.log"
event_handler = FileChangeHandler(path)
observer = Observer()
observer.schedule(event_handler, path=path, recursive=False)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
Probabil, după ce am “discutat” cu ChatGPT legate de chestia cu log-urile mi-a venit ideea sa-i dau un task pe care îl tot amânam de lene, să blochez din firewall autentificările eșuate în postfix. Și după ce i-am zis lui ChatGPT că pe Centos 8 nu există python-watchdog a venit o soluție atât de simplă încât nici nu mi-e trecut prin cap s-o iau în considerare, ceva de genul:
#!/bin/bash
IPSET_NAME="block-spam"
LOG_FILE="/var/log/maillog"
tail -F $LOG_FILE | while read LINE; do
if echo "$LINE" | grep -q "authentication failed"; then
# Extragerea adresei IP
IP=$(echo $LINE | sed -n 's/.*\[\(.*\)\].*/\1/p')
if [ ! -z "$IP" ]; then
echo "Blocking IP: $IP"
# Adăugarea adresei IP la ipset
ipset add $IPSET_NAME $IP 2>/dev/null
fi
fi
done
Sentry este gandit sa te ajute in privinta exceptiilor: se ocupa de agregare (dupa diverse criterii) si prezentare (este foarte util pentru prioritizare, cel putin in cazul meu).
Daca ai resursele necesare sa il folosesti si pentru WARN si/sau INFO, nu te opreste nimeni, dar nu pentru asta a fost gandit.
O solutie la nivel de code (gen Sentry) unde tu apelezi o functie de la un 3rd party, prin care trimiti un log specific catre platforma respectiva. Asta as vedea-o mai simplu, ca solutie.
O solutia automatizata (dar care ar fi mult mai complicat de configurat/gestionat decat solutia manuala de mai sus) in care log-urile in sunt captate la nivel de proces/filesystem si sunt trimise in alta parte. Aici s-ar incadra solutiile din cateogria Logstash. Dar treaba devine complicata in functia de natura aplicatiilor/serverelor. Sunt in in PHP sau Node.js? Sunt pornite cu pm2 sau cu Docker? Deployment-ul e in AWS sau on-premise? … Si lista poate continua aproape la nesfarsit. Pentru fiecare caz in parte, ai bataie de cap, prin urmare, aici o sa te complici destul de tare.
Recomand solutia 1.
Side Note: Sentry suporta si browser console errors.
–
Ar fi mai fi si opiunea 3, (dar nu cred ca e cazul la tine) in care toate aplicatiile sunt Laravel, spre ex, si sunt hostate intr-o solutie ca Forge. Atunci o solutie de genul asta, tinand cont ca e standardizata/nisata, cred ca ar putea sa suporte acest feature.
Datadog nu este tool-ul potrivit pentru afisare de erori, se foloseste pt monitoring si observability, gen “am x erori / ora” → raise alarm cand se depaseste un prag.
Pentru afisare si cautare in logs este necesara indexarea in ceva gen elasticsearch. Acum depinde de volum si pt ce perioada vrei sa le pastrezi, pt volume mici probabil poti folosi si alte solutii.
Am folosit graylog prima dată prin 2014, și mi s-a părut mind blowing.
Apoi am descoperit ELK, unde m-am îndrăgostit iremediabil de Kibana.
M-am jucat puțin cu Sentry și am fost plăcut impresionat.
Am folosit Datadog și NewRelic într-un context corporate unde partea de buget nu era o problemă.
Trăgând linie, aș alege mereu Kibana și Sentry, fix în ordinea asta. Nu sunt neapărat lightweight, în sensul că necesită niște resurse și în funcție de volume, se adună niște costuri de cloud computing.
Dar pentru mine, Kibana face tot ce trebuie.
PS: am testat și Loki cu Grafana, nu ne-am înțeles bine deloc.