Skip to content

Commit 35d17c8

Browse files
committed
Include changes from opentripplanner#6712
1 parent 67c1691 commit 35d17c8

15 files changed

Lines changed: 194 additions & 26 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.opentripplanner.standalone.config.sandbox;
2+
3+
import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_7;
4+
5+
import java.util.Collection;
6+
import java.util.Set;
7+
import org.opentripplanner.apis.gtfs.GtfsApiParameters;
8+
import org.opentripplanner.standalone.config.framework.json.NodeAdapter;
9+
10+
/**
11+
* @see GtfsApiParameters for documentation of parameters
12+
*/
13+
public class GtfsApiConfig implements GtfsApiParameters {
14+
15+
private final Collection<String> tracingTags;
16+
17+
public GtfsApiConfig(String parameterName, NodeAdapter root) {
18+
var c = root
19+
.of(parameterName)
20+
.since(V2_7)
21+
.summary("Configuration for the GTFS GraphQL API.")
22+
.asObject();
23+
24+
tracingTags = c
25+
.of("tracingTags")
26+
.summary("Used to group requests based on headers or query parameters when monitoring OTP.")
27+
.asStringList(Set.of());
28+
}
29+
30+
@Override
31+
public Collection<String> tracingTags() {
32+
return tracingTags;
33+
}
34+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.opentripplanner.apis.gtfs;
2+
3+
import java.util.Collection;
4+
5+
/**
6+
* GTFS API parameters. These parameters configure the behaviour of some aspects of the
7+
* GTFS GraphQL API.
8+
*/
9+
public interface GtfsApiParameters {
10+
/**
11+
* Which HTTP headers or query parameters should be used as tags for performance metering in the
12+
* Actuator API.
13+
*
14+
* @see org.opentripplanner.ext.actuator.MicrometerGraphQLInstrumentation
15+
*/
16+
Collection<String> tracingTags();
17+
}

application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLAPI.java

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
import jakarta.ws.rs.core.HttpHeaders;
1313
import jakarta.ws.rs.core.MediaType;
1414
import jakarta.ws.rs.core.Response;
15+
import jakarta.ws.rs.core.UriInfo;
1516
import java.io.IOException;
1617
import java.util.HashMap;
1718
import java.util.Locale;
1819
import java.util.Map;
20+
import org.opentripplanner.apis.support.TracingUtils;
1921
import org.opentripplanner.standalone.api.OtpServerRequestContext;
2022
import org.slf4j.Logger;
2123
import org.slf4j.LoggerFactory;
@@ -50,12 +52,13 @@ public GtfsGraphQLAPIOldPath(
5052
@POST
5153
@Consumes(MediaType.APPLICATION_JSON)
5254
public Response getGraphQL(
53-
HashMap<String, Object> queryParameters,
55+
HashMap<String, Object> jsonParameters,
5456
@HeaderParam("OTPTimeout") @DefaultValue("30000") int timeout,
5557
@HeaderParam("OTPMaxResolves") @DefaultValue("1000000") int maxResolves,
56-
@Context HttpHeaders headers
58+
@Context HttpHeaders headers,
59+
@Context UriInfo uriInfo
5760
) {
58-
if (queryParameters == null || !queryParameters.containsKey("query")) {
61+
if (jsonParameters == null || !jsonParameters.containsKey("query")) {
5962
LOG.debug("No query found in body");
6063
return Response.status(Response.Status.BAD_REQUEST)
6164
.type(MediaType.TEXT_PLAIN_TYPE)
@@ -67,9 +70,9 @@ public Response getGraphQL(
6770
? headers.getAcceptableLanguages().get(0)
6871
: serverContext.defaultLocale();
6972

70-
String query = (String) queryParameters.get("query");
71-
Object queryVariables = queryParameters.getOrDefault("variables", null);
72-
String operationName = (String) queryParameters.getOrDefault("operationName", null);
73+
String query = (String) jsonParameters.get("query");
74+
Object queryVariables = jsonParameters.getOrDefault("variables", null);
75+
String operationName = (String) jsonParameters.getOrDefault("operationName", null);
7376
Map<String, Object> variables;
7477

7578
if (queryVariables instanceof Map) {
@@ -93,7 +96,12 @@ public Response getGraphQL(
9396
maxResolves,
9497
timeout,
9598
locale,
96-
GraphQLRequestContext.ofServerContext(serverContext)
99+
GraphQLRequestContext.ofServerContext(serverContext),
100+
TracingUtils.findTagsInHeadersOrQueryParameters(
101+
serverContext.gtfsApiParameters().tracingTags(),
102+
headers,
103+
uriInfo.getQueryParameters()
104+
)
97105
);
98106
}
99107

@@ -103,7 +111,8 @@ public Response getGraphQL(
103111
String query,
104112
@HeaderParam("OTPTimeout") @DefaultValue("30000") int timeout,
105113
@HeaderParam("OTPMaxResolves") @DefaultValue("1000000") int maxResolves,
106-
@Context HttpHeaders headers
114+
@Context HttpHeaders headers,
115+
@Context UriInfo uriInfo
107116
) {
108117
Locale locale = headers.getAcceptableLanguages().size() > 0
109118
? headers.getAcceptableLanguages().get(0)
@@ -115,7 +124,12 @@ public Response getGraphQL(
115124
maxResolves,
116125
timeout,
117126
locale,
118-
GraphQLRequestContext.ofServerContext(serverContext)
127+
GraphQLRequestContext.ofServerContext(serverContext),
128+
TracingUtils.findTagsInHeadersOrQueryParameters(
129+
serverContext.gtfsApiParameters().tracingTags(),
130+
headers,
131+
uriInfo.getQueryParameters()
132+
)
119133
);
120134
}
121135
}

application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import graphql.execution.instrumentation.ChainedInstrumentation;
99
import graphql.execution.instrumentation.Instrumentation;
1010
import io.micrometer.core.instrument.Metrics;
11+
import io.micrometer.core.instrument.Tag;
1112
import jakarta.ws.rs.core.Response;
1213
import java.util.HashMap;
1314
import java.util.List;
@@ -30,13 +31,14 @@ static ExecutionResult getGraphQLExecutionResult(
3031
int maxResolves,
3132
int timeoutMs,
3233
Locale locale,
33-
GraphQLRequestContext requestContext
34+
GraphQLRequestContext requestContext,
35+
Iterable<Tag> tracingTags
3436
) {
3537
Instrumentation instrumentation = new MaxQueryComplexityInstrumentation(maxResolves);
3638

3739
if (OTPFeature.ActuatorAPI.isOn()) {
3840
instrumentation = new ChainedInstrumentation(
39-
new MicrometerGraphQLInstrumentation(Metrics.globalRegistry, List.of()),
41+
new MicrometerGraphQLInstrumentation(Metrics.globalRegistry, tracingTags),
4042
instrumentation
4143
);
4244
}
@@ -71,7 +73,8 @@ static Response getGraphQLResponse(
7173
int maxResolves,
7274
int timeoutMs,
7375
Locale locale,
74-
GraphQLRequestContext requestContext
76+
GraphQLRequestContext requestContext,
77+
Iterable<Tag> tracingTags
7578
) {
7679
ExecutionResult executionResult = getGraphQLExecutionResult(
7780
query,
@@ -80,7 +83,8 @@ static Response getGraphQLResponse(
8083
maxResolves,
8184
timeoutMs,
8285
locale,
83-
requestContext
86+
requestContext,
87+
tracingTags
8488
);
8589

8690
return Response.status(Response.Status.OK)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.opentripplanner.apis.support;
2+
3+
import io.micrometer.core.instrument.Tag;
4+
import jakarta.ws.rs.core.HttpHeaders;
5+
import jakarta.ws.rs.core.MultivaluedMap;
6+
import java.util.Collection;
7+
8+
public final class TracingUtils {
9+
10+
private static final String UNKNOWN_VALUE = "__UNKNOWN__";
11+
12+
/**
13+
* This method tries to find a tracing tag from a request's headers.
14+
* If no value is found for a tag, the value is set to "__UNKNOWN__".
15+
*
16+
* @param tracingHeaderTags a collection of tag names to match against headers
17+
* @param headers headers from a request
18+
* @return a list of tracing tags with computed values
19+
*/
20+
public static Iterable<Tag> findTagsInHeaders(
21+
Collection<String> tracingHeaderTags,
22+
HttpHeaders headers
23+
) {
24+
return tracingHeaderTags
25+
.stream()
26+
.map(header -> {
27+
String value = headers.getHeaderString(header);
28+
return Tag.of(header, value == null ? UNKNOWN_VALUE : value);
29+
})
30+
.toList();
31+
}
32+
33+
/**
34+
* This method tries to find a tracing tag from either a request's headers or query parameters.
35+
* The value from headers is favored if a value is present in both.
36+
* If no value is found for a tag, the value is set to "__UNKNOWN__".
37+
*
38+
* @param tracingTags a collection of tag names to match against headers or query parameters
39+
* @param headers headers from a request
40+
* @param queryParameters query parameters from a request
41+
* @return a list of tracing tags with computed values
42+
*/
43+
public static Iterable<Tag> findTagsInHeadersOrQueryParameters(
44+
Collection<String> tracingTags,
45+
HttpHeaders headers,
46+
MultivaluedMap<String, String> queryParameters
47+
) {
48+
return tracingTags
49+
.stream()
50+
.map(header -> {
51+
String headerValue = headers.getHeaderString(header);
52+
String queryParameterValue = queryParameters.getFirst(header);
53+
if (headerValue != null) {
54+
return Tag.of(header, headerValue);
55+
} else if (queryParameterValue != null) {
56+
return Tag.of(header, queryParameterValue);
57+
} else {
58+
return Tag.of(header, UNKNOWN_VALUE);
59+
}
60+
})
61+
.toList();
62+
}
63+
}

application/src/main/java/org/opentripplanner/apis/transmodel/TransmodelAPI.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.HashMap;
2222
import java.util.Map;
2323
import java.util.stream.Collectors;
24+
import org.opentripplanner.apis.support.TracingUtils;
2425
import org.opentripplanner.apis.support.graphql.injectdoc.ApiDocumentationProfile;
2526
import org.opentripplanner.apis.transmodel.mapping.TransitIdMapper;
2627
import org.opentripplanner.routing.api.request.RouteRequest;
@@ -134,7 +135,7 @@ public Response getGraphQL(
134135
variables,
135136
operationName,
136137
maxNumberOfResultFields,
137-
getTagsFromHeaders(headers)
138+
TracingUtils.findTagsInHeaders(tracingHeaderTags, headers)
138139
);
139140
}
140141

@@ -147,7 +148,7 @@ public Response getGraphQL(String query, @Context HttpHeaders headers) {
147148
null,
148149
null,
149150
maxNumberOfResultFields,
150-
getTagsFromHeaders(headers)
151+
TracingUtils.findTagsInHeaders(tracingHeaderTags, headers)
151152
);
152153
}
153154

@@ -157,14 +158,4 @@ public Response getGraphQLSchema() {
157158
var text = SCHEMA_DOC_HEADER + new SchemaPrinter().print(schema);
158159
return Response.ok().encoding("UTF-8").entity(text).build();
159160
}
160-
161-
private static Iterable<Tag> getTagsFromHeaders(HttpHeaders headers) {
162-
return tracingHeaderTags
163-
.stream()
164-
.map(header -> {
165-
String value = headers.getHeaderString(header);
166-
return Tag.of(header, value == null ? "__UNKNOWN__" : value);
167-
})
168-
.collect(Collectors.toList());
169-
}
170161
}

application/src/main/java/org/opentripplanner/standalone/api/OtpServerRequestContext.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.List;
66
import java.util.Locale;
77
import javax.annotation.Nullable;
8+
import org.opentripplanner.apis.gtfs.GtfsApiParameters;
89
import org.opentripplanner.astar.spi.TraverseVisitor;
910
import org.opentripplanner.ext.dataoverlay.routing.DataOverlayContext;
1011
import org.opentripplanner.ext.emissions.EmissionsService;
@@ -130,6 +131,8 @@ default GraphFinder graphFinder() {
130131

131132
ViaCoordinateTransferFactory viaTransferResolver();
132133

134+
GtfsApiParameters gtfsApiParameters();
135+
133136
/* Sandbox modules */
134137

135138
@Nullable

application/src/main/java/org/opentripplanner/standalone/config/RouterConfig.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.fasterxml.jackson.databind.node.MissingNode;
99
import java.io.Serializable;
1010
import java.util.List;
11+
import org.opentripplanner.apis.gtfs.GtfsApiParameters;
1112
import org.opentripplanner.ext.flex.FlexParameters;
1213
import org.opentripplanner.ext.ridehailing.RideHailingServiceParameters;
1314
import org.opentripplanner.routing.api.request.RouteRequest;
@@ -18,6 +19,7 @@
1819
import org.opentripplanner.standalone.config.routerconfig.UpdatersConfig;
1920
import org.opentripplanner.standalone.config.routerconfig.VectorTileConfig;
2021
import org.opentripplanner.standalone.config.sandbox.FlexConfig;
22+
import org.opentripplanner.standalone.config.sandbox.GtfsApiConfig;
2123
import org.opentripplanner.standalone.config.sandbox.TransmodelAPIConfig;
2224
import org.opentripplanner.updater.UpdatersParameters;
2325
import org.slf4j.Logger;
@@ -48,6 +50,7 @@ public class RouterConfig implements Serializable {
4850
private final RideHailingServicesConfig rideHailingConfig;
4951
private final FlexConfig flexConfig;
5052
private final TransmodelAPIConfig transmodelApi;
53+
private final GtfsApiConfig gtfsApi;
5154
private final VectorTileConfig vectorTileConfig;
5255

5356
public RouterConfig(JsonNode node, String source, boolean logUnusedParams) {
@@ -66,6 +69,7 @@ public RouterConfig(JsonNode node, String source, boolean logUnusedParams) {
6669

6770
this.server = new ServerConfig("server", root);
6871
this.transmodelApi = new TransmodelAPIConfig("transmodelApi", root);
72+
this.gtfsApi = new GtfsApiConfig("gtfsApi", root);
6973
this.routingRequestDefaults = mapDefaultRouteRequest("routingDefaults", root);
7074
this.transitConfig = new TransitRoutingConfig("transit", root, routingRequestDefaults);
7175
this.routingRequestDefaults.initMaxSearchWindow(transitConfig.maxSearchWindow());
@@ -131,6 +135,10 @@ public FlexParameters flexParameters() {
131135
return flexConfig;
132136
}
133137

138+
public GtfsApiParameters gtfsApiParameters() {
139+
return gtfsApi;
140+
}
141+
134142
public NodeAdapter asNodeAdapter() {
135143
return root;
136144
}

application/src/main/java/org/opentripplanner/standalone/configure/ConstructApplicationModule.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ OtpServerRequestContext providesServerContext(
5757
var defaultRequest = launcherRequestDecorator.intercept(routerConfig.routingRequestDefaults());
5858

5959
var transitRoutingConfig = routerConfig.transitTuningConfig();
60+
var gtfsApiConfig = routerConfig.gtfsApiParameters();
6061
var vectorTileConfig = routerConfig.vectorTileConfig();
6162
var flexParameters = routerConfig.flexParameters();
6263

@@ -72,6 +73,7 @@ OtpServerRequestContext providesServerContext(
7273
streetLimitationParametersService,
7374
transitRoutingConfig,
7475
transitService,
76+
gtfsApiConfig,
7577
vectorTileConfig,
7678
vehicleParkingService,
7779
vehicleRentalService,

0 commit comments

Comments
 (0)