aboutsummaryrefslogtreecommitdiffstats
path: root/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java
diff options
context:
space:
mode:
Diffstat (limited to 'dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java')
-rw-r--r--dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java516
1 files changed, 0 insertions, 516 deletions
diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java
deleted file mode 100644
index 23fa3fa..0000000
--- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java
+++ /dev/null
@@ -1,516 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * openecomp
- * ================================================================================
- * Copyright (C) 2016 - 2017 AT&T
- * ================================================================================
- * 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.
- * ============LICENSE_END=========================================================
- */
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.tomcat.jdbc.pool.interceptor;
-
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.jdbc.pool.ConnectionPool;
-import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
-import org.apache.tomcat.jdbc.pool.PooledConnection;
-
-/**
- * Slow query report interceptor. Tracks timing of query executions.
- * @version 1.0
- */
-public class SlowQueryReport extends AbstractQueryReport {
- //logger
- private static final Log log = LogFactory.getLog(SlowQueryReport.class);
-
- /**
- * we will be keeping track of query stats on a per pool basis
- */
- protected static final ConcurrentHashMap<String,ConcurrentHashMap<String,QueryStats>> perPoolStats =
- new ConcurrentHashMap<>();
- /**
- * the queries that are used for this interceptor.
- */
- protected volatile ConcurrentHashMap<String,QueryStats> queries = null;
- /**
- * Maximum number of queries we will be storing
- */
- protected int maxQueries= 1000; //don't store more than this amount of queries
-
- /**
- * Flag to enable disable logging of slow queries
- */
- protected boolean logSlow = true;
-
- /**
- * Flag to enable disable logging of failed queries
- */
- protected boolean logFailed = false;
-
- /**
- * Sort QueryStats by last invocation time
- */
- protected final Comparator<QueryStats> queryStatsComparator = new QueryStatsComparator();
-
- /**
- * Returns the query stats for a given pool
- * @param poolname - the name of the pool we want to retrieve stats for
- * @return a hash map containing statistics for 0 to maxQueries
- */
- public static ConcurrentHashMap<String,QueryStats> getPoolStats(String poolname) {
- return perPoolStats.get(poolname);
- }
-
- /**
- * Creates a slow query report interceptor
- */
- public SlowQueryReport() {
- super();
- }
-
- public void setMaxQueries(int maxQueries) {
- this.maxQueries = maxQueries;
- }
-
-
- @Override
- protected String reportFailedQuery(String query, Object[] args, String name, long start, Throwable t) {
- String sql = super.reportFailedQuery(query, args, name, start, t);
- if (this.maxQueries > 0 ) {
- long now = System.currentTimeMillis();
- long delta = now - start;
- QueryStats qs = this.getQueryStats(sql);
- if (qs != null) {
- qs.failure(delta, now);
- if (isLogFailed() && log.isWarnEnabled()) {
- log.warn("Failed Query Report SQL="+sql+"; time="+delta+" ms;");
- }
- }
- }
- return sql;
- }
-
- @Override
- protected String reportQuery(String query, Object[] args, final String name, long start, long delta) {
- String sql = super.reportQuery(query, args, name, start, delta);
- if (this.maxQueries > 0 ) {
- QueryStats qs = this.getQueryStats(sql);
- if (qs != null) qs.add(delta, start);
- }
- return sql;
- }
-
- @Override
- protected String reportSlowQuery(String query, Object[] args, String name, long start, long delta) {
- String sql = super.reportSlowQuery(query, args, name, start, delta);
- if (this.maxQueries > 0 ) {
- QueryStats qs = this.getQueryStats(sql);
- if (qs != null) {
- qs.add(delta, start);
- if (isLogSlow() && log.isWarnEnabled()) {
- log.warn("Slow Query Report SQL="+sql+"; time="+delta+" ms;");
- }
- }
- }
- return sql;
- }
-
- /**
- * invoked when the connection receives the close request
- * Not used for now.
- */
- @Override
- public void closeInvoked() {
- // NOOP
- }
-
- @Override
- public void prepareStatement(String sql, long time) {
- if (this.maxQueries > 0 ) {
- QueryStats qs = getQueryStats(sql);
- if (qs != null) qs.prepare(time);
- }
- }
-
- @Override
- public void prepareCall(String sql, long time) {
- if (this.maxQueries > 0 ) {
- QueryStats qs = getQueryStats(sql);
- if (qs != null) qs.prepare(time);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void poolStarted(ConnectionPool pool) {
- super.poolStarted(pool);
- //see if we already created a map for this pool
- queries = SlowQueryReport.perPoolStats.get(pool.getName());
- if (queries==null) {
- //create the map to hold our stats
- //however TODO we need to improve the eviction
- //selection
- queries = new ConcurrentHashMap<>();
- if (perPoolStats.putIfAbsent(pool.getName(), queries)!=null) {
- //there already was one
- queries = SlowQueryReport.perPoolStats.get(pool.getName());
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void poolClosed(ConnectionPool pool) {
- perPoolStats.remove(pool.getName());
- super.poolClosed(pool);
- }
-
- protected QueryStats getQueryStats(String sql) {
- if (sql==null) sql = "";
- ConcurrentHashMap<String,QueryStats> queries = SlowQueryReport.this.queries;
- if (queries==null) {
- if (log.isWarnEnabled()) log.warn("Connection has already been closed or abandoned");
- return null;
- }
- QueryStats qs = queries.get(sql);
- if (qs == null) {
- qs = new QueryStats(sql);
- if (queries.putIfAbsent(sql,qs)!=null) {
- qs = queries.get(sql);
- } else {
- //we added a new element, see if we need to remove the oldest
- if (queries.size() > maxQueries) {
- removeOldest(queries);
- }
- }
- }
- return qs;
- }
-
- /**
- * Sort QueryStats by last invocation time
- * @param queries The queries map
- */
- protected void removeOldest(ConcurrentHashMap<String,QueryStats> queries) {
- ArrayList<QueryStats> list = new ArrayList<>(queries.values());
- Collections.sort(list, queryStatsComparator);
- int removeIndex = 0;
- while (queries.size() > maxQueries) {
- String sql = list.get(removeIndex).getQuery();
- queries.remove(sql);
- if (log.isDebugEnabled()) log.debug("Removing slow query, capacity reached:"+sql);
- removeIndex++;
- }
- }
-
-
- @Override
- public void reset(ConnectionPool parent, PooledConnection con) {
- super.reset(parent, con);
- if (parent!=null)
- queries = SlowQueryReport.perPoolStats.get(parent.getName());
- else
- queries = null;
- }
-
-
- public boolean isLogSlow() {
- return logSlow;
- }
-
- public void setLogSlow(boolean logSlow) {
- this.logSlow = logSlow;
- }
-
- public boolean isLogFailed() {
- return logFailed;
- }
-
- public void setLogFailed(boolean logFailed) {
- this.logFailed = logFailed;
- }
-
- @Override
- public void setProperties(Map<String, InterceptorProperty> properties) {
- super.setProperties(properties);
- final String threshold = "threshold";
- final String maxqueries= "maxQueries";
- final String logslow = "logSlow";
- final String logfailed = "logFailed";
- InterceptorProperty p1 = properties.get(threshold);
- InterceptorProperty p2 = properties.get(maxqueries);
- InterceptorProperty p3 = properties.get(logslow);
- InterceptorProperty p4 = properties.get(logfailed);
- if (p1!=null) {
- setThreshold(Long.parseLong(p1.getValue()));
- }
- if (p2!=null) {
- setMaxQueries(Integer.parseInt(p2.getValue()));
- }
- if (p3!=null) {
- setLogSlow(Boolean.parseBoolean(p3.getValue()));
- }
- if (p4!=null) {
- setLogFailed(Boolean.parseBoolean(p4.getValue()));
- }
- }
-
-
- public static class QueryStats {
- static final String[] FIELD_NAMES = new String[] {
- "query",
- "nrOfInvocations",
- "maxInvocationTime",
- "maxInvocationDate",
- "minInvocationTime",
- "minInvocationDate",
- "totalInvocationTime",
- "failures",
- "prepareCount",
- "prepareTime",
- "lastInvocation"
- };
-
- static final String[] FIELD_DESCRIPTIONS = new String[] {
- "The SQL query",
- "The number of query invocations, a call to executeXXX",
- "The longest time for this query in milliseconds",
- "The time and date for when the longest query took place",
- "The shortest time for this query in milliseconds",
- "The time and date for when the shortest query took place",
- "The total amount of milliseconds spent executing this query",
- "The number of failures for this query",
- "The number of times this query was prepared (prepareStatement/prepareCall)",
- "The total number of milliseconds spent preparing this query",
- "The date and time of the last invocation"
- };
-
- static final OpenType<?>[] FIELD_TYPES = new OpenType[] {
- SimpleType.STRING,
- SimpleType.INTEGER,
- SimpleType.LONG,
- SimpleType.LONG,
- SimpleType.LONG,
- SimpleType.LONG,
- SimpleType.LONG,
- SimpleType.LONG,
- SimpleType.INTEGER,
- SimpleType.LONG,
- SimpleType.LONG
- };
-
- private final String query;
- private volatile int nrOfInvocations;
- private volatile long maxInvocationTime = Long.MIN_VALUE;
- private volatile long maxInvocationDate;
- private volatile long minInvocationTime = Long.MAX_VALUE;
- private volatile long minInvocationDate;
- private volatile long totalInvocationTime;
- private volatile long failures;
- private volatile int prepareCount;
- private volatile long prepareTime;
- private volatile long lastInvocation = 0;
-
- public static String[] getFieldNames() {
- return FIELD_NAMES;
- }
-
- public static String[] getFieldDescriptions() {
- return FIELD_DESCRIPTIONS;
- }
-
- public static OpenType<?>[] getFieldTypes() {
- return FIELD_TYPES;
- }
-
- @Override
- public String toString() {
- SimpleDateFormat sdf =
- new SimpleDateFormat("d MMM yyyy HH:mm:ss z", Locale.US);
- sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
- StringBuilder buf = new StringBuilder("QueryStats[query:");
- buf.append(query);
- buf.append(", nrOfInvocations:");
- buf.append(nrOfInvocations);
- buf.append(", maxInvocationTime:");
- buf.append(maxInvocationTime);
- buf.append(", maxInvocationDate:");
- buf.append(sdf.format(new java.util.Date(maxInvocationDate)));
- buf.append(", minInvocationTime:");
- buf.append(minInvocationTime);
- buf.append(", minInvocationDate:");
- buf.append(sdf.format(new java.util.Date(minInvocationDate)));
- buf.append(", totalInvocationTime:");
- buf.append(totalInvocationTime);
- buf.append(", averageInvocationTime:");
- buf.append((float)totalInvocationTime / (float)nrOfInvocations);
- buf.append(", failures:");
- buf.append(failures);
- buf.append(", prepareCount:");
- buf.append(prepareCount);
- buf.append(", prepareTime:");
- buf.append(prepareTime);
- buf.append("]");
- return buf.toString();
- }
-
- public CompositeDataSupport getCompositeData(final CompositeType type) throws OpenDataException{
- Object[] values = new Object[] {
- query,
- Integer.valueOf(nrOfInvocations),
- Long.valueOf(maxInvocationTime),
- Long.valueOf(maxInvocationDate),
- Long.valueOf(minInvocationTime),
- Long.valueOf(minInvocationDate),
- Long.valueOf(totalInvocationTime),
- Long.valueOf(failures),
- Integer.valueOf(prepareCount),
- Long.valueOf(prepareTime),
- Long.valueOf(lastInvocation)
- };
- return new CompositeDataSupport(type,FIELD_NAMES,values);
- }
-
- public QueryStats(String query) {
- this.query = query;
- }
-
- public void prepare(long invocationTime) {
- prepareCount++;
- prepareTime+=invocationTime;
-
- }
-
- public void add(long invocationTime, long now) {
- //not thread safe, but don't sacrifice performance for this kind of stuff
- maxInvocationTime = Math.max(invocationTime, maxInvocationTime);
- if (maxInvocationTime == invocationTime) {
- maxInvocationDate = now;
- }
- minInvocationTime = Math.min(invocationTime, minInvocationTime);
- if (minInvocationTime==invocationTime) {
- minInvocationDate = now;
- }
- nrOfInvocations++;
- totalInvocationTime+=invocationTime;
- lastInvocation = now;
- }
-
- public void failure(long invocationTime, long now) {
- add(invocationTime,now);
- failures++;
-
- }
-
- public String getQuery() {
- return query;
- }
-
- public int getNrOfInvocations() {
- return nrOfInvocations;
- }
-
- public long getMaxInvocationTime() {
- return maxInvocationTime;
- }
-
- public long getMaxInvocationDate() {
- return maxInvocationDate;
- }
-
- public long getMinInvocationTime() {
- return minInvocationTime;
- }
-
- public long getMinInvocationDate() {
- return minInvocationDate;
- }
-
- public long getTotalInvocationTime() {
- return totalInvocationTime;
- }
-
- @Override
- public int hashCode() {
- return query.hashCode();
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof QueryStats) {
- QueryStats qs = (QueryStats)other;
- return qs.query.equals(this.query);
- }
- return false;
- }
-
- public boolean isOlderThan(QueryStats other) {
- return this.lastInvocation < other.lastInvocation;
- }
- }
-
- /** Compare QueryStats by their lastInvocation value. QueryStats that
- * have never been updated, have a lastInvocation value of {@code 0}
- * which should be handled as the newest possible invocation.
- */
- private static class QueryStatsComparator implements Comparator<QueryStats> {
-
- @Override
- public int compare(QueryStats stats1, QueryStats stats2) {
- return Long.compare(handleZero(stats1.lastInvocation),
- handleZero(stats2.lastInvocation));
- }
-
- private static long handleZero(long value) {
- return value == 0 ? Long.MAX_VALUE : value;
- }
-
- }
-
-}