ES /docs

Api::V1::CapturesController#create_voxels_upload_credentials (avg 1203ms, max 1203ms)

RCA: Api::V1::CapturesController#create_voxels_upload_credentials Latency (1203ms)

Overview#

What Happened#

2026-05-27 06:00:43 UTC에 us-west-2 리전의 cupixworks-api 서비스에서 POST /api/v1/captures/:id/voxels_upload_credentials 엔드포인트가 1203ms 응답 시간을 기록했다. 이는 APM latency threshold(500ms)를 초과한 것으로 감지되었으나, 에러 없이 HTTP 200으로 정상 응답했다.

Quick Facts#

Field Value
resource_name Api::V1::CapturesController#create_voxels_upload_credentials
top_frame app/services/cupix/storage_service.rb:138
env production, us-west-2
avg_duration 1203ms
HTTP status 200 (정상 응답)

Timeline#

  1. 2026-05-27T06:00:43.572Z — APM에서 1203ms latency span 감지
  2. 2026-05-27T15:41:56Z — RCA 분석 시작

Error Log#

Datadog Logs

text
{
  "resource_name": "Api::V1::CapturesController#create_voxels_upload_credentials",
  "service": "cupixworks-api",
  "occurrences": 1,
  "avg_ms": 1203,
  "max_ms": 1203,
  "sample_trace_id": "144056515843903871"
}

Impact#

  • Service: cupixworks-api
  • 발생 횟수: 1
  • 최초 발생: 2026-05-27T06:00:43.572Z
  • 최근 발생: 2026-05-27T06:00:43.572Z

이 엔드포인트는 voxel 업로드 전 클라이언트가 AWS 임시 자격 증명을 요청하는 용도로, 응답 지연은 업로드 시작 시점을 늦출 수 있으나 기능적 장애를 유발하지는 않는다.

Root Cause Summary#

이 latency는 Cupix::StorageService.get_credential_token 메서드 내에서 AWS STS get_federation_token API를 동기적으로 호출하기 때문에 발생한다. AWS STS API 호출은 네트워크 왕복 시간을 포함하여 통상 800~1200ms가 소요되며, 이는 이 엔드포인트의 구조적 특성이다. 생성된 자격 증명에 대한 캐싱 메커니즘이 없어 매 요청마다 STS API를 호출한다.

Technical Analysis#

Code Path#

  • Entry point: app/controllers/concerns/voxels_controller.rb:27
  • Repository layer: app/repositories/concerns/voxels_repository.rb:27
  • Model layer: app/models/concerns/voxel_module/s3.rb:28
  • Failure point (latency source): app/services/cupix/storage_service.rb:138
  1. Controller에서 repository_instance.create_voxels_upload_credentials 호출:
app/controllers/concerns/voxels_controller.rb:27-31ruby
def create_voxels_upload_credentials
  credentials = repository_instance.create_voxels_upload_credentials

  render_json 200, credentials
end
  1. Repository에서 권한 확인 후 모델 메서드 호출:
app/repositories/concerns/voxels_repository.rb:27-31ruby
def create_voxels_upload_credentials(params = {})
  raise Cupix::Errors::PermissionDenied.new(code: 'PERM10000', reason: 'Permission denied') unless @model.updatable_by?(self.current_user)

  @model.voxels_upload_credentials
end
  1. Model에서 상태 전환(DB write) + STS 자격 증명 생성:
app/models/concerns/voxel_module/s3.rb:28-37ruby
def voxels_upload_credentials
  self.uploading_voxel_state

  Cupix::StorageService.upload_credentials(
    storage_option: storage_option,
    id: id,
    bucket_name: storage_option.s3_hosting_bucket_name,
    key: voxels_basepath(voxels_upload_revision)
  )
end
  1. 핵심 latency 원인upload_credentials에서 get_credential_token 호출 후 AWS STS API를 동기적으로 실행:
app/services/cupix/storage_service.rb:181-192ruby
def upload_credentials(storage_option: nil, **kwargs)
  opts = parse_storage_option(storage_option).merge(kwargs)
  check_required_params(opts, %i[id region bucket_name key])

  expiration_in = opts[:expiration_in] || 4.hour
  expires_at = expiration_in.from_now
  token = get_credential_token(
    storage_option: storage_option,
    name: "#{Rails.env}-#{opts[:id]}-#{Time.now.to_i}",
    policy: upload_credential_policy(opts[:bucket_name], opts[:key]),
    duration_seconds: expiration_in.to_i
  )
  1. AWS STS 동기 호출 (1000~1200ms 소요):
