Skip to content

feat(logging): manage node log rotation, retention, and compression, close #257#256

Open
gzliudan wants to merge 4 commits intoXinFinOrg:masterfrom
gzliudan:rotate-log-file
Open

feat(logging): manage node log rotation, retention, and compression, close #257#256
gzliudan wants to merge 4 commits intoXinFinOrg:masterfrom
gzliudan:rotate-log-file

Conversation

@gzliudan
Copy link
Copy Markdown
Contributor

@gzliudan gzliudan commented Apr 3, 2026

Summary

This PR improves node log lifecycle management for devnet, mainnet, and testnet deployments.

It combines the logging changes in this branch into one operator-facing workflow:

  • rotate node logs by day while keeping graceful shutdown behavior for the log writer
  • retain logs for a configurable number of days with automatic cleanup of expired files
  • compress older retained logs while keeping the most recent logs uncompressed for easier inspection
  • raise the default log verbosity from 2 to 3 in shipped configuration files and script fallbacks

What changed

  • updated the devnet, mainnet, and testnet startup scripts to write rotated XDC logs under /work/xdcchain
  • added LOG_KEEP_DAYS to control how many days of logs are retained
  • added LOG_UNCOMPRESSED_DAYS to keep recent logs in plain text and gzip older retained logs
  • added compression lock recovery and stale temporary file cleanup for interrupted compression runs
  • changed the default LOG_LEVEL from 2 to 3 in shipped env files and script defaults
  • updated compose files, environment examples, and README documentation so the new logging settings are visible in deployment configuration

Motivation and impact

Node logs currently require manual cleanup and can grow without bound over time. This PR reduces disk usage, keeps recent logs easy to inspect during operations, and makes log handling more consistent across devnet, mainnet, and testnet environments.

Raising the default log level to 3 also makes fresh deployments more verbose out of the box, which improves operational visibility when LOG_LEVEL is not overridden.

The resulting behavior is:

  • recent logs remain uncompressed for troubleshooting
  • older retained logs are compressed automatically
  • expired logs are removed automatically
  • log rotation and shutdown continue to be handled by the startup scripts rather than external log tooling
  • new or default deployments emit log level 3 unless operators set LOG_LEVEL explicitly

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 3, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Startup scripts now perform daily, in-process log rotation, retention, and optional compression: devnet/start.sh, mainnet/start-node.sh, and testnet/start-apothem.sh stream XDC stdout/stderr line-by-line into dated logs, rotate at midnight, enforce LOG_KEEP_DAYS/LOG_UNCOMPRESSED_DAYS, run async compression with a lock/stale-lock recovery, and exit with XDC's exit code.

Changes

