Monitering van ETL-prosesse in 'n klein datapakhuis

Baie mense gebruik gespesialiseerde gereedskap om roetines te skep vir die onttrekking, transformasie en laai van data in relasionele databasisse. Die proses van die gereedskap word aangeteken, foute word aangeteken.

In die geval van 'n fout, bevat die log inligting dat die instrument nie die taak voltooi het nie en watter modules (dikwels java) waar gestop het. Die laaste reëls kan 'n databasisfout bevat, soos 'n skending van 'n tabel se unieke sleutel.

Om die vraag te beantwoord watter rol ETL-foutinligting speel, het ek al die probleme wat die afgelope twee jaar voorgekom het in 'n taamlik groot bewaarplek geklassifiseer.

Monitering van ETL-prosesse in 'n klein datapakhuis

Databasisfoute sluit in soos: daar was nie genoeg spasie nie, die verbinding is verloor, die sessie het gehang, ens.

Logiese foute sluit in oortredings van tabelsleutels, ongeldige voorwerpe, gebrek aan toegang tot voorwerpe, ens.
Die skeduleerder mag dalk nie betyds geloods word nie, kan vries, ens.

Eenvoudige foute neem nie veel tyd om reg te stel nie. 'n Goeie ETL kan die meeste van hulle op sy eie hanteer.

Komplekse foute maak dit nodig om datahanteringsprosedures oop te maak en na te gaan en databronne te verken. Dit lei dikwels tot die behoefte om veranderinge te toets en te ontplooi.

Dus, die helfte van alle probleme hou verband met die databasis. 48% van alle foute is eenvoudige foute.
'n Derde van alle probleme hou verband met veranderinge in die stoorlogika of -model; meer as die helfte van hierdie foute is kompleks.

En minder as 'n kwart van alle probleme hou verband met die taakskeduleerder, waarvan 18% eenvoudige foute is.

Oor die algemeen is 22% van alle foute wat voorkom kompleks en verg die meeste aandag en tyd om reg te stel. Hulle gebeur ongeveer een keer per week. Terwyl eenvoudige foute byna elke dag gebeur.

Dit is duidelik dat die monitering van ETL-prosesse effektief sal wees wanneer die ligging van die fout so akkuraat as moontlik in die log aangedui word en minimale tyd nodig is om die bron van die probleem te vind.

Doeltreffende monitering

Wat wou ek in die ETL-moniteringsproses sien?

Monitering van ETL-prosesse in 'n klein datapakhuis
Begin by - toe ek begin werk het,
Bron - databron,
Laag - watter bergingsvlak is gelaai,
ETL Job Name is 'n laaiprosedure wat uit baie klein stappe bestaan,
Stapnommer — nommer van die stap wat uitgevoer word,
Geaffekteerde rye - hoeveel data is reeds verwerk,
Duur sek - hoe lank dit neem om uit te voer,
Status - of alles goed is of nie: OK, FOUT, LOOP, HANG
Boodskap — laaste suksesvolle boodskap of foutbeskrywing.

Op grond van die status van die rekords, kan jy 'n e-pos stuur. brief aan ander deelnemers. As daar geen foute is nie, is 'n brief nie nodig nie.

Op hierdie manier, in die geval van 'n fout, word die ligging van die voorval duidelik aangedui.

Soms gebeur dit dat die moniteringsinstrument self nie werk nie. In hierdie geval is dit moontlik om die aansig (aansig) direk in die databasis op te roep, op grond waarvan die verslag gebou word.

ETL monitering tabel

Om monitering van ETL-prosesse te implementeer, is een tabel en een aansig genoeg.

Om dit te doen kan jy terugkeer na jou eie klein stoorplek en skep 'n prototipe in sqlite databasis.

DDL-tabelle

CREATE TABLE UTL_JOB_STATUS (
/* Table for logging of job execution log. Important that the job has the steps ETL_START and ETL_END or ETL_ERROR */
  UTL_JOB_STATUS_ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
  SID               INTEGER NOT NULL DEFAULT -1, /* Session Identificator. Unique for every Run of job */
  LOG_DT            INTEGER NOT NULL DEFAULT 0,  /* Date time */
  LOG_D             INTEGER NOT NULL DEFAULT 0,  /* Date */
  JOB_NAME          TEXT NOT NULL DEFAULT 'N/A', /* Job name like JOB_STG2DM_GEO */
  STEP_NAME         TEXT NOT NULL DEFAULT 'N/A', /* ETL_START, ... , ETL_END/ETL_ERROR */
  STEP_DESCR        TEXT,                        /* Description of task or error message */
  UNIQUE (SID, JOB_NAME, STEP_NAME)
);
INSERT INTO UTL_JOB_STATUS (UTL_JOB_STATUS_ID) VALUES (-1);

