BK cloud / systemen Notities
NL
English ENDeutsch DEEspañol ES中文 ZHFrançais FRPortuguês (Brasil) PT-BR日本語 JAहिन्दी HINederlands NL
Laten we kennismaken ↗
← Terug naar praktijknotities

Een statische site met een hartslag: privacyvriendelijke bezoekersanalyse op AWS

Een statische website is heerlijk rustig. Er is geen applicatieserver die op patches wacht, geen databaseverbindingspool die uitgeput kan raken en geen openbare API die dag en nacht wakker moet blijven. Een browser vraagt bestanden op; een content delivery network levert ze.

Die eenvoud riep voor dit portfolio een interessante vraag op: kon ik laten zien waar de site wordt gelezen en hoe het verkeer in de loop van de tijd verandert, zonder er een dynamische applicatie van te maken of informatie te publiceren die privé moet blijven?

Het antwoord werd een kleine datapijplijn met CloudFront-toegangslogboeken, CloudWatch, Lambda, EventBridge en één JSON-object in S3. Bezoekers zien een wereldkaart, landtotalen, populaire pagina’s en grafieken van aanvraagfrequenties. Ze krijgen nooit ruwe logboeken, IP-adressen, user-agents of individuele surfgeschiedenissen.

De website blijft statisch. De gegevens worden elders voorbereid en komen aan als gewoon nog een statisch bestand.

De architectuur in één requestpad

Het openbare aanvraagpad blijft bewust kort:

  1. Een bezoeker vraagt de site op via Amazon CloudFront.
  2. CloudFront levert gecachete bestanden met een S3-bucket als privé-origin.
  3. De browser haalt later content/public-visitors.json zoals elk ander statisch bestand.
  4. JavaScript in de browser tekent de kaart en grafieken op basis van dat anonieme document.

De browser roept Lambda niet aan. Hij bevraagt CloudWatch niet. Hij heeft geen AWS-inloggegevens en kan niet om een andere periode of gedetailleerdere registratie vragen. Al het dure en gevoelige werk gebeurt buiten het openbare verzoekpad.

Achter de schermen ziet het datapad er zo uit:

CloudFront → CloudWatch Logs → scheduled Lambda → aggregated JSON → S3 → CloudFront → browser

Deze scheiding is de belangrijkste architectuurkeuze. Het operationele systeem kan met gedetailleerde toegangsgegevens werken; het publicatiesysteem geeft alleen de kleine deelverzameling vrij die voor openbare weergave bedoeld is.

Eén keer verzamelen, minder publiceren

CloudFront standard logging versie 2 levert geselecteerde velden uit toegangslogboeken aan een CloudWatch Logs-groep. Het operationele logboek bevat genoeg informatie om aanvragen en statuscodes te onderzoeken, maar dat betekent niet dat al die informatie op een openbaar dashboard thuishoort.

De publicatiefunctie beperkt de gegevens bewust tot totalen:

  • geslaagde HTML-paginaweergaven gegroepeerd op landcode;
  • de meest opgevraagde HTML-paden;
  • requests per minuut afgeleid van geaggregeerde HTTP-statusmetingen;
  • een bijwerktijdstip en labels die elke periode beschrijven.

Het gegenereerde bestand bevat geen oorspronkelijke IP-adressen, locaties op stadsniveau, cookies, user-agentstrings of reeksen die de route van één bezoeker herkenbaar maken. Het openbare resultaat beantwoordt de vraag ‘welk verkeer kreeg de site?’ in plaats van ‘wie bezocht de site?’

Daarom gebruik ik ook de formulering paginaweergaven, geen personen. Eén lezer kan veel verzoeken veroorzaken. Zoekcrawlers, linkvoorvertoningen, monitoringprobes en andere automatisering kunnen naast menselijk verkeer voorkomen. Het dashboard toont infrastructuursignalen, geen identiteiten.

Waarom CloudWatch ertussen zit

CloudWatch biedt twee bruikbare weergaven van dezelfde activiteit. CloudWatch Logs Insights kan gestructureerde requestgegevens doorzoeken voor aggregaten per land en pagina. Metric filters tellen de vier HTTP-statusgroepen — 2xx, 3xx, 4xx en 5xx — zodat CloudWatch-meetgegevens reeksen van requestfrequenties kunnen leveren zonder elk logevent steeds opnieuw te ontleden.

De openbare dataset biedt verschillende overzichten:

  • landtotalen over de afgelopen 24 uur, 7 dagen en 30 dagen;
  • meetpunten van aanvraagfrequenties voor 24 uur, 7 dagen, 30 dagen en 12 maanden;
  • grovere tijdvakken voor langere perioden, om het document compact te houden.

CloudFront-logboeken vormen geen realtimegebeurtenisstroom. Volgens AWS worden standaardlogboeken doorgaans binnen een uur geleverd, al kunnen sommige regels later binnenkomen. Daarmee zijn ze geschikt voor een eerlijk terugblikkend dashboard, niet voor een live bezoekersteller.

Een geplande momentopname in plaats van een openbare API

Een EventBridge-regel roept de publicatie-Lambda om de zes uur aan. De functie voert begrensde query’s uit, vraagt de meetreeksen op, stelt het document samen en overschrijft precies één S3-sleutel: content/public-visitors.json.

Zes uur is bewust voorzichtig gekozen. Bezoekersanalyse hoeft niet op de seconde actueel te zijn en bij elke verversing worden loggegevens gescand. Een korter interval zou meer query-uitvoeringen en hogere kosten opleveren zonder de pagina wezenlijk nuttiger te maken.

Het JSON-object wordt geleverd met cacheheaders gericht op hervalidatie. Zo kan de homepage een nieuwere momentopname vinden terwijl CloudFront de S3-origin blijft beschermen. Een volledige site-uitrol en algemene cache-invalidatie zijn niet nodig wanneer de statistieken veranderen.

Dit momentopnamemodel faalt op een prettige manier. Als een query of Lambda-aanroep mislukt, blijft het bestaande statische document beschikbaar. Het dashboard kan verouderen, maar het portfolio blijft online en geen enkel request wacht op de analysepijplijn.

Minimale rechten beperken de schadeomvang

De publicatie-Lambda gebruikt een eigen IAM-rol. De relevante rechten zijn bewust beperkt:

  • query's alleen uitvoeren op en ophalen uit de aangewezen toegangsloggroep;
  • de CloudWatch-meetwaarden lezen die nodig zijn voor de grafiek met requestfrequenties;
  • alleen schrijven content/public-visitors.json in de sitebucket;
  • eigen uitvoeringslogboeken schrijven.

De functie kan geen willekeurige sitebestanden uitrollen, de CloudFront-distributie wijzigen of de S3-bucket openbaar maken. EventBridge krijgt toestemming om deze specifieke functie vanuit de specifieke geplande regel aan te roepen.

De sitebucket zelf blijft privé. CloudFront gebruikt Origin Access Control om ondertekende requests naar S3 te sturen. Zo kunnen bezoekers de distributie niet omzeilen en de bucket als openbare bestandsserver gebruiken.

De openbare kaart is bewust minder nauwkeurig

Een gedetailleerder dashboard is niet automatisch een beter openbaar dashboard. Stadsmarkeringen ogen indrukwekkend, maar kleine aantallen in combinatie met een exact tijdstip en een bekende persoon kunnen identificerend worden. Landtotalen zijn genoeg om het wereldwijde verhaal van de site te vertellen, zonder te doen alsof infrastructuurtelemetrie bewijst waar een specifieke lezer woont.

Het visuele ontwerp benadrukt die beperking. De kaart toont de intensiteit per land en een ranglijst, terwijl een toelichting er direct onder aangeeft dat verzoeken signalen zijn en geen personen. De interface biedt geen mogelijkheid om afzonderlijke gebeurtenissen te bekijken.

Dat onderscheid telt, omdat verzorgde grafieken een vals gevoel van zekerheid kunnen geven. Een land afgeleid uit een IP-adres is een waarneming van een edgeplatform. VPN’s, bedrijfsnetwerken, mobiele providers, crawlers en gecachete previews maken het menselijke verhaal erachter allemaal ingewikkelder.

De kosten volgen het scanvolume, niet de visuele complexiteit

De kaart en grafieken worden in de browser weergegeven met code die de statische site al levert. Hun visuele complexiteit veroorzaakt dus geen kosten voor server-side rendering. De relevante operationele kosten komen van het verzamelen en bewaren van logs, het opnemen van meetwaarden en het scannen van loggegevens met geplande query's.

De beheersmaatregelen zitten daarom in de architectuur, niet in het uiterlijk:

  • een bewaartermijn van 30 dagen voor logs voorkomt onbeperkte groei;
  • de functie draait slechts vier keer per dag;
  • query’s vragen begrensde perioden en alleen de benodigde velden op;
  • langere grafiekperioden gebruiken grovere meetintervallen;
  • het gepubliceerde JSON-bestand is klein vergeleken met de bronlogs.

De Lambda-uitvoeringstijd en S3-opslag voor één compact document zijn op deze schaal verwaarloosbaar. Het scanvolume van Logs Insights verdient aandacht als het verkeer of de bewaartermijn sterk groeit.

Wat de implementatie me leerde

Statisch betekent niet blind. Observability kan naast een statische site bestaan zonder deel te worden van het synchrone requestpad.

Aggregatie is een beveiligingsgrens. De omzetting van operationele logs naar een openbaar document moet expliciet, beoordeeld en eenrichtingsverkeer zijn.

Actueel genoeg is beter dan schijnbaar realtime. Een momentopname om de zes uur past bij de vertraagde levering van standaardtoegangslogs en voorkomt onnodig werk.

Bij fouten moet de vorige betrouwbare stand behouden blijven. Een verouderde momentopname is beter dan een homepage die uitvalt omdat een analysedienst niet beschikbaar is.

Leg de beperkingen naast de grafiek uit. Een openbare visualisatie heeft context nodig over bots, herhaalde requests, geografische afleiding en het verschil tussen verkeer en mensen.

Wanneer ik een ander ontwerp zou kiezen

Dit patroon werkt goed voor een persoonlijke site met bescheiden verkeer en een klein aantal vooraf bepaalde overzichten. Ik zou het heroverwegen bij vrije zoekvragen, dashboards met authenticatie, actualiteit op secondenniveau of grote multidimensionale datasets. Zulke eisen kunnen een API, aparte analyseopslag of een beheerd visualisatieplatform rechtvaardigen.

Voor dit portfolio zouden die toevoegingen een probleem oplossen dat ik niet heb. Eén geplande functie en één statisch document behouden de eigenschappen die de site oorspronkelijk aantrekkelijk maakten: een klein aanvalsoppervlak, voorspelbaar gedrag en begrijpelijke componenten.

De belangrijkste les

Het belangrijkste aan dit bezoekersdashboard is niet de wereldkaart. Het is de grens erachter.

Gedetailleerde requestgegevens blijven in de operationele omgeving. Een proces met minimale rechten zet ze regelmatig om in anonieme aggregaten. De website ontvangt alleen een compacte statische momentopname, die de browser in een verhaal omzet.

Zo krijgt de site een hartslag zonder een kwetsbaar dynamisch hart.

Bronnen