Logging¶
1. Inleiding¶
Binnen het iWlz-netwerkmodel is gestandaardiseerde tracelogging verplicht. Het doel hiervan is om transacties en gebeurtenissen in de keten end-to-end te kunnen volgen en analyseren. Hiermee kan sneller worden vastgesteld waar een fout optreedt, hoe een verzoek zich door het netwerk beweegt en welke partijen betrokken zijn.
2. TraceId en SpanId¶
Elke ketenverwerking krijgt een unieke TraceId toegewezen. Deze wordt bij het starten van een nieuw verzoek gegenereerd en doorgegeven aan alle opvolgende diensten. Alle logregels die bij hetzelfde verzoek horen, zijn daardoor aan elkaar te koppelen.
Voor iedere afzonderlijke verwerkingsstap binnen een keten wordt aanvullend een unieke SpanId gebruikt. Hiermee wordt inzichtelijk welke bewerkingen onderdeel uitmaken van dezelfde keten en kan de verwerking stap voor stap gevolgd worden.
3. Technische afspraken¶
3.1 Standaardisatie van TraceId- en SpanId-generatie via OpenTelemetry¶
Om de kans op botsingen in een gedistribueerde omgeving te minimaliseren, moeten zowel TraceId- als SpanId-waarden worden gegenereerd met een mechanisme dat voldoet aan de eisen van randomness en voldoende entropie.
Alle partijen dienen gebruik te maken van dezelfde library voor het genereren van deze identifiers. Om consistentie te waarborgen gebruiken alle partijen de OpenTelemetry SDK voor het genereren van TraceId- als SpanId-waarden. Voor vrijwel alle gangbare programmeertalen zijn OpenTelemetry-implementaties beschikbaar.
In de praktijk kan bijvoorbeeld gebruik worden gemaakt van de volgende compliant libraries:
@opentelemetry/api(JavaScript/Node.js)io.opentelemetry:opentelemetry-api(Java)opentelemetry-api(Python)
Hiermee wordt gegarandeerd dat alle gegenereerde TraceId- en SpanId-waarden voldoen aan de juiste lengte, entropie en formatvereisten.
Voor elke ontvangen request wordt een nieuwe SpanId gegenereerd. Indien een service bestaat uit meerdere verwerkingsstappen (zoals authenticatie, validatie of routering), mag hiervoor per stap ook een aparte SpanId worden aangemaakt.
3.2 Toevoegen aan requests¶
Zowel de TraceId als de SpanId worden toegevoegd aan de headers van elk verzoek dat binnen het netwerkmodel naar een andere dienst wordt verstuurd.
Gebruik hiervoor de volgende headers, conform de B3 Propagation-standaard:
X-B3-TraceId– een unieke ID voor het volledige ketenverzoek.X-B3-SpanId– een unieke ID voor de huidige verwerkingsstap.
Let op:
HTTP-headers zijn niet hoofdlettergevoelig. Conform de B3-standaard wordt aanbevolen de headers te noteren als X-B3-TraceId en X-B3-SpanId (in kebab-case met hoofdletters).
3.3 Randvoorwaarden voor TraceId¶
Een TraceId moet:
- Exact 16 bytes groot zijn, wat overeenkomt met 32 hexadecimale tekens (lowercase).
- Niet uitsluitend uit nullen bestaan (bijv.
0000000000000000is ongeldig). - Uniek zijn. TraceIds dienen gegenereerd te worden met behulp van een UUID-generator of via de OpenTelemetry SDK om duplicaten binnen een trace te voorkomen.
Voorbeeld van een geldig TraceID:
3.4 Randvoorwaarden voor SpanId¶
Een SpanId moet:
- Exact 8 bytes groot zijn, wat overeenkomt met 16 hexadecimale tekens (lowercase).
- Niet uitsluitend uit nullen bestaan (bijv.
0000000000000000is ongeldig). - Uniek zijn. SpanIds worden gegenereerd met behulp van de OpenTelemetry SDK, zodat duplicaten binnen een trace worden voorkomen.
Voorbeeld van een geldig SpanId:
3.5 Validatie van TraceId¶
Bij binnenkomst wordt gecontroleerd of een TraceId aanwezig is. Indien aanwezig, wordt deze gebruikt voor verdere verwerking.
3.6 Voorbeeldimplementatie van tracelogging (niet-normatief)¶
Onderstaande flow toont een mogelijke implementatie van traceerbaarheid binnen een ketenverzoek. De flow omvat zowel het aanvragen van autorisatie als het uitvoeren van een gegevensopvraag (GraphQL) en laat zien hoe TraceId en SpanId zich door de verschillende onderdelen van het netwerkmodel verspreiden.
Dit voorbeeld is afkomstig uit een specifieke context en dient ter illustratie van de werking; de exacte inrichting kan verschillen per ketenpartner of toepassing
---
config:
theme: forest
---
sequenceDiagram
box "Deelnemer"
participant Client as Client
end
box "nID"
participant AuthzServer as autorisatieserver
participant Filter as nID Filter
participant nIDResourceServer as Resource-server
end
box "Register"
participant BEMRegister as Resource
end
autonumber
activate Client
Client->>AuthzServer: **Aanvragen van autorisatie**<br/>"scope": "registers/resource:read"<br/>Authenticatiemiddel<br/>X-B3-TraceId: 463ac35c9f6413ad48485a3953bb6124<br/>X-B3-SpanId: a2fb4a1d1a96d312
activate AuthzServer
AuthzServer->>AuthzServer: Valideer Authenticatiemiddel
AuthzServer->>AuthzServer: Run Rule-engine o.b.v. scope(s)<br/>X-B3-TraceId: 463ac35c9f6413ad48485a3953bb6124<br/>X-B3-SpanId: 34cfd3ee730bbe13
activate AuthzServer
AuthzServer->>AuthzServer: Valideer autorisatie
AuthzServer->>AuthzServer: Genereer Access-Token<br/>X-B3-TraceId: 463ac35c9f6413ad48485a3953bb6124<br/>X-B3-SpanId: 34cfd3ee730bbe13
activate AuthzServer
deactivate AuthzServer
deactivate AuthzServer
AuthzServer-->>Client: 200 Response (Access-Token)
deactivate AuthzServer
deactivate Client
Client->>Filter: **GraphQL Query**<br/>Authenticatiemiddel + Access-Token<br/>X-B3-TraceId: 463ac35c9f6413ad48485a3953bb6124<br/>X-B3-SpanId: 2edb09379a27bfb1
activate Filter
Note right of Filter: Inline filtering requests
activate Client
Filter->>Filter: Valideer Authenticatiemiddel
Filter->>Filter: Valideer Access-Token
Filter->>Filter: Valideer GraphQL
Filter->>Filter: Valideer GraphQL request met scope(s)
Filter->>nIDResourceServer:
deactivate Filter
activate nIDResourceServer
activate BEMRegister
nIDResourceServer->>BEMRegister: GraphQL Request<br/>X-B3-TraceId: 463ac35c9f6413ad48485a3953bb6124<br/>X-B3-SpanId: 75c38117346fa472
BEMRegister-->>nIDResourceServer: 200 Response (GraphQL)
deactivate BEMRegister
nIDResourceServer-->>Client: 200 Response (GraphQL)
deactivate nIDResourceServer
deactivate Client
Figuur 1 - Sequentiediagram Logging