IT/Elasticsearch

[Elasticsearch] ELK 쿼리로 API 호출 건수 집계해보기 (+date_histogram, calendar_interval)

snapcoder 2024. 10. 17. 13:35
728x90
반응형
SMALL

[Elasticsearch] ELK쿼리로 API 호출 건수 집계해보기 (+Kibana Dev tools aggs field)
 
 
 
 

출처 https://dev.to/elastic/running-aggregations-with-elasticsearch-and-kibana-lni

 
 
 
 
 
 

Why

API 호출 추이를 Whatap 필터링으로도 확인 가능하나,
특정 조건을 걸거나, 집계를 하고싶어서
ELK 쿼리로 직접 작성해보았다.
https://www.whatap.io/

 

SaaS 모니터링 No.1 와탭 모니터링 | 와탭 | WhaTap

와탭으로 IT 서비스를 완성하세요. 클라우드 최적화. 15일간 무료 사용. 쉽고 빠른 설치. 특허로 인정받은 분석력. 통합 모니터링. 실시간 모니터링. 마이크로 아키텍처. 유연하고 안정적인 확장

whatap.io

 
 
 
 
 
 

내가 원했던 쿼리는

1. 메뉴 검색 API 관련, 호출 건수 집계
2. 시나리오 구분
     2.1 검색바에서 Enter 치는 경우 : "/api/common/v1/search-menu-list?*"
     2.2 검색바에서 입력값 변경되는 경우(interval로 작동) : "/api/common/v1/search-menu-list-by-typing?*"
3. 날짜 범위 설정
4. 실행 환경 구분 : prd, stage, dev, local
5. 주기별 집계 (일별/주별/월별/년별)

