Commit 6fb3b11b authored by Paul Graydon's avatar Paul Graydon

amari.kpi: Add support for DRB.UEActive measurement

parent 3a35162b
......@@ -205,9 +205,9 @@ def _read(logm):
# _handle_stats handles next stats xlog entry upon _read request.
@func(LogMeasure)
def _handle_stats(logm, stats: xlog.Message, m_prev: kpi.Measurement):
# build Measurement from stats' counters.
# build Measurement from stats' statistical profiles and counters.
#
# we take δ(stats_prev, stat) and process it mapping Amarisoft counters to
# we take δ(stats_prev, stat) and process it, mapping Amarisoft counters to
# 3GPP ones specified by kpi.Measurement. This approach has following limitations:
#
# - for most of the counters there is no direct mapping in between
......@@ -260,6 +260,13 @@ def _handle_stats(logm, stats: xlog.Message, m_prev: kpi.Measurement):
# do init/fini correction if there was also third preceding stats message.
m = logm._m.copy() # [stats_prev, stats)
# cell_statt_profile returns the StatT statistical profile value triplet in stats
def cell_statt_profile(cell, statt_profile):
return tuple(
_stats_cell_sp_el(stats, cell, statt_profile + '_' + el)
for el in ['min', 'avg', 'max']
)
# δcc(counter) tells how specified global cumulative counter changed since last stats result.
def δcc(counter):
old = _stats_cc(stats_prev, counter)
......@@ -305,6 +312,30 @@ def _handle_stats(logm, stats: xlog.Message, m_prev: kpi.Measurement):
# compute δ for counters.
# any logic error in data will be reported via LogError.
try:
cells = set(stats['cells'].keys()) # NOTE cells are taken only from stats, not from stat_prev
# DRB: number of active UEs
#
# Aggregate statistical profile for all cells.
# While summing the averages is correct, it is impossible to compute
# an accurate value of the aggregate minimum and maximum across all cells.
# Summing them is the best approximation that will produce
# a wider interval containing the correct values, i.e.:
# Σ(minimums) <= min(Σ) and max(Σ) <= Σ(maximums)
# [ min, avg, max]
Σue_active_count = [None, None, None]
for cell in cells:
cell_ue_active_count = cell_statt_profile(cell, 'ue_active_count')
for i, el in enumerate(cell_ue_active_count):
if el is not None:
Σue_active_count[i] = Σue_active_count[i] or 0
Σue_active_count[i] += el
# any None here will map to kpi.NA
m['DRB.UEActive'] = kpi.StatT(*Σue_active_count)
# RRC: connection establishment
#
# Aggregate statistics for all cells because in E-RAB Accessibility we need
......@@ -315,7 +346,6 @@ def _handle_stats(logm, stats: xlog.Message, m_prev: kpi.Measurement):
# same whether we do aggregation here or in kpi.Calc.erab_accessibility().
#
# TODO rework to emit per-cell measurements when/if we need per-cell KPIs
cells = set(stats['cells'].keys()) # NOTE cells are taken only from stats, not from stat_prev
δΣcell_rrc_connection_request = 0 # (if a cell disappears its counters stop to be accounted)
δΣcell_rrc_connection_setup_complete = 0
for cell in cells:
......@@ -368,6 +398,15 @@ def _stats_check(stats: xlog.Message):
raise LogError(stats.timestamp, "stats: %s" % e) from None
return
# _stats_cell_sp_el returns specified per-cell element of a statistical profile.
#
# stats is assumed to be already verified by _stats_check.
def _stats_cell_sp_el(stats: xlog.Message, cell: str, stat_profile_el: str):
_ = stats['cells'].get(cell)
if _ is None:
return None # cell is absent in this stats
return _.get(stat_profile_el, None)
# _stats_cc returns specified global cumulative counter from stats result.
#
# stats is assumed to be already verified by _stats_check.
......@@ -378,7 +417,7 @@ def _stats_cc(stats: xlog.Message, counter: str):
def _stats_cell_cc(stats: xlog.Message, cell: str, counter: str):
_ = stats['cells'].get(cell)
if _ is None:
return 0 # cell is absent in this stats
return 0 # cell is absent in this stats
return _['counters']['messages'].get(counter, 0)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment