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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions