강좌Apache Doris 해커톤자기 주도 과제 · 언제든 시작 · 등록 불필요

트랙 A · 과제 A3

로그 검색 탐색기

모든 작업을 SQL로 처리하는 작은 Kibana를 만들고 11:40에 결제가 실패한 원인을 찾아보세요.

  • 60~120분
  • 입문자 환영
  • 언어 자유 · CLI 또는 웹
  • AI 도구 사용 환영

막히는 부분이 있나요? 질문할 곳: #dev 참여할 곳: Apache Doris Slack. 유지 관리자와 다른 참가자가 도와드립니다.

1

환경 준비

만들 결과물과 Doris로 간단히 구현하는 이유를 알아보고 클러스터를 실행합니다.

만들 결과물

로그 탐색기를 만들고 장애 원인을 밝혀보세요.

200,000줄의 로그, 여섯 개 서비스, 장애가 발생한 어느 아침. BM25 순위로 키워드를 검색하고 서비스·수준·시간으로 필터링하며 건수를 집계합니다. 모두 Doris 테이블 하나에서 일반 SQL로 처리합니다.

다음 기능을 갖춘 작은 로그 탐색기:

  • 검색용 검색창 (키워드, 구문) 및 관련성 순위,
  • 필터 (서비스, 수준, 시간 범위),
  • 패싯 집계 (결과 옆에 서비스·수준별 건수 표시),
  • 선택적으로 다음 추가: 타임라인 (5분당 오류 수).

마지막으로 실제 조사를 수행합니다: 11:40에 결제가 실패하기 시작했습니다. 원인이 된 서비스는 무엇이며 실제 문제는 언제 시작됐나요? 탐색기에서 답을 명확히 찾을 수 있어야 합니다.

개략도만들 결과물 · 와이어프레임(스크린샷 아님)

개략도는 코드 패널 상단에 있습니다

Doris로 구현할 때의 장점

  • 같은 테이블에서 검색과 분석. 역색인이 키워드 쿼리를 처리하고 같은 WHERE 절을 다음에 사용합니다: GROUP BY 로 패싯을 집계합니다. 별도 시스템과 동기화할 필요가 없습니다.

  • 실제 관련성 순위. score() 가 결과를 BM25로 정렬하므로 최신 로그가 아니라 가장 관련 있는 로그가 먼저 나옵니다.

  • 저비용 필터. service 및 level 에는 각각 역색인이 있으며 시간 범위는 정렬 키로 가지치기합니다.

패널: 테이블 정의의 인덱스 부분

시작하기 전에

  • docker pull apache/doris:all-in-one-4.1.3
  • docker run -d --name doris -p 9030:9030 -p 8030:8030 -p 8040:8040 apache/doris:all-in-one-4.1.3
  • docker exec -it doris mysql -uroot -h127.0.0.1 -P9030
  • curl -LO https://github.com/morningman/demo-env/releases/download/for-hackathon/doris-hackathon-glasgow-2026.zip && unzip doris-hackathon-glasgow-2026.zip && cd doris-hackathon-glasgow-2026
호스트
127.0.0.1
포트
9030
사용자
root비밀번호 없음
데이터베이스
hackathon

데이터

hackathon.app_logs : 여섯 개 서비스를 테이블 하나에 저장합니다:

테이블hackathon.app_logs · sql
CREATE TABLE app_logs (  ts          DATETIME(3)  NOT NULL,  service     VARCHAR(32)  NOT NULL,   -- api-gateway, auth, catalog, search, checkout, payment  level       VARCHAR(8)   NOT NULL,   -- DEBUG / INFO / WARN / ERROR  host        VARCHAR(32),  trace_id    VARCHAR(32),  status      INT,                     -- HTTP status, when relevant  latency_ms  INT,  message     STRING       NOT NULL,  INDEX idx_msg (message) USING INVERTED PROPERTIES ("parser" = "english", "support_phrase" = "true"),  INDEX idx_service (service) USING INVERTED,  INDEX idx_level (level) USING INVERTED)DUPLICATE KEY(ts)DISTRIBUTED BY HASH(trace_id) BUCKETS 1PROPERTIES ("replication_num" = "1");

