diff --git a/runbot/models/build_error.py b/runbot/models/build_error.py index 26751eeb..7ad43201 100644 --- a/runbot/models/build_error.py +++ b/runbot/models/build_error.py @@ -409,27 +409,26 @@ class BuildError(models.Model): build_error_contents = self.env['runbot.build.error.content'] # add build ids to already detected errors existing_errors_contents = self.env['runbot.build.error.content'].search([('fingerprint', 'in', list(hash_dict.keys())), ('error_id.active', '=', True)]) - existing_fingerprints = existing_errors_contents.mapped('fingerprint') + existing_fingerprints = {error.fingerprint: error for error in existing_errors_contents} build_error_contents |= existing_errors_contents - # for build_error_content in existing_errors_contents: - # logs = hash_dict[build_error_content.fingerprint] - # # update filepath if it changed. This is optionnal and mainly there in case we adapt the OdooRunner log - # if logs[0].path != build_error_content.file_path: - # build_error_content.file_path = logs[0].path - # build_error_content.function = logs[0].func - # create an error for the remaining entries for fingerprint, logs in hash_dict.items(): if fingerprint in existing_fingerprints: + # metadata update, keep this for a while + error = existing_fingerprints[fingerprint] + if not error.metadata and logs[0].metadata: + error.metadata = logs[0].metadata + continue new_build_error_content = self.env['runbot.build.error.content'].create({ 'content': logs[0].message, 'module_name': logs[0].name.removeprefix('odoo.').removeprefix('addons.'), 'file_path': logs[0].path, 'function': logs[0].func, + 'metadata': logs[0].metadata, }) build_error_contents |= new_build_error_content - existing_fingerprints.append(fingerprint) + existing_fingerprints[fingerprint] = new_build_error_content for build_error_content in build_error_contents: logs = hash_dict[build_error_content.fingerprint] @@ -474,6 +473,7 @@ class BuildErrorContent(models.Model): error_display_id = fields.Integer(compute='_compute_error_display_id', string="Error id") content = fields.Text('Error message', required=True) cleaned_content = fields.Text('Cleaned error message') + metadata = JsonDictField('Metadata') summary = fields.Char('Content summary', compute='_compute_summary', store=False) module_name = fields.Char('Module name') # name in ir_logging file_path = fields.Char('File Path') # path in ir logging diff --git a/runbot/models/host.py b/runbot/models/host.py index 033a0964..ea46f6e3 100644 --- a/runbot/models/host.py +++ b/runbot/models/host.py @@ -94,10 +94,21 @@ class Host(models.Model): path character varying NOT NULL, line character varying NOT NULL, type character varying NOT NULL, + metadata jsonb, message text NOT NULL); """) except Exception as e: _logger.exception('Failed to create local logs database: %s', e) + else: + # TODO cleanup remove in 20.0 + with local_pg_cursor(logs_db_name) as local_cr: + local_cr.execute("""SELECT 1 + FROM information_schema.columns + WHERE table_name='ir_logging' and column_name='metadata'""") + if not local_cr.fetchone(): + _logger.info('Adding metadata column to ir_logging table') + local_cr.execute("""ALTER TABLE ir_logging ADD COLUMN metadata jsonb""") + def _bootstrap_db_template(self): """ boostrap template database if needed """ @@ -237,7 +248,7 @@ class Host(models.Model): query = f""" SELECT * FROM ( - SELECT id, create_date, name, level, dbname, func, path, line, type, message, split_part(dbname, '-', 1) as build_id + SELECT id, create_date, name, level, dbname, func, path, line, type, message, split_part(dbname, '-', 1) as build_id, metadata FROM ir_logging ) AS ir_logs diff --git a/runbot/models/ir_logging.py b/runbot/models/ir_logging.py index c7d1194b..dc625738 100644 --- a/runbot/models/ir_logging.py +++ b/runbot/models/ir_logging.py @@ -5,6 +5,7 @@ import logging from collections import defaultdict from ..common import pseudo_markdown +from ..fields import JsonDictField from odoo import models, fields, tools, api from odoo.exceptions import UserError from odoo.tools import html_escape @@ -24,6 +25,7 @@ class IrLogging(models.Model): type = fields.Selection(selection_add=TYPES, string='Type', required=True, index=True, ondelete={t[0]: 'cascade' for t in TYPES}) error_content_id = fields.Many2one('runbot.build.error.content', compute='_compute_known_error') # remember to never store this field dbname = fields.Char(string='Database Name', index=False) + metadata = JsonDictField('Metadata') @api.model_create_multi def create(self, vals_list): diff --git a/runbot/views/build_error_views.xml b/runbot/views/build_error_views.xml index 7aaec957..0e11dc17 100644 --- a/runbot/views/build_error_views.xml +++ b/runbot/views/build_error_views.xml @@ -221,6 +221,7 @@ +