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