seed/a3_app_logs.sql 생성되는 데이터: 2026년 10월 13일의 로그 200,000줄 하나의 INSERT … SELECT … FROM numbers("number" = "200000") 로 생성합니다. 다운로드가 필요 없습니다. 이 데이터 어딘가에 장애 원인이 있습니다.

패널 → 테이블: 전체 테이블 정의

AI로 개발하기

AI 코딩 에이전트와 함께 개발하는 것을 권장합니다. Doris 4.x의 검색 및 AI 기능은 대부분의 모델 학습 데이터보다 최신이므로 SQL을 작성하기 전에 올바른 맥락을 제공하세요:

  1. 다음 컨텍스트 프롬프트 를 에이전트에 붙여 넣으세요.

  2. 참조할 곳을 안내하세요: 이 페이지에 나열된 참고 문서 및 AGENTS.md (스타터 키트 내). 많은 코딩 에이전트가 이 파일을 자동으로 읽습니다.

  3. 코드에 연결하기 전에 모든 SQL 문을 실행 중인 클러스터에서 직접 실행하게 하세요.

  4. 더 나아가 다음을 연결하세요: Doris MCP Server (참고: 과제 A2)를 연결하면 에이전트가 직접 스키마를 확인하고 쿼리를 테스트할 수 있습니다.

컨텍스트 프롬프트에이전트에 붙여 넣기
I'm building a log search explorer on Apache Doris 4.1 for a hackathon.Connection: MySQL protocol, 127.0.0.1:9030, user root, empty password, database `hackathon`.Use a plain MySQL driver and raw SQL.Table `app_logs`: ts DATETIME(3), service, level, host, trace_id, status INT, latency_ms INT,message STRING. Inverted indexes on message (english parser, phrase support), service, level.Doris SQL rules:1. Text search: `message MATCH_ANY 'a b'`, `MATCH_ALL`, `MATCH_PHRASE 'a b'`. Never LIKE.2. BM25: `score()` only with a MATCH_* predicate + `ORDER BY score() DESC LIMIT n`,   selected plain (`score() AS relevance`): no ROUND() or JOIN in that SELECT.   Bind the user's search text as a driver parameter.3. score() cannot be used with GROUP BY. For facet counts run a second query with the   same WHERE clause and GROUP BY service, level.4. Time buckets: `minute_floor(ts, 5)`.Build: search box, service/level/time filters, facet counts, and an error timeline.Run every SQL statement against the live cluster first.

AI 에이전트가 빠지기 쉬운 Doris 함정

TrapWhat to do instead
다음 사용: LIKE '%term%' 로 텍스트 검색col MATCH_ANY 'a b' (OR), MATCH_ALL (AND), MATCH_PHRASE 'a b' . 이들은 역색인을 사용합니다
다음 호출: score() 를 임의의 쿼리에서 사용score() 에 필요한 조건: MATCH_* 조건자를 다음 절에 지정: WHERE 및 ORDER BY score() DESC LIMIT n. 그렇지 않으면 Doris가 쿼리를 거부합니다
반올림, 조인 또는 순위 계산 대상: score() 를 같은 쿼리에서 수행다음은 그대로 유지하세요: score() AS relevance 를 단일 테이블 쿼리에서 그대로 사용하세요. 반올림, 조인 또는 ROW_NUMBER() 작업은 바깥 쿼리에서 수행하고, 다음 대신 하위 쿼리를 사용하세요: WITH CTE
score() 를 다음 안에서 사용: GROUP BY / 집계허용되지 않습니다. 패싯 집계에는 동일한 다음 조건을 재사용하세요: WHERE 제외: score()
ORM 사용일반 MySQL 드라이버와 직접 작성한 SQL을 권장합니다. ORM은 Doris가 지원하지 않는 문을 생성할 수 있습니다
2

구현하기

