Skip to content

Commit cc1de5e

Browse files
committed
progress
1 parent 0651b82 commit cc1de5e

3 files changed

Lines changed: 107 additions & 26 deletions

File tree

src/main/java/graphql/ProfilerImpl.java

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,15 @@
22

33
import graphql.execution.ResultPath;
44
import graphql.schema.DataFetcher;
5+
import graphql.schema.PropertyDataFetcher;
6+
import graphql.schema.SingletonPropertyDataFetcher;
57
import org.jspecify.annotations.NullMarked;
68

7-
import java.util.Map;
8-
import java.util.concurrent.ConcurrentHashMap;
9-
import java.util.concurrent.atomic.AtomicInteger;
10-
119
@Internal
1210
@NullMarked
1311
public class ProfilerImpl implements Profiler {
1412

1513
volatile long startTime;
16-
volatile int rootFieldCount;
17-
18-
AtomicInteger propertyDataFetcherCount;
19-
20-
final Map<String, Integer> dataFetcherInvocationCount = new ConcurrentHashMap<>();
2114

2215

2316
final ProfilerResult profilerResult = new ProfilerResult();
@@ -31,21 +24,17 @@ public void start() {
3124
startTime = System.nanoTime();
3225
}
3326

34-
35-
@Override
36-
public void rootFieldCount(int count) {
37-
this.rootFieldCount = count;
38-
}
39-
4027
@Override
4128
public void fieldFetched(Object fetchedObject, DataFetcher<?> dataFetcher, ResultPath path) {
4229
String key = String.join("/", path.getKeysOnly());
4330
profilerResult.addFieldFetched(key);
44-
45-
// dataFetcherInvocationCount.compute(key, (k, v) -> v == null ? 1 : v + 1);
46-
//
47-
// if (dataFetcher instanceof PropertyDataFetcher) {
48-
// propertyDataFetcherCount.incrementAndGet();
49-
// }
31+
profilerResult.incrementDataFetcherInvocationCount(key);
32+
ProfilerResult.DataFetcherType dataFetcherType;
33+
if (dataFetcher instanceof PropertyDataFetcher || dataFetcher instanceof SingletonPropertyDataFetcher) {
34+
dataFetcherType = ProfilerResult.DataFetcherType.PROPERTY_DATA_FETCHER;
35+
} else {
36+
dataFetcherType = ProfilerResult.DataFetcherType.CUSTOM;
37+
}
38+
profilerResult.setDataFetcherType(key, dataFetcherType);
5039
}
5140
}
Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,30 @@
11
package graphql;
22

3+
import java.util.LinkedHashSet;
34
import java.util.Map;
45
import java.util.Set;
56
import java.util.concurrent.ConcurrentHashMap;
7+
import java.util.concurrent.atomic.AtomicInteger;
68

