Skip to content

Commit

Permalink
Merge pull request #112 from batmat/JENKINS-44236
Browse files Browse the repository at this point in the history
[JENKINS-44236] NFS stats related /proc files should also be gathered
  • Loading branch information
batmat committed May 17, 2017
2 parents 06293e9 + 63b463e commit 5eebe47
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 148 deletions.
@@ -1,110 +1,39 @@
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.FileContent;
import com.cloudbees.jenkins.support.util.Helper;
import com.cloudbees.jenkins.support.util.SystemPlatform;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.security.Permission;
import hudson.slaves.SlaveComputer;
import jenkins.model.Jenkins;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

/**
* System metrics of the JVM process. Only support Unix
* System metrics of the JVM process. Only supports Unix.
*/
@Extension
public class JVMProcessSystemMetricsContents extends Component {
public class JVMProcessSystemMetricsContents extends ProcFilesRetriever {

private static final Logger LOGGER = Logger.getLogger(JVMProcessSystemMetricsContents.class.getName());

private final WeakHashMap<Node,SystemPlatform> systemPlatformCache = new WeakHashMap<Node, SystemPlatform>();

static Map<String,String> UNIX_PROC_CONTENTS;
static final Map<String,String> UNIX_PROC_CONTENTS;
static {
UNIX_PROC_CONTENTS = new HashMap<String,String>();
UNIX_PROC_CONTENTS.put("/proc/meminfo", "meminfo.txt");
UNIX_PROC_CONTENTS.put("/proc/self/status", "self/status.txt");
UNIX_PROC_CONTENTS.put("/proc/self/cmdline", "self/cmdline");
UNIX_PROC_CONTENTS.put("/proc/self/environ", "self/environ");
UNIX_PROC_CONTENTS.put("/proc/self/limits", "self/limits.txt");
UNIX_PROC_CONTENTS.put("/proc/self/mountstats", "self/mountstats.txt");
}

@Override
@NonNull
public String getDisplayName() {
return "JVM process system metrics (Linux only)";
}

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

@Override
public void addContents(@NonNull Container container) {
Jenkins j = Helper.getActiveInstance();
addUnixContents(container, j);

for (Node node : j.getNodes()) {
addUnixContents(container, node);
}
}

private void addUnixContents(@NonNull Container container, final @NonNull Node node) {
Computer c = node.toComputer();
if (c == null) {
return;
}
// fast path bailout for Windows
if (c instanceof SlaveComputer && !Boolean.TRUE.equals(((SlaveComputer) c).isUnix())) {
return;
}
SystemPlatform nodeSystemPlatform = getSystemPlatform(node);
if (!SystemPlatform.LINUX.equals(nodeSystemPlatform)) {
return;
}
String name;
if (node instanceof Jenkins) {
name = "master";
} else {
name = "slave/" + node.getNodeName();
}

for (Map.Entry<String,String> procDescriptor : UNIX_PROC_CONTENTS.entrySet()) {
container.add(new FileContent("nodes/" + name + "/proc/" + procDescriptor.getValue(), new File(procDescriptor.getKey())));
}
}

public SystemPlatform getSystemPlatform(Node node) {
try {
return AsyncResultCache.get(node, systemPlatformCache, new SystemPlatform.GetCurrentPlatform(), "platform", SystemPlatform.UNKNOWN);
} catch (IOException e) {
final LogRecord lr = new LogRecord(Level.FINE, "Could not retrieve system platform type from {0}");
lr.setParameters(new Object[]{getNodeName(node)});
lr.setThrown(e);
LOGGER.log(lr);
}
return SystemPlatform.UNKNOWN;
}

private static String getNodeName(Node node) {
return node instanceof Jenkins ? "master" : node.getNodeName();
@NonNull
public String getDisplayName() {
return "JVM process system metrics (Linux only)";
}
}
@@ -0,0 +1,116 @@
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.FileContent;
import com.cloudbees.jenkins.support.util.Helper;
import com.cloudbees.jenkins.support.util.SystemPlatform;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.security.Permission;
import hudson.slaves.SlaveComputer;
import jenkins.model.Jenkins;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

/**
* Base class for gathering specified /proc files
*/
public abstract class ProcFilesRetriever extends Component {
private static final Logger LOGGER = Logger.getLogger(ProcFilesRetriever.class.getName());
private final WeakHashMap<Node, SystemPlatform> systemPlatformCache = new WeakHashMap<>();

protected static String getNodeName(Node node) {
return node instanceof Jenkins ? "master" : node.getNodeName();
}

/**
* Returns the map of files that should be retrieved.
* <p>
* <code>file name =&gt; path in the support bundle</code>.
* </p>
* <p>
* For example <code>/proc/meminfo =&gt; meminfo.txt</code>.
* </p>
*
* @return the map of files that should be retrieved and put in the support bundle.
*/
abstract public Map<String, String> getFilesToRetrieve();

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

@Override
public void addContents(@NonNull Container container) {
Jenkins j = Helper.getActiveInstance();
addUnixContents(container, j);

for (Node node : j.getNodes()) {
addUnixContents(container, node);
}
}

protected void addUnixContents(@NonNull Container container, final @NonNull Node node) {
Computer c = node.toComputer();
if (c == null) {
return;
}
// fast path bailout for Windows
if (c instanceof SlaveComputer && !Boolean.TRUE.equals(((SlaveComputer) c).isUnix())) {
return;
}
SystemPlatform nodeSystemPlatform = getSystemPlatform(node);
if (!SystemPlatform.LINUX.equals(nodeSystemPlatform)) {
return;
}
String name;
if (node instanceof Jenkins) {
name = "master";
} else {
name = "slave/" + node.getNodeName();
}

for (Map.Entry<String, String> procDescriptor : getFilesToRetrieve().entrySet()) {
container.add(new FileContent("nodes/" + name + "/proc/" + procDescriptor.getValue(),
new File(procDescriptor.getKey())));
}

afterAddUnixContents(container, node, name);
}

/**
* Override this method if you want to hook some code after {@link #addUnixContents(Container, Node)}.
*
* @param container the support {@link Container}.
* @param node the node for which the method is called.
* @param name the node name, <em>"master"</em> if Master, and <em>slave/${nodeName}</em> if an agent.
*/
protected void afterAddUnixContents(@NonNull Container container, final @NonNull Node node, String name) {
}

public SystemPlatform getSystemPlatform(Node node) {
try {
return AsyncResultCache.get(node, systemPlatformCache, new SystemPlatform.GetCurrentPlatform(), "platform",
SystemPlatform.UNKNOWN);
} catch (IOException e) {
final LogRecord record = new LogRecord(Level.FINE, "Could not retrieve system platform type from {0}");
record.setParameters(new Object[]{getNodeName(node)});
record.setThrown(e);
LOGGER.log(record);
}
return SystemPlatform.UNKNOWN;
}
}
Expand Up @@ -26,29 +26,19 @@

import com.cloudbees.jenkins.support.AsyncResultCache;
import com.cloudbees.jenkins.support.api.CommandOutputContent;
import com.cloudbees.jenkins.support.api.Component;
import com.cloudbees.jenkins.support.api.Container;
import com.cloudbees.jenkins.support.api.FileContent;
import com.cloudbees.jenkins.support.api.StringContent;
import com.cloudbees.jenkins.support.util.Helper;
import com.cloudbees.jenkins.support.util.SystemPlatform;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.Util;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.remoting.Callable;
import hudson.security.Permission;
import hudson.slaves.SlaveComputer;
import jenkins.model.Jenkins;
import org.jenkinsci.remoting.RoleChecker;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand All @@ -58,9 +48,7 @@
* kernel messages and entropy)
*/
@Extension
public class SystemConfiguration extends Component {

private final WeakHashMap<Node,SystemPlatform> systemPlatformCache = new WeakHashMap<Node, SystemPlatform>();
public class SystemConfiguration extends ProcFilesRetriever {

private final WeakHashMap<Node,String> sysCtlCache = new WeakHashMap<Node, String>();

Expand All @@ -69,75 +57,36 @@ public class SystemConfiguration extends Component {
private final WeakHashMap<Node,String> dmiCache = new WeakHashMap<Node, String>();

private static final Logger LOGGER = Logger.getLogger(SystemConfiguration.class.getName());
private static final Map<String,String> UNIX_PROC_CONTENTS;

static Map<String,String> UNIX_PROC_CONTENTS;
static {
UNIX_PROC_CONTENTS = new HashMap<String,String>();
UNIX_PROC_CONTENTS.put("/proc/swaps", "swaps.txt");
UNIX_PROC_CONTENTS.put("/proc/cpuinfo", "cpuinfo.txt");
UNIX_PROC_CONTENTS.put("/proc/mounts", "mounts.txt");
UNIX_PROC_CONTENTS.put("/proc/uptime", "system-uptime.txt");
UNIX_PROC_CONTENTS.put("/proc/net/rpc/nfs", "net/rpc/nfs.txt");
UNIX_PROC_CONTENTS.put("/proc/net/rpc/nfsd", "net/rpc/nfsd.txt");
}

@Override
@NonNull
public String getDisplayName() {
return "System configuration (Linux only)";
public Map<String, String> getFilesToRetrieve() {
return UNIX_PROC_CONTENTS;
}

@NonNull
@Override
public Set<Permission> getRequiredPermissions() {
return Collections.singleton(Jenkins.ADMINISTER);
@NonNull
public String getDisplayName() {
return "System configuration (Linux only)";
}

@Override
public void addContents(@NonNull Container container) {
Jenkins j = Helper.getActiveInstance();
addUnixContents(container, j);

for (Node node : j.getNodes()) {
addUnixContents(container, node);
}
}

private void addUnixContents(@NonNull Container container, final @NonNull Node node) {
Computer c = node.toComputer();
if (c == null) {
return;
}
// fast path bailout for Windows
if (c instanceof SlaveComputer && !Boolean.TRUE.equals(((SlaveComputer) c).isUnix())) {
return;
}
SystemPlatform nodeSystemPlatform = getSystemPlatform(node);
if (!SystemPlatform.LINUX.equals(nodeSystemPlatform)) {
return;
}
String name;
if (node instanceof Jenkins) {
name = "master";
} else {
name = "slave/" + node.getNodeName();
}

for (Map.Entry<String, String> procDescriptor : UNIX_PROC_CONTENTS.entrySet()) {
container.add(new FileContent("nodes/" + name + "/proc/" + procDescriptor.getValue(), new File(procDescriptor.getKey())));
}

container.add(CommandOutputContent.runOnNodeAndCache(sysCtlCache, node, "nodes/" + name + "/sysctl.txt", "/bin/sh", "-c", "sysctl -a"));
protected void afterAddUnixContents(@NonNull Container container, final @NonNull Node node, String name) {
container.add(
CommandOutputContent.runOnNodeAndCache(sysCtlCache, node, "nodes/" + name + "/sysctl.txt", "/bin/sh", "-c", "sysctl -a"));
container.add(CommandOutputContent.runOnNode(node, "nodes/" + name + "/dmesg.txt", "/bin/sh", "-c", "dmesg | tail -1000"));
container.add(CommandOutputContent.runOnNodeAndCache(userIdCache, node, "nodes/" + name + "/userid.txt", "/bin/sh", "-c", "id -a"));
container.add(new StringContent( "nodes/" + name + "/dmi.txt", getDmiInfo(node)));
}

public SystemPlatform getSystemPlatform(Node node) {
try {
return AsyncResultCache.get(node, systemPlatformCache, new SystemPlatform.GetCurrentPlatform(), "platform", SystemPlatform.UNKNOWN);
} catch (IOException e) {
LOGGER.log(Level.FINE, "Could not retrieve command content from " + getNodeName(node), e);
}
return SystemPlatform.UNKNOWN;
container.add(new StringContent("nodes/" + name + "/dmi.txt", getDmiInfo(node)));
}

public String getDmiInfo(Node node) {
Expand Down Expand Up @@ -179,8 +128,4 @@ public void checkRoles(RoleChecker checker) throws SecurityException {
// TODO: do we have to verify some role?
}
}

private static String getNodeName(Node node) {
return node instanceof Jenkins ? "master" : node.getNodeName();
}
}

0 comments on commit 5eebe47

Please sign in to comment.