Skip to content

Profiler: 4 of 9 interface methods have no call sites (v25.0 / master) #4366

@Apelsinka223

Description

@Apelsinka223

Describe the bug
The Profiler interface declares 9 methods. In graphql-java-25.0 and on master as of today, 4 of them have zero call sites anywhere in the graphql-java codebase:

  • Profiler.dataLoaderUsed(String) (line)
  • Profiler.batchLoadedOldStrategy(String, int, int) (line)
  • Profiler.batchLoadedNewStrategy(String, Integer, int, boolean, boolean) (line)
  • Profiler.manualDispatch(String, int, int) (line)

That results in Profiler not collecting data relevant to dataloaders usage and ProfilerResult.getDataLoaderLoadInvocations and ProfilerResult.getDispatchEvents always return empty result.

To Reproduce

// Compile & run with graphql-java 25.0 and java-dataloader 6.0.0 on the classpath.
// Expected output:
//   dataLoaderChainingEnabled=true
//   dataLoaderLoadInvocations={}      <-- BUG: empty (Profiler.dataLoaderUsed never called)
//   dispatchEvents=[]                 <-- BUG: empty (batchLoadedNewStrategy/batchLoadedOldStrategy/manualDispatch never called)
//   oldStrategyDispatchingAll=[...]   <-- non-empty only if chaining=false (the one wired DataLoader-related event)
//   fieldsFetched=[/users, /users[*]/name]   <-- this works; demonstrates the Profiler is hooked up

import graphql.ExecutionInput;
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.ProfilerResult;
import graphql.execution.instrumentation.dataloader.DataLoaderDispatchingContextKeys;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import org.dataloader.BatchLoader;
import org.dataloader.DataLoader;
import org.dataloader.DataLoaderFactory;
import org.dataloader.DataLoaderRegistry;

import java.util.List;
import java.util.concurrent.CompletableFuture;

public final class ProfilerUnwiredReproducer {

    private static final String SDL = """
        type Query { users: [User!]! }
        type User { id: ID!, name: String! }
        """;

    public static void main(String[] args) {
        final boolean chaining = args.length == 0 || !args[0].equals("--no-chaining");

        // 1. Schema with one DataLoader-backed field.
        final BatchLoader<String, String> nameLoader =
            keys -> CompletableFuture.completedFuture(keys.stream().map(k -> "name-" + k).toList());

        final RuntimeWiring wiring = RuntimeWiring.newRuntimeWiring()
            .type("Query", t -> t.dataFetcher("users",
                env -> List.of(new User("1"), new User("2"), new User("3"))))
            .type("User", t -> t.dataFetcher("name",
                env -> env.<DataLoader<String, String>>getDataLoader("nameLoader")
                          .load(((User) env.getSource()).id)))
            .build();

        final TypeDefinitionRegistry tdr = new SchemaParser().parse(SDL);
        final GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(tdr, wiring);
        final GraphQL graphQL = GraphQL.newGraphQL(schema).build();

        // 2. ExecutionInput with profileExecution(true) + chaining flag.
        final DataLoaderRegistry registry = new DataLoaderRegistry();
        registry.register("nameLoader", DataLoaderFactory.newDataLoader(nameLoader));

        final ExecutionInput input = ExecutionInput.newExecutionInput()
            .query("{ users { id name } }")
            .dataLoaderRegistry(registry)
            .profileExecution(true)
            .graphQLContext(b -> b.put(DataLoaderDispatchingContextKeys.ENABLE_DATA_LOADER_CHAINING, chaining))
            .build();

        // 3. Execute and read the ProfilerResult.
        final ExecutionResult result = graphQL.execute(input);
        if (!result.getErrors().isEmpty()) {
            System.err.println("Query errors: " + result.getErrors());
            System.exit(1);
        }
        final ProfilerResult profile = input.getGraphQLContext().get(ProfilerResult.PROFILER_CONTEXT_KEY);
        if (profile == null) {
            System.err.println("ProfilerResult is null — profileExecution(true) was not honored");
            System.exit(2);
        }

        // 4. Print the four collections that demonstrate the bug.
        System.out.println("dataLoaderChainingEnabled = " + profile.isDataLoaderChainingEnabled());
        System.out.println("fieldsFetched             = " + profile.getFieldsFetched());           // populated  (fieldFetched is wired)
        System.out.println("oldStrategyDispatchingAll = " + profile.getOldStrategyDispatchingAll());// populated only when chaining=false
        System.out.println("dataLoaderLoadInvocations = " + profile.getDataLoaderLoadInvocations());// EMPTY: dataLoaderUsed has 0 call sites
        System.out.println("dispatchEvents            = " + profile.getDispatchEvents());          // EMPTY: batchLoadedOld/NewStrategy + manualDispatch all have 0 call sites
    }

    private record User(String id) {}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions