ES /docs

Api::V1::BimRevisionsController#create_bim_revision_upload_credentials (avg 1076ms, max 1076ms)

RCA: BimRevisionsController#create_bim_revision_upload_credentials Latency (1076ms)

Overview#

What Happened#

2026-05-26 04:47 UTC, ap-southeast-2 리전의 cupixworks-api에서 BimRevisionsController#create_bim_revision_upload_credentials 엔드포인트가 1076ms의 응답 시간을 기록했다. 정상 응답 시간(~120ms) 대비 약 9배 느린 성능이며, 특정 사용자(nathan.love@multiplex.global)에게 반복적으로 발생하는 패턴이다.

Quick Facts#

Field Value
resource_name Api::V1::BimRevisionsController#create_bim_revision_upload_credentials
top_frame app/services/cupix/storage_service.rb:138
env production, ap-southeast-2
deploy production-ap-southeast-2-20260526t0356z0-3e770a15-cupixworks
avg_duration 1076ms
db_time 8.15ms

Timeline#

  1. 2026-05-24 22:33 UTC — 동일 사용자에서 첫 slow request 관측 (1084ms, 1094ms)
  2. 2026-05-26 04:46:57 UTC — 795ms 응답 (같은 사용자, 다른 호스트)
  3. 2026-05-26 04:47:09 UTC — 1075ms 응답 기록, 클러스터 감지

Error Log#

Datadog Logs

json
{
  "resource_name": "Api::V1::BimRevisionsController#create_bim_revision_upload_credentials",
  "service": "cupixworks-api",
  "occurrences": 1,
  "avg_ms": 1076,
  "max_ms": 1076,
  "sample_trace_id": "338384434465347285"
}

Impact#

  • Service: cupixworks-api
  • 발생 횟수: 1 (클러스터 기준), 4건 (과거 포함)
  • 최초 발생: 2026-05-26T04:47:06.797Z
  • 최근 발생: 2026-05-26T04:47:06.797Z
  • 영향 범위: multiplex-global 팀의 BIM 파일 업로드 UX 저하 (사용자 대기 시간 증가)

Root Cause Summary#

create_bim_revision_upload_credentials 엔드포인트에서 AWS STS get_federation_token API를 호출하여 임시 업로드 자격증명을 생성하는데, 이 외부 API 호출이 ap-southeast-2 리전에서 약 800-1000ms의 지연을 발생시킨다. Aws::STS::Client가 매 요청마다 새로 생성되며(connection pooling 없음), 자격증명 결과도 캐싱되지 않아 모든 요청이 full round-trip을 수행한다. DB 시간은 8ms에 불과하므로 나머지 ~1050ms가 STS API 호출에 소비된다.

Technical Analysis#

Code Path#

  • Entry point: app/controllers/api/v1/bim_revisions_controller.rb:46
  • Repository delegation: app/repositories/bim_revision_repository.rb:92
  • Model method (state transition + credential 생성): app/models/concerns/bim_revision_result/s3.rb:40
  • Failure point (latency source): app/services/cupix/storage_service.rb:138client.get_federation_token(opts)

Controller action은 단순히 repository에 위임한다:

app/controllers/api/v1/bim_revisions_controller.rb:46-50ruby
def create_bim_revision_upload_credentials
  credentials = repository_instance.create_bim_revision_upload_credentials
  render_json 200, credentials
end

Repository에서 권한 확인 후 model 메서드를 호출한다:

app/repositories/bim_revision_repository.rb:92-96ruby
def create_bim_revision_upload_credentials
  raise Cupix::Errors::PermissionDenied... unless @model.updatable_by?(self.current_user)
  @model.bim_revision_upload_credentials
end

Model 메서드에서 state machine 전환 후 STS 호출을 수행한다:

app/models/concerns/bim_revision_result/s3.rb:40-49ruby
def bim_revision_upload_credentials
  self.uploading_bim_revision_state  # State machine -> DB save

  Cupix::StorageService.upload_credentials(
    storage_option: storage_option,
    id: id,
    bucket_name: storage_option.s3_hosting_bucket_name,
    key: bim_revision_basepath(bim_revision_upload_revision)
  )
end

핵심 지연 원인 — 매 요청마다 새 STS client를 생성하고 get_federation_token을 호출한다:

app/services/cupix/storage_service.rb:14-18ruby
def sts_client(storage_option: nil, **kwargs)
  opts = parse_storage_option(storage_option).merge(kwargs)
  Aws::STS::Client.new(opts)  # 매번 새 인스턴스 생성, connection pooling 없음
end
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
    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)  # <-- 800-1000ms 소요
    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

upload_credentials 메서드에서 token name에 Time.now.to_i를 사용하므로 캐싱이 불가능하다:

app/services/cupix/storage_service.rb:187-192ruby
token = get_credential_token(
  storage_option: storage_option,
  name: "#{Rails.env}-#{opts[:id]}-#{Time.now.to_i}",  # 매초 고유한 name
  policy: upload_credential_policy(opts[:bucket_name], opts[:key]),
  duration_seconds: expiration_in.to_i  # 4 hours
)

