Merge branch 'master' into consumers-refactoring

This commit is contained in:
mdoglio 2013-06-12 14:07:31 +01:00
Родитель 4deb7863a8 75f29843f4
Коммит efbfb70f1b
18 изменённых файлов: 1600 добавлений и 0 удалений

93
bin/download_logs.py Normal file
Просмотреть файл

@ -0,0 +1,93 @@
#!/usr/bin/env python
import sys
import urllib2
def download_logs(filename):
"""
Download all ``log_references`` in job objects within a file.
Logs downloaded will be put in the working directory.
USAGE: download_logs <filename>
``filename`` - A txt file with JSON Job objects
Job objects should look like this:
{
"sources": [
{
"commit_timestamp": 1370459461,
"push_timestamp": 1370459461,
"comments": "Backed out changeset fe9dcdf48551 (bug 879374) for mochitest-3 crashes.",
"repository": "mozilla-inbound",
"revision": "a54df4462572"
}
],
"job": {
"submit_timestamp": 1370459521,
"option_collection": {
"opt": true
},
"who": "sendchange-unittest",
"artifact": {},
"machine_platform": {
"platform": "2.2",
"os_name": "android",
"architecture": "ARMv7",
"vm": false
},
"reason": "scheduler",
"result": 0,
"job_guid": "808f4f1372895eda5ecd65f2371ebe67a2a9af9b",
"end_timestamp": "1370461182",
"build_platform": {
"platform": "2.2",
"os_name": "android",
"architecture": "ARMv7",
"vm": false
},
"start_timestamp": 1370484722,
"name": "xpcshell",
"log_references": [
{
"url": "http://ftp.mozilla.org/pub/mozilla.org/mobile/tinderbox-builds/mozilla-inbound-android/1370454517/mozilla-inbound_tegra_android_test-xpcshell-bm22-tests1-tegra-build690.txt.gz",
"name": "unittest"
}
],
"machine": "tegra-132",
"state": "TODO",
"product_name": "mobile"
},
"revision_hash": "0686a4d3fa477cb0415c9ca590177e4b03919b64"
}
"""
lognames = []
job_data = open(filename).read()
for job in job_data:
logrefs = job["job"]["log_references"]
for log in logrefs:
lognames.append(log["name"])
url = log["url"]
try:
handle = urllib2.urlopen(url)
with open(url.rsplit("/", 1)[1], "wb") as out:
while True:
data = handle.read(1024)
if len(data) == 0:
break
out.write(data)
except urllib2.HTTPError:
pass
assert set(lognames) == ""
if __name__ == "__main__":
if len(sys.argv) < 2:
print ("USAGE: download_logs <filename>\n"
"Where <filename> is a txt file with JSON Job objects")
else:
download_logs(sys.argv[1])

Просмотреть файл

Просмотреть файл

@ -0,0 +1,49 @@
import pytest
from treeherder.log_parser.logparsecollection import LogParseCollection
from treeherder.log_parser.logviewparser import BuildbotLogViewParser
def test_parsers_as_list():
"""test that passing in a list of parsers works"""
parser = BuildbotLogViewParser("mochitest")
lpc = LogParseCollection(
"foo-url",
"mochitest",
parsers=[parser]
)
assert lpc.parsers == [parser]
def test_parsers_as_single_still_list():
"""test that passing in a single parser becomes a list"""
parser = BuildbotLogViewParser("mochitest")
lpc = LogParseCollection(
"foo-url",
"mochitest",
parsers=parser
)
assert lpc.parsers == [parser]
def test_default_parsers():
"""test that passing in a job_type instead of a parser"""
parser = BuildbotLogViewParser("mochitest")
lpc = LogParseCollection(
"foo-url",
"mochitest",
)
assert isinstance(lpc.parsers, list)
assert len(lpc.parsers) == 1
assert lpc.parsers[0].name == parser.name
def test_bad_values():
"""test that passing in a single parser becomes a list"""
with pytest.raises(ValueError) as e:
lpc = LogParseCollection(
"foo-url",
)
assert e.exconly() == "ValueError: Must provide either ``job_type`` or ``parsers``"

Просмотреть файл

@ -0,0 +1,75 @@
import json
from treeherder.log_parser.logparsecollection import LogParseCollection
from treeherder.log_parser.logviewparser import BuildbotLogViewParser
from tests import test_utils
from ..sampledata import SampleData
def do_test(job_type, log):
"""
Test a single log.
``job_type`` - Something like "mochitest", "crashtest" or "reftest"
``log`` - the url prefix of the log to test. Also searches for the
result file with the same prefix.
"""
url = "file://{0}".format(
SampleData().get_log_path("{0}.txt.gz".format(log)))
exp = test_utils.load_exp("{0}.logview.json".format(log))
jap = BuildbotLogViewParser(job_type, url)
lpc = LogParseCollection(url, parsers=jap)
lpc.parse()
act = lpc.artifacts[jap.name]
assert act == exp, test_utils.diff_dict(exp, act)
# Use this assert when creating new tests and you want to get the actual
# returned artifact:
# assert act == exp, json.dumps(act, indent=4)
def test_crashtest_passing(jm, initial_data):
"""Process a job with a single log reference."""
do_test(
"crashtest",
"mozilla-central_fedora-b2g_test-crashtest-1-bm54-tests1-linux-build50"
)
def test_mochitest_pass(jm, initial_data):
"""Process a job with a single log reference."""
do_test(
"mochitest",
"mozilla-central_mountainlion_test-mochitest-2-bm77-tests1-macosx-build141"
)
def test_mochitest_fail(jm, initial_data):
"""Process a job with a single log reference."""
do_test(
"mochitest",
"mozilla-esr17_xp_test_pgo-mochitest-browser-chrome-bm74-tests1-windows-build12"
)
def test_mochitest_process_crash(jm, initial_data):
"""Test a mochitest log that has PROCESS-CRASH """
do_test(
"mochitest",
"mozilla-inbound_ubuntu64_vm-debug_test-mochitest-other-bm53-tests1-linux-build122"
)
def test_jetpack_fail(jm, initial_data):
"""Process a job with a single log reference."""
do_test(
"jetpack",
"ux_ubuntu32_vm_test-jetpack-bm67-tests1-linux-build16"
)

