Search code examples
iosswiftgraphqlapollo

Log Apollo iOS Client GraphQL query variables and url to console?


I would like to print the url of my Apollo iOS Client GraphQL queries to the Xcode console when the query is called.


Solution

  • Per the Apollo iOS Client docs, a logging interceptor can be added in a custom Interceptor Provider.

    I created a custom interceptor provider using the code from DefaultInterceptorProvider, and included the logging interceptor.

    import Apollo    
    
    class InterceptorProviderWithLogging: InterceptorProvider {
    
      private let client: URLSessionClient
      private let store: ApolloStore
      private let shouldInvalidateClientOnDeinit: Bool
    
      public init(client: URLSessionClient = URLSessionClient(),
              shouldInvalidateClientOnDeinit: Bool = true,
              store: ApolloStore) {
        self.client = client
        self.shouldInvalidateClientOnDeinit = shouldInvalidateClientOnDeinit
        self.store = store
      }
    
      deinit {
        if self.shouldInvalidateClientOnDeinit {
          self.client.invalidate()
        }
      }
    
      open func interceptors<Operation: GraphQLOperation>(for operation: Operation) -> [ApolloInterceptor] {
        return [
          MaxRetryInterceptor(),
          CacheReadInterceptor(store: self.store),
          RequestLoggingInterceptor(),        // added logging interceptor
          NetworkFetchInterceptor(client: self.client),
          ResponseCodeInterceptor(),
          JSONResponseParsingInterceptor(cacheKeyForObject: self.store.cacheKeyForObject),
          AutomaticPersistedQueryInterceptor(),
          CacheWriteInterceptor(store: self.store),
        ]
      }
    
      open func additionalErrorInterceptor<Operation: GraphQLOperation>(for operation: Operation) -> ApolloErrorInterceptor? {
        return nil
      }
    }
    
    class RequestLoggingInterceptor: ApolloInterceptor {
    
      func interceptAsync<Operation: GraphQLOperation>(
        chain: RequestChain,
        request: HTTPRequest<Operation>,
        response: HTTPResponse<Operation>?,
        completion: @escaping (Result<GraphQLResult<Operation.Data>, Error>) -> Void) {
                    
        if let url = try? request.toURLRequest().url?.absoluteString.removingPercentEncoding {
            if let variables = request.operation.variables {
                print("\(request.operation.operationName) parameters: \(variables) \(url)")
            } else {
                print("\(request.operation.operationName) \(url)")
            }
        }
        
        chain.proceedAsync(request: request, response: response, completion: completion)
      }
    }
    

    I use the custom interceptor provider in the Request Chain Network Transport.

    private(set) lazy var apolloClient: ApolloClient = {
    
      let store = ApolloStore()
      let interceptorProvider = InterceptorProviderWithLogging(store: store)
    
      let requestChainTransport = RequestChainNetworkTransport(
        interceptorProvider: interceptorProvider,
        endpointURL: url,
        additionalHeaders: [:],
        autoPersistQueries: false,
        requestBodyCreator: ApolloRequestBodyCreator(),
        useGETForQueries: true,
        useGETForPersistedQueryRetry: false
      )
    
      return ApolloClient(networkTransport: requestChainTransport, store: store)
    }()