Skip to content

Commit cb048fe

Browse files
committed
core, py3: integrate logging library
1 parent f304d87 commit cb048fe

8 files changed

Lines changed: 129 additions & 168 deletions

File tree

docs/dev-guide/the-py3-helper.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,9 @@ checking.
309309
### log(message, level='info')
310310

311311
Log the message.
312-
The level must be one of LOG_ERROR, LOG_INFO or LOG_WARNING
312+
The level can be any valid logging level name (e.g. "error", info",
313+
"warning") or integer (e.g. `10` -> `logging.INFO``). Constants
314+
LOG_ERROR, LOG_WARNING, and LOG_INFO are also supported.
313315

314316
### notify_user(msg, level='info', rate_limit=5, title=None, icon=None)
315317

docs/dev-guide/writing-modules.md

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -817,42 +817,12 @@ Loadavg 1.41 1.61 1.82
817817
Modules are encouraged to use Python's standard
818818
[`logging`](https://docs.python.org/3/library/logging.config.html?highlight=logging#logging-config-dictschema)
819819
module for debugging. By default, logs will be written to
820-
[`syslog`](https://docs.python.org/3/library/logging.config.html?highlight=logging#logging-config-dictschema)
821-
with a minimum level of `INFO`.
820+
syslog with a minimum level of `INFO`.
822821

823-
Several existing modules will write to logs, with varying levels of details.
822+
Several existing modules can write to logs, with varying levels of details.
824823
Therefore, when debugging a specific module, it may be useful to show only the
825-
one you're interested in. This can be done by using the `--log-config` flag to
826-
pass a JSON file that configures logging. This file must be in the format
827-
specified in
828-
[`logging`'s configuration schema](https://docs.python.org/3/library/logging.config.html?highlight=logging#logging-config-dictschema).
829-
For example, to show only logs from your module in a `DEBUG` level, while
830-
keeping all others at `WARNING`, you can use:
831-
832-
```json
833-
{
834-
"version": 1,
835-
"handlers": {
836-
"file": {
837-
"class": "logging.handlers.RotatingFileHandler",
838-
"filename": "/tmp/py3status_log.log",
839-
"maxBytes": 2048,
840-
"formatter": "default"
841-
}
842-
},
843-
"formatters": {
844-
"default": {
845-
"validate": true,
846-
"format":"%(asctime)s %(levelname)s %(module)s %(message)s",
847-
"datefmt":"%Y-%m-%d %H:%M:%S"
848-
}
849-
},
850-
"loggers": {
851-
"root": {"handlers": ["file"], "level": "WARNING"},
852-
"<my_module>": {"level": "DEBUG"}
853-
}
854-
}
855-
```
824+
one you're interested in. Add a `logging` dict under the `py3status` section of
825+
your config following `logging`'s configuration schema.
856826

857827
## Publishing custom modules on PyPI
858828

py3status/argparsers.py

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ def _format_action_invocation(self, action):
8282
metavar="FILE",
8383
type=Path,
8484
)
85+
parser.add_argument(
86+
"-d",
87+
"--debug",
88+
action="store_true",
89+
help="enable debug logging in syslog or log file if --log-file option is passed",
90+
)
8591
parser.add_argument(
8692
"-i",
8793
"--include",
@@ -91,6 +97,15 @@ def _format_action_invocation(self, action):
9197
metavar="PATH",
9298
type=Path,
9399
)
100+
parser.add_argument(
101+
"-l",
102+
"--log-file",
103+
action="store",
104+
dest="log_file",
105+
help="enable logging to FILE (this option is not set by default)",
106+
metavar="FILE",
107+
type=Path,
108+
)
94109
parser.add_argument(
95110
"-s",
96111
"--standalone",
@@ -142,33 +157,6 @@ def _format_action_invocation(self, action):
142157
help="specify window manager i3 or sway",
143158
)
144159

145-
logging_args = parser.add_argument_group()
146-
logging_args.add_argument(
147-
"-d",
148-
"--debug",
149-
action="store_true",
150-
help="enable debug logging in syslog or log file if --log-file option is passed",
151-
)
152-
logging_args.add_argument(
153-
"-l",
154-
"--log-file",
155-
action="store",
156-
dest="log_file",
157-
help="enable logging to FILE (this option is not set by default)",
158-
metavar="FILE",
159-
type=Path,
160-
)
161-
logging_args.add_argument(
162-
"--log-config",
163-
action="store",
164-
dest="log_config",
165-
help="path to a file that fully configures the 'logging' module. This "
166-
"must contain a JSON dictionary in the format expected by "
167-
"logging.config.dictConfig.",
168-
metavar="FILE",
169-
type=Path,
170-
)
171-
172160
# parse options, command, etc
173161
options = parser.parse_args()
174162

py3status/command.py

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ class CommandRunner:
134134
"""
135135

136136
def __init__(self, py3_wrapper):
137-
self.debug = py3_wrapper.config["debug"]
138137
self.py3_wrapper = py3_wrapper
139138

140139
def find_modules(self, requested_names):
@@ -157,8 +156,7 @@ def find_modules(self, requested_names):
157156
if requested_name == name.split(" ")[0]:
158157
found_modules.add(module_name)
159158

160-
if self.debug:
161-
self.py3_wrapper.log(f"found {found_modules}")
159+
self.py3_wrapper.log(f"found {found_modules}", level="debug")
162160
return found_modules
163161

164162
def refresh(self, data):
@@ -170,8 +168,7 @@ def refresh(self, data):
170168
update_i3status = False
171169
for module_name in self.find_modules(modules):
172170
module = self.py3_wrapper.output_modules[module_name]
173-
if self.debug:
174-
self.py3_wrapper.log(f"refresh {module}")
171+
self.py3_wrapper.log(f"refresh {module}", level="debug")
175172
if module["type"] == "py3status":
176173
module["module"].force_update()
177174
else:
@@ -197,8 +194,7 @@ def click(self, data):
197194
for name, message in CLICK_OPTIONS:
198195
event[name] = data.get(name)
199196

200-
if self.debug:
201-
self.py3_wrapper.log(event)
197+
self.py3_wrapper.log(event, level="debug")
202198
# trigger the event
203199
self.py3_wrapper.events_thread.dispatch_event(event)
204200

@@ -207,8 +203,7 @@ def run_command(self, data):
207203
check the given command and send to the correct dispatcher
208204
"""
209205
command = data.get("command")
210-
if self.debug:
211-
self.py3_wrapper.log(f"Running remote command {command}")
206+
self.py3_wrapper.log(f"Running remote command {command}", level="debug")
212207
if command == "refresh":
213208
self.refresh(data)
214209
elif command == "refresh_all":
@@ -226,7 +221,6 @@ class CommandServer(threading.Thread):
226221
def __init__(self, py3_wrapper):
227222
threading.Thread.__init__(self)
228223

229-
self.debug = py3_wrapper.config["debug"]
230224
self.py3_wrapper = py3_wrapper
231225

232226
self.command_runner = CommandRunner(py3_wrapper)
@@ -244,8 +238,7 @@ def __init__(self, py3_wrapper):
244238
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
245239
sock.bind(server_address.as_posix())
246240

247-
if self.debug:
248-
self.py3_wrapper.log(f"Unix domain socket at {server_address}")
241+
self.py3_wrapper.log(f"Unix domain socket at {server_address}", level="debug")
249242

250243
# Listen for incoming connections
251244
sock.listen(1)
@@ -270,19 +263,16 @@ def run(self):
270263
try:
271264
data = None
272265
# Wait for a connection
273-
if self.debug:
274-
self.py3_wrapper.log("waiting for a connection")
266+
self.py3_wrapper.log("waiting for a connection", level="debug")
275267

276268
connection, client_address = self.sock.accept()
277269
try:
278-
if self.debug:
279-
self.py3_wrapper.log("connection from")
270+
self.py3_wrapper.log("connection from", level="debug")
280271

281272
data = connection.recv(MAX_SIZE)
282273
if data:
283274
data = json.loads(data.decode("utf-8"))
284-
if self.debug:
285-
self.py3_wrapper.log(f"received {data}")
275+
self.py3_wrapper.log(f"received {data}", level="debug")
286276
self.command_runner.run_command(data)
287277
finally:
288278
# Clean up the connection

py3status/constants.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,29 @@
1010
"output_format": None,
1111
}
1212

13+
LOGGING_CONFIG = {
14+
"version": 1,
15+
"disable_existing_loggers": False,
16+
"handlers": {
17+
"syslog": {
18+
"formatter": "default",
19+
"class": "logging.handlers.SysLogHandler",
20+
"address": "/dev/log",
21+
},
22+
},
23+
"formatters": {
24+
"default": {
25+
"format": "%(asctime)s %(levelname)s %(message)s",
26+
"datefmt": "%Y-%m-%d %H:%M:%S",
27+
}
28+
},
29+
"root": {"handlers": ["syslog"], "level": "INFO"},
30+
}
31+
32+
LOG_FILE_CONFIG = {
33+
"__log_file": {"formatter": "default", "class": "logging.FileHandler", "filename": None}
34+
}
35+
1336
MAX_NESTING_LEVELS = 4
1437

1538
TIME_FORMAT = "%Y-%m-%d %H:%M:%S"

0 commit comments

Comments
 (0)