Repository: geode Updated Branches: refs/heads/feature/GEODE-2297 deb52c06b -> d9815b6d2
Latest changes Project: http://git-wip-us.apache.org/repos/asf/geode/repo Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/d9815b6d Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/d9815b6d Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/d9815b6d Branch: refs/heads/feature/GEODE-2297 Commit: d9815b6d2f60d31062957cacaae89868f1302dfc Parents: deb52c0 Author: Kirk Lund <kl...@apache.org> Authored: Fri Jan 20 14:13:27 2017 -0800 Committer: Kirk Lund <kl...@apache.org> Committed: Fri Jan 20 14:13:27 2017 -0800 ---------------------------------------------------------------------- .../geode/admin/AdminDistributedSystem.java | 4 +- .../internal/AdminDistributedSystemImpl.java | 2 +- .../internal/AdminDistributedSystemJmxImpl.java | 2 +- .../internal/DistributedAlertService.java | 238 ++++++++++++++ .../internal/InternalDistributedSystem.java | 122 ++++--- .../internal/direct/DirectChannel.java | 3 +- .../gms/messenger/JGroupsMessenger.java | 3 +- .../admin/remote/AlertLevelChangeMessage.java | 2 +- .../internal/logging/ManagerLogWriter.java | 24 +- .../logging/SecurityManagerLogWriter.java | 12 +- .../internal/logging/log4j/AlertAppender.java | 321 ++++--------------- .../logging/log4j/LogWriterAppenders.java | 8 +- .../apache/geode/internal/tcp/Connection.java | 3 +- .../geode/internal/tcp/ConnectionTable.java | 6 +- .../internal/tcp/ReenteredConnectException.java | 2 +- .../apache/geode/internal/tcp/TCPConduit.java | 4 +- .../internal/alerting/AlertHandler.java | 30 ++ .../internal/alerting/AlertLevel.java | 65 ++++ .../internal/alerting/AlertService.java | 37 +++ .../internal/alerting/AlertServiceListener.java | 23 ++ .../internal/alerting/AlertSubscriber.java | 63 ++++ .../messenger/JGroupsMessengerJUnitTest.java | 6 +- .../internal/logging/TestLogWriterFactory.java | 4 +- .../logging/log4j/AlertAppenderJUnitTest.java | 16 +- 24 files changed, 635 insertions(+), 365 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/admin/AdminDistributedSystem.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/admin/AdminDistributedSystem.java b/geode-core/src/main/java/org/apache/geode/admin/AdminDistributedSystem.java index cd4dc7e..60a620c 100755 --- a/geode-core/src/main/java/org/apache/geode/admin/AdminDistributedSystem.java +++ b/geode-core/src/main/java/org/apache/geode/admin/AdminDistributedSystem.java @@ -94,13 +94,13 @@ public interface AdminDistributedSystem { public String getAlertLevelAsString(); /** - * Registers an <code>AlertListener</code> that will receive all alerts that are at or above the + * Registers an <code>AlertSubscriber</code> that will receive all alerts that are at or above the * {@linkplain #setAlertLevel alert level}. */ public void addAlertListener(AlertListener listener); /** - * Unregisters an <code>AlertListener</code> + * Unregisters an <code>AlertSubscriber</code> */ public void removeAlertListener(AlertListener listener); http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/admin/internal/AdminDistributedSystemImpl.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/admin/internal/AdminDistributedSystemImpl.java b/geode-core/src/main/java/org/apache/geode/admin/internal/AdminDistributedSystemImpl.java index ed0c015..58daa36 100755 --- a/geode-core/src/main/java/org/apache/geode/admin/internal/AdminDistributedSystemImpl.java +++ b/geode-core/src/main/java/org/apache/geode/admin/internal/AdminDistributedSystemImpl.java @@ -1181,7 +1181,7 @@ public class AdminDistributedSystemImpl implements org.apache.geode.admin.AdminD } } - // ----------- org.apache.geode.internal.admin.AlertListener ----------- + // ----------- org.apache.geode.internal.admin.AlertSubscriber ----------- /** * Listener callback for when a SystemMember of this DistributedSystem has crashed. * http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/admin/jmx/internal/AdminDistributedSystemJmxImpl.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/admin/jmx/internal/AdminDistributedSystemJmxImpl.java b/geode-core/src/main/java/org/apache/geode/admin/jmx/internal/AdminDistributedSystemJmxImpl.java index 1bfddf2..d569341 100755 --- a/geode-core/src/main/java/org/apache/geode/admin/jmx/internal/AdminDistributedSystemJmxImpl.java +++ b/geode-core/src/main/java/org/apache/geode/admin/jmx/internal/AdminDistributedSystemJmxImpl.java @@ -517,7 +517,7 @@ public class AdminDistributedSystemJmxImpl extends AdminDistributedSystemImpl } } - // ----------- org.apache.geode.internal.admin.AlertListener ----------- + // ----------- org.apache.geode.internal.admin.AlertSubscriber ----------- /** * Listener callback for when a SystemMember of this DistributedSystem has crashed. * <p> http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributedAlertService.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributedAlertService.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributedAlertService.java new file mode 100644 index 0000000..f5356df --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/DistributedAlertService.java @@ -0,0 +1,238 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.distributed.internal; + +import static org.apache.geode.internal.admin.remote.AlertListenerMessage.create; +import static org.apache.geode.management.internal.alerting.AlertLevel.*; + +import org.apache.geode.distributed.DistributedMember; +import org.apache.geode.internal.admin.Alert; +import org.apache.geode.internal.admin.remote.AlertListenerMessage; +import org.apache.geode.internal.logging.LogService; +import org.apache.geode.internal.tcp.ReenteredConnectException; +import org.apache.geode.management.internal.alerting.AlertServiceListener; +import org.apache.geode.management.internal.alerting.AlertSubscriber; +import org.apache.geode.management.internal.alerting.AlertService; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.config.LoggerConfig; +import org.apache.logging.log4j.status.StatusLogger; + +import java.util.Date; +import java.util.concurrent.CopyOnWriteArrayList; + +public class DistributedAlertService implements AlertService { + private static final StatusLogger logger = StatusLogger.getLogger(); + + /** Is this thread in the process of alerting? */ + private static final ThreadLocal<Boolean> alerting = new ThreadLocal<Boolean>() { + @Override + protected Boolean initialValue() { + return Boolean.FALSE; + } + }; + + // Listeners are ordered with the narrowest levels (e.g. FATAL) at the end + private final CopyOnWriteArrayList<AlertSubscriber> alertSubscribers = new CopyOnWriteArrayList<>(); + + private final InternalDistributedSystem system; + private final DistributionManager dm; + + private volatile boolean enabled; + + public DistributedAlertService(final InternalDistributedSystem system) { + this.system = system; + this.system.addDisconnectListener((final InternalDistributedSystem disconnected) -> { + enabled = false; + }); + this.dm = (DistributionManager)this.system.getDistributionManager(); + this.enabled = !this.system.getDistributionManager().isLoner(); // loner is disabled + } + + /** + * Returns true if the current thread is in the process of delivering an alert message. + */ + public static boolean isThreadAlerting() { + return alerting.get(); + } + + public static void setIsAlerting(boolean isAlerting) { + alerting.set(isAlerting ? Boolean.TRUE : Boolean.FALSE); + } + + public synchronized void shuttingDown() { + this.alertSubscribers.clear(); + } + + private AlertServiceListener alertServiceListener; + + public synchronized void addAlertListener(final DistributedMember member, final int alertLevel) { + final Level level = LogService.toLevel(alertLevelToLogLevel(alertLevel)); + + if (this.alertSubscribers.size() == 0) { + alertServiceListener.clear(); + } + + addListenerToSortedList(new AlertSubscriber(level, member)); + + LoggerConfig loggerConfig = this.appenderContext.getLoggerConfig(); + loggerConfig.addAppender(this, this.alertSubscribers.get(0).getLevel(), null); + if (logger.isDebugEnabled()) { + logger.debug("Added/Replaced alert listener for member {} at level {}", member, level); + } + } + + public synchronized boolean removeAlertListener(final DistributedMember member) { + final boolean memberWasFound = this.listeners.remove(new AlertSubscriber(null, member)); + + if (memberWasFound) { + if (this.alertSubscribers.size() == 0) { + this.appenderContext.getLoggerContext().removePropertyChangeListener(this); + this.appenderContext.getLoggerConfig().removeAppender(APPENDER_NAME); + + } else { + LoggerConfig loggerConfig = this.appenderContext.getLoggerConfig(); + loggerConfig.addAppender(this, this.alertSubscribers.get(0).getLevel(), null); + } + if (logger.isDebugEnabled()) { + logger.debug("Removed alert listener for member {}", member); + } + } + + return memberWasFound; + } + + public synchronized boolean hasAlertListener(final DistributedMember member, + final int alertLevel) { + final Level level = LogService.toLevel(alertLevelToLogLevel(alertLevel)); + + for (AlertSubscriber listener : this.alertSubscribers) { + if (listener.getMember().equals(member) && listener.getLevel().equals(level)) { + return true; + } + } + + // Special case for alert level Alert.OFF (NONE_LEVEL), because we can never have an actual + // listener with + // this level (see AlertLevelChangeMessage.process()). + if (alertLevel == Alert.OFF) { + for (AlertSubscriber listener : this.alertSubscribers) { + if (listener.getMember().equals(member)) { + return false; + } + } + return true; + } + + return false; + } + + /** + * Will add (or replace) a listener to the list of sorted listeners such that listeners with a + * narrower level (e.g. FATAL) will be at the end of the list. + * + * @param listener The listener to add to the list. + */ + private void addListenerToSortedList(final AlertSubscriber listener) { + if (this.alertSubscribers.contains(listener)) { + this.alertSubscribers.remove(listener); + } + + for (int i = 0; i < this.alertSubscribers.size(); i++) { + if (listener.getLevel().compareTo(this.alertSubscribers.get(i).getLevel()) >= 0) { + this.alertSubscribers.add(i, listener); + return; + } + } + + this.alertSubscribers.add(listener); + } + + public boolean isEnabled() { + return this.enabled; + } + + public DistributionManager getDistributionManager() { + return this.dm; + } + + public String getMemberName() { + return system.getName(); + } + + @Override + public boolean isAlerting() { + return false; + } + + @Override + public void handleAlert(final AlertService alertProvider, + final int intLevel, + final Date date, + final String threadName, + final String logMessage, + final String stackTrace, + final String connectionName, + final AlertSubscriber listener) { + + DistributionManager dm = alertProvider.getDistributionManager(); + if (dm == null) { + logger.debug("Did not append alert event because the distributed system is set to null."); + return; + } + + try { + setIsAlerting(true); + + AlertListenerMessage alertMessage = create( + listener.getMember(), + intLevel, + date, + connectionName, + threadName, + Thread.currentThread().getId(), + logMessage, + stackTrace); + + if (listener.getMember().equals(dm.getDistributionManagerId())) { + logger.debug("Processing local alert message: {}, {}, {}, {}, {}, [{}], [{}].", + listener.getMember(), + intLevel, + date, + connectionName, + threadName, + logMessage, + stackTrace); + alertMessage.process(dm); + } else { + logger.debug("Sending remote alert message: {}, {}, {}, {}, {}, [{}], [{}].", + listener.getMember(), + intLevel, + date, + connectionName, + threadName, + logMessage, + stackTrace); + dm.putOutgoing(alertMessage); + } + } catch (ReenteredConnectException e) { + // OK. We can't send to this recipient because we're in the middle of + // trying to connect to it. + } finally { + setIsAlerting(false); + } + } +} http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java index fad9206..eb98f99 100644 --- a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java +++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java @@ -40,6 +40,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import org.apache.geode.cache.CacheXmlException; +import org.apache.geode.management.internal.alerting.AlertService; import org.apache.logging.log4j.Logger; import org.apache.geode.CancelCriterion; @@ -570,50 +571,9 @@ public class InternalDistributedSystem extends DistributedSystem try { SocketCreatorFactory.setDistributionConfig(config); - // LOG: create LogWriterAppender(s) if log-file or security-log-file is specified - final boolean hasLogFile = - this.config.getLogFile() != null && !this.config.getLogFile().equals(new File("")); - final boolean hasSecurityLogFile = this.config.getSecurityLogFile() != null - && !this.config.getSecurityLogFile().equals(new File("")); - LogService.configureLoggers(hasLogFile, hasSecurityLogFile); - if (hasLogFile || hasSecurityLogFile) { - - // main log file - if (hasLogFile) { - // if log-file then create logWriterAppender - this.logWriterAppender = LogWriterAppenders.getOrCreateAppender( - LogWriterAppenders.Identifier.MAIN, this.isLoner, this.config, true); - } - - // security log file - if (hasSecurityLogFile) { - // if security-log-file then create securityLogWriterAppender - this.securityLogWriterAppender = LogWriterAppenders.getOrCreateAppender( - LogWriterAppenders.Identifier.SECURITY, this.isLoner, this.config, false); - } else { - // let security route to regular log-file or stdout - } - } - - // LOG: create LogWriterLogger(s) for backwards compatibility of getLogWriter and - // getSecurityLogWriter - if (this.logWriter == null) { - this.logWriter = - LogWriterFactory.createLogWriterLogger(this.isLoner, false, this.config, true); - this.logWriter.fine("LogWriter is created."); - } - - // logWriter.info("Created log writer for IDS@"+System.identityHashCode(this)); - - if (this.securityLogWriter == null) { - // LOG: whole new LogWriterLogger instance for security - this.securityLogWriter = - LogWriterFactory.createLogWriterLogger(this.isLoner, true, this.config, false); - this.securityLogWriter.fine("SecurityLogWriter is created."); - } + initializeAlerting(); - Services.setLogWriter(this.logWriter); - Services.setSecurityLogWriter(this.securityLogWriter); + initializeLogging(); this.clock = new DSClock(this.isLoner); @@ -736,12 +696,7 @@ public class InternalDistributedSystem extends DistributedSystem this.sampler.start(); } - if (this.logWriterAppender != null) { - LogWriterAppenders.startupComplete(LogWriterAppenders.Identifier.MAIN); - } - if (this.securityLogWriterAppender != null) { - LogWriterAppenders.startupComplete(LogWriterAppenders.Identifier.SECURITY); - } + postInitializeLogging(); // this.logger.info("ds created", new RuntimeException("DEBUG: STACK")); @@ -759,6 +714,75 @@ public class InternalDistributedSystem extends DistributedSystem } /** + * Extract this to a Service Initializer object that is passed into IDS + */ + private void initializeAlerting() { + AlertService.install(new DistributedAlertService(this)); + } + + /** + * Extract this to a Service Initializer object that is passed into IDS + */ + private void initializeLogging() { + // LOG: create LogWriterAppender(s) if log-file or security-log-file is specified + final boolean hasLogFile = + this.config.getLogFile() != null && !this.config.getLogFile().equals(new File("")); + final boolean hasSecurityLogFile = this.config.getSecurityLogFile() != null + && !this.config.getSecurityLogFile().equals(new File("")); + LogService.configureLoggers(hasLogFile, hasSecurityLogFile); + if (hasLogFile || hasSecurityLogFile) { + + // main log file + if (hasLogFile) { + // if log-file then create logWriterAppender + this.logWriterAppender = LogWriterAppenders.getOrCreateAppender( + LogWriterAppenders.Identifier.MAIN, this.isLoner, this.config, true); + } + + // security log file + if (hasSecurityLogFile) { + // if security-log-file then create securityLogWriterAppender + this.securityLogWriterAppender = LogWriterAppenders.getOrCreateAppender( + LogWriterAppenders.Identifier.SECURITY, this.isLoner, this.config, false); + } else { + // let security route to regular log-file or stdout + } + } + + // LOG: create LogWriterLogger(s) for backwards compatibility of getLogWriter and + // getSecurityLogWriter + if (this.logWriter == null) { + this.logWriter = + LogWriterFactory.createLogWriterLogger(this.isLoner, false, this.config, true); + this.logWriter.fine("LogWriter is created."); + } + + // logWriter.info("Created log writer for IDS@"+System.identityHashCode(this)); + + if (this.securityLogWriter == null) { + // LOG: whole new LogWriterLogger instance for security + this.securityLogWriter = + LogWriterFactory.createLogWriterLogger(this.isLoner, true, this.config, false); + this.securityLogWriter.fine("SecurityLogWriter is created."); + } + + Services.setLogWriter(this.logWriter); + Services.setSecurityLogWriter(this.securityLogWriter); + } + + /** + * TODO: move this to lifecycle callbacks in Service Initializers + */ + private void postInitializeLogging() { + if (this.logWriterAppender != null) { + LogWriterAppenders.startupComplete(LogWriterAppenders.Identifier.MAIN); + } + if (this.securityLogWriterAppender != null) { + LogWriterAppenders.startupComplete(LogWriterAppenders.Identifier.SECURITY); + } + } + + /** * @since GemFire 5.7 */ private void startInitLocator() throws InterruptedException { http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/distributed/internal/direct/DirectChannel.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/direct/DirectChannel.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/direct/DirectChannel.java index cc88e95..6e9e9c7 100644 --- a/geode-core/src/main/java/org/apache/geode/distributed/internal/direct/DirectChannel.java +++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/direct/DirectChannel.java @@ -27,7 +27,6 @@ import org.apache.geode.internal.net.SocketCreator; import org.apache.geode.internal.cache.DirectReplyMessage; import org.apache.geode.internal.i18n.LocalizedStrings; import org.apache.geode.internal.logging.LogService; -import org.apache.geode.internal.logging.log4j.AlertAppender; import org.apache.geode.internal.logging.log4j.LocalizedMessage; import org.apache.geode.internal.logging.log4j.LogMarker; import org.apache.geode.internal.tcp.*; @@ -211,7 +210,7 @@ public class DirectChannel { boolean threadOwnsResources() { DM d = getDM(); if (d != null) { - return d.getSystem().threadOwnsResources() && !AlertAppender.isThreadAlerting(); + return d.getSystem().threadOwnsResources() && !DistributedAlertService.isThreadAlerting(); } return false; http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java index e99eff2..1e10227 100644 --- a/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java +++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessenger.java @@ -93,7 +93,6 @@ import org.apache.geode.internal.admin.remote.RemoteTransportConfig; import org.apache.geode.internal.cache.DirectReplyMessage; import org.apache.geode.internal.cache.DistributedCacheOperation; import org.apache.geode.internal.i18n.LocalizedStrings; -import org.apache.geode.internal.logging.log4j.AlertAppender; import org.apache.geode.internal.logging.log4j.LocalizedMessage; import org.apache.geode.internal.tcp.MemberShunnedException; @@ -939,7 +938,7 @@ public class JGroupsMessenger implements Messenger { msg.setFlag(Flag.DONT_BUNDLE); if (gfmsg.getProcessorType() == DistributionManager.HIGH_PRIORITY_EXECUTOR - || gfmsg instanceof HighPriorityDistributionMessage || AlertAppender.isThreadAlerting()) { + || gfmsg instanceof HighPriorityDistributionMessage || DistributedAlertService.isThreadAlerting()) { msg.setFlag(Flag.NO_FC); msg.setFlag(Flag.SKIP_BARRIER); } http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/internal/admin/remote/AlertLevelChangeMessage.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/remote/AlertLevelChangeMessage.java b/geode-core/src/main/java/org/apache/geode/internal/admin/remote/AlertLevelChangeMessage.java index c3a293f..1148c53 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/admin/remote/AlertLevelChangeMessage.java +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/remote/AlertLevelChangeMessage.java @@ -64,7 +64,7 @@ public final class AlertLevelChangeMessage extends SerialDistributionMessage { if (this.newLevel != Alert.OFF) { AlertAppender.getInstance().addAlertListener(this.getSender(), this.newLevel); if (logger.isTraceEnabled(LogMarker.DM)) { - logger.trace(LogMarker.DM, "Added new AlertListener to application log writer"); + logger.trace(LogMarker.DM, "Added new AlertSubscriber to application log writer"); } } } http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/internal/logging/ManagerLogWriter.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/logging/ManagerLogWriter.java b/geode-core/src/main/java/org/apache/geode/internal/logging/ManagerLogWriter.java index 4b333ed..46e806d 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/logging/ManagerLogWriter.java +++ b/geode-core/src/main/java/org/apache/geode/internal/logging/ManagerLogWriter.java @@ -46,6 +46,9 @@ public class ManagerLogWriter extends LocalLogWriter { private final RollingFileHandler rollingFileHandler; + // Don't redirect sysouts/syserrs to client log file. See #49492. + private final boolean redirectStdOut; + private LogConfig cfg = null; private LocalLogWriter mainLogger = this; @@ -67,16 +70,6 @@ public class ManagerLogWriter extends LocalLogWriter { /** * Creates a writer that logs to <code>System.out</code>. - * - * @param level only messages greater than or equal to this value will be logged. - * @throws IllegalArgumentException if level is not in legal range - */ - public ManagerLogWriter(int level, PrintStream out) { - this(level, out, null); - } - - /** - * Creates a writer that logs to <code>System.out</code>. * * @param level only messages greater than or equal to this value will be logged. * @param connectionName Name of the connection associated with this logger @@ -85,10 +78,11 @@ public class ManagerLogWriter extends LocalLogWriter { * * @since GemFire 3.5 */ - public ManagerLogWriter(int level, PrintStream out, String connectionName) { + public ManagerLogWriter(int level, PrintStream out, String connectionName, boolean redirectStdOut) { super(level, out, connectionName); this.fileSizeLimitInKB = Boolean.getBoolean(TEST_FILE_SIZE_LIMIT_IN_KB_PROPERTY); this.rollingFileHandler = new MainWithChildrenRollingFileHandler(); + this.redirectStdOut = redirectStdOut; } /** @@ -244,8 +238,7 @@ public class ManagerLogWriter extends LocalLogWriter { File tmpLogDir = rollingFileHandler.getParentFile(this.cfg.getLogFile()); tmpFile = File.createTempFile("mlw", null, tmpLogDir); // close the old guy down before we do the rename - PrintStream tmpps = OSProcess.redirectOutput(tmpFile, - AlertAppender.getInstance().isAlertingDisabled()/* See #49492 */); + PrintStream tmpps = OSProcess.redirectOutput(tmpFile, this.redirectStdOut); PrintWriter oldPW = this.setTarget(new PrintWriter(tmpps, true)); if (oldPW != null) { oldPW.close(); @@ -263,10 +256,7 @@ public class ManagerLogWriter extends LocalLogWriter { } } this.activeLogFile = new File(oldName); - // Don't redirect sysouts/syserrs to client log file. See #49492. - // IMPORTANT: This assumes that only a loner would have sendAlert set to false. - PrintStream ps = OSProcess.redirectOutput(activeLogFile, - AlertAppender.getInstance().isAlertingDisabled()); + PrintStream ps = OSProcess.redirectOutput(activeLogFile, this.redirectStdOut); PrintWriter oldPW = this.setTarget(new PrintWriter(ps, true), this.activeLogFile.length()); if (oldPW != null) { oldPW.close(); http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/internal/logging/SecurityManagerLogWriter.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/logging/SecurityManagerLogWriter.java b/geode-core/src/main/java/org/apache/geode/internal/logging/SecurityManagerLogWriter.java index 3e62f7d..77ff87e 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/logging/SecurityManagerLogWriter.java +++ b/geode-core/src/main/java/org/apache/geode/internal/logging/SecurityManagerLogWriter.java @@ -31,20 +31,12 @@ import java.io.PrintStream; */ public final class SecurityManagerLogWriter extends ManagerLogWriter { - public SecurityManagerLogWriter(int level, PrintStream stream) { - - super(level, stream); - } - - public SecurityManagerLogWriter(int level, PrintStream stream, String connectionName) { - - super(level, stream, connectionName); + public SecurityManagerLogWriter(int level, PrintStream stream, String connectionName, boolean redirectStdOut) { + super(level, stream, connectionName, redirectStdOut); } - @Override public void setConfig(LogConfig config) { - if (config instanceof DistributionConfig) { config = new SecurityLogConfig((DistributionConfig) config); } http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/internal/logging/log4j/AlertAppender.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/logging/log4j/AlertAppender.java b/geode-core/src/main/java/org/apache/geode/internal/logging/log4j/AlertAppender.java index 258f1d5..1a12b5a 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/logging/log4j/AlertAppender.java +++ b/geode-core/src/main/java/org/apache/geode/internal/logging/log4j/AlertAppender.java @@ -17,96 +17,59 @@ package org.apache.geode.internal.logging.log4j; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Date; -import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicReference; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.Logger; +import org.apache.geode.distributed.internal.DistributedAlertService; +import org.apache.geode.management.internal.alerting.AlertLevel; +import org.apache.geode.management.internal.alerting.AlertServiceListener; +import org.apache.geode.management.internal.alerting.AlertSubscriber; +import org.apache.geode.management.internal.alerting.DefaultAlertHandler; +import org.apache.geode.management.internal.alerting.AlertService; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.appender.AbstractAppender; import org.apache.logging.log4j.core.config.LoggerConfig; import org.apache.logging.log4j.core.layout.PatternLayout; -import org.apache.geode.distributed.DistributedMember; import org.apache.geode.distributed.internal.DistributionManager; -import org.apache.geode.distributed.internal.InternalDistributedSystem; -import org.apache.geode.internal.admin.Alert; -import org.apache.geode.internal.admin.remote.AlertListenerMessage; import org.apache.geode.internal.lang.ThreadUtils; import org.apache.geode.internal.logging.LogService; -import org.apache.geode.internal.tcp.ReenteredConnectException; +import org.apache.logging.log4j.status.StatusLogger; /** * A Log4j Appender which will notify listeners whenever a message of the requested level is written * to the log file. */ -public final class AlertAppender extends AbstractAppender implements PropertyChangeListener { - // TODO: appender impl should use StatusLogger - private static final Logger logger = LogService.getLogger(); +public final class AlertAppender extends AbstractAppender implements PropertyChangeListener, + AlertServiceListener { + private static final StatusLogger logger = StatusLogger.getLogger(); private static final String APPENDER_NAME = AlertAppender.class.getName(); private static final AlertAppender instance = createAlertAppender(); + private static final NullAlertProvider nullAlertProvider = new NullAlertProvider(); - /** Is this thread in the process of alerting? */ - private static final ThreadLocal<Boolean> alerting = new ThreadLocal<Boolean>() { - @Override - protected Boolean initialValue() { - return Boolean.FALSE; - } - }; - - private static final AtomicReference<InternalDistributedSystem> system = new AtomicReference<>(); - - // Listeners are ordered with the narrowest levels (e.g. FATAL) at the end - private final CopyOnWriteArrayList<Listener> listeners = new CopyOnWriteArrayList<>(); - - private final AppenderContext appenderContext = LogService.getAppenderContext(); + private final AtomicReference<AlertService> alertServiceRef = new AtomicReference<>(nullAlertProvider); - // This can be set by a loner distributed system to disable alerting - private volatile boolean alertingDisabled = false; + private final AppenderContext appenderContext; private static AlertAppender createAlertAppender() { - InternalDistributedSystem - .addConnectListener((final InternalDistributedSystem connectedSystem) -> { - system.set(connectedSystem); - connectedSystem - .addDisconnectListener((final InternalDistributedSystem disconnectedSystem) -> { - system.compareAndSet(connectedSystem, null); - }); - }); - - AlertAppender alertAppender = new AlertAppender(); + AlertAppender alertAppender = new AlertAppender(LogService.getAppenderContext()); alertAppender.start(); return alertAppender; } - private AlertAppender() { + private AlertAppender(final AppenderContext appenderContext) { super(APPENDER_NAME, null, PatternLayout.createDefaultLayout()); + this.appenderContext = appenderContext; } public static AlertAppender getInstance() { return instance; } - /** - * Returns true if the current thread is in the process of delivering an alert message. - */ - public static boolean isThreadAlerting() { - return alerting.get(); - } - - public boolean isAlertingDisabled() { - return alertingDisabled; - } - - public void setAlertingDisabled(final boolean alertingDisabled) { - this.alertingDisabled = alertingDisabled; - } - - public static void setIsAlerting(boolean isAlerting) { - alerting.set(isAlerting ? Boolean.TRUE : Boolean.FALSE); + public static void updateAlertService(final AlertService service) { + instance.alertServiceRef.set(service); } /** @@ -116,140 +79,49 @@ public final class AlertAppender extends AbstractAppender implements PropertyCha */ @Override public void append(final LogEvent event) { - if (this.alertingDisabled) { + AlertService alertService = this.alertServiceRef.get(); + if (!alertService.isEnabled()) { return; } // If already appending then don't send to avoid infinite recursion - if ((alerting.get())) { + if (alertService.isAlerting()) { return; } - setIsAlerting(true); + DistributedAlertService.setIsAlerting(true); try { + logger.debug("Delivering an alert event: {}", event); - final boolean isDebugEnabled = logger.isDebugEnabled(); - if (isDebugEnabled) { - logger.debug("Delivering an alert event: {}", event); - } + int intLevel = AlertLevel.logLevelToAlertLevel(event.getLevel().intLevel()); + Date date = new Date(event.getTimeMillis()); + String threadName = event.getThreadName(); + String logMessage = event.getMessage().getFormattedMessage(); + String stackTrace = ThreadUtils.stackTraceToString(event.getThrown(), true); + String connectionName = alertService.getMemberName(); - InternalDistributedSystem ds = system.get(); - if (ds == null) { - logger.debug("Did not append alert event because the distributed system is set to null."); - return; - } - DistributionManager distMgr = (DistributionManager) ds.getDistributionManager(); - - final int intLevel = logLevelToAlertLevel(event.getLevel().intLevel()); - final Date date = new Date(event.getTimeMillis()); - final String threadName = event.getThreadName(); - final String logMessage = event.getMessage().getFormattedMessage(); - final String stackTrace = ThreadUtils.stackTraceToString(event.getThrown(), true); - final String connectionName = ds.getConfig().getName(); - - for (Listener listener : this.listeners) { + for (AlertSubscriber listener : this.listeners) { if (event.getLevel().intLevel() > listener.getLevel().intLevel()) { break; } - try { - AlertListenerMessage alertMessage = - AlertListenerMessage.create(listener.getMember(), intLevel, date, connectionName, - threadName, Thread.currentThread().getId(), logMessage, stackTrace); - - if (listener.getMember().equals(distMgr.getDistributionManagerId())) { - if (isDebugEnabled) { - logger.debug("Delivering local alert message: {}, {}, {}, {}, {}, [{}], [{}].", - listener.getMember(), intLevel, date, connectionName, threadName, logMessage, - stackTrace); - } - alertMessage.process(distMgr); - } else { - if (isDebugEnabled) { - logger.debug("Delivering remote alert message: {}, {}, {}, {}, {}, [{}], [{}].", - listener.getMember(), intLevel, date, connectionName, threadName, logMessage, - stackTrace); - } - distMgr.putOutgoing(alertMessage); - } - } catch (ReenteredConnectException e) { - // OK. We can't send to this recipient because we're in the middle of - // trying to connect to it. - } + alertService + .handleAlert(alertService, intLevel, date, threadName, logMessage, stackTrace, + connectionName, + listener); } } finally { - setIsAlerting(false); - } - } - - public synchronized void addAlertListener(final DistributedMember member, final int alertLevel) { - final Level level = LogService.toLevel(alertLevelToLogLevel(alertLevel)); - - if (this.listeners.size() == 0) { - this.appenderContext.getLoggerContext().addPropertyChangeListener(this); - } - - addListenerToSortedList(new Listener(level, member)); - - LoggerConfig loggerConfig = this.appenderContext.getLoggerConfig(); - loggerConfig.addAppender(this, this.listeners.get(0).getLevel(), null); - if (logger.isDebugEnabled()) { - logger.debug("Added/Replaced alert listener for member {} at level {}", member, level); - } - } - - public synchronized boolean removeAlertListener(final DistributedMember member) { - final boolean memberWasFound = this.listeners.remove(new Listener(null, member)); - - if (memberWasFound) { - if (this.listeners.size() == 0) { - this.appenderContext.getLoggerContext().removePropertyChangeListener(this); - this.appenderContext.getLoggerConfig().removeAppender(APPENDER_NAME); - - } else { - LoggerConfig loggerConfig = this.appenderContext.getLoggerConfig(); - loggerConfig.addAppender(this, this.listeners.get(0).getLevel(), null); - } - if (logger.isDebugEnabled()) { - logger.debug("Removed alert listener for member {}", member); - } - } - - return memberWasFound; - } - - public synchronized boolean hasAlertListener(final DistributedMember member, - final int alertLevel) { - final Level level = LogService.toLevel(alertLevelToLogLevel(alertLevel)); - - for (Listener listener : this.listeners) { - if (listener.getMember().equals(member) && listener.getLevel().equals(level)) { - return true; - } - } - - // Special case for alert level Alert.OFF (NONE_LEVEL), because we can never have an actual - // listener with - // this level (see AlertLevelChangeMessage.process()). - if (alertLevel == Alert.OFF) { - for (Listener listener : this.listeners) { - if (listener.getMember().equals(member)) { - return false; - } - } - return true; + DistributedAlertService.setIsAlerting(false); } - - return false; } @Override - public synchronized void propertyChange(final PropertyChangeEvent evt) { + public synchronized void propertyChange(final PropertyChangeEvent event) { if (logger.isDebugEnabled()) { logger.debug("Responding to a property change event. Property name is {}.", - evt.getPropertyName()); + event.getPropertyName()); } - if (evt.getPropertyName().equals(LoggerContext.PROPERTY_CONFIG)) { + if (event.getPropertyName().equals(LoggerContext.PROPERTY_CONFIG)) { LoggerConfig loggerConfig = this.appenderContext.getLoggerConfig(); if (!loggerConfig.getAppenders().containsKey(APPENDER_NAME)) { loggerConfig.addAppender(this, this.listeners.get(0).getLevel(), null); @@ -257,115 +129,56 @@ public final class AlertAppender extends AbstractAppender implements PropertyCha } } - /** - * Will add (or replace) a listener to the list of sorted listeners such that listeners with a - * narrower level (e.g. FATAL) will be at the end of the list. - * - * @param listener The listener to add to the list. - */ - private void addListenerToSortedList(final Listener listener) { - if (this.listeners.contains(listener)) { - this.listeners.remove(listener); - } - - for (int i = 0; i < this.listeners.size(); i++) { - if (listener.getLevel().compareTo(this.listeners.get(i).getLevel()) >= 0) { - this.listeners.add(i, listener); - return; - } - } - - this.listeners.add(listener); + public synchronized void shuttingDown() { + this.alertServiceRef.get().shuttingDown(); + this.appenderContext.getLoggerContext().removePropertyChangeListener(this); + this.appenderContext.getLoggerConfig().removeAppender(APPENDER_NAME); } - /** - * Converts an int alert level to an int log level. - * - * @param alertLevel The int value for the alert level - * @return The int value for the matching log level - * @throws java.lang.IllegalArgumentException If there is no matching log level - */ - public static int alertLevelToLogLevel(final int alertLevel) { - switch (alertLevel) { - case Alert.SEVERE: - return Level.FATAL.intLevel(); - case Alert.ERROR: - return Level.ERROR.intLevel(); - case Alert.WARNING: - return Level.WARN.intLevel(); - case Alert.OFF: - return Level.OFF.intLevel(); - } - - throw new IllegalArgumentException("Unknown Alert level [" + alertLevel + "]."); + @Override + public void clear() { + this.appenderContext.getLoggerContext().addPropertyChangeListener(this); } - /** - * Converts an int log level to an int alert level. - * - * @param logLevel The int value for the log level - * @return The int value for the matching alert level - * @throws java.lang.IllegalArgumentException If there is no matching log level - */ - public static int logLevelToAlertLevel(final int logLevel) { - if (logLevel == Level.FATAL.intLevel()) { - return Alert.SEVERE; - } else if (logLevel == Level.ERROR.intLevel()) { - return Alert.ERROR; - } else if (logLevel == Level.WARN.intLevel()) { - return Alert.WARNING; - } else if (logLevel == Level.OFF.intLevel()) { - return Alert.OFF; - } + @Override + public void lowestLevel(final int level) { - throw new IllegalArgumentException("Unknown Log level [" + logLevel + "]."); } - public synchronized void shuttingDown() { - this.listeners.clear(); - this.appenderContext.getLoggerContext().removePropertyChangeListener(this); - this.appenderContext.getLoggerConfig().removeAppender(APPENDER_NAME); - } + private static class NullAlertProvider implements AlertService { - /** - * Simple value object which holds a DistributedMember and Level pair. - */ - static class Listener { - private Level level; - private DistributedMember member; - - public Level getLevel() { - return this.level; + @Override + public boolean isEnabled() { + return false; } - public DistributedMember getMember() { - return this.member; + @Override + public DistributionManager getDistributionManager() { + return null; } - Listener(final Level level, final DistributedMember member) { - this.level = level; - this.member = member; + @Override + public String getMemberName() { + return null; } - /** - * Never used, but maintain the hashCode/equals contract. - */ @Override - public int hashCode() { - return 31 + ((this.member == null) ? 0 : this.member.hashCode()); + public boolean isAlerting() { + return false; } - /** - * Ignore the level when determining equality. - */ @Override - public boolean equals(Object other) { - return (this.member.equals(((Listener) other).member)) ? true : false; + public void shuttingDown() { + } @Override - public String toString() { - return "Listener [level=" + this.level + ", member=" + this.member + "]"; + public void handleAlert(final AlertService alertProvider, final int intLevel, final Date date, + final String threadName, + final String logMessage, final String stackTrace, + final String connectionName, + final AlertSubscriber listener) { + } } } http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/internal/logging/log4j/LogWriterAppenders.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/logging/log4j/LogWriterAppenders.java b/geode-core/src/main/java/org/apache/geode/internal/logging/log4j/LogWriterAppenders.java index 310deb2..f4d3ae9 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/logging/log4j/LogWriterAppenders.java +++ b/geode-core/src/main/java/org/apache/geode/internal/logging/log4j/LogWriterAppenders.java @@ -108,8 +108,6 @@ public class LogWriterAppenders { String firstMsg = null; boolean firstMsgWarning = false; - AlertAppender.getInstance().setAlertingDisabled(isLoner); - // security-log-file is specified in DistributionConfig if (isSecurity) { if (isDistributionConfig) { @@ -171,10 +169,11 @@ public class LogWriterAppenders { ManagerLogWriter mlw = null; String logWriterLoggerName = null; if (isSecurity) { - mlw = new SecurityManagerLogWriter(dsConfig.getSecurityLogLevel(), out, config.getName()); + // use false for redirectStdOut fixes bug in which some dunits redirected stdout to security + mlw = new SecurityManagerLogWriter(dsConfig.getSecurityLogLevel(), out, config.getName(), false); logWriterLoggerName = LogService.SECURITY_LOGGER_NAME; } else { - mlw = new ManagerLogWriter(config.getLogLevel(), out, config.getName()); + mlw = new ManagerLogWriter(config.getLogLevel(), out, config.getName(), isLoner); logWriterLoggerName = LogService.MAIN_LOGGER_NAME; } @@ -249,7 +248,6 @@ public class LogWriterAppenders { } public synchronized static void destroy(final Identifier id) { - // TODO:LOG:KIRK: new Exception("KIRK destroy called for " + id).printStackTrace(); LogWriterAppender appender = appenders.get(id); if (appender == null) { return; http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/internal/tcp/Connection.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/tcp/Connection.java b/geode-core/src/main/java/org/apache/geode/internal/tcp/Connection.java index ca5cce1..bc76a9a 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/tcp/Connection.java +++ b/geode-core/src/main/java/org/apache/geode/internal/tcp/Connection.java @@ -29,7 +29,6 @@ import org.apache.geode.internal.SystemTimer.SystemTimerTask; import org.apache.geode.internal.i18n.LocalizedStrings; import org.apache.geode.internal.logging.LogService; import org.apache.geode.internal.logging.LoggingThreadGroup; -import org.apache.geode.internal.logging.log4j.AlertAppender; import org.apache.geode.internal.logging.log4j.LocalizedMessage; import org.apache.geode.internal.net.*; import org.apache.geode.internal.tcp.MsgReader.Header; @@ -1062,7 +1061,7 @@ public class Connection implements Runnable { } else { // if we're sending an alert and can't connect, bail out. A sick // alert listener should not prevent cache operations from continuing - if (AlertAppender.isThreadAlerting()) { + if (DistributedAlertService.isThreadAlerting()) { // do not change the text of this exception - it is looked for in exception handlers throw new IOException("Cannot form connection to alert listener " + remoteAddr); } http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/internal/tcp/ConnectionTable.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/tcp/ConnectionTable.java b/geode-core/src/main/java/org/apache/geode/internal/tcp/ConnectionTable.java index 6307c52..41fe939 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/tcp/ConnectionTable.java +++ b/geode-core/src/main/java/org/apache/geode/internal/tcp/ConnectionTable.java @@ -37,6 +37,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import org.apache.geode.distributed.internal.DistributedAlertService; import org.apache.logging.log4j.Logger; import org.apache.geode.SystemFailure; @@ -53,7 +54,6 @@ import org.apache.geode.internal.SystemTimer; import org.apache.geode.internal.i18n.LocalizedStrings; import org.apache.geode.internal.logging.LogService; import org.apache.geode.internal.logging.LoggingThreadGroup; -import org.apache.geode.internal.logging.log4j.AlertAppender; import org.apache.geode.internal.logging.log4j.LocalizedMessage; /** @@ -187,7 +187,7 @@ public class ConnectionTable { boolean threadOwnsResources() { DM d = getDM(); if (d != null) { - return d.getSystem().threadOwnsResources() && !AlertAppender.isThreadAlerting(); + return d.getSystem().threadOwnsResources() && !DistributedAlertService.isThreadAlerting(); } return false; @@ -478,7 +478,7 @@ public class ConnectionTable { } else { // we have existing connection if (mEntry instanceof PendingConnection) { - if (AlertAppender.isThreadAlerting()) { + if (DistributedAlertService.isThreadAlerting()) { // do not change the text of this exception - it is looked for in exception handlers throw new IOException("Cannot form connection to alert listener " + id); } http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/internal/tcp/ReenteredConnectException.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/tcp/ReenteredConnectException.java b/geode-core/src/main/java/org/apache/geode/internal/tcp/ReenteredConnectException.java index 39554cb..dc71bb2 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/tcp/ReenteredConnectException.java +++ b/geode-core/src/main/java/org/apache/geode/internal/tcp/ReenteredConnectException.java @@ -20,7 +20,7 @@ import org.apache.geode.GemFireException; * An exception indicating that the same thread that is in the middle of trying to connect has tried * to obtain a connection to the same member further down the call stack. * - * This condition has been observered when using an AlertListener, because we try to transmit + * This condition has been observered when using an AlertSubscriber, because we try to transmit * messages logged during a connection to the very member we're trying to connect to. * */ http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/internal/tcp/TCPConduit.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/tcp/TCPConduit.java b/geode-core/src/main/java/org/apache/geode/internal/tcp/TCPConduit.java index 1398070..d9ffd6d 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/tcp/TCPConduit.java +++ b/geode-core/src/main/java/org/apache/geode/internal/tcp/TCPConduit.java @@ -36,6 +36,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLException; +import org.apache.geode.distributed.internal.DistributedAlertService; import org.apache.logging.log4j.Logger; import org.apache.geode.CancelCriterion; @@ -54,7 +55,6 @@ import org.apache.geode.distributed.internal.membership.MembershipManager; import org.apache.geode.internal.i18n.LocalizedStrings; import org.apache.geode.internal.logging.LogService; import org.apache.geode.internal.logging.LoggingThreadGroup; -import org.apache.geode.internal.logging.log4j.AlertAppender; import org.apache.geode.internal.logging.log4j.LocalizedMessage; import org.apache.geode.internal.logging.log4j.LogMarker; import org.apache.geode.internal.net.SocketCreator; @@ -1054,7 +1054,7 @@ public class TCPConduit implements Runnable { } catch (IOException e) { problem = e; // bug #43962 don't keep trying to connect to an alert listener - if (AlertAppender.isThreadAlerting()) { + if (DistributedAlertService.isThreadAlerting()) { if (logger.isDebugEnabled()) { logger.debug("Giving up connecting to alert listener {}", memberAddress); } http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertHandler.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertHandler.java b/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertHandler.java new file mode 100644 index 0000000..f247132 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertHandler.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.management.internal.alerting; + +import java.util.Date; + +public interface AlertHandler { + void handleAlert(AlertService alertProvider, + int intLevel, + Date date, + String threadName, + String logMessage, + String stackTrace, + String connectionName, + AlertSubscriber listener); +} http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertLevel.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertLevel.java b/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertLevel.java new file mode 100644 index 0000000..09ad869 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertLevel.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.management.internal.alerting; + +import org.apache.geode.internal.admin.Alert; +import org.apache.logging.log4j.Level; + +public class AlertLevel { + /** + * Converts an int alert level to an int log level. + * + * @param alertLevel The int value for the alert level + * @return The int value for the matching log level + * @throws IllegalArgumentException If there is no matching log level + */ + public static int alertLevelToLogLevel(final int alertLevel) { + switch (alertLevel) { + case Alert.SEVERE: + return Level.FATAL.intLevel(); + case Alert.ERROR: + return Level.ERROR.intLevel(); + case Alert.WARNING: + return Level.WARN.intLevel(); + case Alert.OFF: + return Level.OFF.intLevel(); + } + + throw new IllegalArgumentException("Unknown Alert level [" + alertLevel + "]."); + } + + /** + * Converts an int log level to an int alert level. + * + * @param logLevel The int value for the log level + * @return The int value for the matching alert level + * @throws IllegalArgumentException If there is no matching log level + */ + public static int logLevelToAlertLevel(final int logLevel) { + if (logLevel == Level.FATAL.intLevel()) { + return Alert.SEVERE; + } else if (logLevel == Level.ERROR.intLevel()) { + return Alert.ERROR; + } else if (logLevel == Level.WARN.intLevel()) { + return Alert.WARNING; + } else if (logLevel == Level.OFF.intLevel()) { + return Alert.OFF; + } + + throw new IllegalArgumentException("Unknown Log level [" + logLevel + "]."); + } +} http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertService.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertService.java b/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertService.java new file mode 100644 index 0000000..2c4f272 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertService.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.management.internal.alerting; + +import org.apache.geode.distributed.internal.DistributionManager; +import org.apache.geode.internal.logging.log4j.AlertAppender; + +public interface AlertService extends AlertHandler { + + static void install(final AlertService service) { + AlertAppender.updateAlertService(service); + } + + boolean isEnabled(); + + DistributionManager getDistributionManager(); + + String getMemberName(); + + boolean isAlerting(); + + void shuttingDown(); +} http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertServiceListener.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertServiceListener.java b/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertServiceListener.java new file mode 100644 index 0000000..9e44bb1 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertServiceListener.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.management.internal.alerting; + +public interface AlertServiceListener { + + void clear(); + void lowestLevel(int level); +} http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertSubscriber.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertSubscriber.java b/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertSubscriber.java new file mode 100644 index 0000000..b7b64b0 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/management/internal/alerting/AlertSubscriber.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.management.internal.alerting; + +import org.apache.geode.distributed.DistributedMember; +import org.apache.logging.log4j.Level; + +/** + * Simple value object which holds a DistributedMember and Level pair. + */ +public class AlertSubscriber { + + private final Level level; + private final DistributedMember member; + + public AlertSubscriber(final Level level, final DistributedMember member) { + this.level = level; + this.member = member; + } + + public Level getLevel() { + return this.level; + } + + public DistributedMember getMember() { + return this.member; + } + + /** + * Never used, but maintain the hashCode/equals contract. + */ + @Override + public int hashCode() { + return 31 + ((this.member == null) ? 0 : this.member.hashCode()); + } + + /** + * Ignore the level when determining equality. + */ + @Override + public boolean equals(Object other) { + return (this.member.equals(((AlertSubscriber) other).member)) ? true : false; + } + + @Override + public String toString() { + return "AlertSubscriber [level=" + this.level + ", member=" + this.member + "]"; + } +} http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/test/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessengerJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessengerJUnitTest.java b/geode-core/src/test/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessengerJUnitTest.java index 307b594..b1914db 100755 --- a/geode-core/src/test/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessengerJUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessengerJUnitTest.java @@ -36,10 +36,8 @@ import org.apache.geode.distributed.internal.membership.gms.messages.JoinRequest import org.apache.geode.distributed.internal.membership.gms.messages.JoinResponseMessage; import org.apache.geode.distributed.internal.membership.gms.messages.LeaveRequestMessage; import org.apache.geode.distributed.internal.membership.gms.messenger.JGroupsMessenger.JGroupsReceiver; -import org.apache.geode.internal.*; import org.apache.geode.internal.admin.remote.RemoteTransportConfig; import org.apache.geode.internal.cache.DistributedCacheOperation; -import org.apache.geode.internal.logging.log4j.AlertAppender; import org.apache.geode.test.junit.categories.IntegrationTest; import static org.apache.geode.distributed.ConfigurationProperties.*; @@ -223,13 +221,13 @@ public class JGroupsMessengerJUnitTest { messenger.setMessageFlags(dmsg, jgmsg); assertFalse("expected no_fc to not be set in " + jgmsg.getFlags(), jgmsg.isFlagSet(Message.Flag.NO_FC)); - AlertAppender.setIsAlerting(true); + DistributedAlertService.setIsAlerting(true); try { messenger.setMessageFlags(dmsg, jgmsg); assertTrue("expected no_fc to be set in " + jgmsg.getFlags(), jgmsg.isFlagSet(Message.Flag.NO_FC)); } finally { - AlertAppender.setIsAlerting(false); + DistributedAlertService.setIsAlerting(false); } } http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/test/java/org/apache/geode/internal/logging/TestLogWriterFactory.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/logging/TestLogWriterFactory.java b/geode-core/src/test/java/org/apache/geode/internal/logging/TestLogWriterFactory.java index 87f370c..f84c518 100644 --- a/geode-core/src/test/java/org/apache/geode/internal/logging/TestLogWriterFactory.java +++ b/geode-core/src/test/java/org/apache/geode/internal/logging/TestLogWriterFactory.java @@ -90,9 +90,9 @@ public class TestLogWriterFactory extends Assert { } if (isSecurityLog) { - mlw = new SecurityManagerLogWriter(config.getSecurityLogLevel(), out, config.getName()); + mlw = new SecurityManagerLogWriter(config.getSecurityLogLevel(), out, config.getName(), false); } else { - mlw = new ManagerLogWriter(config.getLogLevel(), out, config.getName()); + mlw = new ManagerLogWriter(config.getLogLevel(), out, config.getName(), false); } ((ManagerLogWriter) mlw).setConfig(config); } http://git-wip-us.apache.org/repos/asf/geode/blob/d9815b6d/geode-core/src/test/java/org/apache/geode/internal/logging/log4j/AlertAppenderJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/logging/log4j/AlertAppenderJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/logging/log4j/AlertAppenderJUnitTest.java index 5717253..1a440b1 100644 --- a/geode-core/src/test/java/org/apache/geode/internal/logging/log4j/AlertAppenderJUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/internal/logging/log4j/AlertAppenderJUnitTest.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; +import org.apache.geode.management.internal.alerting.AlertSubscriber; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.config.LoggerConfig; import org.junit.After; @@ -43,12 +44,13 @@ import org.apache.geode.test.junit.categories.UnitTest; @Category(UnitTest.class) public class AlertAppenderJUnitTest { - private final List<DistributedMember> members = new ArrayList<DistributedMember>(); + private List<DistributedMember> members; private Level previousLogLevel; @Before public void setUp() { this.previousLogLevel = LogService.getBaseLogLevel(); + this.members = new ArrayList<>(); } @After @@ -62,10 +64,6 @@ public class AlertAppenderJUnitTest { } } - private DistributedMember createTestDistributedMember(String name) { - return new TestDistributedMember(name); - } - /** * Verify that adding/removing/replacing listeners works correctly. */ @@ -91,8 +89,8 @@ public class AlertAppenderJUnitTest { listenersField.setAccessible(true); @SuppressWarnings("unchecked") - final CopyOnWriteArrayList<AlertAppender.Listener> listeners = - (CopyOnWriteArrayList<AlertAppender.Listener>) listenersField + final CopyOnWriteArrayList<AlertSubscriber> listeners = + (CopyOnWriteArrayList<AlertSubscriber>) listenersField .get(AlertAppender.getInstance()); // Verify add @@ -186,6 +184,10 @@ public class AlertAppenderJUnitTest { assertFalse(loggerConfig.getAppenders().containsKey(appenderName)); } + private DistributedMember createTestDistributedMember(final String name) { + return new TestDistributedMember(name); + } + private static class TestDistributedMember implements DistributedMember { private final String name;