Unity Catalog system 카탈로그의 감사 로그(audit)·과금 사용량(billing)·쿼리 이력(query history) 테이블을 조회해 접근 이력·비용·쿼리 실행 현황을 확인하는 방법과 샘플 쿼리
목적
Databricks Unity Catalog의 system 카탈로그가 제공하는 감사 로그(system.access.audit)·과금 사용량(system.billing.usage)·쿼리 이력(system.query.history) 테이블을 조회해, 워크스페이스에서 누가 무엇을 했는지, 어떤 리소스가 얼마나 비용을 소비했는지, 쿼리가 언제 얼마나 실행됐는지를 확인한다.
사전 조건
- UC 카탈로그 탐색기에서
system카탈로그를 확인하려면 관리자 권한이 필요하다. system카탈로그에 저장되는 데이터는 테이블마다 retention 기간이 최소 30~365일로 정해져 있다. 그 기간을 넘겨 영구 보관하려면 감사 로그·과금 사용량 데이터를 S3로 전달하도록 별도로 활성화해야 한다 (참고).- Databricks가 제공하는 전체 시스템 테이블 목록은 공식 문서에서 확인한다. 이 문서는 그중 주요 테이블인 audit·usage·query 세 가지와 활용 샘플 쿼리를 다룬다.
수행 방법
Audit Log — system.access.audit
retention : 365 days · 참고자료
워크스페이스에서 발생한 모든 audit event에 대한 기록을 저장한다.
주요 Action name: tokenLogin(토큰로그인) · createTable(테이블 생성) · runCommand(노트북 셀 실행) · executeQuery(쿼리 실행) · createNotebook(노트북 생성) · getTable(테이블 조회) 등.
runCommand 으로 필터링하면, 노트북에서 어떤 코드를 실행했는지도 함께 저장되어 있어 확인할 수 있다.
샘플 쿼리 — 누가 이 테이블에 권한이 있나요?
SELECT DISTINCT(grantee) AS `ACCESSIBLE BY`
FROM system.information_schema.table_privileges
WHERE table_schema = '{{schema_name}}' AND table_name = '{{table_name}}'
UNION
SELECT table_owner
FROM system.information_schema.tables
WHERE table_schema = '{{schema_name}}' AND table_name = '{{table}}'
UNION
SELECT DISTINCT(grantee)
FROM system.information_schema.schema_privileges
WHERE schema_name = '{{schema_name}}'
샘플 쿼리 — 지난 하루 동안 테이블에 액세스한 사용자는 누구인가요?
SELECT
user_identity.email as `User`,
IFNULL(request_params.full_name_arg,
request_params.name)
AS `Table`,
action_name AS `Type of Access`,
event_time AS `Time of Access`
FROM system.access.audit
WHERE (request_params.full_name_arg = '{{catalog.schema.table}}'
OR (request_params.name = '{{table_name}}'
AND request_params.schema_name = '{{schema_name}}'))
AND action_name
IN ('createTable','getTable','deleteTable')
AND event_date > now() - interval '1 day'
ORDER BY event_date DESC
샘플 쿼리 — 사용자가 어떤 테이블에 액세스했나요?
SELECT
action_name as `EVENT`,
event_time as `WHEN`,
IFNULL(request_params.full_name_arg, 'Non-specific') AS `TABLE ACCESSED`,
IFNULL(request_params.commandText,'GET table') AS `QUERY TEXT`
FROM system.access.audit
WHERE user_identity.email = '{{User}}'
AND action_name IN ('createTable',
'commandSubmit','getTable','deleteTable')
-- AND datediff(now(), event_date) < 1
-- ORDER BY event_date DESC
샘플 쿼리 — 날짜별 워크플로우의 성공 횟수와 실패 횟수
SELECT
event_date,
action_name,
count(*) AS total
FROM
system.access.audit
WHERE action_name IN ("runSucceeded", "runFailed")
GROUP BY 1, 2
ORDER BY event_date DESC, total DESC
샘플 쿼리 — 어제 노트북에서 실행된 SELECT, CRUD SQL문과 실행한 IP & 사용자
SELECT
event_time,
source_ip_address,
user_identity.email,
request_params.commandText,
action_name,
request_id,
user_agent,
response.status_code
FROM
system.access.audit
WHERE
action_name = "runCommand"
AND event_time >= current_date() - 1
AND startswith(request_params.commandText, 'SELECT')
OR startswith(request_params.commandText, 'CREATE')
OR startswith(request_params.commandText, 'DROP')
OR startswith(request_params.commandText, 'ALTER')
OR startswith(request_params.commandText, 'DELETE')
UNION ALL
SELECT
event_time,
source_ip_address,
user_identity.email,
request_params.commandText,
action_name,
request_id,
user_agent,
response.status_code
FROM
system.access.audit
WHERE
action_name IN ("commandSubmit")
AND event_time >= current_date() - 1
ORDER BY
event_time DESC;
Billable Usage — system.billing.usage
retention : 365 days · 참고자료
계정 전체에서 청구 가능한 모든 사용량에 대한 기록을 저장한다. 리소스의 사용량을 시간별로 집계한 데이터다.
DBU를 USD로 계산하려면 system.billing.list_prices(SKU별 DBU당 USD 비용이 저장된 테이블)와 조인해서 계산해야 한다.
DBU를 USD 비용으로 환산하는 Python 코드
# 사용량 테이블 로드
usage = spark.read.table("system.billing.usage")
# 가격 정의 테이블 로드
prices = spark.read.table("system.billing.list_prices").filter("currency_code = 'USD'")
prices = prices.withColumn("coalesced_price_end_time", coalesce(col("price_end_time"), date_add(current_date(), 1)))
# 두 테이블을 조인하고 DBU를 USD 비용으로 계산
list_priced_usd = usage.join(
prices,
(usage.sku_name == prices.sku_name) &
(usage.usage_unit == prices.usage_unit) &
(usage.usage_end_time.between(prices.price_start_time, prices.coalesced_price_end_time)),
"left"
).select(
coalesce(col("usage_quantity") * col("pricing.effective_list.default"), lit(0)).alias("usage_usd"),
col("usage.*")
)
list_priced_usd.display()
샘플 쿼리 — 어떤 워크플로우가 가장 많은 DBU를 소비했나요?
SELECT
usage_metadata.job_id as `Job ID`, sum(usage_quantity) as `Usage`
FROM
system.billing.usage
WHERE
usage_metadata.job_id IS NOT NULL
GROUP BY
`Job ID`
ORDER BY
`DBUs` DESC
샘플 쿼리 — 특정 태그가 있는 리소스가 얼마나 많은 DBU를 소비했나요?
SELECT
sku_name, usage_unit, SUM(usage_quantity) as `Usage`
FROM
system.billing.usage
WHERE
custom_tags.{{key}} = "{{value}}"
GROUP BY 1, 2
Query History — system.query.history
retention : 90 days · 참고자료
SQL Warehouse에서 실행되는 모든 쿼리에 대한 레코드를 저장한다. 카탈로그 탐색기에서 SQL Warehouse를 연결해 UI에서 클릭한 동작도 쿼리로 생성되어 함께 저장된다.
샘플 쿼리 — 날짜별 누가 쿼리를 얼마나 실행했나요?
select date(start_time), executed_as, count(*)
from system.query.history
group by 1, 2
order by 1, 3
대시보드 예시
System 테이블을 활용해 만든 사내 대시보드 두 건이 있다.
- User Stats Dashboard — 워크스페이스 경로
/Workspace/de/Audit Log Dashboard (Databricks User Stats) - Usage Dashboard — 워크스페이스 경로
/Workspace/de/Databricks Usage Dashboard - ver. Notebook
원문의 화면 스크린샷은 옮기지 않았다. 실제 화면은 각 워크스페이스 경로에서 확인한다.
관련 문서
- Databricks 공식 문서 — System Tables 개요: https://docs.databricks.com/en/admin/system-tables/index.html
- 제공 테이블 전체 목록: https://docs.databricks.com/en/admin/system-tables/index.html#which-system-tables-are-available
- Audit Logs 참고자료: https://docs.databricks.com/en/admin/system-tables/audit-logs.html
- Billable Usage 참고자료: https://docs.databricks.com/en/admin/system-tables/billing.html
- Query History 참고자료: https://docs.databricks.com/en/admin/system-tables/query-history.html
- 과금 가능 사용량 로그 S3 전달: https://docs.databricks.com/en/admin/account-settings/billable-usage-delivery.html#deliver-and-access-billable-usage-logs