def item(problem_id, component_names=None): components_form = ProblemComponents() problem = db.session.query(Problem).filter( Problem.id == problem_id).first() if problem is None: raise abort(404) if component_names: try: (db.session.query(ProblemComponent).filter_by( problem_id=problem_id).delete()) for index, comp_name in enumerate(component_names.split(',')): component = (db.session.query(OpSysComponent).filter_by( name=comp_name).first()) if not component: raise ValueError( "Component {} not found.".format(comp_name)) db.session.add( ProblemComponent(problem_id=problem.id, component_id=component.id, order=index + 1)) reassign = (db.session.query(ProblemReassign).filter_by( problem_id=problem_id).first()) if reassign is None: reassign = ProblemReassign(problem_id=problem_id) reassign.date = datetime.date.today() reassign.username = g.user.username db.session.add(reassign) db.session.commit() except SQLAlchemyError: db.session.rollback() flash("Database transaction error.", 'error') except ValueError as e: db.session.rollback() flash(str(e), 'error') report_ids = [report.id for report in problem.reports] solutions = [] equal_solution = lambda s: [x for x in solutions if s.cause == x.cause] for report in problem.reports: if report.max_certainty is not None: osr = get_report_opsysrelease(db=db, report_id=report.id) solution = find_solution(report, db=db, osr=osr) if solution and not equal_solution(solution): solutions.append(solution) sub = (db.session.query( ReportOpSysRelease.opsysrelease_id, func.sum(ReportOpSysRelease.count).label("cnt")).join(Report).filter( Report.id.in_(report_ids)).group_by( ReportOpSysRelease.opsysrelease_id).subquery()) osreleases = (db.session.query(OpSysRelease, sub.c.cnt).join(sub).order_by( desc("cnt")).all()) sub = (db.session.query( ReportArch.arch_id, func.sum(ReportArch.count).label("cnt")).join(Report).filter( Report.id.in_(report_ids)).group_by(ReportArch.arch_id).subquery()) arches = (db.session.query(Arch, sub.c.cnt).join(sub).order_by( desc("cnt")).all()) exes = (db.session.query( ReportExecutable.path, func.sum(ReportExecutable.count).label("cnt")).join(Report).filter( Report.id.in_(report_ids)).group_by( ReportExecutable.path).order_by(desc("cnt")).all()) sub = (db.session.query( ReportPackage.installed_package_id, func.sum(ReportPackage.count).label("cnt")).join(Report).filter( Report.id.in_(report_ids)).group_by( ReportPackage.installed_package_id).subquery()) packages_known = db.session.query(Package, sub.c.cnt).join(sub).all() packages_unknown = (db.session.query( ReportUnknownPackage, ReportUnknownPackage.count).join(Report).filter( Report.id.in_(report_ids))).all() packages = packages_known + packages_unknown # creates a package_counts list with this structure: # [(package name, count, [(package version, count in the version)])] names = defaultdict(lambda: {"count": 0, "versions": defaultdict(int)}) for (pkg, cnt) in packages: names[pkg.name]["name"] = pkg.name names[pkg.name]["count"] += cnt names[pkg.name]["versions"][pkg.evr()] += cnt package_counts = [] for pkg in sorted(names.values(), key=itemgetter("count"), reverse=True): package_counts.append((pkg["name"], pkg["count"], sorted(pkg["versions"].items(), key=itemgetter(1), reverse=True))) for report in problem.reports: for backtrace in report.backtraces: fid = 0 for frame in backtrace.frames: fid += 1 frame.nice_order = fid bt_hashes = (db.session.query( ReportHash.hash).join(Report).join(Problem).filter( Problem.id == problem_id).distinct(ReportHash.hash).all()) forward = { "problem": problem, "osreleases": metric(osreleases), "arches": metric(arches), "exes": metric(exes), "package_counts": package_counts, "solutions": solutions, "components_form": components_form } if not bt_hashes: logger.warning("No backtrace hashes found for problem #%d", problem_id) else: # Generate a permalink for this problem. We do this by uniformly picking # (at most) 10 hashes from the list. This ensures the selected hashes are # more or less representative of the problem. k = min(len(bt_hashes), 10) # A hint of determinism in this uncertain world. r = random.Random(problem_id) hashes_sampled = r.sample(bt_hashes, k) permalink_query = "&".join("bth={}".format(bth) for (bth, ) in hashes_sampled) forward["permalink_query"] = permalink_query if request_wants_json(): return jsonify(forward) is_maintainer = is_problem_maintainer(db, g.user, problem) forward["is_maintainer"] = is_maintainer forward["extfafs"] = get_external_faf_instances(db) if report_ids: bt_diff_form = BacktraceDiffForm() bt_diff_form.lhs.choices = [(id, id) for id in report_ids] bt_diff_form.rhs.choices = bt_diff_form.lhs.choices forward['bt_diff_form'] = bt_diff_form return render_template("problems/item.html", **forward)
def item(problem_id, component_names=None): components_form = ProblemComponents() problem = db.session.query(Problem).filter( Problem.id == problem_id).first() if problem is None: raise abort(404) if component_names: try: (db.session.query(ProblemComponent) .filter_by(problem_id=problem_id) .delete()) for index, comp_name in enumerate(component_names.split(',')): component = (db.session.query(OpSysComponent) .filter_by(name=comp_name) .first()) if not component: raise ValueError("Component {} not found.".format( comp_name)) db.session.add(ProblemComponent(problem_id=problem.id, component_id=component.id, order=index + 1)) reassign = (db.session.query(ProblemReassign) .filter_by(problem_id=problem_id) .first()) if reassign is None: reassign = ProblemReassign(problem_id=problem_id) reassign.date = datetime.date.today() reassign.username = g.user.username db.session.add(reassign) db.session.commit() except SQLAlchemyError: db.session.rollback() flash("Database transaction error.", 'error') except ValueError as e: db.session.rollback() flash(str(e), 'error') report_ids = [report.id for report in problem.reports] solutions = [] equal_solution = lambda s: [x for x in solutions if s.cause == x.cause] for report in problem.reports: if report.max_certainty is not None: osr = get_report_opsysrelease(db=db, report_id=report.id) solution = find_solution(report, db=db, osr=osr) if solution and not equal_solution(solution): solutions.append(solution) sub = (db.session.query(ReportOpSysRelease.opsysrelease_id, func.sum(ReportOpSysRelease.count).label("cnt")) .join(Report) .filter(Report.id.in_(report_ids)) .group_by(ReportOpSysRelease.opsysrelease_id) .subquery()) osreleases = (db.session.query(OpSysRelease, sub.c.cnt) .join(sub) .order_by(desc("cnt")) .all()) sub = (db.session.query(ReportArch.arch_id, func.sum(ReportArch.count).label("cnt")) .join(Report) .filter(Report.id.in_(report_ids)) .group_by(ReportArch.arch_id) .subquery()) arches = (db.session.query(Arch, sub.c.cnt).join(sub) .order_by(desc("cnt")) .all()) exes = (db.session.query(ReportExecutable.path, func.sum(ReportExecutable.count).label("cnt")) .join(Report) .filter(Report.id.in_(report_ids)) .group_by(ReportExecutable.path) .order_by(desc("cnt")) .all()) sub = (db.session.query(ReportPackage.installed_package_id, func.sum(ReportPackage.count).label("cnt")) .join(Report) .filter(Report.id.in_(report_ids)) .group_by(ReportPackage.installed_package_id) .subquery()) packages_known = db.session.query(Package, sub.c.cnt).join(sub).all() packages_unknown = (db.session.query(ReportUnknownPackage, ReportUnknownPackage.count) .join(Report) .filter(Report.id.in_(report_ids))).all() packages = packages_known + packages_unknown # creates a package_counts list with this structure: # [(package name, count, [(package version, count in the version)])] names = defaultdict(lambda: {"count": 0, "versions": defaultdict(int)}) for (pkg, cnt) in packages: names[pkg.name]["name"] = pkg.name names[pkg.name]["count"] += cnt names[pkg.name]["versions"][pkg.evr()] += cnt package_counts = [] for pkg in sorted(names.values(), key=itemgetter("count"), reverse=True): package_counts.append(( pkg["name"], pkg["count"], sorted(pkg["versions"].items(), key=itemgetter(1), reverse=True))) for report in problem.reports: for backtrace in report.backtraces: fid = 0 for frame in backtrace.frames: fid += 1 frame.nice_order = fid bt_hashes = (db.session.query(ReportHash.hash) .join(Report) .join(Problem) .filter(Problem.id == problem_id) .distinct(ReportHash.hash).all()) # Limit to 10 bt_hashes (otherwise the URL can get too long) # Select the 10 hashes uniformly from the entire list to make sure it is a # good representation. (Slicing the 10 first could mean the 10 oldest # are selected which is not a good representation.) k = min(len(bt_hashes), 10) a = 0 d = len(bt_hashes)/float(k) bt_hashes_limited = [] for _ in range(k): bt_hashes_limited.append("bth=" + bt_hashes[int(a)][0]) a += d bt_hash_qs = "&".join(bt_hashes_limited) forward = {"problem": problem, "osreleases": metric(osreleases), "arches": metric(arches), "exes": metric(exes), "package_counts": package_counts, "bt_hash_qs": bt_hash_qs, "solutions": solutions, "components_form": components_form } if request_wants_json(): return jsonify(forward) is_maintainer = is_problem_maintainer(db, g.user, problem) forward["is_maintainer"] = is_maintainer forward["extfafs"] = get_external_faf_instances(db) if report_ids: bt_diff_form = BacktraceDiffForm() bt_diff_form.lhs.choices = [(id, id) for id in report_ids] bt_diff_form.rhs.choices = bt_diff_form.lhs.choices forward['bt_diff_form'] = bt_diff_form return render_template("problems/item.html", **forward)