Skip to content

Commit 649bba5

Browse files
authored
feat: add a separate log for optimizations (fixes #523) (#525)
* feat: use separate python logger for optimizations This is a precursor that will allow us to log these more verbosely and to a different location than the rest of the taskgraph log messages. * fix: IndexSearch tests to pass for the right reasons Without this, we ended up passing due to entering the KeyError block in IndexSearch rather than the actual blocks we were supposed to. * test: add tests for optimization log messages * feat: always write optimization log information verbosely to a separate file This is a _little_ bit nasty because we don't have a great log configuration story in taskgraph to begin with, but it works. The `taskgraph_decision` parts are also untested because we don't have a good testing story there. I don't particularly want to shave those yaks as part of this...
1 parent 8ed01ce commit 649bba5

File tree

4 files changed

+63
-8
lines changed

4 files changed

+63
-8
lines changed

src/taskgraph/decision.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,28 @@ def taskgraph_decision(options, parameters=None):
7474
* generating a set of artifacts to memorialize the graph
7575
* calling TaskCluster APIs to create the graph
7676
"""
77+
level = logging.INFO
7778
if options.get("verbose"):
78-
logging.root.setLevel(logging.DEBUG)
79+
level = logging.DEBUG
80+
81+
logging.root.setLevel(level)
82+
# Handlers must have an explicit level set for them to properly filter
83+
# messages from child loggers (such as the optimization log a few lines
84+
# down).
85+
for h in logging.root.handlers:
86+
h.setLevel(level)
87+
88+
if not os.path.isdir(ARTIFACTS_DIR):
89+
os.mkdir(ARTIFACTS_DIR)
90+
91+
# optimizations are difficult to debug after the fact, so we always
92+
# log them at DEBUG level, and write the log as a separate artifact
93+
opt_log = logging.getLogger("optimization")
94+
opt_log.setLevel(logging.DEBUG)
95+
opt_handler = logging.FileHandler(ARTIFACTS_DIR / "optimizations.log", mode="w")
96+
if logging.root.handlers:
97+
opt_handler.setFormatter(logging.root.handlers[0].formatter)
98+
opt_log.addHandler(opt_handler)
7999

80100
parameters = parameters or (
81101
lambda graph_config: get_decision_parameters(graph_config, options)

src/taskgraph/optimize/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from taskgraph.util.python_path import import_sibling_modules
2525
from taskgraph.util.taskcluster import find_task_id_batched, status_task_batched
2626

27-
logger = logging.getLogger(__name__)
27+
logger = logging.getLogger("optimization")
2828
registry = {}
2929

3030

src/taskgraph/optimize/strategies.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from taskgraph.util.path import match as match_path
66
from taskgraph.util.taskcluster import find_task_id, status_task
77

8-
logger = logging.getLogger(__name__)
8+
logger = logging.getLogger("optimization")
99

1010

1111
@register_strategy("index-search")

test/test_optimize_strategies.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Any copyright is dedicated to the public domain.
22
# http://creativecommons.org/publicdomain/zero/1.0/
33

4+
import logging
45
import os
56
from datetime import datetime
67
from time import mktime
@@ -24,27 +25,37 @@ def params():
2425

2526

2627
@pytest.mark.parametrize(
27-
"state,expires,expected",
28+
"state,expires,expected,logs",
2829
(
2930
(
3031
"completed",
3132
"2021-06-06T14:53:16.937Z",
3233
False,
34+
(
35+
"not replacing {label} with {taskid} because it expires before {deadline}",
36+
),
3337
),
34-
("completed", "2021-06-08T14:53:16.937Z", "abc"),
38+
("completed", "2021-06-08T14:53:16.937Z", "abc", ()),
3539
(
3640
"exception",
3741
"2021-06-08T14:53:16.937Z",
3842
False,
43+
(
44+
"not replacing {label} with {taskid} because it is in failed or exception state",
45+
),
3946
),
4047
(
4148
"failed",
4249
"2021-06-08T14:53:16.937Z",
4350
False,
51+
(
52+
"not replacing {label} with {taskid} because it is in failed or exception state",
53+
),
4454
),
4555
),
4656
)
47-
def test_index_search(responses, params, state, expires, expected):
57+
def test_index_search(caplog, responses, params, state, expires, expected, logs):
58+
caplog.set_level(logging.DEBUG, "optimization")
4859
taskid = "abc"
4960
index_path = "foo.bar.latest"
5061

@@ -79,13 +90,27 @@ def test_index_search(responses, params, state, expires, expected):
7990
deadline = "2021-06-07T19:03:20.482Z"
8091
assert (
8192
opt.should_replace_task(
82-
{}, params, deadline, ([index_path], label_to_taskid, taskid_to_status)
93+
{"label": "task-label"},
94+
params,
95+
deadline,
96+
([index_path], label_to_taskid, taskid_to_status),
8397
)
8498
== expected
8599
)
86100
# test the non-batched variant as well
87101
assert opt.should_replace_task({}, params, deadline, [index_path]) == expected
88102

103+
if logs:
104+
log_records = [
105+
(
106+
"optimization",
107+
logging.DEBUG,
108+
m.format(label="task-label", taskid=taskid, deadline=deadline),
109+
)
110+
for m in logs
111+
]
112+
assert caplog.record_tuples == log_records
113+
89114

90115
@pytest.mark.parametrize(
91116
"params,file_patterns,should_optimize",
@@ -111,8 +136,18 @@ def test_index_search(responses, params, state, expires, expected):
111136
),
112137
),
113138
)
114-
def test_skip_unless_changed(params, file_patterns, should_optimize):
139+
def test_skip_unless_changed(caplog, params, file_patterns, should_optimize):
140+
caplog.set_level(logging.DEBUG, "optimization")
115141
task = make_task("task")
116142

117143
opt = SkipUnlessChanged()
118144
assert opt.should_remove_task(task, params, file_patterns) == should_optimize
145+
146+
if should_optimize:
147+
assert caplog.record_tuples == [
148+
(
149+
"optimization",
150+
logging.DEBUG,
151+
f'no files found matching a pattern in `skip-unless-changed` for "{task.label}"',
152+
),
153+
]

0 commit comments

Comments
 (0)