
oracle.kv.impl.mgmt.jmx.RepNode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of oracle-nosql-server Show documentation
Show all versions of oracle-nosql-server Show documentation
NoSQL Database Server - supplies build and runtime support for the server (store) side of the Oracle NoSQL Database.
The newest version!
/*-
* Copyright (C) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle NoSQL
* Database made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle NoSQL Database for a copy of the license and
* additional information.
*/
package oracle.kv.impl.mgmt.jmx;
import java.util.Date;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.ObjectName;
import oracle.kv.impl.admin.param.RepNodeParams;
import oracle.kv.impl.measurement.ConciseStats;
import oracle.kv.impl.measurement.LatencyInfo;
import oracle.kv.impl.measurement.PerfStatType;
import oracle.kv.impl.measurement.ReplicationState;
import oracle.kv.impl.monitor.views.PerfEvent;
import oracle.kv.impl.rep.monitor.StatsPacket;
import oracle.kv.impl.topo.RepNodeId;
import oracle.kv.impl.util.ConfigurableService.ServiceStatus;
import oracle.kv.impl.util.JsonUtils;
import oracle.kv.mgmt.jmx.RepNodeMXBean;
import com.sleepycat.je.rep.ReplicatedEnvironment.State;
import com.sleepycat.je.rep.StateChangeEvent;
import com.sleepycat.utilint.Latency;
import org.codehaus.jackson.map.ObjectWriter;
import org.codehaus.jackson.node.ObjectNode;
public class RepNode
extends NotificationBroadcasterSupport
implements RepNodeMXBean {
private final RepNodeId rnId;
private final MBeanServer server;
private final StorageNode sn;
private ServiceStatus status;
private LatencyInfo singleInterval;
private LatencyInfo singleCumulative;
private LatencyInfo multiInterval;
private LatencyInfo multiCumulative;
private RepNodeParams parameters;
private State replicationState;
private String opMetricString;
private String envMetricString;
private ObjectName oName;
long notifySequence = 1L;
public static final String
NOTIFY_RN_STATUS_CHANGE = "oracle.kv.repnode.status";
public static final String
NOTIFY_SINGLE_TFLOOR = "oracle.kv.singleop.throughputfloor";
public static final String
NOTIFY_SINGLE_LCEILING = "oracle.kv.singleop.latencyceiling";
public static final String
NOTIFY_MULTI_TFLOOR = "oracle.kv.multiop.throughputfloor";
public static final String
NOTIFY_MULTI_LCEILING = "oracle.kv.multiop.latencyceiling";
public static final String
NOTIFY_RN_OP_METRIC = "oracle.kv.repnode.opmetric";
public static final String
NOTIFY_RN_EXCEPTION_METRIC = "oracle.kv.repnode.exceptionmetric";
public static final String
NOTIFY_RN_ENV_METRIC = "oracle.kv.repnode.envmetric";
public static final String
NOTIFY_RN_REPLICATION_STATE = "oracle.kv.repnode.replicationstate";
public static final String
NOTIFY_RN_TABLE_METRIC = "oracle.kv.repnode.tablemetric";
public static final String
NOTIFY_RN_JVM_STATS = "oracle.kv.repnode.jvmstats";
public RepNode(RepNodeParams rnp, MBeanServer server, StorageNode sn) {
this.server = server;
this.rnId = rnp.getRepNodeId();
this.sn = sn;
status = ServiceStatus.UNREACHABLE;
resetMetrics();
setParameters(rnp);
register();
}
private void resetMetrics() {
/*
* Create a fake LatencyInfo to report when no metrics are available.
*/
final LatencyInfo li = new LatencyInfo
(PerfStatType.PUT_IF_ABSENT_INT,
System.currentTimeMillis(), System.currentTimeMillis(),
new Latency(0));
singleInterval = li;
singleCumulative = li;
multiInterval = li;
multiCumulative = li;
replicationState = State.UNKNOWN;
final String emptyJson = "{}";
opMetricString = emptyJson;
envMetricString = emptyJson;
}
private void register() {
final StringBuffer buf = new StringBuffer(JmxAgent.DOMAIN);
buf.append(":type=RepNode");
buf.append(",id=");
buf.append(getRepNodeId());
try {
oName = new ObjectName(buf.toString());
} catch (MalformedObjectNameException e) {
throw new IllegalStateException
("Unexpected exception creating JMX ObjectName " +
buf.toString(), e);
}
try {
server.registerMBean(this, oName);
} catch (Exception e) {
throw new IllegalStateException
("Unexpected exception registring MBean " + oName.toString(),
e);
}
}
public void unregister() {
if (oName != null) {
try {
server.unregisterMBean(oName);
} catch (Exception e) {
throw new IllegalStateException
("Unexpected exception while unregistring MBean " +
oName.toString(), e);
}
}
}
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return new MBeanNotificationInfo[]
{
new MBeanNotificationInfo
(new String[]{RepNode.NOTIFY_RN_STATUS_CHANGE},
Notification.class.getName(),
"Announce a change in this RepNode's service status"),
new MBeanNotificationInfo
(new String[]{RepNode.NOTIFY_SINGLE_TFLOOR},
Notification.class.getName(),
"Single-operation throughput floor violation notification."),
new MBeanNotificationInfo
(new String[]{RepNode.NOTIFY_SINGLE_LCEILING},
Notification.class.getName(),
"Single-operation latency ceiling violation notification."),
new MBeanNotificationInfo
(new String[]{RepNode.NOTIFY_MULTI_TFLOOR},
Notification.class.getName(),
"Multi-operation throughput floor violation notification."),
new MBeanNotificationInfo
(new String[]{RepNode.NOTIFY_MULTI_LCEILING},
Notification.class.getName(),
"Multi-operation latency ceiling violation notification."),
new MBeanNotificationInfo
(new String[]{RepNode.NOTIFY_RN_OP_METRIC},
Notification.class.getName(),
"New operation performance metrics are available."),
new MBeanNotificationInfo
(new String[]{RepNode.NOTIFY_RN_ENV_METRIC},
Notification.class.getName(),
"New statistics are available."),
new MBeanNotificationInfo
(new String[]{RepNode.NOTIFY_RN_EXCEPTION_METRIC},
Notification.class.getName(),
"New RepNode exception metrics are available"),
new MBeanNotificationInfo
(new String[]{RepNode.NOTIFY_RN_TABLE_METRIC},
Notification.class.getName(),
"New RepNode table metrics are available"),
new MBeanNotificationInfo
(new String[]{RepNode.NOTIFY_RN_REPLICATION_STATE},
Notification.class.getName(),
"Announce a change in this RepNode's replication state"),
new MBeanNotificationInfo(
new String[]{RepNode.NOTIFY_RN_JVM_STATS},
Notification.class.getName(),
"New RepNode JVM stats are available")
};
}
public void setParameters(RepNodeParams rnp) {
parameters = rnp;
}
public synchronized void setPerfStats(StatsPacket packet) {
singleInterval =
packet.get(PerfStatType.USER_SINGLE_OP_INT);
singleCumulative =
packet.get(PerfStatType.USER_SINGLE_OP_CUM);
multiInterval =
packet.get(PerfStatType.USER_MULTI_OP_INT);
multiCumulative =
packet.get(PerfStatType.USER_MULTI_OP_CUM);
/* Extract the replication state from the otherStats. */
for (ConciseStats cs : packet.getOtherStats()) {
if (cs instanceof ReplicationState) {
replicationState = ((ReplicationState) cs).getState();
}
}
final int ceiling = parameters.getLatencyCeiling();
final int floor = parameters.getThroughputFloor();
Notification notification = null;
/*
* Check the interval measurements against their limits to determine
* whether an trap should be issued.
*/
if (singleInterval.getLatency().getTotalOps() != 0) {
if (PerfEvent.latencyCeilingExceeded(ceiling, singleInterval)) {
notification = new Notification
(NOTIFY_SINGLE_LCEILING, oName, notifySequence++,
System.currentTimeMillis(),
"The latency ceiling limit for single operations " +
"of " + ceiling + "ms was violated.");
notification.setUserData(Float.valueOf(getIntervalLatAvg()));
sendNotification(notification);
sn.sendProxyNotification(notification);
}
if (PerfEvent.throughputFloorExceeded(floor, singleInterval)) {
notification = new Notification
(NOTIFY_SINGLE_TFLOOR, oName, notifySequence++,
System.currentTimeMillis(),
"The throughput floor limit for single operations " +
"of " + floor + " ops/sec was violated.");
notification.setUserData
(Long.valueOf(getIntervalThroughput()));
sendNotification(notification);
sn.sendProxyNotification(notification);
}
}
if (multiInterval.getLatency().getTotalOps() != 0) {
if (PerfEvent.latencyCeilingExceeded(ceiling, multiInterval)) {
notification = new Notification
(NOTIFY_MULTI_LCEILING, oName, notifySequence++,
System.currentTimeMillis(),
"The latency ceiling limit for multi operations " +
"of " + ceiling + "ms was violated.");
notification.setUserData
(Float.valueOf(getMultiIntervalLatAvg()));
sendNotification(notification);
sn.sendProxyNotification(notification);
}
if (PerfEvent.throughputFloorExceeded(floor, multiInterval)) {
notification = new Notification
(NOTIFY_MULTI_TFLOOR, oName, notifySequence++,
System.currentTimeMillis(),
"The throughput floor limit for multi operations " +
"of " + floor + " ops/sec was violated.");
notification.setUserData
(Long.valueOf(getMultiIntervalThroughput()));
sendNotification(notification);
sn.sendProxyNotification(notification);
}
}
final String rnOpStr = packet.toOpJsonString();
if (rnOpStr != null && !rnOpStr.isEmpty()) {
opMetricString = rnOpStr;
notification = new Notification
(NOTIFY_RN_OP_METRIC, oName, notifySequence++,
System.currentTimeMillis(),
"New operation metrics for this RepNode.");
notification.setUserData(rnOpStr);
sendNotification(notification);
sn.sendProxyNotification(notification);
}
final String rnExceptionStr = packet.toExceptionsJsonString();
if (rnExceptionStr != null && !rnExceptionStr.isEmpty()) {
notification = new Notification
(NOTIFY_RN_EXCEPTION_METRIC, oName, notifySequence++,
System.currentTimeMillis(),
"New exception metric of this RepNode.");
notification.setUserData(rnExceptionStr);
sendNotification(notification);
sn.sendProxyNotification(notification);
}
final String rnEnvStr = packet.toEnvJsonString();
if (rnEnvStr != null && !rnEnvStr.isEmpty()) {
envMetricString = rnEnvStr;
notification = new Notification
(NOTIFY_RN_ENV_METRIC, oName, notifySequence++,
System.currentTimeMillis(),
"New statistics for this RepNode.");
notification.setUserData(rnEnvStr);
sendNotification(notification);
sn.sendProxyNotification(notification);
}
final String rnTableStr = packet.toTableJsonString();
if (rnTableStr != null && !rnTableStr.isEmpty()) {
notification = new Notification
(NOTIFY_RN_TABLE_METRIC, oName, notifySequence++,
System.currentTimeMillis(),
"New table metrics for this RepNode.");
notification.setUserData(rnTableStr);
sendNotification(notification);
sn.sendProxyNotification(notification);
}
final String rnJVMStatsStr = packet.toJVMStatsJsonString();
if ((rnJVMStatsStr != null) && !rnJVMStatsStr.isEmpty()) {
notification = new Notification(
NOTIFY_RN_JVM_STATS, oName, notifySequence++,
System.currentTimeMillis(),
"New JVM stats for this RepNode.");
notification.setUserData(rnJVMStatsStr);
sendNotification(notification);
sn.sendProxyNotification(notification);
}
}
public synchronized void setServiceStatus(ServiceStatus newStatus) {
if (status.equals(newStatus)) {
return;
}
final Notification n = new Notification
(NOTIFY_RN_STATUS_CHANGE, oName, notifySequence++,
System.currentTimeMillis(),
"The service status for RepNode " + getRepNodeId() +
" changed to " + newStatus.toString() + ".");
String statusInfo = "";
try {
ObjectNode jsonRoot = JsonUtils.createObjectNode();
jsonRoot.put("resource", getRepNodeId());
jsonRoot.put("shard", rnId.getGroupName());
jsonRoot.put("reportTime", System.currentTimeMillis());
jsonRoot.put("service_status", newStatus.toString());
ObjectWriter writer = JsonUtils.createWriter(false);
statusInfo = writer.writeValueAsString(jsonRoot);
} catch (Exception e) {
}
n.setUserData(statusInfo);
sendNotification(n);
/*
* Also send it from the StorageNode. A client can observe this event
* by subscribing ether to the StorageNode or to this RepNode.
*/
sn.sendProxyNotification(n);
status = newStatus;
/*
* Whenever there is a service status change, reset the metrics so that
* we don't report stale information.
*/
resetMetrics();
}
public synchronized void updateReplicationState(StateChangeEvent sce) {
if (sce == null) {
return;
}
State newState = sce.getState();
if (newState == null || newState.equals(replicationState)) {
return;
}
final Notification n = new Notification
(NOTIFY_RN_REPLICATION_STATE, oName, notifySequence++,
System.currentTimeMillis(),
"The replication state for RepNode " + getRepNodeId() +
" changed to " + newState.toString() + ".");
String stateInfo = "";
try {
ObjectNode jsonRoot = JsonUtils.createObjectNode();
jsonRoot.put("resource", getRepNodeId());
jsonRoot.put("shard", rnId.getGroupName());
jsonRoot.put("reportTime", sce.getEventTime());
jsonRoot.put("replication_state", newState.toString());
ObjectWriter writer = JsonUtils.createWriter(false);
stateInfo = writer.writeValueAsString(jsonRoot);
} catch (Exception e) {
}
n.setUserData(stateInfo);
sendNotification(n);
/*
* Also send it from the StorageNode. A client can observe this event
* by subscribing ether to the StorageNode or to this RepNode.
*/
sn.sendProxyNotification(n);
replicationState = newState;
}
@Override
public String getRepNodeId() {
return rnId.getFullName();
}
@Override
public String getServiceStatus() {
return status.toString();
}
@Override
public float getIntervalLatAvg() {
return singleInterval.getLatency().getAvg();
}
@Override
public int getIntervalLatMax() {
return singleInterval.getLatency().getMax();
}
@Override
public int getIntervalLatMin() {
return singleInterval.getLatency().getMin();
}
@Override
public int getIntervalPct95() {
return singleInterval.getLatency().get95thPercent();
}
@Override
public int getIntervalPct99() {
return singleInterval.getLatency().get99thPercent();
}
@Override
public int getIntervalTotalOps() {
return singleInterval.getLatency().getTotalOps();
}
@Override
public Date getIntervalEnd() {
return new Date(singleInterval.getEnd());
}
@Override
public Date getIntervalStart() {
return new Date(singleInterval.getStart());
}
@Override
public long getIntervalThroughput() {
return singleInterval.getThroughputPerSec();
}
@Override
public float getCumulativeLatAvg() {
return singleCumulative.getLatency().getAvg();
}
@Override
public int getCumulativeLatMax() {
return singleCumulative.getLatency().getMax();
}
@Override
public int getCumulativeLatMin() {
return singleCumulative.getLatency().getMin();
}
@Override
public int getCumulativePct95() {
return singleCumulative.getLatency().get95thPercent();
}
@Override
public int getCumulativePct99() {
return singleCumulative.getLatency().get99thPercent();
}
@Override
public int getCumulativeTotalOps() {
return singleCumulative.getLatency().getTotalOps();
}
@Override
public Date getCumulativeEnd() {
return new Date(singleCumulative.getEnd());
}
@Override
public Date getCumulativeStart() {
return new Date(singleCumulative.getStart());
}
@Override
public long getCumulativeThroughput() {
return singleCumulative.getThroughputPerSec();
}
@Override
public float getMultiIntervalLatAvg() {
return multiInterval.getLatency().getAvg();
}
@Override
public int getMultiIntervalLatMax() {
return multiInterval.getLatency().getMax();
}
@Override
public int getMultiIntervalLatMin() {
return multiInterval.getLatency().getMin();
}
@Override
public int getMultiIntervalPct95() {
return multiInterval.getLatency().get95thPercent();
}
@Override
public int getMultiIntervalPct99() {
return multiInterval.getLatency().get99thPercent();
}
@Override
public int getMultiIntervalTotalOps() {
return multiInterval.getLatency().getTotalOps();
}
@Override
public int getMultiIntervalTotalRequests() {
return multiInterval.getLatency().getTotalRequests();
}
@Override
public Date getMultiIntervalEnd() {
return new Date(multiInterval.getEnd());
}
@Override
public Date getMultiIntervalStart() {
return new Date(multiInterval.getStart());
}
@Override
public long getMultiIntervalThroughput() {
return multiInterval.getThroughputPerSec();
}
@Override
public float getMultiCumulativeLatAvg() {
return multiCumulative.getLatency().getAvg();
}
@Override
public int getMultiCumulativeLatMax() {
return multiCumulative.getLatency().getMax();
}
@Override
public int getMultiCumulativeLatMin() {
return multiCumulative.getLatency().getMin();
}
@Override
public int getMultiCumulativePct95() {
return multiCumulative.getLatency().get95thPercent();
}
@Override
public int getMultiCumulativePct99() {
return multiCumulative.getLatency().get99thPercent();
}
@Override
public int getMultiCumulativeTotalOps() {
return multiCumulative.getLatency().getTotalOps();
}
@Override
public int getMultiCumulativeTotalRequests() {
return multiCumulative.getLatency().getTotalRequests();
}
@Override
public Date getMultiCumulativeEnd() {
return new Date(multiCumulative.getEnd());
}
@Override
public Date getMultiCumulativeStart() {
return new Date(multiCumulative.getStart());
}
@Override
public long getMultiCumulativeThroughput() {
return multiCumulative.getThroughputPerSec();
}
@Override
public long getCommitLag() {
/* Stub value for deprecated method */
return 0;
}
@Override
public String getConfigProperties() {
return parameters.getConfigProperties();
}
@Override
public String getJavaMiscParams() {
return parameters.getJavaMiscParams();
}
@Override
public String getLoggingConfigProps() {
return parameters.getLoggingConfigProps();
}
@Override
public boolean getCollectEnvStats() {
return parameters.getCollectEnvStats();
}
@Override
public int getCacheSize() {
return (int) (parameters.getJECacheSize() / (1024 * 1024));
}
@Override
public int getMaxTrackedLatency() {
return parameters.getMaxTrackedLatency();
}
@Override
public int getStatsInterval() {
return (int) sn.getCollectorInterval() / 1000; /* In seconds. */
}
@Override
public int getHeapMB() {
return (int) parameters.getMaxHeapMB();
}
@Override
public String getMountPoint() {
return parameters.getStorageDirectoryPath();
}
@Override
public long getMountPointSize() {
return parameters.getStorageDirectorySize();
}
@Override
public String getLogMountPoint() {
return parameters.getLogDirectoryPath();
}
@Override
public long getLogMountPointSize() {
return parameters.getLogDirectorySize();
}
@Override
public int getLatencyCeiling() {
return parameters.getLatencyCeiling();
}
@Override
public int getThroughputFloor() {
return parameters.getThroughputFloor();
}
@Override
public long getCommitLagThreshold() {
/* Stub value for deprecated method */
return 0;
}
@Override
public String getReplicationState() {
return replicationState.toString();
}
@Override
public String getOpMetric() {
return opMetricString;
}
@Override
public String getEnvMetric() {
return envMetricString;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy