Skip to content

Commit bcf3912

Browse files
committed
feat: update logger and improvements
1 parent 34f796f commit bcf3912

10 files changed

+135
-184
lines changed

config.yml

+21-28
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,34 @@
11
---
22
folders:
33
# Folder in which torrent files are download
4-
# Example downloding my_file.torrent in src_folder
5-
src: "" # Example: C:\Users\foo\Downloads
4+
# Example downloding my_movie.torrent in src_folder
5+
src: "c:\should_exists"
66
# Folder in which the actual files will be downloaded
77
# Example downloading my_move from ftp
8-
dest: '' # Example: 'E:\My_files
8+
dest: "c:\should_exists"
99

1010
qbittorrent:
1111
scheme: https
12-
domain: "" # Example 'qbittorrent.mydomain'
13-
user: "" # qbittorrent user
14-
password: "" # qbittorrent password
15-
port: 8080 # qbitorrent port
16-
clean_older_than: 7 # Clean torrents older than 7 days
12+
domain: "my_domain.com"
13+
user: "userA"
14+
password: "Apasswd"
15+
port: 10412
16+
clean_older_than: 7
1717

18-
# Either use ftp or sftp depending on your remote.
19-
# Only one of those 2 dict should be filles
20-
# If not, ftp will prevail
21-
ftp: {}
22-
#domain: "" # FTP hostname
23-
#port: 21 # FTP port
24-
#user: "" # FTP user
25-
#password: "" # FTP password
26-
#tls: true
27-
# Remote path on the FTP server
28-
#remote_path: "" # Example: "/torrents/qbittorrent/"
18+
ftp:
19+
domain: "my_domain.com"
20+
port: 21
21+
user: "userA"
22+
password: "Apasswd"
23+
tls: True,
24+
remote_path: "/torrents/qbittorrent/"
25+
#sftp:
26+
# domain: "my_domain.com"
27+
# port: 22
28+
# user: "userA"
29+
# password: "Apasswd"
30+
# remote_path: "torrents/qbittorrent/"
2931

30-
sftp:
31-
domain: "" # FTP hostname
32-
port: 22 # FTP port
33-
user: "" # FTP user
34-
password: "" # FTP password
35-
# Remote path on the FTP server
36-
remote_path: "" # Example: "/torrents/qbittorrent/"
37-
38-
# Windows notification
3932
toaster:
4033
duration: 5 # seconds
4134
title: "qbit-watcher"

qbit-watcher.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import os
22
import logging
3+
import logging.handlers
34
import sys
45

6+
from qbit_watcher import MainError
57
from qbit_watcher.main import main
68

79

@@ -33,7 +35,7 @@ def create_emergency_logger():
3335
try:
3436
main()
3537
# Catch all wanted worst case scenario
36-
except Exception as exn:
38+
except (MainError, Exception) as exn:
3739
logger = create_emergency_logger()
3840
logger.error(exn)
3941
sys.exit(1)

qbit_watcher/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
class MainError(Exception):
3+
""" Main Error
4+
"""

qbit_watcher/config.py

+17
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
"""
22
Read config file
33
"""
4+
from pathlib import Path
45
from qbit_watcher.logger import get_logger
56

67
import yaml
78

89
LOGGER = get_logger(__name__)
910

1011

12+
class ConfigError(Exception):
13+
""" Config Error
14+
"""
15+
16+
1117
class Config:
1218
def __init__(self, path):
1319
self.path = path
@@ -26,3 +32,14 @@ def load(self):
2632
LOGGER.error(fnfe)
2733
raise
2834
return conf
35+
36+
def validate(self):
37+
""" Validate config file
38+
"""
39+
conf = self.load()
40+
if not Path(conf['folders']['src']).exists():
41+
LOGGER.error("Source folder does not exists: %s", conf['folders']['src'])
42+
raise ConfigError
43+
if not Path(conf['folders']['dest']).exists():
44+
LOGGER.error("Dest folder does not exists: %s", conf['folders']['dest'])
45+
raise ConfigError