Log Evidence#

Datadog 쿼리로 동일 엔드포인트의 latency 패턴을 확인했다:

text
service:cupixworks-api resource_name:"Api::V1::BimRevisionsController#create_bim_revision_upload_credentials" env:production @http.status_code:200

slow request 로그 (nathan.love@multiplex.global):

json
{
  "timestamp": "2026-05-26T04:47:09.522Z",
  "duration_ms": 1074.94,
  "db_runtime_ms": 8.15,
  "host": "ip-10-1-17-211",
  "http_method": "POST",
  "path": "/api/v1/bim_revisions/4872/bim_revision_upload_credentials",
  "status": 200,
  "user": "nathan.love@multiplex.global",
  "team": "multiplex-global",
  "team_id": 157,
  "user_agent": "cupix-agent",
  "deploy": "production-ap-southeast-2-20260526t0356z0-3e770a15-cupixworks"
}

정상 request 비교 (다른 사용자, 같은 리전):

json
{
  "timestamp": "2026-05-25T22:46:43Z",
  "duration_ms": 125.31,
  "db_runtime_ms": 19.38,
  "host": "ip-10-1-145-251",
  "user": "isha.singh@naylorlove.com.au",
  "status": 200
}

패턴 분석:

  • nathan.love 요청: 795-1094ms (DB 8-21ms) — STS 호출에 ~780-1070ms 소요
  • 다른 사용자 요청: 93-133ms (DB 12-28ms) — STS 호출이 ~70-100ms로 정상적

이 차이는 multiplex-global 팀의 storage_option 설정이 STS 응답 시간에 영향을 미치는 것으로 추정된다 (IAM policy 크기, cross-account 설정, 또는 STS endpoint 거리).

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 AWS STS get_federation_token 호출이 특정 팀의 storage_option 설정에서 높은 지연 발생 DB time 8ms vs total 1076ms = 외부 호출에 ~1050ms 소요. 같은 리전의 다른 사용자는 120ms 정상. nathan.love만 반복적 slow (5/24, 5/26). STS client가 매번 새로 생성됨 (storage_service.rb:17) 같은 사용자도 가끔은 795ms (1076ms보다 낮음) — STS 응답 시간 변동성 Confirmed
H2 permission_joins의 복잡한 SQL 쿼리가 지연 원인 bim_revision_repository에 11개 LEFT JOIN 존재 DB runtime이 8-21ms로 매우 낮음. slow/normal 요청 모두 DB 시간 유사 Rejected
H3 Cognito get_user 인증 호출 지연 첫 요청 시 외부 호출 발생 가능 1시간 캐싱 적용됨. 해당 사용자는 연속 요청 중이므로 cache hit 확실 Rejected
H4 인프라 문제 (특정 호스트 성능 저하) slow request가 여러 호스트에서 발생 (ip-10-1-17-211, ip-10-1-145-251, ip-10-1-83-125) Rejected

Fix Recommendation#

즉시 조치 (Critical)#

  • 없음 — 이 latency는 기능적 오류가 아니며, 요청은 정상적으로 200 응답을 반환한다. 1076ms는 UX에 영향을 주지만 시스템 안정성에는 영향 없음.

단기 개선 (1주 이내)#

  • app/services/cupix/storage_service.rb:14-18: STS client를 singleton 또는 connection pool로 변경. 매 요청마다 새 TCP connection을 맺는 overhead를 제거.
  • app/services/cupix/storage_service.rb:187-192: credential 캐싱 도입. 동일 bim_revision_idstorage_option에 대해 token을 짧은 시간(예: 5분) 캐싱하여 연속 요청 시 STS 호출 회피. token name의 Time.now.to_i를 time bucket(5분 단위)으로 변경.

장기 개선 (재발 방지)#

  • multiplex-global 팀의 storage_option 설정 검토: cross-account access, IAM policy complexity 등이 STS 응답 시간에 영향을 줄 수 있으므로 팀별 storage 구성 감사.
  • APM에서 STS 호출을 별도 span으로 계측하여 리전별/팀별 STS latency를 가시화.
  • 클라이언트 측에서 credential 재사용 여부 확인 — cupix-agent가 매번 새 credential을 요청하는지, 기존 credential을 TTL 내에서 재사용하는지 점검.

Monitoring#

  • STS 호출 latency 추적:
text
service:cupixworks-api resource_name:"Api::V1::BimRevisionsController#create_bim_revision_upload_credentials" env:production @duration:>500ms
  • 팀별 latency 분포 알림:
text
avg(duration){service:cupixworks-api, resource_name:create_bim_revision_upload_credentials} by {team} > 500ms

Risk Assessment#

  • Risk level: low
  • 예상 복잡도: standard
  • 이유: 기능적 오류는 아님 (200 응답). UX 저하에 해당하며, STS client pooling/caching 추가는 기존 동작에 영향을 최소화하면서 개선 가능.