diff --git a/nifi-api/src/main/java/org/apache/nifi/flow/VersionedProcessGroup.java b/nifi-api/src/main/java/org/apache/nifi/flow/VersionedProcessGroup.java index ea4edf22ca8d..c6ee435f5d87 100644 --- a/nifi-api/src/main/java/org/apache/nifi/flow/VersionedProcessGroup.java +++ b/nifi-api/src/main/java/org/apache/nifi/flow/VersionedProcessGroup.java @@ -47,6 +47,8 @@ public class VersionedProcessGroup extends VersionedComponent { private Long defaultBackPressureObjectThreshold; private String defaultBackPressureDataSizeThreshold; + private String logFileSuffix; + @ApiModelProperty("The child Process Groups") public Set getProcessGroups() { @@ -205,4 +207,13 @@ public String getDefaultBackPressureDataSizeThreshold() { public void setDefaultBackPressureDataSizeThreshold(final String defaultBackPressureDataSizeThreshold) { this.defaultBackPressureDataSizeThreshold = defaultBackPressureDataSizeThreshold; } + + @ApiModelProperty(value = "The log file suffix for this Process Group for dedicated logging.") + public String getLogFileSuffix() { + return logFileSuffix; + } + + public void setLogFileSuffix(final String logFileSuffix) { + this.logFileSuffix = logFileSuffix; + } } diff --git a/nifi-assembly/pom.xml b/nifi-assembly/pom.xml index be338304b1e1..feaca4500c40 100644 --- a/nifi-assembly/pom.xml +++ b/nifi-assembly/pom.xml @@ -138,6 +138,12 @@ language governing permissions and limitations under the License. --> slf4j-api compile + + org.apache.nifi + nifi-per-process-group-logging + 2.0.0-SNAPSHOT + compile + org.apache.nifi nifi-api diff --git a/nifi-assembly/src/main/assembly/common.xml b/nifi-assembly/src/main/assembly/common.xml index 9ce32c27f1e5..5bb42a2aa3eb 100644 --- a/nifi-assembly/src/main/assembly/common.xml +++ b/nifi-assembly/src/main/assembly/common.xml @@ -30,6 +30,7 @@ *:logback-core *:nifi-api *:nifi-property-protection-api + *:nifi-per-process-group-logging diff --git a/nifi-commons/nifi-per-process-group-logging/pom.xml b/nifi-commons/nifi-per-process-group-logging/pom.xml new file mode 100644 index 000000000000..aefe923e9e96 --- /dev/null +++ b/nifi-commons/nifi-per-process-group-logging/pom.xml @@ -0,0 +1,31 @@ + + + + 4.0.0 + + org.apache.nifi + nifi-commons + 2.0.0-SNAPSHOT + + nifi-per-process-group-logging + jar + + + ch.qos.logback + logback-classic + + + diff --git a/nifi-commons/nifi-per-process-group-logging/src/main/java/org.apache.nifi.logging/NifiDiscriminator.java b/nifi-commons/nifi-per-process-group-logging/src/main/java/org.apache.nifi.logging/NifiDiscriminator.java new file mode 100644 index 000000000000..df51e22ed4f5 --- /dev/null +++ b/nifi-commons/nifi-per-process-group-logging/src/main/java/org.apache.nifi.logging/NifiDiscriminator.java @@ -0,0 +1,57 @@ +/* + * 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.nifi.logging; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.sift.Discriminator; +import org.slf4j.event.KeyValuePair; + +public class NifiDiscriminator implements Discriminator { + private static final String KEY = "logFileSuffix"; + + private boolean started; + + @Override + public String getDiscriminatingValue(final ILoggingEvent iLoggingEvent) { + for (KeyValuePair keyValuePair : iLoggingEvent.getKeyValuePairs()) { + if (keyValuePair.key.equals(getKey())) { + return keyValuePair.value.toString(); + } + } + return null; + } + + @Override + public String getKey() { + return KEY; + } + + @Override + public void start() { + started = true; + } + + @Override + public void stop() { + started = false; + } + + @Override + public boolean isStarted() { + return started; + } +} diff --git a/nifi-commons/pom.xml b/nifi-commons/pom.xml index 8f8ec3b9bc02..c3286d77b860 100644 --- a/nifi-commons/pom.xml +++ b/nifi-commons/pom.xml @@ -36,6 +36,7 @@ nifi-logging-utils nifi-metrics nifi-parameter + nifi-per-process-group-logging nifi-property-encryptor nifi-property-utils nifi-properties diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupDTO.java index d2f08b5e3f8d..336f5d27145e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupDTO.java @@ -39,6 +39,7 @@ public class ProcessGroupDTO extends ComponentDTO { private String defaultFlowFileExpiration; private Long defaultBackPressureObjectThreshold; private String defaultBackPressureDataSizeThreshold; + private String logFileSuffix; private Integer runningCount; private Integer stoppedCount; @@ -403,4 +404,13 @@ public String getDefaultBackPressureDataSizeThreshold() { public void setDefaultBackPressureDataSizeThreshold(final String defaultBackPressureDataSizeThreshold) { this.defaultBackPressureDataSizeThreshold = defaultBackPressureDataSizeThreshold; } + + @ApiModelProperty(value = "The log file suffix for this Process Group for dedicated logging.") + public String getLogFileSuffix() { + return logFileSuffix; + } + + public void setLogFileSuffix(final String logFileSuffix) { + this.logFileSuffix = logFileSuffix; + } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java index e740336a6dfe..b2095e76df37 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java @@ -61,6 +61,7 @@ import org.apache.nifi.logging.ComponentLog; import org.apache.nifi.logging.LogLevel; import org.apache.nifi.logging.LogRepositoryFactory; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.nar.ExtensionManager; import org.apache.nifi.nar.InstanceClassLoader; import org.apache.nifi.nar.NarCloseable; @@ -1572,7 +1573,7 @@ private void run(ScheduledExecutorService taskScheduler, long administrativeYiel SchedulingAgentCallback schedulingAgentCallback, boolean failIfStopping, ScheduledState desiredState, ScheduledState scheduledState) { final Processor processor = processorRef.get().getProcessor(); - final ComponentLog procLog = new SimpleProcessLogger(StandardProcessorNode.this.getIdentifier(), processor); + final ComponentLog procLog = new SimpleProcessLogger(StandardProcessorNode.this.getIdentifier(), processor, new StandardLoggingContext(StandardProcessorNode.this)); LOG.info("Starting {}", this); ScheduledState currentState; @@ -1714,7 +1715,7 @@ private void initiateStart(final ScheduledExecutorService taskScheduler, final l AtomicLong startupAttemptCount, final Supplier processContextFactory, final SchedulingAgentCallback schedulingAgentCallback) { final Processor processor = getProcessor(); - final ComponentLog procLog = new SimpleProcessLogger(StandardProcessorNode.this.getIdentifier(), processor); + final ComponentLog procLog = new SimpleProcessLogger(StandardProcessorNode.this.getIdentifier(), processor, new StandardLoggingContext(StandardProcessorNode.this)); // Completion Timestamp is set to MAX_VALUE because we don't want to timeout until the task has a chance to run. final AtomicLong completionTimestampRef = new AtomicLong(Long.MAX_VALUE); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java index cde95fce9fb9..2349c8a34398 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java @@ -58,6 +58,7 @@ import org.apache.nifi.parameter.ParameterContext; import org.apache.nifi.parameter.ParameterLookup; import org.apache.nifi.processor.SimpleProcessLogger; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.registry.ComponentVariableRegistry; import org.apache.nifi.util.CharacterFilterUtils; import org.apache.nifi.util.FormatUtils; @@ -596,7 +597,8 @@ public void run() { enablingAttemptCount.incrementAndGet(); if (enablingAttemptCount.get() == 120 || enablingAttemptCount.get() % 3600 == 0) { - final ComponentLog componentLog = new SimpleProcessLogger(getIdentifier(), StandardControllerServiceNode.this); + final ComponentLog componentLog = new SimpleProcessLogger(getIdentifier(), StandardControllerServiceNode.this, + new StandardLoggingContext(StandardControllerServiceNode.this)); componentLog.error("Encountering difficulty enabling. (Validation State is {}: {}). Will continue trying to enable.", validationState, validationState.getValidationErrors()); } @@ -635,7 +637,8 @@ public void run() { future.completeExceptionally(e); final Throwable cause = e instanceof InvocationTargetException ? e.getCause() : e; - final ComponentLog componentLog = new SimpleProcessLogger(getIdentifier(), StandardControllerServiceNode.this); + final ComponentLog componentLog = new SimpleProcessLogger(getIdentifier(), StandardControllerServiceNode.this, + new StandardLoggingContext(StandardControllerServiceNode.this)); componentLog.error("Failed to invoke @OnEnabled method", cause); invokeDisable(configContext); @@ -717,7 +720,7 @@ private void invokeDisable(ConfigurationContext configContext) { LOG.debug("Successfully disabled {}", this); } catch (Exception e) { final Throwable cause = e instanceof InvocationTargetException ? e.getCause() : e; - final ComponentLog componentLog = new SimpleProcessLogger(getIdentifier(), StandardControllerServiceNode.this); + final ComponentLog componentLog = new SimpleProcessLogger(getIdentifier(), StandardControllerServiceNode.this, new StandardLoggingContext(StandardControllerServiceNode.this)); componentLog.error("Failed to invoke @OnDisabled method due to {}", cause); LOG.error("Failed to invoke @OnDisabled method of {} due to {}", getControllerServiceImplementation(), cause.toString()); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/state/StandardStateManager.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/state/StandardStateManager.java index 6a60058d6e70..912cdb76feed 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/state/StandardStateManager.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/state/StandardStateManager.java @@ -25,6 +25,7 @@ import org.apache.nifi.logging.LogRepository; import org.apache.nifi.logging.LogRepositoryFactory; import org.apache.nifi.processor.SimpleProcessLogger; +import org.apache.nifi.logging.StandardLoggingContext; import java.io.IOException; import java.util.Map; @@ -52,7 +53,7 @@ private ComponentLog getLogger(final String componentId) { final LogRepository repo = LogRepositoryFactory.getRepository(componentId); final ComponentLog logger = (repo == null) ? null : repo.getLogger(); if (repo == null || logger == null) { - return new SimpleProcessLogger(componentId, this); + return new SimpleProcessLogger(componentId, this, new StandardLoggingContext(null)); } return logger; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/state/manager/StandardStateManagerProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/state/manager/StandardStateManagerProvider.java index 49eb1e98b528..a6d53a992bc5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/state/manager/StandardStateManagerProvider.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/state/manager/StandardStateManagerProvider.java @@ -51,6 +51,7 @@ import org.apache.nifi.parameter.ParameterParser; import org.apache.nifi.parameter.ParameterTokenList; import org.apache.nifi.processor.SimpleProcessLogger; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.processor.StandardValidationContext; import org.apache.nifi.registry.VariableRegistry; import org.apache.nifi.security.util.SslContextFactory; @@ -341,7 +342,7 @@ private static StateProvider createStateProvider( propertyMap.put(descriptor, new StandardPropertyValue(resourceContext, entry.getValue(),null, parameterLookup, variableRegistry)); } - final ComponentLog logger = new SimpleProcessLogger(providerConfig.getId(), provider); + final ComponentLog logger = new SimpleProcessLogger(providerConfig.getId(), provider, new StandardLoggingContext(null)); final StateProviderInitializationContext initContext = new StandardStateProviderInitializationContext(providerConfig.getId(), propertyMap, sslContext, logger); synchronized (provider) { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/flow/synchronization/StandardVersionedComponentSynchronizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/flow/synchronization/StandardVersionedComponentSynchronizer.java index 889a6e8996f2..4993a415d417 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/flow/synchronization/StandardVersionedComponentSynchronizer.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/flow/synchronization/StandardVersionedComponentSynchronizer.java @@ -317,6 +317,10 @@ private void synchronize(final ProcessGroup group, final VersionedProcessGroup p group.setDefaultBackPressureObjectThreshold(proposed.getDefaultBackPressureObjectThreshold()); group.setDefaultBackPressureDataSizeThreshold(proposed.getDefaultBackPressureDataSizeThreshold()); + if (group.getLogFileSuffix() == null || group.getLogFileSuffix().isEmpty()) { + group.setLogFileSuffix(proposed.getLogFileSuffix()); + } + final VersionedFlowCoordinates remoteCoordinates = proposed.getVersionedFlowCoordinates(); if (remoteCoordinates == null) { group.disconnectVersionControl(false); @@ -1795,6 +1799,7 @@ public void synchronizeProcessGroupSettings(final ProcessGroup processGroup, fin groupToUpdate.setComments(proposed.getComments()); groupToUpdate.setName(proposed.getName()); groupToUpdate.setPosition(new Position(proposed.getPosition().getX(), proposed.getPosition().getY())); + groupToUpdate.setLogFileSuffix(proposed.getLogFileSuffix()); if (processGroup == null) { LOG.info("Successfully synchronized {} by adding it to the flow", groupToUpdate); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java index 634d4c7c68fb..102b0832564a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java @@ -214,6 +214,8 @@ public final class StandardProcessGroup implements ProcessGroup { private static final String DEFAULT_FLOWFILE_EXPIRATION = "0 sec"; private static final long DEFAULT_BACKPRESSURE_OBJECT = 10_000L; private static final String DEFAULT_BACKPRESSURE_DATA_SIZE = "1 GB"; + private static final Pattern INVALID_DIRECTORY_NAME_CHARACTERS = Pattern.compile("[\\s\\<\\>:\\'\\\"\\/\\\\\\|\\?\\*]"); + private volatile String logFileSuffix; public StandardProcessGroup(final String id, final ControllerServiceProvider serviceProvider, final ProcessScheduler scheduler, @@ -244,6 +246,7 @@ public StandardProcessGroup(final String id, final ControllerServiceProvider ser this.defaultFlowFileExpiration = new AtomicReference<>(); this.defaultBackPressureObjectThreshold = new AtomicReference<>(); this.defaultBackPressureDataSizeThreshold = new AtomicReference<>(); + this.logFileSuffix = null; // save only the nifi properties needed, and account for the possibility those properties are missing if (nifiProperties == null) { @@ -4422,6 +4425,20 @@ public QueueSize getQueueSize() { return new QueueSize(count, contentSize); } + @Override + public String getLogFileSuffix() { + return logFileSuffix; + } + + @Override + public void setLogFileSuffix(final String logFileSuffix) { + if (logFileSuffix != null && INVALID_DIRECTORY_NAME_CHARACTERS.matcher(logFileSuffix).find()) { + throw new IllegalArgumentException("Log file suffix can not contain the following characters: space, <, >, :, \', \", /, \\, |, ?, *"); + } else { + this.logFileSuffix = logFileSuffix; + } + } + @Override public String getDefaultBackPressureDataSizeThreshold() { // Use value in this object if it has been set. Otherwise, inherit from parent group; if at root group, obtain from nifi properties. diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/logging/LoggingContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/logging/LoggingContext.java new file mode 100644 index 000000000000..1a43174d20bd --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/logging/LoggingContext.java @@ -0,0 +1,31 @@ +/* + * 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.nifi.logging; + +import java.util.Optional; + +public interface LoggingContext { + /** + * @return the log file name suffix. This will be the discriminating value for the dedicated logging. + */ + Optional getLogFileSuffix(); + + /** + * @return The key under which the discriminating value should be exported into the host environment. + */ + String getDiscriminatorKey(); +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/logging/StandardLoggingContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/logging/StandardLoggingContext.java new file mode 100644 index 000000000000..41cd57884c1d --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/logging/StandardLoggingContext.java @@ -0,0 +1,62 @@ +/* + * 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.nifi.logging; + +import org.apache.nifi.groups.ProcessGroup; + +import java.util.Optional; + + + +public class StandardLoggingContext implements LoggingContext { + private static final String KEY = "logFileSuffix"; + private volatile GroupedComponent component; + + public StandardLoggingContext(final GroupedComponent component) { + this.component = component; + } + + @Override + public Optional getLogFileSuffix() { + if (component != null) { + return getSuffix(component.getProcessGroup()); + } else { + return Optional.empty(); + } + } + + @Override + public String getDiscriminatorKey() { + return KEY; + } + + private Optional getSuffix(final ProcessGroup group) { + if (group == null) { + return Optional.empty(); + } else if (group.getLogFileSuffix() != null && !group.getLogFileSuffix().isEmpty()) { + return Optional.of(group.getLogFileSuffix()); + } else if (group.isRootGroup()) { + return Optional.empty(); + } else { + return getSuffix(group.getParent()); + } + } + + public void setComponent(final GroupedComponent component) { + this.component = component; + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/processor/SimpleProcessLogger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/processor/SimpleProcessLogger.java index c7d8e8eab58c..9f3d7b547fd5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/processor/SimpleProcessLogger.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/processor/SimpleProcessLogger.java @@ -22,8 +22,10 @@ import org.apache.nifi.logging.LogMessage; import org.apache.nifi.logging.LogRepository; import org.apache.nifi.logging.LogRepositoryFactory; +import org.apache.nifi.logging.LoggingContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.event.Level; import java.util.ArrayList; import java.util.List; @@ -38,14 +40,17 @@ public class SimpleProcessLogger implements ComponentLog { private final LogRepository logRepository; private final Object component; - public SimpleProcessLogger(final String componentId, final Object component) { - this(component, LogRepositoryFactory.getRepository(componentId)); + private final LoggingContext loggingContext; + + public SimpleProcessLogger(final String componentId, final Object component, final LoggingContext loggingContext) { + this(component, LogRepositoryFactory.getRepository(componentId), loggingContext); } - public SimpleProcessLogger(final Object component, final LogRepository logRepository) { + public SimpleProcessLogger(final Object component, final LogRepository logRepository, final LoggingContext loggingContext) { this.logger = LoggerFactory.getLogger(component.getClass()); this.logRepository = logRepository; this.component = component; + this.loggingContext = loggingContext; } @Override @@ -55,10 +60,10 @@ public void warn(final String msg, final Throwable t) { final Object[] repositoryArguments = getRepositoryArguments(t); if (t == null) { - logger.warn(componentMessage, component); + log(Level.WARN, componentMessage, component); logRepository.addLogMessage(LogLevel.WARN, componentMessage, repositoryArguments); } else { - logger.warn(componentMessage, component, t); + log(Level.WARN, componentMessage, component, t); logRepository.addLogMessage(LogLevel.WARN, getCausesMessage(msg), repositoryArguments, t); } } @@ -72,10 +77,10 @@ public void warn(final String msg, final Object[] os) { final Throwable lastThrowable = findLastThrowable(os); if (lastThrowable == null) { - logger.warn(componentMessage, arguments); + log(Level.WARN, componentMessage, arguments); logRepository.addLogMessage(LogLevel.WARN, componentMessage, arguments); } else { - logger.warn(componentMessage, setFormattedThrowable(arguments, lastThrowable)); + log(Level.WARN, componentMessage, setFormattedThrowable(arguments, lastThrowable)); logRepository.addLogMessage(LogLevel.WARN, getCausesMessage(msg), setCauses(arguments, lastThrowable), lastThrowable); } } @@ -88,10 +93,10 @@ public void warn(final String msg, final Object[] os, final Throwable t) { final Object[] arguments = insertComponent(os); if (t == null) { - logger.warn(componentMessage, arguments); + log(Level.WARN, componentMessage, arguments); logRepository.addLogMessage(LogLevel.WARN, componentMessage, arguments); } else { - logger.warn(componentMessage, addThrowable(arguments, t)); + log(Level.WARN, componentMessage, addThrowable(arguments, t)); logRepository.addLogMessage(LogLevel.WARN, getCausesMessage(msg), addCauses(arguments, t), t); } } @@ -117,10 +122,10 @@ public void trace(final String msg, final Throwable t) { final Object[] repositoryArguments = getRepositoryArguments(t); if (t == null) { - logger.trace(componentMessage, component); + log(Level.TRACE, componentMessage, component); logRepository.addLogMessage(LogLevel.TRACE, componentMessage, repositoryArguments); } else { - logger.trace(componentMessage, component, t); + log(Level.TRACE, componentMessage, component, t); logRepository.addLogMessage(LogLevel.TRACE, getCausesMessage(msg), repositoryArguments, t); } } @@ -134,10 +139,10 @@ public void trace(final String msg, final Object[] os) { final Throwable lastThrowable = findLastThrowable(os); if (lastThrowable == null) { - logger.trace(componentMessage, arguments); + log(Level.TRACE, componentMessage, arguments); logRepository.addLogMessage(LogLevel.TRACE, componentMessage, arguments); } else { - logger.trace(componentMessage, setFormattedThrowable(arguments, lastThrowable)); + log(Level.TRACE, componentMessage, setFormattedThrowable(arguments, lastThrowable)); logRepository.addLogMessage(LogLevel.TRACE, getCausesMessage(msg), setCauses(arguments, lastThrowable), lastThrowable); } } @@ -155,10 +160,10 @@ public void trace(final String msg, final Object[] os, final Throwable t) { final Object[] arguments = insertComponent(os); if (t == null) { - logger.trace(componentMessage, arguments); + log(Level.TRACE, componentMessage, arguments); logRepository.addLogMessage(LogLevel.TRACE, componentMessage, arguments); } else { - logger.trace(componentMessage, addThrowable(arguments, t)); + log(Level.TRACE, componentMessage, addThrowable(arguments, t)); logRepository.addLogMessage(LogLevel.TRACE, getCausesMessage(msg), addCauses(arguments, t), t); } } @@ -204,10 +209,10 @@ public void info(final String msg, final Throwable t) { final Object[] repositoryArguments = getRepositoryArguments(t); if (t == null) { - logger.info(componentMessage, component); + log(Level.INFO, componentMessage, component); logRepository.addLogMessage(LogLevel.INFO, componentMessage, repositoryArguments); } else { - logger.info(componentMessage, component, t); + log(Level.INFO, componentMessage, component, t); logRepository.addLogMessage(LogLevel.INFO, getCausesMessage(msg), repositoryArguments, t); } } @@ -221,10 +226,10 @@ public void info(final String msg, final Object[] os) { final Throwable lastThrowable = findLastThrowable(os); if (lastThrowable == null) { - logger.info(componentMessage, arguments); + log(Level.INFO, componentMessage, arguments); logRepository.addLogMessage(LogLevel.INFO, componentMessage, arguments); } else { - logger.info(componentMessage, setFormattedThrowable(arguments, lastThrowable)); + log(Level.INFO, componentMessage, setFormattedThrowable(arguments, lastThrowable)); logRepository.addLogMessage(LogLevel.INFO, getCausesMessage(msg), setCauses(arguments, lastThrowable), lastThrowable); } } @@ -242,10 +247,10 @@ public void info(final String msg, final Object[] os, final Throwable t) { final Object[] arguments = insertComponent(os); if (t == null) { - logger.info(componentMessage, arguments); + log(Level.INFO, componentMessage, arguments); logRepository.addLogMessage(LogLevel.INFO, componentMessage, arguments); } else { - logger.info(componentMessage, addThrowable(arguments, t)); + log(Level.INFO, componentMessage, addThrowable(arguments, t)); logRepository.addLogMessage(LogLevel.INFO, getCausesMessage(msg), addCauses(arguments, t), t); } } @@ -276,10 +281,10 @@ public void error(final String msg, final Throwable t) { final Object[] repositoryArguments = getRepositoryArguments(t); if (t == null) { - logger.error(componentMessage, component); + log(Level.ERROR, componentMessage, component); logRepository.addLogMessage(LogLevel.ERROR, componentMessage, repositoryArguments); } else { - logger.error(componentMessage, component, t); + log(Level.ERROR, componentMessage, component, t); logRepository.addLogMessage(LogLevel.ERROR, getCausesMessage(msg), repositoryArguments, t); } } @@ -293,10 +298,10 @@ public void error(final String msg, final Object[] os) { final Throwable lastThrowable = findLastThrowable(os); if (lastThrowable == null) { - logger.error(componentMessage, arguments); + log(Level.ERROR, componentMessage, arguments); logRepository.addLogMessage(LogLevel.ERROR, componentMessage, arguments); } else { - logger.error(componentMessage, setFormattedThrowable(arguments, lastThrowable)); + log(Level.ERROR, componentMessage, setFormattedThrowable(arguments, lastThrowable)); logRepository.addLogMessage(LogLevel.ERROR, getCausesMessage(msg), setCauses(arguments, lastThrowable), lastThrowable); } } @@ -309,10 +314,10 @@ public void error(final String msg, final Object[] os, final Throwable t) { final Object[] arguments = insertComponent(os); if (t == null) { - logger.error(componentMessage, arguments); + log(Level.ERROR, componentMessage, arguments); logRepository.addLogMessage(LogLevel.ERROR, componentMessage, arguments); } else { - logger.error(componentMessage, addThrowable(arguments, t)); + log(Level.ERROR, componentMessage, addThrowable(arguments, t)); logRepository.addLogMessage(LogLevel.ERROR, getCausesMessage(msg), addCauses(arguments, t), t); } } @@ -333,10 +338,10 @@ public void debug(final String msg, final Throwable t) { final Object[] repositoryArguments = getRepositoryArguments(t); if (t == null) { - logger.debug(componentMessage, component); + log(Level.DEBUG, componentMessage, component); logRepository.addLogMessage(LogLevel.DEBUG, componentMessage, repositoryArguments); } else { - logger.debug(componentMessage, component, t); + log(Level.DEBUG, componentMessage, component, t); logRepository.addLogMessage(LogLevel.DEBUG, getCausesMessage(msg), repositoryArguments, t); } } @@ -350,10 +355,10 @@ public void debug(final String msg, final Object[] os) { final Throwable lastThrowable = findLastThrowable(os); if (lastThrowable == null) { - logger.debug(componentMessage, arguments); + log(Level.DEBUG, componentMessage, arguments); logRepository.addLogMessage(LogLevel.DEBUG, componentMessage, arguments); } else { - logger.debug(componentMessage, setFormattedThrowable(arguments, lastThrowable)); + log(Level.DEBUG, componentMessage, setFormattedThrowable(arguments, lastThrowable)); logRepository.addLogMessage(LogLevel.DEBUG, getCausesMessage(msg), setCauses(arguments, lastThrowable), lastThrowable); } } @@ -366,10 +371,10 @@ public void debug(final String msg, final Object[] os, final Throwable t) { final Object[] arguments = insertComponent(os); if (t == null) { - logger.debug(componentMessage, arguments); + log(Level.DEBUG, componentMessage, arguments); logRepository.addLogMessage(LogLevel.DEBUG, componentMessage, arguments); } else { - logger.debug(componentMessage, addThrowable(arguments, t)); + log(Level.DEBUG, componentMessage, addThrowable(arguments, t)); logRepository.addLogMessage(LogLevel.DEBUG, getCausesMessage(msg), addCauses(arguments, t), t); } } @@ -563,4 +568,18 @@ private Throwable findLastThrowable(final Object[] arguments) { } return lastThrowable; } + + private String getDiscriminatorKey() { + return loggingContext.getDiscriminatorKey(); + } + + private String getLogFileSuffix() { + return loggingContext.getLogFileSuffix().orElse(null); + } + + private void log(final Level level, final String message, final Object... arguments) { + logger.makeLoggingEventBuilder(level) + .addKeyValue(getDiscriminatorKey(), getLogFileSuffix()) + .log(message, arguments); + } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/StandardFlowRegistryClientNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/StandardFlowRegistryClientNode.java index 9c27972b3aa0..c5a8f9164902 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/StandardFlowRegistryClientNode.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/StandardFlowRegistryClientNode.java @@ -327,6 +327,7 @@ private void populateVersionedContentsRecursively(final FlowRegistryClientUserCo group.setDefaultFlowFileExpiration(contents.getDefaultFlowFileExpiration()); group.setDefaultBackPressureObjectThreshold(contents.getDefaultBackPressureObjectThreshold()); group.setDefaultBackPressureDataSizeThreshold(contents.getDefaultBackPressureDataSizeThreshold()); + group.setLogFileSuffix(contents.getLogFileSuffix()); coordinates.setLatest(snapshot.isLatest()); snapshotContainer.addChildSnapshot(snapshot, group); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapper.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapper.java index d6e7c19f21b9..92205ee79523 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapper.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapper.java @@ -258,6 +258,7 @@ private InstantiatedVersionedProcessGroup mapGroup(final ProcessGroup group, fin versionedGroup.setDefaultFlowFileExpiration(group.getDefaultFlowFileExpiration()); versionedGroup.setDefaultBackPressureObjectThreshold(group.getDefaultBackPressureObjectThreshold()); versionedGroup.setDefaultBackPressureDataSizeThreshold(group.getDefaultBackPressureDataSizeThreshold()); + versionedGroup.setLogFileSuffix(group.getLogFileSuffix()); final ParameterContext parameterContext = group.getParameterContext(); versionedGroup.setParameterContextName(parameterContext == null ? null : parameterContext.getName()); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/util/FlowDifferenceFilters.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/util/FlowDifferenceFilters.java index ad2fa76122e6..ec710b10d263 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/util/FlowDifferenceFilters.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/util/FlowDifferenceFilters.java @@ -74,7 +74,8 @@ public static boolean isEnvironmentalChange(final FlowDifference difference, fin || isNewZIndexLabelConfigWithDefaultValue(difference, flowManager) || isNewZIndexConnectionConfigWithDefaultValue(difference, flowManager) || isRegistryUrlChange(difference) - || isParameterContextChange(difference); + || isParameterContextChange(difference) + || isLogFileSuffixChange(difference); } private static boolean isSensitivePropertyDueToGhosting(final FlowDifference difference, final FlowManager flowManager) { @@ -529,4 +530,8 @@ private static boolean hasConnection(final VersionedProcessGroup processGroup, f private static boolean isParameterContextChange(final FlowDifference flowDifference) { return flowDifference.getDifferenceType() == DifferenceType.PARAMETER_CONTEXT_CHANGED; } + + private static boolean isLogFileSuffixChange(final FlowDifference flowDifference) { + return flowDifference.getDifferenceType() == DifferenceType.LOG_FILE_SUFFIX_CHANGED; + } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/logging/TestStandardLoggingContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/logging/TestStandardLoggingContext.java new file mode 100644 index 000000000000..a6ff4a4dd30f --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/logging/TestStandardLoggingContext.java @@ -0,0 +1,77 @@ +/* + * 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.nifi.logging; + +import org.apache.nifi.groups.ProcessGroup; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class TestStandardLoggingContext { + private static final String LOG_FILE_SUFFIX = "myGroup"; + + @Mock + private GroupedComponent processor; + + @Mock + private ProcessGroup processGroup; + + @Test + void testNullComponent_ShouldReturnOptionalEmpty() { + LoggingContext context = new StandardLoggingContext(null); + + assertTrue(context.getLogFileSuffix().isEmpty()); + } + + @Test + void testComponentWithProcessGroups_WithoutPerProcessGroupLogging_ShouldReturnOptionalEmpty() { + //component with pg with no setting returns optional empty + LoggingContext context = new StandardLoggingContext(processor); + when(processor.getProcessGroup()).thenReturn(processGroup); + when(processGroup.getLogFileSuffix()).thenReturn(null, null); + when(processGroup.isRootGroup()).thenReturn(Boolean.FALSE, Boolean.TRUE); + when(processGroup.getParent()).thenReturn(processGroup); + + assertTrue(context.getLogFileSuffix().isEmpty()); + } + + @Test + void testComponentWithProcessGroup_WithPerProcessGroupLogging_ShouldReturnLogFileSuffix() { + LoggingContext context = new StandardLoggingContext(processor); + when(processor.getProcessGroup()).thenReturn(processGroup); + when(processGroup.getLogFileSuffix()).thenReturn(LOG_FILE_SUFFIX); + + assertEquals(LOG_FILE_SUFFIX, context.getLogFileSuffix().orElse(null)); + } + + @Test + void testComponentWithProcessGroups_WithPerProcessGroupLoggingSetOnParent_ShouldReturnLogFileSuffix() { + LoggingContext context = new StandardLoggingContext(processor); + when(processor.getProcessGroup()).thenReturn(processGroup); + when(processGroup.isRootGroup()).thenReturn(Boolean.FALSE); + when(processGroup.getParent()).thenReturn(processGroup); + when(processGroup.getLogFileSuffix()).thenReturn(null, LOG_FILE_SUFFIX); + + assertEquals(LOG_FILE_SUFFIX, context.getLogFileSuffix().orElse(null)); + } +} \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/processor/TestSimpleProcessLogger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/processor/TestSimpleProcessLogger.java index 5e5d33fd1370..6ac558ca1fd9 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/processor/TestSimpleProcessLogger.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/processor/TestSimpleProcessLogger.java @@ -20,14 +20,25 @@ import org.apache.nifi.components.ConfigurableComponent; import org.apache.nifi.logging.LogLevel; import org.apache.nifi.logging.LogRepository; +import org.apache.nifi.logging.StandardLoggingContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Answers; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.slf4j.Logger; +import org.slf4j.event.Level; +import org.slf4j.spi.LoggingEventBuilder; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -70,15 +81,25 @@ public class TestSimpleProcessLogger { private static final String LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT_AND_CAUSES = String.format("{} %s: {}", LOG_ARGUMENTS_MESSAGE); + private static final String DISCRIMINATOR_KEY = "logFileSuffix"; + + private static final String LOG_FILE_SUFFIX = "myGroup"; + @Mock private ConfigurableComponent component; @Mock private LogRepository logRepository; - @Mock + @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Logger logger; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + LoggingEventBuilder loggingEventBuilder; + + @Mock + StandardLoggingContext loggingContext; + private Object[] componentArguments; private Object[] componentValueArguments; @@ -89,9 +110,11 @@ public class TestSimpleProcessLogger { private SimpleProcessLogger componentLog; + private final ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Object[].class); + @BeforeEach public void setLogger() throws IllegalAccessException { - componentLog = new SimpleProcessLogger(component, logRepository); + componentLog = new SimpleProcessLogger(component, logRepository, loggingContext); FieldUtils.writeDeclaredField(componentLog, "logger", logger, true); componentArguments = new Object[]{component}; @@ -104,6 +127,10 @@ public void setLogger() throws IllegalAccessException { when(logger.isInfoEnabled()).thenReturn(true); when(logger.isWarnEnabled()).thenReturn(true); when(logger.isErrorEnabled()).thenReturn(true); + when(logger.makeLoggingEventBuilder(any(Level.class))).thenReturn(loggingEventBuilder); + when(loggingContext.getDiscriminatorKey()).thenReturn(DISCRIMINATOR_KEY); + when(loggingContext.getLogFileSuffix()).thenReturn(Optional.of(LOG_FILE_SUFFIX)); + when(loggingEventBuilder.addKeyValue(any(String.class), any(String.class))).thenReturn(loggingEventBuilder); } @Test @@ -113,19 +140,69 @@ public void testLogLevelMessage() { switch (logLevel) { case TRACE: - verify(logger).trace(eq(LOG_MESSAGE_WITH_COMPONENT), eq(component)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.TRACE)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(1, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + + reset(loggingEventBuilder); break; case DEBUG: - verify(logger).debug(eq(LOG_MESSAGE_WITH_COMPONENT), eq(component)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.DEBUG)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(1, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + + reset(loggingEventBuilder); break; case INFO: - verify(logger).info(eq(LOG_MESSAGE_WITH_COMPONENT), eq(component)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.INFO)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(1, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + + reset(loggingEventBuilder); break; case WARN: - verify(logger).warn(eq(LOG_MESSAGE_WITH_COMPONENT), eq(component)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.WARN)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(1, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + + reset(loggingEventBuilder); break; case ERROR: - verify(logger).error(eq(LOG_MESSAGE_WITH_COMPONENT), eq(component)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.ERROR)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(1, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + + reset(loggingEventBuilder); break; default: continue; @@ -142,19 +219,79 @@ public void testLogLevelMessageArguments() { switch (logLevel) { case TRACE: - verify(logger).trace(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.TRACE)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(3, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + + reset(loggingEventBuilder); break; case DEBUG: - verify(logger).debug(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.DEBUG)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(3, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + + reset(loggingEventBuilder); break; case INFO: - verify(logger).info(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.INFO)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(3, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + + reset(loggingEventBuilder); break; case WARN: - verify(logger).warn(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.WARN)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(3, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + + reset(loggingEventBuilder); break; case ERROR: - verify(logger).error(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.ERROR)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(3, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + + reset(loggingEventBuilder); break; default: continue; @@ -171,19 +308,74 @@ public void testLogLevelMessageThrowable() { switch (logLevel) { case TRACE: - verify(logger).trace(eq(LOG_MESSAGE_WITH_COMPONENT), eq(component), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.TRACE)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(2, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[1]); + + reset(loggingEventBuilder); break; case DEBUG: - verify(logger).debug(eq(LOG_MESSAGE_WITH_COMPONENT), eq(component), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.DEBUG)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(2, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[1]); + + reset(loggingEventBuilder); break; case INFO: - verify(logger).info(eq(LOG_MESSAGE_WITH_COMPONENT), eq(component), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.INFO)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(2, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[1]); + + reset(loggingEventBuilder); break; case WARN: - verify(logger).warn(eq(LOG_MESSAGE_WITH_COMPONENT), eq(component), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.WARN)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(2, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[1]); + + reset(loggingEventBuilder); break; case ERROR: - verify(logger).error(eq(LOG_MESSAGE_WITH_COMPONENT), eq(component), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.ERROR)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(2, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[1]); + + reset(loggingEventBuilder); break; default: continue; @@ -200,19 +392,89 @@ public void testLogLevelMessageArgumentsThrowable() { switch (logLevel) { case TRACE: - verify(logger).trace(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND), eq(EXCEPTION_STRING), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.TRACE)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(5, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + assertEquals(EXCEPTION_STRING, argumentCaptor.getValue()[3]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[4]); + + reset(loggingEventBuilder); break; case DEBUG: - verify(logger).debug(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND), eq(EXCEPTION_STRING), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.DEBUG)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(5, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + assertEquals(EXCEPTION_STRING, argumentCaptor.getValue()[3]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[4]); + + reset(loggingEventBuilder); break; case INFO: - verify(logger).info(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND), eq(EXCEPTION_STRING), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.INFO)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(5, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + assertEquals(EXCEPTION_STRING, argumentCaptor.getValue()[3]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[4]); + + reset(loggingEventBuilder); break; case WARN: - verify(logger).warn(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND), eq(EXCEPTION_STRING), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.WARN)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(5, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + assertEquals(EXCEPTION_STRING, argumentCaptor.getValue()[3]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[4]); + + reset(loggingEventBuilder); break; case ERROR: - verify(logger).error(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND), eq(EXCEPTION_STRING), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.ERROR)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(5, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + assertEquals(EXCEPTION_STRING, argumentCaptor.getValue()[3]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[4]); + + reset(loggingEventBuilder); break; default: continue; @@ -229,19 +491,84 @@ public void testLogLevelMessageArgumentsArrayThrowable() { switch (logLevel) { case TRACE: - verify(logger).trace(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.TRACE)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(4, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[3]); + + reset(loggingEventBuilder); break; case DEBUG: - verify(logger).debug(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.DEBUG)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(4, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[3]); + + reset(loggingEventBuilder); break; case INFO: - verify(logger).info(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.INFO)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(4, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[3]); + + reset(loggingEventBuilder); break; case WARN: - verify(logger).warn(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.WARN)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(4, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[3]); + + reset(loggingEventBuilder); break; case ERROR: - verify(logger).error(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND), eq(EXCEPTION)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.ERROR)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + + assertEquals(4, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + assertEquals(EXCEPTION, argumentCaptor.getValue()[3]); + + reset(loggingEventBuilder); break; default: continue; @@ -258,19 +585,69 @@ public void testLogLevelMessageArgumentsThrowableNull() { switch (logLevel) { case TRACE: - verify(logger).trace(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.TRACE)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + assertEquals(3, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + reset(loggingEventBuilder); break; case DEBUG: - verify(logger).debug(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.DEBUG)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + assertEquals(3, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + reset(loggingEventBuilder); break; case INFO: - verify(logger).info(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.INFO)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + assertEquals(3, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + reset(loggingEventBuilder); break; case WARN: - verify(logger).warn(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.WARN)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + assertEquals(3, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + reset(loggingEventBuilder); break; case ERROR: - verify(logger).error(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), eq(component), eq(FIRST), eq(SECOND)); + verify(logger, times(1)).makeLoggingEventBuilder(eq(Level.ERROR)); + verify(loggingEventBuilder, times(1)) + .addKeyValue(eq(DISCRIMINATOR_KEY), eq(LOG_FILE_SUFFIX)); + verify(loggingEventBuilder + .addKeyValue(DISCRIMINATOR_KEY, LOG_FILE_SUFFIX), times(1)) + .log(eq(LOG_ARGUMENTS_MESSAGE_WITH_COMPONENT), argumentCaptor.capture()); + assertEquals(3, argumentCaptor.getValue().length); + assertEquals(component, argumentCaptor.getValue()[0]); + assertEquals(FIRST, argumentCaptor.getValue()[1]); + assertEquals(SECOND, argumentCaptor.getValue()[2]); + reset(loggingEventBuilder); break; default: continue; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connectable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connectable.java index cc006217c774..4ee4fa4f1b0e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connectable.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connectable.java @@ -22,6 +22,7 @@ import org.apache.nifi.controller.BackoffMechanism; import org.apache.nifi.controller.Triggerable; import org.apache.nifi.groups.ProcessGroup; +import org.apache.nifi.logging.GroupedComponent; import org.apache.nifi.processor.ProcessSession; import org.apache.nifi.processor.Relationship; import org.apache.nifi.scheduling.SchedulingStrategy; @@ -34,7 +35,7 @@ /** * Represents a connectable component to which or from which data can flow. */ -public interface Connectable extends Triggerable, ComponentAuthorizable, Positionable, VersionedComponent { +public interface Connectable extends Triggerable, ComponentAuthorizable, Positionable, VersionedComponent, GroupedComponent { /** * @return the unique identifier for this Connectable diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceNode.java index 7a53506fb44e..42a134eeb4c9 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceNode.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/service/ControllerServiceNode.java @@ -27,6 +27,7 @@ import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.logging.ComponentLog; import org.apache.nifi.logging.LogLevel; +import org.apache.nifi.logging.GroupedComponent; import org.apache.nifi.nar.ExtensionManager; import java.util.List; @@ -36,7 +37,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -public interface ControllerServiceNode extends ComponentNode, VersionedComponent { +public interface ControllerServiceNode extends ComponentNode, VersionedComponent, GroupedComponent { /** * @return the Process Group that this Controller Service belongs to, or null if the Controller Service diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java index c6e0e2a53b1d..e48f08ea2afc 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java @@ -1233,4 +1233,16 @@ public interface ProcessGroup extends ComponentAuthorizable, Positionable, Versi * @return the QueueSize of this Process Group and all child Process Groups */ QueueSize getQueueSize(); + + /** + * @return the log file suffix of the ProcessGroup for dedicated logging + */ + String getLogFileSuffix(); + + /** + * Updates the log file suffix of this ProcessGroup for dedicated logging + * + * @param logFileSuffix new log file suffix + */ + void setLogFileSuffix(String logFileSuffix); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/logging/GroupedComponent.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/logging/GroupedComponent.java new file mode 100644 index 000000000000..342165c16829 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/logging/GroupedComponent.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.nifi.logging; + +import org.apache.nifi.groups.ProcessGroup; + +public interface GroupedComponent { + ProcessGroup getProcessGroup(); +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/ExtensionBuilder.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/ExtensionBuilder.java index ac15484fb96f..e4ad7d49b9ac 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/ExtensionBuilder.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/ExtensionBuilder.java @@ -44,6 +44,8 @@ import org.apache.nifi.controller.service.StandardControllerServiceInvocationHandler; import org.apache.nifi.controller.service.StandardControllerServiceNode; import org.apache.nifi.logging.ComponentLog; +import org.apache.nifi.logging.LoggingContext; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.nar.ExtensionManager; import org.apache.nifi.nar.NarCloseable; import org.apache.nifi.nar.PythonBundle; @@ -228,9 +230,10 @@ public ProcessorNode buildProcessor() { } boolean creationSuccessful = true; + final StandardLoggingContext loggingContext = new StandardLoggingContext(null); LoggableComponent loggableComponent; try { - loggableComponent = createLoggableProcessor(); + loggableComponent = createLoggableProcessor(loggingContext); } catch (final ProcessorInstantiationException pie) { logger.error("Could not create Processor of type {} for ID {} due to: {}; creating \"Ghost\" implementation", type, identifier, pie.getMessage(), pie); @@ -252,6 +255,7 @@ public ProcessorNode buildProcessor() { } final ProcessorNode processorNode = createProcessorNode(loggableComponent, componentType, !creationSuccessful); + loggingContext.setComponent(processorNode); return processorNode; } @@ -419,9 +423,9 @@ public ControllerServiceNode buildControllerService() { if (stateManagerProvider == null) { throw new IllegalStateException("State Manager Provider must be specified"); } - + final StandardLoggingContext loggingContext = new StandardLoggingContext(null); try { - return createControllerServiceNode(); + return createControllerServiceNode(loggingContext); } catch (final Exception e) { logger.error("Could not create Controller Service of type " + type + " for ID " + identifier + " due to: " + e.getMessage() + "; creating \"Ghost\" implementation"); if (logger.isDebugEnabled()) { @@ -561,7 +565,8 @@ private void applyDefaultRunDuration(final ProcessorNode processorNode) { } } - private ControllerServiceNode createControllerServiceNode() throws ClassNotFoundException, IllegalAccessException, InstantiationException, InitializationException { + private ControllerServiceNode createControllerServiceNode(final StandardLoggingContext loggingContext) + throws ClassNotFoundException, IllegalAccessException, InstantiationException, InitializationException { final ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader(); try { final Bundle bundle = extensionManager.getBundle(bundleCoordinate); @@ -590,7 +595,7 @@ private ControllerServiceNode createControllerServiceNode() throws ClassNotFound } logger.info("Created Controller Service of type {} with identifier {}", type, identifier); - final ComponentLog serviceLogger = new SimpleProcessLogger(identifier, serviceImpl); + final ComponentLog serviceLogger = new SimpleProcessLogger(identifier, serviceImpl, new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(serviceLogger); final StateManager stateManager = stateManagerProvider.getStateManager(identifier); @@ -608,6 +613,7 @@ private ControllerServiceNode createControllerServiceNode() throws ClassNotFound final ControllerServiceNode serviceNode = new StandardControllerServiceNode(originalLoggableComponent, proxiedLoggableComponent, invocationHandler, identifier, validationContextFactory, serviceProvider, componentVarRegistry, reloadComponent, extensionManager, validationTrigger); serviceNode.setName(rawClass.getSimpleName()); + loggingContext.setComponent(serviceNode); invocationHandler.setServiceNode(serviceNode); return serviceNode; @@ -697,13 +703,13 @@ private ControllerServiceNode createGhostControllerServiceNode() { return serviceNode; } - private LoggableComponent createLoggableProcessor() throws ProcessorInstantiationException { + private LoggableComponent createLoggableProcessor(final LoggingContext loggingContext) throws ProcessorInstantiationException { try { final LoggableComponent processorComponent; if (PythonBundle.isPythonCoordinate(bundleCoordinate)) { processorComponent = createLoggablePythonProcessor(); } else { - processorComponent = createLoggableComponent(Processor.class); + processorComponent = createLoggableComponent(Processor.class, loggingContext); } final Processor processor = processorComponent.getComponent(); @@ -724,7 +730,7 @@ private LoggableComponent createLoggableProcessor() throws ProcessorI private LoggableComponent createLoggableReportingTask() throws ReportingTaskInstantiationException { try { - final LoggableComponent taskComponent = createLoggableComponent(ReportingTask.class); + final LoggableComponent taskComponent = createLoggableComponent(ReportingTask.class, new StandardLoggingContext(null)); final String taskName = taskComponent.getComponent().getClass().getSimpleName(); final ReportingInitializationContext config = new StandardReportingInitializationContext(identifier, taskName, @@ -743,7 +749,7 @@ private LoggableComponent createLoggableReportingTask() throws Re private LoggableComponent createLoggableFlowRegistryClient() throws FlowRepositoryClientInstantiationException { try { - final LoggableComponent clientComponent = createLoggableComponent(FlowRegistryClient.class); + final LoggableComponent clientComponent = createLoggableComponent(FlowRegistryClient.class, new StandardLoggingContext(null)); final FlowRegistryClientInitializationContext context = new StandardFlowRegistryClientInitializationContext( identifier, clientComponent.getLogger(), systemSslContext); @@ -759,7 +765,7 @@ private LoggableComponent createLoggableFlowRegistryClient() private LoggableComponent createLoggableParameterProvider() throws ParameterProviderInstantiationException { try { - final LoggableComponent providerComponent = createLoggableComponent(ParameterProvider.class); + final LoggableComponent providerComponent = createLoggableComponent(ParameterProvider.class, new StandardLoggingContext(null)); final String taskName = providerComponent.getComponent().getClass().getSimpleName(); final ParameterProviderInitializationContext config = new StandardParameterProviderInitializationContext(identifier, taskName, @@ -793,7 +799,7 @@ private LoggableComponent createLoggablePythonProcessor() { final PythonProcessorBridge processorBridge = pythonBridge.createProcessor(identifier, processorType, bundleCoordinate.getVersion(), true); final Processor processor = processorBridge.getProcessorProxy(); - final ComponentLog componentLog = new SimpleProcessLogger(identifier, processor); + final ComponentLog componentLog = new SimpleProcessLogger(identifier, processor, new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLog); final PythonProcessorInitializationContext initContext = new PythonProcessorInitializationContext() { @@ -817,7 +823,8 @@ public ComponentLog getLogger() { } } - private LoggableComponent createLoggableComponent(Class nodeType) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + private LoggableComponent createLoggableComponent(Class nodeType, LoggingContext loggingContext) + throws ClassNotFoundException, IllegalAccessException, InstantiationException { final ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader(); try { final Bundle bundle = extensionManager.getBundle(bundleCoordinate); @@ -832,7 +839,7 @@ private LoggableComponent createLoggableCom final Object extensionInstance = rawClass.newInstance(); - final ComponentLog componentLog = new SimpleProcessLogger(identifier, extensionInstance); + final ComponentLog componentLog = new SimpleProcessLogger(identifier, extensionInstance, loggingContext); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLog); final T cast = nodeType.cast(extensionInstance); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSnippet.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSnippet.java index c1ee7ceb0b47..ecfbdbbb0585 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSnippet.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSnippet.java @@ -533,6 +533,11 @@ public void instantiate(final FlowManager flowManager, final FlowController flow childGroup.setDefaultBackPressureDataSizeThreshold(defaultBackPressureDataSizeThreshold); } + final String logFileSuffix = groupDTO.getLogFileSuffix(); + if (logFileSuffix != null) { + childGroup.setLogFileSuffix(logFileSuffix); + } + // If this Process Group is 'top level' then we do not set versioned component ID's. // We do this only if this component is the child of a Versioned Component. if (!topLevel) { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardReloadComponent.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardReloadComponent.java index 8455e2d9f668..212908cba0f1 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardReloadComponent.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardReloadComponent.java @@ -32,6 +32,7 @@ import org.apache.nifi.parameter.ParameterProvider; import org.apache.nifi.processor.Processor; import org.apache.nifi.processor.SimpleProcessLogger; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.processor.StandardProcessContext; import org.apache.nifi.registry.flow.FlowRegistryClient; import org.apache.nifi.registry.flow.FlowRegistryClientNode; @@ -93,7 +94,7 @@ public void reload(final ProcessorNode existingNode, final String newType, final final ProcessorNode newNode = flowController.getFlowManager().createProcessor(newType, id, bundleCoordinate, additionalUrls, true, false, classloaderIsolationKey); // set the new processor in the existing node - final ComponentLog componentLogger = new SimpleProcessLogger(id, newNode.getProcessor()); + final ComponentLog componentLogger = new SimpleProcessLogger(id, newNode.getProcessor(), new StandardLoggingContext(newNode)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLogger); LogRepositoryFactory.getRepository(id).setLogger(terminationAwareLogger); @@ -152,7 +153,7 @@ public void reload(final ControllerServiceNode existingNode, final String newTyp invocationHandler.setServiceNode(existingNode); // create LoggableComponents for the proxy and implementation - final ComponentLog componentLogger = new SimpleProcessLogger(id, newNode.getControllerServiceImplementation()); + final ComponentLog componentLogger = new SimpleProcessLogger(id, newNode.getControllerServiceImplementation(), new StandardLoggingContext(newNode)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLogger); LogRepositoryFactory.getRepository(id).setLogger(terminationAwareLogger); @@ -203,7 +204,7 @@ public void reload(final ReportingTaskNode existingNode, final String newType, f final ReportingTaskNode newNode = flowController.getFlowManager().createReportingTask(newType, id, bundleCoordinate, additionalUrls, true, false, classloaderIsolationKey); // set the new reporting task into the existing node - final ComponentLog componentLogger = new SimpleProcessLogger(id, existingNode.getReportingTask()); + final ComponentLog componentLogger = new SimpleProcessLogger(id, existingNode.getReportingTask(), new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLogger); LogRepositoryFactory.getRepository(id).setLogger(terminationAwareLogger); @@ -250,7 +251,7 @@ public void reload(final ParameterProviderNode existingNode, final String newTyp } // set the new parameter provider into the existing node - final ComponentLog componentLogger = new SimpleProcessLogger(id, existingNode.getParameterProvider()); + final ComponentLog componentLogger = new SimpleProcessLogger(id, existingNode.getParameterProvider(), new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLogger); LogRepositoryFactory.getRepository(id).setLogger(terminationAwareLogger); @@ -291,7 +292,7 @@ public void reload( extensionManager.closeURLClassLoader(id, existingInstanceClassLoader); // set the new flow registyr client into the existing node - final ComponentLog componentLogger = new SimpleProcessLogger(id, existingNode.getComponent()); + final ComponentLog componentLogger = new SimpleProcessLogger(id, existingNode.getComponent(), new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLogger); LogRepositoryFactory.getRepository(id).setLogger(terminationAwareLogger); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java index d331f9aaff37..ddb86cfafb8e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java @@ -1292,6 +1292,7 @@ private void updateProcessGroup(final ProcessGroup group, final ProcessGroupDTO final String defaultFlowFileExpiration = dto.getDefaultFlowFileExpiration(); final Long defaultBackPressureObjectThreshold = dto.getDefaultBackPressureObjectThreshold(); final String defaultBackPressureDataSizeThreshold = dto.getDefaultBackPressureDataSizeThreshold(); + final String logFileSuffix = dto.getLogFileSuffix(); if (name != null) { group.setName(name); @@ -1333,6 +1334,10 @@ private void updateProcessGroup(final ProcessGroup group, final ProcessGroupDTO if (defaultBackPressureDataSizeThreshold != null) { group.setDefaultBackPressureDataSizeThreshold(defaultBackPressureDataSizeThreshold); } + + if (logFileSuffix != null) { + group.setLogFileSuffix(logFileSuffix); + } } private ScheduledState getScheduledState(final T component, final FlowController flowController) { @@ -1468,6 +1473,8 @@ private ProcessGroup addProcessGroup(final FlowController controller, final Proc processGroup.setDefaultBackPressureObjectThreshold(processGroupDTO.getDefaultBackPressureObjectThreshold()); processGroup.setDefaultBackPressureDataSizeThreshold(processGroupDTO.getDefaultBackPressureDataSizeThreshold()); + processGroup.setLogFileSuffix(processGroupDTO.getLogFileSuffix()); + final String parameterContextId = getString(processGroupElement, "parameterContextId"); if (parameterContextId != null) { final ParameterContext parameterContext = controller.getFlowManager().getParameterContextManager().getParameterContext(parameterContextId); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/scheduling/EventDrivenSchedulingAgent.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/scheduling/EventDrivenSchedulingAgent.java index c5ca6611ef33..3e00e65cd5e8 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/scheduling/EventDrivenSchedulingAgent.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/scheduling/EventDrivenSchedulingAgent.java @@ -42,6 +42,7 @@ import org.apache.nifi.nar.NarCloseable; import org.apache.nifi.processor.ProcessSessionFactory; import org.apache.nifi.processor.SimpleProcessLogger; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.processor.StandardProcessContext; import org.apache.nifi.processor.exception.ProcessException; import org.apache.nifi.util.Connectables; @@ -363,11 +364,11 @@ private void trigger(final ProcessorNode worker, final RepositoryContext context try (final AutoCloseable ncl = NarCloseable.withComponentNarLoader(extensionManager, worker.getProcessor().getClass(), worker.getIdentifier())) { worker.onTrigger(processContext, sessionFactory); } catch (final ProcessException pe) { - final ComponentLog procLog = new SimpleProcessLogger(worker.getIdentifier(), worker.getProcessor()); + final ComponentLog procLog = new SimpleProcessLogger(worker.getIdentifier(), worker.getProcessor(), new StandardLoggingContext(worker)); procLog.error("Failed to process session due to {}", new Object[]{pe}); } catch (final Throwable t) { // Use ComponentLog to log the event so that a bulletin will be created for this processor - final ComponentLog procLog = new SimpleProcessLogger(worker.getIdentifier(), worker.getProcessor()); + final ComponentLog procLog = new SimpleProcessLogger(worker.getIdentifier(), worker.getProcessor(), new StandardLoggingContext(worker)); procLog.error("{} failed to process session due to {}", new Object[]{worker.getProcessor(), t}); procLog.warn("Processor Administratively Yielded for {} due to processing failure", new Object[]{adminYieldDuration}); logger.warn("Administratively Yielding {} due to uncaught Exception: ", worker.getProcessor()); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/scheduling/StandardProcessScheduler.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/scheduling/StandardProcessScheduler.java index c9633bf89ddf..19e7bc18541b 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/scheduling/StandardProcessScheduler.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/scheduling/StandardProcessScheduler.java @@ -43,6 +43,7 @@ import org.apache.nifi.controller.service.StandardConfigurationContext; import org.apache.nifi.engine.FlowEngine; import org.apache.nifi.logging.ComponentLog; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.nar.NarCloseable; import org.apache.nifi.processor.ProcessContext; import org.apache.nifi.processor.Processor; @@ -244,7 +245,7 @@ public void run() { } } catch (final Exception e) { final Throwable cause = e instanceof InvocationTargetException ? e.getCause() : e; - final ComponentLog componentLog = new SimpleProcessLogger(reportingTask.getIdentifier(), reportingTask); + final ComponentLog componentLog = new SimpleProcessLogger(reportingTask.getIdentifier(), reportingTask, new StandardLoggingContext(null)); componentLog.error("Failed to invoke @OnScheduled method due to {}", cause); LOG.error("Failed to invoke the On-Scheduled Lifecycle methods of {} due to {}; administratively yielding this " @@ -297,7 +298,7 @@ public void run() { ReflectionUtils.invokeMethodsWithAnnotation(OnUnscheduled.class, reportingTask, configurationContext); } catch (final Exception e) { final Throwable cause = e instanceof InvocationTargetException ? e.getCause() : e; - final ComponentLog componentLog = new SimpleProcessLogger(reportingTask.getIdentifier(), reportingTask); + final ComponentLog componentLog = new SimpleProcessLogger(reportingTask.getIdentifier(), reportingTask, new StandardLoggingContext(null)); componentLog.error("Failed to invoke @OnUnscheduled method due to {}", cause); LOG.error("Failed to invoke the @OnUnscheduled methods of {} due to {}; administratively yielding this ReportingTask and will attempt to schedule it again after {}", diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/FlowFromDOMFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/FlowFromDOMFactory.java index fcf5d29cff57..9471f7bc32cb 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/FlowFromDOMFactory.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/FlowFromDOMFactory.java @@ -296,6 +296,7 @@ public static ProcessGroupDTO getProcessGroup(final String parentId, final Eleme dto.setDefaultFlowFileExpiration(getString(element, "defaultFlowFileExpiration")); dto.setDefaultBackPressureObjectThreshold(getLong(element, "defaultBackPressureObjectThreshold")); dto.setDefaultBackPressureDataSizeThreshold(getString(element, "defaultBackPressureDataSizeThreshold")); + dto.setLogFileSuffix(getString(element, "logFileSuffix")); final Map variables = new HashMap<>(); final NodeList variableList = DomUtils.getChildNodesByTagName(element, "variable"); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/StandardFlowSerializer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/StandardFlowSerializer.java index d262e9289ab5..d758b3094dbb 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/StandardFlowSerializer.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/StandardFlowSerializer.java @@ -256,6 +256,7 @@ private void addProcessGroup(final Element parentElement, final ProcessGroup gro addTextElement(element, "defaultFlowFileExpiration", group.getDefaultFlowFileExpiration()); addTextElement(element, "defaultBackPressureObjectThreshold", group.getDefaultBackPressureObjectThreshold()); addTextElement(element, "defaultBackPressureDataSizeThreshold", group.getDefaultBackPressureDataSizeThreshold()); + addTextElement(element, "logFileSuffix", group.getLogFileSuffix()); final VersionControlInformation versionControlInfo = group.getVersionControlInformation(); if (versionControlInfo != null) { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/tasks/ConnectableTask.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/tasks/ConnectableTask.java index b9245616e765..6deb542c0e01 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/tasks/ConnectableTask.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/tasks/ConnectableTask.java @@ -40,6 +40,7 @@ import org.apache.nifi.controller.scheduling.RepositoryContextFactory; import org.apache.nifi.controller.scheduling.SchedulingAgent; import org.apache.nifi.logging.ComponentLog; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.nar.NarCloseable; import org.apache.nifi.processor.ProcessContext; import org.apache.nifi.processor.ProcessSessionFactory; @@ -286,7 +287,7 @@ public InvocationResult invoke() { } finally { try { if (batch) { - final ComponentLog procLog = new SimpleProcessLogger(connectable.getIdentifier(), connectable.getRunnableComponent()); + final ComponentLog procLog = new SimpleProcessLogger(connectable.getIdentifier(), connectable.getRunnableComponent(), new StandardLoggingContext(connectable)); try { rawSession.commitAsync(null, t -> { @@ -377,7 +378,7 @@ private boolean isMeasureExpensiveMetrics(final long invocationCount) { } private ComponentLog getComponentLog() { - return new SimpleProcessLogger(connectable.getIdentifier(), connectable.getRunnableComponent()); + return new SimpleProcessLogger(connectable.getIdentifier(), connectable.getRunnableComponent(), new StandardLoggingContext(connectable)); } private static class SampledMetrics { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/tasks/ReportingTaskWrapper.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/tasks/ReportingTaskWrapper.java index b42a47e5466c..c7882b2266fb 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/tasks/ReportingTaskWrapper.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/tasks/ReportingTaskWrapper.java @@ -23,6 +23,7 @@ import org.apache.nifi.nar.ExtensionManager; import org.apache.nifi.nar.NarCloseable; import org.apache.nifi.processor.SimpleProcessLogger; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.util.ReflectionUtils; public class ReportingTaskWrapper implements Runnable { @@ -45,7 +46,7 @@ public synchronized void run() { try (final NarCloseable narCloseable = NarCloseable.withComponentNarLoader(extensionManager, taskNode.getReportingTask().getClass(), taskNode.getIdentifier())) { taskNode.getReportingTask().onTrigger(taskNode.getReportingContext()); } catch (final Throwable t) { - final ComponentLog componentLog = new SimpleProcessLogger(taskNode.getIdentifier(), taskNode.getReportingTask()); + final ComponentLog componentLog = new SimpleProcessLogger(taskNode.getIdentifier(), taskNode.getReportingTask(), new StandardLoggingContext(null)); componentLog.error("Error running task {} due to {}", new Object[]{taskNode.getReportingTask(), t.toString()}); if (componentLog.isDebugEnabled()) { componentLog.error("", t); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/fingerprint/FingerprintFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/fingerprint/FingerprintFactory.java index 524b91fb95a7..ba7bd2483e1a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/fingerprint/FingerprintFactory.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/fingerprint/FingerprintFactory.java @@ -392,6 +392,7 @@ StringBuilder addProcessGroupFingerprint(final StringBuilder builder, final Elem appendFirstValue(builder, DomUtils.getChildNodesByTagName(processGroupElem, "defaultFlowFileExpiration")); appendFirstValue(builder, DomUtils.getChildNodesByTagName(processGroupElem, "defaultBackPressureObjectThreshold")); appendFirstValue(builder, DomUtils.getChildNodesByTagName(processGroupElem, "defaultBackPressureDataSizeThreshold")); + appendFirstValue(builder, DomUtils.getChildNodesByTagName(processGroupElem, "logFileSuffix")); final Element versionControlInfo = DomUtils.getChild(processGroupElem, "versionControlInformation"); if (versionControlInfo == null) { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/resources/FlowConfiguration.xsd b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/resources/FlowConfiguration.xsd index 978976cd14e1..1f5bacf7995d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/resources/FlowConfiguration.xsd +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/resources/FlowConfiguration.xsd @@ -207,6 +207,7 @@ + @@ -273,6 +274,7 @@ + diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java index eadfe09d11ce..427b9930ca1f 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java @@ -858,6 +858,16 @@ public QueueSize getQueueSize() { return null; } + @Override + public String getLogFileSuffix() { + return null; + } + + @Override + public void setLogFileSuffix(String logFileSuffix) { + + } + @Override public void terminateProcessor(ProcessorNode processor) { } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/logback.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/logback.xml index ae2733f88094..dc1db9608dd5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/logback.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/logback.xml @@ -101,6 +101,31 @@ + + + + + ${org.apache.nifi.bootstrap.config.log.dir}/nifi-app-${logFileSuffix}.log + + + ${org.apache.nifi.bootstrap.config.log.dir}/nifi-app-${logFileSuffix}_%d{yyyy-MM-dd_HH}.%i.log + 100MB + + 30 + + true + + %date %level [%thread] %logger{40} %msg%n + + + + + %date %level [%thread] %logger{40} %msg%n @@ -226,4 +251,8 @@ + + + + diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java index 87e8f11d064d..ea26fdd22c8d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java @@ -2686,6 +2686,7 @@ private ProcessGroupDTO createConciseProcessGroupDto(final ProcessGroup group) { dto.setDefaultFlowFileExpiration(group.getDefaultFlowFileExpiration()); dto.setDefaultBackPressureObjectThreshold(group.getDefaultBackPressureObjectThreshold()); dto.setDefaultBackPressureDataSizeThreshold(group.getDefaultBackPressureDataSizeThreshold()); + dto.setLogFileSuffix(group.getLogFileSuffix()); final ParameterContext parameterContext = group.getParameterContext(); if (parameterContext != null) { @@ -4599,6 +4600,7 @@ public ProcessGroupDTO copy(final ProcessGroupDTO original, final boolean deep) copy.setDefaultFlowFileExpiration(original.getDefaultFlowFileExpiration()); copy.setDefaultBackPressureObjectThreshold(original.getDefaultBackPressureObjectThreshold()); copy.setDefaultBackPressureDataSizeThreshold(original.getDefaultBackPressureDataSizeThreshold()); + copy.setLogFileSuffix(original.getLogFileSuffix()); copy.setRunningCount(original.getRunningCount()); copy.setStoppedCount(original.getStoppedCount()); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardControllerServiceDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardControllerServiceDAO.java index 46fd9e15bfa4..31f770d887d6 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardControllerServiceDAO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardControllerServiceDAO.java @@ -40,6 +40,7 @@ import org.apache.nifi.parameter.ParameterLookup; import org.apache.nifi.components.ConfigVerificationResult; import org.apache.nifi.processor.SimpleProcessLogger; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.registry.VariableRegistry; import org.apache.nifi.util.BundleUtils; import org.apache.nifi.web.NiFiCoreException; @@ -413,7 +414,7 @@ public List verifyConfiguration(final String contro final ControllerServiceNode serviceNode = locateControllerService(controllerServiceId); final LogRepository logRepository = new NopLogRepository(); - final ComponentLog configVerificationLog = new SimpleProcessLogger(serviceNode.getControllerServiceImplementation(), logRepository); + final ComponentLog configVerificationLog = new SimpleProcessLogger(serviceNode.getControllerServiceImplementation(), logRepository, new StandardLoggingContext(serviceNode)); final ExtensionManager extensionManager = flowController.getExtensionManager(); final ParameterLookup parameterLookup = serviceNode.getProcessGroup() == null ? ParameterLookup.EMPTY : serviceNode.getProcessGroup().getParameterContext(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterProviderDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterProviderDAO.java index 51b66114beed..237e30e867c6 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterProviderDAO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterProviderDAO.java @@ -36,6 +36,7 @@ import org.apache.nifi.parameter.ParameterLookup; import org.apache.nifi.parameter.ParameterGroupConfiguration; import org.apache.nifi.processor.SimpleProcessLogger; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.util.BundleUtils; import org.apache.nifi.web.NiFiCoreException; import org.apache.nifi.web.ResourceNotFoundException; @@ -233,7 +234,7 @@ public List verifyConfiguration(final String parame final ParameterProviderNode parameterProviderNode = locateParameterProvider(parameterProviderId); final LogRepository logRepository = new NopLogRepository(); - final ComponentLog configVerificationLog = new SimpleProcessLogger(parameterProviderNode.getParameterProvider(), logRepository); + final ComponentLog configVerificationLog = new SimpleProcessLogger(parameterProviderNode.getParameterProvider(), logRepository, new StandardLoggingContext(null)); final ExtensionManager extensionManager = flowController.getExtensionManager(); final ParameterLookup parameterLookup = ParameterLookup.EMPTY; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java index e42a135d2e93..ecfe35e2a29a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java @@ -347,6 +347,8 @@ public ProcessGroup updateProcessGroup(ProcessGroupDTO processGroupDTO) { final Long defaultBackPressureObjectThreshold = processGroupDTO.getDefaultBackPressureObjectThreshold(); final String defaultBackPressureDataSizeThreshold = processGroupDTO.getDefaultBackPressureDataSizeThreshold(); + final String logFileSuffix = processGroupDTO.getLogFileSuffix(); + final ParameterContextReferenceEntity parameterContextReference = processGroupDTO.getParameterContext(); if (parameterContextReference != null) { final String parameterContextId = parameterContextReference.getId(); @@ -392,6 +394,10 @@ public ProcessGroup updateProcessGroup(ProcessGroupDTO processGroupDTO) { group.setDefaultBackPressureDataSizeThreshold(processGroupDTO.getDefaultBackPressureDataSizeThreshold()); } + if (logFileSuffix != null) { + group.setLogFileSuffix(logFileSuffix); + } + group.onComponentModified(); return group; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessorDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessorDAO.java index 1f2d0878a3cd..dca11a8fa5ca 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessorDAO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessorDAO.java @@ -35,6 +35,7 @@ import org.apache.nifi.logging.ComponentLog; import org.apache.nifi.logging.LogLevel; import org.apache.nifi.logging.LogRepository; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.logging.repository.NopLogRepository; import org.apache.nifi.nar.ExtensionManager; import org.apache.nifi.components.ConfigVerificationResult; @@ -482,7 +483,7 @@ public List verifyProcessorConfiguration(final Stri new NopStateManager(), () -> false, flowController); final LogRepository logRepository = new NopLogRepository(); - final ComponentLog configVerificationLog = new SimpleProcessLogger(processor, logRepository); + final ComponentLog configVerificationLog = new SimpleProcessLogger(processor, logRepository, new StandardLoggingContext(processor)); final ExtensionManager extensionManager = flowController.getExtensionManager(); final List verificationResults = processor.verifyConfiguration(processContext, configVerificationLog, attributes, extensionManager); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardReportingTaskDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardReportingTaskDAO.java index cc89982c300a..bf3e55539c9f 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardReportingTaskDAO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardReportingTaskDAO.java @@ -38,6 +38,7 @@ import org.apache.nifi.parameter.ParameterLookup; import org.apache.nifi.components.ConfigVerificationResult; import org.apache.nifi.processor.SimpleProcessLogger; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.scheduling.SchedulingStrategy; import org.apache.nifi.util.BundleUtils; import org.apache.nifi.util.FormatUtils; @@ -266,7 +267,7 @@ public List verifyConfiguration(final String report final ReportingTaskNode taskNode = locateReportingTask(reportingTaskId); final LogRepository logRepository = new NopLogRepository(); - final ComponentLog configVerificationLog = new SimpleProcessLogger(taskNode.getReportingTask(), logRepository); + final ComponentLog configVerificationLog = new SimpleProcessLogger(taskNode.getReportingTask(), logRepository, new StandardLoggingContext(null)); final ExtensionManager extensionManager = flowController.getExtensionManager(); final ParameterLookup parameterLookup = ParameterLookup.EMPTY; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java index d4ebcc06c4a9..9b183193d100 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java @@ -461,6 +461,28 @@ private void resolveNameConflicts(final FlowSnippetDTO snippetContents, final Pr groupNames.add(groupDTO.getName()); } } + + // get a list of all log file suffix + final List existingLogFileSuffixes = new ArrayList<>(); + for (final ProcessGroup processGroup : group.getProcessGroups()) { + if (processGroup.getLogFileSuffix() != null) { + existingLogFileSuffixes.add(processGroup.getLogFileSuffix()); + } + } + + // rename log file suffixes + if (snippetContents.getProcessGroups() != null) { + for (final ProcessGroupDTO processGroupDTO : snippetContents.getProcessGroups()) { + String logFileSuffix = processGroupDTO.getLogFileSuffix(); + if (logFileSuffix != null) { + while (existingLogFileSuffixes.contains(logFileSuffix)) { + logFileSuffix = "Copy_of_" + logFileSuffix; + } + processGroupDTO.setLogFileSuffix(logFileSuffix); + existingLogFileSuffixes.add(processGroupDTO.getLogFileSuffix()); + } + } + } } private FlowSnippetDTO copyContentsForGroup(final FlowSnippetDTO snippetContents, final String groupId, final Map parentConnectableMap, diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/process-group-configuration.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/process-group-configuration.jsp index 64d57d0f9f74..509a3d9677eb 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/process-group-configuration.jsp +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/process-group-configuration.jsp @@ -99,6 +99,17 @@ +
+
Log File Suffix +
+
+
+ +
+
+ +
+
Apply
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/process-group-configuration.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/process-group-configuration.css index 07a45065e406..20cfaec23e3e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/process-group-configuration.css +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/process-group-configuration.css @@ -119,4 +119,8 @@ #upload-process-group-link { float: right; +} + +#process-group-log-to-own-file-combo { + width: 328px; } \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js index 2060e00292ee..d2c9fb289ce0 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js @@ -111,7 +111,8 @@ 'flowfileOutboundPolicy': $('#process-group-outbound-policy-combo').combo('getSelectedOption').value, 'defaultFlowFileExpiration': $('#process-group-default-flowfile-expiration').val(), 'defaultBackPressureObjectThreshold': $('#process-group-default-back-pressure-object-threshold').val(), - 'defaultBackPressureDataSizeThreshold': $('#process-group-default-back-pressure-data-size-threshold').val() + 'defaultBackPressureDataSizeThreshold': $('#process-group-default-back-pressure-data-size-threshold').val(), + 'logFileSuffix': $('#process-group-log-file-suffix').val() } }; @@ -271,7 +272,7 @@ $('#process-group-default-flowfile-expiration').removeClass('unset').val(processGroup.defaultFlowFileExpiration); $('#process-group-default-back-pressure-object-threshold').removeClass('unset').val(processGroup.defaultBackPressureObjectThreshold); $('#process-group-default-back-pressure-data-size-threshold').removeClass('unset').val(processGroup.defaultBackPressureDataSizeThreshold); - + $('#process-group-log-file-suffix').removeClass('unset').val(processGroup.logFileSuffix); // populate the header $('#process-group-configuration-header-text').text(processGroup.name + ' Configuration'); @@ -316,6 +317,9 @@ $('#read-only-process-group-default-flowfile-expiration').text(processGroup.defaultFlowFileExpiration); $('#read-only-process-group-default-back-pressure-object-threshold').text(processGroup.defaultBackPressureObjectThreshold); $('#read-only-process-group-default-back-pressure-data-size-threshold').text(processGroup.defaultBackPressureDataSizeThreshold); + $('#read-only-process-group-log-file-suffix').text(processGroup.logFileSuffix); + + } else { setUnauthorizedText(); } diff --git a/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/DifferenceType.java b/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/DifferenceType.java index 227c5b403d7b..219aff464288 100644 --- a/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/DifferenceType.java +++ b/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/DifferenceType.java @@ -368,7 +368,12 @@ public enum DifferenceType { /** * The Process Group's Default value for connections' FlowFile Expiration is different in each of the flows */ - DEFAULT_FLOWFILE_EXPIRATION_CHANGED("Default FlowFile Expiration Changed") + DEFAULT_FLOWFILE_EXPIRATION_CHANGED("Default FlowFile Expiration Changed"), + + /** + * The Process Group's Log File Suffix value is different in each of the flows + */ + LOG_FILE_SUFFIX_CHANGED("Log File Suffix Changed") ; private final String description; diff --git a/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/StandardFlowComparator.java b/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/StandardFlowComparator.java index 4efe43710c7c..be21d97069cb 100644 --- a/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/StandardFlowComparator.java +++ b/nifi-registry/nifi-registry-core/nifi-registry-flow-diff/src/main/java/org/apache/nifi/registry/flow/diff/StandardFlowComparator.java @@ -522,6 +522,7 @@ private void compare(final VersionedProcessGroup groupA, final VersionedProcessG addIfDifferent(differences, DifferenceType.DEFAULT_BACKPRESSURE_OBJECT_COUNT_CHANGED, groupA, groupB, VersionedProcessGroup::getDefaultBackPressureObjectThreshold, true, 10_000L); addIfDifferent(differences, DifferenceType.DEFAULT_FLOWFILE_EXPIRATION_CHANGED, groupA, groupB, VersionedProcessGroup::getDefaultFlowFileExpiration, true, "0 sec"); addIfDifferent(differences, DifferenceType.PARAMETER_CONTEXT_CHANGED, groupA, groupB, VersionedProcessGroup::getParameterContextName, true, null); + addIfDifferent(differences, DifferenceType.LOG_FILE_SUFFIX_CHANGED, groupA, groupB, VersionedProcessGroup::getLogFileSuffix, true, null); final VersionedFlowCoordinates groupACoordinates = groupA.getVersionedFlowCoordinates(); final VersionedFlowCoordinates groupBCoordinates = groupB.getVersionedFlowCoordinates(); diff --git a/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/core/RegistryUtil.java b/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/core/RegistryUtil.java index f7444c8dd657..1e0da7c5598e 100644 --- a/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/core/RegistryUtil.java +++ b/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/core/RegistryUtil.java @@ -155,6 +155,7 @@ private void populateVersionedContentsRecursively(final VersionedProcessGroup gr group.setDefaultFlowFileExpiration(contents.getDefaultFlowFileExpiration()); group.setDefaultBackPressureObjectThreshold(contents.getDefaultBackPressureObjectThreshold()); group.setDefaultBackPressureDataSizeThreshold(contents.getDefaultBackPressureDataSizeThreshold()); + group.setLogFileSuffix(contents.getLogFileSuffix()); coordinates.setLatest(snapshot.isLatest()); } diff --git a/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/engine/ComponentBuilder.java b/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/engine/ComponentBuilder.java index c2f62b3fec65..b7e84c190e85 100644 --- a/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/engine/ComponentBuilder.java +++ b/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/engine/ComponentBuilder.java @@ -52,6 +52,7 @@ import org.apache.nifi.controller.service.StandardControllerServiceInvocationHandler; import org.apache.nifi.controller.service.StandardControllerServiceNode; import org.apache.nifi.logging.ComponentLog; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.nar.ExtensionManager; import org.apache.nifi.parameter.ParameterProvider; import org.apache.nifi.parameter.ParameterProviderInitializationContext; @@ -165,7 +166,7 @@ public FlowRegistryClientNode buildFlowRegistryClient() throws FlowRepositoryCli private LoggableComponent createLoggableFlowRegistryClient() throws FlowRepositoryClientInstantiationException { try { - final ComponentLog componentLog = new SimpleProcessLogger(identifier, InMemoryFlowRegistry.class.newInstance()); + final ComponentLog componentLog = new SimpleProcessLogger(identifier, InMemoryFlowRegistry.class.newInstance(), new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLog); final InMemoryFlowRegistry registryClient = new InMemoryFlowRegistry(); final LoggableComponent nodeComponent = new LoggableComponent<>(registryClient, bundleCoordinate, terminationAwareLogger); @@ -288,7 +289,7 @@ public ControllerServiceNode buildControllerService() { } logger.info("Created Controller Service of type {} with identifier {}", type, identifier); - final ComponentLog serviceLogger = new SimpleProcessLogger(identifier, serviceImpl); + final ComponentLog serviceLogger = new SimpleProcessLogger(identifier, serviceImpl, new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(serviceLogger); final StateManager stateManager = stateManagerProvider.getStateManager(identifier); @@ -352,7 +353,7 @@ private LoggableComponent createLoggableCom Thread.currentThread().setContextClassLoader(detectedClassLoader); final Object extensionInstance = rawClass.newInstance(); - final ComponentLog componentLog = new SimpleProcessLogger(identifier, extensionInstance); + final ComponentLog componentLog = new SimpleProcessLogger(identifier, extensionInstance, new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLog); final T cast = nodeType.cast(extensionInstance); diff --git a/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/engine/StatelessReloadComponent.java b/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/engine/StatelessReloadComponent.java index 7ac291796998..dffc2a93e402 100644 --- a/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/engine/StatelessReloadComponent.java +++ b/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/engine/StatelessReloadComponent.java @@ -41,6 +41,7 @@ import org.apache.nifi.parameter.ParameterProvider; import org.apache.nifi.processor.Processor; import org.apache.nifi.processor.SimpleProcessLogger; +import org.apache.nifi.logging.StandardLoggingContext; import org.apache.nifi.processor.StandardProcessContext; import org.apache.nifi.registry.flow.FlowRegistryClient; import org.apache.nifi.registry.flow.FlowRegistryClientNode; @@ -94,7 +95,7 @@ public void reload(final ProcessorNode existingNode, final String newType, final } // set the new processor in the existing node - final ComponentLog componentLogger = new SimpleProcessLogger(id, newNode.getProcessor()); + final ComponentLog componentLogger = new SimpleProcessLogger(id, newNode.getProcessor(), new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLogger); LogRepositoryFactory.getRepository(id).setLogger(terminationAwareLogger); @@ -154,7 +155,7 @@ public void reload(final ControllerServiceNode existingNode, final String newTyp invocationHandler.setServiceNode(existingNode); // create LoggableComponents for the proxy and implementation - final ComponentLog componentLogger = new SimpleProcessLogger(id, newNode.getControllerServiceImplementation()); + final ComponentLog componentLogger = new SimpleProcessLogger(id, newNode.getControllerServiceImplementation(), new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLogger); LogRepositoryFactory.getRepository(id).setLogger(terminationAwareLogger); @@ -202,7 +203,7 @@ public void reload(final ReportingTaskNode existingNode, final String newType, f } // set the new reporting task into the existing node - final ComponentLog componentLogger = new SimpleProcessLogger(id, existingNode.getReportingTask()); + final ComponentLog componentLogger = new SimpleProcessLogger(id, existingNode.getReportingTask(), new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLogger); LogRepositoryFactory.getRepository(id).setLogger(terminationAwareLogger); @@ -247,7 +248,7 @@ public void reload(final ParameterProviderNode existingNode, final String newTyp } // set the new reporting task into the existing node - final ComponentLog componentLogger = new SimpleProcessLogger(id, existingNode.getParameterProvider()); + final ComponentLog componentLogger = new SimpleProcessLogger(id, existingNode.getParameterProvider(), new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLogger); LogRepositoryFactory.getRepository(id).setLogger(terminationAwareLogger); @@ -285,7 +286,7 @@ public void reload(FlowRegistryClientNode existingNode, String newType, BundleCo extensionManager.closeURLClassLoader(id, existingInstanceClassLoader); // set the new flow registry client into the existing node - final ComponentLog componentLogger = new SimpleProcessLogger(id, existingNode.getComponent()); + final ComponentLog componentLogger = new SimpleProcessLogger(id, existingNode.getComponent(), new StandardLoggingContext(null)); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLogger); LogRepositoryFactory.getRepository(id).setLogger(terminationAwareLogger); diff --git a/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/engine/StatelessSchedulingAgent.java b/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/engine/StatelessSchedulingAgent.java index 94dc01cfc587..bb088c0d4e49 100644 --- a/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/engine/StatelessSchedulingAgent.java +++ b/nifi-stateless/nifi-stateless-bundle/nifi-stateless-engine/src/main/java/org/apache/nifi/stateless/engine/StatelessSchedulingAgent.java @@ -25,6 +25,7 @@ import org.apache.nifi.nar.ExtensionManager; import org.apache.nifi.nar.NarCloseable; import org.apache.nifi.processor.SimpleProcessLogger; +import org.apache.nifi.logging.StandardLoggingContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -92,7 +93,7 @@ private void triggerReportingTask(final ReportingTaskNode taskNode, final Lifecy } } catch (final Throwable t) { - final ComponentLog componentLog = new SimpleProcessLogger(taskNode.getIdentifier(), taskNode.getReportingTask()); + final ComponentLog componentLog = new SimpleProcessLogger(taskNode.getIdentifier(), taskNode.getReportingTask(), new StandardLoggingContext(null)); componentLog.error("Error running task {} due to {}", new Object[]{taskNode.getReportingTask(), t.toString()}); if (componentLog.isDebugEnabled()) { componentLog.error("", t);