package com.arpnetworking.utils;
import com.jolbox.bonecp.ConnectionHandle;
import com.jolbox.bonecp.StatementHandle;
import com.jolbox.bonecp.hooks.AbstractConnectionHook;
import com.jolbox.bonecp.hooks.AcquireFailConfig;
import com.jolbox.bonecp.hooks.ConnectionHook;
import com.jolbox.bonecp.hooks.ConnectionState;
import play.mvc.Http;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A connection hook that keeps track of metrics
*
* @author barp
*/
public class MetricLoggingHook extends AbstractConnectionHook {
private final ConnectionHook fWrappedHook;
private final String fDataSourceName;
private AtomicInteger fOpenConnections = new AtomicInteger(0);
private AtomicInteger fActiveConnections = new AtomicInteger(0);
public MetricLoggingHook(ConnectionHook wrappedHook, String dataSourceName) {
fWrappedHook = wrappedHook;
fDataSourceName = dataSourceName;
}
@Override
public void onAcquire(final ConnectionHandle connection) {
fOpenConnections.incrementAndGet();
fWrappedHook.onAcquire(connection);
}
@Override
public void onCheckIn(final ConnectionHandle connection) {
fActiveConnections.decrementAndGet();
fWrappedHook.onCheckIn(connection);
}
@Override
public void onCheckOut(final ConnectionHandle connection) {
int active = fActiveConnections.incrementAndGet();
Counter counter = getActiveCounter();
if (counter != null) {
counter.recordGauge(fDataSourceName + ".activeConnections", active);
}
fWrappedHook.onCheckOut(connection);
}
@Override
public void onDestroy(final ConnectionHandle connection) {
fOpenConnections.decrementAndGet();
fWrappedHook.onDestroy(connection);
}
@Override
public boolean onAcquireFail(final Throwable t, final AcquireFailConfig acquireConfig) {
return fWrappedHook.onAcquireFail(t, acquireConfig);
}
@Override
public void onQueryExecuteTimeLimitExceeded(final ConnectionHandle handle, final Statement statement, final String sql, final Map<Object, Object> logParams, final long timeElapsedInNs) {
fWrappedHook.onQueryExecuteTimeLimitExceeded(handle, statement, sql, logParams, timeElapsedInNs);
}
@SuppressWarnings("deprecation")
@Override
public void onQueryExecuteTimeLimitExceeded(final ConnectionHandle handle, final Statement statement, final String sql, final Map<Object, Object> logParams) {
fWrappedHook.onQueryExecuteTimeLimitExceeded(handle, statement, sql, logParams);
}
@SuppressWarnings("deprecation")
@Override
public void onQueryExecuteTimeLimitExceeded(final String sql, final Map<Object, Object> logParams) {
fWrappedHook.onQueryExecuteTimeLimitExceeded(sql, logParams);
}
@Override
public boolean onConnectionException(final ConnectionHandle connection, final String state, final Throwable t) {
return fWrappedHook.onConnectionException(connection, state, t);
}
@Override
public void onBeforeStatementExecute(final ConnectionHandle conn, final StatementHandle statement, final String sql, final Map<Object, Object> params) {
fWrappedHook.onBeforeStatementExecute(conn, statement, sql, params);
Counter counter = getActiveCounter();
if (counter != null) {
counter.startTimer(fDataSourceName + ".queryTime");
}
}
@Override
public void onAfterStatementExecute(final ConnectionHandle conn, final StatementHandle statement, final String sql, final Map<Object, Object> params) {
Counter counter = getActiveCounter();
if (counter != null) {
counter.stopTimer(fDataSourceName + ".queryTime");
counter.increment(fDataSourceName + ".queriesExecuted");
}
fWrappedHook.onAfterStatementExecute(conn, statement, sql, params);
}
@Override
public ConnectionState onMarkPossiblyBroken(final ConnectionHandle connection, final String state, final SQLException e) {
return fWrappedHook.onMarkPossiblyBroken(connection, state, e);
}
private Counter getActiveCounter() {
Http.Context context = Http.Context.current.get();
if (context == null) {
return null;
}
Counter counter = (Counter)context.args.get("query-log");
return counter;
}
}