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 2021/07/17 06:30:40 UTC

[syncope] branch master updated: [SYNCOPE-1615] Loggers actuator for all components (#278)

This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/master by this push:
     new 74a626c  [SYNCOPE-1615] Loggers actuator for all components (#278)
74a626c is described below

commit 74a626cf4b860b947c21e88d9d0983b79e34d126
Author: Francesco Chicchiriccò <il...@users.noreply.github.com>
AuthorDate: Sat Jul 17 08:30:29 2021 +0200

    [SYNCOPE-1615] Loggers actuator for all components (#278)
---
 .../ConnObjectListViewPanel_fr_CA.properties       |   0
 .../console/panels/ConnObjects_fr_CA.properties    |   0
 .../client/console/audit/AuditHistoryDetails.java  |   2 +-
 .../console/audit/AuditHistoryDirectoryPanel.java  |   8 +-
 .../client/console/events/EventCategoryPanel.java  |   2 +-
 .../client/console/events/EventSelectionPanel.java |   2 +-
 .../notifications/NotificationWizardBuilder.java   |   4 +-
 .../apache/syncope/client/console/pages/Audit.java |  14 +-
 .../syncope/client/console/pages/BasePage.java     |   2 +-
 .../syncope/client/console/pages/LogViewer.java    | 137 ------
 .../apache/syncope/client/console/pages/Logs.java  | 100 +++-
 .../client/console/panels/AbstractLogsPanel.java   | 112 -----
 .../client/console/panels/ConsoleLogPanel.java     |  78 ----
 .../client/console/panels/CoreLogPanel.java        |  44 --
 .../client/console/panels/LogStatementPanel.java   |  92 ----
 .../syncope/client/console/panels/LogsPanel.java   | 193 ++++++++
 .../client/console/panels/SchemaTypePanel.java     |   2 +-
 ...{LoggerRestClient.java => AuditRestClient.java} |  82 ++--
 .../syncope/client/console/rest/LoggerConf.java    |  34 +-
 .../syncope/client/console/rest/LoggerConfOp.java  |  20 +-
 .../client/console/rest/LoggerConfRestClient.java  | 124 +++++
 .../syncope/client/console/pages/LogViewer.html    |  34 --
 .../client/console/panels/ConsoleLogPanel.html     |  27 --
 .../console/panels/ConsoleLogPanel.properties      |  18 -
 .../panels/ConsoleLogPanel_fr_CA.properties        |  18 -
 .../client/console/panels/CoreLogPanel.properties  |  18 -
 .../console/panels/CoreLogPanel_it.properties      |  18 -
 .../console/panels/CoreLogPanel_ja.properties      |  18 -
 .../console/panels/CoreLogPanel_ru.properties      |  21 -
 .../panels/{CoreLogPanel.html => LogsPanel.html}   |  18 +-
 ...Panel_pt_BR.properties => LogsPanel.properties} |   1 +
 ...fr_CA.properties => LogsPanel_fr_CA.properties} |   3 +-
 ...Panel_it.properties => LogsPanel_it.properties} |   1 +
 ...Panel_ja.properties => LogsPanel_ja.properties} |   1 +
 ...pt_BR.properties => LogsPanel_pt_BR.properties} |   1 +
 ...Panel_ru.properties => LogsPanel_ru.properties} |   5 +-
 common/idrepo/lib/pom.xml                          |   4 -
 .../common/lib/{log => audit}/AuditEntry.java      |   2 +-
 .../common/lib/{log => audit}/EventCategory.java   |   2 +-
 .../syncope/common/lib/log/LogStatement.java       | 107 -----
 .../apache/syncope/common/lib/log/LoggerTO.java    |  77 ---
 .../LoggerLevel.java => to/AuditConfTO.java}       |  38 +-
 .../syncope/common/lib/types/AuditLoggerName.java  |  23 +-
 .../common/lib/types/IdRepoEntitlement.java        |  18 +-
 .../syncope/common/lib/SerializationTest.java      |   8 +-
 .../syncope/common/rest/api/LoggerWrapper.java     |  55 ---
 .../{LoggerService.java => AuditService.java}      | 127 +++--
 .../logic/{LoggerLogic.java => AuditLogic.java}    | 278 +++--------
 .../apache/syncope/core/logic/MemoryAppender.java  |  96 ----
 .../core/logic/audit/JdbcAuditAppender.java        |   6 +-
 .../syncope/core/logic/init/AuditAccessor.java     |  60 +++
 .../init/{LoggerLoader.java => AuditLoader.java}   |  22 +-
 .../syncope/core/logic/init/LoggerAccessor.java    |  98 ----
 .../core/rest/cxf/service/AuditServiceImpl.java    |  89 ++++
 .../core/rest/cxf/service/LoggerServiceImpl.java   | 150 ------
 .../api/dao/{LoggerDAO.java => AuditConfDAO.java}  |  25 +-
 .../api/entity/{Logger.java => AuditConf.java}     |  15 +-
 .../jpa/dao/AbstractJPAJSONLoggerDAO.java          |   2 +-
 ...ONLoggerDAO.java => MyJPAJSONAuditConfDAO.java} |  14 +-
 ...ONLoggerDAO.java => PGJPAJSONAuditConfDAO.java} |  16 +-
 .../src/main/resources/audit/audit_myjson.sql      |   2 +-
 .../src/main/resources/audit/audit_pgjsonb.sql     |   4 +-
 .../main/resources/myjson/persistence.properties   |   2 +-
 .../main/resources/pgjsonb/persistence.properties  |   2 +-
 .../src/test/resources/domains/MasterContent.xml   |  88 ++--
 .../core/persistence/jpa/PersistenceContext.java   |   8 +-
 .../jpa/content/XMLContentExporter.java            |   6 +-
 .../{JPALoggerDAO.java => JPAAuditConfDAO.java}    |  67 +--
 .../core/persistence/jpa/entity/JPAAuditConf.java  |  37 +-
 .../persistence/jpa/entity/JPAEntityFactory.java   |   6 +-
 .../core/persistence/jpa/entity/JPALogger.java     |  80 ----
 .../src/main/resources/audit/audit.sql             |   2 +-
 .../src/main/resources/audit/audit_mariadb.sql     |   2 +-
 .../main/resources/audit/audit_mysql_innodb.sql    |   2 +-
 .../src/main/resources/audit/audit_oracle.sql      |   2 +-
 .../src/main/resources/audit/audit_sqlserver.sql   |   6 +-
 .../src/main/resources/persistence.properties      |   2 +-
 .../core/persistence/jpa/inner/RoleTest.java       |   9 +-
 .../core/persistence/jpa/outer/AnySearchTest.java  |   4 +-
 .../core/persistence/jpa/outer/RoleTest.java       |   8 +-
 .../src/test/resources/domains/MasterContent.xml   |  86 ++--
 ...{LoggerDataBinder.java => AuditDataBinder.java} |  11 +-
 .../provisioning/java/DefaultAuditManager.java     |  24 +-
 .../java/data/AuditDataBinderImpl.java             |  37 +-
 .../java/data/LoggerDataBinderImpl.java            |  46 --
 .../java/job/report/AuditReportlet.java            |  10 +-
 docker/core/src/main/resources/log4j2.xml          |  40 --
 .../src/main/resources/persistence.properties.all  |   2 +-
 .../main/resources/persistence.properties.myjson   |   2 +-
 .../main/resources/persistence.properties.pgjsonb  |   2 +-
 .../src/main/resources/persistence.properties      |   2 +-
 .../fit/core/reference/TestFileAuditAppender.java  |   8 +-
 .../reference/TestFileRewriteAuditAppender.java    |   6 +-
 .../resources/elasticsearch/persistence.properties |   2 +-
 fit/core-reference/src/main/resources/log4j2.xml   |  48 +-
 .../org/apache/syncope/fit/AbstractITCase.java     |  10 +-
 .../syncope/fit/console/AbstractConsoleITCase.java |   7 +
 .../org/apache/syncope/fit/console/LogsITCase.java |  42 +-
 .../org/apache/syncope/fit/core/AuditITCase.java   | 350 +++++++++++++-
 .../apache/syncope/fit/core/DelegationITCase.java  |  18 +-
 .../org/apache/syncope/fit/core/LoggerITCase.java  | 517 ---------------------
 .../syncope/fit/core/MultitenancyITCase.java       |  15 -
 .../org/apache/syncope/fit/core/ReportITCase.java  |  13 +-
 .../org/apache/syncope/fit/core/RoleITCase.java    |   8 +-
 pom.xml                                            |   5 -
 .../asciidoc/reference-guide/concepts/audit.adoc   |   4 +-
 .../systemadministration/dbms.adoc                 |   4 +-
 .../starter/audit/SyncopeWAAuditTrailManager.java  |  23 +-
 .../starter/events/SyncopeWAEventRepository.java   |  16 +-
 .../audit/SyncopeWAAuditTrailManagerTest.java      |  10 +-
 .../events/SyncopeWAEventRepositoryTest.java       |  12 +-
 111 files changed, 1497 insertions(+), 2808 deletions(-)

diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConnObjectListViewPanel_fr_CA.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/panels/ConnObjectListViewPanel_fr_CA.properties
similarity index 100%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConnObjectListViewPanel_fr_CA.properties
rename to client/idm/console/src/main/resources/org/apache/syncope/client/console/panels/ConnObjectListViewPanel_fr_CA.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConnObjects_fr_CA.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/panels/ConnObjects_fr_CA.properties
similarity index 100%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConnObjects_fr_CA.properties
rename to client/idm/console/src/main/resources/org/apache/syncope/client/console/panels/ConnObjects_fr_CA.properties
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
index 11cc048..47fae01 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
@@ -25,7 +25,7 @@ import java.util.Date;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.JsonDiffPanel;
-import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.UserTO;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDirectoryPanel.java
index c0c5703..a12ee8f 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDirectoryPanel.java
@@ -27,14 +27,14 @@ import org.apache.syncope.client.console.commons.IdRepoConstants;
 import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
-import org.apache.syncope.client.console.rest.LoggerRestClient;
+import org.apache.syncope.client.console.rest.AuditRestClient;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
 import org.apache.syncope.client.ui.commons.DirectoryDataProvider;
 import org.apache.syncope.client.ui.commons.panels.ModalPanel;
-import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
@@ -49,7 +49,7 @@ import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.StringResourceModel;
 
 public abstract class AuditHistoryDirectoryPanel<T extends Serializable> extends DirectoryPanel<
-        AuditEntry, AuditEntry, AuditHistoryDirectoryPanel<T>.AuditHistoryProvider, LoggerRestClient>
+        AuditEntry, AuditEntry, AuditHistoryDirectoryPanel<T>.AuditHistoryProvider, AuditRestClient>
         implements ModalPanel {
 
     private static final long serialVersionUID = -8248734710505211261L;
@@ -90,7 +90,7 @@ public abstract class AuditHistoryDirectoryPanel<T extends Serializable> extends
         this.auditRestoreEntitlement = auditRestoreEntitlement;
         this.pageRef = pageRef;
 
-        this.restClient = new LoggerRestClient();
+        this.restClient = new AuditRestClient();
         initResultTable();
     }
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventCategoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventCategoryPanel.java
index 8f64ac9..9d86c1a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventCategoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventCategoryPanel.java
@@ -33,7 +33,7 @@ import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
 import org.apache.syncope.client.ui.commons.Constants;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.common.lib.log.EventCategory;
+import org.apache.syncope.common.lib.audit.EventCategory;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditElements.EventCategoryType;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventSelectionPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventSelectionPanel.java
index 1d78eee..83ff337 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventSelectionPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/events/EventSelectionPanel.java
@@ -24,7 +24,7 @@ import java.util.List;
 import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormChoiceComponentUpdatingBehavior;
-import org.apache.syncope.common.lib.log.EventCategory;
+import org.apache.syncope.common.lib.audit.EventCategory;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.wicket.ajax.AjaxRequestTarget;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
index ae38a10..acca0ac 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
@@ -34,7 +34,7 @@ import org.apache.syncope.client.console.panels.search.SearchClause;
 import org.apache.syncope.client.console.panels.search.UserSearchPanel;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
-import org.apache.syncope.client.console.rest.LoggerRestClient;
+import org.apache.syncope.client.console.rest.AuditRestClient;
 import org.apache.syncope.client.console.rest.NotificationRestClient;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