Просмотреть файл

@ -0,0 +1,146 @@
{
"url": "file:///home/vagrant/treeherder-service/tests/sample_data/logs/mozilla-central_fedora-b2g_test-crashtest-1-bm54-tests1-linux-build50.txt.gz",
"header": {
"slave": "talos-r3-fed-088",
"buildid": "20130605115738",
"builder": "mozilla-central_fedora-b2g_test-crashtest-1",
"results": "success (0)",
"starttime": "1370461197.84",
"builduid": "0356dff218744cf4b6ca832f12ec183f",
"revision": "1658dc513572"
},
"steps": [
{
"errors": [],
"name": "set props: master",
"started": "2013-06-05 12:39:57.838527",
"started_linenumber": 8,
"finished_linenumber": 10,
"finished": "2013-06-05 12:39:57.839226",
"error_count": 0,
"duration": 0.000699,
"order": 0
},
{
"errors": [],
"name": "set props: basedir",
"started": "2013-06-05 12:39:57.839702",
"started_linenumber": 12,
"finished_linenumber": 42,
"finished": "2013-06-05 12:39:58.346114",
"error_count": 0,
"duration": 0.506412,
"order": 1
},
{
"errors": [],
"name": "downloading to buildprops.json",
"started": "2013-06-05 12:39:58.346573",
"started_linenumber": 44,
"finished_linenumber": 45,
"finished": "2013-06-05 12:39:58.614586",
"error_count": 0,
"duration": 0.268013,
"order": 2
},
{
"errors": [],
"name": "'rm -rf ...'",
"started": "2013-06-05 12:39:58.615003",
"started_linenumber": 47,
"finished_linenumber": 75,
"finished": "2013-06-05 12:39:58.723069",
"error_count": 0,
"duration": 0.108066,
"order": 3
},
{
"errors": [],
"name": "'rm -rf ...'",
"started": "2013-06-05 12:39:58.723521",
"started_linenumber": 77,
"finished_linenumber": 105,
"finished": "2013-06-05 12:39:58.831972",
"error_count": 0,
"duration": 0.108451,
"order": 4
},
{
"errors": [],
"name": "'hg clone ...'",
"started": "2013-06-05 12:39:58.832419",
"started_linenumber": 107,
"finished_linenumber": 142,
"finished": "2013-06-05 12:40:01.114413",
"error_count": 0,
"duration": 2.281994,
"order": 5
},
{
"errors": [],
"name": "'hg update ...'",
"started": "2013-06-05 12:40:01.114870",
"started_linenumber": 144,
"finished_linenumber": 173,
"finished": "2013-06-05 12:40:01.335999",
"error_count": 0,
"duration": 0.221129,
"order": 6
},
{
"errors": [],
"name": "set props: script_repo_revision",
"started": "2013-06-05 12:40:01.336478",
"started_linenumber": 175,
"finished_linenumber": 205,
"finished": "2013-06-05 12:40:01.520234",
"error_count": 0,
"duration": 0.183756,
"order": 7
},
{
"errors": [],
"name": "tinderboxprint_script_revlink",
"started": "2013-06-05 12:40:01.520734",
"started_linenumber": 207,
"finished_linenumber": 209,
"finished": "2013-06-05 12:40:01.521320",
"error_count": 0,
"duration": 0.000586,
"order": 8
},
{
"errors": [],
"name": "'/tools/buildbot/bin/python scripts/scripts/b2g_emulator_unittest.py ...'",
"started": "2013-06-05 12:40:01.521797",
"started_linenumber": 211,
"finished_linenumber": 3369,
"finished": "2013-06-05 12:57:55.646752",
"error_count": 0,
"duration": 1074.124955,
"order": 9
},
{
"errors": [],
"name": "set props: build_url",
"started": "2013-06-05 12:57:55.659998",
"started_linenumber": 3371,
"finished_linenumber": 3401,
"finished": "2013-06-05 12:57:55.793402",
"error_count": 0,
"duration": 0.133404,
"order": 10
},
{
"errors": [],
"name": "reboot slave lost",
"started": "2013-06-05 12:57:55.793914",
"started_linenumber": 3403,
"finished_linenumber": 3433,
"finished": "2013-06-05 12:58:55.994641",
"error_count": 0,
"duration": 60.200727,
"order": 11
}
]
}

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,146 @@
{
"url": "file:///home/vagrant/treeherder-service/tests/sample_data/logs/mozilla-central_mountainlion_test-mochitest-2-bm77-tests1-macosx-build141.txt.gz",
"header": {
"slave": "talos-mtnlion-r5-080",
"buildid": "20130605115738",
"builder": "mozilla-central_mountainlion_test-mochitest-2",
"results": "success (0)",
"starttime": "1370462102.79",
"builduid": "48d01a5d6b0c43d593f8d9e9f60857be",
"revision": "1658dc513572"
},
"steps": [
{
"errors": [],
"name": "set props: master",
"started": "2013-06-05 12:55:02.793687",
"started_linenumber": 8,
"finished_linenumber": 10,
"finished": "2013-06-05 12:55:02.794485",
"error_count": 0,
"duration": 0.000798,
"order": 0
},
{
"errors": [],
"name": "set props: basedir",
"started": "2013-06-05 12:55:02.794985",
"started_linenumber": 12,
"finished_linenumber": 36,
"finished": "2013-06-05 12:55:03.579905",
"error_count": 0,
"duration": 0.78492,
"order": 1
},
{
"errors": [],
"name": "downloading to buildprops.json",
"started": "2013-06-05 12:55:03.580420",
"started_linenumber": 38,
"finished_linenumber": 39,
"finished": "2013-06-05 12:55:05.429410",
"error_count": 0,
"duration": 1.84899,
"order": 2
},
{
"errors": [],
"name": "'rm -rf ...'",
"started": "2013-06-05 12:55:05.429870",
"started_linenumber": 41,
"finished_linenumber": 63,
"finished": "2013-06-05 12:55:05.711713",
"error_count": 0,
"duration": 0.281843,
"order": 3
},
{
"errors": [],
"name": "'rm -rf ...'",
"started": "2013-06-05 12:55:05.712188",
"started_linenumber": 65,
"finished_linenumber": 87,
"finished": "2013-06-05 12:55:05.951055",
"error_count": 0,
"duration": 0.238867,
"order": 4
},
{
"errors": [],
"name": "'hg clone ...'",
"started": "2013-06-05 12:55:05.951563",
"started_linenumber": 89,
"finished_linenumber": 118,
"finished": "2013-06-05 12:55:08.587665",
"error_count": 0,
"duration": 2.636102,
"order": 5
},
{
"errors": [],
"name": "'hg update ...'",
"started": "2013-06-05 12:55:08.588162",
"started_linenumber": 120,
"finished_linenumber": 143,
"finished": "2013-06-05 12:55:09.070938",
"error_count": 0,
"duration": 0.482776,
"order": 6
},
{
"errors": [],
"name": "set props: script_repo_revision",
"started": "2013-06-05 12:55:09.071436",
"started_linenumber": 145,
"finished_linenumber": 169,
"finished": "2013-06-05 12:55:09.553968",
"error_count": 0,
"duration": 0.482532,
"order": 7
},
{
"errors": [],
"name": "tinderboxprint_script_revlink",
"started": "2013-06-05 12:55:09.554462",
"started_linenumber": 171,
"finished_linenumber": 173,
"finished": "2013-06-05 12:55:09.555053",
"error_count": 0,
"duration": 0.000591,
"order": 8
},
{
"errors": [],
"name": "'/tools/buildbot/bin/python scripts/scripts/desktop_unittest.py ...'",
"started": "2013-06-05 12:55:09.555542",
"started_linenumber": 175,
"finished_linenumber": 11552,
"finished": "2013-06-05 13:02:38.681825",
"error_count": 0,
"duration": 449.126283,
"order": 9
},
{
"errors": [],
"name": "set props: build_url",
"started": "2013-06-05 13:02:38.687346",
"started_linenumber": 11554,
"finished_linenumber": 11578,
"finished": "2013-06-05 13:02:38.876303",
"error_count": 0,
"duration": 0.188957,
"order": 10
},
{
"errors": [],
"name": "reboot slave lost",
"started": "2013-06-05 13:02:38.876850",
"started_linenumber": 11580,
"finished_linenumber": 11609,
"finished": "2013-06-05 13:03:00.115654",
"error_count": 0,
"duration": 21.238804,
"order": 11
}
]
}

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,276 @@
{
"url": "file:///home/vagrant/treeherder-service/tests/sample_data/logs/mozilla-esr17_xp_test_pgo-mochitest-browser-chrome-bm74-tests1-windows-build12.txt.gz",
"header": {
"slave": "talos-r3-xp-085",
"buildid": "20130605090546",
"builder": "mozilla-esr17_xp_test_pgo-mochitest-browser-chrome",
"results": "warnings (1)",
"starttime": "1370461908.77",
"builduid": "11d37c0c73ec4f4aa16b29cbe6481a9f",
"revision": "e2eecb449eeb"
},
"steps": [
{
"errors": [],
"name": "set props: revision",
"started": "2013-06-05 12:51:48.767751",
"started_linenumber": 8,
"finished_linenumber": 10,
"finished": "2013-06-05 12:51:48.768393",
"error_count": 0,
"duration": 0.000642,
"order": 0
},
{
"errors": [],
"name": "set props: who",
"started": "2013-06-05 12:51:48.768881",
"started_linenumber": 12,
"finished_linenumber": 14,
"finished": "2013-06-05 12:51:48.769473",
"error_count": 0,
"duration": 0.000592,
"order": 1
},
{
"errors": [],
"name": "set props: basedir",
"started": "2013-06-05 12:51:48.769970",
"started_linenumber": 16,
"finished_linenumber": 62,
"finished": "2013-06-05 12:51:50.898723",
"error_count": 0,
"duration": 2.128753,
"order": 2
},
{
"errors": [],
"name": "set props: hashType",
"started": "2013-06-05 12:51:50.899244",
"started_linenumber": 64,
"finished_linenumber": 110,
"finished": "2013-06-05 12:51:51.050525",
"error_count": 0,
"duration": 0.151281,
"order": 3
},
{
"errors": [],
"name": "set props: builddir",
"started": "2013-06-05 12:51:51.051012",
"started_linenumber": 112,
"finished_linenumber": 158,
"finished": "2013-06-05 12:51:51.285053",
"error_count": 0,
"duration": 0.234041,
"order": 4
},
{
"errors": [],
"name": "clobber build tools",
"started": "2013-06-05 12:51:51.285559",
"started_linenumber": 160,
"finished_linenumber": 204,
"finished": "2013-06-05 12:52:04.344452",
"error_count": 0,
"duration": 13.058893,
"order": 5
},
{
"errors": [],
"name": "clone build tools",
"started": "2013-06-05 12:52:04.344949",
"started_linenumber": 206,
"finished_linenumber": 257,
"finished": "2013-06-05 12:52:27.906228",
"error_count": 0,
"duration": 23.561279,
"order": 6
},
{
"errors": [],
"name": "set props: toolsdir",
"started": "2013-06-05 12:52:27.906738",
"started_linenumber": 259,
"finished_linenumber": 305,
"finished": "2013-06-05 12:52:28.096555",
"error_count": 0,
"duration": 0.189817,
"order": 7
},
{
"errors": [],
"name": "set props: purge_actual purge_target",
"started": "2013-06-05 12:52:28.097052",
"started_linenumber": 307,
"finished_linenumber": 373,
"finished": "2013-06-05 12:52:28.689661",
"error_count": 0,
"duration": 0.592609,
"order": 8
},
{
"errors": [],
"name": "'rm -rf ...'",
"started": "2013-06-05 12:52:28.690156",
"started_linenumber": 375,
"finished_linenumber": 419,
"finished": "2013-06-05 12:53:56.014058",
"error_count": 0,
"duration": 87.323902,
"order": 9
},
{
"errors": [],
"name": "download",
"started": "2013-06-05 12:53:56.014651",
"started_linenumber": 421,
"finished_linenumber": 484,
"finished": "2013-06-05 12:54:02.983974",
"error_count": 0,
"duration": 6.969323,
"order": 10
},
{
"errors": [],
"name": "unpack",
"started": "2013-06-05 12:54:02.984470",
"started_linenumber": 486,
"finished_linenumber": 530,
"finished": "2013-06-05 12:54:06.858348",
"error_count": 0,
"duration": 3.873878,
"order": 11
},
{
"errors": [],
"name": "set props: exepath",
"started": "2013-06-05 12:54:06.858854",
"started_linenumber": 532,
"finished_linenumber": 534,
"finished": "2013-06-05 12:54:06.859521",
"error_count": 0,
"duration": 0.000667,
"order": 12
},
{
"errors": [],
"name": "set props: exedir",
"started": "2013-06-05 12:54:06.859991",
"started_linenumber": 536,
"finished_linenumber": 538,
"finished": "2013-06-05 12:54:06.860629",
"error_count": 0,
"duration": 0.000638,
"order": 13
},
{
"errors": [],
"name": "set props: toolsdir",
"started": "2013-06-05 12:54:06.861112",
"started_linenumber": 540,
"finished_linenumber": 586,
"finished": "2013-06-05 12:54:07.047366",
"error_count": 0,
"duration": 0.186254,
"order": 14
},
{
"errors": [],
"name": "set props: symbols_url",
"started": "2013-06-05 12:54:07.047887",
"started_linenumber": 588,
"finished_linenumber": 590,
"finished": "2013-06-05 12:54:07.048555",
"error_count": 0,
"duration": 0.000668,
"order": 15
},
{
"errors": [],
"name": "download",
"started": "2013-06-05 12:54:07.049041",
"started_linenumber": 592,
"finished_linenumber": 665,
"finished": "2013-06-05 12:54:22.389733",
"error_count": 0,
"duration": 15.340692,
"order": 16
},
{
"errors": [],
"name": "set props: buildid",
"started": "2013-06-05 12:54:22.390374",
"started_linenumber": 667,
"finished_linenumber": 714,
"finished": "2013-06-05 12:54:22.547237",
"error_count": 0,
"duration": 0.156863,
"order": 17
},
{
"errors": [],
"name": "'python.exe c:/talos-slave/test/tools/scripts/support/mouse_and_screen_resolution.py ...'",
"started": "2013-06-05 12:54:22.547836",
"started_linenumber": 716,
"finished_linenumber": 761,
"finished": "2013-06-05 12:54:23.359326",
"error_count": 0,
"duration": 0.81149,
"order": 18
},
{
"errors": [],
"name": "unpack tests",
"started": "2013-06-05 12:54:23.359896",
"started_linenumber": 763,
"finished_linenumber": 807,
"finished": "2013-06-05 12:54:55.231690",
"error_count": 0,
"duration": 31.871794,
"order": 19
},
{
"errors": [
{
"line": "TEST-UNEXPECTED-FAIL | chrome://mochitests/content/browser/dom/tests/browser/browser_ConsoleAPITests.js | Exception thrown in CO_observe: TypeError: Components.utils.isXrayWrapper is not a function\r\n",
"linenumber": 26698
},
{
"line": "TEST-UNEXPECTED-FAIL | chrome://mochitests/content/browser/dom/tests/browser/browser_ConsoleAPITests.js | Test timed out\r\n",
"linenumber": 26705
}
],
"name": "'python mochitest/runtests.py ...' warnings",
"started": "2013-06-05 12:54:55.232364",
"started_linenumber": 809,
"finished_linenumber": 54423,
"finished": "2013-06-05 13:15:39.235146",
"error_count": 2,
"duration": 1244.002782,
"order": 20
},
{
"errors": [],
"name": "'rm -rf ...'",
"started": "2013-06-05 13:15:39.244545",
"started_linenumber": 54425,
"finished_linenumber": 54469,
"finished": "2013-06-05 13:16:04.014823",
"error_count": 0,
"duration": 24.770278,
"order": 21
},
{
"errors": [],
"name": "maybe rebooting slave lost",
"started": "2013-06-05 13:16:04.015405",
"started_linenumber": 54471,
"finished_linenumber": 54473,
"finished": "2013-06-05 13:16:04.963614",
"error_count": 0,
"duration": 0.948209,
"order": 22
}
]
}

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,171 @@
{
"url": "file:///home/vagrant/treeherder-service/tests/sample_data/logs/mozilla-inbound_ubuntu64_vm-debug_test-mochitest-other-bm53-tests1-linux-build122.txt.gz",
"header": {
"slave": "tst-linux64-ec2-428",
"buildid": "20130605113136",
"builder": "mozilla-inbound_ubuntu64_vm-debug_test-mochitest-other",
"results": "warnings (1)",
"starttime": "1370461498.84",
"builduid": "3d82a57013fe406b9740463bad56394e",
"revision": "4d2d0bc38fec"
},
"steps": [
{
"errors": [],
"name": "set props: master",
"started": "2013-06-05 12:44:58.842738",
"started_linenumber": 8,
"finished_linenumber": 10,
"finished": "2013-06-05 12:44:58.843804",
"error_count": 0,
"duration": 0.001066,
"order": 0
},
{
"errors": [],
"name": "set props: basedir",
"started": "2013-06-05 12:44:58.844579",
"started_linenumber": 12,
"finished_linenumber": 52,
"finished": "2013-06-05 12:44:58.975106",
"error_count": 0,
"duration": 0.130527,
"order": 1
},
{
"errors": [],
"name": "downloading to buildprops.json",
"started": "2013-06-05 12:44:58.975618",
"started_linenumber": 54,
"finished_linenumber": 55,
"finished": "2013-06-05 12:44:59.037644",
"error_count": 0,
"duration": 0.062026,
"order": 2
},
{
"errors": [],
"name": "'rm -rf ...'",
"started": "2013-06-05 12:44:59.038141",
"started_linenumber": 57,
"finished_linenumber": 95,
"finished": "2013-06-05 12:44:59.112857",
"error_count": 0,
"duration": 0.074716,
"order": 3
},
{
"errors": [],
"name": "'rm -rf ...'",
"started": "2013-06-05 12:44:59.113592",
"started_linenumber": 97,
"finished_linenumber": 135,
"finished": "2013-06-05 12:44:59.201908",
"error_count": 0,
"duration": 0.088316,
"order": 4
},
{
"errors": [],
"name": "'hg clone ...'",
"started": "2013-06-05 12:44:59.202642",
"started_linenumber": 137,
"finished_linenumber": 182,
"finished": "2013-06-05 12:45:02.180652",
"error_count": 0,
"duration": 2.97801,
"order": 5
},
{
"errors": [],
"name": "'hg update ...'",
"started": "2013-06-05 12:45:02.181421",
"started_linenumber": 184,
"finished_linenumber": 223,
"finished": "2013-06-05 12:45:02.421021",
"error_count": 0,
"duration": 0.2396,
"order": 6
},
{
"errors": [],
"name": "set props: script_repo_revision",
"started": "2013-06-05 12:45:02.421566",
"started_linenumber": 225,
"finished_linenumber": 265,
"finished": "2013-06-05 12:45:02.558016",
"error_count": 0,
"duration": 0.13645,
"order": 7
},
{
"errors": [],
"name": "tinderboxprint_script_revlink",
"started": "2013-06-05 12:45:02.558553",
"started_linenumber": 267,
"finished_linenumber": 269,
"finished": "2013-06-05 12:45:02.559173",
"error_count": 0,
"duration": 0.00062,
"order": 8
},
{
"errors": [
{
"line": "12:46:31 WARNING - TEST-UNEXPECTED-FAIL | automation.py | Exited with code 11 during test run\n",
"linenumber": 826
},
{
"line": "12:46:37 WARNING - PROCESS-CRASH | automation.py | application crashed [@ xOpen]\n",
"linenumber": 829
},
{
"line": "12:46:40 WARNING - TEST-UNEXPECTED-FAIL | automation.py | Exited with code 11 during test run\n",
"linenumber": 1633
},
{
"line": "12:46:46 WARNING - PROCESS-CRASH | automation.py | application crashed [@ xOpen]\n",
"linenumber": 1636
},
{
"line": "12:46:48 WARNING - TEST-UNEXPECTED-FAIL | automation.py | Exited with code 11 during test run\n",
"linenumber": 2316
},
{
"line": "12:46:55 WARNING - PROCESS-CRASH | automation.py | application crashed [@ xOpen]\n",
"linenumber": 2319
}
],
"name": "'/tools/buildbot/bin/python scripts/scripts/desktop_unittest.py ...' warnings",
"started": "2013-06-05 12:45:02.559674",
"started_linenumber": 271,
"finished_linenumber": 3070,
"finished": "2013-06-05 12:46:55.430095",
"error_count": 6,
"duration": 112.870421,
"order": 9
},
{
"errors": [],
"name": "set props: build_url symbols_url",
"started": "2013-06-05 12:46:55.431212",
"started_linenumber": 3072,
"finished_linenumber": 3114,
"finished": "2013-06-05 12:46:55.479840",
"error_count": 0,
"duration": 0.048628,
"order": 10
},
{
"errors": [],
"name": "reboot slave lost",
"started": "2013-06-05 12:46:55.480585",
"started_linenumber": 3116,
"finished_linenumber": 3118,
"finished": "2013-06-05 12:46:57.867188",
"error_count": 0,
"duration": 2.386603,
"order": 11
}
]
}

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,281 @@
{
"url": "file:///home/vagrant/treeherder-service/tests/sample_data/logs/ux_ubuntu32_vm_test-jetpack-bm67-tests1-linux-build16.txt.gz",
"header": {
"slave": "tst-linux32-ec2-094",
"buildid": "20130605124039",
"builder": "ux_ubuntu32_vm_test-jetpack",
"results": "warnings (1)",
"starttime": "1370462504.72",
"builduid": "929df1a898e14a06a7ad65987f35d4a8",
"revision": "546ccc10a18f"
},
"steps": [
{
"errors": [],
"name": "set props: revision",
"started": "2013-06-05 13:01:44.724777",
"started_linenumber": 8,
"finished_linenumber": 10,
"finished": "2013-06-05 13:01:44.725458",
"error_count": 0,
"duration": 0.000681,
"order": 0
},
{
"errors": [],
"name": "set props: who",
"started": "2013-06-05 13:01:44.725937",
"started_linenumber": 12,
"finished_linenumber": 14,
"finished": "2013-06-05 13:01:44.726485",
"error_count": 0,
"duration": 0.000548,
"order": 1
},
{
"errors": [],
"name": "set props: basedir",
"started": "2013-06-05 13:01:44.726944",
"started_linenumber": 16,
"finished_linenumber": 56,
"finished": "2013-06-05 13:01:44.769939",
"error_count": 0,
"duration": 0.042995,
"order": 2
},
{
"errors": [],
"name": "set props: hashType",
"started": "2013-06-05 13:01:44.770409",
"started_linenumber": 58,
"finished_linenumber": 98,
"finished": "2013-06-05 13:01:44.803354",
"error_count": 0,
"duration": 0.032945,
"order": 3
},
{
"errors": [],
"name": "set props: builddir",
"started": "2013-06-05 13:01:44.803818",
"started_linenumber": 100,
"finished_linenumber": 140,
"finished": "2013-06-05 13:01:44.875656",
"error_count": 0,
"duration": 0.071838,
"order": 4
},
{
"errors": [],
"name": "clobber build tools",
"started": "2013-06-05 13:01:44.876351",
"started_linenumber": 142,
"finished_linenumber": 180,
"finished": "2013-06-05 13:01:45.250095",
"error_count": 0,
"duration": 0.373744,
"order": 5
},
{
"errors": [],
"name": "clone build tools",
"started": "2013-06-05 13:01:45.250579",
"started_linenumber": 182,
"finished_linenumber": 227,
"finished": "2013-06-05 13:02:01.869535",
"error_count": 0,
"duration": 16.618956,
"order": 6
},
{
"errors": [],
"name": "set props: toolsdir",
"started": "2013-06-05 13:02:01.870099",
"started_linenumber": 229,
"finished_linenumber": 269,
"finished": "2013-06-05 13:02:01.910811",
"error_count": 0,
"duration": 0.040712,
"order": 7
},
{
"errors": [],
"name": "set props: purge_actual purge_target",
"started": "2013-06-05 13:02:01.911262",
"started_linenumber": 271,
"finished_linenumber": 320,
"finished": "2013-06-05 13:02:02.036732",
"error_count": 0,
"duration": 0.12547,
"order": 8
},
{
"errors": [],
"name": "'rm -rf ...'",
"started": "2013-06-05 13:02:02.037224",
"started_linenumber": 322,
"finished_linenumber": 360,
"finished": "2013-06-05 13:02:02.667440",
"error_count": 0,
"duration": 0.630216,
"order": 9
},
{
"errors": [],
"name": "download",
"started": "2013-06-05 13:02:02.667954",
"started_linenumber": 362,
"finished_linenumber": 421,
"finished": "2013-06-05 13:02:14.651874",
"error_count": 0,
"duration": 11.98392,
"order": 10
},
{
"errors": [],
"name": "unpack",
"started": "2013-06-05 13:02:14.652409",
"started_linenumber": 423,
"finished_linenumber": 461,
"finished": "2013-06-05 13:02:22.926059",
"error_count": 0,
"duration": 8.27365,
"order": 11
},
{
"errors": [],
"name": "set props: exepath",
"started": "2013-06-05 13:02:22.926579",
"started_linenumber": 463,
"finished_linenumber": 465,
"finished": "2013-06-05 13:02:22.927223",
"error_count": 0,
"duration": 0.000644,
"order": 12
},
{
"errors": [],
"name": "set props: exedir",
"started": "2013-06-05 13:02:22.927677",
"started_linenumber": 467,
"finished_linenumber": 469,
"finished": "2013-06-05 13:02:22.928267",
"error_count": 0,
"duration": 0.00059,
"order": 13
},
{
"errors": [],
"name": "set props: symbols_url",
"started": "2013-06-05 13:02:22.928721",
"started_linenumber": 471,
"finished_linenumber": 473,
"finished": "2013-06-05 13:02:22.929347",
"error_count": 0,
"duration": 0.000626,
"order": 14
},
{
"errors": [],
"name": "download",
"started": "2013-06-05 13:02:22.929843",
"started_linenumber": 475,
"finished_linenumber": 550,
"finished": "2013-06-05 13:02:52.272641",
"error_count": 0,
"duration": 29.342798,
"order": 15
},
{
"errors": [],
"name": "set props: buildid",
"started": "2013-06-05 13:02:52.273614",
"started_linenumber": 552,
"finished_linenumber": 593,
"finished": "2013-06-05 13:02:52.350154",
"error_count": 0,
"duration": 0.07654,
"order": 16
},
{
"errors": [],
"name": "'xset s ...'",
"started": "2013-06-05 13:02:52.350652",
"started_linenumber": 595,
"finished_linenumber": 641,
"finished": "2013-06-05 13:02:52.387987",
"error_count": 0,
"duration": 0.037335,
"order": 17
},
{
"errors": [],
"name": "unpack tests",
"started": "2013-06-05 13:02:52.388429",
"started_linenumber": 643,
"finished_linenumber": 681,
"finished": "2013-06-05 13:02:52.671040",
"error_count": 0,
"duration": 0.282611,
"order": 18
},
{
"errors": [
{
"line": "TEST-UNEXPECTED-FAIL | tests/test-addon-page.test that add-on page has no chrome | chrome is not visible for addon page - false == true\n",
"linenumber": 2390
},
{
"line": "TEST-UNEXPECTED-FAIL | tests/test-addon-page.test that add-on page with hash and querystring has no chrome | chrome is not visible for addon page - false == true\n",
"linenumber": 2408
},
{
"line": "TEST-UNEXPECTED-FAIL | tests/test-addon-page.test that add-on page with hash has no chrome | chrome is not visible for addon page - false == true\n",
"linenumber": 2426
},
{
"line": "TEST-UNEXPECTED-FAIL | tests/test-addon-page.test that add-on page with querystring has no chrome | chrome is not visible for addon page - false == true\n",
"linenumber": 2444
},
{
"line": "TEST-UNEXPECTED-FAIL | tests/test-widget.testNavigationBarWidgets | \"Camera / Microphone Access\" != \"2nd widget\"\n",
"linenumber": 9845
},
{
"line": "TEST-UNEXPECTED-FAIL | tests/test-widget.testNavigationBarWidgets | \"Bookmarks\" != \"3rd widget\"\n",
"linenumber": 9865
}
],
"name": "'python jetpack/bin/cfx ...' warnings",
"started": "2013-06-05 13:02:52.671518",
"started_linenumber": 683,
"finished_linenumber": 11828,
"finished": "2013-06-05 13:10:29.331890",
"error_count": 6,
"duration": 456.660372,
"order": 19
},
{
"errors": [],
"name": "'rm -rf ...'",
"started": "2013-06-05 13:10:29.332965",
"started_linenumber": 11830,
"finished_linenumber": 11868,
"finished": "2013-06-05 13:10:29.462254",
"error_count": 0,
"duration": 0.129289,
"order": 20
},
{
"errors": [],
"name": "maybe rebooting slave lost",
"started": "2013-06-05 13:10:29.462735",
"started_linenumber": 11870,
"finished_linenumber": 11872,
"finished": "2013-06-05 13:10:31.487768",
"error_count": 0,
"duration": 2.025033,
"order": 21
}
]
}

Двоичный файл не отображается.

Просмотреть файл

Просмотреть файл

@ -0,0 +1,122 @@
import urllib2
import gzip
import io
from .logviewparser import BuildbotLogViewParser
class LogParseCollection(object):
"""
Run a log through a collection of parsers to get artifacts.
Result: Returns a list of log artifacts, one for each parser.
Architecture
============
LogParseCollection
------------------
* Holds one or more instances of ``BuildbotLogParserBase``
* If ``job_type`` passed in, creates the parser instances
* If ``parsers`` passed in, uses those as the parsers
* Reads the log from the log handle/url and walks each line
calling into each parser with each line for handling
* Maintains no state
BuildbotLogParserBase
-------------
* Base class for all Buildbot log parsers.
* Manages:
* artifact
* state
* job_type
* line number
* Calls either ``parse_header_line`` or ``parse_content_line``
depending on state
* decides whether to call SubParser if in a step that matches
the SubParser ``step_name_match`` regex.
LogViewParser
-------------
* Parses out content for use in a visual Log Parser
* Manages:
* artifact steps (===started and ===finished lines)
* current step number and count
* sub_parser
* Only SubParser here is an ErrorParser
"""
def __init__(self, url, job_type=None, parsers=None):
"""
``url`` - url of the log to be parsed
``job_type`` - The type of job this log is for.
``parsers`` - LogViewParser instances that should
be run against the log.
Must provide either ``parsers`` or ``job_type`` so that
default parsers can be created.
"""
if not parsers and not job_type:
raise ValueError("Must provide either ``job_type`` or ``parsers``")
# the results
self.url = url
self.artifacts = {}
self.job_type = job_type
if parsers:
# ensure that self.parsers is a list, even if a single parser was
# passed in
if not isinstance(parsers, list):
parsers = [parsers]
self.parsers = parsers
else:
# use the defaults
self.parsers = [
BuildbotLogViewParser(self.job_type, self.url),
]
def get_log_handle(self, url):
"""Hook to get a handle to the log with this url"""
return urllib2.urlopen(url)
def parse(self):
"""
Iterate over each line of the log, running each parser against it.
Stream lines from the gzip file and run each parser against it,
building the ``artifact`` as we go.
"""
handle = self.get_log_handle(self.url)
# using BytesIO is a workaround. Apparently this is fixed in
# Python 3.2, but not in the 2.x versions. GzipFile wants the
# the methods seek() and tell(), which don't exist on a normal
# fileobj.
# interesting write-up here:
# http://www.enricozini.org/2011/cazzeggio/python-gzip/
gz_file = gzip.GzipFile(fileobj=io.BytesIO(handle.read()))
for line in gz_file:
# stop parsing if all parsers are done
if not self.parse_complete:
# run each parser on each line of the log
for parser in self.parsers:
parser.parse_line(line)
# gather the artifacts from all parsers
for parser in self.parsers:
self.artifacts[parser.name] = parser.get_artifact()
gz_file.close()
@property
def parse_complete(self):
"""Return true if all parsers are parse_complete."""
return all([x.parse_complete for x in self.parsers])

