Log Message
[JENKINS-20935] Provide separate monitoring pages for each slave node
Modified Paths
- trunk/hudson/plugins/monitoring/src/main/java/net/bull/javamelody/NodesCollector.java
- trunk/hudson/plugins/monitoring/src/main/java/net/bull/javamelody/NodesController.java
- trunk/hudson/plugins/monitoring/src/main/java/net/bull/javamelody/RemoteCallHelper.java
- trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/HudsonMonitoringFilter.java
Added Paths
- trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/NodeMonitoringAction.java
- trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/NodesMonitoringActionFactory.java
- trunk/hudson/plugins/monitoring/src/main/resources/net/
- trunk/hudson/plugins/monitoring/src/main/resources/net/bull/
- trunk/hudson/plugins/monitoring/src/main/resources/net/bull/javamelody/
- trunk/hudson/plugins/monitoring/src/main/resources/net/bull/javamelody/NodesColumn/
Diff
Modified: trunk/hudson/plugins/monitoring/src/main/java/net/bull/javamelody/NodesCollector.java (41033 => 41034)
--- trunk/hudson/plugins/monitoring/src/main/java/net/bull/javamelody/NodesCollector.java 2013-12-08 13:58:41 UTC (rev 41033)
+++ trunk/hudson/plugins/monitoring/src/main/java/net/bull/javamelody/NodesCollector.java 2013-12-22 08:49:14 UTC (rev 41034)
@@ -18,8 +18,10 @@
*/
package net.bull.javamelody;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
@@ -44,7 +46,7 @@
private final boolean monitoringDisabled;
private final Timer timer;
private final Collector collector;
- private List<JavaInformations> lastJavaInformationsList;
+ private Map<String, JavaInformations> lastJavaInformationsList;
/**
* Constructor.
@@ -126,7 +128,8 @@
*/
public void collectWithoutErrors() {
try {
- lastJavaInformationsList = RemoteCallHelper.collectJavaInformationsList();
+ lastJavaInformationsList = new RemoteCallHelper(null)
+ .collectJavaInformationsListByName();
// inspired by https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/LoadStatistics.java#L197
// (note: jobs in quiet period are not counted)
@@ -136,7 +139,9 @@
// including values for buildQueueLength in translations*.properties
JdbcWrapper.BUILD_QUEUE_LENGTH.set(queueLength);
- collector.collectWithoutErrors(lastJavaInformationsList);
+ final List<JavaInformations> javaInformations = new ArrayList<JavaInformations>(
+ getLastJavaInformationsList().values());
+ collector.collectWithoutErrors(javaInformations);
} catch (final Throwable t) { // NOPMD
LOG.warn("exception while collecting data", t);
}
@@ -156,8 +161,9 @@
public void run() {
try {
// send the report
- new MailReport().sendReportMail(getCollector(), true,
- getLastJavaInformationsList(), period);
+ final List<JavaInformations> javaInformations = new ArrayList<JavaInformations>(
+ getLastJavaInformationsList().values());
+ new MailReport().sendReportMail(getCollector(), true, javaInformations, period);
} catch (final Throwable t) { // NOPMD
// no error in this task
LOG.warn("sending mail report failed", t);
@@ -178,7 +184,7 @@
return collector;
}
- List<JavaInformations> getLastJavaInformationsList() {
+ Map<String, JavaInformations> getLastJavaInformationsList() {
return lastJavaInformationsList;
}
Modified: trunk/hudson/plugins/monitoring/src/main/java/net/bull/javamelody/NodesController.java (41033 => 41034)
--- trunk/hudson/plugins/monitoring/src/main/java/net/bull/javamelody/NodesController.java 2013-12-08 13:58:41 UTC (rev 41033)
+++ trunk/hudson/plugins/monitoring/src/main/java/net/bull/javamelody/NodesController.java 2013-12-22 08:49:14 UTC (rev 41034)
@@ -36,6 +36,7 @@
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -52,17 +53,26 @@
*/
public class NodesController {
private final Collector collector;
+ private final String nodeName;
private final List<JavaInformations> lastJavaInformationsList;
private final HttpCookieManager httpCookieManager = new HttpCookieManager();
/**
* Constructor.
* @param nodesCollector NodesCollector
+ * @param nodeName Nom du node
*/
- public NodesController(NodesCollector nodesCollector) {
+ public NodesController(NodesCollector nodesCollector, String nodeName) {
super();
this.collector = nodesCollector.getCollector();
- this.lastJavaInformationsList = nodesCollector.getLastJavaInformationsList();
+ this.nodeName = nodeName;
+ if (nodeName == null) {
+ this.lastJavaInformationsList = new ArrayList<JavaInformations>(nodesCollector
+ .getLastJavaInformationsList().values());
+ } else {
+ this.lastJavaInformationsList = Collections.singletonList(nodesCollector
+ .getLastJavaInformationsList().get(nodeName));
+ }
}
/**
@@ -93,8 +103,8 @@
final String threadId = req.getParameter(THREAD_ID_PARAMETER);
final String jobId = req.getParameter(JOB_ID_PARAMETER);
final String cacheId = req.getParameter(CACHE_ID_PARAMETER);
- messageForReport = RemoteCallHelper.forwardAction(actionName, sessionId,
- threadId, jobId, cacheId);
+ messageForReport = getRemoteCallHelper().forwardAction(actionName,
+ sessionId, threadId, jobId, cacheId);
} else {
// necessaire si action clear_counter
messageForReport = monitoringController.executeActionIfNeeded(req);
@@ -103,8 +113,8 @@
final SerializableController serializableController = new SerializableController(
collector);
final Range range = serializableController.getRangeForSerializable(req);
- final List<JavaInformations> javaInformationsList = RemoteCallHelper
- .collectJavaInformationsList();
+ final List<JavaInformations> javaInformationsList = new ArrayList<JavaInformations>(
+ getRemoteCallHelper().collectJavaInformationsListByName().values());
final Serializable serializable = serializableController
.createDefaultSerializable(javaInformationsList, range,
messageForReport);
@@ -117,8 +127,8 @@
final String formatParameter = req.getParameter(FORMAT_PARAMETER);
if (req.getParameter(JMX_VALUE) != null) {
- final List<String> jmxValues = RemoteCallHelper.collectJmxValues(req
- .getParameter(JMX_VALUE));
+ final List<String> jmxValues = getRemoteCallHelper().collectJmxValues(
+ req.getParameter(JMX_VALUE));
doJmxValue(resp, jmxValues);
} else if (TransportFormat.isATransportFormat(req.getParameter(FORMAT_PARAMETER))) {
doCompressedSerializable(req, resp, monitoringController);
@@ -160,18 +170,19 @@
private void doPdf(HttpServletRequest req, HttpServletResponse resp,
MonitoringController monitoringController) throws IOException, InterruptedException,
ExecutionException {
- if (PROCESSES_PART.equalsIgnoreCase(req.getParameter(PART_PARAMETER))) {
+ final String partParameter = req.getParameter(PART_PARAMETER);
+ if (PROCESSES_PART.equalsIgnoreCase(partParameter)) {
monitoringController.addPdfContentTypeAndDisposition(req, resp);
- final Map<String, List<ProcessInformations>> processInformationsByNodeName = RemoteCallHelper
+ final Map<String, List<ProcessInformations>> processInformationsByNodeName = getRemoteCallHelper()
.collectProcessInformationsByNodeName();
try {
doPdfProcesses(resp, processInformationsByNodeName);
} finally {
resp.getOutputStream().flush();
}
- } else if (MBEANS_PART.equalsIgnoreCase(req.getParameter(PART_PARAMETER))) {
+ } else if (MBEANS_PART.equalsIgnoreCase(partParameter)) {
monitoringController.addPdfContentTypeAndDisposition(req, resp);
- final Map<String, List<MBeanNode>> mbeanNodesByNodeName = RemoteCallHelper
+ final Map<String, List<MBeanNode>> mbeanNodesByNodeName = getRemoteCallHelper()
.collectMBeanNodesByNodeName();
try {
doPdfMBeans(resp, mbeanNodesByNodeName);
@@ -224,15 +235,15 @@
InterruptedException, ExecutionException {
// ici, ni web.xml ni pom.xml
if (MBEANS_PART.equalsIgnoreCase(partParameter)) {
- final Map<String, List<MBeanNode>> mbeanNodesByNodeName = RemoteCallHelper
+ final Map<String, List<MBeanNode>> mbeanNodesByNodeName = getRemoteCallHelper()
.collectMBeanNodesByNodeName();
doMBeans(req, resp, mbeanNodesByNodeName);
} else if (PROCESSES_PART.equalsIgnoreCase(partParameter)) {
- final Map<String, List<ProcessInformations>> processInformationsByNodeName = RemoteCallHelper
+ final Map<String, List<ProcessInformations>> processInformationsByNodeName = getRemoteCallHelper()
.collectProcessInformationsByNodeName();
doProcesses(req, resp, processInformationsByNodeName);
} else if (HEAP_HISTO_PART.equalsIgnoreCase(partParameter)) {
- final HeapHistogram heapHistoTotal = RemoteCallHelper.collectGlobalHeapHistogram();
+ final HeapHistogram heapHistoTotal = getRemoteCallHelper().collectGlobalHeapHistogram();
doHeapHisto(req, resp, heapHistoTotal, monitoringController);
} else {
monitoringController.doReport(req, resp, lastJavaInformationsList);
@@ -312,13 +323,13 @@
private Serializable createSerializable(HttpServletRequest httpRequest) throws Exception { // NOPMD
final String part = httpRequest.getParameter(PART_PARAMETER);
if (MBEANS_PART.equalsIgnoreCase(part)) {
- return new LinkedHashMap<String, List<MBeanNode>>(
- RemoteCallHelper.collectMBeanNodesByNodeName());
+ return new LinkedHashMap<String, List<MBeanNode>>(getRemoteCallHelper()
+ .collectMBeanNodesByNodeName());
} else if (PROCESSES_PART.equalsIgnoreCase(part)) {
- return new LinkedHashMap<String, List<ProcessInformations>>(
- RemoteCallHelper.collectProcessInformationsByNodeName());
+ return new LinkedHashMap<String, List<ProcessInformations>>(getRemoteCallHelper()
+ .collectProcessInformationsByNodeName());
} else if (HEAP_HISTO_PART.equalsIgnoreCase(part)) {
- return RemoteCallHelper.collectGlobalHeapHistogram();
+ return getRemoteCallHelper().collectGlobalHeapHistogram();
} else if (THREADS_PART.equalsIgnoreCase(part)) {
final ArrayList<List<ThreadInformations>> result = new ArrayList<List<ThreadInformations>>();
for (final JavaInformations javaInformations : lastJavaInformationsList) {
@@ -348,6 +359,10 @@
return new PrintWriter(MonitoringController.getWriter(httpResponse));
}
+ private RemoteCallHelper getRemoteCallHelper() {
+ return new RemoteCallHelper(nodeName);
+ }
+
/**
* Is it necessary to collect java informations for this monitoring request?
* @param httpRequest HttpServletRequest
Modified: trunk/hudson/plugins/monitoring/src/main/java/net/bull/javamelody/RemoteCallHelper.java (41033 => 41034)
--- trunk/hudson/plugins/monitoring/src/main/java/net/bull/javamelody/RemoteCallHelper.java 2013-12-08 13:58:41 UTC (rev 41033)
+++ trunk/hudson/plugins/monitoring/src/main/java/net/bull/javamelody/RemoteCallHelper.java 2013-12-22 08:49:14 UTC (rev 41034)
@@ -135,11 +135,14 @@
}
}
- private RemoteCallHelper() {
+ private final String nodeName;
+
+ RemoteCallHelper(String nodeName) {
super();
+ this.nodeName = nodeName;
}
- private static <T> Map<String, T> collectDataByNodeName(Callable<T, Throwable> task)
+ private <T> Map<String, T> collectDataByNodeName(Callable<T, Throwable> task)
throws IOException, InterruptedException, ExecutionException {
final Computer[] computers = Hudson.getInstance().getComputers();
final Map<String, Future<T>> futuresByNodeName = new LinkedHashMap<String, Future<T>>(
@@ -147,7 +150,9 @@
final DelegatingTask<T> delegatingTask = new DelegatingTask<T>(task);
for (final Computer c : computers) {
if (c.isOnline()) {
- futuresByNodeName.put(c.getName(), c.getChannel().callAsync(delegatingTask));
+ if (nodeName == null || nodeName.equals(c.getName())) {
+ futuresByNodeName.put(c.getName(), c.getChannel().callAsync(delegatingTask));
+ }
}
}
final long now = System.currentTimeMillis();
@@ -156,11 +161,11 @@
final Map<String, T> result = new LinkedHashMap<String, T>(futuresByNodeName.size());
for (final Map.Entry<String, Future<T>> entry : futuresByNodeName.entrySet()) {
- final String nodeName = entry.getKey();
+ final String node = entry.getKey();
final Future<T> future = entry.getValue();
final long timeout = Math.max(0, end - System.currentTimeMillis());
try {
- result.put(nodeName, future.get(timeout, TimeUnit.MILLISECONDS));
+ result.put(node, future.get(timeout, TimeUnit.MILLISECONDS));
} catch (final TimeoutException e) {
continue;
}
@@ -168,30 +173,28 @@
return result;
}
- static List<JavaInformations> collectJavaInformationsList() throws IOException,
+ Map<String, JavaInformations> collectJavaInformationsListByName() throws IOException,
InterruptedException, ExecutionException {
- final Map<String, JavaInformations> javaInformationsByNodeName = collectDataByNodeName(JAVA_INFORMATIONS_TASK);
- return new ArrayList<JavaInformations>(javaInformationsByNodeName.values());
-
+ return collectDataByNodeName(JAVA_INFORMATIONS_TASK);
}
- static List<String> collectJmxValues(String jmxValueParameter) throws IOException,
+ List<String> collectJmxValues(String jmxValueParameter) throws IOException,
InterruptedException, ExecutionException {
return new ArrayList<String>(collectDataByNodeName(new JmxValueTask(jmxValueParameter))
.values());
}
- static Map<String, List<MBeanNode>> collectMBeanNodesByNodeName() throws IOException,
+ Map<String, List<MBeanNode>> collectMBeanNodesByNodeName() throws IOException,
InterruptedException, ExecutionException {
return collectDataByNodeName(MBEANS_TASK);
}
- static Map<String, List<ProcessInformations>> collectProcessInformationsByNodeName()
+ Map<String, List<ProcessInformations>> collectProcessInformationsByNodeName()
throws IOException, InterruptedException, ExecutionException {
return collectDataByNodeName(PROCESS_INFORMATIONS_TASK);
}
- static HeapHistogram collectGlobalHeapHistogram() throws IOException, InterruptedException,
+ HeapHistogram collectGlobalHeapHistogram() throws IOException, InterruptedException,
ExecutionException {
final Map<String, HeapHistogram> heapHistograms = collectDataByNodeName(HEAP_HISTOGRAM_TASK);
HeapHistogram heapHistoTotal = null;
@@ -208,7 +211,7 @@
return heapHistoTotal;
}
- static String forwardAction(String actionName, String sessionId, String threadId, String jobId,
+ String forwardAction(String actionName, String sessionId, String threadId, String jobId,
String cacheId) throws IOException, InterruptedException, ExecutionException {
final ActionTask task = new ActionTask(actionName, sessionId, threadId, jobId, cacheId);
final Map<String, String> messagesByNodeName = collectDataByNodeName(task);
Modified: trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/HudsonMonitoringFilter.java (41033 => 41034)
--- trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/HudsonMonitoringFilter.java 2013-12-08 13:58:41 UTC (rev 41033)
+++ trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/HudsonMonitoringFilter.java 2013-12-22 08:49:14 UTC (rev 41034)
@@ -75,9 +75,15 @@
Hudson.getInstance().checkPermission(Hudson.ADMINISTER);
}
- if (requestURI.equals(monitoringSlavesUrl)) {
+ if (requestURI.startsWith(monitoringSlavesUrl)) {
+ final String nodeName;
+ if (requestURI.equals(monitoringSlavesUrl)) {
+ nodeName = null;
+ } else {
+ nodeName = requestURI.substring(monitoringSlavesUrl.length()).replace("/", "");
+ }
final HttpServletResponse httpResponse = (HttpServletResponse) response;
- doMonitoring(httpRequest, httpResponse);
+ doMonitoring(httpRequest, httpResponse, nodeName);
return;
}
@@ -89,14 +95,15 @@
*
* @param httpRequest Http request
* @param httpResponse Http response
+ * @param nodeName nom du node (slave ou "")
* @throws IOException e
*/
- private void doMonitoring(HttpServletRequest httpRequest, HttpServletResponse httpResponse)
- throws IOException {
+ private void doMonitoring(HttpServletRequest httpRequest, HttpServletResponse httpResponse,
+ String nodeName) throws IOException {
if (NodesController.isJavaInformationsNeeded(httpRequest)) {
getNodesCollector().collectWithoutErrors();
}
- final NodesController nodesController = new NodesController(getNodesCollector());
+ final NodesController nodesController = new NodesController(getNodesCollector(), nodeName);
nodesController.doMonitoring(httpRequest, httpResponse);
}
Added: trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/NodeMonitoringAction.java (0 => 41034)
--- trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/NodeMonitoringAction.java (rev 0)
+++ trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/NodeMonitoringAction.java 2013-12-22 08:49:14 UTC (rev 41034)
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2013 by Emeric Vernat
+ *
+ * This file is part of the Monitoring plugin.
+ *
+ * The Monitoring plugin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Monitoring plugin is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the Monitoring plugin. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.jvnet.hudson.plugins.monitoring;
+
+import hudson.model.Action;
+import hudson.model.Computer;
+import hudson.model.Hudson;
+
+/**
+ * Implements a "Monitoring" button for slaves.
+ * This button will be available for everybody with ADMINISTER permission.
+ * @author Oleg Nenashev <[email protected]>, Emeric Vernat
+ * @since 1.49
+ */
+public class NodeMonitoringAction implements Action {
+ private final Computer computer;
+ private final String displayName;
+ private final String iconPath;
+ private String url;
+
+ /**
+ * Constructeur.
+ * @param computer Computer
+ * @param displayName String
+ * @param iconPath String
+ * @param url String
+ */
+ public NodeMonitoringAction(Computer computer, String displayName, String iconPath, String url) {
+ super();
+ this.computer = computer;
+ this.displayName = displayName;
+ this.iconPath = iconPath;
+ this.url = ""
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public final String getDisplayName() {
+ return hasMonitoringPermissions() && computer.isOnline() ? displayName : null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public final String getIconFileName() {
+ return hasMonitoringPermissions() && computer.isOnline() ? iconPath : null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getUrlName() {
+ return url;
+ }
+
+ /**
+ * Sets urlName.
+ * @param url String
+ */
+ public void setUrlName(String url) {
+ this.url = ""
+ }
+
+ /**
+ * Checks that user has access permissions to the monitoring page.
+ * By default, requires global Administer permission.
+ * @return boolean
+ */
+ protected boolean hasMonitoringPermissions() {
+ return Hudson.getInstance().hasPermission(Hudson.ADMINISTER);
+ }
+}
Property changes on: trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/NodeMonitoringAction.java
___________________________________________________________________
Added: svn:mime-type
Added: trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/NodesMonitoringActionFactory.java (0 => 41034)
--- trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/NodesMonitoringActionFactory.java (rev 0)
+++ trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/NodesMonitoringActionFactory.java 2013-12-22 08:49:14 UTC (rev 41034)
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 by Emeric Vernat
+ *
+ * This file is part of the Monitoring plugin.
+ *
+ * The Monitoring plugin is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Monitoring plugin is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the Monitoring plugin. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.jvnet.hudson.plugins.monitoring;
+
+import hudson.Extension;
+import hudson.model.Action;
+import hudson.model.TransientComputerActionFactory;
+import hudson.model.Computer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import jenkins.model.Jenkins;
+
+/**
+ * Generates a {@link NodeMonitoringAction} for the each slave computer.
+ * @author Oleg Nenashev <[email protected]>, Emeric Vernat
+ */
+@Extension
+public class NodesMonitoringActionFactory extends TransientComputerActionFactory {
+
+ /** {@inheritDoc} */
+ @Override
+ public Collection<? extends Action> createFor(Computer computer) {
+ final List<NodeMonitoringAction> result = new ArrayList<NodeMonitoringAction>();
+ result.add(new NodeMonitoringAction(computer, "View threads",
+ "../../../../monitoring?resource=threads.png", "../../monitoring?part=threads"));
+ result.add(new NodeMonitoringAction(computer, "Execute the garbage collector",
+ "../../../../monitoring?resource=broom.png", "../../monitoring?action=""
+ result.add(new NodeMonitoringAction(computer, "Generate a heap dump",
+ "../../../../monitoring?resource=heapdump.png", "../../monitoring?action=""
+ result.add(new NodeMonitoringAction(computer, "View memory histogram",
+ "../../../../monitoring?resource=memory.png", "../../monitoring?part=heaphisto"));
+ result.add(new NodeMonitoringAction(computer, "MBeans",
+ "../../../../monitoring?resource=mbeans.png", "../../monitoring?part=mbeans"));
+ result.add(new NodeMonitoringAction(computer, "View OS processes",
+ "../../../../monitoring?resource=processes.png", "../../monitoring?part=processes"));
+ if (!(computer instanceof Jenkins.MasterComputer)) {
+ for (final NodeMonitoringAction action : result) {
+ action.setUrlName(action.getUrlName().replace("/monitoring",
+ "/monitoring/nodes/" + computer.getName()));
+ }
+ }
+ return result;
+ }
+}
Property changes on: trunk/hudson/plugins/monitoring/src/main/java/org/jvnet/hudson/plugins/monitoring/NodesMonitoringActionFactory.java
___________________________________________________________________
Added: svn:mime-type
You received this message because you are subscribed to the Google Groups "Jenkins Commits" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.
