Передача настраиваемого прото-сообщения с помощью WithDetails () из пакета статуса gRPC

Недавно я экспериментировал с обработкой ошибок gRPC и хотел передать клиенту свое собственное прото-сообщение (определяющее мои собственные сведения об ошибке и внутренние коды ошибок). После поиска обнаружил пару примеров, которые используют WithDetails () в пакете статуса gRPC для прикрепления пользовательских метаданных. Я начал реализовывать то же самое следующим образом

сообщение протокола gRPC

message ErrorInfo {
    int64 error_code = 1;
    string error_message = 2;
    string resource_name = 3;
}

Реализация на стороне сервера

// Frame the error message
        st := status.New(codes.NotFound, "object not found")
        errInfo := &api.ErrorInfo {
            ErrorCode: 100,
            ErrorMessage: "Fetching credential failed",
            ResourceName: req.GetBackupLocation().GetCloudCredential(),
        }
        var err error
        st, err = st.WithDetails(errInfo)
        if err != nil {
            // If this errored, it will always error
            // here, so better panic so we can figure
            // out why than have this silently passing.
            panic(fmt.Sprintf("Unexpected error attaching metadata: %v", err))
        }

        return  st.Err()

Реализация на стороне клиента

fmt.Printf("line 76 err :%v", err)
                st := status.Convert(err)
                for _, detail := range st.Details() {
                    switch t := detail.(type) {
                    case *api.ErrorInfo:
                        fmt.Printf("error code: %v", t.GetErrorCode())
                        fmt.Printf("error msg: %v", t.GetErrorMessage())
                        fmt.Printf("resource name: %v", t.GetResourceName())
                    }
                }

Когда я запускаю код, он попадает в Panic (), добавленный в код сервера, что означает ошибку WithDetails ().

Для продолжения удалена паника на стороне сервера, когда этот клиент выдает следующую ошибку

:any: message type "" isn't linked inerror

Вопросов:

  • Работает ли WithDetails () только для стандартного определения прототипа gRPC googleapis / rpc / errdetails, а не с пользовательским прототипом?
  • Глядя на прото-файлы и реализацию кода, я не вижу ничего специфического для пакета gRPC errdetails.

  • Когда я попробовал использовать прото-сообщение из этого пакета, он работал нормально.

[Примечание: я использую gogo protobuf]

Может ли кто-нибудь сообщить, что мне здесь не хватает?


person pkumarn    schedule 20.04.2020    source источник
comment
Какую ошибку возвращает WithDetails?   -  person Peter    schedule 20.04.2020
comment
Удивительно, но я не вижу никаких ошибок, это null. Это как-то связано с gogo proto? Причина, по которой я спрашиваю об этом, заключается в том, что прото-файлы, сгенерированные в пакете errdetails, имеют дополнительные поля, такие как XXX_, но те, которые я сгенерировал, ничего не содержат. Что означает это сообщение об ошибке: тип сообщения не связан с ошибкой?   -  person pkumarn    schedule 20.04.2020
comment
Эта ошибка, вероятно, просто следствие того, что сервер делает странные вещи. Не обращайте на это внимания, пока сервер не заработает. Если %v форматируется как <nil>, но на самом деле ошибка не равна нулю, это, скорее всего, случай нулевых значений интерфейса . Я бы счел это ошибкой в ​​gogo / protobuf. Вместо этого попробуйте использовать глагол %T.   -  person Peter    schedule 20.04.2020
comment
1) Я пробовал% T, даже если он дал nil 2) Во-вторых, при поиске в Google я наткнулся на ссылку для пакета статуса grpc, в частности, мы используем gogo proto. Думал, попробую и попробовал этот пакет "github.com/gogo/status". Когда я использую это, кажется, что все работает. Я не совсем понимаю реализацию пакета.   -  person pkumarn    schedule 20.04.2020
comment
Пусть этот коммит https://github.com/gogo/status/commit/d60b5acac426cb52f7e28124c6aaa862d9f339f5 исправит проблемы, с которыми я столкнулся.   -  person pkumarn    schedule 20.04.2020


Ответы (2)


Я столкнулся с аналогичной ошибкой (any: message type "" isn't linked in *errors.errorString). В моем случае это произошло из-за grpc.Status API.

Если вы используете gogo proto, вам необходимо импортировать / использовать

"github.com/gogo/status"

Вместо того

"google.golang.org/grpc/status"

person Kishore Bandi    schedule 14.05.2020

С моей точки зрения, смешивание ошибок бизнес-логики с ошибками транспорта не следует рассматривать как хорошую практику, даже если GRPC API позволяет это. Добавление специальной структуры Result или Error к каждому ответу (с вашим собственным набором полей и кодов) - это гораздо более чистый и гибкий способ сообщить о состоянии обработки запроса.

person Vitaly Isaev    schedule 26.04.2020