Skip to content

Log Rotation — File Size, Retention, and Compression

Log rotation prevents log files from consuming unlimited disk space by automatically archiving old log content when size or time limits are reached. MideyeServer uses Logback’s rolling appenders to manage log file rotation.

Default rotation policy:

  • Max file size: 10 MB
  • Policy type: FixedWindowRollingPolicy (numbered archives)
  • Trigger: SizeBasedTriggeringPolicy
  • Compression: Disabled (can be enabled)
  • Applies to: Both mideyeserver.log and mideyeserver.error

Both log files use identical rotation policies by default.

When mideyeserver.log reaches 10 MB:

  1. Current log renamed: mideyeserver.logmideyeserver.log.1
  2. Previous archives shifted: mideyeserver.log.1mideyeserver.log.2, etc.
  3. New empty log created: mideyeserver.log
  4. Oldest archive (if beyond configured window) is deleted

Example file listing after multiple rotations:

mideyeserver.log (current log)
mideyeserver.log.1 (most recent archive)
mideyeserver.log.2
mideyeserver.log.3
mideyeserver.log.4
mideyeserver.log.5 (oldest archive)

Edit the logback.xml file for your platform — see Overview for platform-specific paths.


To rotate at 50 MB instead of 10 MB:

logback.xml
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<charset>utf-8</charset>
<Pattern>${FILE_LOG_PATTERN}</Pattern>
</encoder>
<file>${LOG_PATH}/${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%i</fileNamePattern>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>50MB</MaxFileSize> <!-- Changed from 10MB -->
</triggeringPolicy>
</appender>

Supported size units:

  • KB — Kilobytes (1024 bytes)
  • MB — Megabytes (1024 KB)
  • GB — Gigabytes (1024 MB)

For environments with limited disk space:

logback.xml
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>5MB</MaxFileSize>
</triggeringPolicy>

Configuring retention (number of archives)

Section titled “Configuring retention (number of archives)”

By default, FixedWindowRollingPolicy without explicit minIndex/maxIndex keeps archives indefinitely (until manually deleted).

Keep only the 10 most recent archives:

logback.xml
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%i</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>10</maxIndex>
</rollingPolicy>

When rotation occurs and 10 archives already exist, the oldest (.10) is deleted before shifting.

For long-term retention:

logback.xml
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%i</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>100</maxIndex>
</rollingPolicy>

Compress rotated log files to save disk space.

Add .gz extension to the file name pattern:

logback.xml
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%i.gz</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>10</maxIndex>
</rollingPolicy>

Rotated files are now compressed:

mideyeserver.log
mideyeserver.log.1.gz
mideyeserver.log.2.gz
mideyeserver.log.3.gz

Compression ratio: Typically 85–95% size reduction for text logs.

Alternatively, use .zip extension:

logback.xml
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%i.zip</fileNamePattern>

For daily rotation regardless of file size, use TimeBasedRollingPolicy.

Rotate daily at midnight:

logback.xml
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<charset>utf-8</charset>
<Pattern>${FILE_LOG_PATTERN}</Pattern>
</encoder>
<file>${LOG_PATH}/${LOG_FILE}</file>
<!-- TimeBasedRollingPolicy replaces both rollingPolicy and triggeringPolicy -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- Daily rollover -->
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- Keep 30 days of history -->
<maxHistory>30</maxHistory>
<!-- Optional: total size cap -->
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
</appender>

Result:

mideyeserver.log (current day)
mideyeserver.log.2026-02-24.log
mideyeserver.log.2026-02-23.log
mideyeserver.log.2026-02-22.log

Rotate weekly on Sundays:

logback.xml
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%d{yyyy-ww}.log</fileNamePattern>
<maxHistory>12</maxHistory> <!-- Keep 12 weeks -->
</rollingPolicy>
logback.xml
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%d{yyyy-MM}.log</fileNamePattern>
<maxHistory>12</maxHistory> <!-- Keep 12 months -->
</rollingPolicy>
logback.xml
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>

Combine both strategies: rotate daily OR when file reaches size limit.

logback.xml
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<charset>utf-8</charset>
<Pattern>${FILE_LOG_PATTERN}</Pattern>
</encoder>
<file>${LOG_PATH}/${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- Daily rollover -->
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<!-- Each file, per day, max 50MB -->
<maxFileSize>50MB</maxFileSize>
<!-- Keep 30 days of history -->
<maxHistory>30</maxHistory>
<!-- Total size cap: 10GB -->
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
</appender>

Result (high-volume day):

mideyeserver.log
mideyeserver.log.2026-02-24.0.log.gz (first 50MB from Feb 24)
mideyeserver.log.2026-02-24.1.log.gz (second 50MB from Feb 24)
mideyeserver.log.2026-02-24.2.log.gz (third 50MB from Feb 24)
mideyeserver.log.2026-02-23.0.log.gz (Feb 23)

Configure different rotation policies for main and error logs.

logback.xml
<!-- Main log: daily rotation, 30 days -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<charset>utf-8</charset>
<Pattern>${FILE_LOG_PATTERN}</Pattern>
</encoder>
<file>${LOG_PATH}/${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>
<!-- Error log: 5MB rotation, keep 20 files -->
<appender name="FILE-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator>
<expression>return logger.startsWith("com.mideye");</expression>
</evaluator>
<OnMismatch>DENY</OnMismatch>
<OnMatch>NEUTRAL</OnMatch>
</filter>
<encoder>
<charset>utf-8</charset>
<Pattern>${FILE_LOG_PATTERN}</Pattern>
</encoder>
<file>${LOG_PATH}/${ERROR_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${LOG_PATH}/${ERROR_FILE}.%i.gz</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>20</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>5MB</MaxFileSize>
</triggeringPolicy>
</appender>

Terminal window
# Check log directory size
du -sh /opt/mideyeserver6/log/
# Detailed breakdown
du -h /opt/mideyeserver6/log/ | sort -h
# Count log files
ls -1 /opt/mideyeserver6/log/ | wc -l

Disk usage alerts:

Terminal window
# Nagios / Check_MK
/usr/lib/nagios/plugins/check_disk -w 20% -c 10% -p /opt/mideyeserver6/log/
# Zabbix
vfs.fs.size[/opt/mideyeserver6/log/,used]
vfs.fs.size[/opt/mideyeserver6/log/,pfree]

Force rotation without waiting for size/time trigger:

  1. Stop MideyeServer (or accept brief log loss)
  2. Rename current log:
    Terminal window
    cd /opt/mideyeserver6/log/
    mv mideyeserver.log mideyeserver.log.manual-$(date +%Y%m%d)
  3. Restart MideyeServer or wait for auto-creation

Move old logs to archive storage:

Terminal window
# Create archive directory
mkdir -p /archive/mideyeserver/$(date +%Y)
# Move logs older than 90 days
find /opt/mideyeserver6/log/ -name "mideyeserver.log.*" -mtime +90 \
-exec mv {} /archive/mideyeserver/$(date +%Y)/ \;
Terminal window
# Delete logs older than 30 days
find /opt/mideyeserver6/log/ -name "mideyeserver.log.*" -mtime +30 -delete
# Delete compressed logs older than 90 days
find /opt/mideyeserver6/log/ -name "*.gz" -mtime +90 -delete

Check Logback configuration syntax:

Terminal window
# Look for errors in console output
sudo journalctl -u mideyeserver6 | grep -i "logback\|rolling"

Verify file permissions:

Terminal window
ls -l /opt/mideyeserver6/log/
# MideyeServer user must have write access

Check disk space:

Terminal window
df -h /opt/mideyeserver6/log/
# If disk is full, rotation may fail

Verify .gz extension in fileNamePattern:

<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%i.gz</fileNamePattern>

Compression requires write permissions to the log directory.

Increase MaxFileSize:

<MaxFileSize>50MB</MaxFileSize>

Or switch to time-based rotation — use TimeBasedRollingPolicy for predictable daily/weekly rotation.

Add maxHistory to TimeBasedRollingPolicy:

<maxHistory>30</maxHistory>

Add minIndex/maxIndex to FixedWindowRollingPolicy:

<minIndex>1</minIndex>
<maxIndex>10</maxIndex>
Terminal window
# View compressed log
zcat mideyeserver.log.1.gz
# Search compressed log
zgrep "ERROR" mideyeserver.log.1.gz
# Decompress permanently
gunzip mideyeserver.log.1.gz # Creates mideyeserver.log.1

  1. Enable compression — Save 85–95% disk space with minimal CPU cost
  2. Set maxHistory — Prevent unlimited log accumulation
  3. Monitor disk usage — Alert before disk fills up
  4. Balance size and frequency — Larger files reduce rotation overhead
  5. Test configuration — Verify rotation works before production deployment
  6. Document retention policy — Align with compliance and troubleshooting needs
  7. Consider external archival — Move old logs to cheaper storage (S3, NAS)

  • Overview: Log file locations and default configuration
  • Log Levels: Reduce log volume by adjusting verbosity
  • Syslog / Log Aggregators: Forward logs to external systems (reduces local storage needs)