Grafana에서 Minecraft 로그를 INFO/WARN/ERROR로 분리하기 (Data Stream + Pipeline + Kafka Connect)

2026. 2. 14. 15:47k8s

Minecraft 로그를 Grafana에서 보는데 message만 존재해 INFO/WARN/ERROR로 그룹핑이 불가능했다.
즉, “레벨별 로그 수”를 대시보드로 만들 수 없는 상태였다.
해결 목표는 log.level 필드를 실제로 저장해 Grafana에서 레벨별 집계를 가능하게 만드는 것이었다.

또한 로그가 장기적으로 쌓이므로 Data Stream으로 전환
ILM/자동 롤오버가 동작하도록 운영 안정성을 높였다.
(일반 인덱스는 롤오버/보관 정책을 수동 관리해야 함)


1) 데이터 흐름

  • Filebeat → Kafka → Kafka Connect → Elasticsearch (Data Stream)

2) 왜 Data Stream으로 바꿨나?

  • 일반 인덱스는 롤오버/보관을 수동 관리해야 한다.
  • Data Stream은 ILM과 자동 롤오버가 기본 동작한다.
  • 장기 로그 운영에는 Data Stream이 더 안정적이다.

3) Kafka Connect 설정 변경

Data Stream 전환으로 커넥터 설정도 변경이 필요했다.
(자세한 변경 방법은 아래 글 참고)


4) Ingest Pipeline로 log.level 생성

PUT _ingest/pipeline/minecraft
{
  "description": "Extract log level from minecraft log message",
  "processors": [
    {
      "script": {
        "lang": "painless",
        "source": """
          if (ctx.containsKey('message') && ctx.message != null) {
            def msg = ctx.message;
            if (msg.contains('/ERROR')) { ctx['log'] = ctx.getOrDefault('log', [:]); ctx.log.level = 'ERROR'; }
            else if (msg.contains('/WARN')) { ctx['log'] = ctx.getOrDefault('log', [:]); ctx.log.level = 'WARN'; }
            else if (msg.contains('/INFO')) { ctx['log'] = ctx.getOrDefault('log', [:]); ctx.log.level = 'INFO'; }
          }
        """
      }
    }
  ]
}

5) Index Template에 default_pipeline 적용

Kafka Connect에서 pipeline 전달이 안정적이지 않아
ES 템플릿에 default_pipeline을 강제 적용했다.

PUT _index_template/minecraft-logs-template
{
  "index_patterns": ["minecraft-logs*"],
  "data_stream": {},
  "template": {
    "settings": {
      "index.lifecycle.name": "minecraft-logs-ilm",
      "index.lifecycle.rollover_alias": "minecraft-logs",
      "index.default_pipeline": "minecraft"
    },
    "mappings": {
      "properties": {
        "message": {
          "type": "text",
          "fields": {
            "keyword": { "type": "keyword", "ignore_above": 1024 }
          }
        }
      }
    }
  }
}

6) 롤오버 (권한 필요)

템플릿 변경은 새 인덱스부터 적용되므로 롤오버가 필요하다.
이 작업은 관리 권한이 필요하므로 관리자 계정으로 실행해야 한다.
(kafka-connect 계정에는 롤오버 권한이 없음)

POST minecraft-logs/_rollover

7) 적용 확인

GET minecraft-logs/_search
{
  "size": 5,
  "sort": [{"@timestamp": "desc"}],
  "_source": ["@timestamp","message","log.level"]
}

log.level이 보이면 성공.


8) Grafana 설정

  • Group by → Termslog.level
  • INFO / WARN / ERROR로 깔끔하게 분리됨