CI: support configurable stats files in AnalyzeRTStats_Object

Allow XML test cases to specify one or more files with timing stats that
define which container log paths to collect and analyze. AnalyzeRTStatsObject
loops over the provided list, falling back to the default gNB files
(nrL1_stats.log, nrMAC_stats.log) when none are specified.

Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
This commit is contained in:
Jaroslava Fiedlerova
2026-06-15 11:08:24 +02:00
parent f3589d97c2
commit 9fd43efaf2
7 changed files with 22 additions and 11 deletions

View File

@@ -95,13 +95,13 @@ class Analysis():
test_summary['Nbfail'] = nb_failed
return nb_failed == 0, test_summary, test_result
def analyze_rt_stats(thresholds, L1_stats, MAC_stats):
def analyze_rt_stats(thresholds, stat_files):
with open(thresholds, 'r') as f:
datalog_rt_stats = yaml.load(f, Loader=yaml.FullLoader)
rt_keys = datalog_rt_stats['Ref']
real_time_stats = {}
for sf in [L1_stats, MAC_stats]:
for sf in stat_files:
with open(sf, 'r') as f:
for line in f.readlines():
for k in rt_keys:

View File

@@ -644,7 +644,7 @@ class Containerize():
logging.error('\u001B[1m Undeploying objects Failed\u001B[0m')
return success
def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds, service=None):
def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds, service=None, stats_files=None):
logging.info(f'Analyzing realtime stats from server: {node}')
yaml = self.yamlPath.strip('/')
wd = f'{self.workspace}/{yaml}'
@@ -660,12 +660,20 @@ class Containerize():
raise RuntimeError(f"Requested service {s} not found among services: {deployed_services}")
logging.info(f"Analyzing deployed service '{s}'")
# similar to BuildRunTests(), use docker cp to avoid problems with permissions
cmd.run(f'docker compose -f {wd_yaml} cp {s}:/opt/oai-gnb/nrL1_stats.log {wd}/')
l1_file = archiveArtifact(cmd, ctx, f"{wd}/nrL1_stats.log")
cmd.run(f'docker compose -f {wd_yaml} cp {s}:/opt/oai-gnb/nrMAC_stats.log {wd}/')
mac_file = archiveArtifact(cmd, ctx, f"{wd}/nrMAC_stats.log")
local_files = []
for sf in stats_files:
basename = os.path.basename(sf)
ret = cmd.run(f'docker compose -f {wd_yaml} cp {s}:{sf} {wd}/')
if ret.returncode != 0:
logging.error(f"Cannot retrieve {s}:{sf}")
return False
file = archiveArtifact(cmd, ctx, f"{wd}/{basename}")
if not file:
logging.error(f"Cannot retrieve file {basename}")
return False
local_files.append(file)
logging.info(f"check against thresholds from {thresholds}")
success, datalog_rt_stats = cls_analysis.Analysis.analyze_rt_stats(thresholds, l1_file, mac_file)
success, datalog_rt_stats = cls_analysis.Analysis.analyze_rt_stats(thresholds, local_files)
HTML.CreateHtmlDataLogTable(datalog_rt_stats)
return success

View File

@@ -245,7 +245,8 @@ def ExecuteActionWithParam(action, ctx, node):
elif action == 'AnalyzeRTStats_Object':
yaml = test.findtext('stats_cfg')
service = test.findtext('service')
success = CONTAINERS.AnalyzeRTStatsObject(HTML, node, ctx, yaml, service)
stats_files = (test.findtext('stats_file') or '').split()
success = CONTAINERS.AnalyzeRTStatsObject(HTML, node, ctx, yaml, service, stats_files)
else:
logging.warning(f"unknown action {action}, skip step")

View File

@@ -145,6 +145,6 @@ class RANManagement():
mac_file = archiveArtifact(cmd, ctx, f"{logdir}/nrMAC_stats.log")
logging.info(f"check against thresholds from {thresholds}")
success, datalog_rt_stats = cls_analysis.Analysis.analyze_rt_stats(thresholds, l1_file, mac_file)
success, datalog_rt_stats = cls_analysis.Analysis.analyze_rt_stats(thresholds, [l1_file, mac_file])
HTML.CreateHtmlDataLogTable(datalog_rt_stats)
return success

View File

@@ -26,7 +26,7 @@ class TestAnalysis(unittest.TestCase):
rtsf = "datalog_rt_stats.100.2x2.yaml"
l1f = "tests/analysis/gnb_phytest.success.nrL1.log"
macf = "tests/analysis/gnb_phytest.success.nrMAC.log"
status, s = cls_analysis.Analysis.analyze_rt_stats(rtsf, l1f, macf)
status, s = cls_analysis.Analysis.analyze_rt_stats(rtsf, [l1f, macf])
self.assertTrue(status)
self.assertEqual(s['Title'], "Processing Time (us) from datalog_rt_stats.100.2x2.yaml")
self.assertEqual(s['ColNames'], ["Metric", "Average; Max; Count", "Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold)"])

View File

@@ -36,6 +36,7 @@
<desc>Analyze Real-Time Stats</desc>
<stats_cfg>datalog_rt_stats.100.4x4.fhi72.yaml</stats_cfg>
<service>oai-gnb</service>
<stats_file>/opt/oai-gnb/nrL1_stats.log /opt/oai-gnb/nrMAC_stats.log</stats_file>
<node>bulbul</node>
</testCase>

View File

@@ -44,6 +44,7 @@
<desc>Analyze Real-Time Stats</desc>
<stats_cfg>datalog_rt_stats.100.2x2.fhi72.cacofonix.yaml</stats_cfg>
<service>oai-gnb</service>
<stats_file>/opt/oai-gnb/nrL1_stats.log /opt/oai-gnb/nrMAC_stats.log</stats_file>
<node>cacofonix</node>
</testCase>