app/services/cupix/storage_service.rb:122-145ruby
def get_credential_token(storage_option: nil, **kwargs)
  client = sts_client(storage_option: storage_option)
  opts = kwargs
  opts[:duration_seconds] ||= 7200

  check_required_params(opts, %i[policy name duration_seconds])

  begin
    # NOTE: MinIO doesn't support get_federation_token
    if storage_option.bucket_type == 'minio'
      opts[:role_arn] = 'arn:xxx:xxx:xxx:xxxx'
      opts[:role_session_name] = opts[:name]
      opts.delete(:name)

      resp = client.assume_role(opts)
    else
      resp = client.get_federation_token(opts)  # <-- 주요 latency 원인
    end
  rescue StandardError => e
    raise Cupix::Errors::System.new(code: 'SYS20000', reason: "Can't create temporary token", message: e.message)
  else
    resp.credentials
  end
end

기대 동작: 클라이언트가 voxel 업로드를 위한 임시 자격 증명을 빠르게 받아야 함. 실제 동작: AWS STS get_federation_token 호출이 ~1000-1200ms 소요되어 전체 응답 시간이 1203ms로 측정됨. 이는 AWS STS API의 정상적인 응답 시간 범위이며, 코드 버그가 아닌 구조적 특성.

Log Evidence#

Datadog에서 동일 시간대 해당 엔드포인트 로그를 검색한 결과, 모든 요청이 HTTP 200으로 정상 응답했고 에러는 없었다.

text
service:cupixworks-api "create_voxels_upload_credentials"
Time range: 2026-05-27T05:00:00Z to 2026-05-27T07:00:00Z

대표 로그 항목:

text
[200] POST /api/v1/captures/41190/voxels_upload_credentials (Api::V1::CapturesController#create_voxels_upload_credentials)
[200] POST /api/v1/captures/41203/voxels_upload_credentials (Api::V1::CapturesController#create_voxels_upload_credentials)
[200] POST /api/v1/captures/73365/voxels_upload_credentials (Api::V1::CapturesController#create_voxels_upload_credentials)

에러 로그 검색:

text
service:cupixworks-api status:error "CapturesController"
Time range: 2026-05-27T05:00:00Z to 2026-05-27T07:00:00Z
Result: 0 logs (에러 없음)

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 AWS STS get_federation_token API 호출의 네트워크 latency가 주요 원인 코드 경로에서 유일한 외부 API 호출 (storage_service.rb:138). AWS STS는 통상 800-1200ms 소요. 1203ms는 이 범위 내. Confirmed
H2 DB state transition (uploading_voxel_state)이 latency 유발 s3.rb:29에서 DB write 발생. DB write는 통상 5-20ms. 1203ms 중 극히 일부만 차지. 에러도 없음. Rejected
H3 STS client 초기화(Aws::STS::Client.new)에서 과도한 시간 소요 storage_service.rb:17에서 매 요청마다 새 client 생성 (pooling 없음). Client 초기화는 통상 10-30ms. 전체 latency의 주요 원인이 되기 어려움. Rejected

Fix Recommendation#

즉시 조치 (Critical)#

  • 없음 — 1203ms latency는 AWS STS API의 정상 응답 시간 범위이며, 에러 없이 정상 동작 중. occurrence_count가 1건이므로 즉시 조치는 불필요.

단기 개선 (1주 이내)#

  • APM latency threshold 조정 고려: 이 엔드포인트는 AWS STS 호출이 필수적이므로 500ms threshold가 적절하지 않음. resource-specific threshold를 1500ms 이상으로 올리거나, 이 endpoint를 latency 모니터링 예외 목록에 추가하는 방안 검토.
  • STS Client 재사용: storage_service.rb:14-18에서 매 요청마다 Aws::STS::Client.new를 호출하고 있음. Thread-safe한 client pool을 적용하면 10-30ms 절약 가능.

장기 개선 (재발 방지)#

  • 임시 자격 증명 캐싱: 동일 capture에 대한 반복 요청 시, TTL 내 기존 자격 증명을 재사용하는 캐싱 레이어 도입 (Redis/in-memory). duration_seconds: 4.hours이므로 캐시 TTL을 3.5시간으로 설정하면 안전하게 재사용 가능.
  • Pre-signed URL 방식 전환: STS federation token 대신 S3 pre-signed URL을 사용하면 서버 측 서명만으로 완료되어 외부 API 호출 없이 ~10ms 이내 응답 가능. 단, 업로드 구조 변경이 필요.

Monitoring#

  • APM에서 이 resource의 p95/p99 latency 추이를 추적하여, STS latency가 지속적으로 증가하는지 확인:
text
avg:trace.rack.request.duration{service:cupixworks-api,resource_name:api_v1_captures_create_voxels_upload_credentials} by {availability-zone}
  • STS 호출 실패율 모니터:
text
service:cupixworks-api "SYS20000" "Can't create temporary token"

Risk Assessment#

  • Risk level: low
  • 예상 복잡도: trivial — 이는 코드 버그가 아닌 AWS STS API의 정상적인 latency 특성. 발생 건수가 1건이며 기능적 영향 없음. Latency threshold 조정이나 false-positive 필터링으로 해결 가능.