xref: /openbmc/openbmc/poky/meta/classes/report-error.bbclass (revision a34c030e5ec7021e7fb452410d38abfb3993ec68)
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#
7eb8dc403SDave Cobbley# Licensed under the MIT license, see COPYING.MIT for details
8eb8dc403SDave Cobbley
9eb8dc403SDave CobbleyERR_REPORT_DIR ?= "${LOG_DIR}/error-report"
10eb8dc403SDave Cobbley
11eb8dc403SDave Cobbleydef errorreport_getdata(e):
12eb8dc403SDave Cobbley    import codecs
13eb8dc403SDave Cobbley    logpath = e.data.getVar('ERR_REPORT_DIR')
14eb8dc403SDave Cobbley    datafile = os.path.join(logpath, "error-report.txt")
15eb8dc403SDave Cobbley    with codecs.open(datafile, 'r', 'utf-8') as f:
16eb8dc403SDave Cobbley        data = f.read()
17eb8dc403SDave Cobbley    return data
18eb8dc403SDave Cobbley
19eb8dc403SDave Cobbleydef errorreport_savedata(e, newdata, file):
20eb8dc403SDave Cobbley    import json
21eb8dc403SDave Cobbley    import codecs
22eb8dc403SDave Cobbley    logpath = e.data.getVar('ERR_REPORT_DIR')
23eb8dc403SDave Cobbley    datafile = os.path.join(logpath, file)
24eb8dc403SDave Cobbley    with codecs.open(datafile, 'w', 'utf-8') as f:
25eb8dc403SDave Cobbley        json.dump(newdata, f, indent=4, sort_keys=True)
26eb8dc403SDave Cobbley    return datafile
27eb8dc403SDave Cobbley
28*a34c030eSBrad Bishopdef get_conf_data(e, filename):
29*a34c030eSBrad Bishop    builddir = e.data.getVar('TOPDIR')
30*a34c030eSBrad Bishop    filepath = os.path.join(builddir, "conf", filename)
31*a34c030eSBrad Bishop    jsonstring = ""
32*a34c030eSBrad Bishop    if os.path.exists(filepath):
33*a34c030eSBrad Bishop        with open(filepath, 'r') as f:
34*a34c030eSBrad Bishop            for line in f.readlines():
35*a34c030eSBrad Bishop                if line.startswith("#") or len(line.strip()) == 0:
36*a34c030eSBrad Bishop                    continue
37*a34c030eSBrad Bishop                else:
38*a34c030eSBrad Bishop                    jsonstring=jsonstring + line
39*a34c030eSBrad Bishop    return jsonstring
40*a34c030eSBrad Bishop
41eb8dc403SDave Cobbleypython errorreport_handler () {
42eb8dc403SDave Cobbley        import json
43eb8dc403SDave Cobbley        import codecs
44eb8dc403SDave Cobbley
45eb8dc403SDave Cobbley        def nativelsb():
46eb8dc403SDave Cobbley            nativelsbstr = e.data.getVar("NATIVELSBSTRING")
47eb8dc403SDave Cobbley            # provide a bit more host info in case of uninative build
48eb8dc403SDave Cobbley            if e.data.getVar('UNINATIVE_URL') != 'unset':
49eb8dc403SDave Cobbley                return '/'.join([nativelsbstr, lsb_distro_identifier(e.data)])
50eb8dc403SDave Cobbley            return nativelsbstr
51eb8dc403SDave Cobbley
52eb8dc403SDave Cobbley        logpath = e.data.getVar('ERR_REPORT_DIR')
53eb8dc403SDave Cobbley        datafile = os.path.join(logpath, "error-report.txt")
54eb8dc403SDave Cobbley
55eb8dc403SDave Cobbley        if isinstance(e, bb.event.BuildStarted):
56eb8dc403SDave Cobbley            bb.utils.mkdirhier(logpath)
57eb8dc403SDave Cobbley            data = {}
58eb8dc403SDave Cobbley            machine = e.data.getVar("MACHINE")
59eb8dc403SDave Cobbley            data['machine'] = machine
60eb8dc403SDave Cobbley            data['build_sys'] = e.data.getVar("BUILD_SYS")
61eb8dc403SDave Cobbley            data['nativelsb'] = nativelsb()
62eb8dc403SDave Cobbley            data['distro'] = e.data.getVar("DISTRO")
63eb8dc403SDave Cobbley            data['target_sys'] = e.data.getVar("TARGET_SYS")
64eb8dc403SDave Cobbley            data['failures'] = []
65eb8dc403SDave Cobbley            data['component'] = " ".join(e.getPkgs())
66eb8dc403SDave Cobbley            data['branch_commit'] = str(base_detect_branch(e.data)) + ": " + str(base_detect_revision(e.data))
67*a34c030eSBrad Bishop            data['local_conf'] = get_conf_data(e, 'local.conf')
68*a34c030eSBrad Bishop            data['auto_conf'] = get_conf_data(e, 'auto.conf')
69eb8dc403SDave Cobbley            lock = bb.utils.lockfile(datafile + '.lock')
70eb8dc403SDave Cobbley            errorreport_savedata(e, data, "error-report.txt")
71eb8dc403SDave Cobbley            bb.utils.unlockfile(lock)
72eb8dc403SDave Cobbley
73eb8dc403SDave Cobbley        elif isinstance(e, bb.build.TaskFailed):
74eb8dc403SDave Cobbley            task = e.task
75eb8dc403SDave Cobbley            taskdata={}
76eb8dc403SDave Cobbley            log = e.data.getVar('BB_LOGFILE')
77eb8dc403SDave Cobbley            taskdata['package'] = e.data.expand("${PF}")
78eb8dc403SDave Cobbley            taskdata['task'] = task
79eb8dc403SDave Cobbley            if log:
80eb8dc403SDave Cobbley                try:
81eb8dc403SDave Cobbley                    logFile = codecs.open(log, 'r', 'utf-8')
82eb8dc403SDave Cobbley                    logdata = logFile.read()
83eb8dc403SDave Cobbley
84eb8dc403SDave Cobbley                    # Replace host-specific paths so the logs are cleaner
85eb8dc403SDave Cobbley                    for d in ("TOPDIR", "TMPDIR"):
86eb8dc403SDave Cobbley                        s = e.data.getVar(d)
87eb8dc403SDave Cobbley                        if s:
88eb8dc403SDave Cobbley                            logdata = logdata.replace(s, d)
89eb8dc403SDave Cobbley
90eb8dc403SDave Cobbley                    logFile.close()
91eb8dc403SDave Cobbley                except:
92eb8dc403SDave Cobbley                    logdata = "Unable to read log file"
93eb8dc403SDave Cobbley
94eb8dc403SDave Cobbley            else:
95eb8dc403SDave Cobbley                logdata = "No Log"
96eb8dc403SDave Cobbley
97eb8dc403SDave Cobbley            # server will refuse failures longer than param specified in project.settings.py
98eb8dc403SDave Cobbley            # MAX_UPLOAD_SIZE = "5242880"
99eb8dc403SDave Cobbley            # use lower value, because 650 chars can be spent in task, package, version
100eb8dc403SDave Cobbley            max_logdata_size = 5242000
101eb8dc403SDave Cobbley            # upload last max_logdata_size characters
102eb8dc403SDave Cobbley            if len(logdata) > max_logdata_size:
103eb8dc403SDave Cobbley                logdata = "..." + logdata[-max_logdata_size:]
104eb8dc403SDave Cobbley            taskdata['log'] = logdata
105eb8dc403SDave Cobbley            lock = bb.utils.lockfile(datafile + '.lock')
106eb8dc403SDave Cobbley            jsondata = json.loads(errorreport_getdata(e))
107eb8dc403SDave Cobbley            jsondata['failures'].append(taskdata)
108eb8dc403SDave Cobbley            errorreport_savedata(e, jsondata, "error-report.txt")
109eb8dc403SDave Cobbley            bb.utils.unlockfile(lock)
110eb8dc403SDave Cobbley
111eb8dc403SDave Cobbley        elif isinstance(e, bb.event.BuildCompleted):
112eb8dc403SDave Cobbley            lock = bb.utils.lockfile(datafile + '.lock')
113eb8dc403SDave Cobbley            jsondata = json.loads(errorreport_getdata(e))
114eb8dc403SDave Cobbley            bb.utils.unlockfile(lock)
115eb8dc403SDave Cobbley            failures = jsondata['failures']
116eb8dc403SDave Cobbley            if(len(failures) > 0):
117eb8dc403SDave Cobbley                filename = "error_report_" + e.data.getVar("BUILDNAME")+".txt"
118eb8dc403SDave Cobbley                datafile = errorreport_savedata(e, jsondata, filename)
119eb8dc403SDave 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))
120eb8dc403SDave 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.")
121eb8dc403SDave Cobbley}
122eb8dc403SDave Cobbley
123eb8dc403SDave Cobbleyaddhandler errorreport_handler
124eb8dc403SDave Cobbleyerrorreport_handler[eventmask] = "bb.event.BuildStarted bb.event.BuildCompleted bb.build.TaskFailed"
125