All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
co.paralleluniverse.fibers.JMXFibersMonitor Maven / Gradle / Ivy
Go to download
The core library for Fibers on Java, compatible with Java 11-16. Forked from puniverse/quasar
/*
* Quasar: lightweight threads and actors for the JVM.
* Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 3.0
* as published by the Free Software Foundation.
*/
package co.paralleluniverse.fibers;
import co.paralleluniverse.common.monitoring.Counter;
import co.paralleluniverse.common.monitoring.MonitoringServices;
import co.paralleluniverse.strands.Strand;
import java.lang.management.ManagementFactory;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.StandardEmitterMBean;
/**
* A JMX Mbean that monitors fibers runningin a single {@link FiberScheduler}.
*
* @author pron
*/
class JMXFibersMonitor extends StandardEmitterMBean implements FibersMonitor, NotificationListener, FibersMXBean {
private final String mbeanName;
private final FiberScheduler scheduler;
private boolean registered;
private long lastCollectTime;
private final FibersDetailedMonitor details;
private final Counter activeCount = new Counter();
//private final Counter runnableCount = new Counter();
private final Counter waitingCount = new Counter();
private final Counter spuriousWakeupsCounter = new Counter();
private final Counter timedWakeupsCounter = new Counter();
private final Counter timedParkLatencyCounter = new Counter();
private long spuriousWakeups;
private long meanTimedWakeupLatency;
private Map problemFibers;
private long notificationSequenceNumber = 1;
public JMXFibersMonitor(String name, FiberScheduler scheduler, boolean detailedInfo) {
super(FibersMXBean.class, true, new NotificationBroadcasterSupport());
this.scheduler = scheduler;
this.mbeanName = "co.paralleluniverse:type=Fibers,name=" + name;
registerMBean();
lastCollectTime = nanoTime();
this.details = detailedInfo ? new FibersDetailedMonitor() : null;
}
@SuppressWarnings({"CallToPrintStackTrace", "CallToThreadDumpStack"})
protected void registerMBean() {
try {
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
final ObjectName mxbeanName = new ObjectName(mbeanName);
mbs.registerMBean(this, mxbeanName);
this.registered = true;
} catch (InstanceAlreadyExistsException ex) {
throw new RuntimeException(ex);
} catch (MBeanRegistrationException ex) {
ex.printStackTrace();
} catch (NotCompliantMBeanException ex) {
throw new AssertionError(ex);
} catch (MalformedObjectNameException ex) {
throw new AssertionError(ex);
}
MonitoringServices.getInstance().addPerfNotificationListener(this, mbeanName);
}
@SuppressWarnings({"CallToPrintStackTrace", "CallToThreadDumpStack"})
@Override
public void unregister() {
try {
if (registered) {
MonitoringServices.getInstance().removePerfNotificationListener(this);
ManagementFactory.getPlatformMBeanServer().unregisterMBean(new ObjectName(mbeanName));
}
this.registered = false;
} catch (InstanceNotFoundException ex) {
ex.printStackTrace();
} catch (MBeanRegistrationException ex) {
ex.printStackTrace();
} catch (MalformedObjectNameException ex) {
throw new AssertionError(ex);
}
}
@Override
public void handleNotification(Notification notification, Object handback) {
if ("perfTimer".equals(notification.getType()))
refresh();
}
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
MBeanNotificationInfo info = new MBeanNotificationInfo(
new String[]{RunawayFiberNotification.NAME},
RunawayFiberNotification.class.getName(),
"Runaway fiber detected");
return new MBeanNotificationInfo[]{info};
}
@Override
public void refresh() {
collectAndResetCounters();
}
public boolean isRegistered() {
return registered;
}
private void collectAndResetCounters() {
if (isRegistered()) {
collectAndResetCounters(nanoTime() - lastCollectTime);
}
}
protected void collectAndResetCounters(long intervalNanos) {
spuriousWakeups = spuriousWakeupsCounter.getAndReset();
final long tw = timedWakeupsCounter.getAndReset();
final long tpl = timedParkLatencyCounter.getAndReset();
meanTimedWakeupLatency = tw != 0L ? tpl / tw : 0L;
lastCollectTime = nanoTime();
}
private long nanoTime() {
return System.nanoTime();
}
@Override
public void fiberStarted(Fiber fiber) {
activeCount.inc();
if (details != null)
details.fiberStarted(fiber);
}
@Override
public void fiberTerminated(Fiber fiber) {
activeCount.dec();
//runnableCount.dec();
if (details != null)
details.fiberTerminated(fiber);
}
@Override
public void fiberSuspended() {
//runnableCount.dec();
waitingCount.inc();
}
@Override
public void fiberResumed() {
//runnableCount.inc();
waitingCount.dec();
}
@Override
public void spuriousWakeup() {
spuriousWakeupsCounter.inc();
}
@Override
public void timedParkLatency(long ns) {
timedWakeupsCounter.inc();
timedParkLatencyCounter.add(ns);
}
@Override
public void setRunawayFibers(Collection fs) {
if (fs == null || fs.isEmpty())
this.problemFibers = null;
else {
Map map = new HashMap<>();
for (Fiber f : fs) {
Thread t = f.getRunningThread();
final String status;
if (t == null)
status = "hogging the CPU or blocking a thread";
else if (t.getState() == Thread.State.RUNNABLE)
status = "hogging the CPU (" + t + ")";
else
status = "blocking a thread (" + t + ")";
StackTraceElement[] st = f.getStackTrace();
Map pf = problemFibers;
if (pf == null || !pf.containsKey(f)) {
Notification n = new RunawayFiberNotification(this, notificationSequenceNumber++, System.currentTimeMillis(),
"Runaway fiber " + f.getName() + " is " + status + ":\n" + Strand.toString(st));
sendNotification(n);
}
map.put(f, st);
}
this.problemFibers = map;
}
}
@Override
public Map getRunawayFibers() {
Map map = new HashMap<>();
for (Map.Entry e : problemFibers.entrySet())
map.put(e.getKey().toString(), Strand.toString(e.getValue()));
return map;
}
@Override
public int getNumActiveFibers() {
return (int)activeCount.get();
}
@Override
public int getNumRunnableFibers() {
return getNumActiveFibers() - getNumWaitingFibers();
//return runnableCount.intValue();
}
@Override
public int getNumWaitingFibers() {
return (int)waitingCount.get();
}
@Override
public int getTimedQueueLength() {
return scheduler.getTimedQueueLength();
}
@Override
public long getSpuriousWakeups() {
return spuriousWakeups;
}
@Override
public long getMeanTimedWakeupLatency() {
return meanTimedWakeupLatency;
}
@Override
public long[] getAllFiberIds() {
if (details == null)
return null;
return details.getAllFiberIds();
}
@Override
public FiberInfo getFiberInfo(long id, boolean stack) {
if (details == null)
return null;
return details.getFiberInfo(id, stack);
}
@Override
public FiberInfo[] getFiberInfo(long[] ids, boolean stack) {
if (details == null)
return null;
return details.getFiberInfo(ids, stack);
}
private static class RunawayFiberNotification extends Notification {
static final String NAME = "co.paralleluniverse.fibers.runawayfiber";
public RunawayFiberNotification(String type, Object source, long sequenceNumber, String message) {
super(NAME, source, sequenceNumber, message);
}
public RunawayFiberNotification(Object source, long sequenceNumber, long timeStamp, String message) {
super(NAME, source, sequenceNumber, timeStamp, message);
}
}
}