licence-server/logger/README.md
Nenad Djukic 3480766c3e Prijemnik dijagnostike sa TERMINIA uredjaja (logger/)
- UDP prijemnik (podrazumevano 46465, NE 46464 gde uredjaji slusaju discovery):
  dnevnik rada sa zaglavljem #TERMINIA, heartbeat JSON, sve ostalo se odbacuje
- paket bez zaglavlja (FW < 0.13.4) se vodi kao "nepoznat uredjaj" po izvornoj
  IP adresi i tako je i oznacen u prikazu
- dnevnik u fajlove po uredjaju i danu, rotacija po velicini + tri kvote
  (starost, po uredjaju, ukupno); otvoren fajl se nikad ne brise
- heartbeat u memoriji; interval se meri iz razmaka javljanja, "tih" = 3x interval
- web stranica (podrazumevano 127.0.0.1:8081): spisak uredjaja, crveno za tihe,
  poslednjih N linija sa pretragom, /dnevnik.txt i /api/uredjaji
- bez baze i bez spoljnih zavisnosti; ne dira licencni servis, njegovu bazu,
  rute ni nginx
- sanitizacija svega iz paketa (duzine, kontrolni znaci, ime foldera) — bez
  izlaska iz foldera dnevnika
- systemd unit + primer env fajla + README sa uputstvom za pustanje na server
- testovi: parsiranje (zaglavlje/JSON/bez zaglavlja/smece), registar, rotacija
  i kvote, web rute

Nije pusteno na server — puštanje radi vlasnik po logger/README.md.
2026-07-25 17:40:27 +02:00

