Search code examples
javaspringspring-bootgraphqlgraphql-java

adding apollo tracing to GraphQL Spring


I'm trying to build GraphQL server using graphql-spring-boot-starter, and interested in Apollo tracing (https://github.com/apollographql/apollo-tracing) which add additional data under tracing key in extensions.

After I add the Tracing Instrumentation, there hasn't been any change to my response. Am i missing something here ?

request :

query getalllink{
  allLinks(filter:{description_contains:"ab"}){
    url,
    postedBy {
      id
    ,name
    }
  }
}

response :

{
  "data": {
    "allLinks": [
      {
        "url": "1a",
        "postedBy": {
          "id": "1",
          "name": "1"
        }
      }
    ]
  }

I've provide the TracingInstrumentation Bean. and the bean also picked up by the GraphQLWebAutoConfiguration.

I tried to debug and hit a breakpoint at GraphQLWebAutoConfiguration which the instrumentation has been added to GraphQLServlet bean.

Here is some detail info about my sample project:

@SpringBootApplication
public class DemographqlApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemographqlApplication.class, args);
    }

    @Bean
    Instrumentation instrumentation() {
        return new TracingInstrumentation();
    }

}

resources/graphql/schema.graphqls

schema {
    query: Query
}

type Query {
    allLinks: [Link]
}

type Link {
    id: ID!
    url: String!
    description: String
    postedBy: User
}

type User {
    id: ID!
    name: String!
}

Entity & Repository for User and Link

Resolver and Query Resolver :

@Component
public class LinkResolver implements GraphQLResolver<Link> {
    @Autowired
    private final UserRepository userRepository;

    LinkResolver(UserRepository userRepository) {
        this.userRepository = userRepository;
    }


    public User postedBy(Link link) {
        if (link.getUserId() == null) {
            return null;
        }
        return userRepository.findOne(link.getUserId());
    }
}

@Component
public class Query implements GraphQLQueryResolver {

    private final LinkRepository linkRepository;

    @Autowired
    public Query(LinkRepository linkRepository) {
        this.linkRepository = linkRepository;
    }

    public List<Link> allLinks() {
        return linkRepository.findAll());
    }
}

build.gradle:

dependencies {

    compile('org.springframework.boot:spring-boot-starter-web')
    testCompile('org.springframework.boot:spring-boot-starter-test')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile 'com.graphql-java:graphql-spring-boot-starter:3.10.0'
    compile 'com.graphql-java:graphql-java-tools:4.3.0'

    compile 'javax.xml.bind:jaxb-api:2.3.0'
    compile 'com.h2database:h2'

    // to embed GraphiQL tool
    compile 'com.graphql-java:graphiql-spring-boot-starter:3.10.0'


    compile 'org.springframework.boot:spring-boot-starter-data-jpa'

    // Use MySQL Connector-J
    compile 'mysql:mysql-connector-java'
}

Thank you.


Solution

  • I was facing the same issue today. I opened the source code to understand what's wrong.
    This issue is related to the version of graphql-java-servlet. Code snippet of GraphQLServlet.java for 4.6.0:

    final ExecutionResult executionResult = newGraphQL(schema).execute(new ExecutionInput(query, operationName, context, rootObject, transformVariables(schema, query, variables)));
    final List<GraphQLError> errors = executionResult.getErrors();
    final Object data = executionResult.getData();
    
    final String response = getMapper().writeValueAsString(createResultFromDataAndErrors(data, errors));
    

    executionResult contains the extensions (executionResult#getExtensions) so TracingInstrumentation did the job. But as you can see the response takes into account only data and errors (but no extensions). That's why the tracing instrumentation values are not added to the response.

    If you have a look to the branch master of graphql-java-servlet (https://github.com/graphql-java/graphql-java-servlet/blob/master/src/main/java/graphql/servlet/GraphQLServlet.java), you will see that extensions are taken into account. I don't know if this version has been released to maven central or not.

    In my project I used graphql-spring-boot-starter 3.10.0 and I just added the correct dependency in my gradle config :

        compile "com.graphql-java:graphql-java-servlet:4.7.0"
    

    Now it works: I can all tracing information in GraphiQL or better with GraphQL Plauyground 1.4.2

    Hope it helps