Skip to content
Permalink
Browse files
Merge pull request #119 from escoem/JENKINS-22791
[JENKINS-22791] Record heap histograms
  • Loading branch information
christ66 committed Oct 23, 2017
2 parents 6cb4198 + 2563101 commit ea8b5b929a0cd7196f70018e8ae3e1e5845809d1
Showing with 97 additions and 0 deletions.
  1. +97 −0 src/main/java/com/cloudbees/jenkins/support/impl/HeapUsageHistogram.java
@@ -0,0 +1,97 @@
package com.cloudbees.jenkins.support.impl;

import com.cloudbees.jenkins.support.AsyncResultCache;
import com.cloudbees.jenkins.support.api.Component;
import com.cloudbees.jenkins.support.api.Container;
import com.cloudbees.jenkins.support.api.Content;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.model.Node;
import hudson.remoting.Callable;
import hudson.security.Permission;
import jenkins.model.Jenkins;
import org.jenkinsci.remoting.RoleChecker;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.management.ManagementFactory;
import java.util.Collections;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Heap histogram from master node.
*/
@Extension
@Restricted(NoExternalUse.class)
public class HeapUsageHistogram extends Component {
// first 200 classes so 203 lines required because of the header
private static final int MAX = 203;

private static final Logger logger = Logger.getLogger(HeapUsageHistogram.class.getName());

@NonNull
@Override
public Set<Permission> getRequiredPermissions() {
return Collections.singleton(Jenkins.ADMINISTER);
}

@NonNull
@Override
public String getDisplayName() {
return "Master Heap Histogram";
}

@Override
public void addContents(@NonNull Container result) {
result.add(
new Content("nodes/master/heap-histogram.txt") {
@Override
public void writeTo(OutputStream os) throws IOException {
os.write(getLiveHistogram().getBytes("UTF-8"));
}
}
);
}

private String getLiveHistogram() throws IOException {
final String raw = getRawLiveHistogram();
final String[] lines = raw.split("\n");
final int limit = MAX <= lines.length ? MAX : lines.length;

final StringBuilder bos = new StringBuilder();
//starting in 1 because of an empty line
for (int i=1; i<limit; i++) {
bos.append(lines[i]).append('\n');
}

return bos.toString();
}

private String getRawLiveHistogram() {
String result;
try {
ObjectName objName = new ObjectName("com.sun.management:type=DiagnosticCommand");
MBeanServer platform = ManagementFactory.getPlatformMBeanServer();
if (platform == null) {
return "N/A";
}
result = (String) platform.invoke(objName, "gcClassHistogram", new Object[] {null}, new String[]{String[].class.getName()});
}
catch (InstanceNotFoundException | ReflectionException | MBeanException | MalformedObjectNameException e) {
logger.log(Level.WARNING,"Could not record heap live histogram.", e);
result = "N/A";
}
return result;
}
}

0 comments on commit ea8b5b9

Please sign in to comment.