com.alibaba.druid.stat.JdbcConnectionStat Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of druid Show documentation
Show all versions of druid Show documentation
An JDBC datasource implementation.
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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 com.alibaba.druid.stat;
import com.alibaba.druid.util.Histogram;
import com.alibaba.druid.util.JMXUtils;
import javax.management.JMException;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author wenshao [[email protected]]
*/
public class JdbcConnectionStat implements JdbcConnectionStatMBean {
private final AtomicInteger activeCount = new AtomicInteger();
private final AtomicInteger activeCountMax = new AtomicInteger();
private final AtomicInteger connectingCount = new AtomicInteger();
private final AtomicInteger connectingMax = new AtomicInteger();
private final AtomicLong connectCount = new AtomicLong();
private final AtomicLong connectErrorCount = new AtomicLong();
private Throwable connectErrorLast;
private final AtomicLong connectNanoTotal = new AtomicLong(0); // 连接建立消耗时间总和(纳秒)
private final AtomicLong connectNanoMax = new AtomicLong(0); // 连接建立消耗最大时间(纳秒)
private final AtomicLong errorCount = new AtomicLong();
private final AtomicLong aliveNanoTotal = new AtomicLong();
private Throwable lastError;
private long lastErrorTime;
private long connectLastTime;
private final AtomicLong closeCount = new AtomicLong(0); // 执行Connection.close的计数
private final AtomicLong transactionStartCount = new AtomicLong(0);
private final AtomicLong commitCount = new AtomicLong(0); // 执行commit的计数
private final AtomicLong rollbackCount = new AtomicLong(0); // 执行rollback的计数
private final AtomicLong aliveNanoMin = new AtomicLong();
private final AtomicLong aliveNanoMax = new AtomicLong();
private final Histogram histogram = new Histogram(TimeUnit.SECONDS, new long[]{ //
1, 5, 15, 60, 300, 1800});
public JdbcConnectionStat() {
}
public void reset() {
connectingMax.set(0);
connectErrorCount.set(0);
errorCount.set(0);
aliveNanoTotal.set(0);
aliveNanoMin.set(0);
aliveNanoMax.set(0);
lastError = null;
lastErrorTime = 0;
connectLastTime = 0;
connectCount.set(0);
closeCount.set(0);
transactionStartCount.set(0);
commitCount.set(0);
rollbackCount.set(0);
connectNanoTotal.set(0);
connectNanoMax.set(0);
histogram.reset();
}
public void beforeConnect() {
int invoking = connectingCount.incrementAndGet();
for (; ; ) {
int max = connectingMax.get();
if (invoking > max) {
if (connectingMax.compareAndSet(max, invoking)) {
break;
} else {
continue;
}
} else {
break;
}
}
connectCount.incrementAndGet();
connectLastTime = System.currentTimeMillis();
}
public void afterConnected(long delta) {
connectingCount.decrementAndGet();
connectNanoTotal.addAndGet(delta);
for (; ; ) {
// connectNanoMax
long max = connectNanoMax.get();
if (delta > max) {
if (connectNanoMax.compareAndSet(max, delta)) {
break;
} else {
continue;
}
} else {
break;
}
}
activeCount.incrementAndGet();
}
public long getConnectNanoMax() {
return this.connectNanoMax.get();
}
public long getConnectMillisMax() {
return this.connectNanoMax.get() / (1000 * 1000);
}
public void setActiveCount(int activeCount) {
this.activeCount.set(activeCount);
for (; ; ) {
int max = activeCountMax.get();
if (activeCount > max) {
if (activeCountMax.compareAndSet(max, activeCount)) {
break;
} else {
continue;
}
} else {
break;
}
}
}
public int getActiveCount() {
return activeCount.get();
}
public int getAtiveCountMax() {
return this.activeCount.get();
}
public long getErrorCount() {
return errorCount.get();
}
public int getConnectingCount() {
return connectingCount.get();
}
public int getConnectingMax() {
return connectingMax.get();
}
public long getAliveTotal() {
return aliveNanoTotal.get();
}
public long getAliveNanoMin() {
return aliveNanoMin.get();
}
public long getAliveMillisMin() {
return aliveNanoMin.get() / (1000 * 1000);
}
public long getAliveNanoMax() {
return aliveNanoMax.get();
}
public long getAliveMillisMax() {
return aliveNanoMax.get() / (1000 * 1000);
}
public void afterClose(long aliveNano) {
activeCount.decrementAndGet();
aliveNanoTotal.addAndGet(aliveNano);
for (; ; ) {
long max = aliveNanoMax.get();
if (aliveNano > max) {
if (aliveNanoMax.compareAndSet(max, aliveNano)) {
break;
} else {
continue;
}
} else {
break;
}
}
for (; ; ) {
long min = aliveNanoMin.get();
if (min == 0 || aliveNano < min) {
if (aliveNanoMin.compareAndSet(min, aliveNano)) {
break;
} else {
continue;
}
} else {
break;
}
}
long aliveMillis = aliveNano / (1000 * 1000);
histogram.record(aliveMillis);
}
public Throwable getErrorLast() {
return lastError;
}
public Throwable getConnectErrorLast() {
return this.connectErrorLast;
}
public Date getErrorLastTime() {
if (lastErrorTime <= 0) {
return null;
}
return new Date(lastErrorTime);
}
public void connectError(Throwable error) {
connectErrorCount.incrementAndGet();
connectErrorLast = error;
errorCount.incrementAndGet();
lastError = error;
lastErrorTime = System.currentTimeMillis();
}
public void error(Throwable error) {
errorCount.incrementAndGet();
lastError = error;
lastErrorTime = System.currentTimeMillis();
}
@Override
public long getCloseCount() {
return this.closeCount.get();
}
@Override
public long getCommitCount() {
return this.commitCount.get();
}
@Override
public long getConnectCount() {
return connectCount.get();
}
@Override
public long getConnectMillis() {
return connectNanoTotal.get() / (1000 * 1000);
}
@Override
public int getActiveMax() {
return this.activeCountMax.get();
}
@Override
public long getRollbackCount() {
return rollbackCount.get();
}
@Override
public long getConnectErrorCount() {
return connectErrorCount.get();
}
@Override
public Date getConnectLastTime() {
if (connectLastTime == 0) {
return null;
}
return new Date(connectLastTime);
}
public void incrementConnectionCloseCount() {
closeCount.incrementAndGet();
}
public void incrementConnectionCommitCount() {
commitCount.incrementAndGet();
}
public void incrementConnectionRollbackCount() {
rollbackCount.incrementAndGet();
}
public void incrementTransactionStartCount() {
transactionStartCount.incrementAndGet();
}
public long getTransactionStartCount() {
return transactionStartCount.get();
}
public static class Entry implements EntryMBean {
private long id;
private long establishTime;
private long establishNano;
private Date connectTime;
private long connectTimespanNano;
private Exception connectStackTraceException;
private String lastSql;
private Exception lastStatementStatckTraceException;
protected Throwable lastError;
protected long lastErrorTime;
private final String dataSource;
public Entry(String dataSource, long connectionId) {
this.id = connectionId;
this.dataSource = dataSource;
}
public void reset() {
this.lastSql = null;
this.lastStatementStatckTraceException = null;
this.lastError = null;
this.lastErrorTime = 0;
}
public Date getEstablishTime() {
if (establishTime <= 0) {
return null;
}
return new Date(establishTime);
}
public void setEstablishTime(long establishTime) {
this.establishTime = establishTime;
}
public long getEstablishNano() {
return establishNano;
}
public void setEstablishNano(long establishNano) {
this.establishNano = establishNano;
}
public Date getConnectTime() {
return connectTime;
}
public void setConnectTime(Date connectTime) {
this.connectTime = connectTime;
}
public long getConnectTimespanNano() {
return connectTimespanNano;
}
public void setConnectTimespanNano(long connectTimespanNano) {
this.connectTimespanNano = connectTimespanNano;
}
public String getLastSql() {
return lastSql;
}
public void setLastSql(String lastSql) {
this.lastSql = lastSql;
}
public String getConnectStackTrace() {
if (connectStackTraceException == null) {
return null;
}
StringWriter buf = new StringWriter();
connectStackTraceException.printStackTrace(new PrintWriter(buf));
return buf.toString();
}
public void setConnectStackTrace(Exception connectStackTraceException) {
this.connectStackTraceException = connectStackTraceException;
}
public String getLastStatementStatckTrace() {
if (lastStatementStatckTraceException == null) {
return null;
}
StringWriter buf = new StringWriter();
lastStatementStatckTraceException.printStackTrace(new PrintWriter(buf));
return buf.toString();
}
public void setLastStatementStatckTrace(Exception lastStatementStatckTrace) {
this.lastStatementStatckTraceException = lastStatementStatckTrace;
}
public void error(Throwable lastError) {
this.lastError = lastError;
this.lastErrorTime = System.currentTimeMillis();
}
public Date getLastErrorTime() {
if (lastErrorTime <= 0) {
return null;
}
return new Date(lastErrorTime);
}
private static String[] indexNames = {"ID", "ConnectTime", "ConnectTimespan", "EstablishTime",
"AliveTimespan", "LastSql", "LastError", "LastErrorTime",
"ConnectStatckTrace", "LastStatementStackTrace", "DataSource"};
private static String[] indexDescriptions = indexNames;
public static CompositeType getCompositeType() throws JMException {
OpenType>[] indexTypes = new OpenType>[]{SimpleType.LONG, SimpleType.DATE, SimpleType.LONG,
SimpleType.DATE, SimpleType.LONG,
SimpleType.STRING, JMXUtils.getThrowableCompositeType(), SimpleType.DATE, SimpleType.STRING,
SimpleType.STRING,
SimpleType.STRING};
return new CompositeType("ConnectionStatistic", "Connection Statistic", indexNames, indexDescriptions,
indexTypes);
}
public String getDataSource() {
return this.dataSource;
}
public CompositeDataSupport getCompositeData() throws JMException {
Map map = new HashMap();
map.put("ID", id);
map.put("ConnectTime", getConnectTime());
map.put("ConnectTimespan", getConnectTimespanNano() / (1000 * 1000));
map.put("EstablishTime", getEstablishTime());
map.put("AliveTimespan", (System.nanoTime() - getEstablishNano()) / (1000 * 1000));
map.put("LastSql", getLastSql());
map.put("LastError", JMXUtils.getErrorCompositeData(this.lastError));
map.put("LastErrorTime", getLastErrorTime());
map.put("ConnectStatckTrace", getConnectStackTrace());
map.put("LastStatementStackTrace", getLastStatementStatckTrace());
map.put("DataSource", this.getDataSource());
return new CompositeDataSupport(getCompositeType(), map);
}
}
public interface EntryMBean {
Date getEstablishTime();
long getEstablishNano();
Date getConnectTime();
long getConnectTimespanNano();
String getLastSql();
String getConnectStackTrace();
String getLastStatementStatckTrace();
Date getLastErrorTime();
void reset();
}
public long[] getHistorgramValues() {
return this.histogram.toArray();
}
public long[] getHistogramRanges() {
return this.histogram.getRanges();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy