report: indexed error message added to report emails 98/32898/22
authorViliam Luc <vluc@cisco.com>
Fri, 25 Jun 2021 08:05:28 +0000 (10:05 +0200)
committerTibor Frank <tifrank@cisco.com>
Wed, 11 Aug 2021 06:00:45 +0000 (06:00 +0000)
Report emails will contain error message index now.
Index assigned to error message is described at the end of report.

sample:
avf-dot1q-l2bdbasemaclrn-eth-2memif-1dcr                               25ge2p1xxv710  64b   2t1c[0] 4t2c[0] 8t4c[0]

Legend:

[0] - Failed to run 'cli_inband clear runtime' PAPI command on host xxx.xxx.xxx.xxx

Signed-off-by: Viliam Luc <vluc@cisco.com>
Change-Id: I6c71eb8a8767827e18f88a9a1142b899158a190c

resources/tools/presentation/generator_alerts.py
resources/tools/presentation/generator_tables.py
resources/tools/presentation/specifications/trending/elements.yaml

index 4dd78fe..9a0a03a 100644 (file)
@@ -22,10 +22,11 @@ import smtplib
 import logging
 import re
 
 import logging
 import re
 
+from difflib import SequenceMatcher
 from email.mime.text import MIMEText
 from email.mime.multipart import MIMEMultipart
 from os.path import isdir
 from email.mime.text import MIMEText
 from email.mime.multipart import MIMEMultipart
 from os.path import isdir
-from collections import OrderedDict
+from collections import OrderedDict, defaultdict
 
 from pal_errors import PresentationError
 
 
 from pal_errors import PresentationError
 
@@ -80,12 +81,14 @@ class Alerting:
 
         self._spec = spec
 
 
         self._spec = spec
 
+        self.error_msgs = list()
+
         try:
             self._spec_alert = spec.alerting
         except KeyError as err:
         try:
             self._spec_alert = spec.alerting
         except KeyError as err:
-            raise AlertingError(u"Alerting is not configured, skipped.",
-                                repr(err),
-                                u"WARNING")
+            raise AlertingError(
+                u"Alerting is not configured, skipped.", repr(err), u"WARNING"
+            )
 
         self._path_failed_tests = spec.environment[u"paths"][u"DIR[STATIC,VPP]"]
 
 
         self._path_failed_tests = spec.environment[u"paths"][u"DIR[STATIC,VPP]"]
 
@@ -250,7 +253,7 @@ class Alerting:
         """
 
         directory = self.configs[alert[u"way"]][u"output-dir"]
         """
 
         directory = self.configs[alert[u"way"]][u"output-dir"]
-        failed_tests = OrderedDict()
+        failed_tests = defaultdict(dict)
         file_path = f"{directory}/{test_set}.txt"
         version = u""
         try:
         file_path = f"{directory}/{test_set}.txt"
         version = u""
         try:
@@ -273,20 +276,42 @@ class Alerting:
                         duration = f"{(minutes // 60):02d}:{(minutes % 60):02d}"
                         continue
                     try:
                         duration = f"{(minutes // 60):02d}:{(minutes % 60):02d}"
                         continue
                     try:
-                        test = line[:-1].split(u'-')
+                        line, error_msg = line[:-1].split(u'###', maxsplit=1)
+                        test = line.split(u'-')
                         name = u'-'.join(test[3:-1])
                         name = u'-'.join(test[3:-1])
-                    except IndexError:
+                    except ValueError:
                         continue
                         continue
-                    if failed_tests.get(name, None) is None:
-                        failed_tests[name] = dict(nics=list(),
-                                                  framesizes=list(),
-                                                  cores=list())
-                    if test[0] not in failed_tests[name][u"nics"]:
-                        failed_tests[name][u"nics"].append(test[0])
-                    if test[1] not in failed_tests[name][u"framesizes"]:
-                        failed_tests[name][u"framesizes"].append(test[1])
-                    if test[2] not in failed_tests[name][u"cores"]:
-                        failed_tests[name][u"cores"].append(test[2])
+
+                    for e_msg in self.error_msgs:
+                        if SequenceMatcher(None, e_msg,
+                                           error_msg).ratio() > 0.5:
+                            error_msg = e_msg
+                            break
+                    if error_msg not in self.error_msgs:
+                        self.error_msgs.append(error_msg)
+
+                    error_msg_index = self.error_msgs.index(error_msg)
+
+                    if failed_tests.get(name, {}).get(error_msg_index) is None:
+                        failed_tests[name][error_msg_index] = \
+                            dict(nics=list(),
+                                 framesizes=list(),
+                                 cores=list())
+
+                    if test[0] not in \
+                            failed_tests[name][error_msg_index][u"nics"]:
+                        failed_tests[name][error_msg_index][u"nics"].\
+                            append(test[0])
+                    if test[1] not in \
+                            failed_tests[name][error_msg_index][u"framesizes"]:
+                        failed_tests[name][error_msg_index][u"framesizes"].\
+                            append(test[1])
+                    check_core = test[2] + f"[{str(error_msg_index)}]"
+                    if check_core not in \
+                            failed_tests[name][error_msg_index][u"cores"]:
+                        failed_tests[name][error_msg_index][u"cores"].\
+                            append(test[2] + "[" + str(error_msg_index) + "]")
+
         except IOError:
             logging.error(f"No such file or directory: {file_path}")
             return None, None, None, None, None, None
         except IOError:
             logging.error(f"No such file or directory: {file_path}")
             return None, None, None, None, None, None
@@ -404,31 +429,46 @@ class Alerting:
 
             max_len = MaxLens(0, 0, 0, 0)
 
 
             max_len = MaxLens(0, 0, 0, 0)
 
-            for name, params in failed_tests.items():
-                failed_tests[name][u"nics"] = u",".join(sorted(params[u"nics"]))
-                failed_tests[name][u"framesizes"] = \
-                    u",".join(sorted(params[u"framesizes"]))
-                failed_tests[name][u"cores"] = \
-                    u",".join(sorted(params[u"cores"]))
-                if len(name) > max_len.name:
-                    max_len.name = len(name)
-                if len(failed_tests[name][u"nics"]) > max_len.nics:
-                    max_len.nics = len(failed_tests[name][u"nics"])
-                if len(failed_tests[name][u"framesizes"]) > max_len.frmsizes:
-                    max_len.frmsizes = len(failed_tests[name][u"framesizes"])
-                if len(failed_tests[name][u"cores"]) > max_len.cores:
-                    max_len.cores = len(failed_tests[name][u"cores"])
-
-            for name, params in failed_tests.items():
-                text += (
-                    f"{name + u' ' * (max_len.name - len(name))}  "
-                    f"{params[u'nics']}"
-                    f"{u' ' * (max_len.nics - len(params[u'nics']))}  "
-                    f"{params[u'framesizes']}"
-                    f"{u' ' * (max_len.frmsizes-len(params[u'framesizes']))}  "
-                    f"{params[u'cores']}"
-                    f"{u' ' * (max_len.cores - len(params[u'cores']))}\n"
-                )
+            for test, message in failed_tests.items():
+                for e_message, params in message.items():
+                    failed_tests[test][e_message][u"nics"] = \
+                        u" ".join(sorted(params[u"nics"]))
+                    failed_tests[test][e_message][u"framesizes"] = \
+                        u" ".join(sorted(params[u"framesizes"]))
+                    failed_tests[test][e_message][u"cores"] = \
+                        u" ".join(sorted(params[u"cores"]))
+                    if len(test) > max_len.name:
+                        max_len.name = len(test)
+                    if len(failed_tests[test][e_message][u"nics"]) > \
+                            max_len.nics:
+                        max_len.nics = \
+                            len(failed_tests[test][e_message][u"nics"])
+                    if len(failed_tests[test][e_message][u"framesizes"]) > \
+                            max_len.frmsizes:
+                        max_len.frmsizes = \
+                            len(failed_tests[test][e_message][u"framesizes"])
+                    if len(failed_tests[test][e_message][u"cores"]) > \
+                            max_len.cores:
+                        max_len.cores = \
+                            len(failed_tests[test][e_message][u"cores"])
+
+            for test, message in failed_tests.items():
+                test_added = False
+                for e_message, params in message.items():
+                    if not test_added:
+                        test_added = True
+                    else:
+                        test = ""
+                    text += (
+                        f"{test + u' ' * (max_len.name - len(test))}  "
+                        f"{params[u'nics']}"
+                        f"{u' ' * (max_len.nics - len(params[u'nics']))}  "
+                        f"{params[u'framesizes']}"
+                        f"""{u' ' * (max_len.frmsizes
+                                     - len(params[u'framesizes']))}  """
+                        f"{params[u'cores']}"
+                        f"{u' ' * (max_len.cores - len(params[u'cores']))}\n"
+                    )
 
             gression_hdr = (
                 f"\n\n{test_set_short}, "
 
             gression_hdr = (
                 f"\n\n{test_set_short}, "
@@ -446,6 +486,11 @@ class Alerting:
                     f"{self.configs[alert[u'way']][u'output-file']}"
         logging.info(f"Writing the file {file_name}.txt ...")
 
                     f"{self.configs[alert[u'way']][u'output-file']}"
         logging.info(f"Writing the file {file_name}.txt ...")
 
+        text += f"\n\nLegend:\n\n"
+
+        for e_msg in self.error_msgs:
+            text += f"[{self.error_msgs.index(e_msg)}] - {e_msg}\n"
+
         try:
             with open(f"{file_name}.txt", u'w') as txt_file:
                 txt_file.write(text)
         try:
             with open(f"{file_name}.txt", u'w') as txt_file:
                 txt_file.write(text)
index 351250a..8b88a52 100644 (file)
@@ -25,7 +25,6 @@ from xml.etree import ElementTree as ET
 from datetime import datetime as dt
 from datetime import timedelta
 from copy import deepcopy
 from datetime import datetime as dt
 from datetime import timedelta
 from copy import deepcopy
-from json import loads
 
 import plotly.graph_objects as go
 import plotly.offline as ploff
 
 import plotly.graph_objects as go
 import plotly.offline as ploff
@@ -1375,7 +1374,11 @@ def table_last_failed_tests(table, input_data):
                 if not groups:
                     continue
                 nic = groups.group(0)
                 if not groups:
                     continue
                 nic = groups.group(0)
-                failed_tests.append(f"{nic}-{tst_data[u'name']}")
+                msg = tst_data[u'msg'].replace(u"\n", u"")
+                msg = re.sub(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})',
+                             'xxx.xxx.xxx.xxx', msg)
+                msg = msg.split(u'Also teardown failed')[0]
+                failed_tests.append(f"{nic}-{tst_data[u'name']}###{msg}")
             tbl_list.append(passed)
             tbl_list.append(failed)
             tbl_list.append(duration)
             tbl_list.append(passed)
             tbl_list.append(failed)
             tbl_list.append(duration)