/* API 호출건수 조회 쿼리 (url별 환경별 날짜별) */
GET api-log-index/_search
{
  "size" : 0,
  "query": {
    "bool": {
      "should": [
        {
          "wildcard": {
            "request_uri": "/api/common/v1/search-menu-list-by-typing?*"
          }
        },
        {
          "wildcard": {
            "request_uri": "/api/common/v1/search-menu-list?*"
          }
        }
      ]
    }
  },
  "aggs": {
    "custom_field_1_timestamp": {
      "date_range": {
        "field": "@timestamp",
        "format":"yyyy-MM-dd-HH:mm:ss",
        "time_zone":"+09:00",
        "ranges": [
          {
            "from": "2024-09-01-00:00:00",
            "to": "2025-10-17-00:00:00"
          }
        ]
      },
      "aggs": {
        "custom_field_2_uri": {
          "terms": {
            "script": {
              "source": "def uri = doc['request_uri'].value; if (uri.startsWith('/api/common/v1/search-menu-list-by-typing?')){ return 'typing'; } else { return 'enter';}"
            },
            "min_doc_count": 1
          },
          "aggs": {
            "custom_field_3_env": {
              "terms": {
                "field": "fields.env"
              },
              "aggs": {
                "custom_field_4_day_count": {
                  "date_histogram": {
                    "field": "@timestamp",
                    "calendar_interval": "day"
                  }
                },
                "custom_field_5_week_count": {
                  "date_histogram": {
                    "field": "@timestamp",
                    "calendar_interval": "week"
                  }
                },
                "custom_field_6_month_count": {
                  "date_histogram": {
                    "field": "@timestamp",
                    "calendar_interval": "month"
                  }
                },
                "custom_field_7_year_count": {
                  "date_histogram": {
                    "field": "@timestamp",
                    "calendar_interval": "year"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

 
 
 

결과 분석

- 24년9월1일부터 ~ 24년10월17일 오늘까지
- 총 19055번의 메뉴API가 호출되었고
- 그중 타이핑이 약 1만번, 타이핑 후 엔터동작이 약 9천번 발생. (천번정도는 타이핑 후 enter를 치지 않았다는 뜻)
- 24년10월15일날 오후늦게 API url을 수정했기 때문에, day_count가 15일부터 시작.

/* 결과 */
{
  "took": 54,
  "timed_out": false,
  "_shards": {
    "total": 6,
    "successful": 6,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 10000,
      "relation": "gte"
    },
    "max_score": null,
    "hits": []
  },
  "aggregations": {
    "custom_field_1_timestamp": {
      "buckets": [
        {
          "key": "2024-09-01-00:00:00-2025-10-17-00:00:00",
          "from": 1725116400000,
          "from_as_string": "2024-09-01-00:00:00",
          "to": 1760626800000,
          "to_as_string": "2025-10-17-00:00:00",
          "doc_count": 19055,
          "custom_field_2_uri": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "typing",
                "doc_count": 10036,
                "custom_field_3_env": {
                  "doc_count_error_upper_bound": 0,
                  "sum_other_doc_count": 0,
                  "buckets": [
                    {
                      "key": "prd",
                      "doc_count": 10036,
                      "custom_field_5_week_count": {
                        "buckets": [
                          {
                            "key_as_string": "2024-10-14T00:00:00.000Z",
                            "key": 1728864000000,
                            "doc_count": 10036
                          }
                        ]
                      },
                      "custom_field_6_month_count": {
                        "buckets": [
                          {
                            "key_as_string": "2024-10-01T00:00:00.000Z",
                            "key": 1727740800000,
                            "doc_count": 10036
                          }
                        ]
                      },
                      "custom_field_4_day_count": {
                        "buckets": [
                          {
                            "key_as_string": "2024-10-15T00:00:00.000Z",
                            "key": 1728950400000,
                            "doc_count": 170
                          },
                          {
                            "key_as_string": "2024-10-16T00:00:00.000Z",
                            "key": 1729036800000,
                            "doc_count": 8568
                          },
                          {
                            "key_as_string": "2024-10-17T00:00:00.000Z",
                            "key": 1729123200000,
                            "doc_count": 1298
                          }
                        ]
                      },
                      "custom_field_7_year_count": {
                        "buckets": [
                          {
                            "key_as_string": "2024-01-01T00:00:00.000Z",
                            "key": 1704067200000,
                            "doc_count": 10036
                          }
                        ]
                      }
                    }
                  ]
                }
              },
              {
                "key": "enter",
                "doc_count": 9019,
                "custom_field_3_env": {
                  "doc_count_error_upper_bound": 0,
                  "sum_other_doc_count": 0,
                  "buckets": [
                    {
                      "key": "prd",
                      "doc_count": 9019,
                      "custom_field_5_week_count": {
                        "buckets": [
                          {
                            "key_as_string": "2024-10-14T00:00:00.000Z",
                            "key": 1728864000000,
                            "doc_count": 9019
                          }
                        ]
                      },
                      "custom_field_6_month_count": {
                        "buckets": [
                          {
                            "key_as_string": "2024-10-01T00:00:00.000Z",
                            "key": 1727740800000,
                            "doc_count": 9019
                          }
                        ]
                      },
                      "custom_field_4_day_count": {
                        "buckets": [
                          {
                            "key_as_string": "2024-10-15T00:00:00.000Z",
                            "key": 1728950400000,
                            "doc_count": 136
                          },
                          {
                            "key_as_string": "2024-10-16T00:00:00.000Z",
                            "key": 1729036800000,
                            "doc_count": 7763
                          },
                          {
                            "key_as_string": "2024-10-17T00:00:00.000Z",
                            "key": 1729123200000,
                            "doc_count": 1120
                          }
                        ]
                      },
                      "custom_field_7_year_count": {
                        "buckets": [
                          {
                            "key_as_string": "2024-01-01T00:00:00.000Z",
                            "key": 1704067200000,
                            "doc_count": 9019
                          }
                        ]
                      }
                    }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

 
 
 

고도화 포인트

API url을 기준으로
호출 시간대나, 호출 건수, 딥하게는 파라미터까지 분석이 가능하고
이를 활용할 수도 있을 것 같다.
 
예를들면 다음과 같다.
- 갑작스럽게 호출 건수 급증 => 대용량 트래픽 감지
- 관리 목록에 없는 url 포함 => 비정상접근 알림 발송
- 특정 호출건 추적
- 특정 시간대 건수 알림 => 정기적 모니터링 수행
 
ex.
(트래픽 집중 시간대에만) 짧은 집계 주기 적용 (초/분/시 단위) => 1초에 1000건 이상 api 호출되는 경우 => 카카오톡,SMS,팀즈 등 Alert 발송

 
 
 
 

 

 

 

+ 날짜 동적 필터링

ex. 어제 23시59분59초까지의 데이터만 필터

GET api-log-index/_search
{
  "size": 0,
  "query": {
		// 비즈니스 로직
  },
  "aggs": {
    "custom_field_1_timestamp": {
      "date_range": {
        "field": "@timestamp",
        "format": "yyyy-MM-dd-HH:mm:ss",
        "time_zone": "+09:00",
        "ranges": [
          {
            "from": "1970-01-01-00:00:00",  	// 대과거
            "to": "now-1d/d+23h+59m+59s"        // 어제 23시 59분 59초
          }
        ]
      }
    }
  }
}
728x90
반응형
LIST