Skip to content

Commit 6342c69

Browse files
committed
Integrated UUID into RotatingCLPFileHandler file naming and minor changes to the config file
1 parent 02a07f3 commit 6342c69

File tree

2 files changed

+64
-11
lines changed

2 files changed

+64
-11
lines changed

application/log_handlers/handlers.py

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import uuid
23
from pathlib import Path
34
from typing import Optional
45
from clp_logging.handlers import CLPFileHandler, CLPLogLevelTimeout, EOF_CHAR, FLUSH_FRAME
@@ -41,15 +42,65 @@ def __init__(
4142
loglevel_timeout=loglevel_timeout,
4243
)
4344

45+
@staticmethod
46+
def _get_persistent_machine_uuid() -> str:
47+
"""
48+
Retrieves a persistent machine-specific UUID:
49+
- First checks the `iCtrl_LOG_UUID` environment variable.
50+
- If not found, checks a system-wide file (`/etc/iCtrl_machine_log_uuid` or `~/.iCtrl_machine_log_uuid`).
51+
- If still not found, generates a new UUID, saves it, and returns only the first 8 characters.
52+
"""
53+
env_var_name = "iCtrl_LOG_UUID"
54+
55+
# 1️⃣ Check if UUID exists in an environment variable
56+
env_uuid = os.getenv(env_var_name)
57+
if env_uuid:
58+
return env_uuid.strip()[:8] # Limit to first 8 characters
59+
60+
# 2️⃣ Define a persistent file path
61+
if os.name == "nt": # Windows
62+
uuid_file = Path(os.getenv("APPDATA", "C:/ProgramData")) / "iCtrl_machine_log_uuid.txt"
63+
else: # Linux/macOS
64+
uuid_file = Path(
65+
"/etc/iCtrl_machine_log_uuid") if os.geteuid() == 0 else Path.home() / ".iCtrl_machine_log_uuid"
66+
67+
# 3️⃣ Check if the file exists and read the UUID
68+
if uuid_file.exists():
69+
with open(uuid_file, "r") as f:
70+
machine_uuid = f.read().strip()[:8] # Limit to first 8 characters
71+
os.environ[env_var_name] = machine_uuid # Store in environment for future use
72+
return machine_uuid
73+
74+
# 4️⃣ Generate a new UUID and store only the first 8 characters
75+
new_uuid = str(uuid.uuid4())[:8]
76+
77+
try:
78+
with open(uuid_file, "w") as f:
79+
f.write(new_uuid)
80+
os.environ[env_var_name] = new_uuid # Store in environment
81+
except PermissionError:
82+
print(f"Warning: Could not save machine UUID to {uuid_file}. Using in-memory only.")
83+
84+
return new_uuid
85+
4486
def _generate_log_filename(self) -> Path:
4587
"""
46-
Generate a log filename with the timestamp and prefix.
88+
Generate a log filename with the prefix, persistent UUID and timestamp.
89+
If a file with the same name already exists, append a counter (_1, _2, etc.).
4790
"""
48-
start_time = datetime.now()
49-
timestamp = start_time.strftime(self.timestamp_format)
50-
self.current_log_file = Path(f"{self.log_dir}/{self.filename_prefix}_{timestamp}.clp.zst")
91+
uuid_str = self._get_persistent_machine_uuid() # Get the persistent UUID
92+
timestamp = datetime.now().strftime(self.timestamp_format)
93+
94+
base_filename = f"{self.filename_prefix}_{uuid_str}_{timestamp}"
95+
file_path = self.log_dir / f"{base_filename}.clp.zst"
5196

52-
return self.current_log_file
97+
# Check for name conflicts and append a counter if necessary
98+
counter = 1
99+
while file_path.exists():
100+
file_path = self.log_dir / f"{base_filename}_{counter}.clp.zst"
101+
counter += 1
102+
103+
return file_path
53104

54105
def _should_rotate(self) -> bool:
55106
"""
@@ -62,7 +113,7 @@ def _should_rotate(self) -> bool:
62113

63114
def _rotate(self) -> None:
64115
"""
65-
Perform log rotation by finalizing the current stream, creating a new log file,
116+
Perform log rotation by finalizing the current stream, creating a new log file,
66117
and reinitializing the handler with the new stream.
67118
68119
This method is responsible for:
@@ -73,7 +124,7 @@ def _rotate(self) -> None:
73124
5. Opening a new stream for the new log file and reinitializing the handler to use it.
74125
6. Removing old log files if the number of backups exceeds the specified backup count.
75126
76-
Thread safety is ensured by acquiring and releasing the handler's lock during the
127+
Thread safety is ensured by acquiring and releasing the handler's lock during the
77128
transition between streams.
78129
"""
79130
try:
@@ -82,7 +133,7 @@ def _rotate(self) -> None:
82133
finally:
83134
self.ostream.close()
84135

85-
# Generate a new log filename
136+
# Generate a new log filename (same UUID, new timestamp)
86137
new_log_file = self._generate_log_filename()
87138

88139
# Initialize the new stream
@@ -103,13 +154,15 @@ def _rotate(self) -> None:
103154

104155
def _remove_old_backups(self) -> None:
105156
"""
106-
Remove old log files exceeding the backup count.
157+
Remove old log files exceeding the backup count, but only for the current machine UUID.
107158
"""
108159
if not self.backup_count:
109160
return
110161

162+
uuid_str = self._get_persistent_machine_uuid() # Get the persistent UUID
163+
111164
log_files = sorted(
112-
self.log_dir.glob(f"{self.filename_prefix}_*.clp.zst"),
165+
self.log_dir.glob(f"{self.filename_prefix}_{uuid_str}_*.clp.zst"),
113166
key=os.path.getmtime,
114167
)
115168
if len(log_files) > self.backup_count:

log_config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ handlers:
1616
max_bytes: 5242880 # Rotate after 5 MB
1717
backup_count: 20 # Keep 20 backup files
1818
enable_compression: True
19-
timestamp_format: '%Y-%m-%d'
19+
timestamp_format: '%Y-%m-%d_%H-%M-%S'
2020

2121
root:
2222
level: DEBUG

0 commit comments

Comments
 (0)