index b0baa74..ca1ba6b 100644 (file)
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-skx"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-skx"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-clx"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-clx"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-zn2"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-zn2"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 3n-tsh"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 3n-tsh"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-tx2"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-tx2"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 3n-dnv"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 3n-dnv"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-dnv"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-dnv"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 3n-skx-ndrpdr"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 3n-skx-ndrpdr"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-skx-ndrpdr"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-skx-ndrpdr"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-clx-ndrpdr"
 
 - type: "table"
   title: "Last failed tests (last builds) VPP 2n-clx-ndrpdr"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) DPDK 3n-tsh"
 
 - type: "table"
   title: "Last failed tests (last builds) DPDK 3n-tsh"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) DPDK 2n-tx2"
 
 - type: "table"
   title: "Last failed tests (last builds) DPDK 2n-tx2"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) DPDK 3n-skx"
 
 - type: "table"
   title: "Last failed tests (last builds) DPDK 3n-skx"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) DPDK 2n-skx"
 
 - type: "table"
   title: "Last failed tests (last builds) DPDK 2n-skx"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 - type: "table"
   title: "Last failed tests (last builds) DPDK 2n-clx"
 
 - type: "table"
   title: "Last failed tests (last builds) DPDK 2n-clx"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
 
 # 3n-skx
 - type: "table"
 
 # 3n-skx
 - type: "table"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
   window: 7  # days
 
 - type: "table"
   window: 7  # days
 
 - type: "table"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
   window: 30  # days
 
 - type: "table"
   window: 30  # days
 
 - type: "table"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
   window: 7  # days
 
 - type: "table"
   window: 7  # days
 
 - type: "table"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
   window: 30  # days
 
 - type: "table"
   window: 30  # days
 
 - type: "table"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
   window: 7  # days
 
 - type: "table"
   window: 7  # days
 
 - type: "table"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
   window: 30  # days
 
 - type: "table"
   window: 30  # days
 
 - type: "table"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
   window: 7  # days
 
 - type: "table"
   window: 7  # days
 
 - type: "table"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
   window: 7  # days
 
 - type: "table"
   window: 7  # days
 
 - type: "table"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
   window: 7  # days
 
 - type: "table"
   window: 7  # days
 
 - type: "table"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
   window: 7  # days
 
 - type: "table"
   window: 7  # days
 
 - type: "table"
     - "name"
     - "parent"
     - "status"
     - "name"
     - "parent"
     - "status"
+    - "msg"
   window: 7  # days
 
 - type: "table"
   window: 7  # days
 
 - type: "table"