qbit_watcher/logger/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@
33
"""
44
from .logger import get_logger
55
from .exceptions import LogError
6-
from .json_formatter import QbitJsonFormatter

qbit_watcher/logger/json_formatter.py

-40
This file was deleted.

qbit_watcher/logger/logger.py

+51-85
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,17 @@
11
"""
22
Logging definition module
3-
4-
opts = {
5-
"debug": True,
6-
"stream_handler": True,
7-
"file_handler": {
8-
"path": "/tmp/foo",
9-
"name": "foo.log"
10-
},
11-
'json_formatter': {
12-
'enabled': True,
13-
'extra_fields': {
14-
'foo': 'foo',
15-
'bar': 'bar'
16-
},
17-
'timestamp_fmt': "%Y-%m-%dT%H:%M:%S.%fZ"
18-
}
19-
}
203
"""
214

225
import logging
6+
import logging.handlers
7+
import sys
238

24-
from os import makedirs
259
from pathlib import Path
2610

2711
from colorlog import ColoredFormatter
2812

13+
from qbit_watcher.settings import APP_LOGFILE
2914
from qbit_watcher.logger.exceptions import LogError
30-
from qbit_watcher.logger.json_formatter import QbitJsonFormatter
3115

3216

3317
class LastPartFilter(logging.Filter):
@@ -41,56 +25,39 @@ def filter(self, record):
4125
return True
4226

4327

44-
def get_logger(name, opts=None):
28+
def get_logger(name):
4529
"""
4630
Return a new named logger that will inherit the root logger
4731
"""
48-
__init_main_logger(opts)
32+
__init_main_logger()
4933
return logging.getLogger('qbit_watcher.' + name)
5034

5135

52-
def __init_main_logger(opts):
36+
def __init_main_logger():
5337
"""
5438
Init the main logger with its handlers when required
5539
"""
5640
logger = logging.getLogger('qbit_watcher')
5741
logger.setLevel(logging.INFO)
58-
if not opts:
59-
return logger
60-
__valid_opts(opts)
61-
62-
is_debug = opts['debug'] if "debug" in opts else False
63-
if is_debug:
64-
logger.setLevel(logging.DEBUG)
65-
66-
stream_handler = opts['stream_handler'] if "stream_handler" in opts else False
67-
if stream_handler:
68-
json_opts = None
69-
if 'json_formatter' in opts:
70-
if opts.get('json_formatter', {}).get('enabled') is True:
71-
json_opts = opts['json_formatter']
72-
73-
if logger.handlers:
74-
if not __has_handler(logger.handlers, logging.StreamHandler):
75-
handler = __create_stream_handler(json_opts=json_opts)
76-
logger.addHandler(handler)
77-
else:
78-
handler = __create_stream_handler(json_opts=json_opts)
79-
logger.addHandler(handler)
8042

81-
file_handler = bool("file_handler" in opts)
82-
if file_handler:
83-
if logger.handlers:
84-
if not __has_handler(logger.handlers, logging.FileHandler):
85-
handler = __create_json_file_handler(
86-
opts['file_handler']['path'],
87-
opts['file_handler']['name']
88-
)
43+
if sys.stdout.isatty() and sys.stderr.isatty():
44+
stream_handler = __create_stream_handler()
45+
logger.addHandler(stream_handler)
46+
47+
if logger.handlers:
48+
if not __has_handler(logger.handlers, logging.StreamHandler):
49+
if sys.stdout.isatty() and sys.stderr.isatty():
50+
handler = __create_stream_handler()
8951
logger.addHandler(handler)
90-
else:
91-
handler = __create_stream_handler(json_opts=json_opts)
52+
if not __has_handler(logger.handlers, logging.FileHandler):
53+
handler = __create_file_handler()
9254
logger.addHandler(handler)
93-
55+
else:
56+
if sys.stdout.isatty() and sys.stderr.isatty():
57+
handler = __create_stream_handler()
58+
logger.addHandler(handler)
59+
fhandler = __create_file_handler()
60+
logger.addHandler(fhandler)
9461
return logger
9562

9663

@@ -101,7 +68,7 @@ def __valid_opts(opts):
10168
if 'file_handler' in opts:
10269
if not isinstance(opts['file_handler'], dict):
10370
raise LogError("file_handler must be a dict {path: '/tmp', file: 'file.log'}")
104-
if not 'path' in opts['file_handler'] or not 'name' in opts['file_handler']:
71+
if 'path' not in opts['file_handler'] or 'name' not in opts['file_handler']:
10572
raise LogError("file_handler is set in options but 'name' or 'path' are missing")
10673

10774

@@ -116,42 +83,41 @@ def __has_handler(handlers, handler_type):
11683
return res
11784

11885

119-
def __create_stream_handler(json_opts=None):
86+
def __create_stream_handler():
12087
"""
12188
Create a stream logger with default formatter
12289
"""
12390
stream_handler = logging.StreamHandler()
124-
if json_opts:
125-
extra = json_opts['extra_fields'] if 'extra_fields' in json_opts else {}
126-
ts_fmt = json_opts['timestamp_fmt'] if 'timestamp_fmt' in json_opts else None
127-
formatter = QbitJsonFormatter(extra, ts_fmt)
128-
stream_handler.setFormatter(formatter)
129-
else:
130-
last_filter = LastPartFilter()
131-
stream_handler.addFilter(last_filter)
132-
fmt_name = " %(log_color)s%(name_last)-8s%(reset)s"
133-
fmt_levelname = "%(log_color)s%(levelname)s%(reset)s"
134-
fmt_message = "%(log_color)s%(message)s%(reset)s"
135-
136-
stream_log_fmt = " %s | %s | %s" % (fmt_name, fmt_levelname, fmt_message)
137-
stream_format = ColoredFormatter(stream_log_fmt)
138-
stream_handler.setFormatter(stream_format)
139-
91+
last_filter = LastPartFilter()
92+
stream_handler.addFilter(last_filter)
93+
fmt_name = " %(log_color)s%(name_last)-8s%(reset)s"
94+
fmt_levelname = "%(log_color)s%(levelname)s%(reset)s"
95+
fmt_message = "%(log_color)s%(message)s%(reset)s"
96+
97+
stream_log_fmt = " %s | %s | %s" % (fmt_name, fmt_levelname, fmt_message)
98+
stream_format = ColoredFormatter(stream_log_fmt)
99+
stream_handler.setFormatter(stream_format)
140100
return stream_handler
141101

142102

143-
def __create_json_file_handler(folder_path, fname):
144-
"""
145-
Create a json file logger
103+
def __create_file_handler():
104+
""" Add filehandler
146105
"""
147-
path = Path(folder_path)
148-
if not path.exists():
149-
makedirs(path, exist_ok=True)
150-
151-
file_handler = logging.FileHandler(path / fname)
152-
json_format = logging.Formatter(
153-
'{"timestamp": "%(asctime)s", "level": "%(levelname)s", "short_message": "%(message)s"}',
154-
datefmt="%s"
106+
last_filter = LastPartFilter()
107+
fmt_date = " %(asctime)s"
108+
fmt_name = "%(name_last)-8s"
109+
fmt_levelname = "%(levelname)s"
110+
fmt_message = "%(message)s"
111+
112+
file_log_fmt = "%s %s | %s | %s" % (fmt_date, fmt_name, fmt_levelname, fmt_message)
113+
if not APP_LOGFILE.parent.exists():
114+
Path.mkdir(APP_LOGFILE.parent, exist_ok=True)
115+
file_handler = logging.handlers.RotatingFileHandler(
116+
APP_LOGFILE,
117+
maxBytes=(1048576 * 5),
118+
backupCount=7
155119
)
156-
file_handler.setFormatter(json_format)
120+
121+
file_handler.addFilter(last_filter)
122+
file_handler.setFormatter(logging.Formatter(file_log_fmt))
157123
return file_handler

0 commit comments

Comments
 (0)