6 마일스톤, M0 → M5. 패널은 현재 읽는 단계를 따라갑니다.

  1. 마일스톤 05분

    로그 생성

    스타터 키트 폴더 안에서 실행하세요:

    M0 · 로그 생성bash
    docker exec -i doris mysql -uroot -h127.0.0.1 -P9030 < seed/a3_app_logs.sql
    확인 사항

    몇 초 후 표시: 200,000 줄의 로그, 시작: 00:00:00 종료: 23:59:59 (10월 13일).

  2. 마일스톤 115분

    BM25 키워드 검색

    M1 · BM25 키워드 검색sql
    USE hackathon;SELECT ts, service, level, message, score() AS relevanceFROM app_logsWHERE message MATCH_ANY 'timeout refused'ORDER BY relevance DESCLIMIT 20;

    검색창에 연결하세요. 사용자 입력은 드라이버 매개변수로 전달하세요(MATCH_ANY %s); a3/starter.py (스타터 키트 내)가 이 동작을 구현합니다.

    확인 사항

    20개 결과는 모두 connection refused 로그입니다. BM25는 드문 단어에 더 큰 가중치를 부여합니다: refused 는 68개 행에 등장하고, timeout 는 347개 행에 등장합니다. 다음 단어만 검색하면 timeout 나머지 결과도 볼 수 있습니다.

  3. 마일스톤 215분

    필터

    M2 · 필터sql
    SELECT ts, service, level, message, score() AS relevanceFROM app_logsWHERE message MATCH_ANY 'timeout'  AND level = 'ERROR'  AND service IN ('checkout', 'payment')  AND ts >= '2026-10-13 11:00:00' AND ts < '2026-10-13 12:30:00'ORDER BY relevance DESCLIMIT 20;
    확인 사항

    모든 결과는 timeout이 포함된 ERROR 로그입니다. 두 서비스 중 하나만 표시됩니다.

  4. 마일스톤 315분

    패싯 집계

    score() 는 집계할 수 없으므로 패싯 집계는 이를 제외한 동일한 필터를 사용합니다:

    M3 · 패싯 집계sql
    SELECT service, level, COUNT(*) AS hitsFROM app_logsWHERE message MATCH_ANY 'timeout'  AND ts >= '2026-10-13 11:00:00' AND ts < '2026-10-13 12:30:00'GROUP BY service, levelORDER BY hits DESC;
    확인 사항

    해당 시간대에 일치하는 로그는 163줄이며 모두 ERROR입니다. 집계 합계는 다음을 제외한 동일 검색 건수와 같아야 합니다: GROUP BY: 확인 명령어: SELECT COUNT(*) 및 같은 WHERE.

  5. 마일스톤 415분

    오류 타임라인

    M4 · 오류 타임라인sql
    SELECT minute_floor(ts, 5) AS bucket, service, COUNT(*) AS errorsFROM app_logsWHERE level = 'ERROR'  AND ts >= '2026-10-13 11:00:00' AND ts < '2026-10-13 12:30:00'GROUP BY bucket, serviceORDER BY bucket, service;
    확인 사항

    11:35부터 12:00 사이에 두 서비스의 오류가 급증합니다. 나머지 시간에는 어떤 서비스도 5분당 오류가 4건을 넘지 않습니다.

  6. 마일스톤 5

    장애 원인 파악

    탐색기로 다음에 답하세요: 결제 실패를 일으킨 서비스는 무엇이며 몇 시 몇 분에 시작됐나요? 답과 이를 입증하는 쿼리를 README에 적으세요.

3

완성하기

체크리스트를 확인하고 결과물을 공유한 뒤 배지를 받으세요.

완료 기준

체크리스트

제출하고 배지 받기

참여 → 제출 → 배지 받기.

  1. 다음 이름의 폴더에 결과물을 넣으세요: 본인의 GitHub ID. 코드와 README를 포함하고, README에 기능, 실행 방법, 스크린샷 또는 GIF 한 개, 사용한 Doris 기능을 적어주세요.

  2. 풀 리퀘스트 만들기 다음 위치에 추가하세요: morningman/demo-env 저장 경로: doris-hackathon-glasgow-2026/<your-github-id>/. 포크 후 push하거나 GitHub의 다음 기능을 사용하세요: Add file → Upload files. 그 외에 작성할 항목은 없습니다.

  3. 공유하기 공유할 곳: #dev 참여할 곳: Apache Doris Slack: 풀 리퀘스트 또는 저장소 링크와 함께 스크린샷이나 짧은 데모를 공유하세요. 질문, 제출, 배지 관련 안내는 모두 이곳에서 진행됩니다.

