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