run_results.json 파일

run_results.json 파일

run_results.json은 완료된 dbt 실행(invocation)에 대한 정보를 담고 있어요. 실행된 각 노드(모델·테스트 등)의 타이밍과 상태가 기록되어, 여러 파일을 합치면 평균 모델 실행 시간·테스트 실패율·스냅샷 변경 수 등을 계산할 수 있어요.

출처: 문서

본문

현재 스키마: v6

생성 주체: build clone compile docs generate retry run seed show snapshot test run-operation

이 파일은 완료된 dbt 실행에 대한 정보를 담고 있어요. 각 실행된 노드(모델, 테스트 등)의 타이밍과 상태 정보가 포함돼요. 여러 run_results.json을 합치면 평균 모델 실행 시간, 테스트 실패율, 스냅샷으로 포착된 레코드 변경 수 등을 계산할 수 있어요.

실행된 노드만 run results에 나타난다는 점에 주의하세요. 기준(criteria)이 다른 run/test 단계가 여러 개 있으면 각각 다른 run results를 생성해요.

(dbt v2.0 이상 적용) 참고: dbt freshness는 다른 아티팩트를 생성해요 — freshness.json(소스와 모델 모두)과 sources.json(소스만, 하위 호환성을 위해 유지). dbt source freshness는 여전히 지원되지만 레거시 명령어로 간주돼요.

최상위 키(Top-level keys)

  • metadata
  • args: 이 아티팩트를 생성한 CLI 명령어 또는 RPC 메서드에 전달된 인자의 사전(dictionary). 가장 유용한 것은 which(명령어) 또는 rpc_method예요. 이 dict는 null 값을 제외하고, null이 아닌 기본값은 포함해요. dbt-Jinja 컨텍스트의 invocation_args_dict와 동일해요.
  • elapsed_time: 총 실행 시간(초).
  • results: 노드 실행 상세의 배열.

results의 각 항목은 Result 객체이며, 차이점 하나: 전체 node 객체 대신 unique_id만 포함돼요. (전체 node 객체는 manifest.json에 기록돼요.)

  • unique_id: 결과를 manifest의 nodes에 연결하는 노드 고유 식별자

  • status: dbt가 해석한 런타임 성공·실패·오류 상태

  • thread_id: 이 노드를 실행한 스레드. 예: Thread-1

  • execution_time: 이 노드를 실행하는 데 쓴 총 시간

  • timing: 실행 시간을 단계로 나눈 배열(주로 compile + execute)

  • message: 데이터베이스에서 반환된 정보를 바탕으로 dbt가 CLI에서 이 결과를 어떻게 보고하는지

  • adapter_response: 데이터베이스에서 반환된 메타데이터 사전으로, 어댑터에 따라 달라져요. 예: 성공 code, rows_affected 수, 총 bytes_processed 등. 데이터 테스트에는 적용되지 않아요. rows_affected는 마지막으로 실행된 문장이 수정한 행 수를 반환해요. 쿼리의 행 수를 알 수 없거나 적용할 수 없는 경우(예: 뷰 생성 시) rowcount에 표준값 -1이 반환돼요.

run_results.json은 applied 상태와 관련된 세 가지 속성을 포함하며, 이는 unique_id를 보완해요:

  • compiled: 노드 컴파일 상태의 불리언 항목(False — 파싱 후, True — 컴파일 후).
  • compiled_code: 컴파일된 코드의 렌더링된 문자열(파싱 후엔 비어 있고, 컴파일 후엔 전체 문자열).
  • relation_name: 데이터베이스 내에서 생성(또는 생성될) 객체의 정규화된(full-qualified) 이름.

노드의 logical 상태에 대한 추가 정보는 unique_id를 통해 manifest.json의 전체 node 객체에서 계속 찾을 수 있어요.

예시

run_results.json 파일로 출력되는 몇 가지 예시와 결과예요.

모델 컴파일 결과

다음과 같은 모델이 있다고 가정해 볼게요:

models/my_model.sql

select {{ dbt.current_timestamp() }} as created_at

모델을 컴파일하세요:

dbt compile -s my_model

run_results.json에서 출력되는 일부 스니펫이에요:

    {
      "status": "success",
      "timing": [
        {
          "name": "compile",
          "started_at": "2023-10-12T16:35:28.510434Z",
          "completed_at": "2023-10-12T16:35:28.519086Z"
        },
        {
          "name": "execute",
          "started_at": "2023-10-12T16:35:28.521633Z",
          "completed_at": "2023-10-12T16:35:28.521641Z"
        }
      ],
      "thread_id": "Thread-2",
      "execution_time": 0.0408780574798584,
      "adapter_response": {},
      "message": null,
      "failures": null,
      "unique_id": "model.my_project.my_model",
      "compiled": true,
      "compiled_code": "select now() as created_at",
      "relation_name": "\"postgres\".\"dbt_dbeatty\".\"my_model\""
    }

일반 데이터 테스트 실행

store_failures_as config를 사용해 데이터 테스트 하나만의 실패를 데이터베이스에 저장해 보세요:

models/_models.yml

models:
  - name: my_model
    columns:
      - name: created_at
        data_tests:
          - not_null:
              config:
                store_failures_as: view
          - unique:
              config:
                store_failures_as: ephemeral

내장 unique 테스트를 실행하고 실패를 테이블로 저장하세요:

dbt test -s my_model

run_results.json에서 출력되는 일부 스니펫이에요:

  "results": [
    {
      "status": "pass",
      "timing": [
        {
          "name": "compile",
          "started_at": "2023-10-12T17:20:51.279437Z",
          "completed_at": "2023-10-12T17:20:51.317312Z"
        },
        {
          "name": "execute",
          "started_at": "2023-10-12T17:20:51.319812Z",
          "completed_at": "2023-10-12T17:20:51.441967Z"
        }
      ],
      "thread_id": "Thread-2",
      "execution_time": 0.1807551383972168,
      "adapter_response": {
        "_message": "SELECT 1",
        "code": "SELECT",
        "rows_affected": 1
      },
      "message": null,
      "failures": 0,
      "unique_id": "test.my_project.unique_my_model_created_at.a9276afbbb",
      "compiled": true,
      "compiled_code": "\n    \n    \n\nselect\n    created_at as unique_field,\n    count(*) as n_records\n\nfrom \"postgres\".\"dbt_dbeatty\".\"my_model\"\nwhere created_at is not null\ngroup by created_at\nhaving count(*) > 1\n\n\n",
      "relation_name": null
    },
    {
      "status": "pass",
      "timing": [
        {
          "name": "compile",
          "started_at": "2023-10-12T17:20:51.274049Z",
          "completed_at": "2023-10-12T17:20:51.295237Z"
        },
        {
          "name": "execute",
          "started_at": "2023-10-12T17:20:51.296361Z",
          "completed_at": "2023-10-12T17:20:51.491327Z"
        }
      ],
      "thread_id": "Thread-1",
      "execution_time": 0.22345590591430664,
      "adapter_response": {
        "_message": "SELECT 1",
        "code": "SELECT",
        "rows_affected": 1
      },
      "message": null,
      "failures": 0,
      "unique_id": "test.my_project.not_null_my_model_created_at.9b412fbcc7",
      "compiled": true,
      "compiled_code": "\n    \n    \n\n\n\nselect *\nfrom \"postgres\".\"dbt_dbeatty\".\"my_model\"\nwhere created_at is null\n\n\n",
      "relation_name": "\"postgres\".\"dbt_dbeatty_dbt_test__audit\".\"not_null_my_model_created_at\""
    }
  ],