Bekyk/rapporteer DDL

CREATE VIEW IF NOT EXISTS UTL_JOB_STATUS_V
AS /* Content: Package Execution Log for last 3 Months. */
WITH SRC AS (
  SELECT LOG_D,
    LOG_DT,
    UTL_JOB_STATUS_ID,
    SID,
	CASE WHEN INSTR(JOB_NAME, 'FTP') THEN 'TRANSFER' /* file transfer */
	     WHEN INSTR(JOB_NAME, 'STG') THEN 'STAGE' /* stage */
	     WHEN INSTR(JOB_NAME, 'CLS') THEN 'CLEANSING' /* cleansing */
	     WHEN INSTR(JOB_NAME, 'DIM') THEN 'DIMENSION' /* dimension */
	     WHEN INSTR(JOB_NAME, 'FCT') THEN 'FACT' /* fact */
		 WHEN INSTR(JOB_NAME, 'ETL') THEN 'STAGE-MART' /* data mart */
	     WHEN INSTR(JOB_NAME, 'RPT') THEN 'REPORT' /* report */
	     ELSE 'N/A' END AS LAYER,
	CASE WHEN INSTR(JOB_NAME, 'ACCESS') THEN 'ACCESS LOG' /* source */
	     WHEN INSTR(JOB_NAME, 'MASTER') THEN 'MASTER DATA' /* source */
	     WHEN INSTR(JOB_NAME, 'AD-HOC') THEN 'AD-HOC' /* source */
	     ELSE 'N/A' END AS SOURCE,
    JOB_NAME,
    STEP_NAME,
    CASE WHEN STEP_NAME='ETL_START' THEN 1 ELSE 0 END AS START_FLAG,
    CASE WHEN STEP_NAME='ETL_END' THEN 1 ELSE 0 END AS END_FLAG,
    CASE WHEN STEP_NAME='ETL_ERROR' THEN 1 ELSE 0 END AS ERROR_FLAG,
    STEP_NAME || ' : ' || STEP_DESCR AS STEP_LOG,
	SUBSTR( SUBSTR(STEP_DESCR, INSTR(STEP_DESCR, '***')+4), 1, INSTR(SUBSTR(STEP_DESCR, INSTR(STEP_DESCR, '***')+4), '***')-2 ) AS AFFECTED_ROWS
  FROM UTL_JOB_STATUS
  WHERE datetime(LOG_D, 'unixepoch') >= date('now', 'start of month', '-3 month')
)
SELECT JB.SID,
  JB.MIN_LOG_DT AS START_DT,
  strftime('%d.%m.%Y %H:%M', datetime(JB.MIN_LOG_DT, 'unixepoch')) AS LOG_DT,
  JB.SOURCE,
  JB.LAYER,
  JB.JOB_NAME,
  CASE
  WHEN JB.ERROR_FLAG = 1 THEN 'ERROR'
  WHEN JB.ERROR_FLAG = 0 AND JB.END_FLAG = 0 AND strftime('%s','now') - JB.MIN_LOG_DT > 0.5*60*60 THEN 'HANGS' /* half an hour */
  WHEN JB.ERROR_FLAG = 0 AND JB.END_FLAG = 0 THEN 'RUNNING'
  ELSE 'OK'
  END AS STATUS,
  ERR.STEP_LOG     AS STEP_LOG,
  JB.CNT           AS STEP_CNT,
  JB.AFFECTED_ROWS AS AFFECTED_ROWS,
  strftime('%d.%m.%Y %H:%M', datetime(JB.MIN_LOG_DT, 'unixepoch')) AS JOB_START_DT,
  strftime('%d.%m.%Y %H:%M', datetime(JB.MAX_LOG_DT, 'unixepoch')) AS JOB_END_DT,
  JB.MAX_LOG_DT - JB.MIN_LOG_DT AS JOB_DURATION_SEC
