All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hudson.util.RemotingDiagnostics Maven / Gradle / Ivy

The newest version!
/**
 * *****************************************************************************
 *
 * Copyright (c) 2004-2010 Oracle Corporation.
 *
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *
 * Kohsuke Kawaguchi, Winston Prakash
 *
 ******************************************************************************
 */
package hudson.util;

import hudson.FilePath;
import hudson.Functions;
import hudson.model.Hudson;
import hudson.remoting.Callable;
import hudson.remoting.DelegatingCallable;
import hudson.remoting.VirtualChannel;
import hudson.security.AccessControlled;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.WebMethod;

import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import org.eclipse.hudson.script.ScriptSupport;

/**
 * Various remoting operations related to diagnostics.
 *
 * 

These code are useful wherever {@link VirtualChannel} is used, such as * master, slaves, Maven JVMs, etc. * * @author Kohsuke Kawaguchi * @since 1.175 */ public final class RemotingDiagnostics { public static Map getSystemProperties(VirtualChannel channel) throws IOException, InterruptedException { if (channel == null) { return Collections.singletonMap("N/A", "N/A"); } return channel.call(new GetSystemProperties()); } private static final class GetSystemProperties implements Callable, RuntimeException> { public Map call() { return new TreeMap(System.getProperties()); } private static final long serialVersionUID = 1L; } public static Map getThreadDump(VirtualChannel channel) throws IOException, InterruptedException { if (channel == null) { return Collections.singletonMap("N/A", "N/A"); } return channel.call(new GetThreadDump()); } private static final class GetThreadDump implements Callable, RuntimeException> { public Map call() { Map r = new LinkedHashMap(); try { ThreadInfo[] data = Functions.getThreadInfos(); Functions.ThreadGroupMap map = Functions.sortThreadsAndGetGroupMap(data); for (ThreadInfo ti : data) { r.put(ti.getThreadName(), Functions.dumpThreadInfo(ti, map)); } } catch (LinkageError _) { // not in JDK6. fall back to JDK5 r.clear(); for (Map.Entry t : Functions.dumpAllThreads().entrySet()) { StringBuilder buf = new StringBuilder(); for (StackTraceElement e : t.getValue()) { buf.append(e).append('\n'); } r.put(t.getKey().getName(), buf.toString()); } } return r; } private static final long serialVersionUID = 1L; } /** * Executes script remotely. */ public static String executeScript(String script, VirtualChannel channel) throws IOException, InterruptedException { return channel.call(new Script(script)); } public static String executeScript(String script, VirtualChannel channel, ScriptSupport scriptSupport) throws IOException, InterruptedException { return channel.call(new Script(script, scriptSupport)); } private static final class Script implements DelegatingCallable { private final String script; private transient ClassLoader parentClassLoader; private ScriptSupport scriptSupport; private Script(String script) { this.script = script; parentClassLoader = getClassLoader(); } private Script(String script, String scriptType) { this(script); if (scriptType != null) { for (ScriptSupport scriptSupport : ScriptSupport.getAvailableScriptSupports()) { if (scriptSupport.hasSupport(scriptType)) { this.scriptSupport = scriptSupport; } } } } private Script(String script, ScriptSupport scriptSupport) { this(script); this.scriptSupport = scriptSupport; } public ClassLoader getClassLoader() { return Hudson.getInstance().getPluginManager().uberClassLoader; } public String call() throws RuntimeException { if (scriptSupport != null) { // if we run locally, cl!=null. Otherwise the delegating classloader will be available as context classloader. if (parentClassLoader == null) { parentClassLoader = Thread.currentThread().getContextClassLoader(); } StringWriter out = new StringWriter(); PrintWriter printWriter = new PrintWriter(out); if (scriptSupport != null) { scriptSupport.evaluate(parentClassLoader, script, null, printWriter); return out.toString(); } else { return "No script support to execute the script. Install script support plugin"; } } return ""; } } /** * Obtains the heap dump in an HPROF file. */ public static FilePath getHeapDump(VirtualChannel channel) throws IOException, InterruptedException { return channel.call(new Callable() { public FilePath call() throws IOException { final File hprof = File.createTempFile("hudson-heapdump", "hprof"); hprof.delete(); try { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); server.invoke(new ObjectName("com.sun.management:type=HotSpotDiagnostic"), "dumpHeap", new Object[]{hprof.getAbsolutePath(), true}, new String[]{String.class.getName(), boolean.class.getName()}); return new FilePath(hprof); } catch (JMException e) { throw new IOException2(e); } } private static final long serialVersionUID = 1L; }); } /** * Heap dump, exposable to URL via Stapler. * */ public static class HeapDump { private final AccessControlled owner; private final VirtualChannel channel; public HeapDump(AccessControlled owner, VirtualChannel channel) { this.owner = owner; this.channel = channel; } /** * Obtains the heap dump. */ public void doIndex(StaplerResponse rsp) throws IOException { rsp.sendRedirect("heapdump.hprof"); } @WebMethod(name = "heapdump.hprof") public void doHeapDump(StaplerRequest req, StaplerResponse rsp) throws IOException, InterruptedException { owner.checkPermission(Hudson.ADMINISTER); rsp.setContentType("application/octet-stream"); FilePath dump = obtain(); try { dump.copyTo(rsp.getCompressedOutputStream(req)); } finally { dump.delete(); } } public FilePath obtain() throws IOException, InterruptedException { return RemotingDiagnostics.getHeapDump(channel); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy