blob: 1452513a66b7e66d825381331672b113cbb4dde0 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#
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#
Patrick Williams92b42cb2022-09-03 06:53:57 -05007# SPDX-License-Identifier: MIT
8#
Patrick Williamsc124f4f2015-09-15 14:41:29 -05009
10ERR_REPORT_DIR ?= "${LOG_DIR}/error-report"
11
12def errorreport_getdata(e):
Patrick Williamsf1e5d692016-03-30 15:21:19 -050013 import codecs
Brad Bishop6e60e8b2018-02-01 10:27:11 -050014 logpath = e.data.getVar('ERR_REPORT_DIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050015 datafile = os.path.join(logpath, "error-report.txt")
Patrick Williamsf1e5d692016-03-30 15:21:19 -050016 with codecs.open(datafile, 'r', 'utf-8') as f:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050017 data = f.read()
18 return data
19
20def errorreport_savedata(e, newdata, file):
21 import json
Patrick Williamsf1e5d692016-03-30 15:21:19 -050022 import codecs
Brad Bishop6e60e8b2018-02-01 10:27:11 -050023 logpath = e.data.getVar('ERR_REPORT_DIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050024 datafile = os.path.join(logpath, file)
Patrick Williamsf1e5d692016-03-30 15:21:19 -050025 with codecs.open(datafile, 'w', 'utf-8') as f:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050026 json.dump(newdata, f, indent=4, sort_keys=True)
27 return datafile
28
Brad Bishopa34c0302019-09-23 22:34:48 -040029def 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
Patrick Williams8e7b46e2023-05-01 14:19:06 -050042def get_common_data(e):
43 data = {}
44 data['machine'] = e.data.getVar("MACHINE")
45 data['build_sys'] = e.data.getVar("BUILD_SYS")
46 data['distro'] = e.data.getVar("DISTRO")
47 data['target_sys'] = e.data.getVar("TARGET_SYS")
48 data['branch_commit'] = str(oe.buildcfg.detect_branch(e.data)) + ": " + str(oe.buildcfg.detect_revision(e.data))
49 data['bitbake_version'] = e.data.getVar("BB_VERSION")
50 data['layer_version'] = get_layers_branch_rev(e.data)
51 data['local_conf'] = get_conf_data(e, 'local.conf')
52 data['auto_conf'] = get_conf_data(e, 'auto.conf')
53 return data
54
Patrick Williamsc124f4f2015-09-15 14:41:29 -050055python errorreport_handler () {
56 import json
Patrick Williamsf1e5d692016-03-30 15:21:19 -050057 import codecs
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058
Brad Bishopd7bf8c12018-02-25 22:55:05 -050059 def nativelsb():
60 nativelsbstr = e.data.getVar("NATIVELSBSTRING")
61 # provide a bit more host info in case of uninative build
62 if e.data.getVar('UNINATIVE_URL') != 'unset':
63 return '/'.join([nativelsbstr, lsb_distro_identifier(e.data)])
64 return nativelsbstr
65
Brad Bishop6e60e8b2018-02-01 10:27:11 -050066 logpath = e.data.getVar('ERR_REPORT_DIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050067 datafile = os.path.join(logpath, "error-report.txt")
68
69 if isinstance(e, bb.event.BuildStarted):
70 bb.utils.mkdirhier(logpath)
71 data = {}
Patrick Williams8e7b46e2023-05-01 14:19:06 -050072 data = get_common_data(e)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050073 data['nativelsb'] = nativelsb()
Patrick Williamsc124f4f2015-09-15 14:41:29 -050074 data['failures'] = []
Patrick Williamsc0f7c042017-02-23 20:41:17 -060075 data['component'] = " ".join(e.getPkgs())
Patrick Williamsc124f4f2015-09-15 14:41:29 -050076 lock = bb.utils.lockfile(datafile + '.lock')
77 errorreport_savedata(e, data, "error-report.txt")
78 bb.utils.unlockfile(lock)
79
80 elif isinstance(e, bb.build.TaskFailed):
81 task = e.task
82 taskdata={}
Brad Bishop6e60e8b2018-02-01 10:27:11 -050083 log = e.data.getVar('BB_LOGFILE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050084 taskdata['package'] = e.data.expand("${PF}")
85 taskdata['task'] = task
86 if log:
87 try:
Brad Bishop64c979e2019-11-04 13:55:29 -050088 with codecs.open(log, encoding='utf-8') as logFile:
89 logdata = logFile.read()
Patrick Williamsc0f7c042017-02-23 20:41:17 -060090 # Replace host-specific paths so the logs are cleaner
91 for d in ("TOPDIR", "TMPDIR"):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050092 s = e.data.getVar(d)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060093 if s:
94 logdata = logdata.replace(s, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050095 except:
96 logdata = "Unable to read log file"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050097 else:
98 logdata = "No Log"
99
100 # server will refuse failures longer than param specified in project.settings.py
101 # MAX_UPLOAD_SIZE = "5242880"
102 # use lower value, because 650 chars can be spent in task, package, version
103 max_logdata_size = 5242000
104 # upload last max_logdata_size characters
105 if len(logdata) > max_logdata_size:
106 logdata = "..." + logdata[-max_logdata_size:]
107 taskdata['log'] = logdata
108 lock = bb.utils.lockfile(datafile + '.lock')
109 jsondata = json.loads(errorreport_getdata(e))
110 jsondata['failures'].append(taskdata)
111 errorreport_savedata(e, jsondata, "error-report.txt")
112 bb.utils.unlockfile(lock)
113
Patrick Williams8e7b46e2023-05-01 14:19:06 -0500114 elif isinstance(e, bb.event.NoProvider):
115 bb.utils.mkdirhier(logpath)
116 data = {}
117 data = get_common_data(e)
118 data['nativelsb'] = nativelsb()
119 data['failures'] = []
120 data['component'] = str(e._item)
121 taskdata={}
122 taskdata['log'] = str(e)
123 taskdata['package'] = str(e._item)
124 taskdata['task'] = "Nothing provides " + "'" + str(e._item) + "'"
125 data['failures'].append(taskdata)
126 lock = bb.utils.lockfile(datafile + '.lock')
127 errorreport_savedata(e, data, "error-report.txt")
128 bb.utils.unlockfile(lock)
129
130 elif isinstance(e, bb.event.ParseError):
131 bb.utils.mkdirhier(logpath)
132 data = {}
133 data = get_common_data(e)
134 data['nativelsb'] = nativelsb()
135 data['failures'] = []
136 data['component'] = "parse"
137 taskdata={}
138 taskdata['log'] = str(e._msg)
139 taskdata['task'] = str(e._msg)
140 data['failures'].append(taskdata)
141 lock = bb.utils.lockfile(datafile + '.lock')
142 errorreport_savedata(e, data, "error-report.txt")
143 bb.utils.unlockfile(lock)
144
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500145 elif isinstance(e, bb.event.BuildCompleted):
146 lock = bb.utils.lockfile(datafile + '.lock')
147 jsondata = json.loads(errorreport_getdata(e))
148 bb.utils.unlockfile(lock)
149 failures = jsondata['failures']
150 if(len(failures) > 0):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500151 filename = "error_report_" + e.data.getVar("BUILDNAME")+".txt"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500152 datafile = errorreport_savedata(e, jsondata, filename)
153 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))
154 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.")
155}
156
157addhandler errorreport_handler
Patrick Williams8e7b46e2023-05-01 14:19:06 -0500158errorreport_handler[eventmask] = "bb.event.BuildStarted bb.event.BuildCompleted bb.build.TaskFailed bb.event.NoProvider bb.event.ParseError"