Skip to content

로그

로그는 L1 스택의 Loki 절반입니다. 메트릭과 같은 데이터 플레인 형태를 따릅니다: edge 가 HTTPS 로 Loki 에 직접 push, 매니저는 쿼리만.

데이터 플레인

text
edge:
  ongrid-edge agent
    └─ plugin: promtail (subprocess)
        ├─ tails /var/log/syslog, /var/log/messages, journald
        └─ remote write HTTPS → loki:3100

                                     ▼ /loki/api/v1/query_range
                              ┌───────────────┐
                              │  manager:     │
                              │   - alert     │
                              │   - LLM tools │
                              └───────────────┘

ADR-015 플러그인 런타임

promtail 은 edge 에이전트의 플러그인 런타임 아래 서브 프로세스로 실행. 에이전트가 생명주기 감독 — 크래시 시 재시작, 셧다운 시 드레인, 에이전트와 같은 systemd journal 에 로그. 운영자 관점에서 두 개가 아닌 한 systemd 서비스.

이전 대안 ("promtail 을 정적 링크 Go 라이브러리로 벤더링") 은 모든 Loki 클라이언트 업그레이드가 edge 에이전트 재릴리스를 강제하기 때문에 거부됨. 서브 프로세스가 분리합니다.

구성

Edge 별 promtail 설정은 서버 측에서 biz/edge/plugin_config.go 가 렌더링하며 플러그인 시작 시 컨트롤 터널을 통해 푸시. 관리자가 URL 을 바꾸면 에이전트 재빌드 없이 전파되도록 system_settings.loki.url 참조.

기본 tail 셋:

SourceLoki 레이블
/var/log/syslog, /var/log/messagesjob=node-syslog, host=<edge-name>
systemd journald (모든 unit)job=systemd-journal, host=<edge-name>, unit=<svc>

커스텀 tail 은 SPA 의 /edges/<id>/logs/sources 페이지로 추가 — 같은 system_settings.loki.* 네임스페이스에 쓰임.

데이터 플레인 분할

ADR-014: 텔레메트리는 직접, 컨트롤은 터널 경유. 로그의 경우:

  • promtail HTTPS POST → loki:3100/loki/api/v1/push (직접).
  • ✅ Loki HTTPS GET ← 매니저 /loki/api/v1/query_range (직접).
  • ❌ 로그는 geminio 컨트롤 터널을 통과하지 않음.

이유: 터널은 in-process 멀티플렉서; 통해 로그 버스트를 파이프하면 인제스트가 스파이크할 때 컨트롤 RPC (RCA 도구 호출, WebSSH I/O) 가 굶주림. 데이터 플레인 분리가 noisy-neighbour 문제를 고치고 nginx 가 두 절반에 대해 공개 표면 (TLS, rate limiting, 인증) 을 균일하게 소유하게 합니다.

알림 kind

두 로그 구동 규칙 kind — 둘 다 Phase-B, 둘 다 evaluators_phaseB.go 에.

log_match

count_over_time(<stream_selector> |~ <line_filter> [window]) <op> threshold 가 최소 하나의 매트릭스 엔트리를 반환할 때 발화.

json
{
  "kind": "log_match",
  "scope_type": "global",
  "conditions_json": {
    "stream_selector": "{job=\"systemd-journal\",unit=\"nginx.service\"}",
    "line_filter": "(?i)5\\d{2}",
    "window": "5m",
    "operator": ">=",
    "threshold": 50
  }
}

line_filter 는 선택 — 비어 있으면 규칙은 스트림의 모든 라인을 카운트. 쿼리는 매 틱마다 rules.go:733compileLogMatchRule 가 빌드.

log_volume

v1 에서 log_match 와 같은 엔진 (현재 윈도우 카운트 vs 절대 임계값). 스펙의 원래 "이전 윈도우 대비 비율" 의미는 보류 — 두 LogQL 쿼리 + Go 측 나눗셈 필요; 절대 형태가 이미 일반적 "로그가 N 을 넘어 스파이크" 사용 사례를 커버.

스펙 컬럼은 ratio_op / ratio_threshold (호환성을 위해 유지); 컴파일러가 이를 operator / threshold 로 매핑.

도구

search_logs / query_logql

LLM 대면 로그 검색. 두 등록 경로가 하나의 executor 를 가리킴:

  • query_logql — 원시 LogQL 통과. Persona 가 어떤 스트림을 쿼리할지 정확히 알 때 investigator worker 가 사용.
  • search_logs — 채팅 UI 의 Quick Actions 에 노출된 더 친근한 래퍼, 자유 텍스트 쿼리 + 서비스 이름 받음.

스키마 + executor 는 query_logql_basetool.go. 기반 클라이언트: internal/pkg/logquery.

둘 다 전역 ONGRID_LOG_QUERY_URL 환경 (기본 http://loki:3100) 을 존중하고 edge 가 push 에 사용하는 같은 nginx 레이어에서 인증을 상속.

host_tail_file

기능 측 로그 프로브 — 매니저가 아닌 edge 에서 실행. Loki 인제스트 뷰 대신 원시 파일 (예: journald 에 없는 /var/log/ongrid-edge.log) 이 필요할 때 사용. ScopeHost; edge_id 필요. 디스패치 모델은 기능 참고.

같이 보기