diff --git a/docs/Change Logs.md b/docs/Change Logs.md
index 30324af..ada851e 100644
--- a/docs/Change Logs.md
+++ b/docs/Change Logs.md
@@ -1,5 +1,24 @@
This page contains all of Logger's Change Logs. Starting in version 3.0.0 onwards, only major tickets will be listed here. To see a complete list of all the issues for each version, review the appropriate release page.
+
+## Change Log 3.2.0
+[Download](https://github.com/OraOpenSource/Logger/raw/master/releases/logger_3.2.0.zip)
+[Release Page](https://github.com/OraOpenSource/Logger/issues?utf8=%E2%9C%93&q=milestone%3A%22Release+3.2.0%22)
+Release Articles
+
+
+
+ | Issue# |
+ Feature |
+ Articles |
+
+
+ |
+ Configurable log retention days per log level. Added specific log-level retention preferences in `LOGGER_PREFS` (e.g., `PURGE_AFTER_DAYS_DEBUG`, `PURGE_AFTER_DAYS_INFORMATION`). If a specific preference is not set (i.e. does not exist in `LOGGER_PREFS`), the logs for that level will **not** be purged automatically. The general `PURGE_AFTER_DAYS` acts as a fallback only for undefined or custom log levels not covered by these preferences. Providing an explicit value via the `p_purge_after_days` parameter in `logger.purge` will override all preferences and enforce that retention across all purged levels. |
+ |
+
+
+
## Change Log 3.1.1
[Download](https://github.com/OraOpenSource/Logger/raw/master/releases/logger_3.1.1.zip)
diff --git a/docs/Installation.md b/docs/Installation.md
index 444d9ef..663db57 100644
--- a/docs/Installation.md
+++ b/docs/Installation.md
@@ -210,6 +210,10 @@ Logger stores its configuration settings in LOGGER_PREFS. These are the followin
PURGE_AFTER_DAYS |
Purge logs, equal to or higher than PURGE_MIN_LEVEL, after this many days. A purge job is run each night to clean up logger. |
+
+ | PURGE_AFTER_DAYS_<LEVEL> |
+ Specific retention settings per level. Replaces general PURGE_AFTER_DAYS for that specific level. If a preference does not exist or is null, logs for that specific level will not be purged automatically. Examples: PURGE_AFTER_DAYS_DEBUG, PURGE_AFTER_DAYS_INFORMATION, etc. |
+
| PURGE_MIN_LEVEL |
Min level to purge logs used in auto Logger cleanup job. |
diff --git a/docs/Logger API.md b/docs/Logger API.md
index 65466d4..8d8a327 100644
--- a/docs/Logger API.md
+++ b/docs/Logger API.md
@@ -854,7 +854,9 @@ logger.del_pref(
### PURGE
-TODO_DESC
+Purges records from `LOGGER_LOGS` table.
+
+If `p_purge_after_days` is not passed, it will use the specific retention periods defined in `LOGGER_PREFS` such as `PURGE_AFTER_DAYS_DEBUG`, `PURGE_AFTER_DAYS_INFORMATION`, etc. If a specific log level preference is not defined (i.e., it does not exist in the table or is null), it will **not** purge logs for that level. The general `PURGE_AFTER_DAYS` preference is only used as a fallback for any undocumented or custom log levels. Passing a global `p_purge_after_days` value overrides all preferences and enforces that retention limit across all purged levels.
#### Syntax
```sql
@@ -870,7 +872,7 @@ logger.purge(
| p_purge_after_days |
- Purge entries older than n days. |
+ Purge entries older than n days. If passed, overrides all preference table settings for all levels. |
| p_purge_min_level |
@@ -880,7 +882,8 @@ logger.purge(
#### Example
```sql
-TODO
+-- Manually purge everything older than 30 days
+exec logger.purge(p_purge_after_days => 30);
```
diff --git a/source/packages/logger.pkb b/source/packages/logger.pkb
index 8826ab6..6529f47 100644
--- a/source/packages/logger.pkb
+++ b/source/packages/logger.pkb
@@ -72,6 +72,13 @@ as
gc_pref_protect_admin_procs constant logger_prefs.pref_name%type := 'PROTECT_ADMIN_PROCS';
gc_pref_install_schema constant logger_prefs.pref_name%type := 'INSTALL_SCHEMA';
gc_pref_purge_after_days constant logger_prefs.pref_name%type := 'PURGE_AFTER_DAYS';
+ gc_pref_purge_after_days_debug constant logger_prefs.pref_name%type := 'PURGE_AFTER_DAYS_DEBUG';
+ gc_pref_purge_after_days_info constant logger_prefs.pref_name%type := 'PURGE_AFTER_DAYS_INFORMATION';
+ gc_pref_purge_after_days_warn constant logger_prefs.pref_name%type := 'PURGE_AFTER_DAYS_WARNING';
+ gc_pref_purge_after_days_error constant logger_prefs.pref_name%type := 'PURGE_AFTER_DAYS_ERROR';
+ gc_pref_purge_after_days_time constant logger_prefs.pref_name%type := 'PURGE_AFTER_DAYS_TIMING';
+ gc_pref_purge_after_days_sys constant logger_prefs.pref_name%type := 'PURGE_AFTER_DAYS_SYS_CONTEXT';
+ gc_pref_purge_after_days_apex constant logger_prefs.pref_name%type := 'PURGE_AFTER_DAYS_APEX';
gc_pref_purge_min_level constant logger_prefs.pref_name%type := 'PURGE_MIN_LEVEL';
gc_pref_logger_version constant logger_prefs.pref_name%type := 'LOGGER_VERSION';
gc_pref_client_id_expire_hours constant logger_prefs.pref_name%type := 'PREF_BY_CLIENT_ID_EXPIRE_HOURS';
@@ -2111,6 +2118,13 @@ as
is
$if $$no_op is null or not $$no_op $then
l_purge_after_days number := nvl(p_purge_after_days,get_pref(logger.gc_pref_purge_after_days));
+ l_days_debug number := nvl(p_purge_after_days, get_pref(gc_pref_purge_after_days_debug));
+ l_days_info number := nvl(p_purge_after_days, get_pref(gc_pref_purge_after_days_info));
+ l_days_warn number := nvl(p_purge_after_days, get_pref(gc_pref_purge_after_days_warn));
+ l_days_error number := nvl(p_purge_after_days, get_pref(gc_pref_purge_after_days_error));
+ l_days_time number := nvl(p_purge_after_days, get_pref(gc_pref_purge_after_days_time));
+ l_days_sys number := nvl(p_purge_after_days, get_pref(gc_pref_purge_after_days_sys));
+ l_days_apex number := nvl(p_purge_after_days, get_pref(gc_pref_purge_after_days_apex));
$end
pragma autonomous_transaction;
begin
@@ -2119,11 +2133,20 @@ as
$else
if admin_security_check then
- delete
- from logger_logs
- where logger_level >= p_purge_min_level
- and time_stamp < systimestamp - NUMTODSINTERVAL(l_purge_after_days, 'day')
- and logger_level > g_permanent;
+ delete from logger_logs
+ where logger_level >= p_purge_min_level
+ and logger_level > g_permanent
+ and time_stamp < systimestamp - NUMTODSINTERVAL(
+ case logger_level
+ when g_debug then l_days_debug
+ when g_information then l_days_info
+ when g_warning then l_days_warn
+ when g_error then l_days_error
+ when g_timing then l_days_time
+ when g_sys_context then l_days_sys
+ when g_apex then l_days_apex
+ else l_purge_after_days
+ end, 'day');
end if;
$end
commit;
diff --git a/source/tables/logger_prefs.sql b/source/tables/logger_prefs.sql
index 3b24047..b0e4a2a 100644
--- a/source/tables/logger_prefs.sql
+++ b/source/tables/logger_prefs.sql
@@ -110,6 +110,13 @@ begin
,'PROTECT_ADMIN_PROCS'
,'PURGE_AFTER_DAYS'
,'PURGE_MIN_LEVEL'
+ ,'PURGE_AFTER_DAYS_DEBUG'
+ ,'PURGE_AFTER_DAYS_INFORMATION'
+ ,'PURGE_AFTER_DAYS_WARNING'
+ ,'PURGE_AFTER_DAYS_ERROR'
+ ,'PURGE_AFTER_DAYS_TIMING'
+ ,'PURGE_AFTER_DAYS_SYS_CONTEXT'
+ ,'PURGE_AFTER_DAYS_APEX'
)
then
raise_application_error (-20000, 'Setting system level preferences are restricted to a set list.');