FROM
  ( SELECT SID, SOURCE, LAYER, JOB_NAME,
           MAX(UTL_JOB_STATUS_ID) AS UTL_JOB_STATUS_ID,
           MAX(START_FLAG)       AS START_FLAG,
           MAX(END_FLAG)         AS END_FLAG,
           MAX(ERROR_FLAG)       AS ERROR_FLAG,
           MIN(LOG_DT)           AS MIN_LOG_DT,
           MAX(LOG_DT)           AS MAX_LOG_DT,
           SUM(1)                AS CNT,
           SUM(IFNULL(AFFECTED_ROWS, 0)) AS AFFECTED_ROWS
    FROM SRC
    GROUP BY SID, SOURCE, LAYER, JOB_NAME
  ) JB,
  ( SELECT UTL_JOB_STATUS_ID, SID, JOB_NAME, STEP_LOG
    FROM SRC
    WHERE 1 = 1
  ) ERR
WHERE 1 = 1
  AND JB.SID = ERR.SID
  AND JB.JOB_NAME = ERR.JOB_NAME
  AND JB.UTL_JOB_STATUS_ID = ERR.UTL_JOB_STATUS_ID
ORDER BY JB.MIN_LOG_DT DESC, JB.SID DESC, JB.SOURCE;

SQL Kontroleer die vermoë om 'n nuwe sessienommer te kry

SELECT SUM (
  CASE WHEN start_job.JOB_NAME IS NOT NULL AND end_job.JOB_NAME IS NULL /* existed job finished */
	    AND NOT ( 'y' = 'n' ) /* force restart PARAMETER */
       THEN 1 ELSE 0
  END ) AS IS_RUNNING
  FROM
    ( SELECT 1 AS dummy FROM UTL_JOB_STATUS WHERE sid = -1) d_job
  LEFT OUTER JOIN
    ( SELECT JOB_NAME, SID, 1 AS dummy
      FROM UTL_JOB_STATUS
      WHERE JOB_NAME = 'RPT_ACCESS_LOG' /* job name PARAMETER */
	    AND STEP_NAME = 'ETL_START'
      GROUP BY JOB_NAME, SID
    ) start_job /* starts */
  ON d_job.dummy = start_job.dummy
  LEFT OUTER JOIN
    ( SELECT JOB_NAME, SID
      FROM UTL_JOB_STATUS
      WHERE JOB_NAME = 'RPT_ACCESS_LOG'  /* job name PARAMETER */
	    AND STEP_NAME in ('ETL_END', 'ETL_ERROR') /* stop status */
      GROUP BY JOB_NAME, SID
    ) end_job /* ends */
  ON start_job.JOB_NAME = end_job.JOB_NAME
     AND start_job.SID = end_job.SID

Tafelkenmerke:

  • die begin en einde van die dataverwerkingsprosedure moet vergesel word van die stappe ETL_START en ETL_END
  • in die geval van 'n fout, moet 'n ETL_ERROR-stap met sy beskrywing geskep word
  • die hoeveelheid verwerkte data moet byvoorbeeld met sterretjies uitgelig word
  • dieselfde prosedure kan op dieselfde tyd begin word met die force_restart=y parameter; daarsonder word die sessienommer slegs aan die voltooide prosedure uitgereik
  • in normale modus is dit onmoontlik om dieselfde dataverwerkingsprosedure parallel uit te voer

Die nodige bewerkings om met die tabel te werk is die volgende:

  • kry die sessienommer van die ETL-prosedure wat van stapel gestuur word
  • die invoeging van 'n loginskrywing in 'n tabel
  • om die laaste suksesvolle rekord van 'n ETL-prosedure te kry

In databasisse soos Oracle of Postgres kan hierdie bewerkings met ingeboude funksies geïmplementeer word. sqlite vereis 'n eksterne meganisme en in hierdie geval dit prototipe in PHP.

Output

Dus, foutrapportering in dataverwerkingsinstrumente speel 'n mega-belangrike rol. Maar hulle kan kwalik optimaal genoem word om vinnig die oorsaak van die probleem te vind. Wanneer die aantal prosedures honderd nader, verander prosesmonitering in 'n komplekse projek.

Die artikel verskaf 'n voorbeeld van 'n moontlike oplossing vir die probleem in die vorm van 'n prototipe. Die hele prototipe van die klein bewaarplek is beskikbaar in gitlab SQLite PHP ETL Utilities.

Bron: will.com

Voeg 'n opmerking