xref: /openbmc/openbmc/poky/meta/classes/report-error.bbclass (revision 96e4b4e121e0e2da1535d7d537d6a982a6ff5bc0)
1eb8dc403SDave Cobbley#
2eb8dc403SDave Cobbley# Collects debug information in order to create error report files.
3eb8dc403SDave Cobbley#
4eb8dc403SDave Cobbley# Copyright (C) 2013 Intel Corporation
5eb8dc403SDave Cobbley# Author: Andreea Brandusa Proca <andreea.b.proca@intel.com>
6eb8dc403SDave Cobbley#
792b42cb3SPatrick Williams# SPDX-License-Identifier: MIT
892b42cb3SPatrick Williams#
9eb8dc403SDave Cobbley
10eb8dc403SDave CobbleyERR_REPORT_DIR ?= "${LOG_DIR}/error-report"
11eb8dc403SDave Cobbley
12eb8dc403SDave Cobbleydef errorreport_getdata(e):
13eb8dc403SDave Cobbley    import codecs
14eb8dc403SDave Cobbley    logpath = e.data.getVar('ERR_REPORT_DIR')
15eb8dc403SDave Cobbley    datafile = os.path.join(logpath, "error-report.txt")
16eb8dc403SDave Cobbley    with codecs.open(datafile, 'r', 'utf-8') as f:
17eb8dc403SDave Cobbley        data = f.read()
18eb8dc403SDave Cobbley    return data
19eb8dc403SDave Cobbley
20eb8dc403SDave Cobbleydef errorreport_savedata(e, newdata, file):
21eb8dc403SDave Cobbley    import json
22eb8dc403SDave Cobbley    import codecs
23eb8dc403SDave Cobbley    logpath = e.data.getVar('ERR_REPORT_DIR')
24eb8dc403SDave Cobbley    datafile = os.path.join(logpath, file)
25eb8dc403SDave Cobbley    with codecs.open(datafile, 'w', 'utf-8') as f:
26eb8dc403SDave Cobbley        json.dump(newdata, f, indent=4, sort_keys=True)
27eb8dc403SDave Cobbley    return datafile
28eb8dc403SDave Cobbley
29a34c030eSBrad Bishopdef get_conf_data(e, filename):
30a34c030eSBrad Bishop    builddir = e.data.getVar('TOPDIR')
31a34c030eSBrad Bishop    filepath = os.path.join(builddir, "conf", filename)
32a34c030eSBrad Bishop    jsonstring = ""
33a34c030eSBrad Bishop    if os.path.exists(filepath):
34a34c030eSBrad Bishop        with open(filepath, 'r') as f:
35a34c030eSBrad Bishop            for line in f.readlines():
36a34c030eSBrad Bishop                if line.startswith("#") or len(line.strip()) == 0:
37a34c030eSBrad Bishop                    continue
38a34c030eSBrad Bishop                else:
39a34c030eSBrad Bishop                    jsonstring=jsonstring + line
40a34c030eSBrad Bishop    return jsonstring
41a34c030eSBrad Bishop
428e7b46e2SPatrick Williamsdef get_common_data(e):
438e7b46e2SPatrick Williams    data = {}
448e7b46e2SPatrick Williams    data['machine'] = e.data.getVar("MACHINE")
458e7b46e2SPatrick Williams    data['build_sys'] = e.data.getVar("BUILD_SYS")
468e7b46e2SPatrick Williams    data['distro'] = e.data.getVar("DISTRO")
478e7b46e2SPatrick Williams    data['target_sys'] = e.data.getVar("TARGET_SYS")
488e7b46e2SPatrick Williams    data['branch_commit'] = str(oe.buildcfg.detect_branch(e.data)) + ": " + str(oe.buildcfg.detect_revision(e.data))
498e7b46e2SPatrick Williams    data['bitbake_version'] = e.data.getVar("BB_VERSION")
508e7b46e2SPatrick Williams    data['layer_version'] = get_layers_branch_rev(e.data)
518e7b46e2SPatrick Williams    data['local_conf'] = get_conf_data(e, 'local.conf')
528e7b46e2SPatrick Williams    data['auto_conf'] = get_conf_data(e, 'auto.conf')
538e7b46e2SPatrick Williams    return data
548e7b46e2SPatrick Williams
55eb8dc403SDave Cobbleypython errorreport_handler () {
56eb8dc403SDave Cobbley        import json
57eb8dc403SDave Cobbley        import codecs
58eb8dc403SDave Cobbley
59eb8dc403SDave Cobbley        def nativelsb():
60eb8dc403SDave Cobbley            nativelsbstr = e.data.getVar("NATIVELSBSTRING")
61eb8dc403SDave Cobbley            # provide a bit more host info in case of uninative build
62eb8dc403SDave Cobbley            if e.data.getVar('UNINATIVE_URL') != 'unset':
63eb8dc403SDave Cobbley                return '/'.join([nativelsbstr, lsb_distro_identifier(e.data)])
64eb8dc403SDave Cobbley            return nativelsbstr
65eb8dc403SDave Cobbley
66eb8dc403SDave Cobbley        logpath = e.data.getVar('ERR_REPORT_DIR')
67eb8dc403SDave Cobbley        datafile = os.path.join(logpath, "error-report.txt")
68eb8dc403SDave Cobbley
69eb8dc403SDave Cobbley        if isinstance(e, bb.event.BuildStarted):
70eb8dc403SDave Cobbley            bb.utils.mkdirhier(logpath)
71eb8dc403SDave Cobbley            data = {}
728e7b46e2SPatrick Williams            data = get_common_data(e)
73eb8dc403SDave Cobbley            data['nativelsb'] = nativelsb()
74eb8dc403SDave Cobbley            data['failures'] = []
75eb8dc403SDave Cobbley            data['component'] = " ".join(e.getPkgs())
76eb8dc403SDave Cobbley            lock = bb.utils.lockfile(datafile + '.lock')
77eb8dc403SDave Cobbley            errorreport_savedata(e, data, "error-report.txt")
78eb8dc403SDave Cobbley            bb.utils.unlockfile(lock)
79eb8dc403SDave Cobbley
80eb8dc403SDave Cobbley        elif isinstance(e, bb.build.TaskFailed):
81eb8dc403SDave Cobbley            task = e.task
82eb8dc403SDave Cobbley            taskdata={}
83eb8dc403SDave Cobbley            log = e.data.getVar('BB_LOGFILE')
84*96e4b4e1SPatrick Williams            taskdata['recipe'] = e.data.expand("${PN}")
85eb8dc403SDave Cobbley            taskdata['package'] = e.data.expand("${PF}")
86eb8dc403SDave Cobbley            taskdata['task'] = task
87eb8dc403SDave Cobbley            if log:
88eb8dc403SDave Cobbley                try:
8964c979e8SBrad Bishop                    with codecs.open(log, encoding='utf-8') as logFile:
90eb8dc403SDave Cobbley                        logdata = logFile.read()
91eb8dc403SDave Cobbley                    # Replace host-specific paths so the logs are cleaner
92eb8dc403SDave Cobbley                    for d in ("TOPDIR", "TMPDIR"):
93eb8dc403SDave Cobbley                        s = e.data.getVar(d)
94eb8dc403SDave Cobbley                        if s:
95eb8dc403SDave Cobbley                            logdata = logdata.replace(s, d)
96eb8dc403SDave Cobbley                except:
97eb8dc403SDave Cobbley                    logdata = "Unable to read log file"
98eb8dc403SDave Cobbley            else:
99eb8dc403SDave Cobbley                logdata = "No Log"
100eb8dc403SDave Cobbley
101eb8dc403SDave Cobbley            # server will refuse failures longer than param specified in project.settings.py
102eb8dc403SDave Cobbley            # MAX_UPLOAD_SIZE = "5242880"
103eb8dc403SDave Cobbley            # use lower value, because 650 chars can be spent in task, package, version
104eb8dc403SDave Cobbley            max_logdata_size = 5242000
105eb8dc403SDave Cobbley            # upload last max_logdata_size characters
106eb8dc403SDave Cobbley            if len(logdata) > max_logdata_size:
107eb8dc403SDave Cobbley                logdata = "..." + logdata[-max_logdata_size:]
108eb8dc403SDave Cobbley            taskdata['log'] = logdata
109eb8dc403SDave Cobbley            lock = bb.utils.lockfile(datafile + '.lock')
110eb8dc403SDave Cobbley            jsondata = json.loads(errorreport_getdata(e))
111eb8dc403SDave Cobbley            jsondata['failures'].append(taskdata)
112eb8dc403SDave Cobbley            errorreport_savedata(e, jsondata, "error-report.txt")
113eb8dc403SDave Cobbley            bb.utils.unlockfile(lock)
114eb8dc403SDave Cobbley
1158e7b46e2SPatrick Williams        elif isinstance(e, bb.event.NoProvider):
1168e7b46e2SPatrick Williams            bb.utils.mkdirhier(logpath)
1178e7b46e2SPatrick Williams            data = {}
1188e7b46e2SPatrick Williams            data = get_common_data(e)
1198e7b46e2SPatrick Williams            data['nativelsb'] = nativelsb()
1208e7b46e2SPatrick Williams            data['failures'] = []
1218e7b46e2SPatrick Williams            data['component'] = str(e._item)
1228e7b46e2SPatrick Williams            taskdata={}
1238e7b46e2SPatrick Williams            taskdata['log'] = str(e)
1248e7b46e2SPatrick Williams            taskdata['package'] = str(e._item)
1258e7b46e2SPatrick Williams            taskdata['task'] = "Nothing provides " + "'" + str(e._item) + "'"
1268e7b46e2SPatrick Williams            data['failures'].append(taskdata)
1278e7b46e2SPatrick Williams            lock = bb.utils.lockfile(datafile + '.lock')
1288e7b46e2SPatrick Williams            errorreport_savedata(e, data, "error-report.txt")
1298e7b46e2SPatrick Williams            bb.utils.unlockfile(lock)
1308e7b46e2SPatrick Williams
1318e7b46e2SPatrick Williams        elif isinstance(e, bb.event.ParseError):
1328e7b46e2SPatrick Williams            bb.utils.mkdirhier(logpath)
1338e7b46e2SPatrick Williams            data = {}
1348e7b46e2SPatrick Williams            data = get_common_data(e)
1358e7b46e2SPatrick Williams            data['nativelsb'] = nativelsb()
1368e7b46e2SPatrick Williams            data['failures'] = []
1378e7b46e2SPatrick Williams            data['component'] = "parse"
1388e7b46e2SPatrick Williams            taskdata={}
1398e7b46e2SPatrick Williams            taskdata['log'] = str(e._msg)
1408e7b46e2SPatrick Williams            taskdata['task'] = str(e._msg)
1418e7b46e2SPatrick Williams            data['failures'].append(taskdata)
1428e7b46e2SPatrick Williams            lock = bb.utils.lockfile(datafile + '.lock')
1438e7b46e2SPatrick Williams            errorreport_savedata(e, data, "error-report.txt")
1448e7b46e2SPatrick Williams            bb.utils.unlockfile(lock)
1458e7b46e2SPatrick Williams
146eb8dc403SDave Cobbley        elif isinstance(e, bb.event.BuildCompleted):
147eb8dc403SDave Cobbley            lock = bb.utils.lockfile(datafile + '.lock')
148eb8dc403SDave Cobbley            jsondata = json.loads(errorreport_getdata(e))
149eb8dc403SDave Cobbley            bb.utils.unlockfile(lock)
150eb8dc403SDave Cobbley            failures = jsondata['failures']
151eb8dc403SDave Cobbley            if(len(failures) > 0):
152eb8dc403SDave Cobbley                filename = "error_report_" + e.data.getVar("BUILDNAME")+".txt"
153eb8dc403SDave Cobbley                datafile = errorreport_savedata(e, jsondata, filename)
154eb8dc403SDave Cobbley                bb.note("The errors for this build are stored in %s\nYou can send the errors to a reports server by running:\n  send-error-report %s [-s server]" % (datafile, datafile))
155eb8dc403SDave Cobbley                bb.note("The contents of these logs will be posted in public if you use the above command with the default server. Please ensure you remove any identifying or proprietary information when prompted before sending.")
156eb8dc403SDave Cobbley}
157eb8dc403SDave Cobbley
158eb8dc403SDave Cobbleyaddhandler errorreport_handler
1598e7b46e2SPatrick Williamserrorreport_handler[eventmask] = "bb.event.BuildStarted bb.event.BuildCompleted bb.build.TaskFailed bb.event.NoProvider bb.event.ParseError"
160