Cohort / File(s) Summary
Startup scripts (rotation, retention, compression)
devnet/start.sh, mainnet/start-node.sh, testnet/start-apothem.sh
Replaced one-shot timestamped LOG_FILE + tee pipeline with a line-oriented logger: compute current_log_file and next_rotation_epoch, rotate at midnight, append lines via write_log_line, validate LOG_KEEP_DAYS/LOG_UNCOMPRESSED_DAYS, delete expired logs, capture PIPESTATUS[0] and exit with it. Added asynchronous compression of older .log.log.gz guarded by a lock directory and stale-lock recovery; uses ionice/renice when available.
Environment configs (added vars)
mainnet/.env, mainnet/env.example, testnet/.env, devnet/envs/*
Added LOG_KEEP_DAYS=30 and LOG_UNCOMPRESSED_DAYS=3 to mainnet/testnet env files and multiple devnet instance env files to configure retention and uncompressed-window defaults.
Docs
README.md
Added “Log Retention Settings” section documenting LOG_KEEP_DAYS, LOG_UNCOMPRESSED_DAYS, default values, validation rule, and rotation/compression behavior.
Minor change
devnet/start.sh
Writes "$PRIVATE_KEY" to /tmp/key using quoted expansion (avoids unquoted variable expansion).

Sequence Diagram

sequenceDiagram
    participant Script as Startup Script
    participant XDC as XDC Process
    participant FS as File System
    participant Compressor as Async Compressor

    Script->>Script: compute current_log_file (xdc-YYYYMMDD-*.log) and next_rotation_epoch
    Script->>XDC: start XDC (stdout+stderr piped to read loop)
    loop for each output line
        XDC->>Script: emit line
        Script->>Script: if now >= next_rotation_epoch then rotate
        alt rotate
            Script->>FS: touch new current_log_file
            Script->>Script: update current_log_file & next_rotation_epoch
        end
        Script->>FS: append line to current_log_file
        Script->>Script: echo line to stdout
    end
    note over Compressor,FS: periodically (or on rotation) Compressor attempts compression
    Compressor->>Compressor: obtain lock dir, detect stale locks via /proc, recover if needed
    Compressor->>FS: gzip eligible .log → .log.gz (skip if gzip unavailable), remove tmp artifacts
    XDC->>Script: exit
    Script->>Script: read PIPESTATUS[0]
    Script->>Script: exit with XDC's code
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hop through lines at midnight's chime,
I nudge old crumbs into a zippy clime,
Dates keep order, locks keep pace,
I echo each line and save its trace,
Then I bow out with the node's last sign.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed All primary requirements from issue #257 are met: daily log rotation is implemented in startup scripts, stdout logging is preserved, retention/compression via LOG_KEEP_DAYS and LOG_UNCOMPRESSED_DAYS is added, and XDC exit codes are properly propagated.
Out of Scope Changes check ✅ Passed All changes are within scope: logging system implementation in three startup scripts, retention variable configuration across environment files, process exit code handling, and documentation updates align with the linked issue objectives.
Title check ✅ Passed The title 'feat(logging): manage node log rotation, retention, and compression, close #257' accurately summarizes the main changes—implementing log rotation, retention policies, and compression across startup scripts and environment configurations.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
mainnet/start-node.sh (1)

36-45: Plan retention for the daily log files.

Line 36 writes xdc-YYYYMMDD.log under /work/xdcchain, but nothing here compresses or expires older files. On long-lived nodes, those logs can eventually compete with chaindata for disk. Consider handing this directory off to logrotate or pruning after N days.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mainnet/start-node.sh` around lines 36 - 45, The script currently creates
daily files in set_current_log_file using variables log_dir, current_log_date,
current_log_file and next_rotation_epoch but does not rotate or prune older
logs; add retention by either (a) integrating with system logrotate (write a
/etc/logrotate.d/xdcchain snippet that rotates xdc-YYYYMMDD.log, compresses, and
keeps N rotations) or (b) adding a simple pruning routine in the script that
runs at midnight (or when next_rotation_epoch is reached) to gzip older logs and
delete files older than N days (operate on files matching
"${log_dir}/xdc-*.log"); update set_current_log_file or add a separate
rotate_logs function to trigger compression/deletion and ensure it runs before
creating a new current_log_file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@devnet/start.sh`:
- Around line 3-4: Replace the insecure append to /tmp/key with a secure
ephemeral temp file: create a temp file via mktemp (e.g., keyfile=$(mktemp)),
immediately chmod 600 "$keyfile", write the PRIVATE_KEY to it with an overwrite
write (printf '%s' "$PRIVATE_KEY" > "$keyfile"), call the import using that
variable (wallet=$(XDC account import --password .pwd --datadir /work/xdcchain
"$keyfile" | awk -F '[{}]' '{print $2}')), and ensure the temp file is removed
after import (use trap 'rm -f "$keyfile"' EXIT or rm -f "$keyfile" after the
import) so the key is not left on disk and repeated runs remain idempotent.

---

Nitpick comments:
In `@mainnet/start-node.sh`:
- Around line 36-45: The script currently creates daily files in
set_current_log_file using variables log_dir, current_log_date, current_log_file
and next_rotation_epoch but does not rotate or prune older logs; add retention
by either (a) integrating with system logrotate (write a
/etc/logrotate.d/xdcchain snippet that rotates xdc-YYYYMMDD.log, compresses, and
keeps N rotations) or (b) adding a simple pruning routine in the script that
runs at midnight (or when next_rotation_epoch is reached) to gzip older logs and
delete files older than N days (operate on files matching
"${log_dir}/xdc-*.log"); update set_current_log_file or add a separate
rotate_logs function to trigger compression/deletion and ensure it runs before
creating a new current_log_file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e99ea35e-512a-4170-9f16-b473f317beb8

📥 Commits

Reviewing files that changed from the base of the PR and between 88bc0b6 and a9c134f.

📒 Files selected for processing (3)
  • devnet/start.sh
  • mainnet/start-node.sh
  • testnet/start-apothem.sh

Comment thread devnet/start.sh
Comment on lines +3 to 4
echo "$PRIVATE_KEY" >>/tmp/key
wallet=$(XDC account import --password .pwd --datadir /work/xdcchain /tmp/key | awk -F '[{}]' '{print $2}')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use an ephemeral, locked-down key file here.

Line 3 appends the raw private key to a predictable /tmp/key path and never removes it. That leaves sensitive material on disk and makes repeated starts non-idempotent because the file can accumulate multiple keys. Create a temp file with restrictive permissions, overwrite it, and delete it after import.

Suggested fix
 if [ ! -d /work/xdcchain/XDC/chaindata ]; then
-    echo "$PRIVATE_KEY" >>/tmp/key
-    wallet=$(XDC account import --password .pwd --datadir /work/xdcchain /tmp/key | awk -F '[{}]' '{print $2}')
+    key_file="$(mktemp /tmp/xdc-key.XXXXXX)"
+    chmod 600 "$key_file"
+    trap 'rm -f "$key_file"' EXIT
+    printf '%s\n' "$PRIVATE_KEY" >"$key_file"
+    wallet=$(XDC account import --password .pwd --datadir /work/xdcchain "$key_file" | awk -F '[{}]' '{print $2}')
     XDC init --datadir /work/xdcchain /work/genesis.json
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo "$PRIVATE_KEY" >>/tmp/key
wallet=$(XDC account import --password .pwd --datadir /work/xdcchain /tmp/key | awk -F '[{}]' '{print $2}')
if [ ! -d /work/xdcchain/XDC/chaindata ]; then
key_file="$(mktemp /tmp/xdc-key.XXXXXX)"
chmod 600 "$key_file"
trap 'rm -f "$key_file"' EXIT
printf '%s\n' "$PRIVATE_KEY" >"$key_file"
wallet=$(XDC account import --password .pwd --datadir /work/xdcchain "$key_file" | awk -F '[{}]' '{print $2}')
XDC init --datadir /work/xdcchain /work/genesis.json
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@devnet/start.sh` around lines 3 - 4, Replace the insecure append to /tmp/key
with a secure ephemeral temp file: create a temp file via mktemp (e.g.,
keyfile=$(mktemp)), immediately chmod 600 "$keyfile", write the PRIVATE_KEY to
it with an overwrite write (printf '%s' "$PRIVATE_KEY" > "$keyfile"), call the
import using that variable (wallet=$(XDC account import --password .pwd
--datadir /work/xdcchain "$keyfile" | awk -F '[{}]' '{print $2}')), and ensure
the temp file is removed after import (use trap 'rm -f "$keyfile"' EXIT or rm -f
"$keyfile" after the import) so the key is not left on disk and repeated runs
remain idempotent.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
devnet/start.sh (1)

3-4: ⚠️ Potential issue | 🟠 Major

Still importing the key through a predictable /tmp/key file.

Line 3 appends a raw private key to disk and never removes it, so repeated starts can accumulate secrets and leave sensitive material behind. Please switch to a locked-down temp file and clean it up right after the import.

Suggested fix
-    echo "$PRIVATE_KEY" >>/tmp/key
-    wallet=$(XDC account import --password .pwd --datadir /work/xdcchain /tmp/key | awk -F '[{}]' '{print $2}')
+    key_file="$(mktemp /tmp/xdc-key.XXXXXX)"
+    chmod 600 "$key_file"
+    trap 'rm -f "$key_file"' EXIT
+    printf '%s\n' "$PRIVATE_KEY" >"$key_file"
+    wallet=$(XDC account import --password .pwd --datadir /work/xdcchain "$key_file" | awk -F '[{}]' '{print $2}')
+    rm -f "$key_file"
+    trap - EXIT
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@devnet/start.sh` around lines 3 - 4, The script currently writes the raw
PRIVATE_KEY to a predictable /tmp/key and never removes it; change the flow used
around the XDC account import to create a secure, unique temp file (e.g., via
mktemp) with restrictive permissions, write PRIVATE_KEY to that temp file, run
the XDC account import and capture the wallet variable as before, then securely
delete/unlink the temp file immediately after import (and add a trap to ensure
cleanup on exit). Ensure you update the commands around the XDC account import
(the line producing wallet=$(XDC account import ... /tmp/key | awk ...)) to
point at the temp file and remove references to /tmp/key.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@devnet/start.sh`:
- Around line 34-38: The filename currently includes time (%H%M%S) causing
multiple log files per day; in set_current_log_file change current_log_date to
use only the calendar date (date +%Y%m%d) so current_log_file becomes
"${log_dir}/xdc-${current_log_date}.log" and restarts will append to the same
daily file; keep touch "${current_log_file}" and next_rotation_epoch calculation
as-is so rotation still occurs at tomorrow 00:00:00.

In `@mainnet/start-node.sh`:
- Around line 41-45: The log filename uses a timestamp including
hours/minutes/seconds so each restart makes a new file; in set_current_log_file
change current_log_date to only the day (use date +%Y%m%d) and build
current_log_file as "${log_dir}/xdc-${current_log_date}.log" so restarts on the
same day continue the same file; keep next_rotation_epoch logic (date -d
'tomorrow 00:00:00' +%s) unchanged and ensure touch/create of current_log_file
still occurs if it doesn't exist.

In `@testnet/start-apothem.sh`:
- Around line 44-48: The current set_current_log_file function uses date format
%Y%m%d-%H%M%S (current_log_date) which creates a new per-start file; change
current_log_date to use only the date (e.g., date +%Y%m%d) so current_log_file
becomes xdc-YYYYMMDD.log and restarts on the same day reuse the same file, keep
the touch of "${current_log_file}" and keep next_rotation_epoch computed the
same way; update the variable current_log_date and current_log_file in
set_current_log_file accordingly.

---

Duplicate comments:
In `@devnet/start.sh`:
- Around line 3-4: The script currently writes the raw PRIVATE_KEY to a
predictable /tmp/key and never removes it; change the flow used around the XDC
account import to create a secure, unique temp file (e.g., via mktemp) with
restrictive permissions, write PRIVATE_KEY to that temp file, run the XDC
account import and capture the wallet variable as before, then securely
delete/unlink the temp file immediately after import (and add a trap to ensure
cleanup on exit). Ensure you update the commands around the XDC account import
(the line producing wallet=$(XDC account import ... /tmp/key | awk ...)) to
point at the temp file and remove references to /tmp/key.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0fc66dd3-e31d-4aa0-a8b6-a46759c6a115

📥 Commits

Reviewing files that changed from the base of the PR and between a9c134f and feed5b6.

📒 Files selected for processing (3)
  • devnet/start.sh
  • mainnet/start-node.sh
  • testnet/start-apothem.sh

Comment thread devnet/start.sh Outdated
Comment thread mainnet/start-node.sh Outdated
Comment thread testnet/start-apothem.sh Outdated
@gzliudan gzliudan changed the title feat(logging): rotate node logs by day feat(logging): rotate and retain node logs by day Apr 3, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (4)
mainnet/start-node.sh (1)

55-57: ⚠️ Potential issue | 🟠 Major

This is still restart-based, not day-based.

Line 68 still uses %H%M%S, so a restart later the same day creates another file instead of appending to xdc-YYYYMMDD.log. Line 55 also still parses the timestamped shape, so retention needs the matching update too.

Suggested fix
-        if [[ "$log_name" =~ ^xdc-([0-9]{8})-[0-9]{6}\.log$ ]]; then
+        if [[ "$log_name" =~ ^xdc-([0-9]{8})\.log$ ]]; then
             log_date="${BASH_REMATCH[1]}"
             if [[ "$log_date" < "$retention_start_date" ]]; then
                 rm -f -- "$log_file"
                 deleted_logs=$((deleted_logs + 1))
             fi
         fi
@@
-    current_log_date="$(date +%Y%m%d-%H%M%S)"
+    current_log_date="$(date +%Y%m%d)"
     current_log_file="${log_dir}/xdc-${current_log_date}.log"

Also applies to: 67-70

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mainnet/start-node.sh` around lines 55 - 57, The retention check and rotation
are still using timestamped filenames and the log creation still includes time
(%H%M%S), so change the log naming to produce xdc-YYYYMMDD.log (remove the time
suffix) where the file is created (replace use of %H%M%S), and update the
parsing regex/pattern that sets log_date from log_name (currently using
^xdc-([0-9]{8})-[0-9]{6}\.log$) to match ^xdc-([0-9]{8})\.log$; also update any
other places that construct or match log filenames (variables: log_name,
log_date, retention_start_date) so retention compares the YYYYMMDD date only and
multiple restarts on the same day append to the same file.
testnet/start-apothem.sh (1)

58-60: ⚠️ Potential issue | 🟠 Major

This still creates per-start log files.

Line 71 still includes %H%M%S, so same-day restarts will keep producing xdc-YYYYMMDD-HHMMSS.log instead of reusing xdc-YYYYMMDD.log. Line 58 also still expects the timestamped filename, so retention needs to be adjusted in the same patch.

Suggested fix
-        if [[ "$log_name" =~ ^xdc-([0-9]{8})-[0-9]{6}\.log$ ]]; then
+        if [[ "$log_name" =~ ^xdc-([0-9]{8})\.log$ ]]; then
             log_date="${BASH_REMATCH[1]}"
             if [[ "$log_date" < "$retention_start_date" ]]; then
                 rm -f -- "$log_file"
                 deleted_logs=$((deleted_logs + 1))
             fi
         fi
@@
-    current_log_date="$(date +%Y%m%d-%H%M%S)"
+    current_log_date="$(date +%Y%m%d)"
     current_log_file="${log_dir}/xdc-${current_log_date}.log"

Also applies to: 70-73

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testnet/start-apothem.sh` around lines 58 - 60, The log rotation/retention
still treats filenames as timestamped per-start (regex
^xdc-([0-9]{8})-[0-9]{6}\.log$ and the %H%M%S in the rotation format) so
same-day restarts create new files; change the filename format to date-only and
update the matching/retention logic accordingly: update the regex that parses
log_name to ^xdc-([0-9]{8})\.log$ (so log_date captures YYYYMMDD), remove %H%M%S
from the log filename generation so logs are named xdc-YYYYMMDD.log, and ensure
the comparison against retention_start_date still uses log_date and
retention_start_date for correct deletion; apply the same change to the other
occurrence mentioned (around lines 70-73).
devnet/start.sh (2)

48-50: ⚠️ Potential issue | 🟠 Major

Use the calendar day as the filename key.

Line 61 still includes %H%M%S, so same-day restarts keep creating xdc-YYYYMMDD-HHMMSS.log instead of continuing one xdc-YYYYMMDD.log. Line 48 still matches the timestamped pattern, so retention needs to be updated in the same change.

Suggested fix
-        if [[ "$log_name" =~ ^xdc-([0-9]{8})-[0-9]{6}\.log$ ]]; then
+        if [[ "$log_name" =~ ^xdc-([0-9]{8})\.log$ ]]; then
             log_date="${BASH_REMATCH[1]}"
             if [[ "$log_date" < "$retention_start_date" ]]; then
                 rm -f -- "$log_file"
                 deleted_logs=$((deleted_logs + 1))
             fi
         fi
@@
-    current_log_date="$(date +%Y%m%d-%H%M%S)"
+    current_log_date="$(date +%Y%m%d)"
     current_log_file="${log_dir}/xdc-${current_log_date}.log"

Also applies to: 60-63

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@devnet/start.sh` around lines 48 - 50, The retention matching and log
rotation should use the calendar day only: change the filename pattern that
reads log_name and sets log_date to match ^xdc-([0-9]{8})\.log$ (no -HHMMSS) and
update the creation logic so the logfile produced by the script is named
xdc-YYYYMMDD.log (remove %H%M%S from the filename generation), then ensure
comparisons against retention_start_date use the extracted log_date variable;
update the corresponding checks around log_name, log_date and
retention_start_date (also the same logic at the other occurrence around lines
60-63) so same-day restarts append to the same xdc-YYYYMMDD.log and retention
deletes by day only.

3-4: ⚠️ Potential issue | 🟠 Major

Stop persisting the raw private key in /tmp/key.

Line 3 still appends the secret to a predictable file and never removes it. That leaves key material on disk and makes repeated bootstrap runs non-idempotent because multiple keys can accumulate in the same file.

Suggested fix
-    echo "$PRIVATE_KEY" >>/tmp/key
-    wallet=$(XDC account import --password .pwd --datadir /work/xdcchain /tmp/key | awk -F '[{}]' '{print $2}')
+    key_file="$(mktemp /tmp/xdc-key.XXXXXX)"
+    chmod 600 "$key_file"
+    trap 'rm -f "$key_file"' EXIT
+    printf '%s\n' "$PRIVATE_KEY" >"$key_file"
+    wallet=$(XDC account import --password .pwd --datadir /work/xdcchain "$key_file" | awk -F '[{}]' '{print $2}')
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@devnet/start.sh` around lines 3 - 4, The script is writing the raw
PRIVATE_KEY to a predictable file (/tmp/key) and never removing it; update the
devnet start script so the key is not persisted to disk by piping the secret
directly into the XDC import command or using a secure temporary file that is
immediately deleted. Replace the echo >>/tmp/key + XDC account import flow with
a here-string or stdin pipe (e.g. printf '%s\n' "$PRIVATE_KEY" | XDC account
import --password .pwd --datadir /work/xdcchain /dev/stdin ...) or, if a temp
file is required, create it with mktemp, set strict permissions, run XDC account
import against it, and rm -f the temp file immediately after; ensure you still
capture the wallet id as before (wallet=$(... | awk -F '[{}]' '{print $2}')).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@devnet/start.sh`:
- Around line 48-50: The retention matching and log rotation should use the
calendar day only: change the filename pattern that reads log_name and sets
log_date to match ^xdc-([0-9]{8})\.log$ (no -HHMMSS) and update the creation
logic so the logfile produced by the script is named xdc-YYYYMMDD.log (remove
%H%M%S from the filename generation), then ensure comparisons against
retention_start_date use the extracted log_date variable; update the
corresponding checks around log_name, log_date and retention_start_date (also
the same logic at the other occurrence around lines 60-63) so same-day restarts
append to the same xdc-YYYYMMDD.log and retention deletes by day only.
- Around line 3-4: The script is writing the raw PRIVATE_KEY to a predictable
file (/tmp/key) and never removing it; update the devnet start script so the key
is not persisted to disk by piping the secret directly into the XDC import
command or using a secure temporary file that is immediately deleted. Replace
the echo >>/tmp/key + XDC account import flow with a here-string or stdin pipe
(e.g. printf '%s\n' "$PRIVATE_KEY" | XDC account import --password .pwd
--datadir /work/xdcchain /dev/stdin ...) or, if a temp file is required, create
it with mktemp, set strict permissions, run XDC account import against it, and
rm -f the temp file immediately after; ensure you still capture the wallet id as
before (wallet=$(... | awk -F '[{}]' '{print $2}')).

In `@mainnet/start-node.sh`:
- Around line 55-57: The retention check and rotation are still using
timestamped filenames and the log creation still includes time (%H%M%S), so
change the log naming to produce xdc-YYYYMMDD.log (remove the time suffix) where
the file is created (replace use of %H%M%S), and update the parsing
regex/pattern that sets log_date from log_name (currently using
^xdc-([0-9]{8})-[0-9]{6}\.log$) to match ^xdc-([0-9]{8})\.log$; also update any
other places that construct or match log filenames (variables: log_name,
log_date, retention_start_date) so retention compares the YYYYMMDD date only and
multiple restarts on the same day append to the same file.

In `@testnet/start-apothem.sh`:
- Around line 58-60: The log rotation/retention still treats filenames as
timestamped per-start (regex ^xdc-([0-9]{8})-[0-9]{6}\.log$ and the %H%M%S in
the rotation format) so same-day restarts create new files; change the filename
format to date-only and update the matching/retention logic accordingly: update
the regex that parses log_name to ^xdc-([0-9]{8})\.log$ (so log_date captures
YYYYMMDD), remove %H%M%S from the log filename generation so logs are named
xdc-YYYYMMDD.log, and ensure the comparison against retention_start_date still
uses log_date and retention_start_date for correct deletion; apply the same
change to the other occurrence mentioned (around lines 70-73).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e8d99536-ca85-4152-9ada-3d0a68a0156e

📥 Commits

Reviewing files that changed from the base of the PR and between 41ef3f8 and 55b6c2e.

📒 Files selected for processing (16)
  • devnet/envs/144.126.140.3-1
  • devnet/envs/144.126.140.3-2
  • devnet/envs/194.163.167.177-1
  • devnet/envs/194.163.167.177-2
  • devnet/envs/194.233.77.19-1
  • devnet/envs/194.233.77.19-2
  • devnet/envs/66.94.121.151-1
  • devnet/envs/66.94.121.151-2
  • devnet/envs/66.94.98.186-1
  • devnet/envs/66.94.98.186-2
  • devnet/start.sh
  • mainnet/.env
  • mainnet/env.example
  • mainnet/start-node.sh
  • testnet/.env
  • testnet/start-apothem.sh
✅ Files skipped from review due to trivial changes (11)
  • devnet/envs/194.163.167.177-2
  • devnet/envs/66.94.98.186-1
  • devnet/envs/66.94.121.151-2
  • devnet/envs/144.126.140.3-1
  • devnet/envs/194.163.167.177-1
  • devnet/envs/144.126.140.3-2
  • devnet/envs/66.94.98.186-2
  • devnet/envs/194.233.77.19-1
  • devnet/envs/194.233.77.19-2
  • mainnet/env.example
  • devnet/envs/66.94.121.151-1

@gzliudan gzliudan changed the title feat(logging): rotate and retain node logs by day feat(logging): rotate, retain, and compress node logs Apr 3, 2026
@gzliudan gzliudan force-pushed the rotate-log-file branch 12 times, most recently from e0d4f7e to 225a6ca Compare April 4, 2026 03:37
Replace the mixed tee/redirection pipeline in the devnet, mainnet, and testnet startup scripts with a bash-native log streamer that creates the first timestamped log file before XDC starts and rotates on day boundaries.

Mirror XDC output to stdout and the active daily log, forward TERM/INT, wait for both the XDC process and the log writer to exit, and preserve the node exit status.

Mount the upstream entry.sh in the mainnet and testnet compose files and add a 60s stop_grace_period so containers can finish the shutdown path and flush logs before Docker sends SIGKILL.
Add LOG_KEEP_DAYS defaults to the mainnet, testnet, and devnet runtime configs.
Delete expired xdc-*.log files on startup and after daily log rotation.
Reject retention values below 3 days to avoid accidental log loss.
Add gzip compression for rotated logs in mainnet, testnet, and devnet startup scripts with lock-based async processing.

Validate retention settings with LOG_KEEP_DAYS >= 3, LOG_UNCOMPRESSED_DAYS >= 2, and enforce LOG_UNCOMPRESSED_DAYS <= LOG_KEEP_DAYS; update env examples and README accordingly.
@gzliudan gzliudan changed the title feat(logging): rotate, retain, and compress node logs feat(logging): manage node log rotation, retention, and compression Apr 4, 2026
@gzliudan gzliudan changed the title feat(logging): manage node log rotation, retention, and compression feat(logging): manage node log rotation, retention, and compression, close #257 Apr 4, 2026
Update all shipped env files and startup script defaults to use log level 3 so new deployments and unset environments are more verbose by default.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant