import std/[os, strutils] import ../src/namespaced_logging when not defined(multithreaded): {.error: "Compile this fixture with -d:multithreaded to exercise writer threads".} proc formatLine(msg: LogMessage): string {.gcsafe.} = msg.msg & "\n" proc formatOptionalLine(msg: LogMessage): string {.gcsafe.} = if msg.msg.len > 0: msg.msg & "\n" else: "" proc writeMessages(args: tuple[service: LogService, worker: int]) {.thread.} = let logger = args.service.threadLocalRef().getLogger("shutdown") for i in 0 ..< 2_500: logger.info("message " & $(args.worker * 2_500 + i)) proc main() = doAssert paramCount() == 2 let destination = paramStr(1) var service = initLogService() case destination of "file", "file-parallel", "file-empty": service.addAppender(initFileLogAppender(paramStr(2))) of "files": service.addAppender(initFileLogAppender(paramStr(2), namespace = "first")) service.addAppender(initFileLogAppender(paramStr(2) & ".second", namespace = "second")) of "console", "console-parallel", "console-empty": # Keep stdout open through the library's exit hook. Redirecting it to a # file also prevents a full parent/child pipe from blocking the writer. doAssert open(stdout, paramStr(2), fmWrite) if destination == "console-empty": service.addAppender(initConsoleLogAppender(formatter = formatOptionalLine)) else: service.addAppender(initConsoleLogAppender(formatter = formatLine)) of "stderr": doAssert open(stderr, paramStr(2), fmWrite) service.addAppender(initConsoleLogAppender(useStderr = true, formatter = formatLine)) else: raise newException(ValueError, "unknown writer destination") if destination.endsWith("-parallel"): var workers: array[4, Thread[tuple[service: LogService, worker: int]]] for i in 0 ..< workers.len: createThread(workers[i], writeMessages, (service, i)) joinThreads(workers) else: let local = service.threadLocalRef() if destination == "files": let first = local.getLogger("first") let second = local.getLogger("second") for i in 0 ..< 10_000: first.info("message " & $i) second.info("message " & $i) else: let logger = local.getLogger("shutdown") for i in 0 ..< 10_000: if destination.endsWith("-empty") and i mod 128 == 0: logger.info("") logger.info("message " & $i) # No sleep or explicit flush: normal exit must preserve accepted messages. main()