Skip to main content

Telecom — network performance & capacity

The problem. Subscribers notice a degraded cell long before a threshold report does — dropped calls, stalling video, dead zones at rush hour. The network operations centre needs to spot a degrading or congesting cell and localize the cause, then see far enough ahead to add capacity before the busy hour turns into an outage. The catch: a cell's problem is often not in the cell at all, but in a backhaul link it shares with others.

What we solve here is finding and localizing degradation fast, and planning capacity before congestion bites.

Set up demo data

New workspace? Run this once (Python) to create two cells' utilisation series (with busy-hour peaks) and the topology where they share a backhaul link — so the localisation in step 2 points at the link. Safe to re-run.

import datahub_sdk, numpy as np, pandas as pd

client = datahub_sdk.DataHubClient.from_env()

util = 50 + 40 * np.clip(np.sin(np.arange(168) / 24 * 2 * np.pi), 0, 1) # ~90% at busy hour
idx = pd.date_range(end=pd.Timestamp.now(tz="UTC"), periods=168, freq="1h")
for c in ["cell_oslo_4412", "cell_oslo_4418"]:
client.timeseries.create([datahub_sdk.TimeSeries(external_id=f"{c}_prb_util", name=f"{c} PRB util", unit="pct", value_type="float")])
client.timeseries.insert_from_lists(timestamps=idx, values=util, ts=f"{c}_prb_util")

client.resources.create(
[datahub_sdk.Resource(external_id=x, name=x, labels=[lbl]) for x, lbl in
[("cell_oslo_4412", "Cell"), ("cell_oslo_4418", "Cell"),
("backhaul_link_88", "BackhaulLink"), ("controller_rnc_3", "Controller")]],
[datahub_sdk.RelForm.by_external_ids("cell_oslo_4412", "backhaul_link_88", "backhauled_by"),
datahub_sdk.RelForm.by_external_ids("cell_oslo_4418", "backhaul_link_88", "backhauled_by"),
datahub_sdk.RelForm.by_external_ids("backhaul_link_88", "controller_rnc_3", "connects_to")])

1. Find the busy-hour congestion

Per-cell throughput, drop rate and active users are series. Aggregating to hourly peaks reveals which cells run hot at the busy hour — the capacity-planning shortlist. See Query & aggregate.

var filter = new RetrieveFilter();
filter.setExternalId("cell_oslo_4412_prb_util");
filter.setStart(ZonedDateTime.now().minusDays(7));
filter.setEnd(ZonedDateTime.now());
filter.setAggregates(List.of("max"));
filter.setGranularity("1h");

var request = new DataRetriever<RetrieveFilter>();
request.setItems(List.of(filter));

client.timeseries().retrieve(request).getItems().get(0).getDatapoints()
.forEach(p -> flagIfSaturated(p.getTimestamp(), p.getValue())); // PRB utilisation %

2. Localize a fault to shared backhaul

When several cells degrade together, the common cause is usually a backhaul link or controller they share. Model cells → backhaul → controller as a graph and walk from each degraded cell to the element they have in common — the shared-dependency pattern, pointing the field team at the one link to fix instead of a dozen cells to chase.

ResourceNetwork c1 = client.resources().fetchRelated("cell_oslo_4412", 4);
ResourceNetwork c2 = client.resources().fetchRelated("cell_oslo_4418", 4);

Set<String> n1 = c1.nodes().stream().map(Resource::getExternalId).collect(Collectors.toSet());
Set<String> shared = c2.nodes().stream().map(Resource::getExternalId)
.filter(n1::contains).collect(Collectors.toSet());
// shared contains "backhaul_link_88" → fix the link, not the cells

See the result

Busy-hour utilisation peaks near 90%, and the two degraded cells share one element:

backhaul_link_88 ← fix the link, not the dozen cells behind it

See also