79
@ExperimentalApi
810
public class ProfilerResult {
911

1012
public static String PROFILER_CONTEXT_KEY = "__GJ_PROFILER";
1113

12-
private int fieldCount;
14+
private final AtomicInteger totalDataFetcherInvocations = new AtomicInteger();
15+
private final AtomicInteger totalPropertyDataFetcherInvocations = new AtomicInteger();
1316

14-
private int propertyDataFetcherCount;
1517

1618
private final Set<String> fieldsFetched = ConcurrentHashMap.newKeySet();
19+
private final Map<String, Integer> dataFetcherInvocationCount = new ConcurrentHashMap<>();
20+
private final Map<String, DataFetcherType> dataFetcherTypeMap = new ConcurrentHashMap<>();
1721

18-
public static enum ResultType {
22+
public enum DataFetcherType {
23+
PROPERTY_DATA_FETCHER,
24+
CUSTOM
25+
}
26+
27+
public enum ResultType {
1928
COMPLETABLE_FUTURE_COMPLETED,
2029
COMPLETABLE_FUTURE_NOT_COMPLETED,
2130
MATERIALIZED
@@ -24,14 +33,58 @@ public static enum ResultType {
2433

2534
private Map<String, ResultType> queryPathToResultType;
2635

36+
void setDataFetcherType(String key, DataFetcherType dataFetcherType) {
37+
dataFetcherTypeMap.putIfAbsent(key, dataFetcherType);
38+
totalDataFetcherInvocations.incrementAndGet();
39+
if (dataFetcherType == DataFetcherType.PROPERTY_DATA_FETCHER) {
40+
totalPropertyDataFetcherInvocations.incrementAndGet();
41+
}
42+
}
43+
44+
void incrementDataFetcherInvocationCount(String key) {
45+
dataFetcherInvocationCount.compute(key, (k, v) -> v == null ? 1 : v + 1);
46+
}
2747

28-
public void addFieldFetched(String fieldPath) {
48+
void addFieldFetched(String fieldPath) {
2949
fieldsFetched.add(fieldPath);
3050
}
3151

52+
3253
public Set<String> getFieldsFetched() {
3354
return fieldsFetched;
3455
}
3556

57+
public Set<String> getCustomDataFetcherFields() {
58+
Set<String> result = new LinkedHashSet<>(fieldsFetched);
59+
for (String field : fieldsFetched) {
60+
if (dataFetcherTypeMap.get(field) == DataFetcherType.CUSTOM) {
61+
result.add(field);
62+
}
63+
}
64+
return result;
65+
}
66+
67+
public Set<String> getPropertyDataFetcherFields() {
68+
Set<String> result = new LinkedHashSet<>(fieldsFetched);
69+
for (String field : fieldsFetched) {
70+
if (dataFetcherTypeMap.get(field) == DataFetcherType.PROPERTY_DATA_FETCHER) {
71+
result.add(field);
72+
}
73+
}
74+
return result;
75+
}
76+
77+
78+
public int getTotalDataFetcherInvocations() {
79+
return totalDataFetcherInvocations.get();
80+
}
81+
82+
public int getTotalPropertyDataFetcherInvocations() {
83+
return totalPropertyDataFetcherInvocations.get();
84+
}
85+
86+
public int getTotalCustomDataFetcherInvocations() {
87+
return totalDataFetcherInvocations.get() - totalPropertyDataFetcherInvocations.get();
88+
}
3689

3790
}

src/test/groovy/graphql/ProfilerTest.groovy

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import spock.lang.Specification
77
class ProfilerTest extends Specification {
88

99

10-
def "simple query"() {
10+
def "one field"() {
1111
given:
1212
def sdl = '''
1313
type Query {
@@ -35,4 +35,43 @@ class ProfilerTest extends Specification {
3535
profilerResult.getFieldsFetched() == ["hello"] as Set
3636

3737
}
38+
39+
def "two DF with list"() {
40+
given:
41+
def sdl = '''
42+
type Query {
43+
foo: [Foo]
44+
}
45+
type Foo {
46+
id: String
47+
bar: String
48+
}
49+
'''
50+
def schema = TestUtil.schema(sdl, [
51+
Query: [
52+
foo: { DataFetchingEnvironment dfe -> return [[id: "1"], [id: "2"], [id: "3"]] } as DataFetcher],
53+
Foo : [
54+
bar: { DataFetchingEnvironment dfe -> dfe.source.id } as DataFetcher
55+
]])
56+
def graphql = GraphQL.newGraphQL(schema).build();
57+
58+
ExecutionInput ei = ExecutionInput.newExecutionInput()
59+
.query("{ foo { id bar } }")
60+
.profileExecution(true)
61+
.build()
62+
63+
when:
64+
def result = graphql.execute(ei)
65+
def profilerResult = ei.getGraphQLContext().get(ProfilerResult.PROFILER_CONTEXT_KEY) as ProfilerResult
66+
67+
then:
68+
result.getData() == [foo: [[id: "1", bar: "1"], [id: "2", bar: "2"], [id: "3", bar: "3"]]]
69+
70+
then:
71+
profilerResult.getFieldsFetched() == ["foo", "foo/bar", "foo/id"] as Set
72+
profilerResult.getTotalDataFetcherInvocations() == 7
73+
profilerResult.getTotalCustomDataFetcherInvocations() == 4
74+
profilerResult.getTotalPropertyDataFetcherInvocations() == 3
75+
}
76+
3877
}

0 commit comments

Comments
 (0)