MetricSign
NL|ENStart free →
Data Observability8 min·

Je afwijkingsvisual in Power BI liegt alleen als de refresh stilletjes mislukt

Custom visuals zoals PBIGenie's Hammerhead maken actual-versus-budget vergelijkingen leesbaar. Ze maken de onderliggende data nog niet betrouwbaar.

Read this article in English →

Een nette grafiek is gevaarlijker dan een kapotte

Een Fabric Community thread uit mei 2025 laat PBIGenie hun Hammerhead Variance Bar presenteren: een custom visual die actual-versus-budget vergelijkingen weergeeft als horizontale balken met positieve en negatieve afwijkingscues. De community-reacties waren enthousiast. De visual is overzichtelijk, geen DAX-trucs nodig en de opmaak maakt variantie-interpretatie direct zichtbaar.

Dat enthousiasme is terecht voor de visualisatielaag. Custom visuals zoals de Hammerhead, IBCS-conforme bullet charts en de native Power BI watervalgrafiek lossen een echt probleem op: afwijkingsdata in één oogopslag leesbaar maken. Maar elke van deze visuals heeft dezelfde fundamentele beperking. Ze renderen wat het datamodel bevat. Ze kunnen geen onderscheid maken tussen een dataset die om 05:00 uur is gerefresht met actuele cijfers en één die om 04:47 uur is mislukt en de cijfers van gisteren serveert.

Dat is belangrijk omdat afwijkingsrapporten onevenredig veel organisatorisch gewicht dragen. Als een CFO ziet dat de omzet 3,2% onder budget zit, handelt hij daarnaar. Als dat cijfer feitelijk gebaseerd is op actuals van 36 uur geleden omdat de refresh van de bron is mislukt na een gateway time-out, handelt hij op basis van fictie. De visual zag er perfect uit. De data was dat niet.

De kloof tussen visuele kwaliteit en datakwaliteit is waar productie-incidenten zich schuilhouden. Een grafiek die een renderingsfout gooit, wordt meteen gemeld. Een grafiek die zelfverzekerd onjuiste cijfers toont, kan dagenlang blijven staan.

Custom visuals voegen een renderlaag toe die data freshness verhult

De native visuals van Power BI nemen deel aan de ingebouwde indicators voor data freshness van de service. Als je over een native tabel of staafdiagram hovert, kun je inspecteren wanneer het dataset voor het laatst is gerefresht. Custom visuals, inclusief gecertificeerde visuals via AppSource, tonen deze metadata niet altijd consistent.

Het certificeringsproces voor Power BI custom visuals, gedocumenteerd in de vereisten van Microsoft's Partner Center, richt zich op beveiligingsbeperkingen: geen externe HTTP-verzoeken via fetch of XMLHttpRequest, geen eval() en geen toegang tot externe services. Dat zijn zinvolle grenzen. Maar certificering beoordeelt niet of de visual data staleness communiceert naar gebruikers. Het VisualUpdateOptions-object dat wordt doorgegeven aan de update()-methode van een custom visual bevat viewport-afmetingen en de DataView, maar de DataView zelf bevat geen refresh-tijdstempels of failure-status.

Dit betekent dat een custom visual-ontwikkelaar die een afwijkingsbalk bouwt, op API-niveau geen mechanisme heeft om een waarschuwing zoals "deze data is 14 uur oud" te tonen. De visual ontvangt rijen en measures, rendert die en vertrouwt op de host. De host (Power BI Service of Desktop) kent de refresh-status, maar die kennis stroomt niet door naar de rendercontext van de visual.

Voor standaard rapportage is dit een klein gemis. Voor afwijkingsrapportage, waarbij het volledige doel van de visual is om discrepanties tussen werkelijke en verwachte waarden te tonen, toont een stale dataset niet alleen verkeerde cijfers. Hij toont verkeerde afwijkingen. Een negatieve afwijking wordt positief, of een materieel gemis ziet eruit als een kwartaal op koers. De visual is er om anomalieën te signaleren, en hij kan die taak niet vervullen als de onderliggende anomalie in de data pipeline zit en niet in de data zelf.

Hoe stale actuals een afwijkingsvisual bereiken zonder een alert te triggeren ADF pipeline mislukt om 2:00 uur (API throttling) Lakehouse behoudt actuals van gisteren Power BI geplande refresh draait om 6:00 uur Dataset refresh slaagt (beide bronnen reageren) Afwijkingsvisual rendert stale actuals vs actueel CFO ziet onjuiste afwijking — geen waarschuwing getoond
Hoe stale actuals een afwijkingsvisual bereiken zonder een alert te triggeren

Budget tables refreshen anders dan actuals en mislukken onafhankelijk van elkaar

De meeste actual-versus-budget modellen in Power BI gebruiken minstens twee afzonderlijke databronnen. Actuals komen doorgaans uit een transactioneel systeem: een ERP, een data warehouse fact table of een Lakehouse-tabel in Fabric. Budget data komt uit een planningssysteem, een spreadsheet geüpload naar SharePoint of een apart data warehouse. Deze bronnen refreshen op verschillende schema's, via verschillende pipelines en mislukken om verschillende redenen.

Neem een veelvoorkomende architectuur: actuals worden nachtelijks geladen via een Azure Data Factory pipeline die extraheert uit Dynamics 365 naar een Lakehouse, waarna een Power BI dataset om 06:00 uur refresht op basis van zowel het Lakehouse (actuals) als een in SharePoint gehoste Excel-bestand (budget). Als de ADF pipeline om 02:00 uur mislukt door een API throttling-limiet van Dynamics, behoudt de Lakehouse-tabel de actuals van de vorige nacht. De Power BI refresh om 06:00 uur slaagt: hij kan de Lakehouse-tabel en het Excel-bestand nog steeds lezen. Het dataset rapporteert als "succesvol gerefresht" omdat vanuit Power BI's perspectief beide bronnen hebben gereageerd.

De afwijkingsvisual toont nu het budget van het huidige jaar tegen stale actuals. De delta is onjuist, maar niets in Power BI meldt dit. De dataset refresh is geslaagd. De visual rendert. Het enige signaal dat er iets mis is gegaan, staat in de ADF pipeline run history die de Power BI rapport-consument nooit ziet.

Dit failure mode verergert in composite models. Een DirectQuery-verbinding naar actuals kan actuele data retourneren terwijl een Import-mode budget table data behoudt van de laatste geslaagde refresh drie dagen geleden. De LASTDATE() in je actuals wijkt af van het effectieve datumbereik in je budget, en de afwijkingsbalk toont een vergelijking over niet-overeenkomende tijdvensters zonder enige indicatie dat de periodes niet overeenkomen.

Stale afwijkingsdata detecteren vereist signalen buiten de visuallaag

De oplossing zit niet in de visual. PBIGenie's Hammerhead, of welke custom afwijkingsbalk dan ook, doet zijn werk correct: hij rendert de data die hij ontvangt. Het probleem zit stroomopwaarts, in de kloof tussen een pipeline run en dataset-consumptie.

Eén aanpak is freshness checks inbouwen in je DAX-model. Een measure zoals Actuals Data Age = DATEDIFF(MAX(FactSales[LoadTimestamp]), NOW(), HOUR) geeft je een numeriek signaal dat je naast je afwijkingsbalk kunt tonen in een kaartvisual. Als dat getal je verwachte refresh-venster overschrijdt, weet de rapport-consument dat er iets mis is. Dit vereist wel dat de brontabel een load timestamp bijhoudt, wat veel ERP-extracten niet standaard bevatten.

Een andere aanpak gebruikt de Power BI REST API. Het endpoint GET /groups/{groupId}/datasets/{datasetId}/refreshes retourneert refresh history met statuscodes: Completed, Failed en Disabled. Je kunt dit programmatisch pollen, maar je moet de alerting-logica zelf bouwen: een Logic App, een Power Automate flow of een geplande Azure Function die het endpoint controleert en bij een failure een Teams-melding stuurt. Elk van deze opties introduceert zijn eigen failure surface: de Logic App kan mislukken, het service principal-token kan verlopen en de Teams webhook kan worden throttled.

