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 28a34c030eSBrad Bishopdef get_conf_data(e, filename): 29a34c030eSBrad Bishop builddir = e.data.getVar('TOPDIR') 30a34c030eSBrad Bishop filepath = os.path.join(builddir, "conf", filename) 31a34c030eSBrad Bishop jsonstring = "" 32a34c030eSBrad Bishop if os.path.exists(filepath): 33a34c030eSBrad Bishop with open(filepath, 'r') as f: 34a34c030eSBrad Bishop for line in f.readlines(): 35a34c030eSBrad Bishop if line.startswith("#") or len(line.strip()) == 0: 36a34c030eSBrad Bishop continue 37a34c030eSBrad Bishop else: 38a34c030eSBrad Bishop jsonstring=jsonstring + line 39a34c030eSBrad Bishop return jsonstring 40a34c030eSBrad 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)) 67a34c030eSBrad Bishop data['local_conf'] = get_conf_data(e, 'local.conf') 68a34c030eSBrad 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: 81*64c979e8SBrad Bishop with codecs.open(log, encoding='utf-8') as logFile: 82eb8dc403SDave Cobbley logdata = logFile.read() 83eb8dc403SDave Cobbley # Replace host-specific paths so the logs are cleaner 84eb8dc403SDave Cobbley for d in ("TOPDIR", "TMPDIR"): 85eb8dc403SDave Cobbley s = e.data.getVar(d) 86eb8dc403SDave Cobbley if s: 87eb8dc403SDave Cobbley logdata = logdata.replace(s, d) 88eb8dc403SDave Cobbley except: 89eb8dc403SDave Cobbley logdata = "Unable to read log file" 90eb8dc403SDave Cobbley else: 91eb8dc403SDave Cobbley logdata = "No Log" 92eb8dc403SDave Cobbley 93eb8dc403SDave Cobbley # server will refuse failures longer than param specified in project.settings.py 94eb8dc403SDave Cobbley # MAX_UPLOAD_SIZE = "5242880" 95eb8dc403SDave Cobbley # use lower value, because 650 chars can be spent in task, package, version 96eb8dc403SDave Cobbley max_logdata_size = 5242000 97eb8dc403SDave Cobbley # upload last max_logdata_size characters 98eb8dc403SDave Cobbley if len(logdata) > max_logdata_size: 99eb8dc403SDave Cobbley logdata = "..." + logdata[-max_logdata_size:] 100eb8dc403SDave Cobbley taskdata['log'] = logdata 101eb8dc403SDave Cobbley lock = bb.utils.lockfile(datafile + '.lock') 102eb8dc403SDave Cobbley jsondata = json.loads(errorreport_getdata(e)) 103eb8dc403SDave Cobbley jsondata['failures'].append(taskdata) 104eb8dc403SDave Cobbley errorreport_savedata(e, jsondata, "error-report.txt") 105eb8dc403SDave Cobbley bb.utils.unlockfile(lock) 106eb8dc403SDave Cobbley 107eb8dc403SDave Cobbley elif isinstance(e, bb.event.BuildCompleted): 108eb8dc403SDave Cobbley lock = bb.utils.lockfile(datafile + '.lock') 109eb8dc403SDave Cobbley jsondata = json.loads(errorreport_getdata(e)) 110eb8dc403SDave Cobbley bb.utils.unlockfile(lock) 111eb8dc403SDave Cobbley failures = jsondata['failures'] 112eb8dc403SDave Cobbley if(len(failures) > 0): 113eb8dc403SDave Cobbley filename = "error_report_" + e.data.getVar("BUILDNAME")+".txt" 114eb8dc403SDave Cobbley datafile = errorreport_savedata(e, jsondata, filename) 115eb8dc403SDave 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)) 116eb8dc403SDave 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.") 117eb8dc403SDave Cobbley} 118eb8dc403SDave Cobbley 119eb8dc403SDave Cobbleyaddhandler errorreport_handler 120eb8dc403SDave Cobbleyerrorreport_handler[eventmask] = "bb.event.BuildStarted bb.event.BuildCompleted bb.build.TaskFailed" 121