이 가이드에서는 Data Manager API가 오류를 처리하고 전달하는 방법을 설명합니다. API 오류의 구조와 의미를 이해하는 것은 잘못된 입력부터 일시적인 서비스 사용 불가능에 이르기까지 문제를 원활하게 처리할 수 있는 강력한 애플리케이션을 빌드하는 데 매우 중요합니다.
데이터 관리자 API는 gRPC 상태 코드를 기반으로 하는 표준 Google API 오류 모델을 따릅니다. 오류가 발생하는 각 API 응답에는 다음이 포함된 Status 객체가 포함됩니다.
- 숫자 오류 코드입니다.
- 오류 메시지입니다.
- 선택사항인 추가 오류 세부정보입니다.
표준 오류 코드
데이터 관리자 API는 gRPC 및 HTTP로 정의된 표준 오류 코드 집합을 사용합니다. 이 코드는 오류 유형을 대략적으로 나타냅니다. 이 코드를 먼저 확인하여 문제의 근본적인 성격을 파악해야 합니다.
이러한 코드에 대한 자세한 내용은 API 디자인 가이드 - 오류 코드를 참고하세요.
오류 처리
요청이 실패하면 다음 단계를 따르세요.
오류 코드를 확인하여 오류 유형을 찾습니다.
- gRPC를 사용하는 경우 오류 코드는
Status의code필드에 있습니다. 클라이언트 라이브러리를 사용하는 경우 오류 코드에 해당하는 특정 유형의 예외가 발생할 수 있습니다. 예를 들어 오류 코드가INVALID_ARGUMENT인 경우 Java용 클라이언트 라이브러리는com.google.api.gax.rpc.InvalidArgumentException를 발생시킵니다. - REST를 사용하는 경우 오류 코드는
error.status의 오류 응답에 있고 해당 HTTP 상태는error.code에 있습니다.
- gRPC를 사용하는 경우 오류 코드는
오류 코드의 표준 세부정보 페이로드를 확인합니다. 표준 세부정보 페이로드는 Google API의 오류 메시지 집합입니다. 오류 세부정보를 구조화되고 일관된 방식으로 제공합니다. Data Manager API의 각 오류에는 여러 표준 세부정보 페이로드 메시지가 있을 수 있습니다. 데이터 관리 도구 API 클라이언트 라이브러리에는 오류에서 표준 세부정보 페이로드를 가져오는 도우미 메서드가 있습니다.
오류 코드와 관계없이
ErrorInfo,RequestInfo,Help,LocalizedMessage페이로드를 확인하고 로깅하는 것이 좋습니다.ErrorInfo에는 다른 페이로드에 없을 수 있는 정보가 있습니다.RequestInfo에는 요청 ID가 있어 지원팀에 문의해야 하는 경우에 유용합니다.Help및LocalizedMessage에는 오류를 해결하는 데 도움이 되는 링크와 기타 세부정보가 포함되어 있습니다.
또한
BadRequest,QuotaFailure,RetryInfo페이로드는 특정 오류 코드에 유용합니다.- 상태 코드가
INVALID_ARGUMENT인 경우BadRequest페이로드를 확인하여 오류를 일으킨 필드에 관한 정보를 확인합니다. - 상태 코드가
RESOURCE_EXHAUSTED인 경우QuotaFailure및RetryInfo페이로드에서 할당량 정보와 재시도 지연 권장사항을 확인합니다.
표준 세부정보 페이로드
Data Manager API의 가장 일반적인 표준 세부정보 페이로드는 다음과 같습니다.
BadRequest
요청이 INVALID_ARGUMENT (HTTP 상태 코드 400)로 실패할 때 BadRequest 페이로드를 확인합니다.
BadRequest 메시지는 요청에 잘못된 값이 있는 필드가 있거나 필수 필드의 값이 누락되었음을 나타냅니다. BadRequest에서 field_violations 목록을 확인하여 오류가 있는 필드를 찾습니다. 각 field_violations 항목에는 오류를 수정하는 데 도움이 되는 정보가 있습니다.
field카멜 표기법 경로 구문을 사용하는 요청의 필드 위치입니다.
경로가 목록의 항목 (
repeated필드)을 가리키는 경우 목록 이름 뒤에 대괄호 ([...])로 색인이 표시됩니다.예를 들어
destinations[0].operating_account.account_id은destinations목록의 첫 번째 항목의operating_account에 있는account_id입니다.description값이 오류를 일으킨 이유에 대한 설명입니다.
reasonINVALID_HEX_ENCODING또는INVALID_CURRENCY_CODE과 같은ErrorReasonenum입니다.
BadRequest의 예
BadRequest 메시지가 포함된 INVALID_ARGUMENT 오류의 샘플 응답은 다음과 같습니다. field_violations에는 숫자가 아닌 accountId 오류가 표시됩니다. field 값 destinations[0].login_account.account_id은 필드 위반이 있는 accountId이 destinations 목록의 첫 번째 항목의 login_account에 있음을 보여줍니다.
{
"error": {
"code": 400,
"message": "There was a problem with the request.",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "INVALID_ARGUMENT",
"domain": "datamanager.googleapis.com",
"metadata": {
"requestId": "t-a8896317-069f-4198-afed-182a3872a660"
}
},
{
"@type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "t-a8896317-069f-4198-afed-182a3872a660"
},
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "destinations[0].login_account.account_id",
"description": "String is not a valid number.",
"reason": "INVALID_NUMBER_FORMAT"
}
]
}
]
}
}
다음은 BadRequest 메시지가 포함된 INVALID_ARGUMENT 오류의 또 다른 샘플 응답입니다. 이 경우 field_violations 목록에 두 가지 오류가 표시됩니다.
첫 번째
event의 값이 이벤트의 두 번째 사용자 식별자에서 16진수로 인코딩되지 않았습니다.두 번째
event에는 이벤트의 세 번째 사용자 식별자에 16진수로 인코딩되지 않은 값이 있습니다.
{
"error": {
"code": 400,
"message": "There was a problem with the request.",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "INVALID_ARGUMENT",
"domain": "datamanager.googleapis.com",
"metadata": {
"requestId": "t-6bc8fb83-d648-4942-9c49-2604276638d8"
}
},
{
"@type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "t-6bc8fb83-d648-4942-9c49-2604276638d8"
},
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "events.events[0].user_data.user_identifiers[1]",
"description": "The HEX encoded value is malformed.",
"reason": "INVALID_HEX_ENCODING"
},
{
"field": "events.events[1].user_data.user_identifiers[2]",
"description": "The HEX encoded value is malformed.",
"reason": "INVALID_HEX_ENCODING"
}
]
}
]
}
}
QuotaFailure 및 RetryInfo
요청이 RESOURCE_EXHAUSTED (HTTP 상태 코드 429)로 실패할 때 QuotaFailure 및 RetryInfo 페이로드를 확인합니다.
QuotaFailure 메시지는 리소스가 소진되었거나(예: 할당량 초과) 시스템에 과부하가 걸렸음을 나타냅니다. violations 목록을 검사하여 초과된 할당량을 확인합니다.
오류에는 요청을 재시도하기 위해 권장되는 retry_delay를 나타내는 RetryInfo 메시지가 포함될 수도 있습니다.
RequestInfo
요청이 실패할 때마다 RequestInfo 페이로드를 확인합니다. RequestInfo에는 API 요청을 고유하게 식별하는 request_id가 포함됩니다.
{
"@type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "t-4490c640-dc5d-4c28-91c1-04a1cae0f49f"
}
오류를 로깅하거나 지원팀에 문의할 때는 문제 진단에 도움이 되도록 요청 ID를 포함하세요.
ErrorInfo
ErrorInfo 메시지를 확인하여 다른 표준 세부정보 페이로드에 포착되지 않을 수 있는 추가 정보를 가져옵니다. ErrorInfo 페이로드에는 오류에 관한 정보가 포함된 metadata 지도가 포함되어 있습니다.
예를 들어 Data Manager API가 사용 설정되지 않은 Google Cloud 프로젝트의 사용자 인증 정보를 사용하여 발생한 PERMISSION_DENIED 오류의 ErrorInfo는 다음과 같습니다. ErrorInfo는 다음과 같은 오류에 대한 추가 정보를 제공합니다.
metadata.consumer아래에 있는 요청과 연결된 프로젝트입니다.metadata.serviceTitle아래의 서비스 이름입니다.metadata.activationUrl에서 서비스를 사용 설정할 수 있는 URL입니다.
{
"error": {
"code": 403,
"message": "Data Manager API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.",
"status": "PERMISSION_DENIED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "SERVICE_DISABLED",
"domain": "googleapis.com",
"metadata": {
"consumer": "projects/PROJECT_NUMBER",
"service": "datamanager.googleapis.com",
"containerInfo": "PROJECT_NUMBER",
"serviceTitle": "Data Manager API",
"activationUrl": "https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER"
}
},
...
]
}
}
Help 및 LocalizedMessage
Help 및 LocalizedMessage 페이로드를 확인하여 오류를 이해하고 수정하는 데 도움이 되는 문서 링크와 현지화된 오류 메시지를 확인합니다.
예를 들어 Data Manager API가 사용 설정되지 않은 Google Cloud 프로젝트의 사용자 인증 정보를 사용하여 발생한 PERMISSION_DENIED 실패의 Help 및 LocalizedMessage는 다음과 같습니다. Help 페이로드에는 서비스를 사용 설정할 수 있는 URL이 표시되고 LocalizedMessage에는 오류에 대한 설명이 있습니다.
{
"error": {
"code": 403,
"message": "Data Manager API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.",
"status": "PERMISSION_DENIED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.LocalizedMessage",
"locale": "en-US",
"message": "Data Manager API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry."
},
{
"@type": "type.googleapis.com/google.rpc.Help",
"links": [
{
"description": "Google developers console API activation",
"url": "https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER"
}
]
},
...
]
}
}
액세스 오류 세부정보
클라이언트 라이브러리 중 하나를 사용하는 경우 도우미 메서드를 사용하여 표준 세부정보 페이로드를 가져옵니다.
.NET
try {
// Send API request
}
catch (Grpc.Core.RpcException rpcException)
{
Console.WriteLine($"Exception encountered: {rpcException.Message}");
var statusDetails =
Google.Api.Gax.Grpc.RpcExceptionExtensions.GetAllStatusDetails(
rpcException
);
foreach (var detail in statusDetails)
{
if (detail is Google.Rpc.BadRequest)
{
Google.Rpc.BadRequest badRequest = (Google.Rpc.BadRequest)detail;
foreach (
BadRequest.Types.FieldViolation? fieldViolation in badRequest.FieldViolations
)
{
// Access attributes such as fieldViolation!.Reason and fieldViolation!.Field
}
}
else if (detail is Google.Rpc.RequestInfo)
{
Google.Rpc.RequestInfo requestInfo = (Google.Rpc.RequestInfo)detail;
string requestId = requestInfo.RequestId;
// Log the requestId...
}
else if (detail is Google.Rpc.QuotaFailure)
{
Google.Rpc.QuotaFailure quotaFailure = (Google.Rpc.QuotaFailure)detail;
foreach (
Google.Rpc.QuotaFailure.Types.Violation violation in quotaFailure.Violations
)
{
// Access attributes such as violation.Subject and violation.QuotaId
}
}
else
{
// ...
}
}
}
자바
try {
// Send API request
} catch (com.google.api.gax.rpc.InvalidArgumentException invalidArgumentException) {
// Gets the standard BadRequest payload from the exception.
BadRequest badRequest = invalidArgumentException.getErrorDetails().getBadRequest();
for (int i = 0; i < badRequest.getFieldViolationsCount(); i++) {
FieldViolation fieldViolation = badRequest.getFieldViolations(i);
// Access attributes such as fieldViolation.getField() and fieldViolation.getReason()
}
// Gets the standard RequestInfo payload from the exception.
RequestInfo requestInfo = invalidArgumentException.getErrorDetails().getRequestInfo();
if (requestInfo != null) {
String requestId = requestInfo.getRequestId();
// Log the requestId...
}
} catch (com.google.api.gax.rpc.QuotaFailureException quotaFailureException) {
// Gets the standard QuotaFailure payload from the exception.
QuotaFailure quotaFailure = quotaFailureException.getErrorDetails().getQuotaFailure();
for (int i = 0; i < quotaFailure.getViolationsCount(); i++) {
QuotaFailure.Violation violation = quotaFailure.getViolations(i);
// Access attributes such as violation.getSubject() and violation.getQuotaId()
}
// Gets the standard RequestInfo payload from the exception.
RequestInfo requestInfo = quotaFailureException.getErrorDetails().getRequestInfo();
if (requestInfo != null) {
String requestId = requestInfo.getRequestId();
// Log the requestId...
}
} catch (com.google.api.gax.rpc.ApiException apiException) {
// Fallback exception handler for other types of ApiException.
...
}
오류 처리 권장사항
복원력이 있는 애플리케이션을 빌드하려면 다음 권장사항을 구현하세요.
- 오류 세부정보 검사
- 항상
BadRequest과 같은 표준 세부정보 페이로드 중 하나를 찾습니다. 각 표준 세부정보 페이로드에는 오류의 원인을 파악하는 데 도움이 되는 정보가 포함되어 있습니다. - 클라이언트 오류와 서버 오류 구분
오류가 구현 (클라이언트) 문제인지 API (서버) 문제인지 확인합니다.
- 클라이언트 오류:
INVALID_ARGUMENT,NOT_FOUND,PERMISSION_DENIED,FAILED_PRECONDITION,UNAUTHENTICATED과 같은 코드 이러한 오류에는 요청 또는 애플리케이션의 상태/사용자 인증 정보를 변경해야 합니다. 문제를 해결하지 않고 요청을 다시 시도하지 마세요. - 서버 오류:
UNAVAILABLE,INTERNAL,DEADLINE_EXCEEDED,UNKNOWN과 같은 코드입니다. API 서비스에 일시적인 문제가 있음을 나타냅니다.
- 클라이언트 오류:
- 재시도 전략 구현
오류를 다시 시도할 수 있는지 확인하고 다시 시도 전략을 사용합니다.
UNAVAILABLE,DEADLINE_EXCEEDED,INTERNAL,UNKNOWN,ABORTED과 같은 일시적인 서버 오류에 대해서만 다시 시도하세요.- 지수 백오프 알고리즘을 사용하여 재시도 간 대기 시간을 늘립니다. 이렇게 하면 이미 스트레스를 받고 있는 서비스에 과부하가 걸리지 않습니다. 예를 들어 1초, 2초, 4초 동안 기다리는 식으로 최대 재시도 횟수 또는 총 대기 시간까지 계속합니다.
- 많은 클라이언트가 동시에 재시도하는 'thundering herd' 문제를 방지하기 위해 백오프 지연에 작은 임의의 '지터'를 추가합니다.
- 철저하게 로깅
모든 표준 세부정보 페이로드, 특히 요청 ID를 포함한 전체 오류 응답을 로깅합니다. 이 정보는 필요한 경우 문제를 디버깅하고 Google 지원팀에 보고하는 데 필수적입니다.
- 사용자 의견 제공
표준 세부정보 페이로드의 코드와 메시지를 기반으로 애플리케이션 사용자에게 명확하고 유용한 의견을 제공합니다. 예를 들어 '오류가 발생했습니다'라고만 말하는 대신 '거래 ID가 누락되었습니다' 또는 '목적지의 계정 ID를 찾을 수 없습니다'라고 말할 수 있습니다.
이 가이드라인을 따르면 Data Manager API에서 반환된 오류를 효과적으로 진단하고 처리하여 더 안정적이고 사용자 친화적인 애플리케이션을 만들 수 있습니다.