modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/EventContext.java
| 7
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/log/LogFileEventPoller.java
| 25 +
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/log/LogFileEventResourceComponentHelper.java
| 160 ++++++----
modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventContextImpl.java
| 3
modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventManager.java
| 7
modules/plugins/platform/src/main/java/org/rhq/plugins/platform/FileSystemComponent.java
| 46 +-
6 files changed, 162 insertions(+), 86 deletions(-)
New commits:
commit 22da9591737868d71ccc70474fe3701434ec8385
Merge: 371ed2f f808b1f
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Mon Jan 30 22:27:20 2012 -0500
Merge branch 'release/jon3.0.x' of
ssh://git.fedorahosted.org/git/rhq/rhq into
release/jon3.0.x
commit 371ed2faefd38ca58d514bb95793978de4a4fa46
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Mon Jan 30 22:25:35 2012 -0500
[BZ 785026] if log file event sources are enabled, but SIGAR is disabled or
unavailable, log a warning, rather than
silently failing (
https://bugzilla.redhat.com/show_bug.cgi?id=785026)
diff --git
a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/EventContext.java
b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/EventContext.java
index f9bb654..8651272 100644
---
a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/EventContext.java
+++
b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/EventContext.java
@@ -22,6 +22,7 @@
*/
package org.rhq.core.pluginapi.event;
+import com.sun.istack.Nullable;
import org.hyperic.sigar.SigarProxy;
import org.jetbrains.annotations.NotNull;
@@ -90,10 +91,10 @@ public interface EventContext {
/**
* Gets an instance of Sigar. Plugins that need to use Sigar, should use this method
to get an instance, rather than
- * instantiating Sigar themselves.
+ * instantiating Sigar themselves. Returns null if the native layer is unavailable or
has been disabled.
*
- * @return an instance of Sigar
+ * @return an instance of Sigar, or null if the native layer is unavailable or has
been disabled
*/
- @NotNull
+ @Nullable
SigarProxy getSigar();
}
diff --git
a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/log/LogFileEventPoller.java
b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/log/LogFileEventPoller.java
index d936522..bcc42de 100644
---
a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/log/LogFileEventPoller.java
+++
b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/log/LogFileEventPoller.java
@@ -1,6 +1,6 @@
- /*
+/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -55,13 +55,17 @@ public class LogFileEventPoller implements EventPoller {
private LogEntryProcessor entryProcessor;
public LogFileEventPoller(EventContext eventContext, String eventType, File logFile,
LogEntryProcessor entryProcessor) {
+ SigarProxy sigar = eventContext.getSigar();
this.eventType = eventType;
this.logFile = logFile;
- SigarProxy sigar = eventContext.getSigar();
- try {
- this.logFileInfo = new LogFileInfo(sigar.getFileInfo(logFile.getPath()));
- } catch (SigarException e) {
- throw new RuntimeException(e);
+ if (sigar != null) {
+ try {
+ this.logFileInfo = new
LogFileInfo(sigar.getFileInfo(logFile.getPath()));
+ } catch (SigarException e) {
+ throw new RuntimeException("Failed to obtain file info for log file
[" + this.logFile + "].", e);
+ }
+ } else {
+ log.warn("SIGAR is unavailable - cannot poll log file [" +
this.logFile + "] for events.");
}
this.entryProcessor = entryProcessor;
}
@@ -78,12 +82,15 @@ public class LogFileEventPoller implements EventPoller {
@Nullable
public Set<Event> poll() {
+ if (this.logFileInfo == null) {
+ return null;
+ }
if (!this.logFile.exists()) {
- log.warn("Log file [" + this.logFile + "' being polled
does not exist.");
+ log.warn("Log file [" + this.logFile + "] being polled does
not exist.");
return null;
}
if (this.logFile.isDirectory()) {
- log.error("Log file [" + this.logFile + "' being polled is
a directory, not a regular file.");
+ log.error("Log file [" + this.logFile + "] being polled is a
directory, not a regular file.");
return null;
}
try {
diff --git
a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/log/LogFileEventResourceComponentHelper.java
b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/log/LogFileEventResourceComponentHelper.java
index 962764a..d134638 100644
---
a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/log/LogFileEventResourceComponentHelper.java
+++
b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/event/log/LogFileEventResourceComponentHelper.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -21,6 +21,9 @@ package org.rhq.core.pluginapi.event.log;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
@@ -32,10 +35,12 @@ import org.rhq.core.domain.configuration.Property;
import org.rhq.core.domain.configuration.PropertyList;
import org.rhq.core.domain.configuration.PropertyMap;
import org.rhq.core.domain.event.EventSeverity;
+import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pluginapi.event.EventContext;
import org.rhq.core.pluginapi.event.EventPoller;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.system.SystemInfoFactory;
/**
* @author Ian Springer
@@ -47,83 +52,132 @@ public class LogFileEventResourceComponentHelper {
public static final String LOG_EVENT_SOURCE_CONFIG_PROP =
"logEventSource";
public abstract static class LogEventSourcePropertyNames {
- public static final String LOG_FILE_PATH = "logFilePath";
- public static final String ENABLED = "enabled";
- public static final String DATE_FORMAT = "dateFormat";
- public static final String INCLUDES_PATTERN = "includesPattern";
- public static final String MINIMUM_SEVERITY = "minimumSeverity";
+ public static final String LOG_FILE_PATH = "logFilePath"; //
required
+ public static final String ENABLED = "enabled"; //
required
+ public static final String DATE_FORMAT = "dateFormat"; //
optional
+ public static final String INCLUDES_PATTERN = "includesPattern"; //
optional
+ public static final String MINIMUM_SEVERITY = "minimumSeverity"; //
optional
}
+ // TODO: Make this configurable via a plugin config prop.
+ private static final int POLLING_INTERVAL_IN_SECONDS = 60;
+
private final Log log = LogFactory.getLog(this.getClass());
private ResourceContext<?> resourceContext;
+ private List<PropertyMap> startedEventSources = new
ArrayList<PropertyMap>();
public LogFileEventResourceComponentHelper(ResourceContext<?> resourceContext)
{
this.resourceContext = resourceContext;
}
public void startLogFileEventPollers() {
+ // Grab the list-o-maps of event sources from the plugin config.
Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
PropertyList logEventSources =
pluginConfig.getList(LOG_EVENT_SOURCES_CONFIG_PROP);
+
+ // Build a new list containing the event sources that are enabled.
+ List<PropertyMap> enabledEventSources = new
ArrayList<PropertyMap>();
for (Property prop : logEventSources.getList()) {
PropertyMap logEventSource = (PropertyMap) prop;
- Boolean enabled =
Boolean.valueOf(logEventSource.getSimpleValue(LogEventSourcePropertyNames.ENABLED,
null));
- if (enabled) {
- String logFilePathname =
logEventSource.getSimpleValue(LogEventSourcePropertyNames.LOG_FILE_PATH, null);
- if (logFilePathname == null) {
- log.info("LOGFILE: No logfile path given, can not watch this
event log.");
- return;
- }
- File logFile = new File(logFilePathname);
- if (!logFile.exists() || !logFile.canRead()) {
- log.error("LOGFILE: Logfile at location " +
logFilePathname
- + " does not exist or is not readable. Can not start
watching the event log.");
- return;
- }
+ String enabled =
logEventSource.getSimpleValue(LogEventSourcePropertyNames.ENABLED, null);
+ if (enabled == null) {
+ throw new IllegalStateException("Required property [" +
LogEventSourcePropertyNames.ENABLED
+ + "] is not defined in map.");
+ }
+ if (Boolean.valueOf(enabled)) {
+ enabledEventSources.add(logEventSource);
+ }
+ }
- Log4JLogEntryProcessor processor = new
Log4JLogEntryProcessor(LOG_ENTRY_EVENT_TYPE, logFile);
- String dateFormatString =
logEventSource.getSimpleValue(LogEventSourcePropertyNames.DATE_FORMAT, null);
- if (dateFormatString != null) {
- try {
- DateFormat dateFormat = new SimpleDateFormat(dateFormatString);
// TODO locale specific ?
- processor.setDateFormat(dateFormat);
- } catch (IllegalArgumentException e) {
- throw new InvalidPluginConfigurationException("Date format
[" + dateFormatString
- + "] is not a valid simple date format.");
- }
- }
- String includesPatternString = logEventSource.getSimpleValue(
- LogEventSourcePropertyNames.INCLUDES_PATTERN, null);
- if (includesPatternString != null) {
- try {
- Pattern includesPattern =
Pattern.compile(includesPatternString);
- processor.setIncludesPattern(includesPattern);
- } catch (PatternSyntaxException e) {
- throw new InvalidPluginConfigurationException("Includes
pattern [" + includesPatternString
- + "] is not a valid regular expression.");
- }
+ // Log a warning then return if SIGAR isn't available, since
LogFileEventPoller depends on it. We only log this
+ // warning if at least one event source is enabled, since otherwise the user
probably doesn't care.
+ boolean sigarAvailable = this.resourceContext.getSystemInformation().isNative();
+ if (!sigarAvailable && !enabledEventSources.isEmpty()) {
+ boolean nativeSystemInfoDisabled =
SystemInfoFactory.isNativeSystemInfoDisabled();
+ ResourceType resourceType = this.resourceContext.getResourceType();
+ List<String> logFilePaths = getLogFilePaths(enabledEventSources);
+ log.warn("Log files " + logFilePaths + " for [" +
resourceType.getPlugin() + ":"
+ + resourceType.getName() + "] Resource with key [" +
this.resourceContext.getResourceKey()
+ + "] cannot be polled, because log file polling requires RHQ native
support, which "
+ + ((nativeSystemInfoDisabled) ? "has been disabled for this
Agent" : "is not available on this platform") + ".");
+ return;
+ }
+
+ // Start up log file pollers for each of the enabled event sources.
+ for (PropertyMap logEventSource : enabledEventSources) {
+ String logFilePath =
logEventSource.getSimpleValue(LogEventSourcePropertyNames.LOG_FILE_PATH, null);
+ if (logFilePath == null) {
+ throw new IllegalStateException("Required property [" +
LogEventSourcePropertyNames.LOG_FILE_PATH
+ + "] is not defined in map.");
+ }
+ File logFile = new File(logFilePath);
+ if (!logFile.canRead()) {
+ log.error("LOGFILE: Logfile at location " + logFilePath
+ + " does not exist or is not readable. Can not start watching
the event log.");
+ continue;
+ }
+
+ Log4JLogEntryProcessor processor = new
Log4JLogEntryProcessor(LOG_ENTRY_EVENT_TYPE, logFile);
+ String dateFormatString =
logEventSource.getSimpleValue(LogEventSourcePropertyNames.DATE_FORMAT, null);
+ if (dateFormatString != null) {
+ try {
+ DateFormat dateFormat = new SimpleDateFormat(dateFormatString); //
TODO locale specific ?
+ processor.setDateFormat(dateFormat);
+ } catch (IllegalArgumentException e) {
+ throw new InvalidPluginConfigurationException("Date format
[" + dateFormatString
+ + "] is not a valid simple date format.");
}
- String minimumSeverityString = logEventSource.getSimpleValue(
- LogEventSourcePropertyNames.MINIMUM_SEVERITY, null);
- if (minimumSeverityString != null) {
- EventSeverity minimumSeverity =
EventSeverity.valueOf(minimumSeverityString.toUpperCase());
- processor.setMinimumSeverity(minimumSeverity);
+ }
+ String includesPatternString = logEventSource.getSimpleValue(
+ LogEventSourcePropertyNames.INCLUDES_PATTERN, null);
+ if (includesPatternString != null) {
+ try {
+ Pattern includesPattern = Pattern.compile(includesPatternString);
+ processor.setIncludesPattern(includesPattern);
+ } catch (PatternSyntaxException e) {
+ throw new InvalidPluginConfigurationException("Includes pattern
[" + includesPatternString
+ + "] is not a valid regular expression.");
}
- EventContext eventContext = this.resourceContext.getEventContext();
- EventPoller poller = new LogFileEventPoller(eventContext,
LOG_ENTRY_EVENT_TYPE, logFile, processor);
- eventContext.registerEventPoller(poller, 60, logFile.getPath());
}
+ String minimumSeverityString = logEventSource.getSimpleValue(
+ LogEventSourcePropertyNames.MINIMUM_SEVERITY, null);
+ if (minimumSeverityString != null) {
+ EventSeverity minimumSeverity =
EventSeverity.valueOf(minimumSeverityString.toUpperCase());
+ processor.setMinimumSeverity(minimumSeverity);
+ }
+ EventContext eventContext = this.resourceContext.getEventContext();
+ EventPoller poller = new LogFileEventPoller(eventContext,
LOG_ENTRY_EVENT_TYPE, logFile, processor);
+ eventContext.registerEventPoller(poller, POLLING_INTERVAL_IN_SECONDS,
logFile.getPath());
+ this.startedEventSources.add(logEventSource);
}
}
public void stopLogFileEventPollers() {
- Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
- PropertyList logEventSources =
pluginConfig.getList(LOG_EVENT_SOURCES_CONFIG_PROP);
- for (Property prop : logEventSources.getList()) {
- PropertyMap logEventSource = (PropertyMap) prop;
- String logFilePath =
logEventSource.getSimpleValue(LogEventSourcePropertyNames.LOG_FILE_PATH, null);
+ boolean sigarAvailable = this.resourceContext.getSystemInformation().isNative();
+ if (!sigarAvailable) {
+ return;
+ }
+
+ for (Iterator<PropertyMap> iterator = this.startedEventSources.iterator();
iterator.hasNext(); ) {
+ PropertyMap logEventSource = iterator.next();
EventContext eventContext = this.resourceContext.getEventContext();
+ String logFilePath =
logEventSource.getSimpleValue(LogEventSourcePropertyNames.LOG_FILE_PATH, null);
eventContext.unregisterEventPoller(LOG_ENTRY_EVENT_TYPE, logFilePath);
+ iterator.remove();
+ }
+ }
+
+ private List<String> getLogFilePaths(List<PropertyMap>
enabledEventSources) {
+ List<String> logFilePaths = new
ArrayList<String>(enabledEventSources.size());
+ for (PropertyMap logEventSource : enabledEventSources) {
+ String logFilePath =
logEventSource.getSimpleValue(LogEventSourcePropertyNames.LOG_FILE_PATH, null);
+ if (logFilePath == null) {
+ throw new IllegalStateException("Required property [" +
LogEventSourcePropertyNames.LOG_FILE_PATH
+ + "] is not defined in map.");
+ }
+ logFilePaths.add(logFilePath);
}
+ return logFilePaths;
}
}
diff --git
a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventContextImpl.java
b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventContextImpl.java
index b0b37ec..1735aff 100644
---
a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventContextImpl.java
+++
b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventContextImpl.java
@@ -24,6 +24,7 @@ package org.rhq.core.pc.event;
import org.hyperic.sigar.SigarProxy;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.rhq.core.domain.event.Event;
import org.rhq.core.domain.event.EventDefinition;
import org.rhq.core.domain.resource.Resource;
@@ -99,7 +100,7 @@ public class EventContextImpl implements EventContext {
unregisterEventPollerInternal(eventType, sourceLocation);
}
- @NotNull
+ @Nullable
public SigarProxy getSigar() {
return getEventManager().getSigar();
}
diff --git
a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventManager.java
b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventManager.java
index 4ad5c50..87b9bd7 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventManager.java
@@ -34,6 +34,7 @@ import org.apache.commons.logging.LogFactory;
import org.hyperic.sigar.SigarProxy;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.rhq.core.domain.event.Event;
import org.rhq.core.domain.event.EventDefinition;
import org.rhq.core.domain.event.EventSource;
@@ -44,6 +45,7 @@ import org.rhq.core.pc.PluginContainerConfiguration;
import org.rhq.core.pc.util.LoggingThreadFactory;
import org.rhq.core.pluginapi.event.EventPoller;
import org.rhq.core.system.SigarAccess;
+import org.rhq.core.system.SystemInfoException;
/**
* Manager for the Plugin Container's Event subsystem.
@@ -113,9 +115,12 @@ public class EventManager implements ContainerService {
}
}
+ @Nullable
SigarProxy getSigar() {
if (this.sigar == null) {
- this.sigar = SigarAccess.getSigar();
+ if (SigarAccess.isSigarAvailable()) {
+ this.sigar = SigarAccess.getSigar();
+ }
}
return this.sigar;
}
commit 9b740863e19ec6cde4007f53c4ad76d399d12ecb
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Fri Nov 11 10:41:00 2011 -0500
[BZ 752981] remove duplicate call to FileSystemInfo.refresh(), which was resulting in
invalid metric values (
https://bugzilla.redhat.com/show_bug.cgi?id=752981); use
switch-case rather than if-else in getValues() to make code more readable
(cherry picked from commit 68be8c6fa8086e0c16fa706e3bad3c84b9d8b2fd)
diff --git
a/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/FileSystemComponent.java
b/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/FileSystemComponent.java
index 9d68c23..5eae991 100644
---
a/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/FileSystemComponent.java
+++
b/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/FileSystemComponent.java
@@ -1,6 +1,6 @@
- /*
+/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2011 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -28,7 +28,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.measurement.AvailabilityType;
-import org.rhq.core.domain.measurement.DataType;
import org.rhq.core.domain.measurement.MeasurementDataNumeric;
import org.rhq.core.domain.measurement.MeasurementDataTrait;
import org.rhq.core.domain.measurement.MeasurementReport;
@@ -39,12 +38,15 @@ import org.rhq.core.pluginapi.inventory.ResourceContext;
import org.rhq.core.pluginapi.measurement.MeasurementFacet;
import org.rhq.core.pluginapi.util.ObjectUtil;
import org.rhq.core.system.FileSystemInfo;
+import org.rhq.core.system.SystemInfo;
-/**
+ /**
* @author Greg Hinkle
*/
public class FileSystemComponent implements ResourceComponent<PlatformComponent>,
MeasurementFacet {
+
private static final Log LOG = LogFactory.getLog(FileSystemComponent.class);
+
private ResourceContext<PlatformComponent> resourceContext;
public void start(ResourceContext<PlatformComponent> resourceContext) throws
InvalidPluginConfigurationException,
@@ -65,26 +67,32 @@ public class FileSystemComponent implements
ResourceComponent<PlatformComponent>
}
}
- private FileSystemInfo getFileSystemInfo() {
- return
resourceContext.getSystemInformation().getFileSystem(resourceContext.getResourceKey());
- }
-
- public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest>
metrics) throws Exception {
+ public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest>
requests) throws Exception {
FileSystemInfo fileSystemInfo = getFileSystemInfo();
- fileSystemInfo.refresh();
- for (MeasurementScheduleRequest request : metrics) {
+ for (MeasurementScheduleRequest request : requests) {
try {
- if (request.getDataType() == DataType.TRAIT) {
- Object value = ObjectUtil.lookupDeepAttributeProperty(fileSystemInfo,
request.getName());
- report.addData(new MeasurementDataTrait(request,
String.valueOf(value)));
- } else if (request.getDataType() == DataType.MEASUREMENT) {
- report.addData(new MeasurementDataNumeric(request,
ObjectUtil.lookupDeepNumericAttributeProperty(
- fileSystemInfo, request.getName())));
+ switch (request.getDataType()) {
+ case TRAIT:
+ Object object =
ObjectUtil.lookupDeepAttributeProperty(fileSystemInfo, request.getName());
+ report.addData(new MeasurementDataTrait(request,
String.valueOf(object)));
+ break;
+ case MEASUREMENT:
+ Double value =
ObjectUtil.lookupDeepNumericAttributeProperty(fileSystemInfo, request.getName());
+ report.addData(new MeasurementDataNumeric(request, value));
+ break;
+ default:
+ throw new IllegalStateException("Unsupported metric type:
" + request.getDataType());
}
} catch (Exception e) {
- LOG.info("Unable to collection file system metric [" +
request.getName() + "] on resource "
- + this.resourceContext.getResourceKey(), e);
+ LOG.info("Unable to collect metric [" + request.getName() +
"] on filesystem resource ["
+ + this.resourceContext.getResourceKey() + "].", e);
}
}
}
+
+ private FileSystemInfo getFileSystemInfo() {
+ SystemInfo systemInfo = resourceContext.getSystemInformation();
+ return systemInfo.getFileSystem(resourceContext.getResourceKey());
+ }
+
}
\ No newline at end of file