Erros do Google Distributed Cloud air-gapped

Este capítulo fornece uma vista geral do modelo de erro para as APIs do Google Distributed Cloud air-gapped (GDC). Também fornece orientações gerais aos programadores sobre como gerar e tratar corretamente os erros.

As APIs GDC usam um modelo de erro simples independente do protocolo, o que nos permite oferecer uma experiência consistente em diferentes APIs, diferentes protocolos de API (como gRPC ou HTTP) e diferentes contextos de erro (como erros assíncronos, em lote ou de fluxo de trabalho).

Modelo de erro

O modelo de erro para as APIs GDC é definido logicamente por google.rpc.Status, uma instância da qual é devolvida ao cliente quando ocorre um erro da API. O fragmento do código seguinte mostra a estrutura geral do modelo de erro:

package google.rpc;

// The `Status` type defines a logical error model that is suitable for
// different programming environments, including REST APIs and RPC APIs.
message Status {
  // A simple error code that can be easily handled by the client. The
  // actual error code is defined by `google.rpc.Code`.
  int32 code = 1;

  // A developer-facing human-readable error message in English. It should
  // both explain the error and offer an actionable resolution to it.
  string message = 2;

  // Additional error information that the client code can use to handle
  // the error, such as retry info or a help link.
  repeated google.protobuf.Any details = 3;
}

Uma vez que a maioria das APIs Google usa um design de API orientado para recursos, o processamento de erros segue o mesmo princípio de design usando um pequeno conjunto de erros padrão com um grande número de recursos. Por exemplo, em vez de definir diferentes tipos de erros "não encontrado", o servidor usa um código de erro google.rpc.Code.NOT_FOUND padrão e indica ao cliente que recurso específico não foi encontrado. O espaço de erro mais pequeno reduz a complexidade da documentação, permite melhores mapeamentos idiomáticos nas bibliotecas de cliente e reduz a complexidade da lógica do cliente sem restringir a inclusão de informações acionáveis.

Códigos de erro

As APIs GDC têm de usar os códigos de erro canónicos definidos por google.rpc.Code. As APIs individuais têm de evitar a definição de códigos de erro adicionais, uma vez que é muito improvável que os programadores escrevam lógica para processar um grande número de códigos de erro. Para referência, o processamento de uma média de três códigos de erro por chamada da API significaria que a maioria da lógica da aplicação seria apenas para o processamento de erros, o que não seria uma boa experiência para o programador.

Mensagens de erro

A mensagem de erro deve ajudar os utilizadores a compreender e resolver o erro da API de forma fácil e rápida. Em geral, considere as seguintes diretrizes ao escrever mensagens de erro:

  • Não assuma que o utilizador é um utilizador especialista da sua API. Os utilizadores podem ser programadores de clientes, pessoas das operações, pessoal de TI ou utilizadores finais de apps.
  • Não assuma que o utilizador sabe algo sobre a implementação do seu serviço ou que está familiarizado com o contexto dos erros (como a análise de registos).
  • Sempre que possível, as mensagens de erro devem ser criadas de forma que um utilizador técnico (mas não necessariamente um programador da sua API) possa responder ao erro e corrigi-lo.
  • Mantenha a mensagem de erro breve. Se necessário, forneça um link onde um leitor confuso possa fazer perguntas, dar feedback ou obter mais informações que não se enquadrem claramente numa mensagem de erro. Caso contrário, use o campo de detalhes para expandir.

Detalhes do erro

As APIs GDC definem um conjunto de payloads de erro padrão para detalhes de erros, que pode encontrar em google/rpc/error_details.proto. Estes abrangem as necessidades mais comuns para erros de API, como falhas de quota e parâmetros inválidos. Tal como os códigos de erro, os programadores devem usar estes payloads padrão sempre que possível.

Os tipos de detalhes de erros adicionais só devem ser introduzidos se puderem ajudar o código da aplicação a processar os erros. Se as informações de erro só puderem ser processadas por humanos, baseie-se no conteúdo da mensagem de erro e deixe que os programadores as processem manualmente, em vez de introduzir tipos de detalhes de erros adicionais.