Просмотреть файл

@ -0,0 +1,118 @@
import datetime
import re
class BuildbotLogParserBase(object):
"""
Base class for all Buildbot log parsers.
The child class will be designed to create a particular type of artifact.
This class is called for each line of the log file, so it has no
knowledge of the log file itself, as a whole. It only, optionally, has
the url to the log file to add to its own artifact.
"""
#################
# state constants
#################
# while still reading the initial header section
ST_HEADER = 'header'
# after having started any section
ST_STARTED = "started"
# after having finished any section
ST_FINISHED = "finished"
# this parser is done, no more need to parse lines
ST_PARSE_COMPLETE = "parse complete"
#################
# regex patterns for started and finished sections
#################
RE_HEADER_VALUE = re.compile('^(?P<key>[a-z]+): (?P<value>.*)$')
PATTERN = ' (.*?) \(results: \d+, elapsed: (?:\d+ mins, )?\d+ secs\) \(at (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d+)\) ={9}'
RE_START = re.compile('={9} Started' + PATTERN)
RE_FINISH = re.compile('={9} Finished' + PATTERN)
RE_PROPERTY = re.compile('(\w*): (.*)')
DATE_FORMAT = '%Y-%m-%d %H:%M:%S.%f'
def __init__(self, job_type, url=None):
"""
Create the LogParser
``job_type`` - Something like "mochitest" or "reftest", etc.
``url`` - The url this log comes from. It's optional, but it gets
added to the artifact.
"""
self.artifact = {
"header": {},
"url": url
}
self.state = self.ST_HEADER
self.job_type = job_type
self.lineno = 0
@property
def name(self):
"""Return the name used to store this in the collection's artifact"""
raise NotImplementedError # pragma nocover
def parsetime(self, match):
"""Convert a string date into a datetime."""
return datetime.datetime.strptime(match, self.DATE_FORMAT)
def parse_header_line(self, line):
"""
Parse out a value in the header
The header values in the log look like this:
builder: mozilla-central_ubuntu32_vm_test-crashtest-ipc
slave: tst-linux32-ec2-137
starttime: 1368466076.01
results: success (0)
buildid: 20130513091541
builduid: acddb5f7043c4d5b9f66619f9433cab0
revision: c80dc6ffe865
"""
match = self.RE_HEADER_VALUE.match(line)
if match:
key, value = match.groups()
self.artifact["header"][key] = value
def parse_line(self, line):
"""
Parse a single line of the log.
Parse the header until we hit a line with "started" in it.
"""
if self.state == self.ST_HEADER:
if not self.RE_START.match(line):
self.parse_header_line(line)
else:
self.state = self.ST_STARTED
self.parse_content_line(line)
else:
self.parse_content_line(line)
self.lineno += 1
def parse_content_line(self, line):
"""Child class implements to handle parsing of non-header data"""
raise NotImplementedError # pragma nocover
@property
def parse_complete(self):
"""Whether or not this parser is complete and should stop parsing."""
return self.state == self.ST_PARSE_COMPLETE
def get_artifact(self):
"""
Return the job artifact.
A good place to update the artifact before returning it, if needed.
This can be handy to get the "final duration" based on the
last finished section.
"""
return self.artifact

