Api::V1::MeasurementsController#index (avg 1028ms, max 1028ms)
RCA: Api::V1::MeasurementsController#index Latency (1028ms)
Overview#
What Happened#
2026-05-27 03:32 UTC에 ap-southeast-2 리전의 cupixworks-api 서비스에서 MeasurementsController#index 엔드포인트가 1028ms의 응답 시간을 기록했다. 결과는 0건(빈 응답)이었음에도 불구하고 높은 지연이 발생했으며, DB 시간은 62ms에 불과해 약 964ms가 인증/미들웨어 계층에서 소비된 것으로 분석된다.
Quick Facts#
| Field | Value |
|---|---|
| resource_name | Api::V1::MeasurementsController#index |
| duration | 1028ms (DB: 62ms, View: 0.09ms, Serialization: 0ms) |
| top_frame | app/controllers/api/v1/measurements_controller.rb:14 |
| runtime | Ruby on Rails (Cognito auth) |
| deploy | production-ap-southeast-2-20260526t0527z0-dd7bd097-cupixworks |
| env | production, ap-southeast-2 |
Timeline#
- 2026-05-27T03:30:12Z — 동일 호스트(ip-10-1-145-251)에서 다른 엔드포인트(ReviewsController) 624ms 지연 발생
- 2026-05-27T03:32:10Z — MeasurementsController#index 요청 1028ms 기록 (review_key: qqgtdc, user: built.com.au)
- 2026-05-27T03:35:24Z — 동일 엔드포인트 다른 호스트에서 848ms 지연 (user: downer.co.nz)
- 2026-05-27T04:21:40Z — ap-southeast-2에서 다수의
Operation timed out after 10002 milliseconds에러 발생
Error Log#
{
"resource_name": "Api::V1::MeasurementsController#index",
"service": "cupixworks-api",
"occurrences": 1,
"avg_ms": 1028,
"max_ms": 1028,
"sample_trace_id": "2094942667927055673"
}
Impact#
- Service:
cupixworks-api - 발생 횟수: 1
- 최초 발생: 2026-05-27T03:32:08.760Z
- 최근 발생: 2026-05-27T03:32:08.760Z
Root Cause Summary#
ap-southeast-2 리전의 특정 호스트(ip-10-1-145-251)에서 인프라 수준의 일시적 성능 저하가 발생했다. 요청이 0건의 결과를 반환했음에도 1028ms가 소요된 이유는, DB 처리(62ms)와 직렬화(0ms)를 제외한 약 964ms가 Cognito 인증 검증(Cupix::Auth::Verification#verify_authenticated_request!) 및 before_action 필터 체인(set_review → ReviewRepository#show)에서 소비되었기 때문이다. 동일 호스트가 같은 시간대에 다른 컨트롤러에서도 지연을 보였고, 약 50분 후 리전 전체에서 타임아웃 에러가 발생한 점으로 볼 때, 이는 호스트 또는 리전 네트워크의 일시적 불안정에 의한 것이다.
Technical Analysis#
Code Path#
- Entry point:
app/controllers/api/v1/measurements_controller.rb:14 - Authentication:
app/controllers/concerns/verification_controller.rb:15-35 - Before action:
app/controllers/concerns/parameter_required.rb:27-29(set_review) - Search:
app/repositories/measurement_repository.rb:265-325 - Permission joins:
app/repositories/base_repository.rb:70-98
요청 처리 흐름:
- Cognito 인증 검증 — 외부 서비스 호출 포함
def authenticate!
if @cupix_auth_method == 'COGNITO'
begin
verification = Cupix::Auth::Verification.new(request: request)
response = verification.verify_authenticated_request!
rescue Cupix::Errors::Unauthorized => e
if %w[AUTH20000].include?(e.code) && authenticate_public_accessible_review_access == true
return
else
raise e
end
end
@current_user = response.user
@current_team = response.team
@session = response.session
Current.access_token = verification.access_token
else
legacy_authenticate!
end
end
이 단계에서 Cognito 토큰 검증을 위한 외부 네트워크 호출이 발생한다. 네트워크 지연이 있을 경우 수백 ms가 소비될 수 있다.
- set_review before_action — ReviewRepository 조회
def set_review
@review = ReviewRepository.new(current_user: current_user).show(params[:review_key])
end
review_key qqgtdc로 ReviewRepository#show를 호출하며, 내부적으로 permission_joins가 적용된다.
- MeasurementsController#index 실행 — Elasticsearch 검색 + SQL permission joins
def index
measurement_query_option = Cupix::QueryOption::Measurement.new(get_query_option, params)
measurements = repository_instance.search(measurement_query_option)
render_api Renderable.new({
search_result: measurements,
is_collection: true,
serializer_option: @serializer_option
})
end
- _search 내부에서 ReviewRepository 재조회
review = ReviewRepository.new(current_user: self.current_user).show(self.query_option.review_key)
raise Cupix::Errors::NotFound.new(code: 'ARG10000', reason: 'review not found') if review.blank?
facility = review.facility
set_review before_action과 _search 메서드 양쪽에서 ReviewRepository#show가 중복 호출된다. 각 호출은 permission_joins (11개 LEFT JOIN)를 포함한 복잡한 쿼리를 실행한다.
기대 동작: 빈 결과셋에 대해 100ms 이내 응답 실제 동작: 1028ms 소요, DB 62ms + 인증/미들웨어 964ms
Log Evidence#
사용한 Datadog 쿼리:
service:cupixworks-api resource_name:"Api::V1::MeasurementsController#index" @duration:>500ms env:production
핵심 로그 (일치하는 요청):
{
"timestamp": "2026-05-27T03:32:10.939Z",
"resource_name": "Api::V1::MeasurementsController#index",
"duration_ms": 1026.71,
"db_ms": 62.17,
"view_ms": 0.09,
"serialization_ms": 0,
"per_page": 100,
"page": 1,
"total_entries": 0,
"total_pages": 1,
"review_key": "qqgtdc",
"host": "ip-10-1-145-251.ap-southeast-2.compute.internal",
"user": "Ermias Wedajo (built.com.au)",
"team_id": 16,
"auth_method": "COGNITO"
}
동일 호스트의 다른 지연 요청:
2026-05-27T03:30:12.891Z - 624.97ms - review_key:vxoj2g (Cupix Support, team: mtpo-vida)
2026-05-27T03:32:10.939Z - 1026.71ms - review_key:qqgtdc (Ermias Wedajo, team: built)
약 50분 후 리전 타임아웃 에러:
2026-05-27T04:21:40Z - "Operation timed out after 10002 milliseconds with 0 bytes received"
- PanoRepository, Admin::EditingRepository, ElementTraceRepository
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | 호스트/리전 인프라 일시적 성능 저하 (Cognito 인증 네트워크 지연) | 동일 호스트에서 다수 컨트롤러 지연 발생, DB 62ms vs 총 1028ms (964ms gap), 50분 후 리전 전체 타임아웃 에러 | 단일 발생이라 패턴 확증 어려움 | Confirmed |
| H2 | N+1 쿼리 또는 DB 성능 이슈 | 코드에 permission_joins 11개 LEFT JOIN 존재 | DB 시간이 62ms로 전체의 6%에 불과, 결과 0건이므로 serialization 병목 없음 | Rejected |
| H3 | ReviewRepository 중복 호출로 인한 지연 | set_review + _search에서 ReviewRepository#show 2회 호출 확인 (코드 확인) | DB 시간 62ms에 두 쿼리 모두 포함됨, 주요 병목은 DB 외부 | Contributing factor |
| H4 | Ruby GC pause 또는 프로세스 경합 | 동일 호스트 다른 요청도 느림, 빈 결과에도 높은 지연 | GC pause는 보통 수십 ms 수준이며 964ms는 과도함 | Inconclusive |
Fix Recommendation#
즉시 조치 (Critical)#
- 현재 단일 발생(occurrence: 1)이며 인프라 일시적 이슈로 판단되어, 즉시 코드 수정은 불필요하다.
- 모니터링을 추가하여 패턴 반복 여부를 확인한다.
단기 개선 (1주 이내)#
app/repositories/measurement_repository.rb:280—_search내 ReviewRepository#show 중복 호출 제거.set_reviewbefore_action에서 이미 조회한@review를 재활용하도록 변경.app/controllers/concerns/verification_controller.rb:18-19— Cognito 인증 결과 캐싱 (동일 요청 내). 현재도 단일 요청이지만 미들웨어 간 중복 검증 방지.
장기 개선 (재발 방지)#
- Cognito 토큰 검증에 대한 로컬 캐싱 레이어 도입 (JWT 서명 검증은 로컬에서 수행 가능, JWKS 키를 주기적으로 갱신).
- ap-southeast-2 리전 호스트 상태 모니터링 강화 (특정 호스트에서 반복적 지연 발생 시 자동 드레인).
- ReviewRepository 중복 호출 패턴은 다른 컨트롤러에서도 공통적으로 존재할 수 있으므로 전체 리팩토링 검토.
Monitoring#
MeasurementsController#indexP95/P99 지연 시간 알림 (임계값: 500ms)- 호스트별 평균 응답 시간 이상 탐지
service:cupixworks-api resource_name:"Api::V1::MeasurementsController#index" @duration:>500ms env:production
Risk Assessment#
- Risk level: low
- 예상 복잡도: trivial
- 단일 발생이며 인프라 일시적 이슈로 확인됨. 코드 레벨 최적화(ReviewRepository 중복 호출 제거)는 선택적 개선 사항.