// Copyright 2017 JanusGraph Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package org.janusgraph.graphdb.query.profile; import org.janusgraph.graphdb.query.Query; import java.util.Collection; import java.util.function.Function; /** * @author Matthias Broecheler (me@matthiasb.com) */ public interface QueryProfiler { public static final String CONDITION_ANNOTATION = "condition"; public static final String ORDERS_ANNOTATION = "orders"; public static final String LIMIT_ANNOTATION = "limit"; public static final String MULTIQUERY_ANNOTATION = "multi"; public static final String NUMVERTICES_ANNOTATION = "vertices"; public static final String PARTITIONED_VERTEX_ANNOTATION = "partitioned"; public static final String FITTED_ANNOTATION = "isFitted"; public static final String ORDERED_ANNOTATION = "isOrdered"; public static final String QUERY_ANNOTATION = "query"; public static final String FULLSCAN_ANNOTATION = "fullscan"; public static final String INDEX_ANNOTATION = "index"; public static final String OR_QUERY = "OR-query"; public static final String AND_QUERY = "AND-query"; public static final String OPTIMIZATION = "optimization"; public static final QueryProfiler NO_OP = new QueryProfiler() { @Override public QueryProfiler addNested(String groupName) { return this; } @Override public QueryProfiler setAnnotation(String key, Object value) { return this; } @Override public void startTimer() { } @Override public void stopTimer() { } @Override public void setResultSize(long size) { } }; public QueryProfiler addNested(String groupName); public QueryProfiler setAnnotation(String key, Object value); public void startTimer(); public void stopTimer(); public void setResultSize(long size); public static<Q extends Query,R extends Collection> R profile(QueryProfiler profiler, Q query, Function<Q,R> queryExecutor) { return profile(profiler,query,false,queryExecutor); } public static<Q extends Query,R extends Collection> R profile(String groupName, QueryProfiler profiler, Q query, Function<Q,R> queryExecutor) { return profile(groupName,profiler,query,false,queryExecutor); } public static<Q extends Query,R extends Collection> R profile(QueryProfiler profiler, Q query, boolean multiQuery, Function<Q,R> queryExecutor) { return profile("backend-query",profiler,query,multiQuery,queryExecutor); } public static<Q extends Query,R extends Collection> R profile(String groupName, QueryProfiler profiler, Q query, boolean multiQuery, Function<Q,R> queryExecutor) { QueryProfiler sub = profiler.addNested(groupName); sub.setAnnotation(QUERY_ANNOTATION, query); if (query.hasLimit()) sub.setAnnotation(LIMIT_ANNOTATION,query.getLimit()); sub.startTimer(); R result = queryExecutor.apply(query); sub.stopTimer(); long resultSize = 0; if (multiQuery && profiler!=QueryProfiler.NO_OP) { //The result set is a collection of collections, but don't do this computation if profiling is disabled for (Object r : result) { if (r instanceof Collection) resultSize+=((Collection)r).size(); else resultSize++; } } else { resultSize = result.size(); } sub.setResultSize(resultSize); return result; } }