@@ -165,7 +165,7 @@ public class NotificationWizardBuilder extends BaseAjaxWizardBuilder<Notificatio
 
             add(new EventCategoryPanel(
                     "eventSelection",
-                    LoggerRestClient.listEvents(),
+                    AuditRestClient.listEvents(),
                     new PropertyModel<List<String>>(modelObject.getInnerObject(), "events")) {
 
                 private static final long serialVersionUID = 6429053774964787735L;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Audit.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Audit.java
index 71c5446..0184357 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Audit.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Audit.java
@@ -25,8 +25,8 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
 import org.apache.syncope.client.console.events.EventCategoryPanel;
 import org.apache.syncope.client.console.events.SelectedEventsPanel;
-import org.apache.syncope.client.console.rest.LoggerRestClient;
-import org.apache.syncope.common.lib.log.EventCategory;
+import org.apache.syncope.client.console.rest.AuditRestClient;
+import org.apache.syncope.common.lib.audit.EventCategory;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
@@ -45,7 +45,7 @@ public class Audit extends BasePage {
 
         body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", Dashboard.class));
 
-        List<String> events = LoggerRestClient.listAudits().stream().
+        List<String> events = AuditRestClient.list().stream().
                 map(audit -> AuditLoggerName.buildEvent(
                 audit.getType(),
                 audit.getCategory(),
@@ -62,7 +62,7 @@ public class Audit extends BasePage {
 
         form.add(new EventCategoryPanel(
                 "auditPanel",
-                LoggerRestClient.listEvents(),
+                AuditRestClient.listEvents(),
                 new ListModel<>(events)) {
 
             private static final long serialVersionUID = 6113164334533550277L;
@@ -74,7 +74,7 @@ public class Audit extends BasePage {
 
             @Override
             protected List<String> getChangeAuthRoles() {
-                return List.of(IdRepoEntitlement.AUDIT_ENABLE, IdRepoEntitlement.AUDIT_DISABLE);
+                return List.of(IdRepoEntitlement.AUDIT_UPDATE);
             }
 
             @Override
@@ -95,7 +95,7 @@ public class Audit extends BasePage {
                                 ? null : eventCategory.getKey().getEvents().iterator().next(),
                                 eventCategory.getValue());
 
-                        LoggerRestClient.disableAudit(auditLoggerName);
+                        AuditRestClient.disableAudit(auditLoggerName);
                     });
 
                     eventSelectionChanged.getToBeAdded().forEach(toBeAdded -> {
@@ -110,7 +110,7 @@ public class Audit extends BasePage {
                                 ? null : eventCategory.getKey().getEvents().iterator().next(),
                                 eventCategory.getValue());
 
-                        LoggerRestClient.enableAudit(auditLoggerName);
+                        AuditRestClient.enableAudit(auditLoggerName);
                     });
                 }
             }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
index 94451e8..0dfdd98 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
@@ -290,7 +290,7 @@ public class BasePage extends BaseWebPage {
         liContainer = new WebMarkupContainer(getLIContainerId("logs"));
         confULContainer.add(liContainer);
         link = BookmarkablePageLinkBuilder.build("logs", Logs.class);
-        MetaDataRoleAuthorizationStrategy.authorize(link, WebPage.RENDER, IdRepoEntitlement.LOG_LIST);
+        MetaDataRoleAuthorizationStrategy.authorize(link, WebPage.RENDER, IdRepoEntitlement.LOGGER_LIST);
         liContainer.add(link);
 
         liContainer = new WebMarkupContainer(getLIContainerId("types"));
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/LogViewer.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/LogViewer.java
deleted file mode 100644
index 5f59e98..0000000
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/LogViewer.java
+++ /dev/null
@@ -1,137 +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.client.console.pages;
-
-import java.time.Duration;
-import java.time.temporal.ChronoUnit;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.commons.collections4.list.SetUniqueList;
-import org.apache.syncope.client.console.panels.LogStatementPanel;
-import org.apache.syncope.client.console.rest.LoggerRestClient;
-import org.apache.syncope.client.ui.commons.Constants;
-import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.common.lib.log.LogStatement;
-import org.apache.syncope.common.lib.types.IdRepoEntitlement;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.AjaxSelfUpdatingTimerBehavior;
-import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
-import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.WebPage;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.util.ListModel;
-
-public class LogViewer extends WebPage {
-
-    private static final int MAX_STATEMENTS_PER_APPENDER = 50;
-
-    private static final long serialVersionUID = -7578329899052708105L;
-
-    public LogViewer() {
-        WebMarkupContainer viewer = new WebMarkupContainer("viewer");
-        viewer.setOutputMarkupId(true);
-        add(viewer);
-
-        AjaxDropDownChoicePanel<String> appenders = new AjaxDropDownChoicePanel<>(
-                "appenders", "Appender", new Model<>(), false);
-        MetaDataRoleAuthorizationStrategy.authorize(appenders, ENABLE, IdRepoEntitlement.LOG_READ);
-        appenders.setChoices(LoggerRestClient.listMemoryAppenders());
-        viewer.add(appenders);
-
-        WebMarkupContainer stContainer = new WebMarkupContainer("stContainer");
-        stContainer.setOutputMarkupId(true);
-        viewer.add(stContainer);
-
-        Model<Long> lastTimeInMillis = Model.of(0L);
-        IModel<List<LogStatement>> statementViewModel = new ListModel<>(new ArrayList<>());
-        ListView<LogStatement> statementView = new ListView<LogStatement>("statements", statementViewModel) {
-
-            private static final long serialVersionUID = -9180479401817023838L;
-
-            @Override
-            protected void populateItem(final ListItem<LogStatement> item) {
-                LogStatementPanel panel = new LogStatementPanel("statement", item.getModelObject());
-                panel.setOutputMarkupId(true);
-                item.add(panel);
-            }
-        };
-        statementView.setOutputMarkupId(true);
-        stContainer.add(statementView);
-        stContainer.add(new AjaxSelfUpdatingTimerBehavior(Duration.of(10, ChronoUnit.SECONDS)) {
-
-            private static final long serialVersionUID = 7298597675929755960L;
-
-            @Override
-            protected void onPostProcessTarget(final AjaxRequestTarget target) {
-                // save scroll position
-                target.prependJavaScript(
-                        String.format("window.scrollTop = $('#%s').scrollTop();", stContainer.getMarkupId()));
-
-                List<LogStatement> recentLogStatements = appenders.getModelObject() == null
-                        ? new ArrayList<>()
-                        : LoggerRestClient.getLastLogStatements(appenders.getModelObject(),
-                    lastTimeInMillis.getObject());
-                if (!recentLogStatements.isEmpty()) {
-                    lastTimeInMillis.setObject(recentLogStatements.get(recentLogStatements.size() - 1).getTimeMillis());
-
-                    int currentSize = statementView.getModelObject().size();
-                    int recentSize = recentLogStatements.size();
-
-                    List<LogStatement> newModelObject = SetUniqueList.<LogStatement>setUniqueList(
-                            new ArrayList<>(MAX_STATEMENTS_PER_APPENDER));
-                    if (currentSize <= MAX_STATEMENTS_PER_APPENDER - recentSize) {
-                        newModelObject.addAll(statementView.getModelObject());
-                    } else {
-                        newModelObject.addAll(statementView.getModelObject().
-                                subList(currentSize - (MAX_STATEMENTS_PER_APPENDER - recentSize), currentSize));
-                    }
-                    newModelObject.addAll(recentLogStatements);
-
-                    statementViewModel.setObject(newModelObject);
-                    target.add(stContainer);
-
-                }
-
-                // restore scroll position - might not work perfectly if items were removed from the top
-                target.appendJavaScript(
-                        String.format("$('#%s').scrollTop(window.scrollTop);", stContainer.getMarkupId()));
-            }
-        });
-
-        appenders.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-            private static final long serialVersionUID = -1107858522700306810L;
-
-            @Override
-            protected void onUpdate(final AjaxRequestTarget target) {
-                List<LogStatement> lastStatements = appenders.getModelObject() == null
-                        ? new ArrayList<>()
-                        : LoggerRestClient.getLastLogStatements(appenders.getModelObject(), 0);
-                statementViewModel.setObject(lastStatements);
-                target.add(stContainer);
-
-                lastTimeInMillis.setObject(0L);
-            }
-        });
-    }
-}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Logs.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Logs.java
index 74fe69f..7704f00 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Logs.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Logs.java
@@ -20,21 +20,43 @@ package org.apache.syncope.client.console.pages;
 
 import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
 import java.util.List;
+import java.util.stream.Collectors;
 import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
-import org.apache.syncope.client.console.panels.ConsoleLogPanel;
-import org.apache.syncope.client.console.panels.CoreLogPanel;
+import org.apache.syncope.client.console.panels.LogsPanel;
+import org.apache.syncope.client.console.rest.LoggerConf;
+import org.apache.syncope.client.console.rest.LoggerConfOp;
+import org.apache.syncope.client.console.rest.LoggerConfRestClient;
+import org.apache.syncope.common.keymaster.client.api.DomainOps;
+import org.apache.syncope.common.keymaster.client.api.ServiceOps;
+import org.apache.syncope.common.keymaster.client.api.model.Domain;
+import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
 import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.springframework.boot.logging.LogLevel;
+import org.springframework.boot.logging.LoggerConfiguration;
+import org.springframework.boot.logging.LoggingSystem;
 
 public class Logs extends BasePage {
 
     private static final long serialVersionUID = -1100228004207271271L;
 
+    @SpringBean
+    private ServiceOps serviceOps;
+
+    @SpringBean
+    private DomainOps domainOps;
+
+    @SpringBean
+    private LoggingSystem loggingSystem;
+
     public Logs(final PageParameters parameters) {
         super(parameters);
 
@@ -46,29 +68,93 @@ public class Logs extends BasePage {
     }
 
     private List<ITab> buildTabList() {
+        List<ITab> tabs = new ArrayList<>();
 
-        final List<ITab> tabs = new ArrayList<>(2);
+        List<Domain> domains = domainOps.list();
 
-        tabs.add(new AbstractTab(new Model<>("Core")) {
+        List<NetworkService> coreInstances = serviceOps.list(NetworkService.Type.CORE);
+        tabs.add(new AbstractTab(Model.of(NetworkService.Type.CORE.name())) {
 
             private static final long serialVersionUID = -6815067322125799251L;
 
             @Override
             public Panel getPanel(final String panelId) {
-                return new CoreLogPanel(panelId, getPageReference());
+                return new LogsPanel(panelId, new LoggerConfRestClient(coreInstances, domains), getPageReference());
             }
         });
 
-        tabs.add(new AbstractTab(new Model<>("Console")) {
+        tabs.add(new AbstractTab(Model.of(NetworkService.Type.CONSOLE.name())) {
 
             private static final long serialVersionUID = -6815067322125799251L;
 
             @Override
             public Panel getPanel(final String panelId) {
-                return new ConsoleLogPanel(panelId, getPageReference());
+                return new LogsPanel(panelId, new LoggerConfOp() {
+
+                    private static final long serialVersionUID = 24740659553491L;
+
+                    @Override
+                    public List<LoggerConf> list() {
+                        Collection<LoggerConfiguration> configurations = loggingSystem.getLoggerConfigurations();
+                        if (configurations == null) {
+                            return List.of();
+                        }
+
+                        return configurations.stream().map(conf -> {
+                            LoggerConf loggerConf = new LoggerConf();
+                            loggerConf.setKey(conf.getName());
+                            loggerConf.setLevel(conf.getEffectiveLevel());
+                            return loggerConf;
+                        }).sorted(Comparator.comparing(LoggerConf::getKey)).collect(Collectors.toList());
+                    }
+
+                    @Override
+                    public void setLevel(final String key, final LogLevel level) {
+                        loggingSystem.setLogLevel(key, level);
+                    }
+                }, getPageReference());
             }
         });
 
+        List<NetworkService> euInstances = serviceOps.list(NetworkService.Type.ENDUSER);
+        if (!euInstances.isEmpty()) {
+            tabs.add(new AbstractTab(Model.of(NetworkService.Type.ENDUSER.name())) {
+
+                private static final long serialVersionUID = -6815067322125799251L;
+
+                @Override
+                public Panel getPanel(final String panelId) {
+                    return new LogsPanel(panelId, new LoggerConfRestClient(euInstances, domains), getPageReference());
+                }
+            });
+        }
+
+        List<NetworkService> waInstances = serviceOps.list(NetworkService.Type.WA);
+        if (!waInstances.isEmpty()) {
+            tabs.add(new AbstractTab(Model.of(NetworkService.Type.WA.name())) {
+
+                private static final long serialVersionUID = -6815067322125799251L;
+
+                @Override
+                public Panel getPanel(final String panelId) {
+                    return new LogsPanel(panelId, new LoggerConfRestClient(waInstances, domains), getPageReference());
+                }
+            });
+        }
+
+        List<NetworkService> sraInstances = serviceOps.list(NetworkService.Type.SRA);
+        if (!sraInstances.isEmpty()) {
+            tabs.add(new AbstractTab(Model.of(NetworkService.Type.SRA.name())) {
+
+                private static final long serialVersionUID = -6815067322125799251L;
+
+                @Override
+                public Panel getPanel(final String panelId) {
+                    return new LogsPanel(panelId, new LoggerConfRestClient(sraInstances, domains), getPageReference());
+                }
+            });
+        }
+
         return tabs;
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractLogsPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractLogsPanel.java
deleted file mode 100644
index 1a1ac60..0000000
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AbstractLogsPanel.java
+++ /dev/null
@@ -1,112 +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.client.console.panels;
-
-import java.io.Serializable;
-import java.util.List;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.ui.commons.Constants;
-import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
-import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.log.LoggerTO;
-import org.apache.syncope.common.lib.types.LoggerLevel;
-import org.apache.syncope.common.lib.types.IdRepoEntitlement;
-import org.apache.wicket.Component;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.util.ListModel;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class AbstractLogsPanel<T extends Serializable> extends Panel {
-
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractLogsPanel.class);
-
-    private static final long serialVersionUID = -6313532280206208227L;
-
-    protected WebMarkupContainer loggerContainer;
-
-    public AbstractLogsPanel(
-            final String id,
-            final PageReference pageRef,
-            final List<LoggerTO> loggerTOs) {
-
-        super(id);
-
-        loggerContainer = new WebMarkupContainer("loggerContainer");
-        loggerContainer.setOutputMarkupId(true);
-        add(loggerContainer);
-
-        ListViewPanel.Builder<LoggerTO> builder = new ListViewPanel.Builder<LoggerTO>(LoggerTO.class, pageRef) {
-
-            private static final long serialVersionUID = 6957788356709885298L;
-
-            @Override
-            protected Component getValueComponent(final String key, final LoggerTO loggerTO) {
-                if ("level".equalsIgnoreCase(key)) {
-                    AjaxDropDownChoicePanel<LoggerLevel> loggerTOs = new AjaxDropDownChoicePanel<>(
-                            "field", getString("level"), Model.of(loggerTO.getLevel()), false);
-                    MetaDataRoleAuthorizationStrategy.authorize(loggerTOs, ENABLE, IdRepoEntitlement.LOG_SET_LEVEL);
-
-                    loggerTOs.hideLabel();
-                    loggerTOs.setChoices(List.of(LoggerLevel.values()));
-                    loggerTOs.setNullValid(false);
-                    loggerTOs.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-                        private static final long serialVersionUID = -1107858522700306810L;
-
-                        @Override
-                        protected void onUpdate(final AjaxRequestTarget target) {
-                            try {
-                                loggerTO.setLevel(loggerTOs.getModelObject());
-                                update(loggerTO);
-                                SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
-                                target.add(loggerTOs);
-                            } catch (SyncopeClientException e) {
-                                LOG.error("Error updating the logger level", e);
-                                SyncopeConsoleSession.get().onException(e);
-                            }
-                            ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
-                        }
-                    });
-                    return loggerTOs;
-                } else {
-                    return super.getValueComponent(key, loggerTO);
-                }
-            }
-        };
-
-        builder.setItems(loggerTOs).
-                setModel(new ListModel<>(loggerTOs)).
-                includes(Constants.KEY_FIELD_NAME, "level").
-                withChecks(ListViewPanel.CheckAvailability.NONE).
-                setCaptionVisible(false).
-                setReuseItem(false);
-
-        loggerContainer.add(builder.build("logger"));
-    }
-
-    protected abstract void update(LoggerTO loggerTO);
-}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ConsoleLogPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ConsoleLogPanel.java
deleted file mode 100644
index b0f7f68..0000000
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ConsoleLogPanel.java
+++ /dev/null
@@ -1,78 +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.client.console.panels;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-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.log.LoggerTO;
-import org.apache.syncope.common.lib.types.LoggerLevel;
-import org.apache.wicket.PageReference;
-
-public class ConsoleLogPanel extends AbstractLogsPanel<LoggerTO> {
-
-    private static final long serialVersionUID = -9165749229623482717L;
-
-    public ConsoleLogPanel(final String id, final PageReference pageReference) {
-        super(id, pageReference, ConsoleLoggerController.getLoggers());
-    }
-
-    @Override
-    protected void update(final LoggerTO loggerTO) {
-        ConsoleLoggerController.setLogLevel(loggerTO.getKey(), loggerTO.getLevel());
-    }
-
-    private static class ConsoleLoggerController implements Serializable {
-
-        private static final long serialVersionUID = -1550459341476431714L;
-
-        public static List<LoggerTO> getLoggers() {
-            LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
-
-            List<LoggerTO> result = new ArrayList<>();
-            ctx.getConfiguration().getLoggers().values().forEach(logger -> {
-                String loggerName = LogManager.ROOT_LOGGER_NAME.equals(logger.getName())
-                        ? SyncopeConstants.ROOT_LOGGER : logger.getName();
-                if (logger.getLevel() != null) {
-                    LoggerTO loggerTO = new LoggerTO();
-                    loggerTO.setKey(loggerName);
-                    loggerTO.setLevel(LoggerLevel.fromLevel(logger.getLevel()));
-                    result.add(loggerTO);
-                }
-            });
-            result.sort(Comparator.comparing(LoggerTO::getKey));
-
-            return result;
-        }
-
-        public static void setLogLevel(final String name, final LoggerLevel level) {
-            LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
-            LoggerConfig logConf = SyncopeConstants.ROOT_LOGGER.equals(name)
-                    ? ctx.getConfiguration().getLoggerConfig(LogManager.ROOT_LOGGER_NAME)
-                    : ctx.getConfiguration().getLoggerConfig(name);
-            logConf.setLevel(level.getLevel());
-            ctx.updateLoggers();
-        }
-    }
-}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/CoreLogPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/CoreLogPanel.java
deleted file mode 100644
index 053da7e..0000000
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/CoreLogPanel.java
+++ /dev/null
@@ -1,44 +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.client.console.panels;
-
-import org.apache.syncope.client.console.pages.LogViewer;
-import org.apache.syncope.client.console.rest.LoggerRestClient;
-import org.apache.syncope.common.lib.log.LoggerTO;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.markup.html.link.PopupSettings;
-
-public class CoreLogPanel extends AbstractLogsPanel<LoggerTO> {
-
-    private static final long serialVersionUID = 3905038169553185171L;
-
-    public CoreLogPanel(final String id, final PageReference pageReference) {
-        super(id, pageReference, LoggerRestClient.listLogs());
-
-        BookmarkablePageLink<Void> viewer = new BookmarkablePageLink<>("viewer", LogViewer.class);
-        viewer.setPopupSettings(new PopupSettings().setHeight(600).setWidth(800));
-        loggerContainer.add(viewer);
-    }
-
-    @Override
-    protected void update(final LoggerTO loggerTO) {
-        LoggerRestClient.setLogLevel(loggerTO);
-    }
-}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/LogStatementPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/LogStatementPanel.java
deleted file mode 100644
index b1ab069..0000000
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/LogStatementPanel.java
+++ /dev/null
@@ -1,92 +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.client.console.panels;
-
-import com.googlecode.wicket.jquery.core.Options;
-import com.googlecode.wicket.jquery.ui.JQueryUIBehavior;
-import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Alert;
-import de.agilecoders.wicket.core.util.Attributes;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.time.FastDateFormat;
-import org.apache.syncope.common.lib.log.LogStatement;
-import org.apache.wicket.markup.ComponentTag;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.Model;
-
-public class LogStatementPanel extends Panel {
-
-    private static final long serialVersionUID = 1610867968070669922L;
-
-    private static final FastDateFormat FORMAT = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS");
-
-    private final String labelCssClass;
-
-    public LogStatementPanel(final String id, final LogStatement statement) {
-        super(id);
-
-        Alert.Type type;
-        switch (statement.getLevel()) {
-            case DEBUG:
-                type = Alert.Type.Success;
-                break;
-
-            case INFO:
-                type = Alert.Type.Info;
-                break;
-
-            case ERROR:
-                type = Alert.Type.Danger;
-                break;
-
-            case WARN:
-                type = Alert.Type.Warning;
-                break;
-
-            default:
-                type = Alert.Type.Info;
-        }
-        labelCssClass = "alert-" + type.name().toLowerCase();
-
-        add(new Label("logger", Model.of(statement.getLoggerName())));
-        add(new Label("instant", Model.of(FORMAT.format(statement.getTimeMillis()))));
-        add(new Label("message", Model.of(statement.getMessage())));
-
-        WebMarkupContainer collapse = new WebMarkupContainer("collapse");
-        collapse.setOutputMarkupId(true);
-        collapse.setOutputMarkupPlaceholderTag(true);
-        collapse.setVisible(StringUtils.isNotBlank(statement.getStackTrace()));
-        collapse.add(new JQueryUIBehavior(
-                '#' + collapse.getMarkupId(), "accordion", new Options("active", false).set("collapsible", true)));
-        add(collapse);
-
-        Label stacktrace = new Label("stacktrace", Model.of(statement.getStackTrace()));
-        stacktrace.setOutputMarkupId(true);
-        collapse.add(stacktrace);
-    }
-
-    @Override
-    protected void onComponentTag(final ComponentTag tag) {
-        super.onComponentTag(tag);
-
-        checkComponentTag(tag, "div");
-        Attributes.addClass(tag, labelCssClass);
-    }
-}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/LogsPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/LogsPanel.java
new file mode 100644
index 0000000..40ab747
--- /dev/null
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/LogsPanel.java
@@ -0,0 +1,193 @@
+/*
+ * 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.client.console.panels;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.console.rest.LoggerConf;
+import org.apache.syncope.client.console.rest.LoggerConfOp;
+import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.types.IdRepoEntitlement;
+import org.apache.wicket.Component;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.logging.LogLevel;
+
+public class LogsPanel extends Panel {
+
+    private static final long serialVersionUID = -6313532280206208227L;
+
+    private static final Logger LOG = LoggerFactory.getLogger(LogsPanel.class);
+
+    private final IModel<List<LoggerConf>> loggerConfs = new LoadableDetachableModel<List<LoggerConf>>() {
+
+        private static final long serialVersionUID = 5275935387613157437L;
+
+        @Override
+        protected List<LoggerConf> load() {
+            return loggerConfOp.list();
+        }
+    };
+
+    private final LoggerConfOp loggerConfOp;
+
+    private final ListViewPanel<LoggerConf> loggerConfsView;
+
+    public LogsPanel(final String id, final LoggerConfOp loggerConfOp, final PageReference pageRef) {
+        super(id);
+        this.loggerConfOp = loggerConfOp;
+
+        WebMarkupContainer searchBoxContainer = new WebMarkupContainer("searchBox");
+        add(searchBoxContainer.setOutputMarkupId(true));
+
+        Form<?> form = new Form<>("form");
+        searchBoxContainer.add(form);
+
+        Model<String> keywordModel = new Model<>(StringUtils.EMPTY);
+
+        AjaxTextFieldPanel filter = new AjaxTextFieldPanel("filter", "filter", keywordModel, true);
+        form.add(filter.hideLabel().setOutputMarkupId(true).setRenderBodyOnly(true));
+
+        AjaxButton search = new AjaxButton("search") {
+
+            private static final long serialVersionUID = 8390605330558248736L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target) {
+                send(LogsPanel.this, Broadcast.EXACT, new LoggerConfSearchEvent(target, keywordModel.getObject()));
+            }
+        };
+        form.add(search.setOutputMarkupId(true));
+        form.setDefaultButton(search);
+
+        WebMarkupContainer loggerContainer = new WebMarkupContainer("loggerContainer");
+        add(loggerContainer.setOutputMarkupId(true));
+
+        ListViewPanel.Builder<LoggerConf> builder = new ListViewPanel.Builder<LoggerConf>(LoggerConf.class, pageRef) {
+
+            private static final long serialVersionUID = 6957788356709885298L;
+
+            @Override
+            protected Component getValueComponent(final String key, final LoggerConf loggerConf) {
+                if ("level".equalsIgnoreCase(key)) {
+                    AjaxDropDownChoicePanel<LogLevel> loggerLevel = new AjaxDropDownChoicePanel<>(
+                            "field", getString("level"), Model.of(loggerConf.getLevel()), false);
+                    MetaDataRoleAuthorizationStrategy.authorize(loggerLevel, ENABLE, IdRepoEntitlement.LOGGER_UPDATE);
+
+                    loggerLevel.hideLabel();
+                    loggerLevel.setChoices(List.of(LogLevel.values()));
+                    loggerLevel.setNullValid(false);
+                    loggerLevel.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                        private static final long serialVersionUID = -1107858522700306810L;
+
+                        @Override
+                        protected void onUpdate(final AjaxRequestTarget target) {
+                            try {
+                                loggerConf.setLevel(loggerLevel.getModelObject());
+                                loggerConfOp.setLevel(loggerConf.getKey(), loggerConf.getLevel());
+
+                                SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
+                                target.add(loggerLevel);
+                            } catch (SyncopeClientException e) {
+                                LOG.error("Error updating the logger level", e);
+                                SyncopeConsoleSession.get().onException(e);
+                            }
+                            ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
+                        }
+                    });
+                    return loggerLevel;
+                } else {
+                    return super.getValueComponent(key, loggerConf);
+                }
+            }
+        };
+
+        builder.setItems(loggerConfs.getObject()).
+                setModel(loggerConfs).
+                includes(Constants.KEY_FIELD_NAME, "level").
+                withChecks(ListViewPanel.CheckAvailability.NONE).
+                setCaptionVisible(false).
+                setReuseItem(false);
+
+        loggerConfsView = (ListViewPanel<LoggerConf>) builder.build("logger");
+        loggerContainer.add(loggerConfsView);
+    }
+
+    @Override
+    public void onEvent(final IEvent<?> event) {
+        if (event.getPayload() instanceof LoggerConfSearchEvent) {
+            LoggerConfSearchEvent payload = LoggerConfSearchEvent.class.cast(event.getPayload());
+            AjaxRequestTarget target = payload.getTarget();
+
+            String keyword = payload.getKeyword();
+            if (StringUtils.isBlank(keyword)) {
+                loggerConfsView.refreshList(loggerConfs.getObject());
+            } else {
+                loggerConfsView.refreshList(loggerConfs.getObject().stream().
+                        filter(l -> l.getKey().contains(keyword)).collect(Collectors.toList()));
+            }
+            target.add(loggerConfsView);
+        } else {
+            super.onEvent(event);
+        }
+    }
+
+    private static class LoggerConfSearchEvent implements Serializable {
+
+        private static final long serialVersionUID = -282052400565266028L;
+
+        private final AjaxRequestTarget target;
+
+        private final String keyword;
+
+        LoggerConfSearchEvent(final AjaxRequestTarget target, final String keyword) {
+            this.target = target;
+            this.keyword = keyword;
+        }
+
+        public AjaxRequestTarget getTarget() {
+            return target;
+        }
+
+        public String getKeyword() {
+            return keyword;
+        }
+    }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
index 3d4e283..636013b 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
@@ -243,7 +243,7 @@ public class SchemaTypePanel extends TypesDirectoryPanel<SchemaTO, SchemaProvide
                     keyword = "*" + keyword;
                 }
                 if (!StringUtils.endsWith(keyword, "*")) {
-                    keyword = keyword + "*";
+                    keyword += "*";
                 }
             }
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/AuditRestClient.java
similarity index 57%
rename from client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerRestClient.java
rename to client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/AuditRestClient.java
index 9dcc214..3cf291f 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/AuditRestClient.java
@@ -18,60 +18,43 @@
  */
 package org.apache.syncope.client.console.rest;
 
-import java.util.ArrayList;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.apache.syncope.common.lib.log.AuditEntry;
-import org.apache.syncope.common.lib.log.EventCategory;
-import org.apache.syncope.common.lib.log.LogAppender;
-import org.apache.syncope.common.lib.log.LogStatement;
-import org.apache.syncope.common.lib.log.LoggerTO;
+import org.apache.syncope.common.lib.audit.AuditEntry;
+import org.apache.syncope.common.lib.audit.EventCategory;
+import org.apache.syncope.common.lib.to.AuditConfTO;
 import org.apache.syncope.common.lib.types.AuditElements;
 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.common.rest.api.LoggerWrapper;
 import org.apache.syncope.common.rest.api.beans.AuditQuery;
-import org.apache.syncope.common.rest.api.service.LoggerService;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
+import org.apache.syncope.common.rest.api.service.AuditService;
 
-public class LoggerRestClient extends BaseRestClient {
+public class AuditRestClient extends BaseRestClient {
 
     private static final long serialVersionUID = 4579786978763032240L;
 
-    public static List<String> listMemoryAppenders() {
-        return getService(LoggerService.class).memoryAppenders().stream().
-                map(LogAppender::getName).collect(Collectors.toList());
-    }
-
-    public static List<LogStatement> getLastLogStatements(final String appender, final long lastStatementTime) {
-        List<LogStatement> result = new ArrayList<>();
-        getService(LoggerService.class).getLastLogStatements(appender).stream().
-                filter(statement -> statement.getTimeMillis() > lastStatementTime).
-                forEachOrdered(result::add);
-
-        return result;
-    }
-
-    public static List<LoggerTO> listLogs() {
-        List<LoggerTO> logs = getService(LoggerService.class).list(LoggerType.LOG);
-        logs.sort(Comparator.comparing(LoggerTO::getKey));
-
-        return logs;
-    }
-
-    public static List<AuditLoggerName> listAudits() {
-        return LoggerWrapper.wrap(getService(LoggerService.class).list(LoggerType.AUDIT));
+    public static List<AuditLoggerName> list() {
+        return getService(AuditService.class).list().stream().
+                map(a -> {
+                    try {
+                        return AuditLoggerName.fromAuditKey(a.getKey());
+                    } catch (Exception e) {
+                        LOG.error("Unexpected when parsing {}", a.getKey(), e);
+                        return null;
+                    }
+                }).
+                filter(Objects::nonNull).
+                collect(Collectors.toList());
     }
 
     public static Map<String, Set<AuditLoggerName>> listAuditsByCategory() {
         Map<String, Set<AuditLoggerName>> result = new HashMap<>();
-        listAudits().forEach(audit -> {
+        list().forEach(audit -> {
             if (!result.containsKey(audit.getCategory())) {
                 result.put(audit.getCategory(), new HashSet<>());
             }
@@ -82,28 +65,23 @@ public class LoggerRestClient extends BaseRestClient {
         return result;
     }
 
-    public static void setLogLevel(final LoggerTO loggerTO) {
-        getService(LoggerService.class).update(LoggerType.LOG, loggerTO);
-    }
-
     public static void enableAudit(final AuditLoggerName auditLoggerName) {
-        LoggerTO loggerTO = new LoggerTO();
-        loggerTO.setKey(auditLoggerName.toLoggerName());
-        loggerTO.setLevel(LoggerLevel.DEBUG);
-        getService(LoggerService.class).update(LoggerType.AUDIT, loggerTO);
-    }
-
-    public static void deleteLog(final String name) {
-        getService(LoggerService.class).delete(LoggerType.LOG, name);
+        AuditConfTO audit = new AuditConfTO();
+        audit.setKey(auditLoggerName.toAuditKey());
+        audit.setActive(true);
+        getService(AuditService.class).update(audit);
     }
 
     public static void disableAudit(final AuditLoggerName auditLoggerName) {
-        getService(LoggerService.class).delete(LoggerType.AUDIT, auditLoggerName.toLoggerName());
+        AuditConfTO audit = new AuditConfTO();
+        audit.setKey(auditLoggerName.toAuditKey());
+        audit.setActive(false);
+        getService(AuditService.class).update(audit);
     }
 
     public static List<EventCategory> listEvents() {
         try {
-            return getService(LoggerService.class).events();
+            return getService(AuditService.class).events();
         } catch (Exception e) {
             return List.of();
         }
@@ -130,7 +108,7 @@ public class LoggerRestClient extends BaseRestClient {
                 orderBy(toOrderBy(sort)).
                 build();
 
-        return getService(LoggerService.class).search(query).getResult();
+        return getService(AuditService.class).search(query).getResult();
     }
 
     public int count(
@@ -149,6 +127,6 @@ public class LoggerRestClient extends BaseRestClient {
                 events(events).
                 result(result).
                 build();
-        return getService(LoggerService.class).search(query).getTotalCount();
+        return getService(AuditService.class).search(query).getTotalCount();
     }
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/LoggerLevel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConf.java
similarity index 63%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/LoggerLevel.java
copy to client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConf.java
index dd54348..8600ffd 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/LoggerLevel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConf.java
@@ -16,32 +16,32 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.client.console.rest;
 
-import org.apache.logging.log4j.Level;
+import java.io.Serializable;
+import org.springframework.boot.logging.LogLevel;
 
-public enum LoggerLevel {
+public class LoggerConf implements Serializable {
 
-    OFF(Level.OFF),
-    FATAL(Level.FATAL),
-    ERROR(Level.ERROR),
-    WARN(Level.WARN),
-    INFO(Level.INFO),
-    DEBUG(Level.DEBUG),
-    TRACE(Level.TRACE),
-    ALL(Level.ALL);
+    private static final long serialVersionUID = 15926519538056L;
 
-    private final Level level;
+    private String key;
 
-    LoggerLevel(final Level level) {
-        this.level = level;
+    private LogLevel level;
+
+    public String getKey() {
+        return key;
     }
 
-    public Level getLevel() {
+    public void setKey(final String key) {
+        this.key = key;
+    }
+
+    public LogLevel getLevel() {
         return level;
     }
 
-    public static LoggerLevel fromLevel(final Level level) {
-        return LoggerLevel.valueOf(level.name());
+    public void setLevel(final LogLevel level) {
+        this.level = level;
     }
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/LogAppender.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConfOp.java
similarity index 68%
rename from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/LogAppender.java
rename to client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConfOp.java
index 1d07589..dc0ce5c 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/LogAppender.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConfOp.java
@@ -16,21 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.log;
+package org.apache.syncope.client.console.rest;
 
-import org.apache.syncope.common.lib.BaseBean;
+import java.io.Serializable;
+import java.util.List;
+import org.springframework.boot.logging.LogLevel;
 
-public class LogAppender implements BaseBean {
+public interface LoggerConfOp extends Serializable {
 
-    private static final long serialVersionUID = 5975199884460548302L;
+    List<LoggerConf> list();
 
-    private String name;
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(final String name) {
-        this.name = name;
-    }
+    void setLevel(String key, LogLevel level);
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConfRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConfRestClient.java
new file mode 100644
index 0000000..65a2b4f
--- /dev/null
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/LoggerConfRestClient.java
@@ -0,0 +1,124 @@
+/*
+ * 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.client.console.rest;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.client.console.SyncopeWebApplication;
+import org.apache.syncope.client.ui.commons.rest.RestClient;
+import org.apache.syncope.common.keymaster.client.api.model.Domain;
+import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.logging.LogLevel;
+
+public class LoggerConfRestClient implements RestClient, LoggerConfOp {
+
+    private static final long serialVersionUID = 16051907544728L;
+
+    private static final Logger LOG = LoggerFactory.getLogger(LoggerConfRestClient.class);
+
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    private final List<NetworkService> instances;
+
+    private final List<String> domains;
+
+    public LoggerConfRestClient(final List<NetworkService> instances, final List<Domain> domains) {
+        this.instances = instances;
+        this.domains = Stream.concat(
+                Stream.of(SyncopeConstants.MASTER_DOMAIN), domains.stream().map(Domain::getKey)).
+                collect(Collectors.toList());
+    }
+
+    private String getActuatorEndpoint(final NetworkService instance) {
+        String address = instance.getAddress();
+        if (address.contains("/rest")) {
+            address = address.replace("/rest", "");
+        }
+        return address + "actuator/loggers";
+    }
+
+    private WebClient webClient(final NetworkService instance) {
+        return WebClient.create(
+                getActuatorEndpoint(instance),
+                SyncopeWebApplication.get().getAnonymousUser(),
+                SyncopeWebApplication.get().getAnonymousKey(),
+                null).
+                accept(MediaType.APPLICATION_JSON_TYPE).
+                type(MediaType.APPLICATION_JSON_TYPE);
+    }
+
+    @Override
+    public List<LoggerConf> list() {
+        List<LoggerConf> loggerConfs = new ArrayList<>();
+
+        try {
+            Response response = webClient(instances.get(0)).get();
+            if (response.getStatus() == Response.Status.OK.getStatusCode()) {
+                JsonNode node = MAPPER.readTree((InputStream) response.getEntity());
+                if (node.has("loggers")) {
+                    for (Iterator<Map.Entry<String, JsonNode>> itor = node.get("loggers").fields(); itor.hasNext();) {
+                        Map.Entry<String, JsonNode> entry = itor.next();
+
+                        LoggerConf loggerConf = new LoggerConf();
+                        loggerConf.setKey(entry.getKey());
+                        if (entry.getValue().has("effectiveLevel")) {
+                            loggerConf.setLevel(LogLevel.valueOf(entry.getValue().get("effectiveLevel").asText()));
+                        } else {
+                            loggerConf.setLevel(LogLevel.OFF);
+                        }
+
+                        if (!loggerConf.getKey().startsWith(AuditLoggerName.AUDIT_PREFIX)
+                                && domains.stream().noneMatch(domain -> loggerConf.getKey().startsWith(domain))) {
+
+                            loggerConfs.add(loggerConf);
+                        }
+                    }
+                }
+            } else {
+                LOG.error("Unexpected response for loggers from {}: {}",
+                        getActuatorEndpoint(instances.get(0)), response.getStatus());
+            }
+        } catch (Exception e) {
+            LOG.error("Could not fetch loggers from {}", getActuatorEndpoint(instances.get(0)), e);
+        }
+
+        loggerConfs.sort(Comparator.comparing(LoggerConf::getKey));
+        return loggerConfs;
+    }
+
+    @Override
+    public void setLevel(final String key, final LogLevel level) {
+        instances.forEach(i -> webClient(i).path(key).post("{\"configuredLevel\": \"" + level.name() + "\"}"));
+    }
+}
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/LogViewer.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/LogViewer.html
deleted file mode 100644
index c68b2e4..0000000
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/LogViewer.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<!--
-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.
--->
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
-  <head>
-    <title>Apache Syncope - Log Viewer</title>
-  </head>
-  <body>
-    <div wicket:id="viewer" style="padding: 5px;">
-      <div wicket:id="appenders" style="margin-bottom: 10px;"></div>
-      <div wicket:id="stContainer" style="overflow-y: auto; overflow-x: auto; max-width: 100vw; max-height: 85vh;">
-        <div wicket:id="statements">
-          <div wicket:id="statement"/>
-        </div>
-      </div>
-    </div>
-  </body>
-</html>
\ No newline at end of file
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel.html
deleted file mode 100644
index a4cd024..0000000
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel.html
+++ /dev/null
@@ -1,27 +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.
--->
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
-  <wicket:panel>
-    <span wicket:id="loggerContainer">
-      <div class="logs">
-        <span wicket:id="logger">[logger]</span>
-      </div>
-    </span>
-  </wicket:panel>
-</html>
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel.properties
deleted file mode 100644
index 11bf815..0000000
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel.properties
+++ /dev/null
@@ -1,18 +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.
-logger=Logger
-level=Level
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_fr_CA.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_fr_CA.properties
deleted file mode 100644
index 135955c..0000000
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_fr_CA.properties
+++ /dev/null
@@ -1,18 +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.
-logger=Enregistreur de donn�es
-level=Niveau
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel.properties
deleted file mode 100644
index 11bf815..0000000
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel.properties
+++ /dev/null
@@ -1,18 +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.
-logger=Logger
-level=Level
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_it.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_it.properties
deleted file mode 100644
index 8a89715..0000000
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_it.properties
+++ /dev/null
@@ -1,18 +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.
-logger=Logger
-level=Livello
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_ja.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_ja.properties
deleted file mode 100644
index 936c13e..0000000
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_ja.properties
+++ /dev/null
@@ -1,18 +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.
-logger=\u30ed\u30b0\u53d6\u5f97
-level=\u30ec\u30d9\u30eb
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_ru.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_ru.properties
deleted file mode 100644
index 22348f5..0000000
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_ru.properties
+++ /dev/null
@@ -1,21 +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.
-#
-# logger=Логгер
-logger=\u041b\u043e\u0433\u0433\u0435\u0440
-# level=Уровень
-level=\u0423\u0440\u043e\u0432\u0435\u043d\u044c
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel.html
similarity index 71%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel.html
rename to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel.html
index 1c0f363..fa47713 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel.html
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel.html
@@ -18,13 +18,21 @@ under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
   <wicket:panel>
+    <div wicket:id="searchBox">
+      <form wicket:id="form">
+        <div class="input-group mb-3">
+          <span wicket:id="filter">[FILTER]</span>
+          <span class="input-group-btn">
+            <button type="button" class="btn btn-default btn-flat" wicket:id="search">
+              <span class="fas fa-search" aria-hidden="true"></span>
+            </button>
+          </span>
+        </div>
+      </form>
+    </div>
+
     <span wicket:id="loggerContainer">
       <div class="logs">
-        <div class="logviewer-btn">
-          <button class="btn btn-success" wicket:id="viewer">
-            <span class="far fa-list-alt"></span> Log Viewer
-          </button>
-        </div>
         <span wicket:id="logger">[logger]</span>
       </div>
     </span>
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_pt_BR.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel.properties
similarity index 93%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_pt_BR.properties
rename to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel.properties
index 11bf815..38bb3c2 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_pt_BR.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel.properties
@@ -16,3 +16,4 @@
 # under the License.
 logger=Logger
 level=Level
+newLoggerConf=Are you sure you want to create a new logger?
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_fr_CA.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_fr_CA.properties
similarity index 89%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_fr_CA.properties
rename to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_fr_CA.properties
index 135955c..ff19781 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/CoreLogPanel_fr_CA.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_fr_CA.properties
@@ -14,5 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-logger=Enregistreur de donn�es
+logger=Enregistreur de donn\u00e9es
 level=Niveau
+newLoggerConf=Are you sure you want to create a new logger?
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_it.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_it.properties
similarity index 93%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_it.properties
rename to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_it.properties
index 8a89715..e974729 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_it.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_it.properties
@@ -16,3 +16,4 @@
 # under the License.
 logger=Logger
 level=Livello
+newLoggerConf=Sicuro di voler creare un nuovo logger?
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_ja.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_ja.properties
similarity index 93%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_ja.properties
rename to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_ja.properties
index 936c13e..b7035eb 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_ja.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_ja.properties
@@ -16,3 +16,4 @@
 # under the License.
 logger=\u30ed\u30b0\u53d6\u5f97
 level=\u30ec\u30d9\u30eb
+newLoggerConf=Are you sure you want to create a new logger?
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_pt_BR.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_pt_BR.properties
similarity index 93%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_pt_BR.properties
rename to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_pt_BR.properties
index 11bf815..38bb3c2 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_pt_BR.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_pt_BR.properties
@@ -16,3 +16,4 @@
 # under the License.
 logger=Logger
 level=Level
+newLoggerConf=Are you sure you want to create a new logger?
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_ru.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_ru.properties
similarity index 78%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_ru.properties
rename to client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_ru.properties
index 22348f5..5ad96be 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ConsoleLogPanel_ru.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/LogsPanel_ru.properties
@@ -15,7 +15,8 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-# logger=Логгер
+# logger=\u00d0\u009b\u00d0\u00be\u00d0\u00b3\u00d0\u00b3\u00d0\u00b5\u00d1\u0080
 logger=\u041b\u043e\u0433\u0433\u0435\u0440
-# level=Уровень
+# level=\u00d0\u00a3\u00d1\u0080\u00d0\u00be\u00d0\u00b2\u00d0\u00b5\u00d0\u00bd\u00d1\u008c
 level=\u0423\u0440\u043e\u0432\u0435\u043d\u044c
+newLoggerConf=Are you sure you want to create a new logger?
diff --git a/common/idrepo/lib/pom.xml b/common/idrepo/lib/pom.xml
index f27827a..a81ba34 100644
--- a/common/idrepo/lib/pom.xml
+++ b/common/idrepo/lib/pom.xml
@@ -79,10 +79,6 @@ under the License.
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-api</artifactId>
-    </dependency>
     
     <dependency>
       <groupId>org.junit.jupiter</groupId>
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/AuditEntry.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/audit/AuditEntry.java
similarity index 98%
rename from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/AuditEntry.java
rename to common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/audit/AuditEntry.java
index ab50384..4fe9aa2 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/AuditEntry.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/audit/AuditEntry.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.log;
+package org.apache.syncope.common.lib.audit;
 
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/EventCategory.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/audit/EventCategory.java
similarity index 98%
rename from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/EventCategory.java
rename to common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/audit/EventCategory.java
index cf49f98..8682019 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/EventCategory.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/audit/EventCategory.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.log;
+package org.apache.syncope.common.lib.audit;
 
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/LogStatement.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/LogStatement.java
deleted file mode 100644
index 64ba4cd..0000000
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/LogStatement.java
+++ /dev/null
@@ -1,107 +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.common.lib.log;
-
-import org.apache.syncope.common.lib.BaseBean;
-import org.apache.syncope.common.lib.types.LoggerLevel;
-
-public class LogStatement implements BaseBean {
-
-    private static final long serialVersionUID = -2931205859104653385L;
-
-    private LoggerLevel level;
-
-    private String loggerName;
-
-    private String message;
-
-    private String stackTrace;
-
-    private long timeMillis;
-
-    private long threadId;
-
-    private String threadName;
-
-    private int threadPriority;
-
-    public LoggerLevel getLevel() {
-        return level;
-    }
-
-    public void setLevel(final LoggerLevel level) {
-        this.level = level;
-    }
-
-    public String getLoggerName() {
-        return loggerName;
-    }
-
-    public void setLoggerName(final String loggerName) {
-        this.loggerName = loggerName;
-    }
-
-    public String getMessage() {
-        return message;
-    }
-
-    public void setMessage(final String message) {
-        this.message = message;
-    }
-
-    public String getStackTrace() {
-        return stackTrace;
-    }
-
-    public void setStackTrace(final String stackTrace) {
-        this.stackTrace = stackTrace;
-    }
-
-    public long getTimeMillis() {
-        return timeMillis;
-    }
-
-    public void setTimeMillis(final long timeMillis) {
-        this.timeMillis = timeMillis;
-    }
-
-    public long getThreadId() {
-        return threadId;
-    }
-
-    public void setThreadId(final long threadId) {
-        this.threadId = threadId;
-    }
-
-    public String getThreadName() {
-        return threadName;
-    }
-
-    public void setThreadName(final String threadName) {
-        this.threadName = threadName;
-    }
-
-    public int getThreadPriority() {
-        return threadPriority;
-    }
-
-    public void setThreadPriority(final int threadPriority) {
-        this.threadPriority = threadPriority;
-    }
-}
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/LoggerTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/LoggerTO.java
deleted file mode 100644
index 5646fe0..0000000
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/log/LoggerTO.java
+++ /dev/null
@@ -1,77 +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.common.lib.log;
-
-import javax.ws.rs.PathParam;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
-import org.apache.syncope.common.lib.BaseBean;
-import org.apache.syncope.common.lib.types.LoggerLevel;
-
-public class LoggerTO implements BaseBean {
-
-    private static final long serialVersionUID = -7794833835668648505L;
-
-    private String key;
-
-    private LoggerLevel level;
-
-    public LoggerLevel getLevel() {
-        return level;
-    }
-
-    public void setLevel(final LoggerLevel level) {
-        this.level = level;
-    }
-
-    public String getKey() {
-        return key;
-    }
-
-    @PathParam("key")
-    public void setKey(final String key) {
-        this.key = key;
-    }
-
-    @Override
-    public int hashCode() {
-        return new HashCodeBuilder().
-                append(key).
-                append(level).
-                build();
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final LoggerTO other = (LoggerTO) obj;
-        return new EqualsBuilder().
-                append(key, other.key).
-                append(level, other.level).
-                build();
-    }
-}
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/LoggerLevel.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AuditConfTO.java
similarity index 60%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/LoggerLevel.java
copy to common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AuditConfTO.java
index dd54348..8064462 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/LoggerLevel.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AuditConfTO.java
@@ -16,32 +16,34 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.common.lib.to;
 
-import org.apache.logging.log4j.Level;
+import javax.ws.rs.PathParam;
 
-public enum LoggerLevel {
+public class AuditConfTO implements EntityTO {
 
-    OFF(Level.OFF),
-    FATAL(Level.FATAL),
-    ERROR(Level.ERROR),
-    WARN(Level.WARN),
-    INFO(Level.INFO),
-    DEBUG(Level.DEBUG),
-    TRACE(Level.TRACE),
-    ALL(Level.ALL);
+    private static final long serialVersionUID = 7077562682788L;
 
-    private final Level level;
+    private String key;
 
-    LoggerLevel(final Level level) {
-        this.level = level;
+    private boolean active;
+
+    @Override
+    public String getKey() {
+        return key;
+    }
+
+    @PathParam("key")
+    @Override
+    public void setKey(final String key) {
+        this.key = key;
     }
 
-    public Level getLevel() {
-        return level;
+    public boolean isActive() {
+        return active;
     }
 
-    public static LoggerLevel fromLevel(final Level level) {
-        return LoggerLevel.valueOf(level.name());
+    public void setActive(final boolean active) {
+        this.active = active;
     }
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/AuditLoggerName.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/AuditLoggerName.java
index 4298ead..21e354f 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/AuditLoggerName.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/AuditLoggerName.java
@@ -28,7 +28,7 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.BaseBean;
-import org.apache.syncope.common.lib.log.EventCategory;
+import org.apache.syncope.common.lib.audit.EventCategory;
 import org.apache.syncope.common.lib.types.AuditElements.EventCategoryType;
 import org.apache.syncope.common.lib.types.AuditElements.Result;
 
@@ -36,8 +36,10 @@ public class AuditLoggerName implements BaseBean {
 
     private static final long serialVersionUID = -647989486671786839L;
 
+    public static final String AUDIT_PREFIX = "syncope.audit";
+
     public static String getAuditLoggerName(final String domain) {
-        return LoggerType.AUDIT.getPrefix() + '.' + domain;
+        return AUDIT_PREFIX + '.' + domain;
     }
 
     public static String getAuditEventLoggerName(final String domain, final String loggerName) {
@@ -91,8 +93,8 @@ public class AuditLoggerName implements BaseBean {
         return subcategory;
     }
 
-    public String toLoggerName() {
-        return new StringBuilder().append(LoggerType.AUDIT.getPrefix()).append('.').
+    public String toAuditKey() {
+        return new StringBuilder().append(AUDIT_PREFIX).append('.').
                 append(buildEvent(type, category, subcategory, event, result)).toString();
     }
 
@@ -128,19 +130,16 @@ public class AuditLoggerName implements BaseBean {
                 build();
     }
 
-    public static AuditLoggerName fromLoggerName(final String loggerName)
-            throws ParseException {
-
-        if (StringUtils.isBlank(loggerName)) {
+    public static AuditLoggerName fromAuditKey(final String key) throws ParseException {
+        if (StringUtils.isBlank(key)) {
             throw new IllegalArgumentException("Null value not permitted");
         }
 
-        if (!loggerName.startsWith(LoggerType.AUDIT.getPrefix())) {
-            throw new ParseException("Audit logger name must start with " + LoggerType.AUDIT.getPrefix(), 0);
+        if (!key.startsWith(AUDIT_PREFIX)) {
+            throw new ParseException("Audit logger name must start with " + AUDIT_PREFIX, 0);
         }
 
-        Map.Entry<EventCategory, Result> eventCategory = parseEventCategory(
-                loggerName.replaceAll(LoggerType.AUDIT.getPrefix() + '.', ""));
+        Map.Entry<EventCategory, Result> eventCategory = parseEventCategory(key.replace(AUDIT_PREFIX + '.', ""));
 
         return new AuditLoggerName(
                 eventCategory.getKey().getType(),
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/IdRepoEntitlement.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/IdRepoEntitlement.java
index b88e4ad..1dc1ebf 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/IdRepoEntitlement.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/IdRepoEntitlement.java
@@ -110,8 +110,6 @@ public final class IdRepoEntitlement {
 
     public static final String SCHEMA_DELETE = "SCHEMA_DELETE";
 
-    public static final String AUDIT_SEARCH = "AUDIT_SEARCH";
-
     public static final String USER_SEARCH = "USER_SEARCH";
 
     public static final String USER_CREATE = "USER_CREATE";
@@ -200,13 +198,7 @@ public final class IdRepoEntitlement {
 
     public static final String REPORT_EXECUTE = "REPORT_EXECUTE";
 
-    public static final String LOG_READ = "LOG_READ";
-
-    public static final String LOG_LIST = "LOG_LIST";
-
-    public static final String LOG_SET_LEVEL = "LOG_SET_LEVEL";
-
-    public static final String LOG_DELETE = "LOG_DELETE";
+    public static final String AUDIT_SEARCH = "AUDIT_SEARCH";
 
     public static final String AUDIT_LIST = "AUDIT_LIST";
 
@@ -214,9 +206,9 @@ public final class IdRepoEntitlement {
 
     public static final String AUDIT_CREATE = "AUDIT_CREATE";
 
-    public static final String AUDIT_ENABLE = "AUDIT_ENABLE";
+    public static final String AUDIT_UPDATE = "AUDIT_UPDATE";
 
-    public static final String AUDIT_DISABLE = "AUDIT_DISABLE";
+    public static final String AUDIT_DELETE = "AUDIT_DELETE";
 
     public static final String SECURITY_QUESTION_CREATE = "SECURITY_QUESTION_CREATE";
 
@@ -250,6 +242,10 @@ public final class IdRepoEntitlement {
 
     public static final String DELEGATION_DELETE = "DELEGATION_DELETE";
 
+    public static final String LOGGER_LIST = "LOGGER_LIST";
+
+    public static final String LOGGER_UPDATE = "LOGGER_UPDATE";
+
     private static final Set<String> VALUES;
 
     static {
diff --git a/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/SerializationTest.java b/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/SerializationTest.java
index 1d24582..fad075e 100644
--- a/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/SerializationTest.java
+++ b/common/idrepo/lib/src/test/java/org/apache/syncope/common/lib/SerializationTest.java
@@ -28,7 +28,6 @@ import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
-import org.apache.syncope.common.lib.log.LoggerTO;
 import org.apache.syncope.common.lib.request.AnyObjectCR;
 import org.apache.syncope.common.lib.request.GroupUR;
 import org.apache.syncope.common.lib.request.PasswordPatch;
@@ -40,6 +39,7 @@ import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.junit.jupiter.api.Test;
 
@@ -49,13 +49,13 @@ public abstract class SerializationTest {
 
     @Test
     public void emptyListAsRoot() throws IOException {
-        List<LoggerTO> original = new ArrayList<>();
+        List<ReportTO> original = new ArrayList<>();
 
         StringWriter writer = new StringWriter();
         objectMapper().writeValue(writer, original);
 
-        List<LoggerTO> actual = objectMapper().readValue(writer.toString(),
-                new TypeReference<List<LoggerTO>>() {
+        List<ReportTO> actual = objectMapper().readValue(writer.toString(),
+                new TypeReference<List<ReportTO>>() {
         });
         assertEquals(original, actual);
     }
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/LoggerWrapper.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/LoggerWrapper.java
deleted file mode 100644
index b48fbb5..0000000
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/LoggerWrapper.java
+++ /dev/null
@@ -1,55 +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.common.rest.api;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.stream.Collectors;
-import org.apache.syncope.common.lib.log.LoggerTO;
-import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.common.lib.types.LoggerLevel;
-
-public final class LoggerWrapper {
-
-    private LoggerWrapper() {
-        // empty constructor for static utility class
-    }
-
-    public static List<AuditLoggerName> wrap(final Collection<LoggerTO> logger) {
-        List<AuditLoggerName> result = new ArrayList<>();
-        logger.forEach(loggerTO -> {
-            try {
-                result.add(AuditLoggerName.fromLoggerName(loggerTO.getKey()));
-            } catch (Exception ignore) {
-                // ignore
-            }
-        });
-        return result;
-    }
-
-    public static List<LoggerTO> unwrap(final Collection<AuditLoggerName> auditNames) {
-        return auditNames.stream().map(name -> {
-            LoggerTO loggerTO = new LoggerTO();
-            loggerTO.setKey(name.toLoggerName());
-            loggerTO.setLevel(LoggerLevel.DEBUG);
-            return loggerTO;
-        }).collect(Collectors.toList());
-    }
-}
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/LoggerService.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AuditService.java
similarity index 61%
rename from common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/LoggerService.java
rename to common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AuditService.java
index d54f690..a86dd8c 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/LoggerService.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AuditService.java
@@ -38,127 +38,110 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
-import org.apache.syncope.common.lib.log.AuditEntry;
-import org.apache.syncope.common.lib.log.EventCategory;
-import org.apache.syncope.common.lib.log.LogAppender;
-import org.apache.syncope.common.lib.log.LogStatement;
-import org.apache.syncope.common.lib.log.LoggerTO;
+import org.apache.syncope.common.lib.audit.AuditEntry;
+import org.apache.syncope.common.lib.audit.EventCategory;
+import org.apache.syncope.common.lib.to.AuditConfTO;
 import org.apache.syncope.common.lib.to.PagedResult;
-import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.beans.AuditQuery;
 
 /**
- * REST operations for logging and auditing.
+ * REST operations for audit.
  */
-@Tag(name = "Loggers")
+@Tag(name = "Audit")
 @SecurityRequirements({
     @SecurityRequirement(name = "BasicAuthentication"),
     @SecurityRequirement(name = "Bearer") })
-@Path("loggers")
-public interface LoggerService extends JAXRSService {
+@Path("audit")
+public interface AuditService extends JAXRSService {
 
     /**
-     * Returns the list of memory appenders available in the current logging configuration.
+     * Returns a list of all audits.
      *
-     * @return the list of memory appenders available in the current logging configuration
+     * @return list of all audits.
      */
     @GET
-    @Path("memoryAppenders")
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    List<LogAppender> memoryAppenders();
+    List<AuditConfTO> list();
 
     /**
-     * Return the last log statements available in the provided memory appender.
+     * Returns audit with matching key.
      *
-     * @param memoryAppender memory appender name
-     * @return the last log statements available in the provided memory appender
+     * @param key audit key to be read
+     * @return audit with matching key
      */
     @GET
-    @Path("memoryAppenders/{memoryAppender}/lastLogStatements")
+    @Path("{key}")
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    List<LogStatement> getLastLogStatements(@NotNull @PathParam("memoryAppender") String memoryAppender);
+    AuditConfTO read(@NotNull @PathParam("key") String key);
 
     /**
-     * Returns the list of all managed events in audit.
+     * Creates a new audit.
      *
-     * @return list of all managed events in audit
+     * @param auditTO audit to be created
      */
-    @GET
-    @Path("events")
+    @ApiResponses(
+            @ApiResponse(responseCode = "201", description = "Audit successfully created"))
+    @POST
+    @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    List<EventCategory> events();
+    void create(@NotNull AuditConfTO auditTO);
 
     /**
-     * Returns a paged list of audit entries matching the given query.
+     * Updates the audit matching the provided key.
      *
-     * @param auditQuery query conditions
-     * @return paged list of audit entries matching the given query
+     * @param auditTO audit to be stored
      */
-    @GET
-    @Path("AUDIT/entries")
+    @Parameter(name = "key", description = "Audit's key", in = ParameterIn.PATH, schema =
+            @Schema(type = "string"))
+    @ApiResponses(
+            @ApiResponse(responseCode = "204", description = "Operation was successful"))
+    @PUT
+    @Path("{key}")
+    @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    PagedResult<AuditEntry> search(@BeanParam AuditQuery auditQuery);
+    void update(@NotNull AuditConfTO auditTO);
 
     /**
-     * Create an audit entry.
+     * Deletes the audit matching the provided key.
      *
-     * @param auditEntry audit entry to persist.
+     * @param key audit key to be deleted
      */
-    @POST
-    @Path("AUDIT/entries")
-    @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    void create(@NotNull AuditEntry auditEntry);
-    
-    /**
-     * Returns logger with matching type and name.
-     *
-     * @param type LoggerType to be selected.
-     * @param name Logger name to be read
-     * @return logger with matching type and name
-     */
-    @GET
-    @Path("{type}/{name}")
+    @ApiResponses(
+            @ApiResponse(responseCode = "204", description = "Operation was successful"))
+    @DELETE
+    @Path("{key}")
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    LoggerTO read(@NotNull @PathParam("type") LoggerType type, @NotNull @PathParam("name") String name);
+    void delete(@NotNull @PathParam("key") String key);
 
     /**
-     * Returns a list of loggers with matching type.
+     * Returns the list of all managed events in audit.
      *
-     * @param type LoggerType to be selected
-     * @return list of loggers with matching type
+     * @return list of all managed events in audit
      */
     @GET
-    @Path("{type}")
+    @Path("events")
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    List<LoggerTO> list(@NotNull @PathParam("type") LoggerType type);
+    List<EventCategory> events();
 
     /**
-     * Creates or updates (if existing) the logger with matching name.
+     * Returns a paged list of audit entries matching the given query.
      *
-     * @param type LoggerType to be selected
-     * @param logger Logger to be created or updated
+     * @param auditQuery query conditions
+     * @return paged list of audit entries matching the given query
      */
-    @Parameter(name = "key", description = "Logger's key", in = ParameterIn.PATH, schema =
-            @Schema(type = "string"))
-    @ApiResponses(
-            @ApiResponse(responseCode = "204", description = "Operation was successful"))
-    @PUT
-    @Path("{type}/{key}")
-    @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
+    @GET
+    @Path("entries")
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    void update(@NotNull @PathParam("type") LoggerType type, @NotNull LoggerTO logger);
+    PagedResult<AuditEntry> search(@BeanParam AuditQuery auditQuery);
 
     /**
-     * Deletes the logger with matching name.
+     * Create an audit entry.
      *
-     * @param type LoggerType to be selected
-     * @param name Logger name to be deleted
+     * @param auditEntry audit entry to persist.
      */
-    @ApiResponses(
-            @ApiResponse(responseCode = "204", description = "Operation was successful"))
-    @DELETE
-    @Path("{type}/{name}")
-    @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    void delete(@NotNull @PathParam("type") LoggerType type, @NotNull @PathParam("name") String name);
+    @POST
+    @Path("entries")
+    @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
+    void create(@NotNull AuditEntry auditEntry);
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AuditLogic.java
similarity index 52%
rename from core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
rename to core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AuditLogic.java
index 10f4884..a57ff6f 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AuditLogic.java
@@ -23,42 +23,33 @@ import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.tuple.Pair;
 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.config.LoggerConfig;
-import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.log.EventCategory;
-import org.apache.syncope.common.lib.log.LogAppender;
-import org.apache.syncope.common.lib.log.LogStatement;
-import org.apache.syncope.common.lib.log.LoggerTO;
-import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.common.lib.audit.EventCategory;
+import org.apache.syncope.common.lib.to.AuditConfTO;
 import org.apache.syncope.common.lib.types.AuditElements.EventCategoryType;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
-import org.apache.syncope.common.lib.types.LoggerLevel;
-import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 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.IdRepoEntitlement;
-import org.apache.syncope.core.logic.audit.AuditAppender;
-import org.apache.syncope.core.logic.init.LoggerLoader;
-import org.apache.syncope.core.persistence.api.DomainHolder;
+import org.apache.syncope.core.logic.init.AuditLoader;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
-import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
-import org.apache.syncope.core.persistence.api.entity.Logger;
 import org.apache.syncope.core.provisioning.api.AuditManager;
 import org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate;
 import org.apache.syncope.core.provisioning.java.pushpull.PullJobDelegate;
@@ -70,25 +61,23 @@ import org.springframework.core.io.support.ResourcePatternResolver;
 import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
 import org.springframework.core.type.classreading.MetadataReader;
 import org.springframework.core.type.classreading.MetadataReaderFactory;
-import org.springframework.dao.InvalidDataAccessApiUsageException;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.ClassUtils;
 import org.springframework.util.SystemPropertyUtils;
-import org.apache.syncope.core.provisioning.api.data.LoggerDataBinder;
+import org.apache.syncope.core.provisioning.api.data.AuditDataBinder;
+import org.apache.syncope.core.persistence.api.entity.AuditConf;
+import org.apache.syncope.core.persistence.api.dao.AuditConfDAO;
 
 @Component
-public class LoggerLogic extends AbstractTransactionalLogic<EntityTO> {
+public class AuditLogic extends AbstractTransactionalLogic<AuditConfTO> {
 
     @Autowired
-    private DomainHolder domainHolder;
+    private AuditLoader auditLoader;
 
     @Autowired
-    private LoggerLoader loggerLoader;
-
-    @Autowired
-    private LoggerDAO loggerDAO;
+    private AuditConfDAO auditDAO;
 
     @Autowired
     private ExternalResourceDAO resourceDAO;
@@ -97,214 +86,76 @@ public class LoggerLogic extends AbstractTransactionalLogic<EntityTO> {
     private EntityFactory entityFactory;
 
     @Autowired
-    private LoggerDataBinder binder;
+    private AuditDataBinder binder;
 
     @Autowired
     private AuditManager auditManager;
 
-    @PreAuthorize("hasRole('" + IdRepoEntitlement.LOG_LIST + "') and authentication.details.domain == "
-            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
-    @Transactional(readOnly = true)
-    public List<LogAppender> memoryAppenders() {
-        return loggerLoader.getMemoryAppenders().keySet().stream().map(appender -> {
-            LogAppender logAppender = new LogAppender();
-            logAppender.setName(appender);
-            return logAppender;
-        }).collect(Collectors.toList());
-    }
-
-    @PreAuthorize("hasRole('" + IdRepoEntitlement.LOG_READ + "') and authentication.details.domain == "
-            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
-    @Transactional(readOnly = true)
-    public List<LogStatement> getLastLogStatements(final String memoryAppender) {
-        MemoryAppender appender = loggerLoader.getMemoryAppenders().get(memoryAppender);
-        if (appender == null) {
-            throw new NotFoundException("Appender " + memoryAppender);
-        }
-
-        return appender.getStatements().stream().collect(Collectors.toList());
-    }
-
-    private List<LoggerTO> list(final LoggerType type) {
-        return loggerDAO.findAll(type).stream().map(binder::getLoggerTO).collect(Collectors.toList());
-    }
-
-    @PreAuthorize("hasRole('" + IdRepoEntitlement.LOG_LIST + "') and authentication.details.domain == "
-            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
-    @Transactional(readOnly = true)
-    public List<LoggerTO> listLogs() {
-        return list(LoggerType.LOG).stream().
-                filter(logger -> !logger.getKey().startsWith(SyncopeConstants.MASTER_DOMAIN)).
-                filter(logger -> domainHolder.getDomains().keySet().stream().
-                noneMatch(domain -> logger.getKey().startsWith(domain))).
-                collect(Collectors.toList());
-    }
-
     @PreAuthorize("hasRole('" + IdRepoEntitlement.AUDIT_LIST + "')")
     @Transactional(readOnly = true)
-    public List<AuditLoggerName> listAudits() {
-        return list(LoggerType.AUDIT).stream().
-                map(logger -> {
-                    AuditLoggerName result = null;
-                    try {
-                        result = AuditLoggerName.fromLoggerName(logger.getKey());
-                    } catch (Exception e) {
-                        LOG.warn("Unexpected audit logger name: {}", logger.getKey(), e);
-                    }
-
-                    return result;
-                }).
-                filter(Objects::nonNull).
-                collect(Collectors.toList());
-    }
-
-    private static void throwInvalidLogger(final LoggerType type) {
-        SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidLogger);
-        sce.getElements().add("Expected " + type.name());
-
-        throw sce;
-    }
-
-    @PreAuthorize("hasRole('" + IdRepoEntitlement.LOG_READ + "') and authentication.details.domain == "
-            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
-    @Transactional(readOnly = true)
-    public LoggerTO readLog(final String name) {
-        return listLogs().stream().
-                filter(logger -> logger.getKey().equals(name)).findFirst().
-                orElseThrow(() -> new NotFoundException("Logger " + name));
+    public List<AuditConfTO> list() {
+        return auditDAO.findAll().stream().map(binder::getAuditTO).collect(Collectors.toList());
     }
 
     @PreAuthorize("hasRole('" + IdRepoEntitlement.AUDIT_READ + "')")
     @Transactional(readOnly = true)
-    public LoggerTO readAudit(final String name) {
-        return listAudits().stream().
-                filter(logger -> logger.toLoggerName().equals(name)).findFirst().
-                map(binder::getLoggerTO).orElseThrow(() -> new NotFoundException("Audit " + name));
+    public AuditConfTO read(final String key) {
+        return Optional.ofNullable(auditDAO.find(key)).map(binder::getAuditTO).
+                orElseThrow(() -> new NotFoundException("Audit " + key));
     }
 
-    private LoggerTO setLevel(final String name, final Level level, final LoggerType expectedType) {
-        Logger syncopeLogger = loggerDAO.find(name);
-        if (syncopeLogger == null) {
-            LOG.debug("Logger {} not found: creating new...", name);
-
-            syncopeLogger = entityFactory.newEntity(Logger.class);
-            syncopeLogger.setKey(name);
-            syncopeLogger.setType(name.startsWith(LoggerType.AUDIT.getPrefix())
-                    ? LoggerType.AUDIT
-                    : LoggerType.LOG);
-        }
-
-        if (expectedType != syncopeLogger.getType()) {
-            throwInvalidLogger(expectedType);
-        }
-
-        syncopeLogger.setLevel(LoggerLevel.fromLevel(level));
-        syncopeLogger = loggerDAO.save(syncopeLogger);
-
-        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
-        LoggerConfig logConf;
-
-        if (LoggerType.AUDIT.equals(syncopeLogger.getType())) {
-            String auditLoggerName = AuditLoggerName.getAuditEventLoggerName(
-                    AuthContextUtils.getDomain(), syncopeLogger.getKey());
-
-            logConf = ctx.getConfiguration().getLoggerConfig(auditLoggerName);
+    @PreAuthorize("hasRole('" + IdRepoEntitlement.AUDIT_CREATE + "')")
+    public void create(final AuditConfTO auditTO) {
+        AuditConf audit = entityFactory.newEntity(AuditConf.class);
+        audit.setKey(auditTO.getKey());
+        audit.setActive(auditTO.isActive());
+        audit = auditDAO.save(audit);
 
-            // SYNCOPE-1144 For each custom audit appender class add related appenders to log4j logger
-            boolean isRootLogConf = LogManager.ROOT_LOGGER_NAME.equals(logConf.getName());
-            if (isRootLogConf) {
-                logConf = new LoggerConfig(auditLoggerName, null, false);
-            }
-            for (AuditAppender auditAppender : loggerLoader.auditAppenders(AuthContextUtils.getDomain())) {
-                if (auditAppender.getEvents().stream().anyMatch(event -> name.equalsIgnoreCase(event.toLoggerName()))) {
-                    LoggerLoader.addAppenderToContext(ctx, auditAppender, logConf);
-                }
-            }
-            if (isRootLogConf) {
-                ctx.getConfiguration().addLogger(auditLoggerName, logConf);
-            }
-        } else {
-            logConf = SyncopeConstants.ROOT_LOGGER.equals(name)
-                    ? ctx.getConfiguration().getLoggerConfig(LogManager.ROOT_LOGGER_NAME)
-                    : ctx.getConfiguration().getLoggerConfig(name);
+        if (audit.isActive()) {
+            setLevel(audit.getKey(), Level.DEBUG);
         }
-
-        logConf.setLevel(level);
-        ctx.updateLoggers();
-
-        return binder.getLoggerTO(syncopeLogger);
     }
 
-    @PreAuthorize("hasRole('" + IdRepoEntitlement.LOG_SET_LEVEL + "') and authentication.details.domain == "
-            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
-    public LoggerTO setLogLevel(final String name, final Level level) {
-        return setLevel(name, level, LoggerType.LOG);
-    }
+    @PreAuthorize("hasRole('" + IdRepoEntitlement.AUDIT_UPDATE + "')")
+    public void update(final AuditConfTO auditTO) {
+        AuditConf audit = Optional.ofNullable(auditDAO.find(auditTO.getKey())).
+                orElseThrow(() -> new NotFoundException("Audit " + auditTO.getKey()));
+        audit.setActive(auditTO.isActive());
+        audit = auditDAO.save(audit);
 
-    @PreAuthorize("hasRole('" + IdRepoEntitlement.AUDIT_ENABLE + "')")
-    public void enableAudit(final AuditLoggerName auditLoggerName) {
-        try {
-            setLevel(auditLoggerName.toLoggerName(), Level.DEBUG, LoggerType.AUDIT);
-        } catch (IllegalArgumentException | InvalidDataAccessApiUsageException e) {
-            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidLogger);
-            sce.getElements().add(e.getMessage());
-            throw sce;
+        if (audit.isActive()) {
+            setLevel(audit.getKey(), Level.OFF);
         }
     }
 
-    private LoggerTO delete(final String name, final LoggerType expectedType) {
-        Logger syncopeLogger = loggerDAO.find(name);
-        if (syncopeLogger == null) {
-            throw new NotFoundException("Logger " + name);
-        }
-        if (expectedType != syncopeLogger.getType()) {
-            throwInvalidLogger(expectedType);
-        }
+    @PreAuthorize("hasRole('" + IdRepoEntitlement.AUDIT_DELETE + "')")
+    public void delete(final String key) {
+        AuditConf audit = Optional.ofNullable(auditDAO.find(key)).
+                orElseThrow(() -> new NotFoundException("Audit " + key));
+        auditDAO.delete(audit);
 
-        LoggerTO loggerToDelete = binder.getLoggerTO(syncopeLogger);
+        setLevel(audit.getKey(), Level.OFF);
+    }
 
-        // remove SyncopeLogger from local storage, so that LoggerLoader won't load this next time
-        loggerDAO.delete(syncopeLogger);
+    private void setLevel(final String key, final Level level) {
+        String auditLoggerName = AuditLoggerName.getAuditEventLoggerName(AuthContextUtils.getDomain(), key);
 
-        // set log level to OFF in order to disable configured logger until next reboot
         LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+        LoggerConfig logConf = ctx.getConfiguration().getLoggerConfig(auditLoggerName);
 
-        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)
-                : LoggerType.AUDIT.equals(syncopeLogger.getType())
-                ? ctx.getLogger(auditLoggerName)
-                : ctx.getLogger(name);
+        // SYNCOPE-1144 For each custom audit appender class add related appenders to log4j logger
+        auditLoader.auditAppenders(AuthContextUtils.getDomain()).stream().
+                filter(appender -> appender.getEvents().stream().
+                anyMatch(event -> key.equalsIgnoreCase(event.toAuditKey()))).
+                forEach(auditAppender -> AuditLoader.addAppenderToContext(ctx, auditAppender, logConf));
 
-        logger.setLevel(Level.OFF);
+        logConf.setLevel(level);
         ctx.updateLoggers();
-
-        return loggerToDelete;
-    }
-
-    @PreAuthorize("hasRole('" + IdRepoEntitlement.LOG_DELETE + "') and authentication.details.domain == "
-            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
-    public LoggerTO deleteLog(final String name) {
-        return delete(name, LoggerType.LOG);
-    }
-
-    @PreAuthorize("hasRole('" + IdRepoEntitlement.AUDIT_DISABLE + "')")
-    public void disableAudit(final AuditLoggerName auditLoggerName) {
-        try {
-            delete(auditLoggerName.toLoggerName(), LoggerType.AUDIT);
-        } catch (NotFoundException e) {
-            LOG.debug("Ignoring disable of non existing logger {}", auditLoggerName.toLoggerName());
-        } catch (IllegalArgumentException | InvalidDataAccessApiUsageException e) {
-            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidLogger);
-            sce.getElements().add(e.getMessage());
-            throw sce;
-        }
     }
 
     @PreAuthorize("hasRole('" + IdRepoEntitlement.AUDIT_LIST + "') "
             + "or hasRole('" + IdRepoEntitlement.NOTIFICATION_LIST + "')")
-    public List<EventCategory> listAuditEvents() {
+    public List<EventCategory> events() {
         // use set to avoid duplications or null elements
         Set<EventCategory> events = new HashSet<>();
 
@@ -413,8 +264,8 @@ public class LoggerLogic extends AbstractTransactionalLogic<EntityTO> {
             final AuditElements.Result result,
             final List<OrderByClause> orderByClauses) {
 
-        int count = loggerDAO.countAuditEntries(entityKey, type, category, subcategory, events, result);
-        List<AuditEntry> matching = loggerDAO.findAuditEntries(
+        int count = auditDAO.countEntries(entityKey, type, category, subcategory, events, result);
+        List<AuditEntry> matching = auditDAO.searchEntries(
                 entityKey, page, size, type, category, subcategory, events, result, orderByClauses);
         return Pair.of(count, matching);
     }
@@ -444,9 +295,30 @@ public class LoggerLogic extends AbstractTransactionalLogic<EntityTO> {
     }
 
     @Override
-    protected EntityTO resolveReference(final Method method, final Object... args)
+    protected AuditConfTO resolveReference(final Method method, final Object... args)
             throws UnresolvedReferenceException {
 
+        String key = null;
+
+        if (ArrayUtils.isNotEmpty(args)) {
+            for (int i = 0; key == null && i < args.length; i++) {
+                if (args[i] instanceof String) {
+                    key = (String) args[i];
+                } else if (args[i] instanceof AuditConfTO) {
+                    key = ((AuditConfTO) args[i]).getKey();
+                }
+            }
+        }
+
+        if (key != null) {
+            try {
+                return binder.getAuditTO(auditDAO.find(key));
+            } catch (Throwable ignore) {
+                LOG.debug("Unresolved reference", ignore);
+                throw new UnresolvedReferenceException(ignore);
+            }
+        }
+
         throw new UnresolvedReferenceException();
     }
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/MemoryAppender.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/MemoryAppender.java
deleted file mode 100644
index c942730..0000000
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/MemoryAppender.java
+++ /dev/null
@@ -1,96 +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.Queue;
-import org.apache.logging.log4j.core.Appender;
-import org.apache.logging.log4j.core.Filter;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.appender.AbstractAppender;
-import org.apache.logging.log4j.core.config.Property;
-import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
-import org.apache.logging.log4j.core.config.plugins.PluginElement;
-import org.apache.logging.log4j.core.config.plugins.PluginFactory;
-import org.apache.logging.log4j.message.Message;
-import org.apache.logging.log4j.message.ReusableMessage;
-import org.apache.syncope.common.lib.collections.CircularFifoQueue;
-import org.apache.syncope.common.lib.log.LogStatement;
-import org.apache.syncope.common.lib.types.LoggerLevel;
-import org.apache.syncope.core.provisioning.api.utils.ExceptionUtils2;
-
-@Plugin(name = "Memory", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
-public class MemoryAppender extends AbstractAppender {
-
-    private final CircularFifoQueue<LogStatement> statements;
-
-    protected MemoryAppender(
-            final String name,
-            final int size,
-            final Filter filter,
-            final boolean ignoreExceptions) {
-
-        super(name, filter, null, ignoreExceptions, Property.EMPTY_ARRAY);
-        this.statements = new CircularFifoQueue<>(size);
-    }
-
-    @Override
-    public void append(final LogEvent event) {
-        LogStatement statement = new LogStatement();
-
-        statement.setLevel(LoggerLevel.fromLevel(event.getLevel()));
-        statement.setLoggerName(event.getLoggerName());
-
-        Message msg = event.getMessage();
-        statement.setMessage((msg instanceof ReusableMessage
-                ? ((ReusableMessage) msg).memento()
-                : msg).getFormattedMessage());
-
-        statement.setTimeMillis(event.getTimeMillis());
-
-        if (event.getThrown() != null) {
-            statement.setStackTrace(ExceptionUtils2.getFullStackTrace(event.getThrown()));
-        }
-
-        statement.setThreadId(event.getThreadId());
-        statement.setThreadName(event.getThreadName());
-        statement.setThreadPriority(event.getThreadPriority());
-
-        this.statements.add(statement);
-    }
-
-    public Queue<LogStatement> getStatements() {
-        return statements;
-    }
-
-    @PluginFactory
-    public static MemoryAppender createAppender(
-            @PluginAttribute("name") final String name,
-            @PluginAttribute(value = "size", defaultInt = 10) final int size,
-            @PluginElement("Filter") final Filter filter,
-            @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions) {
-
-        return new MemoryAppender(
-                name,
-                size,
-                filter,
-                ignoreExceptions);
-    }
-
-}
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/JdbcAuditAppender.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/JdbcAuditAppender.java
index e96132f..896bd85 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/JdbcAuditAppender.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/audit/JdbcAuditAppender.java
@@ -29,9 +29,9 @@ import org.apache.logging.log4j.core.appender.db.ColumnMapping;
 import org.apache.logging.log4j.core.appender.db.jdbc.AbstractConnectionSource;
 import org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender;
 import org.apache.syncope.core.persistence.api.DomainHolder;
-import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.datasource.DataSourceUtils;
+import org.apache.syncope.core.persistence.api.dao.AuditConfDAO;
 
 public class JdbcAuditAppender extends DefaultAuditAppender {
 
@@ -51,7 +51,7 @@ public class JdbcAuditAppender extends DefaultAuditAppender {
             setConfiguration(ctx.getConfiguration()).setName("LOGGER").setPattern("%logger").build(),
             ColumnMapping.newBuilder().
             setConfiguration(ctx.getConfiguration()).
-            setName(LoggerDAO.AUDIT_MESSAGE_COLUMN).setPattern("%message").build(),
+            setName(AuditConfDAO.AUDIT_ENTRY_MESSAGE_COLUMN).setPattern("%message").build(),
             ColumnMapping.newBuilder().
             setConfiguration(ctx.getConfiguration()).setName("THROWABLE").setPattern("%ex{full}").build()
         };
@@ -63,7 +63,7 @@ public class JdbcAuditAppender extends DefaultAuditAppender {
                     setIgnoreExceptions(false).
                     setConnectionSource(new DataSourceConnectionSource(domain, domainHolder.getDomains().get(domain))).
                     setBufferSize(0).
-                    setTableName(LoggerDAO.AUDIT_TABLE).
+                    setTableName(AuditConfDAO.AUDIT_ENTRY_TABLE).
                     setColumnMappings(columnMappings).
                     build();
             appender.start();
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/AuditAccessor.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/AuditAccessor.java
new file mode 100644
index 0000000..b8dcaf7
--- /dev/null
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/AuditAccessor.java
@@ -0,0 +1,60 @@
+/*
+ * 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.init;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
+import org.apache.syncope.core.spring.security.AuthContextUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+import org.apache.syncope.core.persistence.api.entity.AuditConf;
+import org.apache.syncope.core.persistence.api.dao.AuditConfDAO;
+
+/**
+ * Domain-sensible (via {@code @Transactional} access to audit data.
+ *
+ * @see AuditLoader
+ */
+@Component
+public class AuditAccessor {
+
+    @Autowired
+    private AuditConfDAO auditDAO;
+
+    @Transactional
+    public void synchronizeLoggingWithAudit(final LoggerContext ctx) {
+        Map<String, AuditConf> audits = auditDAO.findAll().stream().
+                collect(Collectors.toMap(
+                        audit -> AuditLoggerName.getAuditEventLoggerName(AuthContextUtils.getDomain(), audit.getKey()),
+                        Function.identity()));
+
+        audits.forEach((logger, audit) -> {
+            LoggerConfig logConf = ctx.getConfiguration().getLoggerConfig(logger);
+            logConf.setLevel(audit.isActive() ? Level.DEBUG : Level.OFF);
+        });
+
+        ctx.updateLoggers();
+    }
+}
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/AuditLoader.java
similarity index 89%
rename from core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java
rename to core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/AuditLoader.java
index 45ea48c..280415a 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/AuditLoader.java
@@ -18,9 +18,7 @@
  */
 package org.apache.syncope.core.logic.init;
 
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
 import javax.sql.DataSource;
@@ -32,7 +30,6 @@ 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.audit.AuditAppender;
-import org.apache.syncope.core.logic.MemoryAppender;
 import org.apache.syncope.core.logic.audit.JdbcAuditAppender;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
@@ -45,10 +42,10 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
 import org.springframework.stereotype.Component;
 
 @Component
-public class LoggerLoader implements SyncopeCoreLoader {
+public class AuditLoader implements SyncopeCoreLoader {
 
     @Autowired
-    private LoggerAccessor loggerAccessor;
+    private AuditAccessor auditAccessor;
 
     @Autowired
     private ImplementationLookup implementationLookup;
@@ -56,8 +53,6 @@ public class LoggerLoader implements SyncopeCoreLoader {
     @Value("${enable.jdbcAuditAppender:true}")
     private boolean enableJdbcAuditAppender;
 
-    private final Map<String, MemoryAppender> memoryAppenders = new HashMap<>();
-
     @Override
     public int getOrder() {
         return 300;
@@ -67,10 +62,6 @@ public class LoggerLoader implements SyncopeCoreLoader {
     public void load(final String domain, final DataSource datasource) {
         LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
 
-        ctx.getConfiguration().getAppenders().entrySet().stream().
-                filter(entry -> entry.getValue() instanceof MemoryAppender).
-                forEach(entry -> memoryAppenders.put(entry.getKey(), (MemoryAppender) entry.getValue()));
-
         if (enableJdbcAuditAppender) {
             JdbcAuditAppender jdbcAuditAppender = (JdbcAuditAppender) ApplicationContextProvider.getBeanFactory().
                     createBean(JdbcAuditAppender.class, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
@@ -84,7 +75,7 @@ public class LoggerLoader implements SyncopeCoreLoader {
 
         // SYNCOPE-1144 For each custom audit appender class add related appenders to log4j logger
         auditAppenders(domain).forEach(auditAppender -> auditAppender.getEvents().stream().
-                map(event -> AuditLoggerName.getAuditEventLoggerName(domain, event.toLoggerName())).
+                map(event -> AuditLoggerName.getAuditEventLoggerName(domain, event.toAuditKey())).
                 forEach(domainAuditLoggerName -> {
                     LoggerConfig eventLogConf = ctx.getConfiguration().getLoggerConfig(domainAuditLoggerName);
                     boolean isRootLogConf = LogManager.ROOT_LOGGER_NAME.equals(eventLogConf.getName());
@@ -99,17 +90,13 @@ public class LoggerLoader implements SyncopeCoreLoader {
                 }));
 
         AuthContextUtils.callAsAdmin(domain, () -> {
-            loggerAccessor.synchronizeLog4J(ctx);
+            auditAccessor.synchronizeLoggingWithAudit(ctx);
             return null;
         });
 
         ctx.updateLoggers();
     }
 
-    public Map<String, MemoryAppender> getMemoryAppenders() {
-        return memoryAppenders;
-    }
-
     public List<AuditAppender> auditAppenders(final String domain) throws BeansException {
         return implementationLookup.getAuditAppenderClasses().stream().map(clazz -> {
             AuditAppender auditAppender;
@@ -119,6 +106,7 @@ public class LoggerLoader implements SyncopeCoreLoader {
             } else {
                 auditAppender = (AuditAppender) ApplicationContextProvider.getBeanFactory().
                         createBean(clazz, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
+                ApplicationContextProvider.getBeanFactory().registerSingleton(clazz.getName(), auditAppender);
                 auditAppender.init(domain);
             }
             return auditAppender;
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerAccessor.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerAccessor.java
deleted file mode 100644
index 4b057e3..0000000
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerAccessor.java
+++ /dev/null
@@ -1,98 +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.init;
-
-import java.util.HashMap;
-import java.util.Map;
-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.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-
-/**
- * Domain-sensible (via {@code @Transactional} access to logger / audit data.
- *
- * @see LoggerLoader
- */
-@Component
-public class LoggerAccessor {
-
-    @Autowired
-    private LoggerDAO loggerDAO;
-
-    @Autowired
-    private EntityFactory entityFactory;
-
-    @Transactional
-    public void synchronizeLog4J(final LoggerContext ctx) {
-        Map<String, Logger> syncopeLoggers = new HashMap<>();
-        if (SyncopeConstants.MASTER_DOMAIN.equals(AuthContextUtils.getDomain())) {
-            for (Logger syncopeLogger : loggerDAO.findAll(LoggerType.LOG)) {
-                syncopeLoggers.put(syncopeLogger.getKey(), syncopeLogger);
-            }
-        }
-        for (Logger syncopeLogger : loggerDAO.findAll(LoggerType.AUDIT)) {
-            syncopeLoggers.put(AuditLoggerName.getAuditEventLoggerName(
-                    AuthContextUtils.getDomain(), syncopeLogger.getKey()), syncopeLogger);
-        }
-
-        /*
-         * Traverse all defined log4j loggers: if there is a matching SyncopeLogger, set log4j level accordingly,
-         * otherwise create a SyncopeLogger instance with given name and level.
-         */
-        for (LoggerConfig logConf : ctx.getConfiguration().getLoggers().values()) {
-            String loggerName = LogManager.ROOT_LOGGER_NAME.equals(logConf.getName())
-                    ? SyncopeConstants.ROOT_LOGGER : logConf.getName();
-            if (logConf.getLevel() != null) {
-                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())) {
-
-                    Logger syncopeLogger = entityFactory.newEntity(Logger.class);
-                    syncopeLogger.setKey(loggerName);
-                    syncopeLogger.setLevel(LoggerLevel.fromLevel(logConf.getLevel()));
-                    syncopeLogger.setType(LoggerType.LOG);
-                    loggerDAO.save(syncopeLogger);
-                }
-            }
-        }
-
-        /*
-         * Foreach SyncopeLogger not found in log4j create a new log4j logger with given name and level.
-         */
-        for (Map.Entry<String, Logger> entry : syncopeLoggers.entrySet()) {
-            LoggerConfig logConf = ctx.getConfiguration().getLoggerConfig(entry.getKey());
-            logConf.setLevel(entry.getValue().getLevel().getLevel());
-        }
-
-        ctx.updateLoggers();
-    }
-}
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AuditServiceImpl.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AuditServiceImpl.java
new file mode 100644
index 0000000..998ee76
--- /dev/null
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AuditServiceImpl.java
@@ -0,0 +1,89 @@
+/*
+ * 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.rest.cxf.service;
+
+import java.util.List;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.audit.AuditEntry;
+import org.apache.syncope.common.lib.audit.EventCategory;
+import org.apache.syncope.common.lib.to.AuditConfTO;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.rest.api.beans.AuditQuery;
+import org.apache.syncope.common.rest.api.service.AuditService;
+import org.apache.syncope.core.logic.AuditLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AuditServiceImpl extends AbstractServiceImpl implements AuditService {
+
+    @Autowired
+    private AuditLogic logic;
+
+    @Override
+    public List<AuditConfTO> list() {
+        return logic.list();
+    }
+
+    @Override
+    public AuditConfTO read(final String key) {
+        return logic.read(key);
+    }
+
+    @Override
+    public void create(final AuditConfTO auditTO) {
+        logic.create(auditTO);
+    }
+
+    @Override
+    public void update(final AuditConfTO auditTO) {
+        logic.update(auditTO);
+    }
+
+    @Override
+    public void delete(final String key) {
+        logic.delete(key);
+    }
+
+    @Override
+    public void create(final AuditEntry auditEntry) {
+        logic.create(auditEntry);
+    }
+
+    @Override
+    public List<EventCategory> events() {
+        return logic.events();
+    }
+
+    @Override
+    public PagedResult<AuditEntry> search(final AuditQuery auditQuery) {
+        Pair<Integer, List<AuditEntry>> result = logic.search(
+                auditQuery.getEntityKey(),
+                auditQuery.getPage(),
+                auditQuery.getSize(),
+                auditQuery.getType(),
+                auditQuery.getCategory(),
+                auditQuery.getSubcategory(),
+                auditQuery.getEvents(),
+                auditQuery.getResult(),
+                getOrderByClauses(auditQuery.getOrderBy()));
+
+        return buildPagedResult(result.getRight(), auditQuery.getPage(), auditQuery.getSize(), result.getLeft());
+    }
+}
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/LoggerServiceImpl.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/LoggerServiceImpl.java
deleted file mode 100644
index 9367c9d..0000000
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/LoggerServiceImpl.java
+++ /dev/null
@@ -1,150 +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.rest.cxf.service;
-
-import java.text.ParseException;
-import java.util.List;
-import javax.ws.rs.BadRequestException;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.log.AuditEntry;
-import org.apache.syncope.common.lib.log.EventCategory;
-import org.apache.syncope.common.lib.log.LogAppender;
-import org.apache.syncope.common.lib.log.LogStatement;
-import org.apache.syncope.common.lib.log.LoggerTO;
-import org.apache.syncope.common.lib.to.PagedResult;
-import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.common.lib.types.LoggerType;
-import org.apache.syncope.common.rest.api.LoggerWrapper;
-import org.apache.syncope.common.rest.api.beans.AuditQuery;
-import org.apache.syncope.common.rest.api.service.LoggerService;
-import org.apache.syncope.core.logic.LoggerLogic;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-@Service
-public class LoggerServiceImpl extends AbstractServiceImpl implements LoggerService {
-
-    @Autowired
-    private LoggerLogic logic;
-
-    @Override
-    public List<LogAppender> memoryAppenders() {
-        return logic.memoryAppenders();
-    }
-
-    @Override
-    public List<LogStatement> getLastLogStatements(final String memoryAppender) {
-        return logic.getLastLogStatements(memoryAppender);
-    }
-    
-    @Override
-    public void create(final AuditEntry auditEntry) {
-        logic.create(auditEntry);
-    }
-
-    @Override
-    public void delete(final LoggerType type, final String name) {
-        switch (type) {
-            case LOG:
-                logic.deleteLog(name);
-                break;
-
-            case AUDIT:
-                try {
-                logic.disableAudit(AuditLoggerName.fromLoggerName(name));
-            } catch (IllegalArgumentException | ParseException e) {
-                throw new BadRequestException(e);
-            }
-            break;
-
-            default:
-                throw new BadRequestException();
-        }
-    }
-
-    @Override
-    public List<LoggerTO> list(final LoggerType type) {
-        switch (type) {
-            case LOG:
-                return logic.listLogs();
-
-            case AUDIT:
-                List<AuditLoggerName> auditLogger = logic.listAudits();
-                return LoggerWrapper.unwrap(auditLogger);
-
-            default:
-                throw new BadRequestException();
-        }
-    }
-
-    @Override
-    public LoggerTO read(final LoggerType type, final String name) {
-        switch (type) {
-            case LOG:
-                return logic.readLog(name);
-
-            case AUDIT:
-                return logic.readAudit(name);
-
-            default:
-                throw new BadRequestException();
-        }
-    }
-
-    @Override
-    public void update(final LoggerType type, final LoggerTO logger) {
-        switch (type) {
-            case LOG:
-                logic.setLogLevel(logger.getKey(), logger.getLevel().getLevel());
-                break;
-
-            case AUDIT:
-                try {
-                logic.enableAudit(AuditLoggerName.fromLoggerName(logger.getKey()));
-            } catch (Exception e) {
-                throw new BadRequestException(e);
-            }
-            break;
-
-            default:
-                throw new BadRequestException();
-        }
-    }
-
-    @Override
-    public List<EventCategory> events() {
-        return logic.listAuditEvents();
-    }
-
-    @Override
-    public PagedResult<AuditEntry> search(final AuditQuery auditQuery) {
-        Pair<Integer, List<AuditEntry>> result = logic.search(
-                auditQuery.getEntityKey(),
-                auditQuery.getPage(),
-                auditQuery.getSize(),
-                auditQuery.getType(),
-                auditQuery.getCategory(),
-                auditQuery.getSubcategory(),
-                auditQuery.getEvents(),
-                auditQuery.getResult(),
-                getOrderByClauses(auditQuery.getOrderBy()));
-
-        return buildPagedResult(result.getRight(), auditQuery.getPage(), auditQuery.getSize(), result.getLeft());
-    }
-}
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/LoggerDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AuditConfDAO.java
similarity index 74%
rename from core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/LoggerDAO.java
rename to core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AuditConfDAO.java
index 0539ef3..96d2158 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/LoggerDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AuditConfDAO.java
@@ -19,29 +19,26 @@
 package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.common.lib.types.AuditElements;
-import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.entity.Logger;
+import org.apache.syncope.core.persistence.api.entity.AuditConf;
 
-public interface LoggerDAO extends DAO<Logger> {
+public interface AuditConfDAO extends DAO<AuditConf> {
 
-    String AUDIT_TABLE = "SYNCOPEAUDIT";
+    String AUDIT_ENTRY_TABLE = "AuditEntry";
 
-    String AUDIT_MESSAGE_COLUMN = "MESSAGE";
+    String AUDIT_ENTRY_MESSAGE_COLUMN = "MESSAGE";
 
-    Logger find(String key);
+    AuditConf find(String key);
 
-    List<Logger> findAll(LoggerType type);
+    List<AuditConf> findAll();
 
-    Logger save(Logger logger);
+    AuditConf save(AuditConf auditConf);
 
-    void delete(String key);
+    void delete(AuditConf auditConf);
 
-    void delete(Logger logger);
-
-    int countAuditEntries(
+    int countEntries(
             String entityKey,
             AuditElements.EventCategoryType type,
             String category,
@@ -49,7 +46,7 @@ public interface LoggerDAO extends DAO<Logger> {
             List<String> events,
             AuditElements.Result result);
 
-    List<AuditEntry> findAuditEntries(
+    List<AuditEntry> searchEntries(
             String entityKey,
             int page,
             int size,
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Logger.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AuditConf.java
similarity index 73%
rename from core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Logger.java
rename to core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AuditConf.java
index 875854b..b43edcf 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Logger.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AuditConf.java
@@ -18,18 +18,9 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-import org.apache.syncope.common.lib.types.LoggerLevel;
-import org.apache.syncope.common.lib.types.LoggerType;
+public interface AuditConf extends ProvidedKeyEntity {
 
-public interface Logger extends Entity {
+    boolean isActive();
 
-    void setKey(String name);
-
-    LoggerLevel getLevel();
-
-    void setLevel(LoggerLevel level);
-
-    LoggerType getType();
-
-    void setType(LoggerType type);
+    void setActive(boolean active);
 }
diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONLoggerDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONLoggerDAO.java
index 3a7c1f3..7f2a098 100644
--- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONLoggerDAO.java
+++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractJPAJSONLoggerDAO.java
@@ -27,7 +27,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.springframework.util.CollectionUtils;
 
-public abstract class AbstractJPAJSONLoggerDAO extends JPALoggerDAO {
+public abstract class AbstractJPAJSONLoggerDAO extends JPAAuditConfDAO {
 
     private static final ObjectMapper MAPPER = new ObjectMapper();
 
diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONLoggerDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONAuditConfDAO.java
similarity index 74%
rename from core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONLoggerDAO.java
rename to core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONAuditConfDAO.java
index cd9be15..4b64c8c 100644
--- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONLoggerDAO.java
+++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MyJPAJSONAuditConfDAO.java
@@ -23,16 +23,19 @@ import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 
-public class MyJPAJSONLoggerDAO extends AbstractJPAJSONLoggerDAO {
+public class MyJPAJSONAuditConfDAO extends AbstractJPAJSONLoggerDAO {
 
     private static class MyMessageCriteriaBuilder extends JSONMessageCriteriaBuilder {
 
         @Override
         protected String doBuild(final List<ObjectNode> containers) {
             if (entityKey != null) {
-                query.append('(').append(AUDIT_MESSAGE_COLUMN).append("->'$.before' LIKE '%").append(entityKey).
-                        append("%' OR ").append(AUDIT_MESSAGE_COLUMN).append("->'$.input' LIKE '%").append(entityKey).
-                        append("%' OR ").append(AUDIT_MESSAGE_COLUMN).append("->'$.output' LIKE '%").append(entityKey).
+                query.append('(').
+                        append(AUDIT_ENTRY_MESSAGE_COLUMN).append("->'$.before' LIKE '%").append(entityKey).
+                        append("%' OR ").
+                        append(AUDIT_ENTRY_MESSAGE_COLUMN).append("->'$.input' LIKE '%").append(entityKey).
+                        append("%' OR ").
+                        append(AUDIT_ENTRY_MESSAGE_COLUMN).append("->'$.output' LIKE '%").append(entityKey).
                         append("%')");
             }
 
@@ -40,7 +43,8 @@ public class MyJPAJSONLoggerDAO extends AbstractJPAJSONLoggerDAO {
                 if (entityKey != null) {
                     query.append(" AND (");
                 }
-                query.append(containers.stream().map(container -> "JSON_CONTAINS(" + AUDIT_MESSAGE_COLUMN + ", '"
+                query.append(containers.stream().
+                        map(container -> "JSON_CONTAINS(" + AUDIT_ENTRY_MESSAGE_COLUMN + ", '"
                         + POJOHelper.serialize(container).replace("'", "''")
                         + "')").collect(Collectors.joining(" OR ")));
                 if (entityKey != null) {
diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONLoggerDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAuditConfDAO.java
similarity index 74%
rename from core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONLoggerDAO.java
rename to core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAuditConfDAO.java
index 071625d..4e9acf5 100644
--- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONLoggerDAO.java
+++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAuditConfDAO.java
@@ -24,16 +24,19 @@ import java.util.stream.Collectors;
 import org.apache.syncope.core.persistence.jpa.dao.AbstractJPAJSONLoggerDAO.JSONMessageCriteriaBuilder;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 
-public class PGJPAJSONLoggerDAO extends AbstractJPAJSONLoggerDAO {
+public class PGJPAJSONAuditConfDAO extends AbstractJPAJSONLoggerDAO {
 
     private static class PGMessageCriteriaBuilder extends JSONMessageCriteriaBuilder {
 
         @Override
         protected String doBuild(final List<ObjectNode> containers) {
             if (entityKey != null) {
-                query.append('(').append(AUDIT_MESSAGE_COLUMN).append(" ->> 'before' LIKE '%").append(entityKey).
-                        append("%' OR ").append(AUDIT_MESSAGE_COLUMN).append(" ->> 'input' LIKE '%").append(entityKey).
-                        append("%' OR ").append(AUDIT_MESSAGE_COLUMN).append(" ->> 'output' LIKE '%").append(entityKey).
+                query.append('(').
+                        append(AUDIT_ENTRY_MESSAGE_COLUMN).append(" ->> 'before' LIKE '%").append(entityKey).
+                        append("%' OR ").
+                        append(AUDIT_ENTRY_MESSAGE_COLUMN).append(" ->> 'input' LIKE '%").append(entityKey).
+                        append("%' OR ").
+                        append(AUDIT_ENTRY_MESSAGE_COLUMN).append(" ->> 'output' LIKE '%").append(entityKey).
                         append("%')");
             }
 
@@ -41,7 +44,8 @@ public class PGJPAJSONLoggerDAO extends AbstractJPAJSONLoggerDAO {
                 if (entityKey != null) {
                     query.append(" AND (");
                 }
-                query.append(containers.stream().map(container -> AUDIT_MESSAGE_COLUMN + "::jsonb @> '"
+                query.append(containers.stream().
+                        map(container -> AUDIT_ENTRY_MESSAGE_COLUMN + "::jsonb @> '"
                         + POJOHelper.serialize(container).replace("'", "''")
                         + "'::jsonb").collect(Collectors.joining(" OR ")));
                 if (entityKey != null) {
@@ -55,7 +59,7 @@ public class PGJPAJSONLoggerDAO extends AbstractJPAJSONLoggerDAO {
 
     @Override
     protected String select() {
-        return AUDIT_MESSAGE_COLUMN + "::text";
+        return AUDIT_ENTRY_MESSAGE_COLUMN + "::text";
     }
 
     @Override
diff --git a/core/persistence-jpa-json/src/main/resources/audit/audit_myjson.sql b/core/persistence-jpa-json/src/main/resources/audit/audit_myjson.sql
index af5d37b..2ffba2e 100644
--- a/core/persistence-jpa-json/src/main/resources/audit/audit_myjson.sql
+++ b/core/persistence-jpa-json/src/main/resources/audit/audit_myjson.sql
@@ -15,7 +15,7 @@
 -- specific language governing permissions and limitations
 -- under the License.
 
-CREATE TABLE IF NOT EXISTS SYNCOPEAUDIT (
+CREATE TABLE IF NOT EXISTS AuditEntry (
   EVENT_DATE TIMESTAMP,
   LOGGER_LEVEL VARCHAR(255) NOT NULL,
   LOGGER VARCHAR(255) NOT NULL,
diff --git a/core/persistence-jpa-json/src/main/resources/audit/audit_pgjsonb.sql b/core/persistence-jpa-json/src/main/resources/audit/audit_pgjsonb.sql
index 0edbdf8..0104222 100644
--- a/core/persistence-jpa-json/src/main/resources/audit/audit_pgjsonb.sql
+++ b/core/persistence-jpa-json/src/main/resources/audit/audit_pgjsonb.sql
@@ -15,11 +15,11 @@
 -- specific language governing permissions and limitations
 -- under the License.
 
-CREATE TABLE IF NOT EXISTS SYNCOPEAUDIT (
+CREATE TABLE IF NOT EXISTS AuditEntry (
   EVENT_DATE TIMESTAMP,
   LOGGER_LEVEL VARCHAR(255) NOT NULL,
   LOGGER VARCHAR(255) NOT NULL,
   MESSAGE JSONB NOT NULL,
   THROWABLE TEXT
 );
-CREATE INDEX SYNCOPEAUDIT_idx ON SYNCOPEAUDIT USING gin ((MESSAGE) jsonb_path_ops)
+CREATE INDEX AuditEntry_idx ON AuditEntry USING gin ((MESSAGE) jsonb_path_ops)
diff --git a/core/persistence-jpa-json/src/main/resources/myjson/persistence.properties b/core/persistence-jpa-json/src/main/resources/myjson/persistence.properties
index a2a38a9..fe430c2 100644
--- a/core/persistence-jpa-json/src/main/resources/myjson/persistence.properties
+++ b/core/persistence-jpa-json/src/main/resources/myjson/persistence.properties
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
-logger.dao=org.apache.syncope.core.persistence.jpa.dao.MyJPAJSONLoggerDAO
+audit.dao=org.apache.syncope.core.persistence.jpa.dao.MyJPAJSONAuditConfDAO
 openjpa.RemoteCommitProvider=sjvm
diff --git a/core/persistence-jpa-json/src/main/resources/pgjsonb/persistence.properties b/core/persistence-jpa-json/src/main/resources/pgjsonb/persistence.properties
index 5bb728a..f8eb86e 100644
--- a/core/persistence-jpa-json/src/main/resources/pgjsonb/persistence.properties
+++ b/core/persistence-jpa-json/src/main/resources/pgjsonb/persistence.properties
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
-logger.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONLoggerDAO
+audit.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONAuditConfDAO
 openjpa.RemoteCommitProvider=sjvm
diff --git a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
index 6821ddd..bf0e75a 100644
--- a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
@@ -2428,48 +2428,48 @@ $$ }&#10;
   <SyncopeRole_entitlements role_id="GROUP_OWNER" entitlement="GROUP_UPDATE"/>
   <SyncopeRole_entitlements role_id="GROUP_OWNER" entitlement="GROUP_DELETE"/>
 
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[SyncopeLogic]:[]:[isSelfRegAllowed]:[SUCCESS]" logLevel="DEBUG"/>
-
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[WA]:[LoggerLogic]:[AUTHENTICATION]:[validate]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[WA]:[LoggerLogic]:[AuthenticationEvent]:[auth]:[SUCCESS]" logLevel="DEBUG"/>
-
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[ConnectorLogic]:[]:[create]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[ConnectorLogic]:[]:[update]:[SUCCESS]" logLevel="DEBUG"/>
-
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[ResourceLogic]:[]:[create]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]" logLevel="DEBUG"/>
-
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[assign]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[confirmPasswordReset]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[create]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[deprovision]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[link]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[mustChangePassword]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[provision]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[requestPasswordReset]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[selfCreate]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[selfStatus]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[selfUpdate]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[status]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[unassign]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[unlink]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[update]:[SUCCESS]" logLevel="DEBUG"/>
-
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[assign]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[create]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[deprovision]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[provisionMembers]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[unassign]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[unlink]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[update]:[SUCCESS]" logLevel="DEBUG"/>
-
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[assign]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[create]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[delete]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[deprovision]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[link]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[provision]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[unassign]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[unlink]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[update]:[SUCCESS]" logLevel="DEBUG"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[SyncopeLogic]:[]:[isSelfRegAllowed]:[SUCCESS]" active="1"/>
+
+  <AuditConf id="syncope.audit.[WA]:[]:[AUTHENTICATION]:[validate]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[WA]:[]:[AuthenticationEvent]:[auth]:[SUCCESS]" active="1"/>
+
+  <AuditConf id="syncope.audit.[LOGIC]:[ConnectorLogic]:[]:[create]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[ConnectorLogic]:[]:[update]:[SUCCESS]" active="1"/>
+
+  <AuditConf id="syncope.audit.[LOGIC]:[ResourceLogic]:[]:[create]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]" active="1"/>
+
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[assign]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[confirmPasswordReset]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[create]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[deprovision]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[link]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[mustChangePassword]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[provision]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[requestPasswordReset]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[selfCreate]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[selfStatus]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[selfUpdate]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[status]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[unassign]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[unlink]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[update]:[SUCCESS]" active="1"/>
+
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[assign]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[create]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[deprovision]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[provisionMembers]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[unassign]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[unlink]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[update]:[SUCCESS]" active="1"/>
+
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[assign]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[create]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[delete]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[deprovision]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[link]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[provision]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[unassign]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[unlink]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[update]:[SUCCESS]" active="1"/>
 </dataset>
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
index 9d48a90..d5825f6 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java
@@ -26,7 +26,6 @@ import javax.validation.Validator;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
-import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainAttrValueDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
@@ -48,6 +47,7 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.PropertySource;
 import org.springframework.core.env.Environment;
 import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
+import org.apache.syncope.core.persistence.api.dao.AuditConfDAO;
 
 @PropertySource("classpath:persistence.properties")
 @PropertySource(value = "file:${conf.directory}/persistence.properties", ignoreResourceNotFound = true)
@@ -182,13 +182,13 @@ public class PersistenceContext implements EnvironmentAware {
         return (AnyObjectDAO) Class.forName(env.getProperty("anyObject.dao")).getConstructor().newInstance();
     }
 
-    @ConditionalOnMissingBean(name = "loggerDAO")
+    @ConditionalOnMissingBean(name = "auditDAO")
     @Bean
-    public LoggerDAO loggerDAO()
+    public AuditConfDAO auditDAO()
             throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException,
             IllegalArgumentException, InvocationTargetException {
 
-        return (LoggerDAO) Class.forName(env.getProperty("logger.dao")).getConstructor().newInstance();
+        return (AuditConfDAO) Class.forName(env.getProperty("audit.dao")).getConstructor().newInstance();
     }
 
     @Bean
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
index 538821f..7074f89 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
@@ -71,7 +71,7 @@ import org.apache.openjpa.lib.util.collections.DualHashBidiMap;
 import org.apache.syncope.core.persistence.api.DomainHolder;
 import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
 import org.apache.syncope.core.persistence.api.content.ContentExporter;
-import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
+import org.apache.syncope.core.persistence.api.dao.AuditConfDAO;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAccessToken;
 import org.apache.syncope.core.persistence.jpa.entity.JPARealm;
@@ -109,7 +109,7 @@ public class XMLContentExporter implements ContentExporter {
     private static final Logger LOG = LoggerFactory.getLogger(XMLContentExporter.class);
 
     private static final Set<String> TABLE_PREFIXES_TO_BE_EXCLUDED = Stream.of(
-            "QRTZ_", "LOGGING", "NotificationTask_recipients", LoggerDAO.AUDIT_TABLE, JPAReportExec.TABLE,
+            "QRTZ_", "LOGGING", "NotificationTask_recipients", AuditConfDAO.AUDIT_ENTRY_TABLE, JPAReportExec.TABLE,
             JPATaskExec.TABLE, JPAUser.TABLE, JPAUPlainAttr.TABLE, JPAUPlainAttrValue.TABLE,
             JPAUPlainAttrUniqueValue.TABLE, JPAURelationship.TABLE, JPAUMembership.TABLE,
             JPAAnyObject.TABLE, JPAAPlainAttr.TABLE, JPAAPlainAttrValue.TABLE, JPAAPlainAttrUniqueValue.TABLE,
@@ -468,7 +468,7 @@ public class XMLContentExporter implements ContentExporter {
                         String tableName = joinTable.name();
                         if (StringUtils.isBlank(tableName)) {
                             tableName = entities.getKey(e) + "_"
-                                    + entities.getKey((EntityType) ((PluralAttribute) a).getElementType());
+                                    + entities.getKey(((PluralAttribute) a).getElementType());
                         }
 
                         relationTables.put(
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPALoggerDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAuditConfDAO.java
similarity index 75%
rename from core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPALoggerDAO.java
rename to core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAuditConfDAO.java
index a2f44dd..cc30ead 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPALoggerDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAuditConfDAO.java
@@ -26,18 +26,16 @@ import java.util.stream.Collectors;
 import javax.persistence.Query;
 import javax.persistence.TypedQuery;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.common.lib.types.AuditElements;
-import org.apache.syncope.common.lib.types.LoggerLevel;
-import org.apache.syncope.common.lib.types.LoggerType;
-import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.entity.Logger;
-import org.apache.syncope.core.persistence.jpa.entity.JPALogger;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.springframework.transaction.annotation.Transactional;
+import org.apache.syncope.core.persistence.jpa.entity.JPAAuditConf;
+import org.apache.syncope.core.persistence.api.entity.AuditConf;
+import org.apache.syncope.core.persistence.api.dao.AuditConfDAO;
 
-public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
+public class JPAAuditConfDAO extends AbstractDAO<AuditConf> implements AuditConfDAO {
 
     protected static class MessageCriteriaBuilder {
 
@@ -49,7 +47,7 @@ public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
 
         protected MessageCriteriaBuilder entityKey(final String entityKey) {
             if (entityKey != null) {
-                query.append(andIfNeeded()).append(AUDIT_MESSAGE_COLUMN).
+                query.append(andIfNeeded()).append(AUDIT_ENTRY_MESSAGE_COLUMN).
                         append(" LIKE '%key%").append(entityKey).append("%'");
             }
             return this;
@@ -57,7 +55,7 @@ public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
 
         public MessageCriteriaBuilder type(final AuditElements.EventCategoryType type) {
             if (type != null) {
-                query.append(andIfNeeded()).append(AUDIT_MESSAGE_COLUMN).
+                query.append(andIfNeeded()).append(AUDIT_ENTRY_MESSAGE_COLUMN).
                         append(" LIKE '%\"type\":\"").append(type.name()).append("\"%'");
             }
             return this;
@@ -65,7 +63,7 @@ public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
 
         public MessageCriteriaBuilder category(final String category) {
             if (StringUtils.isNotBlank(category)) {
-                query.append(andIfNeeded()).append(AUDIT_MESSAGE_COLUMN).
+                query.append(andIfNeeded()).append(AUDIT_ENTRY_MESSAGE_COLUMN).
                         append(" LIKE '%\"category\":\"").append(category).append("\"%'");
             }
             return this;
@@ -73,7 +71,7 @@ public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
 
         public MessageCriteriaBuilder subcategory(final String subcategory) {
             if (StringUtils.isNotBlank(subcategory)) {
-                query.append(andIfNeeded()).append(AUDIT_MESSAGE_COLUMN).
+                query.append(andIfNeeded()).append(AUDIT_ENTRY_MESSAGE_COLUMN).
                         append(" LIKE '%\"subcategory\":\"").append(subcategory).append("\"%'");
             }
             return this;
@@ -83,7 +81,7 @@ public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
             if (!events.isEmpty()) {
                 query.append(andIfNeeded()).append("( ").
                         append(events.stream().
-                                map(event -> AUDIT_MESSAGE_COLUMN + " LIKE '%\"event\":\"" + event + "\"%'").
+                                map(event -> AUDIT_ENTRY_MESSAGE_COLUMN + " LIKE '%\"event\":\"" + event + "\"%'").
                                 collect(Collectors.joining(" OR "))).
                         append(" )");
             }
@@ -92,7 +90,7 @@ public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
 
         public MessageCriteriaBuilder result(final AuditElements.Result result) {
             if (result != null) {
-                query.append(andIfNeeded()).append(AUDIT_MESSAGE_COLUMN).
+                query.append(andIfNeeded()).append(AUDIT_ENTRY_MESSAGE_COLUMN).
                         append(" LIKE '%\"result\":\"").append(result.name()).append("\"%' ");
             }
             return this;
@@ -104,40 +102,25 @@ public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
     }
 
     @Override
-    public Logger find(final String key) {
-        return entityManager().find(JPALogger.class, key);
+    public AuditConf find(final String key) {
+        return entityManager().find(JPAAuditConf.class, key);
     }
 
     @Override
-    public List<Logger> findAll(final LoggerType type) {
-        TypedQuery<Logger> query = entityManager().createQuery(
-                "SELECT e FROM " + JPALogger.class.getSimpleName() + " e WHERE e.type=:type", Logger.class);
-        query.setParameter("type", type);
+    public List<AuditConf> findAll() {
+        TypedQuery<AuditConf> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAAuditConf.class.getSimpleName() + " e ", AuditConf.class);
         return query.getResultList();
     }
 
     @Override
-    public Logger save(final Logger logger) {
-        // Audit loggers must be either OFF or DEBUG, no more options
-        if (LoggerType.AUDIT == logger.getType() && LoggerLevel.OFF != logger.getLevel()) {
-            logger.setLevel(LoggerLevel.DEBUG);
-        }
-        return entityManager().merge(logger);
-    }
-
-    @Override
-    public void delete(final Logger logger) {
-        entityManager().remove(logger);
+    public AuditConf save(final AuditConf auditConf) {
+        return entityManager().merge(auditConf);
     }
 
     @Override
-    public void delete(final String key) {
-        Logger logger = find(key);
-        if (logger == null) {
-            return;
-        }
-
-        delete(logger);
+    public void delete(final AuditConf auditConf) {
+        entityManager().remove(auditConf);
     }
 
     protected MessageCriteriaBuilder messageCriteriaBuilder(final String entityKey) {
@@ -145,7 +128,7 @@ public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
     }
 
     @Override
-    public int countAuditEntries(
+    public int countEntries(
             final String entityKey,
             final AuditElements.EventCategoryType type,
             final String category,
@@ -154,7 +137,7 @@ public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
             final AuditElements.Result result) {
 
         String queryString = "SELECT COUNT(0)"
-                + " FROM " + AUDIT_TABLE
+                + " FROM " + AUDIT_ENTRY_TABLE
                 + " WHERE " + messageCriteriaBuilder(entityKey).
                         type(type).
                         category(category).
@@ -168,12 +151,12 @@ public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
     }
 
     protected String select() {
-        return AUDIT_MESSAGE_COLUMN;
+        return AUDIT_ENTRY_MESSAGE_COLUMN;
     }
 
     @Transactional(readOnly = true)
     @Override
-    public List<AuditEntry> findAuditEntries(
+    public List<AuditEntry> searchEntries(
             final String entityKey,
             final int page,
             final int itemsPerPage,
@@ -185,7 +168,7 @@ public class JPALoggerDAO extends AbstractDAO<Logger> implements LoggerDAO {
             final List<OrderByClause> orderByClauses) {
 
         String queryString = "SELECT " + select()
-                + " FROM " + AUDIT_TABLE
+                + " FROM " + AUDIT_ENTRY_TABLE
                 + " WHERE " + messageCriteriaBuilder(entityKey).
                         type(type).
                         category(category).
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/LoggerType.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAuditConf.java
similarity index 54%
rename from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/LoggerType.java
rename to core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAuditConf.java
index c696d6e..7762526 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/LoggerType.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAuditConf.java
@@ -16,30 +16,31 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.core.persistence.jpa.entity;
 
-import org.apache.commons.lang3.StringUtils;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.core.persistence.api.entity.AuditConf;
 
-public enum LoggerType {
+@Entity
+@Table(name = JPAAuditConf.TABLE)
+public class JPAAuditConf extends AbstractProvidedKeyEntity implements AuditConf {
 
-    /**
-     * This type describes a common logger used to handle system and application events.
-     */
-    LOG(StringUtils.EMPTY),
-    /**
-     * Audit logger only focus on security related events, usually logging how did what and when.
-     * In case of a security incident audit loggers should allow an administrator to recall all
-     * actions a certain user has done.
-     */
-    AUDIT("syncope.audit");
+    private static final long serialVersionUID = 943012777014416027L;
 
-    private final String prefix;
+    public static final String TABLE = "AuditConf";
 
-    LoggerType(final String prefix) {
-        this.prefix = prefix;
+    @NotNull
+    private Boolean active = true;
+
+    @Override
+    public boolean isActive() {
+        return active;
     }
 
-    public String getPrefix() {
-        return prefix;
+    @Override
+    public void setActive(final boolean active) {
+        this.active = active;
     }
 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
index c15bdb2..0b1b369 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
@@ -35,7 +35,6 @@ import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
 import org.apache.syncope.core.persistence.api.entity.Entity;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
-import org.apache.syncope.core.persistence.api.entity.Logger;
 import org.apache.syncope.core.persistence.api.entity.MailTemplate;
 import org.apache.syncope.core.persistence.api.entity.Notification;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
@@ -168,6 +167,7 @@ import org.apache.syncope.core.persistence.api.entity.auth.SAML2SPEntity;
 import org.apache.syncope.core.persistence.api.entity.auth.SAML2SPClientApp;
 import org.apache.syncope.core.persistence.api.entity.auth.CASSPClientApp;
 import org.apache.syncope.core.persistence.api.entity.auth.OIDCRPClientApp;
+import org.apache.syncope.core.persistence.api.entity.AuditConf;
 
 public class JPAEntityFactory implements EntityFactory {
 
@@ -302,8 +302,8 @@ public class JPAEntityFactory implements EntityFactory {
             result = (E) new JPAAnyTemplatePullTask();
         } else if (reference.equals(SecurityQuestion.class)) {
             result = (E) new JPASecurityQuestion();
-        } else if (reference.equals(Logger.class)) {
-            result = (E) new JPALogger();
+        } else if (reference.equals(AuditConf.class)) {
+            result = (E) new JPAAuditConf();
         } else if (reference.equals(DynRoleMembership.class)) {
             result = (E) new JPADynRoleMembership();
         } else if (reference.equals(ADynGroupMembership.class)) {
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPALogger.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPALogger.java
deleted file mode 100644
index ce5e1ab..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPALogger.java
+++ /dev/null
@@ -1,80 +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.persistence.jpa.entity;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.Id;
-import javax.persistence.Table;
-import org.apache.syncope.common.lib.types.LoggerLevel;
-import org.apache.syncope.common.lib.types.LoggerType;
-import org.apache.syncope.core.persistence.api.entity.Logger;
-
-@Entity
-@Table(name = JPALogger.TABLE)
-public class JPALogger extends AbstractEntity implements Logger {
-
-    private static final long serialVersionUID = 943012777014416027L;
-
-    public static final String TABLE = "SyncopeLogger";
-
-    @Id
-    @Column(name = "logName")
-    private String key;
-
-    @Column(name = "logLevel", nullable = false)
-    @Enumerated(EnumType.STRING)
-    private LoggerLevel level;
-
-    @Column(name = "logType", nullable = false)
-    @Enumerated(EnumType.STRING)
-    private LoggerType type;
-
-    @Override
-    public String getKey() {
-        return key;
-    }
-
-    @Override
-    public void setKey(final String name) {
-        this.key = name;
-    }
-
-    @Override
-    public LoggerLevel getLevel() {
-        return level;
-    }
-
-    @Override
-    public void setLevel(final LoggerLevel level) {
-        this.level = level;
-    }
-
-    @Override
-    public LoggerType getType() {
-        return type;
-    }
-
-    @Override
-    public void setType(final LoggerType type) {
-        this.type = type;
-    }
-}
diff --git a/core/persistence-jpa/src/main/resources/audit/audit.sql b/core/persistence-jpa/src/main/resources/audit/audit.sql
index 1526b50..23eefc2 100644
--- a/core/persistence-jpa/src/main/resources/audit/audit.sql
+++ b/core/persistence-jpa/src/main/resources/audit/audit.sql
@@ -15,7 +15,7 @@
 -- specific language governing permissions and limitations
 -- under the License.
 
-CREATE TABLE IF NOT EXISTS SYNCOPEAUDIT (
+CREATE TABLE IF NOT EXISTS AuditEntry (
   EVENT_DATE TIMESTAMP,
   LOGGER_LEVEL VARCHAR(255) NOT NULL,
   LOGGER VARCHAR(255) NOT NULL,
diff --git a/core/persistence-jpa/src/main/resources/audit/audit_mariadb.sql b/core/persistence-jpa/src/main/resources/audit/audit_mariadb.sql
index c6ee824..1612342 100644
--- a/core/persistence-jpa/src/main/resources/audit/audit_mariadb.sql
+++ b/core/persistence-jpa/src/main/resources/audit/audit_mariadb.sql
@@ -15,7 +15,7 @@
 -- specific language governing permissions and limitations
 -- under the License.
 
-CREATE TABLE IF NOT EXISTS SYNCOPEAUDIT (
+CREATE TABLE IF NOT EXISTS AuditEntry (
   EVENT_DATE TIMESTAMP,
   LOGGER_LEVEL VARCHAR(255) NOT NULL,
   LOGGER VARCHAR(255) NOT NULL,
diff --git a/core/persistence-jpa/src/main/resources/audit/audit_mysql_innodb.sql b/core/persistence-jpa/src/main/resources/audit/audit_mysql_innodb.sql
index 0376c1f..e3ab42e 100644
--- a/core/persistence-jpa/src/main/resources/audit/audit_mysql_innodb.sql
+++ b/core/persistence-jpa/src/main/resources/audit/audit_mysql_innodb.sql
@@ -15,7 +15,7 @@
 -- specific language governing permissions and limitations
 -- under the License.
 
-CREATE TABLE IF NOT EXISTS SYNCOPEAUDIT (
+CREATE TABLE IF NOT EXISTS AuditEntry (
   EVENT_DATE TIMESTAMP,
   LOGGER_LEVEL VARCHAR(255) NOT NULL,
   LOGGER VARCHAR(255) NOT NULL,
diff --git a/core/persistence-jpa/src/main/resources/audit/audit_oracle.sql b/core/persistence-jpa/src/main/resources/audit/audit_oracle.sql
index 9115bee..6dd4d02 100644
--- a/core/persistence-jpa/src/main/resources/audit/audit_oracle.sql
+++ b/core/persistence-jpa/src/main/resources/audit/audit_oracle.sql
@@ -15,7 +15,7 @@
 -- specific language governing permissions and limitations
 -- under the License.
 
-CREATE TABLE SYNCOPEAUDIT (
+CREATE TABLE AuditEntry (
   EVENT_DATE TIMESTAMP,
   LOGGER_LEVEL VARCHAR(255) NOT NULL,
   LOGGER VARCHAR(255) NOT NULL,
diff --git a/core/persistence-jpa/src/main/resources/audit/audit_sqlserver.sql b/core/persistence-jpa/src/main/resources/audit/audit_sqlserver.sql
index 4615af6..a802cdb 100644
--- a/core/persistence-jpa/src/main/resources/audit/audit_sqlserver.sql
+++ b/core/persistence-jpa/src/main/resources/audit/audit_sqlserver.sql
@@ -15,10 +15,10 @@
 -- specific language governing permissions and limitations
 -- under the License.
 
-IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[SYNCOPEAUDIT]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
-DROP TABLE [dbo].[SYNCOPEAUDIT];
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[AuditEntry]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[AuditEntry];
 
-CREATE TABLE SYNCOPEAUDIT (
+CREATE TABLE AuditEntry (
   EVENT_DATE DATETIME,
   LOGGER_LEVEL VARCHAR(255) NOT NULL,
   LOGGER VARCHAR(255) NOT NULL,
diff --git a/core/persistence-jpa/src/main/resources/persistence.properties b/core/persistence-jpa/src/main/resources/persistence.properties
index b547e65..0ed337d 100644
--- a/core/persistence-jpa/src/main/resources/persistence.properties
+++ b/core/persistence-jpa/src/main/resources/persistence.properties
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAnyObjectDAO
-logger.dao=org.apache.syncope.core.persistence.jpa.dao.JPALoggerDAO
+audit.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAuditConfDAO
 openjpa.RemoteCommitProvider=sjvm
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RoleTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RoleTest.java
index 5e536e3..239e257 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RoleTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RoleTest.java
@@ -29,6 +29,7 @@ import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.RoleDAO;
 import org.apache.syncope.core.persistence.api.entity.Role;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -57,9 +58,7 @@ public class RoleTest extends AbstractTest {
         List<Role> list = roleDAO.findAll();
         assertNotNull(list);
         assertFalse(list.isEmpty());
-        for (Role role : list) {
-            assertNotNull(role);
-        }
+        list.forEach(Assertions::assertNotNull);
     }
 
     @Test
@@ -68,8 +67,8 @@ public class RoleTest extends AbstractTest {
         role.setKey("new");
         role.add(realmDAO.getRoot());
         role.add(realmDAO.findByFullPath("/even/two"));
-        role.getEntitlements().add(IdRepoEntitlement.LOG_LIST);
-        role.getEntitlements().add(IdRepoEntitlement.LOG_SET_LEVEL);
+        role.getEntitlements().add(IdRepoEntitlement.AUDIT_LIST);
+        role.getEntitlements().add(IdRepoEntitlement.AUDIT_UPDATE);
 
         Role actual = roleDAO.save(role);
         assertNotNull(actual);
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AnySearchTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AnySearchTest.java
index dce7627..180d97c 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AnySearchTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AnySearchTest.java
@@ -82,8 +82,8 @@ public class AnySearchTest extends AbstractTest {
         role.setKey("new");
         role.add(realmDAO.getRoot());
         role.add(realmDAO.findByFullPath("/even/two"));
-        role.getEntitlements().add(IdRepoEntitlement.LOG_LIST);
-        role.getEntitlements().add(IdRepoEntitlement.LOG_SET_LEVEL);
+        role.getEntitlements().add(IdRepoEntitlement.AUDIT_LIST);
+        role.getEntitlements().add(IdRepoEntitlement.AUDIT_UPDATE);
 
         DynRoleMembership dynMembership = entityFactory.newEntity(DynRoleMembership.class);
         dynMembership.setFIQLCond("cool==true");
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
index 617bbf4..768e7e9 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
@@ -120,8 +120,8 @@ public class RoleTest extends AbstractTest {
         role.setKey("new");
         role.add(realmDAO.getRoot());
         role.add(realmDAO.findByFullPath("/even/two"));
-        role.getEntitlements().add(IdRepoEntitlement.LOG_LIST);
-        role.getEntitlements().add(IdRepoEntitlement.LOG_SET_LEVEL);
+        role.getEntitlements().add(IdRepoEntitlement.AUDIT_LIST);
+        role.getEntitlements().add(IdRepoEntitlement.AUDIT_UPDATE);
 
         DynRoleMembership dynMembership = entityFactory.newEntity(DynRoleMembership.class);
         dynMembership.setFIQLCond("cool==true");
@@ -184,8 +184,8 @@ public class RoleTest extends AbstractTest {
         role.setKey("new");
         role.add(realmDAO.getRoot());
         role.add(realmDAO.findByFullPath("/even/two"));
-        role.getEntitlements().add(IdRepoEntitlement.LOG_LIST);
-        role.getEntitlements().add(IdRepoEntitlement.LOG_SET_LEVEL);
+        role.getEntitlements().add(IdRepoEntitlement.AUDIT_LIST);
+        role.getEntitlements().add(IdRepoEntitlement.AUDIT_UPDATE);
 
         role = roleDAO.save(role);
         assertNotNull(role);
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index f67c79c..25d3776 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -2515,48 +2515,48 @@ $$ }&#10;
   <SyncopeRole_entitlements role_id="GROUP_OWNER" entitlement="GROUP_UPDATE"/>
   <SyncopeRole_entitlements role_id="GROUP_OWNER" entitlement="GROUP_DELETE"/>
 
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[SyncopeLogic]:[]:[isSelfRegAllowed]:[SUCCESS]" logLevel="DEBUG"/>
-
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[WA]:[LoggerLogic]:[AUTHENTICATION]:[validate]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[WA]:[LoggerLogic]:[AuthenticationEvent]:[auth]:[SUCCESS]" logLevel="DEBUG"/>
-
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[ConnectorLogic]:[]:[create]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[ConnectorLogic]:[]:[update]:[SUCCESS]" logLevel="DEBUG"/>
-
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[ResourceLogic]:[]:[create]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]" logLevel="DEBUG"/>
-
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[assign]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[confirmPasswordReset]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[create]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[deprovision]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[link]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[mustChangePassword]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[provision]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[requestPasswordReset]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[selfCreate]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[selfStatus]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[selfUpdate]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[status]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[unassign]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[unlink]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[UserLogic]:[]:[update]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[assign]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[create]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[deprovision]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[provisionMembers]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[unassign]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[unlink]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[GroupLogic]:[]:[update]:[SUCCESS]" logLevel="DEBUG"/>
-
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[assign]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[create]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[delete]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[deprovision]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[link]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[provision]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[unassign]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[unlink]:[SUCCESS]" logLevel="DEBUG"/>
-  <SyncopeLogger logType="AUDIT" logName="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[update]:[SUCCESS]" logLevel="DEBUG"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[SyncopeLogic]:[]:[isSelfRegAllowed]:[SUCCESS]" active="1"/>
+
+  <AuditConf id="syncope.audit.[WA]:[]:[AUTHENTICATION]:[validate]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[WA]:[]:[AuthenticationEvent]:[auth]:[SUCCESS]" active="1"/>
+
+  <AuditConf id="syncope.audit.[LOGIC]:[ConnectorLogic]:[]:[create]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[ConnectorLogic]:[]:[update]:[SUCCESS]" active="1"/>
+
+  <AuditConf id="syncope.audit.[LOGIC]:[ResourceLogic]:[]:[create]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]" active="1"/>
+
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[assign]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[confirmPasswordReset]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[create]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[deprovision]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[link]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[mustChangePassword]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[provision]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[requestPasswordReset]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[selfCreate]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[selfStatus]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[selfUpdate]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[status]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[unassign]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[unlink]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[UserLogic]:[]:[update]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[assign]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[create]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[deprovision]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[provisionMembers]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[unassign]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[unlink]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[GroupLogic]:[]:[update]:[SUCCESS]" active="1"/>
+
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[assign]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[create]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[delete]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[deprovision]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[link]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[provision]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[unassign]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[unlink]:[SUCCESS]" active="1"/>
+  <AuditConf id="syncope.audit.[LOGIC]:[AnyObjectLogic]:[]:[update]:[SUCCESS]" active="1"/>
 
 </dataset>
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/LoggerDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AuditDataBinder.java
similarity index 73%
rename from core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/LoggerDataBinder.java
rename to core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AuditDataBinder.java
index 1b491ce..f7ecfbf 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/LoggerDataBinder.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AuditDataBinder.java
@@ -18,13 +18,10 @@
  */
 package org.apache.syncope.core.provisioning.api.data;
 
-import org.apache.syncope.common.lib.log.LoggerTO;
-import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.core.persistence.api.entity.Logger;
+import org.apache.syncope.common.lib.to.AuditConfTO;
+import org.apache.syncope.core.persistence.api.entity.AuditConf;
 
-public interface LoggerDataBinder {
+public interface AuditDataBinder {
 
-    LoggerTO getLoggerTO(Logger logger);
-
-    LoggerTO getLoggerTO(AuditLoggerName auditLoggerName);
+    AuditConfTO getAuditTO(AuditConf audit);
 }
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java
index 934f03a..ce9b631 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java
@@ -22,7 +22,7 @@ import java.util.Arrays;
 import java.util.Date;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.SerializationUtils;
-import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.common.lib.request.UserCR;
 import org.apache.syncope.common.lib.request.UserUR;
 import org.apache.syncope.common.lib.to.UserTO;
@@ -30,9 +30,7 @@ import org.apache.syncope.core.provisioning.api.AuditManager;
 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.core.provisioning.api.serialization.POJOHelper;
-import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
 import org.apache.syncope.core.provisioning.api.event.AfterHandlingEvent;
 import org.apache.syncope.core.provisioning.api.utils.ExceptionUtils2;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
@@ -41,6 +39,8 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
+import org.apache.syncope.core.persistence.api.entity.AuditConf;
+import org.apache.syncope.core.persistence.api.dao.AuditConfDAO;
 
 @Transactional(readOnly = true)
 public class DefaultAuditManager implements AuditManager {
@@ -77,7 +77,7 @@ public class DefaultAuditManager implements AuditManager {
     }
 
     @Autowired
-    private LoggerDAO loggerDAO;
+    private AuditConfDAO auditDAO;
 
     @Override
     public boolean auditRequested(
@@ -92,9 +92,8 @@ public class DefaultAuditManager implements AuditManager {
         auditEntry.setLogger(new AuditLoggerName(type, category, subcategory, event, Result.SUCCESS));
         auditEntry.setDate(new Date());
 
-        org.apache.syncope.core.persistence.api.entity.Logger syncopeLogger =
-                loggerDAO.find(auditEntry.getLogger().toLoggerName());
-        boolean auditRequested = syncopeLogger != null && syncopeLogger.getLevel() == LoggerLevel.DEBUG;
+        AuditConf audit = auditDAO.find(auditEntry.getLogger().toAuditKey());
+        boolean auditRequested = audit != null && audit.isActive();
 
         if (auditRequested) {
             return true;
@@ -102,8 +101,8 @@ public class DefaultAuditManager implements AuditManager {
 
         auditEntry.setLogger(new AuditLoggerName(type, category, subcategory, event, Result.FAILURE));
 
-        syncopeLogger = loggerDAO.find(auditEntry.getLogger().toLoggerName());
-        auditRequested = syncopeLogger != null && syncopeLogger.getLevel() == LoggerLevel.DEBUG;
+        audit = auditDAO.find(auditEntry.getLogger().toAuditKey());
+        auditRequested = audit != null && audit.isActive();
 
         return auditRequested;
     }
@@ -138,9 +137,8 @@ public class DefaultAuditManager implements AuditManager {
 
         AuditLoggerName auditLoggerName = new AuditLoggerName(type, category, subcategory, event, condition);
 
-        org.apache.syncope.core.persistence.api.entity.Logger syncopeLogger =
-                loggerDAO.find(auditLoggerName.toLoggerName());
-        if (syncopeLogger != null && syncopeLogger.getLevel() == LoggerLevel.DEBUG) {
+        AuditConf audit = auditDAO.find(auditLoggerName.toAuditKey());
+        if (audit != null && audit.isActive()) {
             Throwable throwable = null;
             if (output instanceof Throwable) {
                 throwable = (Throwable) output;
@@ -166,7 +164,7 @@ public class DefaultAuditManager implements AuditManager {
             Logger logger = LoggerFactory.getLogger(
                     AuditLoggerName.getAuditLoggerName(AuthContextUtils.getDomain()));
             Logger eventLogger = LoggerFactory.getLogger(
-                    AuditLoggerName.getAuditEventLoggerName(AuthContextUtils.getDomain(), syncopeLogger.getKey()));
+                    AuditLoggerName.getAuditEventLoggerName(AuthContextUtils.getDomain(), audit.getKey()));
             String serializedAuditEntry = POJOHelper.serialize(auditEntry);
 
             if (throwable == null) {
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/LoggerLevel.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AuditDataBinderImpl.java
similarity index 57%
rename from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/LoggerLevel.java
rename to core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AuditDataBinderImpl.java
index dd54348..a74d0cc 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/LoggerLevel.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AuditDataBinderImpl.java
@@ -16,32 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.core.provisioning.java.data;
 
-import org.apache.logging.log4j.Level;
+import org.apache.syncope.common.lib.to.AuditConfTO;
+import org.springframework.stereotype.Component;
+import org.apache.syncope.core.provisioning.api.data.AuditDataBinder;
+import org.apache.syncope.core.persistence.api.entity.AuditConf;
 
-public enum LoggerLevel {
+@Component
+public class AuditDataBinderImpl implements AuditDataBinder {
 
-    OFF(Level.OFF),
-    FATAL(Level.FATAL),
-    ERROR(Level.ERROR),
-    WARN(Level.WARN),
-    INFO(Level.INFO),
-    DEBUG(Level.DEBUG),
-    TRACE(Level.TRACE),
-    ALL(Level.ALL);
-
-    private final Level level;
-
-    LoggerLevel(final Level level) {
-        this.level = level;
-    }
-
-    public Level getLevel() {
-        return level;
-    }
-
-    public static LoggerLevel fromLevel(final Level level) {
-        return LoggerLevel.valueOf(level.name());
+    @Override
+    public AuditConfTO getAuditTO(final AuditConf audit) {
+        AuditConfTO auditTO = new AuditConfTO();
+        auditTO.setKey(audit.getKey());
+        auditTO.setActive(audit.isActive());
+        return auditTO;
     }
 }
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/LoggerDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/LoggerDataBinderImpl.java
deleted file mode 100644
index 906c92d..0000000
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/LoggerDataBinderImpl.java
+++ /dev/null
@@ -1,46 +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.provisioning.java.data;
-
-import org.apache.syncope.common.lib.log.LoggerTO;
-import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.common.lib.types.LoggerLevel;
-import org.apache.syncope.core.persistence.api.entity.Logger;
-import org.springframework.stereotype.Component;
-import org.apache.syncope.core.provisioning.api.data.LoggerDataBinder;
-
-@Component
-public class LoggerDataBinderImpl implements LoggerDataBinder {
-
-    @Override
-    public LoggerTO getLoggerTO(final Logger logger) {
-        LoggerTO loggerTO = new LoggerTO();
-        loggerTO.setKey(logger.getKey());
-        loggerTO.setLevel(logger.getLevel());
-        return loggerTO;
-    }
-
-    @Override
-    public LoggerTO getLoggerTO(final AuditLoggerName auditLoggerName) {
-        LoggerTO loggerTO = new LoggerTO();
-        loggerTO.setKey(auditLoggerName.toLoggerName());
-        loggerTO.setLevel(LoggerLevel.DEBUG);
-        return loggerTO;
-    }
-}
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/AuditReportlet.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/AuditReportlet.java
index 7a67647..beccfc0 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/AuditReportlet.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/report/AuditReportlet.java
@@ -23,11 +23,10 @@ import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.sql.DataSource;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.common.lib.report.AuditReportletConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.core.persistence.api.DomainHolder;
-import org.apache.syncope.core.persistence.api.dao.LoggerDAO;
 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.ReportletConfClass;
@@ -36,6 +35,7 @@ import org.springframework.jdbc.core.JdbcTemplate;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
+import org.apache.syncope.core.persistence.api.dao.AuditConfDAO;
 
 @ReportletConfClass(AuditReportletConf.class)
 public class AuditReportlet extends AbstractReportlet {
@@ -48,12 +48,12 @@ public class AuditReportlet extends AbstractReportlet {
     private DataSource datasource;
 
     private void doExtractConf(final ContentHandler handler, final AtomicReference<String> status) throws SAXException {
-        status.set("Fetching " + conf.getSize() + " rows from the " + LoggerDAO.AUDIT_TABLE + " table");
+        status.set("Fetching " + conf.getSize() + " rows from the " + AuditConfDAO.AUDIT_ENTRY_TABLE + " table");
 
         JdbcTemplate jdbcTemplate = new JdbcTemplate(datasource);
         jdbcTemplate.setMaxRows(conf.getSize());
         List<Map<String, Object>> rows = jdbcTemplate.
-                queryForList("SELECT * FROM " + LoggerDAO.AUDIT_TABLE + " ORDER BY EVENT_DATE DESC");
+                queryForList("SELECT * FROM " + AuditConfDAO.AUDIT_ENTRY_TABLE + " ORDER BY EVENT_DATE DESC");
 
         handler.startElement("", "", "events", null);
         AttributesImpl atts = new AttributesImpl();
@@ -119,7 +119,7 @@ public class AuditReportlet extends AbstractReportlet {
         }
         handler.endElement("", "", "events");
 
-        status.set("Fetched " + conf.getSize() + " rows from the SYNCOPEAUDIT table");
+        status.set("Fetched " + conf.getSize() + " rows from the " + AuditConfDAO.AUDIT_ENTRY_TABLE + " table");
     }
 
     @Override
diff --git a/docker/core/src/main/resources/log4j2.xml b/docker/core/src/main/resources/log4j2.xml
index 063d123..d9796f2 100644
--- a/docker/core/src/main/resources/log4j2.xml
+++ b/docker/core/src/main/resources/log4j2.xml
@@ -25,151 +25,111 @@ under the License.
       <PatternLayout pattern="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} %highlight{${LOG_LEVEL_PATTERN:-%5p}}{FATAL=red blink, ERROR=red, WARN=yellow bold, INFO=green, DEBUG=green bold, TRACE=blue} [%11.11t] %style{%-60.60c{60}}{cyan} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
     </Console>
 
-    <Memory name="main" size="25"/>
-
-    <Memory name="persistence" size="25"/>
-
-    <Memory name="rest" size="25"/>
-
-    <Memory name="connid" size="25"/>
-    
   </appenders>
   
   <loggers>
     
     <asyncLogger name="org.apache.syncope.core.persistence" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="persistence"/>
     </asyncLogger>
     <asyncLogger name="org.springframework.orm" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="persistence"/>
     </asyncLogger>
     <asyncLogger name="org.apache.openjpa" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="persistence"/>
     </asyncLogger>
     <asyncLogger name="org.apache.ibatis" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="persistence"/>
     </asyncLogger>
     
     <asyncLogger name="org.apache.syncope.core.rest" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="rest"/>
     </asyncLogger>
     <asyncLogger name="org.springframework.web" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="rest"/>
     </asyncLogger>
     <asyncLogger name="org.apache.http" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="rest"/>
     </asyncLogger>
     <asyncLogger name="org.apache.cxf" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="rest"/>
     </asyncLogger>
     
     <asyncLogger name="org.identityconnectors" additivity="false" level="DEBUG">
       <appender-ref ref="console"/>
-      <appender-ref ref="connid"/>
     </asyncLogger>
     <asyncLogger name="net.tirasa.connid" additivity="false" level="DEBUG">
       <appender-ref ref="console"/>
-      <appender-ref ref="connid"/>
     </asyncLogger>
     <asyncLogger name="org.apache.syncope.core.provisioning.api.ConnIdBundleManager" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="connid"/>
     </asyncLogger>
     
     <asyncLogger name="org.apache.syncope" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.syncope.core.provisioning" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.syncope.core.logic" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.springframework" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.quartz" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.flowable" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="liquibase" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.cocoon" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.fop" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.camel" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.wss4j" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.xml" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.opensaml" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="io.swagger" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.reflections" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.elasticsearch" additivity="false" level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="io.netty" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="com.zaxxer.hikari" additivity="false" level="ERROR">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     
     <!-- To enable when setting 'mail.debug=true' in mail.properties -->
     <!--<asyncLogger name="org.apache.syncope.core.provisioning.java.job.notification" additivity="false" level="DEBUG">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="javax.mail" additivity="false" level="DEBUG">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </asyncLogger>-->
     
     <root level="INFO">
       <appender-ref ref="console"/>
-      <appender-ref ref="main"/>
     </root>
     
   </loggers>
diff --git a/docker/core/src/main/resources/persistence.properties.all b/docker/core/src/main/resources/persistence.properties.all
index 4808aa0..34293b8 100644
--- a/docker/core/src/main/resources/persistence.properties.all
+++ b/docker/core/src/main/resources/persistence.properties.all
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAnyObjectDAO
-logger.dao=org.apache.syncope.core.persistence.jpa.dao.JPALoggerDAO
+audit.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAuditConfDAO
 openjpa.RemoteCommitProvider=${OPENJPA_REMOTE_COMMIT}
diff --git a/docker/core/src/main/resources/persistence.properties.myjson b/docker/core/src/main/resources/persistence.properties.myjson
index 20b19a8..f32258e 100644
--- a/docker/core/src/main/resources/persistence.properties.myjson
+++ b/docker/core/src/main/resources/persistence.properties.myjson
@@ -25,5 +25,5 @@ user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
 conf.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONConfDAO
-logger.dao=org.apache.syncope.core.persistence.jpa.dao.MyJPAJSONLoggerDAO
+audit.dao=org.apache.syncope.core.persistence.jpa.dao.MyJPAJSONAuditConfDAO
 openjpa.RemoteCommitProvider=sjvm
diff --git a/docker/core/src/main/resources/persistence.properties.pgjsonb b/docker/core/src/main/resources/persistence.properties.pgjsonb
index 238a10b..ab20e0d 100644
--- a/docker/core/src/main/resources/persistence.properties.pgjsonb
+++ b/docker/core/src/main/resources/persistence.properties.pgjsonb
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
-logger.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONLoggerDAO
+audit.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONAuditConfDAO
 openjpa.RemoteCommitProvider=${OPENJPA_REMOTE_COMMIT}
diff --git a/ext/elasticsearch/persistence-jpa/src/main/resources/persistence.properties b/ext/elasticsearch/persistence-jpa/src/main/resources/persistence.properties
index 6a968d8..6cbab38 100644
--- a/ext/elasticsearch/persistence-jpa/src/main/resources/persistence.properties
+++ b/ext/elasticsearch/persistence-jpa/src/main/resources/persistence.properties
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAnyObjectDAO
-logger.dao=org.apache.syncope.core.persistence.jpa.dao.JPALoggerDAO
+audit.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAuditConfDAO
 openjpa.RemoteCommitProvider=sjvm
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 ca508f7..cbe4f44 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
@@ -57,13 +57,13 @@ public class TestFileAuditAppender extends DefaultAuditAppender {
     protected void initTargetAppender() {
         LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
         // get log file path from existing file appender
-        RollingRandomAccessFileAppender mainFile =
-                (RollingRandomAccessFileAppender) ctx.getConfiguration().getAppender("mainFile");
+        RollingRandomAccessFileAppender main =
+                (RollingRandomAccessFileAppender) ctx.getConfiguration().getAppender("main");
 
-        String pathPrefix = mainFile == null
+        String pathPrefix = main == null
                 ? System.getProperty("user.dir") + StringUtils.replace("/target/log", "/", File.separator)
                 + File.separator
-                : StringUtils.replace(mainFile.getFileName(), "core.log", StringUtils.EMPTY);
+                : StringUtils.replace(main.getFileName(), "core.log", StringUtils.EMPTY);
 
         targetAppender = FileAppender.newBuilder().
                 setName(getTargetAppenderName()).
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 9741a29..afc7528 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
@@ -49,9 +49,9 @@ public class TestFileRewriteAuditAppender extends DefaultRewriteAuditAppender {
         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);
+        RollingRandomAccessFileAppender main =
+                (RollingRandomAccessFileAppender) ctx.getConfiguration().getAppender("main");
+        String pathPrefix = StringUtils.replace(main.getFileName(), "core.log", StringUtils.EMPTY);
 
         targetAppender = FileAppender.newBuilder().
                 setName(getTargetAppenderName()).
diff --git a/fit/core-reference/src/main/resources/elasticsearch/persistence.properties b/fit/core-reference/src/main/resources/elasticsearch/persistence.properties
index 6a968d8..6cbab38 100644
--- a/fit/core-reference/src/main/resources/elasticsearch/persistence.properties
+++ b/fit/core-reference/src/main/resources/elasticsearch/persistence.properties
@@ -24,5 +24,5 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAnyObjectDAO
-logger.dao=org.apache.syncope.core.persistence.jpa.dao.JPALoggerDAO
+audit.dao=org.apache.syncope.core.persistence.jpa.dao.JPAAuditConfDAO
 openjpa.RemoteCommitProvider=sjvm
diff --git a/fit/core-reference/src/main/resources/log4j2.xml b/fit/core-reference/src/main/resources/log4j2.xml
index d0ddcbb..acecff4 100644
--- a/fit/core-reference/src/main/resources/log4j2.xml
+++ b/fit/core-reference/src/main/resources/log4j2.xml
@@ -21,7 +21,7 @@ under the License.
 
   <appenders>
 
-    <RollingRandomAccessFile name="mainFile" fileName="${log.directory}/core.log"
+    <RollingRandomAccessFile name="main" fileName="${log.directory}/core.log"
                              filePattern="${log.directory}/core-%d{yyyy-MM-dd}.log.gz"
                              immediateFlush="false" append="true">
       <PatternLayout>
@@ -32,9 +32,8 @@ under the License.
         <SizeBasedTriggeringPolicy size="250 MB"/>
       </Policies>
     </RollingRandomAccessFile>
-    <Memory name="main" size="25"/>
 
-    <RollingRandomAccessFile name="persistenceFile" fileName="${log.directory}/core-persistence.log"
+    <RollingRandomAccessFile name="persistence" fileName="${log.directory}/core-persistence.log"
                              filePattern="${log.directory}/core-persistence-%d{yyyy-MM-dd}.log.gz"
                              immediateFlush="false" append="true">
       <PatternLayout>
@@ -45,9 +44,8 @@ under the License.
         <SizeBasedTriggeringPolicy size="250 MB"/>
       </Policies>
     </RollingRandomAccessFile>
-    <Memory name="persistence" size="25"/>
 
-    <RollingRandomAccessFile name="restFile" fileName="${log.directory}/core-rest.log"
+    <RollingRandomAccessFile name="rest" fileName="${log.directory}/core-rest.log"
                              filePattern="${log.directory}/core-rest-%d{yyyy-MM-dd}.log.gz"
                              immediateFlush="false" append="true">
       <PatternLayout>
@@ -58,9 +56,8 @@ under the License.
         <SizeBasedTriggeringPolicy size="250 MB"/>
       </Policies>
     </RollingRandomAccessFile>
-    <Memory name="rest" size="25"/>
 
-    <RollingRandomAccessFile name="connidFile" fileName="${log.directory}/core-connid.log"
+    <RollingRandomAccessFile name="connid" fileName="${log.directory}/core-connid.log"
                              filePattern="${log.directory}/core-connid-%d{yyyy-MM-dd}.log.gz"
                              immediateFlush="false" append="true">
       <PatternLayout>
@@ -71,160 +68,123 @@ under the License.
         <SizeBasedTriggeringPolicy size="250 MB"/>
       </Policies>
     </RollingRandomAccessFile>
-    <Memory name="connid" size="25"/>
     
   </appenders>
   
   <loggers>
     
     <asyncLogger name="org.apache.syncope.core.persistence" additivity="false" level="INFO">
-      <appender-ref ref="persistenceFile"/>
       <appender-ref ref="persistence"/>
     </asyncLogger>
     <asyncLogger name="org.springframework.orm" additivity="false" level="INFO">
-      <appender-ref ref="persistenceFile"/>
       <appender-ref ref="persistence"/>
     </asyncLogger>
     <asyncLogger name="org.apache.openjpa" additivity="false" level="INFO">
-      <appender-ref ref="persistenceFile"/>
       <appender-ref ref="persistence"/>
     </asyncLogger>
     <asyncLogger name="org.apache.ibatis" additivity="false" level="INFO">
-      <appender-ref ref="persistenceFile"/>
       <appender-ref ref="persistence"/>
     </asyncLogger>
     
     <asyncLogger name="org.apache.syncope.core.rest" additivity="false" level="INFO">
-      <appender-ref ref="restFile"/>
       <appender-ref ref="rest"/>
     </asyncLogger>
     <asyncLogger name="org.springframework.web" additivity="false" level="INFO">
-      <appender-ref ref="restFile"/>
       <appender-ref ref="rest"/>
     </asyncLogger>
     <asyncLogger name="org.apache.http" additivity="false" level="INFO">
-      <appender-ref ref="restFile"/>
       <appender-ref ref="rest"/>
     </asyncLogger>
     <asyncLogger name="org.apache.cxf" additivity="false" level="ERROR">
-      <appender-ref ref="restFile"/>
       <appender-ref ref="rest"/>
     </asyncLogger>
     <asyncLogger name="org.apache.syncope.ext.self.keymaster" additivity="false" level="ERROR">
-      <appender-ref ref="restFile"/>
       <appender-ref ref="rest"/>
     </asyncLogger>
     
     <asyncLogger name="org.identityconnectors" additivity="false" level="DEBUG">
-      <appender-ref ref="connidFile"/>
       <appender-ref ref="connid"/>
     </asyncLogger>
     <asyncLogger name="net.tirasa.connid" additivity="false" level="DEBUG">
-      <appender-ref ref="connidFile"/>
       <appender-ref ref="connid"/>
     </asyncLogger>
     <asyncLogger name="org.apache.syncope.core.provisioning.api.ConnIdBundleManager" additivity="false" level="INFO">
-      <appender-ref ref="connidFile"/>
       <appender-ref ref="connid"/>
     </asyncLogger>
     
     <asyncLogger name="org.apache.syncope" additivity="false" level="INFO">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.syncope.core.provisioning" additivity="false" level="INFO">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.syncope.core.logic" additivity="false" level="INFO">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.springframework" additivity="false" level="INFO">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.quartz" additivity="false" level="INFO">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.flowable" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="liquibase" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.cocoon" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.fop" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.camel" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.wss4j" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.xml" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.bval" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.opensaml" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="io.swagger" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.reflections" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.elasticsearch" additivity="false" level="INFO">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="io.netty" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="com.zaxxer.hikari" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.zookeeper" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="org.apache.curator" additivity="false" level="ERROR">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     
     <!-- To enable when setting 'mail.debug=true' in mail.properties -->
     <!--<asyncLogger name="org.apache.syncope.core.provisioning.java.job.notification" additivity="false" level="DEBUG">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
     <asyncLogger name="javax.mail" additivity="false" level="DEBUG">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>-->
     
     <root level="INFO">
-      <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </root>
     
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index 1f84ccd..8770f2f 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -63,7 +63,7 @@ import org.apache.syncope.common.lib.request.AnyObjectUR;
 import org.apache.syncope.common.lib.request.AttrPatch;
 import org.apache.syncope.common.lib.request.GroupUR;
 import org.apache.syncope.common.lib.request.UserUR;
-import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.common.lib.policy.PolicyTO;
 import org.apache.syncope.common.lib.request.AnyObjectCR;
 import org.apache.syncope.common.lib.request.GroupCR;
@@ -114,7 +114,6 @@ import org.apache.syncope.common.rest.api.service.CamelRouteService;
 import org.apache.syncope.common.rest.api.service.ClientAppService;
 import org.apache.syncope.common.rest.api.service.ConnectorService;
 import org.apache.syncope.common.rest.api.service.DynRealmService;
-import org.apache.syncope.common.rest.api.service.LoggerService;
 import org.apache.syncope.common.rest.api.service.NotificationService;
 import org.apache.syncope.common.rest.api.service.wa.GoogleMfaAuthAccountService;
 import org.apache.syncope.common.rest.api.service.wa.GoogleMfaAuthTokenService;
@@ -161,6 +160,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+import org.apache.syncope.common.rest.api.service.AuditService;
 
 @SpringJUnitConfig({ CoreITContext.class, SelfKeymasterClientContext.class, ZookeeperKeymasterClientContext.class })
 public abstract class AbstractITCase {
@@ -287,7 +287,7 @@ public abstract class AbstractITCase {
 
     protected static ConnectorService connectorService;
 
-    protected static LoggerService loggerService;
+    protected static AuditService auditService;
 
     protected static ReportTemplateService reportTemplateService;
 
@@ -402,7 +402,7 @@ public abstract class AbstractITCase {
         groupService = adminClient.getService(GroupService.class);
         resourceService = adminClient.getService(ResourceService.class);
         connectorService = adminClient.getService(ConnectorService.class);
-        loggerService = adminClient.getService(LoggerService.class);
+        auditService = adminClient.getService(AuditService.class);
         reportTemplateService = adminClient.getService(ReportTemplateService.class);
         reportService = adminClient.getService(ReportService.class);
         taskService = adminClient.getService(TaskService.class);
@@ -891,7 +891,7 @@ public abstract class AbstractITCase {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
             }
-            results = loggerService.search(query).getResult();
+            results = auditService.search(query).getResult();
             i++;
         } while (results.isEmpty() && i < maxWaitSeconds);
         return results;
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractConsoleITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractConsoleITCase.java
index 000b3eb..b67c386 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractConsoleITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractConsoleITCase.java
@@ -46,6 +46,7 @@ import org.apache.wicket.util.tester.FormTester;
 import org.apache.wicket.util.tester.WicketTester;
 import org.junit.jupiter.api.BeforeAll;
 import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.logging.LoggingSystem;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -111,6 +112,12 @@ public abstract class AbstractConsoleITCase extends AbstractUITCase {
         public PolicyTabProvider idRepoPolicyTabProvider() {
             return new IdRepoPolicyTabProvider();
         }
+
+        @Bean
+        public LoggingSystem loggingSystem() {
+            System.setProperty(LoggingSystem.SYSTEM_PROPERTY, LoggingSystem.NONE);
+            return LoggingSystem.get(getClass().getClassLoader());
+        }
     }
 
     @BeforeAll
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/LogsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/LogsITCase.java
index b2131c5..07c9489 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/LogsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/LogsITCase.java
@@ -23,9 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import java.lang.reflect.InvocationTargetException;
 import org.apache.syncope.client.ui.commons.Constants;
 import org.apache.syncope.client.console.pages.Logs;
-import org.apache.syncope.common.lib.log.LoggerTO;
 import org.apache.wicket.Component;
-import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
 import org.apache.wicket.core.util.lang.PropertyResolver;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.form.DropDownChoice;
@@ -47,7 +45,7 @@ public class LogsITCase extends AbstractConsoleITCase {
     }
 
     @Test
-    public void readCoreLogs() {
+    public void readLogs() {
         TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:0:link");
         TESTER.assertComponent(CONTAINER_PATH, WebMarkupContainer.class);
 
@@ -55,7 +53,7 @@ public class LogsITCase extends AbstractConsoleITCase {
     }
 
     @Test
-    public void updateCoreLogs() {
+    public void updateLogs() {
         TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:0:link");
         TESTER.assertComponent(CONTAINER_PATH, WebMarkupContainer.class);
 
@@ -73,42 +71,16 @@ public class LogsITCase extends AbstractConsoleITCase {
         assertSuccessMessage();
     }
 
-    @Test
-    public void readConsoleLogs() {
-        TESTER.assertComponent("body:content:tabbedPanel:tabs-container:tabs:1:link", AjaxFallbackLink.class);
-        TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:1:link");
-        TESTER.assertComponent(CONTAINER_PATH, WebMarkupContainer.class);
-
-        assertNotNull(searchLog(KEY, CONTAINER_PATH, "org.apache.wicket"));
-    }
-
-    @Test
-    public void updateConsoleLogs() {
-        TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:1:link");
-        TESTER.assertComponent(CONTAINER_PATH, WebMarkupContainer.class);
-
-        Component result = searchLog(KEY, CONTAINER_PATH, "org.apache.wicket");
-        assertNotNull(result);
-
-        TESTER.getRequest().setMethod(Form.METHOD_GET);
-        TESTER.getRequest().addParameter(
-                result.getPageRelativePath() + ":fields:1:field:dropDownChoiceField", "6");
-        TESTER.assertComponent(
-                result.getPageRelativePath() + ":fields:1:field:dropDownChoiceField", DropDownChoice.class);
-        TESTER.executeAjaxEvent(
-                result.getPageRelativePath() + ":fields:1:field:dropDownChoiceField", Constants.ON_CHANGE);
-
-        assertSuccessMessage();
-    }
-
     private static Component searchLog(final String property, final String searchPath, final String key) {
         Component component = TESTER.getComponentFromLastRenderedPage(searchPath);
 
         Component result = component.getPage().
-                visitChildren(ListItem.class, (final ListItem<LoggerTO> object, final IVisit<Component> visit) -> {
+                visitChildren(ListItem.class, (final ListItem<?> object, final IVisit<Component> visit) -> {
                     try {
-                        if (object.getModelObject() instanceof LoggerTO && PropertyResolver.getPropertyGetter(
-                                property, object.getModelObject()).invoke(object.getModelObject()).equals(key)) {
+                        if ("LoggerConf".equals(object.getModelObject().getClass().getSimpleName())
+                                && PropertyResolver.getPropertyGetter(property, object.getModelObject()).
+                                        invoke(object.getModelObject()).equals(key)) {
+
                             visit.stop(object);
                         }
                     } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuditITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuditITCase.java
index 0afcaa4..d93f790 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuditITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuditITCase.java
@@ -18,31 +18,61 @@
  */
 package org.apache.syncope.fit.core;
 
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Properties;
 import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.audit.AuditEntry;
+import org.apache.syncope.common.lib.audit.EventCategory;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.common.lib.to.AuditConfTO;
 import org.apache.syncope.common.lib.to.ConnInstanceTO;
+import org.apache.syncope.common.lib.to.ConnPoolConfTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.PushTaskTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AuditElements;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.ConnectorCapability;
+import org.apache.syncope.common.lib.types.MatchingRule;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.common.lib.types.UnmatchingRule;
 import org.apache.syncope.common.rest.api.beans.AnyQuery;
 import org.apache.syncope.common.rest.api.beans.AuditQuery;
+import org.apache.syncope.common.rest.api.beans.ReconQuery;
 import org.apache.syncope.core.logic.ConnectorLogic;
+import org.apache.syncope.core.logic.GroupLogic;
+import org.apache.syncope.core.logic.ReportLogic;
+import org.apache.syncope.core.logic.ResourceLogic;
 import org.apache.syncope.core.logic.UserLogic;
 import org.apache.syncope.fit.AbstractITCase;
 import org.junit.jupiter.api.Test;
@@ -185,7 +215,7 @@ public class AuditITCase extends AbstractITCase {
                 event("update").
                 result(AuditElements.Result.SUCCESS).
                 build();
-        List<AuditEntry> entries = loggerService.search(query).getResult();
+        List<AuditEntry> entries = auditService.search(query).getResult();
         int pre = entries.size();
 
         ConnInstanceTO ldapConn = connectorService.read(connectorKey, null);
@@ -217,4 +247,314 @@ public class AuditITCase extends AbstractITCase {
         assertEquals(originalCapabilities, ldapConn.getCapabilities());
         assertEquals(originalConfProp, ldapConn.getConf("maintainPosixGroupMembership").get());
     }
+
+    @Test
+    public void enableDisable() {
+        AuditLoggerName auditLoggerName = new AuditLoggerName(
+                AuditElements.EventCategoryType.LOGIC,
+                ReportLogic.class.getSimpleName(),
+                null,
+                "deleteExecution",
+                AuditElements.Result.FAILURE);
+
+        List<AuditConfTO> audits = auditService.list();
+        assertFalse(audits.stream().anyMatch(a -> a.getKey().equals(auditLoggerName.toAuditKey())));
+
+        AuditConfTO audit = new AuditConfTO();
+        audit.setKey(auditLoggerName.toAuditKey());
+        audit.setActive(true);
+        auditService.create(audit);
+
+        audits = auditService.list();
+        assertTrue(audits.stream().anyMatch(a -> a.getKey().equals(auditLoggerName.toAuditKey())));
+
+        auditService.delete(audit.getKey());
+
+        audits = auditService.list();
+        assertFalse(audits.stream().anyMatch(a -> a.getKey().equals(auditLoggerName.toAuditKey())));
+    }
+
+    @Test
+    public void listAuditEvents() {
+        List<EventCategory> events = auditService.events();
+
+        boolean found = false;
+
+        for (EventCategory eventCategoryTO : events) {
+            if (UserLogic.class.getSimpleName().equals(eventCategoryTO.getCategory())) {
+                assertEquals(AuditElements.EventCategoryType.LOGIC, eventCategoryTO.getType());
+                assertTrue(eventCategoryTO.getEvents().contains("create"));
+                assertTrue(eventCategoryTO.getEvents().contains("search"));
+                assertFalse(eventCategoryTO.getEvents().contains("doCreate"));
+                assertFalse(eventCategoryTO.getEvents().contains("setStatusOnWfAdapter"));
+                assertFalse(eventCategoryTO.getEvents().contains("resolveReference"));
+                found = true;
+            }
+        }
+        assertTrue(found);
+
+        found = false;
+        for (EventCategory eventCategoryTO : events) {
+            if (GroupLogic.class.getSimpleName().equals(eventCategoryTO.getCategory())) {
+                assertEquals(AuditElements.EventCategoryType.LOGIC, eventCategoryTO.getType());
+                assertTrue(eventCategoryTO.getEvents().contains("create"));
+                assertTrue(eventCategoryTO.getEvents().contains("search"));
+                assertFalse(eventCategoryTO.getEvents().contains("resolveReference"));
+                found = true;
+            }
+        }
+        assertTrue(found);
+
+        found = false;
+        for (EventCategory eventCategoryTO : events) {
+            if (ResourceLogic.class.getSimpleName().equals(eventCategoryTO.getCategory())) {
+                assertEquals(AuditElements.EventCategoryType.LOGIC, eventCategoryTO.getType());
+                assertTrue(eventCategoryTO.getEvents().contains("create"));
+                assertTrue(eventCategoryTO.getEvents().contains("read"));
+                assertTrue(eventCategoryTO.getEvents().contains("delete"));
+                assertFalse(eventCategoryTO.getEvents().contains("resolveReference"));
+                found = true;
+            }
+        }
+        assertTrue(found);
+
+        found = false;
+        for (EventCategory eventCategoryTO : events) {
+            if (AnyTypeKind.USER.name().toLowerCase().equals(eventCategoryTO.getCategory())) {
+                if (RESOURCE_NAME_LDAP.equals(eventCategoryTO.getSubcategory())
+                        && AuditElements.EventCategoryType.PULL == eventCategoryTO.getType()) {
+
+                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.DELETE.name().toLowerCase()));
+                    found = true;
+                }
+            }
+        }
+        assertTrue(found);
+
+        found = false;
+        for (EventCategory eventCategoryTO : events) {
+            if (AnyTypeKind.USER.name().toLowerCase().equals(eventCategoryTO.getCategory())) {
+                if (RESOURCE_NAME_CSV.equals(eventCategoryTO.getSubcategory())
+                        && AuditElements.EventCategoryType.PROPAGATION == eventCategoryTO.getType()) {
+
+                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.CREATE.name().toLowerCase()));
+                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.UPDATE.name().toLowerCase()));
+                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.DELETE.name().toLowerCase()));
+                    found = true;
+                }
+            }
+        }
+        assertTrue(found);
+
+        found = false;
+        for (EventCategory eventCategoryTO : events) {
+            if (AuditElements.EventCategoryType.TASK == eventCategoryTO.getType()
+                    && "PullJobDelegate".equals(eventCategoryTO.getCategory())) {
+                found = true;
+            }
+        }
+        assertTrue(found);
+    }
+
+    private static void checkLogFileFor(
+            final Path path,
+            final Function<String, Boolean> checker,
+            final int maxWaitSeconds)
+            throws IOException {
+
+        await().atMost(maxWaitSeconds, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS).until(() -> {
+            try {
+                return checker.apply(Files.readString(path, StandardCharsets.UTF_8));
+            } catch (Exception e) {
+                return false;
+            }
+        });
+    }
+
+    @Test
+    public void saveAuditEvent() {
+        AuditEntry auditEntry = new AuditEntry();
+        auditEntry.setWho("syncope-user " + UUID.randomUUID().toString());
+        auditEntry.setLogger(new AuditLoggerName(
+                AuditElements.EventCategoryType.WA,
+                null,
+                AuditElements.AUTHENTICATION_CATEGORY.toUpperCase(),
+                "validate",
+                AuditElements.Result.SUCCESS));
+        auditEntry.setDate(new Date());
+        auditEntry.setBefore(UUID.randomUUID().toString());
+        auditEntry.setOutput(UUID.randomUUID().toString());
+        assertDoesNotThrow(() -> auditService.create(auditEntry));
+
+        PagedResult<AuditEntry> events = auditService.search(new AuditQuery.Builder().
+                size(1).
+                type(auditEntry.getLogger().getType()).
+                category(auditEntry.getLogger().getCategory()).
+                subcategory(auditEntry.getLogger().getSubcategory()).
+                event(auditEntry.getLogger().getEvent()).
+                result(auditEntry.getLogger().getResult()).
+                build());
+        assertNotNull(events);
+        assertEquals(1, events.getSize());
+    }
+
+    @Test
+    public void saveAuthEvent() {
+        AuditEntry auditEntry = new AuditEntry();
+        auditEntry.setWho("syncope-user " + UUID.randomUUID().toString());
+        auditEntry.setLogger(new AuditLoggerName(
+                AuditElements.EventCategoryType.WA,
+                null,
+                "AuthenticationEvent",
+                "auth",
+                AuditElements.Result.SUCCESS));
+        auditEntry.setDate(new Date());
+        auditEntry.setBefore(UUID.randomUUID().toString());
+        auditEntry.setOutput(UUID.randomUUID().toString());
+        assertDoesNotThrow(() -> auditService.create(auditEntry));
+
+        PagedResult<AuditEntry> events = auditService.search(new AuditQuery.Builder().
+                size(1).
+                type(auditEntry.getLogger().getType()).
+                category(auditEntry.getLogger().getCategory()).
+                subcategory(auditEntry.getLogger().getSubcategory()).
+                event(auditEntry.getLogger().getEvent()).
+                result(auditEntry.getLogger().getResult()).
+                build());
+        assertNotNull(events);
+        assertEquals(1, events.getSize());
+    }
+
+    @Test
+    public void customAuditAppender() throws IOException, InterruptedException {
+        try (InputStream propStream = getClass().getResourceAsStream("/test.properties")) {
+            Properties props = new Properties();
+            props.load(propStream);
+
+            Path auditFilePath = Paths.get(props.getProperty("test.log.dir")
+                    + File.separator + "audit_for_Master_file.log");
+            Files.write(auditFilePath, new byte[0], StandardOpenOption.TRUNCATE_EXISTING);
+
+            Path auditNoRewriteFilePath = Paths.get(props.getProperty("test.log.dir")
+                    + File.separator + "audit_for_Master_norewrite_file.log");
+            Files.write(auditNoRewriteFilePath, new byte[0], StandardOpenOption.TRUNCATE_EXISTING);
+
+            // check that resource update is transformed and logged onto an audit file.
+            ResourceTO resource = resourceService.read(RESOURCE_NAME_CSV);
+            assertNotNull(resource);
+            resource.setPropagationPriority(100);
+            resourceService.update(resource);
+
+            ConnInstanceTO connector = connectorService.readByResource(RESOURCE_NAME_CSV, null);
+            assertNotNull(connector);
+            connector.setPoolConf(new ConnPoolConfTO());
+            connectorService.update(connector);
+
+            // check audit_for_Master_file.log, it should contain only a static message
+            checkLogFileFor(
+                    auditFilePath,
+                    content -> content.contains(
+                            "DEBUG Master.syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]"
+                            + " - This is a static test message"),
+                    10);
+
+            // nothing expected in audit_for_Master_norewrite_file.log instead
+            checkLogFileFor(
+                    auditNoRewriteFilePath,
+                    content -> !content.contains(
+                            "DEBUG Master.syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]"
+                            + " - This is a static test message"),
+                    10);
+        } catch (IOException e) {
+            fail("Unable to read/write log files", e);
+        }
+    }
+
+    @Test
+    public void issueSYNCOPE976() {
+        List<EventCategory> events = auditService.events();
+        assertNotNull(events);
+
+        EventCategory userLogic = events.stream().
+                filter(object -> "UserLogic".equals(object.getCategory())).findAny().get();
+        assertNotNull(userLogic);
+        assertEquals(1, userLogic.getEvents().stream().filter("create"::equals).count());
+    }
+
+    @Test
+    public void issueSYNCOPE1446() {
+        AuditLoggerName createSuccess = new AuditLoggerName(
+                AuditElements.EventCategoryType.PROPAGATION,
+                AnyTypeKind.ANY_OBJECT.name().toLowerCase(),
+                RESOURCE_NAME_DBSCRIPTED,
+                "create",
+                AuditElements.Result.SUCCESS);
+        AuditLoggerName createFailure = new AuditLoggerName(
+                AuditElements.EventCategoryType.PROPAGATION,
+                AnyTypeKind.ANY_OBJECT.name().toLowerCase(),
+                RESOURCE_NAME_DBSCRIPTED,
+                "create",
+                AuditElements.Result.FAILURE);
+        AuditLoggerName updateSuccess = new AuditLoggerName(
+                AuditElements.EventCategoryType.PROPAGATION,
+                AnyTypeKind.ANY_OBJECT.name().toLowerCase(),
+                RESOURCE_NAME_DBSCRIPTED,
+                "update",
+                AuditElements.Result.SUCCESS);
+        AuditLoggerName updateFailure = new AuditLoggerName(
+                AuditElements.EventCategoryType.PROPAGATION,
+                AnyTypeKind.ANY_OBJECT.name().toLowerCase(),
+                RESOURCE_NAME_DBSCRIPTED,
+                "update",
+                AuditElements.Result.FAILURE);
+        try {
+            // 1. setup audit for propagation
+            AuditConfTO audit = new AuditConfTO();
+            audit.setKey(createSuccess.toAuditKey());
+            audit.setActive(true);
+            auditService.create(audit);
+
+            audit.setKey(createFailure.toAuditKey());
+            auditService.create(audit);
+
+            audit.setKey(updateSuccess.toAuditKey());
+            auditService.create(audit);
+
+            audit.setKey(updateFailure.toAuditKey());
+            auditService.create(audit);
+
+            // 2. push on resource
+            PushTaskTO pushTask = new PushTaskTO();
+            pushTask.setPerformCreate(true);
+            pushTask.setPerformUpdate(true);
+            pushTask.setUnmatchingRule(UnmatchingRule.PROVISION);
+            pushTask.setMatchingRule(MatchingRule.UPDATE);
+            reconciliationService.push(new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).
+                    anyKey("fc6dbc3a-6c07-4965-8781-921e7401a4a5").build(), pushTask);
+        } catch (Exception e) {
+            LOG.error("Unexpected exception", e);
+            fail(e::getMessage);
+        } finally {
+            try {
+                auditService.delete(createSuccess.toAuditKey());
+            } catch (Exception e) {
+                // ignore
+            }
+            try {
+                auditService.delete(createFailure.toAuditKey());
+            } catch (Exception e) {
+                // ignore
+            }
+            try {
+                auditService.delete(updateSuccess.toAuditKey());
+            } catch (Exception e) {
+                // ignore
+            }
+            try {
+                auditService.delete(updateFailure.toAuditKey());
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+    }
 }
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DelegationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DelegationITCase.java
index 02a65eb..21b9877 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DelegationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DelegationITCase.java
@@ -35,16 +35,14 @@ import org.apache.commons.lang3.tuple.Triple;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.log.AuditEntry;
-import org.apache.syncope.common.lib.log.LoggerTO;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.common.lib.request.UserCR;
+import org.apache.syncope.common.lib.to.AuditConfTO;
 import org.apache.syncope.common.lib.to.DelegationTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
-import org.apache.syncope.common.lib.types.LoggerLevel;
-import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.common.rest.api.beans.AnyQuery;
 import org.apache.syncope.common.rest.api.beans.AuditQuery;
 import org.apache.syncope.common.rest.api.service.DelegationService;
@@ -206,10 +204,10 @@ public class DelegationITCase extends AbstractITCase {
                 null,
                 "search",
                 AuditElements.Result.SUCCESS);
-        LoggerTO authLogin = new LoggerTO();
-        authLogin.setKey(authLoginSuccess.toLoggerName());
-        authLogin.setLevel(LoggerLevel.DEBUG);
-        loggerService.update(LoggerType.AUDIT, authLogin);
+        AuditConfTO authLogin = new AuditConfTO();
+        authLogin.setKey(authLoginSuccess.toAuditKey());
+        authLogin.setActive(true);
+        auditService.create(authLogin);
 
         // 1. bellini delegates rossini
         DelegationTO delegation = new DelegationTO();
@@ -266,7 +264,7 @@ public class DelegationITCase extends AbstractITCase {
         assertTrue(entries.stream().anyMatch(entry -> "rossini [delegated by bellini]".equals(entry.getWho())));
 
         // 6. disable audit
-        authLogin.setLevel(LoggerLevel.OFF);
-        loggerService.update(LoggerType.AUDIT, authLogin);
+        authLogin.setActive(false);
+        auditService.update(authLogin);
     }
 }
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
deleted file mode 100644
index 227350f..0000000
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
+++ /dev/null
@@ -1,517 +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.fit.core;
-
-import static org.awaitility.Awaitility.await;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-import java.text.ParseException;
-import java.util.Date;
-import java.util.List;
-import java.util.Properties;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Function;
-import javax.ws.rs.core.Response;
-import javax.xml.ws.WebServiceException;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.log.AuditEntry;
-import org.apache.syncope.common.lib.log.EventCategory;
-import org.apache.syncope.common.lib.log.LogAppender;
-import org.apache.syncope.common.lib.log.LogStatement;
-import org.apache.syncope.common.lib.log.LoggerTO;
-import org.apache.syncope.common.lib.to.ConnInstanceTO;
-import org.apache.syncope.common.lib.to.ConnPoolConfTO;
-import org.apache.syncope.common.lib.to.PagedResult;
-import org.apache.syncope.common.lib.to.PushTaskTO;
-import org.apache.syncope.common.lib.to.ResourceTO;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.AuditElements;
-import org.apache.syncope.common.lib.types.AuditElements.EventCategoryType;
-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.common.lib.types.MatchingRule;
-import org.apache.syncope.common.lib.types.ResourceOperation;
-import org.apache.syncope.common.lib.types.UnmatchingRule;
-import org.apache.syncope.common.rest.api.LoggerWrapper;
-import org.apache.syncope.common.rest.api.beans.AuditQuery;
-import org.apache.syncope.common.rest.api.beans.ReconQuery;
-import org.apache.syncope.core.logic.ConnectorLogic;
-import org.apache.syncope.core.logic.ReportLogic;
-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.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-public class LoggerITCase extends AbstractITCase {
-
-    @Test
-    public void listMemoryAppenders() {
-        List<LogAppender> memoryAppenders = loggerService.memoryAppenders();
-        assertNotNull(memoryAppenders);
-        assertFalse(memoryAppenders.isEmpty());
-        memoryAppenders.forEach(appender -> {
-            assertNotNull(appender);
-            assertNotNull(appender.getName());
-        });
-    }
-
-    @Test
-    public void lastStatements() {
-        List<LogStatement> statements = loggerService.getLastLogStatements("connid");
-        assertNotNull(statements);
-        assertFalse(statements.isEmpty());
-
-        LogStatement statement = statements.get(0);
-        assertNotNull(statement);
-        assertNotNull(statement.getLoggerName());
-        assertNotNull(statement.getLevel());
-        assertNotNull(statement.getMessage());
-        assertNotNull(statement.getTimeMillis());
-    }
-
-    @Test
-    public void listLogs() {
-        List<LoggerTO> loggers = loggerService.list(LoggerType.LOG);
-        assertNotNull(loggers);
-        assertFalse(loggers.isEmpty());
-        loggers.forEach(Assertions::assertNotNull);
-    }
-
-    @Test
-    public void listAudits() throws ParseException {
-        List<LoggerTO> audits = loggerService.list(LoggerType.AUDIT);
-        assertNotNull(audits);
-        assertFalse(audits.isEmpty());
-        for (LoggerTO audit : audits) {
-            assertNotNull(AuditLoggerName.fromLoggerName(audit.getKey()));
-        }
-    }
-
-    @Test
-    public void setLevel() {
-        List<LoggerTO> loggers = loggerService.list(LoggerType.LOG);
-        assertNotNull(loggers);
-        int startSize = loggers.size();
-
-        LoggerTO logger = new LoggerTO();
-        logger.setKey("TEST");
-        logger.setLevel(LoggerLevel.INFO);
-        loggerService.update(LoggerType.LOG, logger);
-        logger = loggerService.read(LoggerType.LOG, logger.getKey());
-        assertNotNull(logger);
-        assertEquals(LoggerLevel.INFO, logger.getLevel());
-
-        loggers = loggerService.list(LoggerType.LOG);
-        assertNotNull(loggers);
-        assertEquals(startSize + 1, loggers.size());
-
-        // TEST Delete
-        loggerService.delete(LoggerType.LOG, "TEST");
-        loggers = loggerService.list(LoggerType.LOG);
-        assertNotNull(loggers);
-        assertEquals(startSize, loggers.size());
-    }
-
-    @Test
-    public void enableDisableAudit() {
-        AuditLoggerName auditLoggerName = new AuditLoggerName(
-                EventCategoryType.LOGIC,
-                ReportLogic.class.getSimpleName(),
-                null,
-                "deleteExecution",
-                AuditElements.Result.FAILURE);
-
-        List<AuditLoggerName> audits = LoggerWrapper.wrap(loggerService.list(LoggerType.AUDIT));
-        assertNotNull(audits);
-        assertFalse(audits.contains(auditLoggerName));
-
-        LoggerTO loggerTO = new LoggerTO();
-        loggerTO.setKey(auditLoggerName.toLoggerName());
-        loggerTO.setLevel(LoggerLevel.DEBUG);
-        loggerService.update(LoggerType.AUDIT, loggerTO);
-
-        audits = LoggerWrapper.wrap(loggerService.list(LoggerType.AUDIT));
-        assertNotNull(audits);
-        assertTrue(audits.contains(auditLoggerName));
-
-        loggerService.delete(LoggerType.AUDIT, auditLoggerName.toLoggerName());
-
-        audits = LoggerWrapper.wrap(loggerService.list(LoggerType.AUDIT));
-        assertNotNull(audits);
-        assertFalse(audits.contains(auditLoggerName));
-    }
-
-    @Test
-    public void listAuditEvents() {
-        final List<EventCategory> events = loggerService.events();
-
-        boolean found = false;
-
-        for (EventCategory eventCategoryTO : events) {
-            if (UserLogic.class.getSimpleName().equals(eventCategoryTO.getCategory())) {
-                assertEquals(EventCategoryType.LOGIC, eventCategoryTO.getType());
-                assertTrue(eventCategoryTO.getEvents().contains("create"));
-                assertTrue(eventCategoryTO.getEvents().contains("search"));
-                assertFalse(eventCategoryTO.getEvents().contains("doCreate"));
-                assertFalse(eventCategoryTO.getEvents().contains("setStatusOnWfAdapter"));
-                assertFalse(eventCategoryTO.getEvents().contains("resolveReference"));
-                found = true;
-            }
-        }
-        assertTrue(found);
-
-        found = false;
-        for (EventCategory eventCategoryTO : events) {
-            if (GroupLogic.class.getSimpleName().equals(eventCategoryTO.getCategory())) {
-                assertEquals(EventCategoryType.LOGIC, eventCategoryTO.getType());
-                assertTrue(eventCategoryTO.getEvents().contains("create"));
-                assertTrue(eventCategoryTO.getEvents().contains("search"));
-                assertFalse(eventCategoryTO.getEvents().contains("resolveReference"));
-                found = true;
-            }
-        }
-        assertTrue(found);
-
-        found = false;
-        for (EventCategory eventCategoryTO : events) {
-            if (ResourceLogic.class.getSimpleName().equals(eventCategoryTO.getCategory())) {
-                assertEquals(EventCategoryType.LOGIC, eventCategoryTO.getType());
-                assertTrue(eventCategoryTO.getEvents().contains("create"));
-                assertTrue(eventCategoryTO.getEvents().contains("read"));
-                assertTrue(eventCategoryTO.getEvents().contains("delete"));
-                assertFalse(eventCategoryTO.getEvents().contains("resolveReference"));
-                found = true;
-            }
-        }
-        assertTrue(found);
-
-        found = false;
-        for (EventCategory eventCategoryTO : events) {
-            if (AnyTypeKind.USER.name().toLowerCase().equals(eventCategoryTO.getCategory())) {
-                if (RESOURCE_NAME_LDAP.equals(eventCategoryTO.getSubcategory())
-                        && EventCategoryType.PULL == eventCategoryTO.getType()) {
-
-                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.DELETE.name().toLowerCase()));
-                    found = true;
-                }
-            }
-        }
-        assertTrue(found);
-
-        found = false;
-        for (EventCategory eventCategoryTO : events) {
-            if (AnyTypeKind.USER.name().toLowerCase().equals(eventCategoryTO.getCategory())) {
-                if (RESOURCE_NAME_CSV.equals(eventCategoryTO.getSubcategory())
-                        && EventCategoryType.PROPAGATION == eventCategoryTO.getType()) {
-
-                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.CREATE.name().toLowerCase()));
-                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.UPDATE.name().toLowerCase()));
-                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.DELETE.name().toLowerCase()));
-                    found = true;
-                }
-            }
-        }
-        assertTrue(found);
-
-        found = false;
-        for (EventCategory eventCategoryTO : events) {
-            if (EventCategoryType.TASK == eventCategoryTO.getType()
-                    && "PullJobDelegate".equals(eventCategoryTO.getCategory())) {
-                found = true;
-            }
-        }
-        assertTrue(found);
-    }
-
-    private static void checkLogFileFor(
-            final Path path,
-            final Function<String, Boolean> checker,
-            final int maxWaitSeconds)
-            throws IOException {
-
-        await().atMost(maxWaitSeconds, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS).until(() -> {
-            try {
-                return checker.apply(Files.readString(path, StandardCharsets.UTF_8));
-            } catch (Exception e) {
-                return false;
-            }
-        });
-    }
-
-    @Test
-    public void saveAuditEvent() {
-        AuditEntry auditEntry = new AuditEntry();
-        auditEntry.setWho("syncope-user " + UUID.randomUUID().toString());
-        auditEntry.setLogger(new AuditLoggerName(
-                EventCategoryType.WA,
-                "LoggerLogic",
-                AuditElements.AUTHENTICATION_CATEGORY.toUpperCase(),
-                "validate",
-                AuditElements.Result.SUCCESS));
-        auditEntry.setDate(new Date());
-        auditEntry.setBefore(UUID.randomUUID().toString());
-        auditEntry.setOutput(UUID.randomUUID().toString());
-        assertDoesNotThrow(() -> loggerService.create(auditEntry));
-
-        PagedResult<AuditEntry> events = loggerService.search(new AuditQuery.Builder().
-                size(1).
-                type(auditEntry.getLogger().getType()).
-                category(auditEntry.getLogger().getCategory()).
-                subcategory(auditEntry.getLogger().getSubcategory()).
-                event(auditEntry.getLogger().getEvent()).
-                result(auditEntry.getLogger().getResult()).
-                build());
-        assertNotNull(events);
-        assertEquals(1, events.getSize());
-    }
-    
-    @Test
-    public void saveAuthEvent() {
-        AuditEntry auditEntry = new AuditEntry();
-        auditEntry.setWho("syncope-user " + UUID.randomUUID().toString());
-        auditEntry.setLogger(new AuditLoggerName(
-                EventCategoryType.WA,
-                "LoggerLogic",
-                "AuthenticationEvent",
-                "auth",
-                AuditElements.Result.SUCCESS));
-        auditEntry.setDate(new Date());
-        auditEntry.setBefore(UUID.randomUUID().toString());
-        auditEntry.setOutput(UUID.randomUUID().toString());
-        assertDoesNotThrow(() -> loggerService.create(auditEntry));
-
-        PagedResult<AuditEntry> events = loggerService.search(new AuditQuery.Builder().
-                size(1).
-                type(auditEntry.getLogger().getType()).
-                category(auditEntry.getLogger().getCategory()).
-                subcategory(auditEntry.getLogger().getSubcategory()).
-                event(auditEntry.getLogger().getEvent()).
-                result(auditEntry.getLogger().getResult()).
-                build());
-        assertNotNull(events);
-        assertEquals(1, events.getSize());
-    }
-
-    @Test
-    public void customAuditAppender() throws IOException, InterruptedException {
-        AuditLoggerName auditLoggerResUpd = new AuditLoggerName(
-                EventCategoryType.LOGIC,
-                ResourceLogic.class.getSimpleName(),
-                null,
-                "update",
-                AuditElements.Result.SUCCESS);
-        LoggerTO resUpd = new LoggerTO();
-        resUpd.setKey(auditLoggerResUpd.toLoggerName());
-
-        AuditLoggerName auditLoggerConnUpd = new AuditLoggerName(
-                EventCategoryType.LOGIC,
-                ConnectorLogic.class.getSimpleName(),
-                null,
-                "update",
-                AuditElements.Result.SUCCESS);
-        LoggerTO connUpd = new LoggerTO();
-        connUpd.setKey(auditLoggerConnUpd.toLoggerName());
-
-        try (InputStream propStream = getClass().getResourceAsStream("/test.properties")) {
-            Properties props = new Properties();
-            props.load(propStream);
-
-            Path auditFilePath = Paths.get(props.getProperty("test.log.dir")
-                    + File.separator + "audit_for_Master_file.log");
-            Files.write(auditFilePath, new byte[0], StandardOpenOption.TRUNCATE_EXISTING);
-
-            Path auditNoRewriteFilePath = Paths.get(props.getProperty("test.log.dir")
-                    + File.separator + "audit_for_Master_norewrite_file.log");
-            Files.write(auditNoRewriteFilePath, new byte[0], StandardOpenOption.TRUNCATE_EXISTING);
-
-            // 1. Enable audit for resource update -> catched by FileRewriteAuditAppender
-            resUpd.setLevel(LoggerLevel.DEBUG);
-            loggerService.update(LoggerType.AUDIT, resUpd);
-
-            // 2. Enable audit for connector update -> NOT catched by FileRewriteAuditAppender
-            connUpd.setLevel(LoggerLevel.DEBUG);
-            loggerService.update(LoggerType.AUDIT, connUpd);
-
-            // 3. check that resource update is transformed and logged onto an audit file.
-            ResourceTO resource = resourceService.read(RESOURCE_NAME_CSV);
-            assertNotNull(resource);
-            resource.setPropagationPriority(100);
-            resourceService.update(resource);
-
-            ConnInstanceTO connector = connectorService.readByResource(RESOURCE_NAME_CSV, null);
-            assertNotNull(connector);
-            connector.setPoolConf(new ConnPoolConfTO());
-            connectorService.update(connector);
-
-            // check audit_for_Master_file.log, it should contain only a static message
-            checkLogFileFor(
-                    auditFilePath,
-                    content -> content.contains(
-                            "DEBUG Master.syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]"
-                            + " - This is a static test message"),
-                    10);
-
-            // nothing expected in audit_for_Master_norewrite_file.log instead
-            checkLogFileFor(
-                    auditNoRewriteFilePath,
-                    content -> !content.contains(
-                            "DEBUG Master.syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]"
-                            + " - This is a static test message"),
-                    10);
-
-            // clean audit_for_Master_file.log
-            Files.write(auditFilePath, new byte[0], StandardOpenOption.TRUNCATE_EXISTING);
-            loggerService.delete(LoggerType.AUDIT, "syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]");
-
-            resource = resourceService.read(RESOURCE_NAME_CSV);
-            assertNotNull(resource);
-            resource.setPropagationPriority(200);
-            resourceService.update(resource);
-
-            // check that nothing has been written to audit_for_Master_file.log
-            assertTrue(StringUtils.isEmpty(Files.readString(auditFilePath, StandardCharsets.UTF_8)));
-        } catch (IOException e) {
-            fail("Unable to read/write log files", e);
-        } finally {
-            resUpd.setLevel(LoggerLevel.ERROR);
-            loggerService.update(LoggerType.AUDIT, resUpd);
-
-            connUpd.setLevel(LoggerLevel.ERROR);
-            loggerService.update(LoggerType.AUDIT, connUpd);
-        }
-    }
-
-    @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<EventCategory> events = loggerService.events();
-        assertNotNull(events);
-
-        EventCategory userLogic = events.stream().
-                filter(object -> "UserLogic".equals(object.getCategory())).findAny().get();
-        assertNotNull(userLogic);
-        assertEquals(1, userLogic.getEvents().stream().filter("create"::equals).count());
-    }
-
-    @Test
-    public void issueSYNCOPE1446() {
-        AuditLoggerName createSuccess = new AuditLoggerName(
-                AuditElements.EventCategoryType.PROPAGATION,
-                AnyTypeKind.ANY_OBJECT.name().toLowerCase(),
-                RESOURCE_NAME_DBSCRIPTED,
-                "create",
-                AuditElements.Result.SUCCESS);
-        AuditLoggerName createFailure = new AuditLoggerName(
-                AuditElements.EventCategoryType.PROPAGATION,
-                AnyTypeKind.ANY_OBJECT.name().toLowerCase(),
-                RESOURCE_NAME_DBSCRIPTED,
-                "create",
-                AuditElements.Result.FAILURE);
-        AuditLoggerName updateSuccess = new AuditLoggerName(
-                AuditElements.EventCategoryType.PROPAGATION,
-                AnyTypeKind.ANY_OBJECT.name().toLowerCase(),
-                RESOURCE_NAME_DBSCRIPTED,
-                "update",
-                AuditElements.Result.SUCCESS);
-        AuditLoggerName updateFailure = new AuditLoggerName(
-                AuditElements.EventCategoryType.PROPAGATION,
-                AnyTypeKind.ANY_OBJECT.name().toLowerCase(),
-                RESOURCE_NAME_DBSCRIPTED,
-                "update",
-                AuditElements.Result.FAILURE);
-        try {
-            // 1. setup audit for propagation
-            LoggerTO loggerTO = new LoggerTO();
-            loggerTO.setKey(createSuccess.toLoggerName());
-            loggerTO.setLevel(LoggerLevel.DEBUG);
-            loggerService.update(LoggerType.AUDIT, loggerTO);
-
-            loggerTO.setKey(createFailure.toLoggerName());
-            loggerService.update(LoggerType.AUDIT, loggerTO);
-
-            loggerTO.setKey(updateSuccess.toLoggerName());
-            loggerService.update(LoggerType.AUDIT, loggerTO);
-
-            loggerTO.setKey(updateFailure.toLoggerName());
-            loggerService.update(LoggerType.AUDIT, loggerTO);
-
-            // 2. push on resource
-            PushTaskTO pushTask = new PushTaskTO();
-            pushTask.setPerformCreate(true);
-            pushTask.setPerformUpdate(true);
-            pushTask.setUnmatchingRule(UnmatchingRule.PROVISION);
-            pushTask.setMatchingRule(MatchingRule.UPDATE);
-            reconciliationService.push(new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).
-                    anyKey("fc6dbc3a-6c07-4965-8781-921e7401a4a5").build(), pushTask);
-        } catch (Exception e) {
-            LOG.error("Unexpected exception", e);
-            fail(e::getMessage);
-        } finally {
-            try {
-                loggerService.delete(LoggerType.AUDIT, createSuccess.toLoggerName());
-            } catch (Exception e) {
-                // ignore
-            }
-            try {
-                loggerService.delete(LoggerType.AUDIT, createFailure.toLoggerName());
-            } catch (Exception e) {
-                // ignore
-            }
-            try {
-                loggerService.delete(LoggerType.AUDIT, updateSuccess.toLoggerName());
-            } catch (Exception e) {
-                // ignore
-            }
-            try {
-                loggerService.delete(LoggerType.AUDIT, updateFailure.toLoggerName());
-            } catch (Exception e) {
-                // ignore
-            }
-        }
-    }
-}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
index 8a368a2..02175e1 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
@@ -27,7 +27,6 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
 import java.util.List;
 import java.util.Locale;
-import javax.ws.rs.ForbiddenException;
 import javax.ws.rs.core.GenericType;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.StringUtils;
@@ -51,7 +50,6 @@ import org.apache.syncope.common.lib.to.PushTaskTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
-import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.ExecStatus;
 import org.apache.syncope.common.lib.types.MatchingRule;
@@ -64,7 +62,6 @@ import org.apache.syncope.common.rest.api.beans.ReconQuery;
 import org.apache.syncope.common.rest.api.beans.SchemaQuery;
 import org.apache.syncope.common.rest.api.beans.TaskQuery;
 import org.apache.syncope.common.rest.api.service.ConnectorService;
-import org.apache.syncope.common.rest.api.service.LoggerService;
 import org.apache.syncope.common.rest.api.service.RealmService;
 import org.apache.syncope.common.rest.api.service.ReconciliationService;
 import org.apache.syncope.common.rest.api.service.ResourceService;
@@ -98,18 +95,6 @@ public class MultitenancyITCase extends AbstractITCase {
     }
 
     @Test
-    public void masterOnly() {
-        try {
-            adminClient.getService(LoggerService.class).list(LoggerType.LOG);
-            fail("This should not happen");
-        } catch (ForbiddenException e) {
-            assertNotNull(e);
-        }
-
-        adminClient.getService(LoggerService.class).list(LoggerType.AUDIT);
-    }
-
-    @Test
     public void readPlainSchemas() {
         assertEquals(1, adminClient.getService(SchemaService.class).
                 search(new SchemaQuery.Builder().type(SchemaType.PLAIN).build()).size());
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
index cd49551..2dcd233 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
@@ -39,7 +39,7 @@ import org.apache.commons.io.IOUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.report.AuditReportletConf;
 import org.apache.syncope.common.lib.report.UserReportletConf;
-import org.apache.syncope.common.lib.log.LoggerTO;
+import org.apache.syncope.common.lib.to.AuditConfTO;
 import org.apache.syncope.common.lib.to.ExecTO;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.ReportTO;
@@ -48,8 +48,6 @@ import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.LoggerLevel;
-import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.common.lib.types.ReportExecExportFormat;
 import org.apache.syncope.common.lib.types.ReportExecStatus;
 import org.apache.syncope.common.rest.api.RESTHeaders;
@@ -303,10 +301,9 @@ public class ReportITCase extends AbstractITCase {
                 AuditElements.Result.SUCCESS);
 
         try {
-            LoggerTO loggerTO = new LoggerTO();
-            loggerTO.setKey(auditLoggerName.toLoggerName());
-            loggerTO.setLevel(LoggerLevel.DEBUG);
-            loggerService.update(LoggerType.AUDIT, loggerTO);
+            AuditConfTO audit = new AuditConfTO();
+            audit.setKey(auditLoggerName.toAuditKey());
+            auditService.create(audit);
 
             ImplementationTO auditReportlet = new ImplementationTO();
             auditReportlet.setKey("UserReportletConf" + getUUIDString());
@@ -329,7 +326,7 @@ public class ReportITCase extends AbstractITCase {
             report = reportService.read(report.getKey());
             assertNotNull(report.getLastExec());
         } finally {
-            loggerService.delete(LoggerType.AUDIT, auditLoggerName.toLoggerName());
+            auditService.delete(auditLoggerName.toAuditKey());
         }
     }
 
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RoleITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RoleITCase.java
index 5deceef..6f5e2cc 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RoleITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RoleITCase.java
@@ -45,7 +45,7 @@ public class RoleITCase extends AbstractITCase {
         RoleTO role = new RoleTO();
         role.setKey(name + getUUIDString());
         role.getRealms().add("/even");
-        role.getEntitlements().add(IdRepoEntitlement.LOG_SET_LEVEL);
+        role.getEntitlements().add(IdRepoEntitlement.AUDIT_UPDATE);
 
         return role;
     }
@@ -70,8 +70,8 @@ public class RoleITCase extends AbstractITCase {
         RoleTO role = new RoleTO();
         role.getRealms().add(SyncopeConstants.ROOT_REALM);
         role.getRealms().add("/even/two");
-        role.getEntitlements().add(IdRepoEntitlement.LOG_LIST);
-        role.getEntitlements().add(IdRepoEntitlement.LOG_SET_LEVEL);
+        role.getEntitlements().add(IdRepoEntitlement.AUDIT_CREATE);
+        role.getEntitlements().add(IdRepoEntitlement.AUDIT_UPDATE);
 
         try {
             createRole(role);
@@ -89,7 +89,7 @@ public class RoleITCase extends AbstractITCase {
     public void createWithTilde() {
         RoleTO role = new RoleTO();
         role.getRealms().add(SyncopeConstants.ROOT_REALM);
-        role.getEntitlements().add(IdRepoEntitlement.LOG_LIST);
+        role.getEntitlements().add(IdRepoEntitlement.AUDIT_UPDATE);
         role.setKey("new~" + getUUIDString());
         role = createRole(role);
         assertNotNull(role);
diff --git a/pom.xml b/pom.xml
index 37c075d..000547b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1744,11 +1744,6 @@ under the License.
       </dependency>
       <dependency>
         <groupId>org.apache.logging.log4j</groupId>
-        <artifactId>log4j-api</artifactId>
-        <version>${log4j.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.logging.log4j</groupId>
         <artifactId>log4j-core</artifactId>
         <version>${log4j.version}</version>
       </dependency>
diff --git a/src/main/asciidoc/reference-guide/concepts/audit.adoc b/src/main/asciidoc/reference-guide/concepts/audit.adoc
index 4f195d7..5bbaaae 100644
--- a/src/main/asciidoc/reference-guide/concepts/audit.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/audit.adoc
@@ -20,7 +20,7 @@
 
 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.
+By default, events are logged as entries into the `AuditEntry` table of the internal storage.
 
 Once events are reported, they can be used as input for external tools.
 
@@ -36,7 +36,7 @@ except for the admin console <<console-configuration-audit,tooling>>, which is n
 
 ==== Audit Appenders
 
-In addition to insertions into the `SYNCOPEAUDIT` table, events are also available for custom handling via Audit
+In addition to insertions into the `AuditEntry` 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.
diff --git a/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/dbms.adoc b/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/dbms.adoc
index 9cf2bec..1118406 100644
--- a/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/dbms.adoc
+++ b/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/dbms.adoc
@@ -91,7 +91,7 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
-logger.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONLoggerDAO
+audit.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONAuditConfDAO
 ....
 
 In `provisioning.properties`, replace as follows:
@@ -224,7 +224,7 @@ any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisi
 user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
 group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
 anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
-logger.dao=org.apache.syncope.core.persistence.jpa.dao.MyJPAJSONLoggerDAO
+audit.dao=org.apache.syncope.core.persistence.jpa.dao.MyJPAJSONAuditConfDAO
 ....
 
 In `provisioning.properties`, replace as follows:
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/audit/SyncopeWAAuditTrailManager.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/audit/SyncopeWAAuditTrailManager.java
index 42f1adc..d76814f 100644
--- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/audit/SyncopeWAAuditTrailManager.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/audit/SyncopeWAAuditTrailManager.java
@@ -25,21 +25,16 @@ import java.util.Set;
 import org.apereo.cas.audit.spi.AbstractAuditTrailManager;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.common.rest.api.service.LoggerService;
+import org.apache.syncope.common.rest.api.service.AuditService;
 import org.apache.syncope.wa.bootstrap.WARestClient;
 import org.apereo.inspektr.audit.AuditActionContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.syncope.client.lib.SyncopeClient;
 
 public class SyncopeWAAuditTrailManager extends AbstractAuditTrailManager {
 
-    private static final Logger LOG = LoggerFactory.getLogger(SyncopeWAAuditTrailManager.class);
-
     private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
 
     private final WARestClient waRestClient;
@@ -71,12 +66,14 @@ public class SyncopeWAAuditTrailManager extends AbstractAuditTrailManager {
                     ? AuditElements.Result.FAILURE
                     : AuditElements.Result.SUCCESS;
 
-            AuditLoggerName auditLogger = new AuditLoggerName(AuditElements.EventCategoryType.WA,
-                    "LoggerLogic", AuditElements.AUTHENTICATION_CATEGORY.toUpperCase(),
-                    audit.getActionPerformed(), result);
-
+            AuditLoggerName auditLogger = new AuditLoggerName(
+                    AuditElements.EventCategoryType.WA,
+                    null,
+                    AuditElements.AUTHENTICATION_CATEGORY.toUpperCase(),
+                    audit.getActionPerformed(),
+                    result);
             auditEntry.setLogger(auditLogger);
-            syncopeClient.getService(LoggerService.class).create(auditEntry);
+            syncopeClient.getService(AuditService.class).create(auditEntry);
         } catch (JsonProcessingException e) {
             LOG.error("During serialization", e);
         }
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/events/SyncopeWAEventRepository.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/events/SyncopeWAEventRepository.java
index fdcb4c3..1286ea1 100644
--- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/events/SyncopeWAEventRepository.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/events/SyncopeWAEventRepository.java
@@ -26,10 +26,10 @@ import java.util.HashMap;
 import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.lib.SyncopeClient;
-import org.apache.syncope.common.lib.log.AuditEntry;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.common.rest.api.service.LoggerService;
+import org.apache.syncope.common.rest.api.service.AuditService;
 import org.apache.syncope.wa.bootstrap.WARestClient;
 import org.apereo.cas.support.events.CasEventRepositoryFilter;
 import org.apereo.cas.support.events.dao.AbstractCasEventRepository;
@@ -85,11 +85,14 @@ public class SyncopeWAEventRepository extends AbstractCasEventRepository {
                 auditEntry.setDate(new Date(event.getTimestamp()));
             }
             auditEntry.setOutput(output);
-            AuditLoggerName auditLogger = new AuditLoggerName(AuditElements.EventCategoryType.WA,
-                    "LoggerLogic", event.getType().toUpperCase(),
-                    String.valueOf(event.getId()), AuditElements.Result.SUCCESS);
+            AuditLoggerName auditLogger = new AuditLoggerName(
+                    AuditElements.EventCategoryType.WA,
+                    null,
+                    event.getType().toUpperCase(),
+                    String.valueOf(event.getId()),
+                    AuditElements.Result.SUCCESS);
             auditEntry.setLogger(auditLogger);
-            syncopeClient.getService(LoggerService.class).create(auditEntry);
+            syncopeClient.getService(AuditService.class).create(auditEntry);
         } catch (JsonProcessingException e) {
             LOG.error("During serialization", e);
         }
@@ -99,5 +102,4 @@ public class SyncopeWAEventRepository extends AbstractCasEventRepository {
     public Collection<? extends CasEvent> load() {
         throw new UnsupportedOperationException("Fetching authentication events from WA is not supported");
     }
-
 }
diff --git a/wa/starter/src/test/java/org/apache/syncope/wa/starter/audit/SyncopeWAAuditTrailManagerTest.java b/wa/starter/src/test/java/org/apache/syncope/wa/starter/audit/SyncopeWAAuditTrailManagerTest.java
index 79d2a64..7c2a352 100644
--- a/wa/starter/src/test/java/org/apache/syncope/wa/starter/audit/SyncopeWAAuditTrailManagerTest.java
+++ b/wa/starter/src/test/java/org/apache/syncope/wa/starter/audit/SyncopeWAAuditTrailManagerTest.java
@@ -25,24 +25,24 @@ import static org.mockito.Mockito.when;
 
 import java.util.Date;
 import org.apache.syncope.client.lib.SyncopeClient;
-import org.apache.syncope.common.lib.log.AuditEntry;
-import org.apache.syncope.common.rest.api.service.LoggerService;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.wa.bootstrap.WARestClient;
 import org.apache.syncope.wa.starter.AbstractTest;
 import org.apereo.inspektr.audit.AuditActionContext;
 import org.junit.jupiter.api.Test;
+import org.apache.syncope.common.rest.api.service.AuditService;
 
 public class SyncopeWAAuditTrailManagerTest extends AbstractTest {
 
-    private static LoggerService loggerService;
+    private static AuditService loggerService;
 
     private static WARestClient getWaRestClient() {
         WARestClient restClient = mock(WARestClient.class);
         SyncopeClient syncopeClient = mock(SyncopeClient.class);
-        loggerService = mock(LoggerService.class);
+        loggerService = mock(AuditService.class);
 
         when(restClient.getSyncopeClient()).thenReturn(syncopeClient);
-        when(syncopeClient.getService(LoggerService.class)).thenReturn(loggerService);
+        when(syncopeClient.getService(AuditService.class)).thenReturn(loggerService);
 
         return restClient;
     }
diff --git a/wa/starter/src/test/java/org/apache/syncope/wa/starter/events/SyncopeWAEventRepositoryTest.java b/wa/starter/src/test/java/org/apache/syncope/wa/starter/events/SyncopeWAEventRepositoryTest.java
index e823ed3..cd6ac5a 100644
--- a/wa/starter/src/test/java/org/apache/syncope/wa/starter/events/SyncopeWAEventRepositoryTest.java
+++ b/wa/starter/src/test/java/org/apache/syncope/wa/starter/events/SyncopeWAEventRepositoryTest.java
@@ -25,25 +25,25 @@ import static org.mockito.Mockito.when;
 
 import java.util.Map;
 import org.apache.syncope.client.lib.SyncopeClient;
-import org.apache.syncope.common.lib.log.AuditEntry;
-import org.apache.syncope.common.rest.api.service.LoggerService;
+import org.apache.syncope.common.lib.audit.AuditEntry;
 import org.apache.syncope.wa.bootstrap.WARestClient;
 import org.apache.syncope.wa.starter.AbstractTest;
 import org.apereo.cas.support.events.CasEventRepositoryFilter;
 import org.apereo.cas.support.events.dao.CasEvent;
 import org.junit.jupiter.api.Test;
+import org.apache.syncope.common.rest.api.service.AuditService;
 
 public class SyncopeWAEventRepositoryTest extends AbstractTest {
 
-    private static LoggerService loggerService;
+    private static AuditService auditService;
 
     private static WARestClient getWaRestClient() {
         WARestClient restClient = mock(WARestClient.class);
         SyncopeClient syncopeClient = mock(SyncopeClient.class);
-        loggerService = mock(LoggerService.class);
+        auditService = mock(AuditService.class);
 
         when(restClient.getSyncopeClient()).thenReturn(syncopeClient);
-        when(syncopeClient.getService(LoggerService.class)).thenReturn(loggerService);
+        when(syncopeClient.getService(AuditService.class)).thenReturn(auditService);
 
         return restClient;
     }
@@ -54,7 +54,7 @@ public class SyncopeWAEventRepositoryTest extends AbstractTest {
         SyncopeWAEventRepository eventRepository = new SyncopeWAEventRepository(CasEventRepositoryFilter.noOp(),
                 getWaRestClient());
         eventRepository.saveInternal(event);
-        verify(loggerService).create(any(AuditEntry.class));
+        verify(auditService).create(any(AuditEntry.class));
     }
 
 }