# Nedávno navštívené

V "*Nedávno navštívené*" umožňuje vidět historii prokliků.

[![historie.png](https://doc.eainfoport.cz/uploads/images/gallery/2022-05/scaled-1680-/historie.png)](https://doc.eainfoport.cz/uploads/images/gallery/2022-05/historie.png)

V tabulce vidíme:

- *Datum*
- *Čas*
- *Diagram/element/package/atribute/operace - řádek lze prokliknout na artefakt*
- *GUID*

[![historie1.png](https://doc.eainfoport.cz/uploads/images/gallery/2022-05/scaled-1680-/S4zhistorie1.png)](https://doc.eainfoport.cz/uploads/images/gallery/2022-05/S4zhistorie1.png)

## Statistika návštěv - přímé čtení z databáze (pro administrátory)

Každé úspěšné otevření detailu (diagram, element, balíček, atribut, operace, kořenový balíček modelu) se zapisuje do tabulky `infoport."VisitedDetails"` v databázi Infoportu. Tato tabulka je zdrojem funkce "Nedávno navštívené". Pro administrátora nemá aplikace žádnou obrazovku ani statistiky nad touto tabulkou, data lze číst pouze přímo SQL dotazem do databáze.

### Struktura tabulky infoport."VisitedDetails"

<table border="1" id="bkmrk-sloupec-v%C3%BDznam-id-pr" style="border-collapse: collapse; width: 100%;"><thead><tr><th>Sloupec</th><th>Význam</th></tr></thead><tbody><tr><td>ID</td><td>Primární klíč (autoinkrement).</td></tr><tr><td>UserId</td><td>Odkaz na AspNetUsers.Id. Při smazání uživatele se smažou i jeho záznamy.</td></tr><tr><td>RepositoryId</td><td>Odkaz na Repositories.Id.</td></tr><tr><td>Guid</td><td>EA GUID zobrazené položky (ea\_guid).</td></tr><tr><td>DetailKind</td><td>Typ položky: 1 = diagram, 2 = element, 3 = balíček, 4 = atribut, 5 = operace, 10 = model (kořenový balíček).</td></tr><tr><td>VisitTimestamp</td><td>Čas serveru (místní čas serveru, nikoli UTC).</td></tr></tbody></table>

Indexy jsou pouze na sloupcích UserId a RepositoryId, na VisitTimestamp žádný index není.

### Kdy záznam vzniká

- Jeden řádek vzniká při každém úspěšném otevření detailu.
- Nic se neslučuje: obnovení stránky, vynucené obnovení nebo opakované otevření vytvoří další řádek.
- Při přístupu přes veřejný klíč se návštěva zapíše pod uživatele, kterému klíč patří.
- Nezapisuje se odmítnutý přístup (403/404), procházení stromu, vyhledávání, IP adresa ani session.

### Retence - důležité pro statistiky

Noční úloha údržby maže záznamy starší než hodnota CleanAfterXDays. Výchozí hodnota je 30 dní a nastavuje se v Configuration Manageru. Úloha běží ve výchozím plánu v 01:00 a spustí se i při startu aplikace. Pro dlouhodobé statistiky je proto nutné tuto hodnotu zvýšit, nebo data každý den archivovat (např. do agregační tabulky).

### Příklady dotazů (PostgreSQL)

```
-- aktivita uživatelů
select u."UserName", count(*) as zobrazeni, count(distinct v."Guid") as unikatni,
       count(distinct v."VisitTimestamp"::date) as aktivni_dny, max(v."VisitTimestamp") as posledni
from infoport."VisitedDetails" v
join infoport."AspNetUsers" u on u."Id" = v."UserId"
group by u."UserName"
order by zobrazeni desc;

-- nejnavštěvovanější položky
select "RepositoryId", "DetailKind", "Guid", count(*) as n, count(distinct "UserId") as uzivatelu
from infoport."VisitedDetails"
group by 1, 2, 3
order by n desc
limit 50;

-- denní průběh
select date_trunc('day', "VisitTimestamp") as den, count(*) as zobrazeni, count(distinct "UserId") as uzivatelu
from infoport."VisitedDetails"
group by 1
order by 1;

-- hodinový průběh
select extract(hour from "VisitTimestamp") as h, count(*) as zobrazeni
from infoport."VisitedDetails"
group by 1
order by 1;

-- poměr typů položek
select "DetailKind", count(*) as zobrazeni
from infoport."VisitedDetails"
group by 1
order by 1;

-- "sezení": mezera delší než 30 minut = nové sezení
select t.*, sum(novy) over (partition by "UserId" order by "VisitTimestamp") as sezeni
from (
  select v.*, case when "VisitTimestamp" - lag("VisitTimestamp") over w > interval '30 min'
                     or lag("VisitTimestamp") over w is null then 1 else 0 end as novy
  from infoport."VisitedDetails" v
  window w as (partition by "UserId" order by "VisitTimestamp")
) t;
```

Pomocí funkce lag("Guid") lze sledovat i přechody z položky na položku, tedy jak uživatelé procházejí model.

### Omezení

- Chybí názvy položek. Tabulka obsahuje jen GUID. Název a typ je nutné dohledat v databázi Enterprise Architect příslušného repozitáře (t\_object, t\_diagram, t\_package, t\_attribute, t\_operation podle ea\_guid). Jde o jinou databázi, proto je nutné propojení (dblink/FDW) nebo export.
- Smazané položky v EA nedohledáte. Aplikace je v historii uživatele tiše vynechává.
- Opakovaná otevření nafukují počty, proto rozlišujte count(\*) a count(distinct ...).
- Návštěvy přes veřejný klíč nelze odlišit od běžných návštěv vlastníka klíče.
- Pomalé dotazy u velkých dat: chybí index na VisitTimestamp. Vyplatil by se index (UserId, VisitTimestamp).

### Další zdroj dat - Insights log

Pokud potřebujete záznam všech HTTP požadavků (nejen otevření detailu), zapněte v Configuration Manageru (App Logs) volbu Insights a nastavte Log Type na Debug. Každý požadavek se zapíše do souboru insights.log ve složce logů (LogPath) ve tvaru: \[doba\] \[stavový kód\] \[uživatel nebo no user\] \[adresa včetně dotazu a těla požadavku, u přihlášení bez hesla\]. Soubor se rotuje podle nastavení RollingInterval. Upozornění: Debug zapisuje obsah požadavků, používejte jej jen dočasně a v interním prostředí.