MetricSign monitort Power BI dataset refreshes en de upstream pipelines die ze voeden (ADF, Databricks, dbt) als een verbonden graaf. Wanneer een ADF pipeline run om 02:00 uur mislukt, correleert MetricSign die failure aan de downstream Power BI datasets die afhankelijk zijn van de getroffen Lakehouse-tabel en meldt een incident voordat de refresh van 06:00 uur überhaupt loopt. De afwijkingsvisual krijgt nooit de kans om stale data te tonen, omdat de pipeline-onderbreking aan de bron wordt opgepakt.

Productiechecklist: afwijkingsvisuals betrouwbaar houden

Een betrouwbaar actual-versus-budget rapport in Power BI vereist werk op elke laag, niet alleen de visual. Begin bij de bron. Elke fact table die in een afwijkingsberekening wordt gebruikt, moet een kolom LoadTimestamp of RefreshDate bevatten, gevuld tijdens het ETL-proces. In ADF gebruik je pipeline().TriggerTime als expressie in een Derived Column-activiteit. In Databricks voeg je current_timestamp() toe aan je schrijfoperatie. In dbt gebruik je {{ run_started_at }} als kolomwaarde in je staging-model.

Op dataset-niveau maak je een DAX measure die de leeftijd van de meest recente load timestamp berekent voor elke brontabel. Toon deze als kaartvisuals op de rapportpagina, of beter nog, op een verborgen pagina die je datateam dagelijks bekijkt. Stel conditional formatting in zodat de kaart rood wordt als de leeftijd je SLA overschrijdt: doorgaans het refresh-schema plus een buffer.

Op Power BI Service-niveau configureer je meldingen bij dataset refresh failures. Ga naar de dataset-instellingen, navigeer naar Scheduled Refresh en voeg e-mailadressen toe onder "Send refresh failure notification to." Dit is een minimumvereiste. Het vangt alleen Power BI-niveau refresh failures op, niet upstream pipeline failures die stale maar technisch geldige data produceren.

Op pipeline-niveau instrumenteer je je orchestratietool om failure-signalen uit te sturen die verbinden met je rapportagelaag. Hier hebben de meeste teams een gat. De eigenaar van de ADF pipeline en de eigenaar van het Power BI rapport zijn vaak verschillende mensen, in verschillende teams, die verschillende monitoringtools gebruiken. Het failure-signaal bestaat, maar bereikt de persoon die erop moet handelen niet: de analist die om 09:00 uur een afwijkingsgrafiek aan de CFO gaat presenteren op basis van data van twee dagen geleden.

Veelgestelde vragen

Kan een Power BI custom visual detecteren of de onderliggende dataset stale is?+
Nee. De Power BI Visuals API geeft een DataView-object door aan de `update()`-methode van de visual, met daarin de datarijen en measures maar geen metadata over refresh-tijdstempels of failure-status. De visual rendert wat hij ontvangt. Data freshness-informatie is beschikbaar via de Power BI REST API op serviceniveau, maar stroomt niet door naar de rendercontext van de visual.
Waarom is stale data gevaarlijker in afwijkingsrapporten dan in standaardrapporten?+
Een omzetcijfer van een dag oud is doorgaans herkenbaar als stale: je weet ruwweg wat het cijfer vandaag zou moeten zijn. Een afwijkingspercentage berekend op basis van stale actuals tegen het huidige budget kan van teken wisselen. Een gunstige afwijking van 2% kan in werkelijkheid een ongunstige afwijking van 1,5% zijn, en niets aan de visual wijst op de discrepantie. Het volledige doel van een afwijkingsvisual is het signaleren van anomalieën, zodat een verborgen datakwaliteitsprobleem de kernfunctie van het rapport ondergraaft.
Hoe voeg ik een data freshness-indicator toe aan mijn Power BI afwijkingsrapport?+
Voeg een LoadTimestamp-kolom toe aan je fact tables tijdens ETL (gebruik `pipeline().TriggerTime` in ADF, `current_timestamp()` in Databricks of `run_started_at` in dbt). Maak vervolgens een DAX measure zoals `Actuals Data Age = DATEDIFF(MAX(FactSales[LoadTimestamp]), NOW(), HOUR)` en toon die in een kaartvisual met conditional formatting die rood wordt als de leeftijd je refresh SLA overschrijdt.

Gerelateerde integraties

Gerelateerde artikelen