153 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Prijemnik dijagnostike sa TERMINIA uređaja
Mali samostalan servis: sluša UDP pakete koje terminal šalje (dnevnik rada i
heartbeat), piše ih u fajlove po uređaju i po danu, i prikazuje na jednoj
web stranici.
- **Nema bazu**, nema spoljnih Go zavisnosti (samo standardna biblioteka).
- **Ne dira licencni servis** — zaseban proces, zaseban port, zaseban
systemd unit. Deli samo Go modul (isti repo).
- Ugovor o formatu paketa: ASP repo, `docs/24-servisni-kanal.md`.
## Šta prima
| Vrsta | Kako se prepoznaje | Šta radi sa njim |
|---|---|---|
| Dnevnik rada (dbg) | čist tekst; prvi red `#TERMINIA <naziv> <MAC> <fw>` | linije se upisuju u fajl uređaja |
| Heartbeat | paket počinje sa `{` (JSON sa `"hb":1`) | pamti se u memoriji (naziv, MAC, IP, FW, vreme) |
| Sve ostalo | — | tiho se odbacuje, brojač „odbačeno" na stranici |
**Zaglavlje dnevnika postoji tek od FW 0.13.4.** Stariji uređaj šalje goli
tekst — takav se vodi kao **nepoznat uređaj**, razvrstava po izvornoj IP
adresi i tako je i **označen na stranici** (ne pravimo se da znamo ko je).
Prijemnik **ne odgovara** na pakete. Prijem naloga na uređaju nije
implementiran i traži potpis (docs/24 §3.2), pa slanja naloga ovde nema.
## Web stranica
| Ruta | Šta daje |
|---|---|
| `/` | spisak uređaja: naziv, MAC, IP, FW, „poslednji put pre X"; **crveno** = nije se javio duže od 3× svog intervala |
| `/uredjaj?k=<ključ>&q=<pretraga>&n=<broj>` | poslednjih N linija dnevnika, sa pretragom po tekstu |
| `/dnevnik.txt?k=<ključ>&n=&q=` | isto, kao čist tekst (za `curl`) |
| `/api/uredjaji` | JSON spisak uređaja (za alate) |
Interval javljanja se **meri** iz razmaka između dva heartbeat-a; dok ga nema,
koristi se `LOGGER_HB_DEFAULT_SEC`.
## Pokretanje lokalno
```powershell
cd D:\Terminia\TERMINIA-SOFTWARE\licence-server
go build -o terminia-logger.exe .\logger\cmd\terminia-logger
$env:LOGGER_UDP_PORT="46465"
$env:LOGGER_HTTP_PORT="8081"
$env:LOGGER_DIR="D:\Terminia\TERMINIA-SOFTWARE\licence-server\data\logger"
.\terminia-logger.exe
```
Zatim otvoriti `http://127.0.0.1:8081`.
Proba bez uređaja (PowerShell, u drugom prozoru):
```powershell
$u=New-Object System.Net.Sockets.UdpClient; $u.Connect("127.0.0.1",46465)
function Send($s){ $b=[System.Text.Encoding]::UTF8.GetBytes($s); [void]$u.Send($b,$b.Length) }
Send '{"app":"TERMINIA","name":"TERM-001","mac":"1C:DB:D4:A6:A4:60","ip":"192.168.0.20","fw":"0.13.4","hb":1}'
Send "#TERMINIA TERM-001 1C:DB:D4:A6:A4:60 0.13.4`n[stampac] javio se na 192.168.123.100`n"
$u.Close()
```
Testovi:
```powershell
go test ./logger/...
```
## Env promenljive
| Promenljiva | Podrazumevano | Značenje |
|---|---|---|
| `LOGGER_UDP_PORT` | `46465` | port na koji uređaji šalju. **Ne 46464** — tamo uređaji slušaju discovery |
| `LOGGER_UDP_HOST` | (prazno) | adresa za slušanje; prazno = sve |
| `LOGGER_HTTP_HOST` | `127.0.0.1` | web sluša samo lokalno jer dnevnik sadrži **brojeve karata** |
| `LOGGER_HTTP_PORT` | `8081` | port web pregleda |
| `LOGGER_TOKEN` | (prazno) | ako je postavljen, web traži `?t=<token>` (obavezno ako web nije samo lokalni) |
| `LOGGER_DIR` | `./data/logger` | folder sa dnevnicima |
| `LOGGER_KEEP_DAYS` | `14` | koliko dana se dnevnici čuvaju |
| `LOGGER_MAX_FILE_MB` | `10` | preko toga se dnevni fajl rotira (`.log.001`, `.002`…) |
| `LOGGER_MAX_DEVICE_MB` | `50` | kvota po uređaju; preko toga se briše najstarije |
| `LOGGER_MAX_TOTAL_MB` | `1024` | ukupna kvota za sve uređaje |
| `LOGGER_MAX_DEVICES` | `500` | koliko uređaja se drži u memoriji |
| `LOGGER_HB_DEFAULT_SEC` | `60` | pretpostavljeni interval dok se ne izmeri |
Neispravna vrednost = servis se **ne pokreće** i kaže koja promenljiva ne valja
(bolje nego da tiho radi sa pogrešnim podešavanjem).
## Šta se upisuje u uređaj
U SPA uređaja: **Podešavanja → Servis**
| Polje | Vrednost |
|---|---|
| `svcLogHost` | `157.180.119.151:46465` |
| „Šalji dnevnik rada na server" | **uključeno** |
| heartbeat (`svcHbSeconds`) | npr. `60` |
Uređaj šalje **samo brojčani IP:port** — domen se ne može upisati (docs/24 §1).
> ⚠️ Ovo ide preko interneta **u čistom tekstu**, a u dnevniku ima brojeva
> karata. Za trajno praćenje flote predviđen je HTTPS kanal (docs/24 §3);
> ovaj prijemnik je za dijagnostiku dok se problem lovi.
## Puštanje na server (radi vlasnik)
```bash
# 1) build na serveru
cd /root/projects/licence-server
git pull
go build -o terminia-logger ./logger/cmd/terminia-logger
# 2) podešavanja
cp logger/deploy/terminia-logger.env.example logger.env
$EDITOR logger.env
# 3) systemd
cp logger/deploy/terminia-logger.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now terminia-logger
systemctl status terminia-logger
journalctl -u terminia-logger -f
# 4) firewall — SAMO taj port, UDP
ufw allow 46465/udp
# 5) provera sa strane (ne sme da vrati odgovor, samo da ne pukne)
echo '#TERMINIA PROBA AA:BB:CC:DD:EE:FF 0.13.4
proba veze' | nc -u -w1 157.180.119.151 46465
# 6) pregled (web je vezan za 127.0.0.1) — SSH tunel sa svog racunara:
ssh -L 8081:127.0.0.1:8081 root@157.180.119.151
# pa u pregledacu: http://127.0.0.1:8081
```
Ako web treba da bude dostupan bez tunela: postaviti `LOGGER_TOKEN`, staviti
nginx ispred sa TLS-om i lozinkom, i tek onda promeniti `LOGGER_HTTP_HOST`.
**Ne otvarati port 8081 direktno na internet.**
Šta ovaj servis **ne dira**: bazu `licence_db`, proces `licence-server`, nginx
konfiguraciju, portove 8090/8091/8092.
## Granice i odbrane
- Paket može poslati bilo ko: sve iz paketa je ograničeno po dužini, kontrolni
znaci se izbacuju, a ime foldera se pravi isključivo od belih znakova
(`[A-Za-z0-9_-]`) — sadržaj paketa ne može da odluči gde se piše.
- Broj uređaja u memoriji je ograničen; kad se granica dostigne, izbacuje se
onaj koji se najduže nije javio.
- Dnevnici se brišu po tri pravila redom: starost → kvota po uređaju → ukupna
kvota. Fajl koji je trenutno otvoren za pisanje se nikad ne briše.
- Greška pri upisu ne obara prijem — vidi se kao brojač „greške upisa".