과제에 참여하는 모든 분께 다음 배지를 드립니다: Apache Doris Contributor 배지. Doris 프로젝트에 병합된 풀 리퀘스트가 없어도 됩니다. 마감일이 없으니 필요한 만큼 시간을 쓰세요. 팀 참여도 가능하지만 필수는 아닙니다. 모든 팀원의 GitHub ID를 다음에 적어주세요: README.

추가 도전 과제

  • 구문 검색 및 입력 자동 완성: MATCH_PHRASE 'connection refused', MATCH_PHRASE_PREFIX 로 입력 중 검색을 구현합니다.

  • 트레이스 보기: 로그 한 줄을 클릭하면 동일한 다음 값을 가진 모든 로그를 표시합니다: trace_id, 시간순으로 표시합니다.

  • 쿼리 문자열 검색: 다음을 사용해 보세요: SEARCH() DSL(Lucene 스타일의 field:term AND …). 참고: SEARCH 함수.

  • 실시간 로그 추적: 매초 몇 행을 삽입하고 자동으로 새로 고칩니다.

  • 인덱스 유무 비교: 비교 대상: MATCH_ANY 함께하는 LIKE '%timeout%' 를 전체 테이블에서 실행하고 소요 시간을 표시합니다.

문제 해결 및 참고 자료

SymptomFix
docker: command not found (macOS)Docker Desktop을 시작하세요. 이미 실행 중이면 CLI 링크를 연결하세요: sudo ln -s /Applications/Docker.app/Contents/Resources/bin/docker /usr/local/bin/docker
error getting credentials 이미지를 내려받을 때삭제할 항목: credsStore 필드가 있는 파일: ~/.docker/config.json (로컬 개발 환경에서만)
port is already allocated다른 프로세스(주로 다른 Doris)가 9030, 8030 또는 8040 포트를 사용 중입니다. 실행 중인 컨테이너를 확인하세요(docker ps), 또는 다른 호스트 포트를 노출하세요. 예: -p 19030:9030, 이 경우 19030에 연결하세요
The container name "/doris" is already in use이전에 실행한 적이 있습니다: docker start doris. 처음부터 다시 시작하려면 docker rm -f doris (데이터가 삭제됩니다)
컨테이너가 종료되거나 다음 상태로 바뀌지 않음: (healthy)확인: docker logs doris. 대개 메모리 문제입니다. Docker Desktop에 6 GB 이상을 할당하세요(Settings → Resources). Apple Silicon에서는 다음을 추가하지 마세요: --platform linux/amd64
permission denied: ./doris.sh압축 해제 도구가 실행 권한을 제거했습니다: chmod +x doris.sh, 또는 다음 실행: bash doris.sh start
Current database is not set실행: USE hackathon; 를 먼저 실행하거나 다음으로 연결하세요: -Dhackathon
score() function requires WHERE clause with MATCH function, ORDER BY and LIMIT다음 추가: MATCH_* 조건자, ORDER BY score() DESC 및 LIMIT그리고 다음을 유지하세요: score() 를 다른 식으로 감싸지 마세요(위의 함정 참고)
10분 이상 해결하지 못한 경우게시할 곳: #dev 참여할 곳: Apache Doris Slack

참고 자료

전문 검색BM25역색인SEARCH 함수

Apache Doris 해커톤

전체 과제

강좌로 돌아가기
  1. A160~120분하이브리드 검색 앱과제 개요 열기
  2. A245~90분MCP로 Doris에 질문하기과제 개요 열기
  3. A360~120분로그 검색 탐색기현재 위치
  4. A460~120분에이전트 트레이스 탐색기과제 개요 열기
  5. B30~60분트랙 B · 문서에서 데모로과제 개요 열기