QGrpcClientInterceptor logging example | Qt GRPC 6.8.0

- Qt 6.8
- Qt GRPC
- QGrpcClientInterceptor logging example
- Qt 6.8.0 Reference Documentation

# QGrpcClientInterceptor logging example

## Logging Interceptor

The Logging Interceptor can be a versatile tool for gaining insights into your Qt GRPC requests. By creating a custom interceptor, you can tailor the logging behavior to meet the specific requirements of your application.

## Creating a Logging Interceptor

To create a Logging Interceptor, you'll need to subclass QGrpcClientInterceptor and override the appropriate interception method(s) to incorporate the logging functionality.

### Prerequisites

To establish what types can be processed by our interceptor, let's say our .proto file is:

     syntax = "proto3";

     message SimpleStringMessage {
         string testFieldString = 6;
     }

     service TestService {
         rpc testMethod(SimpleStringMessage) returns (SimpleStringMessage) {}
         rpc testMethodServerStream(SimpleStringMessage) returns (stream SimpleStringMessage) {}
     }

### LoggingInterceptor implementation

Here's an example of a simple Logging Interceptor:

     class LoggingInterceptor : public QGrpcClientInterceptor
     {
     protected:
         void interceptCall(std::shared_ptr<QGrpcChannelOperation> operation,
                                                       std::shared_ptr<QGrpcCallReply> response,
                                                       QGrpcInterceptorContinuation<QGrpcCallReply> &continuation) override
         {
             // Log an outgoing requests here
             SimpleStringMessage requestArg;
             if (!operation->serializer()->deserialize(&requestArg, operation->arg())) {
                 qError() << "Deserialization of arg failed.";
                 return;
             }
             qDebug() << "Request sent:" << requestArg.testFieldString();

             continuation(std::move(response), operation);

             // Intercept the response
             auto responsePtr = response.get();
             QObject::connect(responsePtr, &QGrpcServerStream::messageReceived, responsePtr,
                             [responsePtr]{
                                 const auto mess = responsePtr->read<SimpleStringMessage>();
                                 if (!mess)
                                     qDebug() << "Failed deserialization";
                                 qDebug() << "Response received:" << mess->testFieldString();
                             });
         }

         void interceptServerStream(std::shared_ptr<QGrpcChannelOperation> operation,
                                                       std::shared_ptr<QGrpcServerStream> stream,
                                                       QGrpcInterceptorContinuation<QGrpcServerStream> &continuation) override
         {
             // Intercept the response
             QObject::connect(stream.get(), &QGrpcServerStream::messageReceived, this,
                                  [stream] {
                                     if (const auto mess = responsePtr->read<SimpleStringMessage>())
                                         qDebug() << "Response received:" << mess->testFieldString();
                                  });

             // Log incoming and outgoing requests here
             SimpleStringMessage requestArg;
             if (!operation->serializer()->deserialize(&requestArg, operation->arg())) {
                 qError() << "Deserialization of arg failed.";
                 return;
             }
             qDebug() << "Request sent:" << requestArg.testFieldString();
             continuation(std::move(response), operation);
         }
     };

The LoggingInterceptor overrides two interception methods: QGrpcClientInterceptor::interceptCall and QGrpcClientInterceptor::interceptServerStream. Each of these methods handles a specific type of Qt GRPC interaction: Unary call and server streaming, respectively. Because QGrpcChannelOperation stores the argument in the serialized form, both methods need to deserialize the request, which can then be logged using `qDebug()`.

Use QObject::connect to subscribe to the QGrpcCallReply::finished or QGrpcServerStream::messageReceived signals and log the response.

## Registering the Logging Interceptor

Next, you'll need to register the Logging Interceptor with the QGrpcClientInterceptorManager. This ensures that it becomes part of the interceptor chain.

     QGrpcClientInterceptorManager manager;
     std::shared_ptr<LoggingInterceptor> loggingInterceptor = std::make_shared<LoggingInterceptor>();
     manager.registerInterceptor(loggingInterceptor);