implemented threadlogging

This commit is contained in:
Paul Wilde 2024-08-27 21:16:31 +01:00
parent 54e4ca3c8b
commit 287495608a
14 changed files with 92 additions and 31 deletions

View file

@ -14,3 +14,4 @@ bin = @["norg"]
requires "nim >= 2.0.0" requires "nim >= 2.0.0"
requires "parsetoml >= 0.7.1" requires "parsetoml >= 0.7.1"
requires "argparse >= 4.0.1" requires "argparse >= 4.0.1"
requires "threadlogging"

View file

@ -1,6 +1,7 @@
import ../model/config_type import ../model/config_type
import ../model/command_type import ../model/command_type
import ../utils/actions import ../utils/actions
import ../model/log_type
import execute import execute
import prune import prune
@ -9,6 +10,7 @@ import mount
import extract import extract
proc initRepo(nc: NorgConfig, repo: Repository): int = proc initRepo(nc: NorgConfig, repo: Repository): int =
return runDiscard genCommand(cmd = "init", repo = repo.path, further_args = nc.args.further_args) return runDiscard genCommand(cmd = "init", repo = repo.path, further_args = nc.args.further_args)
@ -16,43 +18,43 @@ proc listArchives(nc: NorgConfig, repo: Repository): int =
return run genCommand(cmd = "list", repo = repo.path, further_args = nc.args.further_args) return run genCommand(cmd = "list", repo = repo.path, further_args = nc.args.further_args)
proc compactRepo(nc: NorgConfig, repo: Repository): int = proc compactRepo(nc: NorgConfig, repo: Repository): int =
echo "Not Yet Implemented." error "Not Yet Implemented."
discard discard
proc checkRepo(nc: NorgConfig, repo: Repository): int = proc checkRepo(nc: NorgConfig, repo: Repository): int =
echo "Not Yet Implemented." error "Not Yet Implemented."
discard discard
proc execute*(nc: NorgConfig, repo: Repository): int {.discardable.} = proc execute*(nc: NorgConfig, repo: Repository): int {.discardable.} =
case nc.args.command case nc.args.command
of INIT: of INIT:
echo "Initializing repo: ", repo.label info "Initializing repo: ", repo.label
discard initRepo(nc, repo) discard initRepo(nc, repo)
of CREATE: of CREATE:
run_actions(norg_config.actions.before_backup) run_actions(norg_config.actions.before_backup)
echo "Creating archive on ", repo.label info "Creating archive on ", repo.label
discard createBackup(nc, repo) discard createBackup(nc, repo)
run_actions(norg_config.actions.after_backup) run_actions(norg_config.actions.after_backup)
of LIST: of LIST:
echo "Listing Archives on ", repo.label info "Listing Archives on ", repo.label
discard listArchives(nc, repo) discard listArchives(nc, repo)
of MOUNT: of MOUNT:
echo "Mounting Archive from ", repo.label info "Mounting Archive from ", repo.label
discard mountArchive(nc, repo) discard mountArchive(nc, repo)
of UMOUNT: of UMOUNT:
discard unmountArchive(nc) discard unmountArchive(nc)
of EXTRACT: of EXTRACT:
run_actions(norg_config.actions.before_extract) run_actions(norg_config.actions.before_extract)
echo "Extracting archive from ", repo.label info "Extracting archive from ", repo.label
discard extractArchive(nc, repo) discard extractArchive(nc, repo)
run_actions(norg_config.actions.after_extract) run_actions(norg_config.actions.after_extract)
of PRUNE: of PRUNE:
run_actions(norg_config.actions.before_prune) run_actions(norg_config.actions.before_prune)
echo "Pruning repo: ", repo.label info "Pruning repo: ", repo.label
discard pruneRepo(nc, repo) discard pruneRepo(nc, repo)
run_actions(norg_config.actions.after_prune) run_actions(norg_config.actions.after_prune)
of DELETE: of DELETE:
echo "Deleting Archive ", nc.args.archive info "Deleting Archive ", nc.args.archive
discard deleteArchive(nc, repo) discard deleteArchive(nc, repo)
of COMPACT: of COMPACT:
run_actions(norg_config.actions.before_compact) run_actions(norg_config.actions.before_compact)

View file

