diff --git a/library/libsds.h b/library/libsds.h index 886d3cb..3453a9d 100644 --- a/library/libsds.h +++ b/library/libsds.h @@ -55,6 +55,9 @@ int SdsMarkDependenciesMet(void* ctx, int SdsStartPeriodicTasks(void* ctx, SdsCallBack callback, void* userData); +// Configure log file path for nim-sds logging +int SdsSetLogFile(const char* logFilePath); + #ifdef __cplusplus diff --git a/library/libsds.nim b/library/libsds.nim index ea95844..f4e4776 100644 --- a/library/libsds.nim +++ b/library/libsds.nim @@ -5,7 +5,7 @@ when defined(linux): {.passl: "-Wl,-soname,libsds.so".} -import std/[typetraits, tables, atomics], chronos, chronicles +import std/[typetraits, tables, atomics], chronos, chronicles, os, times, strutils import ./sds_thread/sds_thread, ./alloc, @@ -104,23 +104,52 @@ proc libsdsNimMain() {.importc.} # To control when the library has been initialized var initialized: Atomic[bool] +proc getLogFilePath(): string = + # Check for environment variable first, fallback to default location + let envPath = getEnv("SDS_LOG_FILE") + if envPath.len > 0: + return envPath + + # Default to a location that status-go can manage + let defaultDir = getEnv("SDS_LOG_DIR", "/tmp") + return joinPath(defaultDir, "nim-sds.log") + +proc writeToLogFile(logLevel: LogLevel, msg: LogOutputStr) {.raises: [].} = + try: + let logFile = getLogFilePath() + let timestamp = now().format("yyyy-MM-dd HH:mm:ss.fff") + let logLine = "[$1] [$2] $3\n".format(timestamp, $logLevel, $msg) + + # Create directory if it doesn't exist + let logDir = parentDir(logFile) + if not dirExists(logDir): + createDir(logDir) + + # Append to log file + let file = open(logFile, fmAppend) + defer: file.close() + file.write(logLine) + except: + # Fallback to console if file writing fails + echo "[nim-sds-fallback] ", logLevel, ": ", msg + when defined(android): - # Redirect chronicles to Android System logs when compiles(defaultChroniclesStream.outputs[0].writer): defaultChroniclesStream.outputs[0].writer = proc( logLevel: LogLevel, msg: LogOutputStr ) {.raises: [].} = echo logLevel, msg else: - # For non-android, configure Chronicles with a null writer to suppress logs - # or redirect to a proper logging mechanism when compiles(defaultChroniclesStream.outputs[0].writer): defaultChroniclesStream.outputs[0].writer = proc( logLevel: LogLevel, msg: LogOutputStr ) {.raises: [].} = - # Only log ERROR and FATAL levels to reduce verbosity + # Critical logs (ERROR, FATAL) are written to console if logLevel >= LogLevel.ERROR: echo "[nim-sds] ", logLevel, ": ", msg + else: + # All other logs are written to a file + writeToLogFile(logLevel, msg) proc initializeLibrary() {.exported.} = if not initialized.exchange(true): @@ -332,5 +361,21 @@ proc SdsStartPeriodicTasks( userData, ) +proc SdsSetLogFile( + logFilePath: cstring +): cint {.dynlib, exportc.} = + ## Sets the log file path for nim-sds logging + ## This allows applications to configure where nim-sds logs should be written + initializeLibrary() + + if logFilePath == nil: + return RET_ERR + + try: + putEnv("SDS_LOG_FILE", $logFilePath) + return RET_OK + except: + return RET_ERR + ### End of exported procs ################################################################################