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