@ -1,6 +1,7 @@
import ../model/config_type import ../model/config_type
import ../model/state_type import ../model/state_type
import ../notifier/notifier import ../notifier/notifier
import ../model/log_type
import execute import execute
import prune import prune
@ -19,6 +20,7 @@ proc createArchive(nc: NorgConfig, repo: Repository, archivename: string, retry:
let further_args = nc.args.further_args let further_args = nc.args.further_args
let res = run genCreateCommand(repo = archivename, sources = nc.source_directories, stats=nc.args.stats, further_args = further_args) let res = run genCreateCommand(repo = archivename, sources = nc.source_directories, stats=nc.args.stats, further_args = further_args)
if res != 0: if res != 0:
info "Failed to run Restic. Waiting 15 seconds and trying again"
sleep 15 * 1000 # 15 seconds sleep 15 * 1000 # 15 seconds
if retry == nc.retries: if retry == nc.retries:
return 1 return 1
@ -30,6 +32,7 @@ proc createBackup*(nc: NorgConfig, repo: Repository): int =
let start_time = now() let start_time = now()
notify(nc.notifiers, state=Running) notify(nc.notifiers, state=Running)
let archivename = repo.path & "::" & genArchiveName() let archivename = repo.path & "::" & genArchiveName()
debug "Creating Archive: ", archivename
let res = createArchive(nc, repo, archivename) let res = createArchive(nc, repo, archivename)
let end_time = now() let end_time = now()
let total = (end_time - start_time).inMilliSeconds() let total = (end_time - start_time).inMilliSeconds()

View file

@ -1,4 +1,6 @@
import ../model/config_type import ../model/config_type
import ../model/log_type
import execute import execute
import strformat import strformat
import os import os
@ -17,8 +19,8 @@ proc extractArchive*(nc: NorgConfig, repo: Repository): int =
setCurrentDir(nc.args.extract_destination) setCurrentDir(nc.args.extract_destination)
let dir = getCurrentDir() let dir = getCurrentDir()
if dir.isEmpty(): if dir.isEmpty():
echo "Restoring..." info "Restoring..."
let ok = run genCommand(cmd = "extract", repo = archive, further_args = further_args) let ok = run genCommand(cmd = "extract", repo = archive, further_args = further_args)
return ok return ok
else: else:
echo "Not restoring to non-empty destination\r\nPlease use the --destination flag or cd to an empty directory." error "Not restoring to non-empty destination\r\nPlease use the --destination flag or cd to an empty directory."

View file

@ -1,4 +1,6 @@
import ../model/config_type import ../model/config_type
import ../model/log_type
import execute import execute
import strformat import strformat
@ -7,13 +9,13 @@ proc mountArchive*(nc: NorgConfig, repo: Repository): int =
let further_args = nc.args.further_args let further_args = nc.args.further_args
let ok = runDiscard genCommand(cmd = "mount", repo = archive, further_args = further_args) let ok = runDiscard genCommand(cmd = "mount", repo = archive, further_args = further_args)
if ok == 0: if ok == 0:
echo fmt"Mounted {archive} at {further_args[0]}" info fmt"Mounted {archive} at {further_args[0]}"
else: else:
echo "Failed to mount ", archive error "Failed to mount ", archive
proc unmountArchive*(nc: NorgConfig): int = proc unmountArchive*(nc: NorgConfig): int =
let ok = runDiscard genCommand(cmd = "umount", repo = "", further_args = nc.args.further_args) let ok = runDiscard genCommand(cmd = "umount", repo = "", further_args = nc.args.further_args)
if ok == 0: if ok == 0:
echo "Unmounted ", nc.args.further_args[0] info "Unmounted ", nc.args.further_args[0]
else: else:
echo "Failed to unmount ", nc.args.further_args[0] error "Failed to unmount ", nc.args.further_args[0]

View file

@ -39,6 +39,13 @@ proc parseEncryption*(enc_conf: TomlValueRef) =
setEncryptionPassphraseFile(enc_conf{"encryption_passphrase_file"}.getStr("")) setEncryptionPassphraseFile(enc_conf{"encryption_passphrase_file"}.getStr(""))
setEncryptionPassCommand(enc_conf{"encryption_passcommand"}.getStr("")) setEncryptionPassCommand(enc_conf{"encryption_passcommand"}.getStr(""))
proc parseLogging(nc: var NorgConfig, log_conf: TomlValueRef) =
let ll = log_conf{"log_level"}.getStr()
if ll != "":
nc.log_info.level = ll.toLogLevel()
nc.log_info.file = log_conf{"log_file"}.getStr()
discard
proc addConfigBinaries*(current: var Binaries, bin_conf: TomlValueRef) = proc addConfigBinaries*(current: var Binaries, bin_conf: TomlValueRef) =
let let
borg = bin_conf{"borg_bin"}.getStr() borg = bin_conf{"borg_bin"}.getStr()
@ -61,6 +68,7 @@ proc parseConfigFile*(file: string): NorgConfig =
norg_config.maintenance = parseMaintenance(in_conf{"maintenance"}) norg_config.maintenance = parseMaintenance(in_conf{"maintenance"})
norg_config.bins.addConfigBinaries(in_conf{"binaries"}) norg_config.bins.addConfigBinaries(in_conf{"binaries"})
norg_config.bins.setBinaryLocations() norg_config.bins.setBinaryLocations()
norg_config.parseLogging(in_conf{"logging"})
return norg_config return norg_config

View file

@ -4,6 +4,7 @@ import actions_type
import maintenance_type import maintenance_type
import binary_type import binary_type
import args_type import args_type
import log_type
export repository_type export repository_type
export notifier_types export notifier_types
@ -11,8 +12,10 @@ export actions_type
export maintenance_type export maintenance_type
export binary_type export binary_type
export args_type export args_type
export log_type
import ../utils/version import ../utils/version
const VERSION*: string = getVersion() const VERSION*: string = getVersion()
type type
@ -26,11 +29,13 @@ type
actions*: Actions actions*: Actions
args*: NorgArgs args*: NorgArgs
bins*: Binaries bins*: Binaries
log_info*: LogInfo
proc newNorgConfig*(): NorgConfig = proc newNorgConfig*(): NorgConfig =
var nc = NorgConfig() var nc = NorgConfig()
nc.maintenance = newMaintenance() nc.maintenance = newMaintenance()
nc.bins = newBinaries() nc.bins = newBinaries()
nc.log_info = newLogInfo()
return nc return nc
var norg_config*: NorgConfig = newNorgConfig() var norg_config*: NorgConfig = newNorgConfig()

22
norg/model/log_type.nim Normal file
View file

@ -0,0 +1,22 @@
import logging
import threadlogging
export logging.newConsoleLogger
export logging.newFileLogger
export threadlogging
type
LogInfo* = object
level*: Level
file*: string
proc newLogInfo*(): LogInfo =
var log = LogInfo()
log.level = lvlInfo
log.file = ""
return log
proc toLogLevel*(s: string): Level =
for l in Level.items:
if s == $l: return l
return lvlInfo

View file

@ -4,11 +4,16 @@ import borg/borg
import restic/restic import restic/restic
import model/encryption_type import model/encryption_type
import utils/actions import utils/actions
import model/log_type
import os
proc showVersion() = proc showVersion() =
echo "Norg Version: ", VERSION echo "Norg Version: ", VERSION
quit(0) quit(0)
proc startLogger(nc: NorgConfig) =
initLogThread("[$levelname] ", nc.log_info.level)
proc start() = proc start() =
parseArgs() parseArgs()
norg_config.args = norg_args norg_config.args = norg_args
@ -16,6 +21,7 @@ proc start() =
showVersion() showVersion()
elif norg_args.config_file != "": elif norg_args.config_file != "":
norg_config = parseConfigFile(norg_args.config_file) norg_config = parseConfigFile(norg_args.config_file)
startLogger(norg_config)
if norg_config.source_directories.len > 0 and norg_config.repositories.len > 0: if norg_config.source_directories.len > 0 and norg_config.repositories.len > 0:
run_actions(norg_config.actions.before_everything) run_actions(norg_config.actions.before_everything)
for repo in norg_config.repositories: for repo in norg_config.repositories:
@ -33,3 +39,5 @@ proc start() =
when isMainModule: when isMainModule:
start() start()
# sleep for a bit to let logs finish
sleep 5

View file

@ -1,5 +1,6 @@
import ../model/state_type import ../model/state_type
import ../model/notifier_type import ../model/notifier_type
import ../model/log_type
import strformat import strformat
import ../utils/httprequest import ../utils/httprequest
@ -19,7 +20,7 @@ proc send_notify*(uk: UptimeKuma, state: State, runtime: int = 0, msg: string =
message &= fmt":{msg}" message &= fmt":{msg}"
let url = fmt"{uk.base_url}?status={status}&msg={message}&ping={runtime}" let url = fmt"{uk.base_url}?status={status}&msg={message}&ping={runtime}"
echo "Sending notification to " & url debug "Sending notification to " & url
let res = sendHttpRequest(HttpGet, url) let res = sendHttpRequest(HttpGet, url)
if res.status == $Http200: if res.status == $Http200:
return 0 return 0

View file

@ -2,11 +2,13 @@ import ../model/config_type
import execute import execute
import strformat import strformat
import threadlogging
proc mountSnapshot*(nc: NorgConfig, repo: Repository): int = proc mountSnapshot*(nc: NorgConfig, repo: Repository): int =
#let further_args = nc.args.further_args[1..^1] #let further_args = nc.args.further_args[1..^1]
let further_args = nc.args.further_args let further_args = nc.args.further_args
let ok = runDiscard genCommand(cmd = "mount", repo = repo.path, further_args = further_args) let ok = runDiscard genCommand(cmd = "mount", repo = repo.path, further_args = further_args)
if ok == 0: if ok == 0:
echo fmt"Mounted {repo.path} at {further_args[0]}" info fmt"Mounted {repo.path} at {further_args[0]}"
else: else:
echo "Failed to mount ", repo.path error "Failed to mount ", repo.path

View file

@ -8,34 +8,36 @@ import mount
import restore import restore
import prune import prune
import threadlogging
proc execute*(nc: NorgConfig, repo: Repository) = proc execute*(nc: NorgConfig, repo: Repository) =
case nc.args.command case nc.args.command
of INIT: of INIT:
echo "Initializing repo: ", repo.label info "Initializing repo: ", repo.label
discard initRepo(nc, repo) discard initRepo(nc, repo)
of CREATE: of CREATE:
run_actions(norg_config.actions.before_backup) run_actions(norg_config.actions.before_backup)
echo "Backing up to ", repo.label info "Backing up to ", repo.label
discard createBackup(nc, repo) discard createBackup(nc, repo)
run_actions(norg_config.actions.after_backup) run_actions(norg_config.actions.after_backup)
of LIST: of LIST:
echo "Listing Snapshots at ", repo.label info "Listing Snapshots at ", repo.label
discard listSnapshots(nc, repo) discard listSnapshots(nc, repo)
of MOUNT: of MOUNT:
echo "Mounting Snapshot from ", repo.label info "Mounting Snapshot from ", repo.label
discard mountSnapshot(nc, repo) discard mountSnapshot(nc, repo)
of EXTRACT: of EXTRACT:
run_actions(norg_config.actions.before_extract) run_actions(norg_config.actions.before_extract)
echo "Restoring snapshot from ", repo.label info "Restoring snapshot from ", repo.label
discard restoreSnapshot(nc, repo) discard restoreSnapshot(nc, repo)
run_actions(norg_config.actions.after_extract) run_actions(norg_config.actions.after_extract)
of PRUNE: of PRUNE:
run_actions(norg_config.actions.before_prune) run_actions(norg_config.actions.before_prune)
echo "Pruning repo: ", repo.label info "Pruning repo: ", repo.label
discard pruneRepo(nc, repo) discard pruneRepo(nc, repo)
run_actions(norg_config.actions.after_prune) run_actions(norg_config.actions.after_prune)
of DELETE: of DELETE:
echo "Forgetting snapshot: ", nc.args.archive info "Forgetting snapshot: ", nc.args.archive
discard forgetSnapshot(nc, repo) discard forgetSnapshot(nc, repo)
else: else:
discard discard

View file

@ -3,6 +3,8 @@ import execute
import strformat import strformat
import os import os
import threadlogging
proc isEmpty(dir: string): bool = proc isEmpty(dir: string): bool =
var count = 0 var count = 0
for idx, f in walkDir(dir): return false for idx, f in walkDir(dir): return false
@ -17,8 +19,8 @@ proc restoreSnapshot*(nc: NorgConfig, repo: Repository): int =
setCurrentDir(nc.args.extract_destination) setCurrentDir(nc.args.extract_destination)
let dir = getCurrentDir() let dir = getCurrentDir()
if dir.isEmpty(): if dir.isEmpty():
echo "Restoring..." info "Restoring..."
let ok = run genRestoreCommand(repo_snapshot = repo_snapshot, destination = nc.args.extract_destination, further_args = further_args) let ok = run genRestoreCommand(repo_snapshot = repo_snapshot, destination = nc.args.extract_destination, further_args = further_args)
return ok return ok
else: else:
echo "Not restoring to non-empty destination\r\nPlease use the --destination flag or cd to an empty directory." error "Not restoring to non-empty destination\r\nPlease use the --destination flag or cd to an empty directory."

View file

@ -1,21 +1,22 @@
import strformat import strformat
import osproc import osproc
import threadlogging
proc run*(cmd: string): int = proc run*(cmd: string): int =
echo fmt"Trying to run : {cmd}" debug fmt"Trying to run : {cmd}"
try: try:
let res = execCmd(cmd) let res = execCmd(cmd)
return res return res
except: except:
echo getCurrentExceptionMsg() error getCurrentExceptionMsg()
return 1 return 1
proc runDiscard*(cmd: string): int = proc runDiscard*(cmd: string): int =
echo fmt"Trying to run : {cmd}" debug fmt"Trying to run : {cmd}"
try: try:
let res = execCmd(cmd) let res = execCmd(cmd)
return res return res
except: except:
echo getCurrentExceptionMsg() error getCurrentExceptionMsg()
return 1 return 1