Просмотреть файл

@ -0,0 +1,123 @@
import re
from .logparserbase import BuildbotLogParserBase
class BuildbotLogViewParser(BuildbotLogParserBase):
"""
Makes the artifact for the log viewer.
The stored object for a log will be
"steps": [
{
"errors": [],
"name": "set props: master", # the name of the process on start line
"started": "2013-06-05 12:39:57.838527",
"started_linenumber": 8,
"finished_linenumber": 10,
"finished": "2013-06-05 12:39:57.839226",
"error_count": 0,
"duration": 0.000699, # in seconds
"order": 0 # the order the process came in the log file
},
...
]
"""
def __init__(self, job_type, url=None):
"""
Construct a ``BuildbotLogViewParser``
Keep track of the current step number, and step artifacts
Uses a simple ErrorParser to detect errors. Error lines are added
to each step they come from.
"""
super(BuildbotLogViewParser, self).__init__(job_type, url)
self.stepnum = -1
self.artifact["steps"] = []
self.sub_parser = ErrorParser()
@property
def name(self):
"""The name of this type of log artifact"""
return "Structured Log"
def parse_content_line(self, line):
"""Parse a single non-header line of the log"""
# check if it's the start of a step
match = self.RE_START.match(line)
if match:
self.state = self.ST_STARTED
self.stepnum += 1
self.steps.append({
"name": match.group(1),
"started": match.group(2),
"started_linenumber": self.lineno,
"order": self.stepnum,
"errors": [],
})
return
# check if it's the end of a step
match = self.RE_FINISH.match(line)
if match:
self.state = self.ST_FINISHED
self.current_step.update({
"finished": match.group(2),
"finished_linenumber": self.lineno,
"errors": self.sub_parser.get_artifact(),
})
self.set_duration()
self.current_step["error_count"] = len(self.current_step["errors"])
# reset the sub_parser for the next step
self.sub_parser = ErrorParser()
return
# call the subparser to check for errors
self.sub_parser.parse_content_line(line, self.lineno)
def set_duration(self):
"""Sets duration for the step in seconds."""
start = self.parsetime(self.current_step["started"])
finish = self.parsetime(self.current_step["finished"])
delta = finish - start
self.current_step["duration"] = delta.total_seconds()
@property
def steps(self):
"""Return the list of steps in the artifact"""
return self.artifact["steps"]
@property
def current_step(self):
"""Return the current step in the artifact"""
return self.steps[self.stepnum]
class ErrorParser(object):
"""
Super simple parser to just find any line with an error or failure
"""
def __init__(self):
"""A simple error detection sub-parser"""
self.RE_ERR = re.compile(r".*?(TEST-UNEXPECTED-.*|PROCESS-CRASH) \| (.*)\|(.*)")
self.errors = []
def parse_content_line(self, line, lineno):
"""Check a single line for an error. Keeps track of the linenumber"""
if self.RE_ERR.match(line):
self.errors.append({
"linenumber": lineno,
"line": line
})
def get_artifact(self):
"""Return the list of errors found, if any."""
return self.errors