Seguem-se alguns exemplos de payloads error_details:

  • ErrorInfo: fornece informações de erro estruturadas que são estáveis e extensíveis.
  • RetryInfo: descreve quando os clientes podem tentar novamente um pedido falhado, podendo ser devolvido em Code.UNAVAILABLE ou Code.ABORTED
  • QuotaFailure: descreve como falhou uma verificação de quota, podendo ser devolvida em Code.RESOURCE_EXHAUSTED
  • BadRequest: descreve violações num pedido de cliente e pode ser devolvido em Code.INVALID_ARGUMENT

Informações do erro

ErrorInfo é um tipo especial de payload de erro. Fornece informações de erro estáveis e extensíveis nas quais os humanos e as aplicações podem confiar. Cada ErrorInfo tem três informações: um domínio de erro, um motivo do erro e um conjunto de metadados de erro. Para mais informações, consulte a definição de ErrorInfo.

Para as APIs GDC, o domínio de erro principal é googleapis.com e os motivos de erro correspondentes são definidos pela enumeração google.api.ErrorReason. Para mais informações, consulte a definição de google.api.ErrorReason.

Localização de erros

O campo message em google.rpc.Status é apresentado aos programadores e tem de estar em inglês.

Se for necessária uma mensagem de erro visível para o utilizador, use google.rpc.LocalizedMessage como campo de detalhes. Embora o campo de mensagem em google.rpc.LocalizedMessage possa ser localizado, certifique-se de que o campo de mensagem em google.rpc.Status está em inglês.

Por predefinição, o serviço de API deve usar o local do utilizador autenticado ou o cabeçalho HTTP Accept-Language ou o parâmetro language_code no pedido para determinar o idioma para a localização.

Mapeamento de erros

As APIs GDC são acessíveis em diferentes ambientes de programação. Normalmente, cada ambiente tem a sua própria forma de processar erros. As secções seguintes explicam como o modelo de erro é mapeado em ambientes usados frequentemente.

Mapeamento HTTP

Embora as mensagens proto3 tenham uma codificação JSON nativa, a plataforma da API GDC usa um esquema de erros diferente para as APIs HTTP JSON da GDC por motivos de compatibilidade com versões anteriores.

Esquema:

// This message defines the error schema for GDC JSON HTTP APIs.
message Error {
  // Deprecated. This message is only used by error format v1.
  message ErrorProto {}
  // This message has the same semantics as `google.rpc.Status`. It uses HTTP
  // status code instead of gRPC status code. It has extra fields `status` and
  // `errors` for backward compatibility with [GDC API Client
  // Libraries](https://developers.google.com/api-client-library).
  message Status {
    // The HTTP status code that corresponds to `google.rpc.Status.code`.
    int32 code = 1;
    // This corresponds to `google.rpc.Status.message`.
    string message = 2;
    // Deprecated. This field is only used by error format v1.
    repeated ErrorProto errors = 3;
    // This is the enum version for `google.rpc.Status.code`.
    google.rpc.Code status = 4;
    // This corresponds to `google.rpc.Status.details`.
    repeated google.protobuf.Any details = 5;
  }
  // The actual error payload. The nested message structure is for backward
  // compatibility with [GDC API Client
  // Libraries](https://developers.google.com/api-client-library). It also
  // makes the error more readable to developers.
  Status error = 1;
}

Exemplo:

{
  "error": {
    "code": 400,
    "message": "API key not valid. Please pass a valid API key.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "API_KEY_INVALID",
        "domain": "googleapis.com",
        "metadata": {
          "service": "translate.googleapis.com"
        }
      }
    ]
  }
}

Mapeamento gRPC

Os diferentes protocolos RPC mapeiam o modelo de erro de forma diferente. Para o gRPC, o modelo de erro é suportado nativamente pelo código gerado e pela biblioteca de tempo de execução em cada idioma suportado. Pode saber mais na documentação da API gRPC. Por exemplo, consulte o io.grpc.Status do gRPC Java.

Mapeamento da biblioteca cliente

As bibliotecas cliente da GDC podem optar por apresentar erros de forma diferente por idioma para serem consistentes com as expressões idiomáticas estabelecidas. Por exemplo, a biblioteca google-cloud-go devolve um erro que implementa a mesma interface que google.rpc.Status, enquanto google-cloud-java gera uma exceção.

Processar erros

A tabela seguinte contém todos os códigos de erro gRPC definidos em google.rpc.Code e uma breve descrição da respetiva causa. Para processar um erro, pode verificar a descrição do código de estado devolvido e modificar a chamada em conformidade.

HTTP gRPC Descrição
200 OK Sem erros.
400 INVALID_ARGUMENT O cliente especificou um argumento inválido. Verifique a mensagem de erro e os detalhes do erro para mais informações.
400 FAILED_PRECONDITION Não é possível executar o pedido no estado atual do sistema, como eliminar um diretório não vazio.
400 OUT_OF_RANGE O cliente especificou uma alteração inválida.
401 UNAUTHENTICATED Pedido não autenticado devido a token OAuth em falta, inválido ou expirado.
403 PERMISSION_DENIED O cliente não tem autorização suficiente. Isto pode acontecer porque o token OAuth não tem os âmbitos certos, o cliente não tem autorização ou a API não foi ativada.
404 NOT_FOUND Não foi possível encontrar um recurso especificado.
409 ABORTED Conflito de simultaneidade, tal como conflito de ler-modificar-gravar.
409 ALREADY_EXISTS O recurso que um cliente tentou criar já existe.
429 RESOURCE_EXHAUSTED Sem quota de recursos ou a atingir a limitação de velocidade. O cliente deve procurar o detalhe do erro google.rpc.QuotaFailure para mais informações.
499 CANCELLED Pedido cancelado pelo cliente.
500 DATA_LOSS Perda de dados irrecuperável ou corrupção de dados. O cliente deve comunicar o erro ao utilizador.
500 UNKNOWN Erro de servidor desconhecido. Normalmente, trata-se de um erro do servidor.
500 INTERNAL Erro interno do servidor. Normalmente, trata-se de um erro do servidor.
501 NOT_IMPLEMENTED Método de API não implementado pelo servidor.
502 N/A Ocorreu um erro de rede antes de alcançar o servidor. Normalmente, uma indisponibilidade ou uma configuração incorreta da rede.
503 UNAVAILABLE Serviço indisponível. Normalmente, o servidor está inativo.
504 DEADLINE_EXCEEDED Prazo do pedido excedido. Isto só acontece se o autor da chamada definir um prazo mais curto do que o prazo predefinido do método (ou seja, o prazo pedido não é suficiente para o servidor processar o pedido) e o pedido não terminar dentro do prazo.

Atualizar rascunhos com erros

Os clientes podem tentar novamente em erros 503 UNAVAILABLE com retirada exponencial. O atraso mínimo deve ser de 1 s, salvo indicação em contrário. A repetição de novas tentativas predefinida deve ser uma vez, salvo indicação em contrário.

Para erros 429 RESOURCE_EXHAUSTED, o cliente pode tentar novamente ao nível superior com um atraso mínimo de 30 segundos. As novas tentativas só são úteis para tarefas em segundo plano de longa duração.

Para todos os outros erros, a repetição pode não ser aplicável. Primeiro, certifique-se de que o seu pedido é idempotente e consulte google.rpc.RetryInfo para obter orientações.

Propague erros

Se o seu serviço de API depender de outros serviços, não deve propagar cegamente erros desses serviços aos seus clientes. Ao traduzir erros, sugerimos o seguinte:

  • Oculte detalhes de implementação e informações confidenciais.
  • Ajuste a parte responsável pelo erro. Por exemplo, um servidor que recebe um erro INVALID_ARGUMENT de outro serviço deve propagar um erro INTERNAL ao seu próprio autor da chamada.

Reproduza erros

