You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2017/07/13 14:08:02 UTC

[2/2] syncope git commit: [SYNCOPE-1144] Minor changes and cleanup

[SYNCOPE-1144] Minor changes and cleanup


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/cb57c5ad
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/cb57c5ad
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/cb57c5ad

Branch: refs/heads/master
Commit: cb57c5ad20bcd90efe09d0666f27ab151aa4b00c
Parents: d7fbfe4
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Jul 13 16:07:44 2017 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Jul 13 16:07:53 2017 +0200

----------------------------------------------------------------------
 .../common/lib/types/AuditLoggerName.java       | 10 ++-
 .../core/logic/AbstractAuditAppender.java       |  1 +
 .../syncope/core/logic/AuditAppender.java       | 51 ------------
 .../core/logic/DefaultAuditAppender.java        | 54 -------------
 .../core/logic/DefaultRewriteAuditAppender.java | 64 ----------------
 .../apache/syncope/core/logic/LoggerLogic.java  | 52 ++++++-------
 .../core/logic/PassThroughRewritePolicy.java    | 41 ----------
 .../syncope/core/logic/audit/AuditAppender.java | 52 +++++++++++++
 .../core/logic/audit/DefaultAuditAppender.java  | 54 +++++++++++++
 .../audit/DefaultRewriteAuditAppender.java      | 64 ++++++++++++++++
 .../audit/PassThroughAuditRewritePolicy.java    | 43 +++++++++++
 .../init/ClassPathScanImplementationLookup.java |  2 +-
 .../syncope/core/logic/init/LoggerAccessor.java | 14 ++--
 .../syncope/core/logic/init/LoggerLoader.java   | 50 ++++++------
 .../provisioning/java/AuditManagerImpl.java     | 16 +---
 .../reference/SyslogRewriteAuditAppender.java   |  2 +-
 .../core/reference/TestFileAuditAppender.java   |  2 +-
 .../reference/TestFileRewriteAuditAppender.java | 20 ++---
 .../apache/syncope/fit/core/LoggerITCase.java   | 81 ++++++++++----------
 .../reference-guide/concepts/audit.adoc         | 79 +++++++++----------
 .../workingwithapachesyncope/customization.adoc |  7 +-
 21 files changed, 375 insertions(+), 384 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/common/lib/src/main/java/org/apache/syncope/common/lib/types/AuditLoggerName.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AuditLoggerName.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/AuditLoggerName.java
