33import atexit
44import io
55import logging
6- import os
76import re
87import threading
98import time
109from dataclasses import dataclass
1110from datetime import datetime
1211from functools import reduce
12+ from pathlib import Path
1313from typing import Optional , List , Tuple
1414
1515import parse # type: ignore[import-untyped]
2222
2323from .arrow import FeatherWriter
2424
25+ logger = logging .getLogger (__name__ )
2526
2627def root_dir () -> str :
2728 """Return the root directory for slog files."""
2829
2930 app_name = "meshtastic"
3031 app_author = "meshtastic"
3132 app_dir = platformdirs .user_data_dir (app_name , app_author )
32- dir_name = f" { app_dir } / slogs"
33- os . makedirs ( dir_name , exist_ok = True )
34- return dir_name
33+ dir_name = Path ( app_dir , " slogs")
34+ dir_name . mkdir ( exist_ok = True )
35+ return str ( dir_name )
3536
3637
3738@dataclass (init = False )
@@ -197,7 +198,7 @@ def _onLogMessage(self, line: str) -> None:
197198 if m :
198199 src = m .group (1 )
199200 args = m .group (2 )
200- logging .debug (f"SLog { src } , args: { args } " )
201+ logger .debug (f"SLog { src } , args: { args } " )
201202
202203 d = log_defs .get (src )
203204 if d :
@@ -219,9 +220,9 @@ def _onLogMessage(self, line: str) -> None:
219220 # If the last field is an empty string, remove it
220221 del di [last_field [0 ]]
221222 else :
222- logging .warning (f"Failed to parse slog { line } with { d .format } " )
223+ logger .warning (f"Failed to parse slog { line } with { d .format } " )
223224 else :
224- logging .warning (f"Unknown Structured Log: { line } " )
225+ logger .warning (f"Unknown Structured Log: { line } " )
225226
226227 # Store our structured log record
227228 if di or self .include_raw :
@@ -256,18 +257,22 @@ def __init__(
256257
257258 if not dir_name :
258259 app_dir = root_dir ()
259- dir_name = f" { app_dir } / { datetime .now ().strftime ('%Y%m%d-%H%M%S' )} "
260- os . makedirs ( dir_name , exist_ok = True )
260+ dir_name = Path ( app_dir , datetime .now ().strftime ('%Y%m%d-%H%M%S' ))
261+ dir_name . mkdir ( exist_ok = True )
261262
262263 # Also make a 'latest' directory that always points to the most recent logs
264+ latest_dir = Path (app_dir , "latest" )
265+ latest_dir .unlink (missing_ok = True )
266+
263267 # symlink might fail on some platforms, if it does fail silently
264- if os .path .exists (f"{ app_dir } /latest" ):
265- os .unlink (f"{ app_dir } /latest" )
266- os .symlink (dir_name , f"{ app_dir } /latest" , target_is_directory = True )
268+ try :
269+ latest_dir .symlink_to (dir_name , target_is_directory = True )
270+ except OSError as e :
271+ pass
267272
268273 self .dir_name = dir_name
269274
270- logging .info (f"Writing slogs to { dir_name } " )
275+ logger .info (f"Writing slogs to { dir_name } " )
271276
272277 self .power_logger : Optional [PowerLogger ] = (
273278 None
@@ -286,7 +291,7 @@ def close(self) -> None:
286291 """Close the log set."""
287292
288293 if self .slog_logger :
289- logging .info (f"Closing slogs in { self .dir_name } " )
294+ logger .info (f"Closing slogs in { self .dir_name } " )
290295 atexit .unregister (
291296 self .atexit_handler
292297 ) # docs say it will silently ignore if not found
0 commit comments