Se não conseguir resolver os erros através da análise dos registos e da monitorização, deve tentar reproduzir os erros com um teste simples e repetível. Pode usar o teste para recolher mais informações para a resolução de problemas, que pode fornecer quando contactar o apoio técnico.

Recomendamos que use oauth2l e curl -v e parâmetros do sistema para reproduzir erros com as APIs GDC. Em conjunto, podem reproduzir quase todos os pedidos da API GDC e fornecer informações de depuração detalhadas. Para mais informações, consulte as páginas de documentação respetivas da API que está a chamar.

Gerar erros

Se for um programador de servidores, deve gerar erros com informações suficientes para ajudar os programadores de clientes a compreender e resolver o problema. Ao mesmo tempo, tem de estar ciente da segurança e privacidade dos dados do utilizador e evitar a divulgação de informações confidenciais na mensagem de erro e nos detalhes do erro, uma vez que os erros são frequentemente registados e podem ser acessíveis a outras pessoas. Por exemplo, uma mensagem de erro como "O endereço IP do cliente não está na lista de autorizações 128.0.0.0/8" expõe informações sobre a política do lado do servidor, que podem não estar acessíveis ao utilizador que tem acesso aos registos.

Para gerar erros adequados, primeiro tem de conhecer o google.rpc.Code para escolher o código de erro mais adequado para cada condição de erro. Uma aplicação de servidor pode verificar várias condições de erro em paralelo e devolver a primeira.

A tabela seguinte lista cada código de erro e um exemplo de uma boa mensagem de erro.

HTTP gRPC Exemplo de mensagem de erro
400 INVALID_ARGUMENT O campo de pedido x.y.z é xxx, esperava-se um de [yyy, zzz].
400 FAILED_PRECONDITION O recurso xxx é um diretório não vazio, pelo que não pode ser eliminado.
400 OUT_OF_RANGE O parâmetro "age" está fora do intervalo [0, 125].
401 UNAUTHENTICATED Credenciais de autenticação inválidas.
403 PERMISSION_DENIED Autorização "xxx" recusada no recurso "yyy".
404 NOT_FOUND Não foi encontrado o recurso "xxx".
409 ABORTED Não foi possível adquirir o bloqueio no recurso "xxx".
409 ALREADY_EXISTS O recurso "xxx" já existe.
429 RESOURCE_EXHAUSTED Limite de quota "xxx" excedido.
499 CANCELLED Pedido cancelado pelo cliente.
500 DATA_LOSS Ver nota.
500 UNKNOWN Ver nota.
500 INTERNAL Ver nota.
501 NOT_IMPLEMENTED Método "xxx" não implementado.
503 UNAVAILABLE Ver nota.
504 DEADLINE_EXCEEDED Ver nota.

Payloads de erro

O pacote google.rpc define um conjunto de payloads de erro padrão, que são preferíveis aos payloads de erro personalizados. A tabela seguinte apresenta cada código de erro e a respetiva carga útil de erro padrão, se aplicável. Recomendamos que as aplicações avançadas procurem estes payloads de erro em google.rpc.Status quando processam erros.

HTTP gRPC Detalhes do erro recomendados
400 INVALID_ARGUMENT google.rpc.BadRequest
400 FAILED_PRECONDITION google.rpc.PreconditionFailure
400 OUT_OF_RANGE google.rpc.BadRequest
401 UNAUTHENTICATED google.rpc.ErrorInfo
403 PERMISSION_DENIED google.rpc.ErrorInfo
404 NOT_FOUND google.rpc.ResourceInfo
409 ABORTED google.rpc.ErrorInfo
409 ALREADY_EXISTS google.rpc.ResourceInfo
429 RESOURCE_EXHAUSTED google.rpc.QuotaFailure
499 CANCELLED
500 DATA_LOSS google.rpc.DebugInfo
500 UNKNOWN google.rpc.DebugInfo
500 INTERNAL google.rpc.DebugInfo
501 NOT_IMPLEMENTED
503 UNAVAILABLE google.rpc.DebugInfo
504 DEADLINE_EXCEEDED google.rpc.DebugInfo