index 9c071b8..6fc1ab0 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AuditLoggerName.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/AuditLoggerName.java
@@ -34,6 +34,14 @@ public class AuditLoggerName extends AbstractBaseBean {
 
     private static final long serialVersionUID = -647989486671786839L;
 
+    public static String getAuditLoggerName(final String domain) {
+        return LoggerType.AUDIT.getPrefix() + "." + domain;
+    }
+
+    public static String getAuditEventLoggerName(final String domain, final String loggerName) {
+        return domain + "." + loggerName;
+    }
+
     private final AuditElements.EventCategoryType type;
 
     private final String category;
@@ -105,7 +113,7 @@ public class AuditLoggerName extends AbstractBaseBean {
                 eventCategory.getKey().getCategory(),
                 eventCategory.getKey().getSubcategory(),
                 eventCategory.getKey().getEvents().isEmpty()
-                        ? StringUtils.EMPTY : eventCategory.getKey().getEvents().iterator().next(),
+                ? StringUtils.EMPTY : eventCategory.getKey().getEvents().iterator().next(),
                 eventCategory.getValue());
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAuditAppender.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAuditAppender.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAuditAppender.java
index 5383a81..0065543 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAuditAppender.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAuditAppender.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.core.logic;
 
+import org.apache.syncope.core.logic.audit.AuditAppender;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
 import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/AuditAppender.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AuditAppender.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AuditAppender.java
deleted file mode 100644
index 93dbfed..0000000
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AuditAppender.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.syncope.core.logic;
-
-import java.util.Set;
-import org.apache.logging.log4j.core.Appender;
-import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
-import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
-import org.apache.syncope.common.lib.types.AuditLoggerName;
-
-/**
- * Basic interface to implement to define a custom audit appender
- *
- * @see org.apache.syncope.core.logic.DefaultRewriteAuditAppender or org.apache.syncope.core.logic.DefaultAuditAppender
- */
-public interface AuditAppender {
-
-    void init();
-
-    Set<AuditLoggerName> getEvents();
-
-    Appender getTargetAppender();
-
-    RewritePolicy getRewritePolicy();
-
-    String getTargetAppenderName();
-    
-    void setDomainName(String name);
-
-    String getDomainName();
-
-    boolean isRewriteEnabled();
-
-    RewriteAppender getRewriteAppender();
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/DefaultAuditAppender.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/DefaultAuditAppender.java b/core/logic/src/main/java/org/apache/syncope/core/logic/DefaultAuditAppender.java
deleted file mode 100644
index 1fd9e5e..0000000
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/DefaultAuditAppender.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.syncope.core.logic;
-
-import java.util.Collections;
-import java.util.Set;
-import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
-import org.apache.syncope.common.lib.types.AuditLoggerName;
-
-/**
- * Default (abstract) implementation of custom audit appender.
- * It is bound to an empty collection of events, i.e. it does not create any logger.
- * This class has to be extended by non-rewrite appenders
- *
- * @see org.apache.syncope.fit.core.reference.TestFileAuditAppender
- */
-public abstract class DefaultAuditAppender extends AbstractAuditAppender {
-
-    @Override
-    public void init() {
-        initTargetAppender();
-    }
-
-    @Override
-    public Set<AuditLoggerName> getEvents() {
-        return Collections.emptySet();
-    }
-
-    @Override
-    public void initRewriteAppender() {
-    }
-
-    @Override
-    public RewritePolicy getRewritePolicy() {
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/DefaultRewriteAuditAppender.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/DefaultRewriteAuditAppender.java b/core/logic/src/main/java/org/apache/syncope/core/logic/DefaultRewriteAuditAppender.java
deleted file mode 100644
index 207502e..0000000
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/DefaultRewriteAuditAppender.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.syncope.core.logic;
-
-import java.util.Collections;
-import java.util.Set;
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
-import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
-import org.apache.logging.log4j.core.config.AppenderRef;
-import org.apache.syncope.common.lib.types.AuditLoggerName;
-
-/**
- * Default (abstract) implementation of custom rewriting audit appender; it provides rewrite appender definition and 
- * a default "pass-through" policy. It is bound to an empty collection of events, i.e. it does not create any logger.
- * This class has to be extended by rewrite appenders.
- *
- * @see org.apache.syncope.fit.core.reference.TestFileRewriteAuditAppender
- */
-public abstract class DefaultRewriteAuditAppender extends AbstractAuditAppender {
-
-    @Override
-    public void init() {
-        initTargetAppender();
-        initRewriteAppender();
-    }
-
-    @Override
-    public void initRewriteAppender() {
-        rewriteAppender = RewriteAppender.createAppender(getTargetAppenderName() + "_rewrite",
-                "true",
-                new AppenderRef[] { AppenderRef.createAppenderRef(getTargetAppenderName(), Level.DEBUG, null) },
-                ((LoggerContext) LogManager.getContext(false)).getConfiguration(), getRewritePolicy(), null);
-    }
-
-    @Override
-    public Set<AuditLoggerName> getEvents() {
-        return Collections.emptySet();
-    }
-
-    @Override
-    public RewritePolicy getRewritePolicy() {
-        return PassThroughRewritePolicy.createPolicy();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
index 667efc8..5429c24 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
@@ -53,6 +53,7 @@ import org.apache.syncope.common.lib.types.UnmatchingRule;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.syncope.core.logic.audit.AuditAppender;
 import org.apache.syncope.core.logic.init.LoggerLoader;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
@@ -62,7 +63,6 @@ import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.Logger;
 import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
-import org.apache.syncope.core.provisioning.java.AuditManagerImpl;
 import org.apache.syncope.core.spring.BeanUtils;
 import org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate;
 import org.apache.syncope.core.provisioning.java.pushpull.PullJobDelegate;
@@ -220,41 +220,41 @@ public class LoggerLogic extends AbstractTransactionalLogic<LoggerTO> {
         syncopeLogger.setLevel(LoggerLevel.fromLevel(level));
         syncopeLogger = loggerDAO.save(syncopeLogger);
 
-        boolean isAudit = LoggerType.AUDIT.equals(syncopeLogger.getType());
         LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
-        String domainAuditLoggerName =
-                AuditManagerImpl.getDomainAuditEventLoggerName(AuthContextUtils.getDomain(), syncopeLogger.
-                        getKey());
-        LoggerConfig logConf = SyncopeConstants.ROOT_LOGGER.equals(name)
-                ? ctx.getConfiguration().getLoggerConfig(LogManager.ROOT_LOGGER_NAME)
-                : isAudit
-                        ? ctx.getConfiguration().getLoggerConfig(domainAuditLoggerName)
-                        : ctx.getConfiguration().getLoggerConfig(name);
-
-        if (isAudit) {
+        LoggerConfig logConf;
+
+        if (LoggerType.AUDIT.equals(syncopeLogger.getType())) {
+            String auditLoggerName = AuditLoggerName.getAuditEventLoggerName(
+                    AuthContextUtils.getDomain(), syncopeLogger.getKey());
+
+            logConf = ctx.getConfiguration().getLoggerConfig(auditLoggerName);
+
             // SYNCOPE-1144 For each custom audit appender class add related appenders to log4j logger
-            List<AuditAppender> auditAppenders = loggerLoader.auditAppenders(AuthContextUtils.getDomain());
             boolean isRootLogConf = LogManager.ROOT_LOGGER_NAME.equals(logConf.getName());
-            final String loggerKey = syncopeLogger.getKey();
             if (isRootLogConf) {
-                logConf = new LoggerConfig(domainAuditLoggerName, null, false);
+                logConf = new LoggerConfig(auditLoggerName, null, false);
             }
-            for (AuditAppender auditAppender : auditAppenders) {
-
+            for (AuditAppender auditAppender : loggerLoader.auditAppenders(AuthContextUtils.getDomain())) {
                 if (IterableUtils.matchesAny(auditAppender.getEvents(), new Predicate<AuditLoggerName>() {
 
                     @Override
                     public boolean evaluate(final AuditLoggerName auditLoggerName) {
-                        return loggerKey.equalsIgnoreCase(auditLoggerName.toLoggerName());
+                        return name.equalsIgnoreCase(auditLoggerName.toLoggerName());
                     }
                 })) {
+
                     loggerLoader.addAppenderToContext(ctx, auditAppender, logConf);
                 }
             }
             if (isRootLogConf) {
-                ctx.getConfiguration().addLogger(domainAuditLoggerName, logConf);
+                ctx.getConfiguration().addLogger(auditLoggerName, logConf);
             }
+        } else {
+            logConf = SyncopeConstants.ROOT_LOGGER.equals(name)
+                    ? ctx.getConfiguration().getLoggerConfig(LogManager.ROOT_LOGGER_NAME)
+                    : ctx.getConfiguration().getLoggerConfig(name);
         }
+
         logConf.setLevel(level);
         ctx.updateLoggers();
 
@@ -289,7 +289,6 @@ public class LoggerLogic extends AbstractTransactionalLogic<LoggerTO> {
         if (expectedType != syncopeLogger.getType()) {
             throwInvalidLogger(expectedType);
         }
-        boolean isAudit = LoggerType.AUDIT.equals(syncopeLogger.getType());
 
         LoggerTO loggerToDelete = new LoggerTO();
         BeanUtils.copyProperties(syncopeLogger, loggerToDelete);
@@ -299,14 +298,15 @@ public class LoggerLogic extends AbstractTransactionalLogic<LoggerTO> {
 
         // set log level to OFF in order to disable configured logger until next reboot
         LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
-        String domainAuditLoggerName =
-                AuditManagerImpl.getDomainAuditEventLoggerName(AuthContextUtils.getDomain(), syncopeLogger.
-                        getKey());
+
+        String auditLoggerName = AuditLoggerName.getAuditEventLoggerName(
+                AuthContextUtils.getDomain(), syncopeLogger.getKey());
         org.apache.logging.log4j.core.Logger logger = SyncopeConstants.ROOT_LOGGER.equals(name)
                 ? ctx.getLogger(LogManager.ROOT_LOGGER_NAME)
-                : isAudit
-                        ? ctx.getLogger(domainAuditLoggerName)
-                        : ctx.getLogger(name);
+                : LoggerType.AUDIT.equals(syncopeLogger.getType())
+                ? ctx.getLogger(auditLoggerName)
+                : ctx.getLogger(name);
+
         logger.setLevel(Level.OFF);
         ctx.updateLoggers();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/PassThroughRewritePolicy.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/PassThroughRewritePolicy.java b/core/logic/src/main/java/org/apache/syncope/core/logic/PassThroughRewritePolicy.java
deleted file mode 100644
index 08c6c4e..0000000
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/PassThroughRewritePolicy.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.syncope.core.logic;
-
-import org.apache.logging.log4j.core.Core;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
-import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.config.plugins.PluginFactory;
-
-@Plugin(name = "PassThroughRewritePolicy", category = Core.CATEGORY_NAME, elementType = "rewritePolicy",
-        printObject = true)
-public class PassThroughRewritePolicy implements RewritePolicy {
-
-    @Override
-    public LogEvent rewrite(final LogEvent event) {
-        return event;
-    }
-
-    @PluginFactory
-    public static PassThroughRewritePolicy createPolicy() {
-        return new PassThroughRewritePolicy();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditAppender.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditAppender.java b/core/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditAppender.java
new file mode 100644
index 0000000..f6a0716
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditAppender.java
@@ -0,0 +1,52 @@
+/*
+ * 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.syncope.core.logic.audit;
+
+import java.util.Set;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
+import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
+
+/**
+ * Basic interface to implement to define a custom audit appender
+ *
+ * @see DefaultAuditAppender
+ * @see DefaultRewriteAuditAppender
+ */
+public interface AuditAppender {
+
+    void init();
+
+    Set<AuditLoggerName> getEvents();
+
+    Appender getTargetAppender();
+
+    RewritePolicy getRewritePolicy();
+
+    String getTargetAppenderName();
+
+    void setDomainName(String name);
+
+    String getDomainName();
+
+    boolean isRewriteEnabled();
+
+    RewriteAppender getRewriteAppender();
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java b/core/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java
new file mode 100644
index 0000000..0fdd0b5
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java
@@ -0,0 +1,54 @@
+/*
+ * 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.syncope.core.logic.audit;
+
+import java.util.Collections;
+import java.util.Set;
+import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
+import org.apache.syncope.core.logic.AbstractAuditAppender;
+
+/**
+ * Default (abstract) implementation of custom audit appender.
+ * It is bound to an empty collection of events, i.e. it does not create any logger.
+ * This class shall be extended by non-rewriting appenders; for rewriting, extend
+ * {@link DefaultRewriteAuditAppender} instead.
+ */
+public abstract class DefaultAuditAppender extends AbstractAuditAppender {
+
+    @Override
+    public void init() {
+        initTargetAppender();
+    }
+
+    @Override
+    public Set<AuditLoggerName> getEvents() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public void initRewriteAppender() {
+    }
+
+    @Override
+    public RewritePolicy getRewritePolicy() {
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultRewriteAuditAppender.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultRewriteAuditAppender.java b/core/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultRewriteAuditAppender.java
new file mode 100644
index 0000000..a937cc9
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultRewriteAuditAppender.java
@@ -0,0 +1,64 @@
+/*
+ * 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.syncope.core.logic.audit;
+
+import java.util.Collections;
+import java.util.Set;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
+import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
+import org.apache.logging.log4j.core.config.AppenderRef;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
+import org.apache.syncope.core.logic.AbstractAuditAppender;
+
+/**
+ * Default (abstract) implementation of custom rewriting audit appender; it provides rewrite appender definition and
+ * a default "pass-through" policy.
+ * It is bound to an empty collection of events, i.e. it does not create any logger.
+ * This class shall be extended by rewriting appenders; for non-rewriting, extend {@link DefaultAuditAppender} instead.
+ */
+public abstract class DefaultRewriteAuditAppender extends AbstractAuditAppender {
+
+    @Override
+    public void init() {
+        initTargetAppender();
+        initRewriteAppender();
+    }
+
+    @Override
+    public void initRewriteAppender() {
+        rewriteAppender = RewriteAppender.createAppender(getTargetAppenderName() + "_rewrite",
+                "true",
+                new AppenderRef[] { AppenderRef.createAppenderRef(getTargetAppenderName(), Level.DEBUG, null) },
+                ((LoggerContext) LogManager.getContext(false)).getConfiguration(), getRewritePolicy(), null);
+    }
+
+    @Override
+    public Set<AuditLoggerName> getEvents() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public RewritePolicy getRewritePolicy() {
+        return PassThroughAuditRewritePolicy.createPolicy();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/audit/PassThroughAuditRewritePolicy.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/audit/PassThroughAuditRewritePolicy.java b/core/logic/src/main/java/org/apache/syncope/core/logic/audit/PassThroughAuditRewritePolicy.java
new file mode 100644
index 0000000..b3ee968
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/audit/PassThroughAuditRewritePolicy.java
@@ -0,0 +1,43 @@
+/*
+ * 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.syncope.core.logic.audit;
+
+import org.apache.logging.log4j.core.Core;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+
+@Plugin(name = "PassThroughRewritePolicy",
+        category = Core.CATEGORY_NAME,
+        elementType = "rewritePolicy",
+        printObject = true)
+public class PassThroughAuditRewritePolicy implements RewritePolicy {
+
+    @Override
+    public LogEvent rewrite(final LogEvent event) {
+        return event;
+    }
+
+    @PluginFactory
+    public static PassThroughAuditRewritePolicy createPolicy() {
+        return new PassThroughAuditRewritePolicy();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
index 902fa4d..1b9bc72 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
@@ -28,7 +28,7 @@ import java.util.Set;
 import org.apache.syncope.common.lib.policy.AccountRuleConf;
 import org.apache.syncope.common.lib.policy.PasswordRuleConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
-import org.apache.syncope.core.logic.AuditAppender;
+import org.apache.syncope.core.logic.audit.AuditAppender;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator;
 import org.apache.syncope.core.persistence.api.dao.AccountRule;

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerAccessor.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerAccessor.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerAccessor.java
index 675fd94..4f71ae6 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerAccessor.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerAccessor.java
@@ -24,13 +24,13 @@ import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.config.LoggerConfig;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.common.lib.types.LoggerLevel;
 import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.Logger;
-import org.apache.syncope.core.provisioning.java.AuditManagerImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
@@ -58,8 +58,8 @@ public class LoggerAccessor {
             }
         }
         for (Logger syncopeLogger : loggerDAO.findAll(LoggerType.AUDIT)) {
-            syncopeLoggers.put(AuditManagerImpl.getDomainAuditEventLoggerName(AuthContextUtils.getDomain(),
-                    syncopeLogger.getKey()), syncopeLogger);
+            syncopeLoggers.put(AuditLoggerName.getAuditEventLoggerName(
+                    AuthContextUtils.getDomain(), syncopeLogger.getKey()), syncopeLogger);
         }
 
         /*
@@ -73,8 +73,9 @@ public class LoggerAccessor {
                 if (syncopeLoggers.containsKey(loggerName)) {
                     logConf.setLevel(syncopeLoggers.get(loggerName).getLevel().getLevel());
                     syncopeLoggers.remove(loggerName);
-                } else if (!loggerName.startsWith(LoggerType.AUDIT.getPrefix()) || !loggerName.startsWith(
-                        AuthContextUtils.getDomain() + "." + LoggerType.AUDIT.getPrefix())) {
+                } else if (!loggerName.startsWith(LoggerType.AUDIT.getPrefix())
+                        || !loggerName.startsWith(AuthContextUtils.getDomain() + "." + LoggerType.AUDIT.getPrefix())) {
+
                     Logger syncopeLogger = entityFactory.newEntity(Logger.class);
                     syncopeLogger.setKey(loggerName);
                     syncopeLogger.setLevel(LoggerLevel.fromLevel(logConf.getLevel()));
@@ -88,9 +89,8 @@ public class LoggerAccessor {
          * Foreach SyncopeLogger not found in log4j create a new log4j logger with given name and level.
          */
         for (Map.Entry<String, Logger> entry : syncopeLoggers.entrySet()) {
-            Logger syncopeLogger = entry.getValue();
             LoggerConfig logConf = ctx.getConfiguration().getLoggerConfig(entry.getKey());
-            logConf.setLevel(syncopeLogger.getLevel().getLevel());
+            logConf.setLevel(entry.getValue().getLevel().getLevel());
         }
 
         ctx.updateLoggers();

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java
index 4a24d32..e4a4bc5 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java
@@ -36,9 +36,8 @@ import org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender;
 import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
 import org.apache.logging.log4j.core.config.LoggerConfig;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.core.logic.AuditAppender;
+import org.apache.syncope.core.logic.audit.AuditAppender;
 import org.apache.syncope.core.logic.MemoryAppender;
-import org.apache.syncope.core.provisioning.java.AuditManagerImpl;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.apache.syncope.core.persistence.api.DomainsHolder;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
@@ -111,13 +110,28 @@ public class LoggerLoader implements SyncopeLoader {
             }
 
             LoggerConfig logConf = new LoggerConfig(
-                    AuditManagerImpl.getDomainAuditLoggerName(entry.getKey()), null, false);
+                    AuditLoggerName.getAuditLoggerName(entry.getKey()), null, false);
             logConf.addAppender(appender, Level.DEBUG, null);
             logConf.setLevel(Level.DEBUG);
-            ctx.getConfiguration().addLogger(AuditManagerImpl.getDomainAuditLoggerName(entry.getKey()), logConf);
+            ctx.getConfiguration().addLogger(AuditLoggerName.getAuditLoggerName(entry.getKey()), logConf);
 
             // SYNCOPE-1144 For each custom audit appender class add related appenders to log4j logger
-            configureCustomAppenders(entry.getKey(), ctx);
+            for (AuditAppender auditAppender : auditAppenders(entry.getKey())) {
+                for (AuditLoggerName event : auditAppender.getEvents()) {
+                    String domainAuditLoggerName =
+                            AuditLoggerName.getAuditEventLoggerName(entry.getKey(), event.toLoggerName());
+                    LoggerConfig eventLogConf = ctx.getConfiguration().getLoggerConfig(domainAuditLoggerName);
+
+                    if (LogManager.ROOT_LOGGER_NAME.equals(eventLogConf.getName())) {
+                        eventLogConf = new LoggerConfig(domainAuditLoggerName, null, false);
+                    }
+                    addAppenderToContext(ctx, auditAppender, eventLogConf);
+                    eventLogConf.setLevel(Level.DEBUG);
+                    if (LogManager.ROOT_LOGGER_NAME.equals(eventLogConf.getName())) {
+                        ctx.getConfiguration().addLogger(domainAuditLoggerName, eventLogConf);
+                    }
+                }
+            }
 
             AuthContextUtils.execWithAuthContext(entry.getKey(), new AuthContextUtils.Executable<Void>() {
 
@@ -136,28 +150,7 @@ public class LoggerLoader implements SyncopeLoader {
         return memoryAppenders;
     }
 
-    public void configureCustomAppenders(final String domainName, final LoggerContext ctx) {
-        List<AuditAppender> auditAppenders = auditAppenders(domainName);
-        for (AuditAppender auditAppender : auditAppenders) {
-            for (AuditLoggerName event : auditAppender.getEvents()) {
-                String domainAuditLoggerName =
-                        AuditManagerImpl.getDomainAuditEventLoggerName(domainName, event.toLoggerName());
-                LoggerConfig eventLogConf = ctx.getConfiguration().getLoggerConfig(domainAuditLoggerName);
-                boolean isRootLogConf = LogManager.ROOT_LOGGER_NAME.equals(eventLogConf.getName());
-
-                if (isRootLogConf) {
-                    eventLogConf = new LoggerConfig(domainAuditLoggerName, null, false);
-                }
-                addAppenderToContext(ctx, auditAppender, eventLogConf);
-                eventLogConf.setLevel(Level.DEBUG);
-                if (isRootLogConf) {
-                    ctx.getConfiguration().addLogger(domainAuditLoggerName, eventLogConf);
-                }
-            }
-        }
-    }
-
-    public List<AuditAppender> auditAppenders(final String domainName) throws BeansException {
+    public List<AuditAppender> auditAppenders(final String domain) throws BeansException {
         List<AuditAppender> auditAppenders = new ArrayList<>();
         for (Class<?> clazz : implementationLookup.getAuditAppenderClasses()) {
             AuditAppender auditAppender;
@@ -167,7 +160,7 @@ public class LoggerLoader implements SyncopeLoader {
             } else {
                 auditAppender = (AuditAppender) ApplicationContextProvider.getBeanFactory().
                         createBean(clazz, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
-                auditAppender.setDomainName(domainName);
+                auditAppender.setDomainName(domain);
                 auditAppender.init();
             }
             auditAppenders.add(auditAppender);
@@ -179,6 +172,7 @@ public class LoggerLoader implements SyncopeLoader {
             final LoggerContext ctx,
             final AuditAppender auditAppender,
             final LoggerConfig eventLogConf) {
+
         Appender targetAppender = ctx.getConfiguration().getAppender(auditAppender.getTargetAppenderName());
         if (targetAppender == null) {
             targetAppender = auditAppender.getTargetAppender();

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/AuditManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/AuditManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/AuditManagerImpl.java
index 760a9fa..6b32cbb 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/AuditManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/AuditManagerImpl.java
@@ -23,7 +23,6 @@ import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditElements.Result;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.common.lib.types.LoggerLevel;
-import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
@@ -41,14 +40,6 @@ public class AuditManagerImpl implements AuditManager {
     @Autowired
     private LoggerDAO loggerDAO;
 
-    public static String getDomainAuditLoggerName(final String domain) {
-        return LoggerType.AUDIT.getPrefix() + "." + domain;
-    }
-
-    public static String getDomainAuditEventLoggerName(final String domain, final String loggerName) {
-        return domain + "." + loggerName;
-    }
-
     @Override
     public boolean auditRequested(
             final AuditElements.EventCategoryType type,
@@ -121,9 +112,10 @@ public class AuditManagerImpl implements AuditManager {
         org.apache.syncope.core.persistence.api.entity.Logger syncopeLogger =
                 loggerDAO.find(auditEntry.getLogger().toLoggerName());
         if (syncopeLogger != null && syncopeLogger.getLevel() == LoggerLevel.DEBUG) {
-            Logger logger = LoggerFactory.getLogger(getDomainAuditLoggerName(AuthContextUtils.getDomain()));
-            Logger eventLogger = LoggerFactory.getLogger(getDomainAuditEventLoggerName(AuthContextUtils.getDomain(),
-                    syncopeLogger.getKey()));
+            Logger logger = LoggerFactory.getLogger(
+                    AuditLoggerName.getAuditLoggerName(AuthContextUtils.getDomain()));
+            Logger eventLogger = LoggerFactory.getLogger(
+                    AuditLoggerName.getAuditEventLoggerName(AuthContextUtils.getDomain(), syncopeLogger.getKey()));
             String serializedAuditEntry = POJOHelper.serialize(auditEntry);
             if (throwable == null) {
                 logger.debug(serializedAuditEntry);

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/SyslogRewriteAuditAppender.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/SyslogRewriteAuditAppender.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/SyslogRewriteAuditAppender.java
index 9a192df..0efc767 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/SyslogRewriteAuditAppender.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/SyslogRewriteAuditAppender.java
@@ -27,7 +27,7 @@ import org.apache.logging.log4j.core.net.Protocol;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.core.logic.ConnectorLogic;
-import org.apache.syncope.core.logic.DefaultRewriteAuditAppender;
+import org.apache.syncope.core.logic.audit.DefaultRewriteAuditAppender;
 import org.apache.syncope.core.logic.ResourceLogic;
 
 public class SyslogRewriteAuditAppender extends DefaultRewriteAuditAppender {

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileAuditAppender.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileAuditAppender.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileAuditAppender.java
index cffc8f7..8942a5c 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileAuditAppender.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileAuditAppender.java
@@ -30,7 +30,7 @@ import org.apache.logging.log4j.core.layout.PatternLayout;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.core.logic.ConnectorLogic;
-import org.apache.syncope.core.logic.DefaultAuditAppender;
+import org.apache.syncope.core.logic.audit.DefaultAuditAppender;
 import org.apache.syncope.core.logic.ResourceLogic;
 
 public class TestFileAuditAppender extends DefaultAuditAppender {

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileRewriteAuditAppender.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileRewriteAuditAppender.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileRewriteAuditAppender.java
index 932ce56..83af712 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileRewriteAuditAppender.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileRewriteAuditAppender.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.fit.core.reference;
 
-import java.io.File;
 import java.util.HashSet;
 import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
@@ -30,7 +29,7 @@ import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
 import org.apache.logging.log4j.core.layout.PatternLayout;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.core.logic.DefaultRewriteAuditAppender;
+import org.apache.syncope.core.logic.audit.DefaultRewriteAuditAppender;
 import org.apache.syncope.core.logic.ResourceLogic;
 
 public class TestFileRewriteAuditAppender extends DefaultRewriteAuditAppender {
@@ -51,20 +50,17 @@ public class TestFileRewriteAuditAppender extends DefaultRewriteAuditAppender {
     @Override
     public void initTargetAppender() {
         LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+
         // get log file path from existing file appender
         RollingRandomAccessFileAppender mainFile =
                 (RollingRandomAccessFileAppender) ctx.getConfiguration().getAppender("mainFile");
+        String pathPrefix = StringUtils.replace(mainFile.getFileName(), "core.log", StringUtils.EMPTY);
 
-        String pathPrefix = mainFile == null
-                ? System.getProperty("user.dir") + StringUtils.replace("/target/log", "/", File.separator)
-                + File.separator
-                : StringUtils.replace(mainFile.getFileName(), "core.log", StringUtils.EMPTY);
-
-        targetAppender = FileAppender.newBuilder()
-                .withName(getTargetAppenderName())
-                .withAppend(true)
-                .withFileName(pathPrefix + getTargetAppenderName() + ".log")
-                .withLayout(
+        targetAppender = FileAppender.newBuilder().
+                withName(getTargetAppenderName()).
+                withAppend(true).
+                withFileName(pathPrefix + getTargetAppenderName() + ".log").
+                withLayout(
                         PatternLayout.newBuilder()
                                 .withPattern("%d{HH:mm:ss.SSS} %-5level %logger - %msg%n")
                                 .build())

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
index 9bc6ed6..0f7253e 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
@@ -27,6 +27,7 @@ import static org.junit.Assert.fail;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.Charset;
 import java.text.ParseException;
 import java.util.List;
 import java.util.Properties;
@@ -59,7 +60,6 @@ import org.apache.syncope.core.logic.ResourceLogic;
 import org.apache.syncope.core.logic.GroupLogic;
 import org.apache.syncope.core.logic.UserLogic;
 import org.apache.syncope.fit.AbstractITCase;
-import org.junit.Assert;
 import org.junit.Test;
 
 public class LoggerITCase extends AbstractITCase {
@@ -256,45 +256,17 @@ public class LoggerITCase extends AbstractITCase {
     }
 
     @Test
-    public void issueSYNCOPE708() {
-        try {
-            loggerService.read(LoggerType.LOG, "notExists");
-            fail("Reading non-existing logger, it should go in exception");
-        } catch (final WebServiceException ex) {
-            fail("Exception is WebServiceException but it should be SyncopeClientException");
-        } catch (final SyncopeClientException ex) {
-            assertEquals(Response.Status.NOT_FOUND, ex.getType().getResponseStatus());
-        }
-    }
-
-    @Test
-    public void issueSYNCOPE976() {
-        List<EventCategoryTO> events = loggerService.events();
-        assertNotNull(events);
-
-        EventCategoryTO userLogic = IterableUtils.find(events, new Predicate<EventCategoryTO>() {
-
-            @Override
-            public boolean evaluate(final EventCategoryTO object) {
-                return "UserLogic".equals(object.getCategory());
-            }
-        });
-        assertNotNull(userLogic);
-        assertEquals(1, IterableUtils.frequency(userLogic.getEvents(), "create"));
-    }
-
-    @Test
-    public void testCustomAuditAppender() throws IOException, InterruptedException {
+    public void customAuditAppender() throws IOException, InterruptedException {
         InputStream propStream = null;
         try {
             Properties props = new Properties();
             propStream = getClass().getResourceAsStream("/core-test.properties");
             props.load(propStream);
 
-            final String auditFilePath = props.getProperty("test.log.dir") + File.separator
-                    + "audit_for_Master_file.log";
-            final String auditNoRewriteFilePath = props.getProperty("test.log.dir") + File.separator
-                    + "audit_for_Master_norewrite_file.log";
+            String auditFilePath = props.getProperty("test.log.dir")
+                    + File.separator + "audit_for_Master_file.log";
+            String auditNoRewriteFilePath = props.getProperty("test.log.dir")
+                    + File.separator + "audit_for_Master_norewrite_file.log";
             // 1. Enable audit for resource update -> catched by FileRewriteAuditAppender
             AuditLoggerName auditLoggerResUpd = new AuditLoggerName(
                     EventCategoryType.LOGIC,
@@ -307,6 +279,7 @@ public class LoggerITCase extends AbstractITCase {
             loggerTOUpd.setKey(auditLoggerResUpd.toLoggerName());
             loggerTOUpd.setLevel(LoggerLevel.DEBUG);
             loggerService.update(LoggerType.AUDIT, loggerTOUpd);
+
             // 2. Enable audit for connector update -> NOT catched by FileRewriteAuditAppender
             AuditLoggerName auditLoggerConnUpd = new AuditLoggerName(
                     EventCategoryType.LOGIC,
@@ -333,21 +306,21 @@ public class LoggerITCase extends AbstractITCase {
 
             File auditTempFile = new File(auditFilePath);
             // check audit_for_Master_file.log, it should contain only a static message
-            String auditLog = FileUtils.readFileToString(auditTempFile, "UTF-8");
+            String auditLog = FileUtils.readFileToString(auditTempFile, Charset.defaultCharset());
 
-            Assert.assertTrue(StringUtils.contains(auditLog,
+            assertTrue(StringUtils.contains(auditLog,
                     "DEBUG Master.syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]"
                     + " - This is a static test message"));
             File auditNoRewriteTempFile = new File(auditNoRewriteFilePath);
             // check audit_for_Master_file.log, it should contain only a static message
-            String auditLogNoRewrite = FileUtils.readFileToString(auditNoRewriteTempFile, "UTF-8");
+            String auditLogNoRewrite = FileUtils.readFileToString(auditNoRewriteTempFile, Charset.defaultCharset());
 
-            Assert.assertFalse(StringUtils.contains(auditLogNoRewrite,
+            assertFalse(StringUtils.contains(auditLogNoRewrite,
                     "DEBUG Master.syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]"
                     + " - This is a static test message"));
 
             // clean audit_for_Master_file.log
-            FileUtils.writeStringToFile(auditTempFile, StringUtils.EMPTY, "UTF-8");
+            FileUtils.writeStringToFile(auditTempFile, StringUtils.EMPTY, Charset.defaultCharset());
             loggerService.delete(LoggerType.AUDIT, "syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]");
 
             resource = resourceService.read(RESOURCE_NAME_CSV);
@@ -356,11 +329,39 @@ public class LoggerITCase extends AbstractITCase {
             resourceService.update(resource);
 
             // check that nothing has been written to audit_for_Master_file.log
-            assertTrue(StringUtils.isEmpty(FileUtils.readFileToString(auditTempFile, "UTF-8")));
+            assertTrue(StringUtils.isEmpty(FileUtils.readFileToString(auditTempFile, Charset.defaultCharset())));
         } catch (IOException e) {
             fail("Unable to read/write log files" + e.getMessage());
         } finally {
             IOUtils.closeQuietly(propStream);
         }
     }
+
+    @Test
+    public void issueSYNCOPE708() {
+        try {
+            loggerService.read(LoggerType.LOG, "notExists");
+            fail("Reading non-existing logger, it should go in exception");
+        } catch (final WebServiceException ex) {
+            fail("Exception is WebServiceException but it should be SyncopeClientException");
+        } catch (final SyncopeClientException ex) {
+            assertEquals(Response.Status.NOT_FOUND, ex.getType().getResponseStatus());
+        }
+    }
+
+    @Test
+    public void issueSYNCOPE976() {
+        List<EventCategoryTO> events = loggerService.events();
+        assertNotNull(events);
+
+        EventCategoryTO userLogic = IterableUtils.find(events, new Predicate<EventCategoryTO>() {
+
+            @Override
+            public boolean evaluate(final EventCategoryTO object) {
+                return "UserLogic".equals(object.getCategory());
+            }
+        });
+        assertNotNull(userLogic);
+        assertEquals(1, IterableUtils.frequency(userLogic.getEvents(), "create"));
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/src/main/asciidoc/reference-guide/concepts/audit.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/reference-guide/concepts/audit.adoc b/src/main/asciidoc/reference-guide/concepts/audit.adoc
index 78c38d3..d774594 100644
--- a/src/main/asciidoc/reference-guide/concepts/audit.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/audit.adoc
@@ -19,8 +19,8 @@
 === Audit
 
 The audit feature allows to capture <<audit-events,events>> occurring within the <<core>> and to log relevant information
-about them. By default events are logged as entries into the `SYNCOPEAUDIT` table of the internal storage,
-but can also be logged on some additional Log4j2 appenders defined through simple customization mechanisms.
+about them. +
+By default, events are logged as entries into the `SYNCOPEAUDIT` table of the internal storage.
 
 Once events are reported, they can be used as input for external tools.
 
@@ -34,47 +34,48 @@ An example of how audit entries can be extracted for reporting is shown by the <
 The information provided for <<notification-events,notification events>> is also valid for audit events, including examples -
 except for the admin console <<console-configuration-audit,tooling>>, which is naturally distinct.
 
-==== Audit Customization
+==== Audit Appenders
 
-As mentioned above, events are, basically, logged in a database table, but this behavior can be extended through 
-`AuditAppender` interface implementation which allows an user to define additional logging supports that we address 
-as appenders.
+In addition to insertions into the `SYNCOPEAUDIT` table, events are also available for custom handling via Audit
+Appenders, based on https://logging.apache.org/log4j/2.x/manual/appenders.html[Apache Log4j 2 Appenders^]. +
+This allows to empower the available implementations or to write new ones in order to route audit messages, with optional
+transformation (rewrite), to files, queues, sockets, syslog, etc.
 
-Appender is a Log4j entity that allows to write whatever log message on different destinations (file, queues, syslog, 
-other appenders, etc.). Moreover it provides the ability to edit (rewrite) the message, that is flowing through appenders,
-in order to customize information.
-Audit customization relies on Log4j appenders. To implement a custom audit appender an user just needs to extend to basic 
-classes:
+Custom implementations must follow the
+ifeval::["{snapshotOrRelease}" == "release"]
+https://github.com/apache/syncope/blob/syncope-{docVersion}/core/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditAppender.java[AuditAppender^]
+endif::[]
+ifeval::["{snapshotOrRelease}" == "snapshot"]
+https://github.com/apache/syncope/blob/2_0_X/core/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditAppender.java[AuditAppender^]
+endif::[]
+interface.
 
-. DefaultAuditAppender
-. DefaultRewriteAuditAppender
+Some convenience implementations are provided, meant to serve as reference - see table below.
 
-The first is intended to add custom appender without any rewrtining of the message, the second allows message rewriting.
+[cols="1,2"]
+|===
 
-What is needed to implement a well formed appender:
- 
-. Events: a set of events to which the appender is bound. Appender will log only if one of those events occurs.
-. Target Appender: the Log4j appender that writes message somewhere. See 
-  https://github.com/andrea-patricelli/syncope/blob/2_0_X/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileRewriteAuditAppender.java[TestFileRewriteAuditAppender^] or 
-  https://github.com/andrea-patricelli/syncope/blob/2_0_X/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestFileAuditAppender.java[TestFileAuditAppender^].
-. Rewrite policy (if needed): in case of rewrite enabled a rewrite policy should be defined, by implementing Log4j 
-  `RewritePolicy` interface. Some examples are 
-  https://github.com/andrea-patricelli/syncope/blob/2_0_X/core/logic/src/main/java/org/apache/syncope/core/logic/PassThroughRewritePolicy.java[PassThroughRewritePolicy^] 
-  and https://github.com/andrea-patricelli/syncope/blob/2_0_X/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestRewritePolicy.java[TestRewritePolicy^].
-  If no rewrite policy is specified `PassThroughRewritePolicy` will be used.
+| 
+ifeval::["{snapshotOrRelease}" == "release"]
+https://github.com/apache/syncope/blob/syncope-{docVersion}/core/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java[DefaultAuditAppender^]
+endif::[]
+ifeval::["{snapshotOrRelease}" == "snapshot"]
+https://github.com/apache/syncope/blob/2_0_X/core/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultAuditAppender.java[DefaultAuditAppender^]
+endif::[]
+| This requires to specify (a) a set of events to which the appender is bound (log only if one of such events occurs)
+and (b) a target appender, e.g. one of https://logging.apache.org/log4j/2.x/manual/appenders.html[Apache Log4j 2 Appenders^]
+or a custom implementation.
 
-[TIP]
-====
-Be careful while assigning names to the appenders. The name of the target appender should be unique and should depend on
-the domain. 
-A best practice is to assign different names to the appenders in order to avoid names collisions and strange behavior of
-the logging framework.
-====
-
-===== How custom appenders work
+| 
+ifeval::["{snapshotOrRelease}" == "release"]
+https://github.com/apache/syncope/blob/syncope-{docVersion}/core/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultRewriteAuditAppender.java[DefaultRewriteAuditAppender^]
+endif::[]
+ifeval::["{snapshotOrRelease}" == "snapshot"]
+https://github.com/apache/syncope/blob/2_0_X/core/logic/src/main/java/org/apache/syncope/core/logic/audit/DefaultRewriteAuditAppender.java[DefaultRewriteAuditAppender^]
+endif::[]
+| In addition, this requires to provide a
+https://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/appender/rewrite/RewritePolicy.html[RewritePolicy^] 
+implementation, which allows to rewrite the original audit message into something more suitable to the target
+destination.
 
-An appender is bound to specific events. While enabling audit on some event, if that event is "catched" also by the custom
-appender, it automatically activates. Once the audit is enabled the same audit message will be logged by the 
-default audit appender and all the extensions bound to those events. While disabling audit all audit extensions are 
-disabled.
-To enable an audit extension an user just needs to implement his custom `AuditAppender` in the sources, build application and deploy.
\ No newline at end of file
+|===

http://git-wip-us.apache.org/repos/asf/syncope/blob/cb57c5ad/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc b/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc
index c166583..5a115e4 100644
--- a/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc
+++ b/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc
@@ -193,6 +193,7 @@ Besides replacing existing classes as explained <<override-behavior,above>>, new
 * <<provisioning-managers,provisioning managers>>
 * <<notifications,notification recipient providers>>
 * <<jwtssoprovider,JWT SSO providers>>
+* <<audit-appenders, audit appenders>>
 
 [[new-rest-endpoints]]
 [TIP]
@@ -691,9 +692,3 @@ Moreover, `defaultValues` do not overwrite any existing value.
 For example, the http://www.chorevolution.eu/[CHOReVOLUTION^] IdM - based on Apache Syncope - provides
 https://gitlab.ow2.org/chorevolution/syncope/tree/master/ext/choreography[an extension^]
 for managing via the <<core>> and visualizing via the <<admin-console-component>> the running choreography instances.
-
-[[audit-customization]]
-==== Audit Extensions
-
-<<audit>> by default, if enabled, logs on a specific database table, though this functionality could be extended to log 
-also on different supports (file, queue, syslog, etc.).