Add perftrace. Remove regex

This commit is contained in:
Tadgh 2020-03-13 15:29:48 -07:00
parent 74fd2c1519
commit 03567c5831
3 changed files with 34 additions and 6 deletions

View File

@ -81,7 +81,6 @@ public class MatchResourceUrlService {
.add(StorageProcessingMessage.class, message); .add(StorageProcessingMessage.class, message);
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, Pointcut.JPA_PERFTRACE_INFO, params); JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, Pointcut.JPA_PERFTRACE_INFO, params);
} }
return retVal; return retVal;
} }

View File

@ -21,14 +21,19 @@ package ca.uhn.fhir.jpa.dao.predicate;
*/ */
import ca.uhn.fhir.context.*; import ca.uhn.fhir.context.*;
import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.dao.*; import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.dao.index.IdHelperService; import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId; import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.*; import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.ResourceMetaParams; import ca.uhn.fhir.jpa.searchparam.ResourceMetaParams;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.util.SourceParam; import ca.uhn.fhir.jpa.searchparam.util.SourceParam;
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
import ca.uhn.fhir.model.api.IQueryParameterAnd; import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterOr; import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.IQueryParameterType;
@ -41,6 +46,7 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.*; import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IAnyResource;
@ -71,6 +77,8 @@ class PredicateBuilderReference extends BasePredicateBuilder {
MatchUrlService myMatchUrlService; MatchUrlService myMatchUrlService;
@Autowired @Autowired
DaoRegistry myDaoRegistry; DaoRegistry myDaoRegistry;
@Autowired
private IInterceptorBroadcaster myInterceptorBroadcaster;
private final PredicateBuilder myPredicateBuilder; private final PredicateBuilder myPredicateBuilder;
@ -275,7 +283,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
} }
boolean foundChainMatch = false; boolean foundChainMatch = false;
List<Class<? extends IBaseResource>> candidateTargetTypes = new ArrayList<>();
for (Class<? extends IBaseResource> nextType : resourceTypes) { for (Class<? extends IBaseResource> nextType : resourceTypes) {
String chain = theReferenceParam.getChain(); String chain = theReferenceParam.getChain();
@ -303,7 +311,6 @@ class PredicateBuilderReference extends BasePredicateBuilder {
} }
boolean isMeta = ResourceMetaParams.RESOURCE_META_PARAMS.containsKey(chain); boolean isMeta = ResourceMetaParams.RESOURCE_META_PARAMS.containsKey(chain);
//TODO LOG PERF TRACE ISSUE ON AMBIGUOUS REFERENCE TARGETS
RuntimeSearchParam param = null; RuntimeSearchParam param = null;
if (!isMeta) { if (!isMeta) {
param = mySearchParamRegistry.getSearchParamByName(typeDef, chain); param = mySearchParamRegistry.getSearchParamByName(typeDef, chain);
@ -325,23 +332,46 @@ class PredicateBuilderReference extends BasePredicateBuilder {
orValues.add(chainValue); orValues.add(chainValue);
} }
Subquery<Long> subQ = createLinkSubquery(foundChainMatch, chain, subResourceName, orValues, theRequest); Subquery<Long> subQ = createLinkSubquery(foundChainMatch, chain, subResourceName, orValues, theRequest);
Predicate pathPredicate = createResourceLinkPathPredicate(theResourceName, theParamName, theJoin); Predicate pathPredicate = createResourceLinkPathPredicate(theResourceName, theParamName, theJoin);
Predicate pidPredicate = theJoin.get("myTargetResourcePid").in(subQ); Predicate pidPredicate = theJoin.get("myTargetResourcePid").in(subQ);
Predicate andPredicate = myCriteriaBuilder.and(pathPredicate, pidPredicate); Predicate andPredicate = myCriteriaBuilder.and(pathPredicate, pidPredicate);
theCodePredicates.add(andPredicate); theCodePredicates.add(andPredicate);
candidateTargetTypes.add(nextType);
} }
if (!foundChainMatch) { if (!foundChainMatch) {
throw new InvalidRequestException(myContext.getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "invalidParameterChain", theParamName + '.' + theReferenceParam.getChain())); throw new InvalidRequestException(myContext.getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "invalidParameterChain", theParamName + '.' + theReferenceParam.getChain()));
} }
if (candidateTargetTypes.size() > 1) {
warnAboutPerformanceOnUnqualifiedResources(theParamName, theRequest, candidateTargetTypes);
}
Predicate predicate = myCriteriaBuilder.or(toArray(theCodePredicates)); Predicate predicate = myCriteriaBuilder.or(toArray(theCodePredicates));
myQueryRoot.addPredicate(predicate); myQueryRoot.addPredicate(predicate);
return predicate; return predicate;
} }
private void warnAboutPerformanceOnUnqualifiedResources(String theParamName, RequestDetails theRequest, List<Class<? extends IBaseResource>> theCandidateTargetTypes) {
String message = new StringBuilder()
.append("This search uses an unqualified resource(a parameter in a chain without a resource type). ")
.append("This is less efficient than using a qualified type. ")
.append("[" + theParamName + "] resolves to ["+ theCandidateTargetTypes.stream().map(Class::getSimpleName).collect(Collectors.joining(",")) +"].")
.append("If you know what you're looking for, try qualifying it like this: ")
.append(theCandidateTargetTypes.stream().map(cls -> "[" +cls.getSimpleName() +":"+theParamName+"]").collect(Collectors.joining(" or ")))
.toString();
StorageProcessingMessage msg = new StorageProcessingMessage()
.setMessage(message);
HookParams params = new HookParams()
.add(RequestDetails.class, theRequest)
.addIfMatchesType(ServletRequestDetails.class, theRequest)
.add(StorageProcessingMessage.class, msg);
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, Pointcut.JPA_PERFTRACE_WARNING, params);
}
Predicate createResourceLinkPathPredicate(String theResourceName, String theParamName, From<?, ? extends ResourceLink> from) { Predicate createResourceLinkPathPredicate(String theResourceName, String theParamName, From<?, ? extends ResourceLink> from) {
return createResourceLinkPathPredicate(myContext, theParamName, from, theResourceName); return createResourceLinkPathPredicate(myContext, theParamName, from, theResourceName);
} }
@ -835,7 +865,6 @@ class PredicateBuilderReference extends BasePredicateBuilder {
Subquery<Long> subQ = myPredicateBuilder.createLinkSubquery(paramName, targetResourceType, orValues, theRequest); Subquery<Long> subQ = myPredicateBuilder.createLinkSubquery(paramName, targetResourceType, orValues, theRequest);
Join<ResourceTable, ResourceLink> join = myQueryRoot.join("myResourceLinksAsTarget", JoinType.LEFT); Join<ResourceTable, ResourceLink> join = myQueryRoot.join("myResourceLinksAsTarget", JoinType.LEFT);
//Predicate predicate = addPredicateReferenceWithChain("Device", paramName, orValues, join, Collections.emptyList(), refere, theRequest);
Predicate pathPredicate = myPredicateBuilder.createResourceLinkPathPredicate(targetResourceType, paramReference, join); Predicate pathPredicate = myPredicateBuilder.createResourceLinkPathPredicate(targetResourceType, paramReference, join);
Predicate sourceTypePredicate = myCriteriaBuilder.equal(join.get("myTargetResourceType"), theResourceType); Predicate sourceTypePredicate = myCriteriaBuilder.equal(join.get("myTargetResourceType"), theResourceType);
@ -846,8 +875,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
} }
} }
private String getChainedPart(String parameter) { private String getChainedPart(String parameter) {
//replace with indexof(.) stuff. return parameter.substring(parameter.indexOf(".") + 1);
return parameter.replaceAll("^.+?\\.(.+)$", "$1");
} }
private void addPredicateComposite(String theResourceName, RuntimeSearchParam theParamDef, List<? extends IQueryParameterType> theNextAnd) { private void addPredicateComposite(String theResourceName, RuntimeSearchParam theParamDef, List<? extends IQueryParameterType> theNextAnd) {

View File

@ -376,6 +376,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
// Patient?_has:Observation:subject:device.identifier=urn:system|DEVICEID // Patient?_has:Observation:subject:device.identifier=urn:system|DEVICEID
myCaptureQueriesListener.clear(); myCaptureQueriesListener.clear();
assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(hasWithChainParamQuery)), contains(pid0.getValue())); assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(hasWithChainParamQuery)), contains(pid0.getValue()));
ourLog.warn(myCaptureQueriesListener.getSelectQueriesForCurrentThread().stream().map(q -> q.getSql(true, true)).collect(Collectors.joining("******")));
} }
@Test @Test