v2.6.3 Release Changes - #1123
Merged
Merged
Conversation
…xis, and links that carry where you came from (#1121) * Monitoring: carry the WAN into Network Performance on single-WAN sites A jump from a live tile or a map's analyze icon named no WAN when the site had only one, so the destination kept whatever scope it was last left in and the chart then refused the category the link had asked for: clicking ISP RTT while Network Performance was saved on LAN landed on the LAN chart, and the 2D/3D analyze icons landed on ISP because Fabric is not offered in a WAN scope. The WAN key is whichever WAN the live chart is showing, which is not necessarily WAN1 - a single-WAN site can be on wan2. Emit side: - LiveWanScope.QueryFragment no longer gates on HasChoice. The gate assumed one WAN means one view; the destination splits that WAN from the LAN regardless of how many WANs exist. - The Monitoring page now loads LiveWanScope on single-WAN sites too, as the dashboard panel already did. Without the options loaded there was no key to put on the link at all, which is why the Live tab's ISP Health tile also named no WAN there while the dashboard's did. - The gateway fabric tile on both surfaces asks for All through a shared MonitoringLinks.FabricTarget, so a LAN target link stops landing in a WAN scope that hides the row it names. Receiving side (Network Performance): - The link's WAN applies whenever the console named any WAN, not only on multi-WAN sites. One WAN still has a scope to set. - All is taken from the token rather than inferred from the resolved keys: on a single-WAN site "all" and that one WAN resolve identically, and only All keeps the LAN categories on the chart. Multi-WAN is unchanged throughout: every gate that moved was already satisfied there, and the All inference behind the new token check is the same expression it was. * Monitoring: carry the moment into Device Stats, and into the gateway latency jump The gateway tiles on both Live surfaces were the only ones that arrived somewhere with no idea what moment they came from. Gateway RTT and Loss opened Latency and Packet Loss on whatever window it was last left framing, and Gateway CPU, Memory and Temp opened Device Stats the same way - so a tile showing a spike could land on some earlier stretch of the day, and a tile parked on an instant during playback lost that instant entirely. Both now carry ?at=, live marker or parked instant, the way the ISP and Transit tiles already did: - Device Stats reads it and frames its charts on it. New frameMoment / frameTrailing in device-health-charts.js, an hour wide rather than the latency charts' 15 minutes: temperature, CPU and memory drift over a shift, and 15 minutes of a slow climb reads as a flat line. frameTrailing stands down on a fresh mount, which already opens on a trailing hour. - Gateway RTT and Loss go through the same 15-minute framing as the other latency tiles, since they land on the same charts. Both links are built by MonitoringLinks (FabricTarget gains the moment, DeviceStats is new), so the two surfaces cannot drift apart on it again. The Monitoring page reads its moment from CurrentAtToken, extracted from JumpToAnalysis; the dashboard's tiles have no timeline and always say live. The devices tab keeps its own pre-select pair rather than sharing the performance tab's: those are consumed and cleared by the latency charts' mount, which would eat the instant before Device Stats ever mounted. * Device Stats: name the day once, under the x-axis The tick labels are times, and datetimeFormatter only grows a date where the granularity rolls over - so any window that crosses no midnight, which is most of them, said nowhere what day it was showing. ApexCharts has no option for stamping the date once, so this is an axis caption rather than a tick: a caption holds still, where the tick that would carry it moves with the chart's width. Reads "Aug 8", or "Aug 7 - Aug 8" when the window spans midnight, from the same effective window the range controls already compute. Applied on load only when the text actually changes, since updateOptions redraws and the poll runs every few seconds, and before the mark layer redraws - that call recreates the annotation labels its tooltips are bound to. Device Stats only for now; the other Monitoring charts share the same axis shape and can follow. * Monitoring charts: name the day once under the x-axis, everywhere but ISP Health The Device Stats trial moves into chart-axis-date.js and goes on the other six chart sets: Latency and Packet Loss, Device Stats, SFP Stats, CM Stats, ONT Stats, Cellular Stats and Starlink Stats. ISP Health is deliberately left alone. Suppressed at 24 hours and above, where the tick labels carry dates of their own and the caption would only repeat them. Since every tab except Latency and Packet Loss and Device Stats opens on 24h, most of them show nothing until the window is narrowed - which is the point: the caption exists for the windows that name no day at all. An empty string is a real suppression, not a blank label: ApexCharts guards the xaxis title on a truthy check, so nothing is drawn and no space is reserved for it. Each module hands the caption its own charts and its own effective window, since that is where the presets, shift offsets and custom ranges live. The charts callback takes either chart instances or the [chart, element] pairs the mark layer already uses, so no module keeps a second list. Applied ahead of each module's redraw: that redraw recreates the annotation label elements the mark layer binds its tooltips to. * Chart axis date: match the tick labels it sits under 12px/600 Helvetica in the same grey ApexCharts draws x-axis labels in, and the day zero-padded the way a day tick is ("Aug 08", not "Aug 8"), so the caption reads as one of the labels rather than as a heading beneath them. The importers move to ?v=2: a transitive import bypasses Razor's content hash, so the browser would otherwise hold the v=1 copy. * Monitoring: the gap between stacked charts belongs to the stack Twenty-one identical `style="margin-top: 1rem"` on Monitoring's chart cards and two more on the device page, all saying the same thing: a chart card following a chart card is spaced from it. That is one rule. Scoped to .card-body deliberately. Threat Intelligence pairs two chart cards side by side inside .threat-two-chart-row, which is not in a card-body, and an unscoped sibling rule would have dropped the second card an inch below the first. Four keep their inline margin because they are not this case - each is the FIRST card inside a wrapper, with no chart-card sibling to be spaced from: the SFP PON and ONT error sections, the stats table chart-stats.js injects, and the custom-field charts device-health-charts.js appends. * Monitoring: close the gap between stacked charts The 1rem was excessive - stacked charts read as one instrument, and an inch of dead space between each of six of them pushed half the tab below the fold. Gone rather than reduced: the chart cards carry their own header padding, and ApexCharts leaves room around the plot. The rule added a commit ago goes with it - consolidating the 23 copies is what made this a one-line deletion instead of 23 edits. The stats table keeps its gap (chart-stats.js): it is a table under the charts, not another chart, and the break is what says so. * Monitoring: drop the stats table's top margin too It is a sibling of the charts in the same stack, and the charts already carry plenty of space below the plot - which is the whole reason the 1rem was excessive in the first place. No chart-card anywhere carries an inline top margin now. chart-stats.js renders the port stats table as well, so that one loses its gap on the same grounds. Its importers move to ?v=7: a transitive import bypasses Razor's content hash. * Live View: keep the port stats table's gap It renders through the same shared table as the chart tabs, but nothing charted sits above it - it follows the filter chips - so it was the one place that actually needed the 1rem, and dropping it there closed a gap that was doing work. On the container rather than back in chart-stats.js: every other caller follows a chart and wants none. * Live View: half the gap is enough over the port stats table * Device Stats: hover one chart, read the same instant on all three Temperature, CPU and Memory join an ApexCharts group, so the tooltip and crosshair follow the pointer across all of them. That is the question being asked of a device anyway - what else was happening when this climbed - and answering it meant reading three charts by eye and hoping. Trial, on this tab only. The custom-field charts are deliberately out of the group: the sync is by data index rather than timestamp, and while the three fixed charts come from one payload through alignedPoints - so index i is the same moment on each - a custom field is plotted from its own array and would put the crosshair somewhere else. * Device Stats: trim synced tooltips, and bring the custom charts into the group Two things the trial turned up. A synced tooltip answers for a chart nobody is pointing at, and past a handful of series it grows taller than the chart being read - covering the thing the reader came to look at. Synced copies now stop at five rows and mark the trim with an ellipsis; the hovered chart still lists everything. Which copy is which comes from a document-level pointerover, because a synced chart sees no pointer event of its own. Unknown counts as hovered: with no pointer seen yet, the full list is the safer answer. The custom-field charts can join the group after all. They arrive from their own Influx query - same window, own rows - and ApexCharts syncs by data index, so plotted as they arrived their crosshair pointed at a different moment. customPoints re-keys them onto the health rows (nearest within half a step, so a bucket boundary landing a moment off still matches instead of blanking the series) and bridges gaps on the field's own cadence, so a slowly-polled OID keeps the line it had rather than breaking between every reading and drawing nothing. chart-tooltip.js importers move to ?v=11. * Synced tooltip: lift the ellipsis off the bottom edge * Synced tooltip: put the ellipsis on the last row, not under it As its own block it cost a row of height - which is most of what capping the list was meant to win back. It now sits at the right end of the fifth row, pushed there by margin-left:auto inside the row's existing flex. * Monitoring: hover sync on every multi-chart tab The Device Stats trial generalizes. Latency and Packet Loss, Device Stats, SFP Stats, CM Stats, ONT Stats, Cellular Stats and Starlink Stats now each put their stacked charts in an ApexCharts group, so pointing at one reads the same instant on all of them. The identity comes from chart-sync.js and is stamped inside each module's base options, so every chart a tab builds - including the ones created later, like the custom-field and PON charts - joins without a call site knowing about it. Two charts are deliberately not in their tab's group, because hover sync addresses a point by data INDEX and both are drawn from a second query whose rows are their own: - SFP's PON charts get their own group rather than the optics one. They sync with each other, which is what a PON reader is comparing anyway. - Latency's WAN Throughput joins nothing. It is a different measurement on its own cadence, and its index i is some other moment entirely. The tooltip stops trusting that index either way: a synced copy now resolves against the x the hovered chart reported rather than reading its own x at the index it was handed, so rows and hover dots answer for the moment under the pointer even where two charts' points do not line up one for one. The crosshair is still ApexCharts' own, which is why the two exclusions stand. Device Stats moves off its hand-rolled wrapper onto the shared helper. chart-tooltip.js importers go to ?v=12. * Monitoring: bring PON and WAN Throughput into their tabs' hover sync Both were held out because hover sync addresses a point by index and both are fed by a second query whose rows are their own. Being outside the group is the wrong answer to that: the WAN Throughput under a latency spike is most of why it sits there, and PON counters beside the optics are one reading of one link. SFP's PON charts join the tab group properly rather than loosely: ponPoints now places the counters on the module's own optics rows through alignedOnto, so index i is the same instant and the crosshair lands where the tooltip says. A module reporting PON with no optics rows keeps its own timeline and simply does not sync, which is what it did before. WAN Throughput joins as it is - there is no single timeline on that tab to re-key onto, since every target carries its own rows. Its rows stay honest because the tooltip resolves by the hovered instant rather than by index. alignedOnto is the device-health customPoints logic, moved beside alignedPoints now that two tabs need it; customPoints is a call to it. chart-tooltip.js importers go to ?v=13. * Latency & Packet Loss: keep WAN Throughput synced across a category change Each category brings its own targets, and their row counts differ - so the data index the hovered chart hands the throughput chart could land past the end of its own array, where there is nothing to draw and the synced tooltip simply did not appear. Flipping categories until the counts happened to fit brought it back, which is what made it look intermittent. Its series are now placed on the longest series on screen through alignedOnto, so index i is the same instant and always exists. Falls back to its own timeline when nothing is charted to key onto. * Monitoring: make the hover sync fire at all - match the group's extents The sync was intermittent and failed in BOTH directions at once, which ruled out anything about indices. ApexCharts passes a hover to a grouped chart only when a.w.globals.minX === i.w.globals.minX && a.w.globals.maxX === i.w.globals.maxX - an exact match on both ends. Charts drawn from one query agree by construction, which is why Device Stats looked fine; a chart answering a second query lands on the same first and last timestamp only by luck, so WAN Throughput and the PON charts synced or did not depending on where their data happened to start and stop. Changing category reshuffled that, and flipping back through the categories eventually landed on a match again. Each tab now stretches one series per chart to the group's extents with null points (spanTo), so every chart reports the same minX and maxX. A null draws nothing, takes no hover dot and gets no tooltip row, so the padding is invisible. The re-keying added in the last two commits goes with the theory that prompted it. Apex resolves the hovered point per chart from the pointer's position against that chart's own grid, so no chart ever needed its points moved onto another's timeline - and doing it resampled a measurement onto a cadence that was not its own. WAN Throughput, the PON counters and the custom-field charts are back on their own rows, and alignedOnto is gone. * Monitoring: anchor grouped charts to the window, not to their data Still flaky, and flaky in TIME rather than by filter - the same category worked or did not across a refresh. Padding to the group's data extents could not settle that: it only stretches a series to reach them, and each query is polled on its own schedule, so whichever poller wrote last owned the later final sample and the extents disagreed again. Which one that was came down to timing, which is exactly what the symptom said. Every chart on a tab now reports the window it asked the server for: points outside it are dropped - a sample a second past the end, from a poller whose clock ran ahead, is precisely what broke the match - and the first series is padded to both ends with nulls. Two charts agree because they were built from the same request, not because their data happened to line up. * Revert "Monitoring: anchor grouped charts to the window, not to their data" This reverts commit 0b08913. * Monitoring: instrument the chart hover sync, both sides Four attempts in, the sync is still intermittent and there is nothing to read: the deciding test lives inside ApexCharts, comparing each grouped chart's minX and maxX against the hovered one's, and nothing on the page or in the logs says what those values are. Client: __netoptSync.report() prints every grouped chart's extents, the delta from its group's reference, and whether ApexCharts would sync it - read straight out of the library's own registry, so it compares what the library compares. __netoptSync.watch() logs only when a group's alignment CHANGES, which is what a flaky fault needs: leave it running, use the WAN pills, and the log names the moment it broke instead of the moment someone thought to look. __netoptSync.stop() ends it. Console only, and only when called. Server: chart-data and wan-rate-chart each log their row count, first and last instant, and the window asked for, so the two queries can be read against each other for the same moment. Extents only - no target names or addresses. * Monitoring: trim grouped charts to the group's extents, not just pad to them The watcher named it: latency-12 (WAN Throughput) reported -24000/0 and then 0/+3000 against its group. Its own query starts and ends at its own instants, and spanTo could only reach outwards - so a chart whose data went PAST the group's ends kept its own and stayed out of step, in both directions, exactly as often as the two pollers disagreed. spanTo now takes the whole series array: every series is trimmed to the group's extents and the first is padded to both ends. Anchored to the group's own data, computed once per pass - not to the clock, which is what broke this outright last time by giving each chart a max a few milliseconds apart. * SFP Stats: PON follows the optics only when the ONT modules are alone on screen With another module shown beside them, the optics charts are drawing a line the PON charts have nothing to answer with, and a crosshair tracking across the two claims a correspondence that is not there. The PON charts move into a group of their own then, so they still follow each other, and rejoin the optics group as soon as the ONT modules are the only ones selected. Membership is set on both the registry entry and the chart's own config, since ApexCharts reads one to find a group's members and the other to decide what the hovered chart belongs to. Rebuilding the charts would mean a full remount on every chip click. * Monitoring: remove the chart sync diagnostics They found the fault - a 24s/3s extents drift on WAN Throughput - and the fix went in with it. __netoptSync and the two endpoint log lines come back out of git if another one of these ever needs chasing (8aa5984). * Monitoring: stop grouped charts inheriting each other's options ApexCharts' updateOptions takes a fourth argument, updateSyncedCharts, and it defaults to TRUE - so once these charts shared a group, every call was also applying its options to the rest of the group. Positional settings are the ones that show it: SFP's RX-solid/TX-dashed pattern reached the PON charts and dashed TX Frames on GEM Frames, and the WAN comparison dash array reached WAN Throughput and dashed its upload. Every call in a grouped module now passes false. The event marks and the axis date caption too: those were being handed to group-mates as well, which would have drawn one chart's marks on another as soon as two disagreed. Pre-dates nothing - this arrived with the grouping, which is why it reads as a regression on this branch. * Latency & Packet Loss: draw every compared WAN's throughput Comparing two WANs was answered by one WAN's throughput - the primary's - under a title naming it. The point of putting two WANs side by side is to see them apart, so the chart now draws each selected WAN's download and upload, fetched per WAN and told apart the way the RTT chart does it: the color still says download or upload, the dash pattern says which connection, in the same progression the pills and the RTT series use. Series carry the WAN's own token from the pill bar. The card title drops its single-WAN suffix while several are drawn, since naming one of them would contradict the chart under it. * Latency & Packet Loss: key the throughput dash to the WAN, not to draw order Review of the change above. The pattern was taken from each series' place among the ones drawn, so one WAN's request failing shifted every WAN after it onto another's pattern - and the whole point is that a WAN wears the same dash here as on the RTT chart. Keyed off its place in the filter now, the way wanDashFor does it. The pattern is also only pushed when it changes: updateOptions redraws, and the poll comes round every few seconds. * Suggested targets: call SpaceX by its name AS14593 registers as "Space Exploration Technologies Corporation", which the suffix strippers boil down to "Space Exploration" - a name nobody would recognize as the operator behind Starlink when picking targets to monitor. CleanOrgName gains a last alias step, applied to whatever the strippers leave, so discovery and manual add both store the known name. The lighter display pass carries it too, under both forms the two cleaners can produce, so names already stored read right without re-discovery. Exact-match on the whole stripped name, like the brand overrides beside it: a firm that merely starts with those words keeps its own. * Network Performance: rename a target in place from Latency Targets Renaming meant deleting the target and adding it again, which threw away its history to fix a typo. The name cell now carries the same inline edit the Sites table has - pencil, input, Save and Cancel, Enter to save, Escape to back out. Operator, the role that adds a target: naming one is curating the list, not administering the site. The gate is on IMonitoringTargetService, so the role is enforced and the change audited from and to whatever the name was; the card's SiteOperatorOnly only decides whether the pencil is drawn. The name is validated the way AddAsync validates it, so a rename cannot set one that adding a target would have refused. The inline-edit styles the Sites table introduced are now named for what they do, and shared rather than copied. * Inline rename: keep Save and Cancel together when they wrap In a table cell there is rarely room for the field and both buttons, and wrapping them one at a time left Cancel stranded on a line of its own. They are one group now, so they drop to the next line together - in Latency Targets and in the Sites table both, off the shared rule. * ISP Health: analyze the window Per-Network RTT is showing The chart plots per-ASN latency clusters, which Latency and Packet Loss charts as Transit - but getting there meant switching tab, category and WAN by hand and then finding the stretch again. The card gains the same magnifier the Live surfaces carry. It hands over the window rather than a moment: the instant at the center of the current zoom, and how wide that zoom is. A reader who narrowed to one evening did that to say WHICH evening, and landing on a fixed 15 minutes would drop exactly what they had expressed. The zoom answers first, then the report window, then what the chart drew. ?span= is an override and nothing more - every link without one frames what it always framed. The WAN rides along as it does everywhere else. * Latency Targets: keep a refused rename in the box The edit closed before the save was attempted, so a name the service refused - over the length limit, or from a role without the permission - left its reason under the table with nothing to correct: the typed name was gone and the row had reverted. It closes on success now, and stays open otherwise. * ISP Health: pull the analyze magnifier flush with the card edge * Guided tour for v2.6.3, and a predicate for a site that monitors anything Two steps: the hover sync across a tab's charts, and renaming a target in place. Both gated on has-targets - a new predicate for monitoring being on with at least one enabled target of any type, which isp-health could not answer: it wants an Access ISP target, so a site watching nothing but its own switches and APs was turned away from steps its charts can show. The rename step is optional as well: a Viewer sees no pencil, and the RBAC gate is authored per step until the engine has one of its own. The hover-sync anchor sits on the chart rather than the card - the sync is something the plot does under the pointer, and it reads as that only with a line to hover. The rename anchor is the table, not a row: which target comes first depends on the site.
* Multi-Site: an agent on the UniFi gateway gets the gateway update instructions (#1107) * Agent list: recognize a gateway agent on the main site The upgrade one-liner a site's agent row offers was picked off a per-site verdict that is false for the main site twice over: the call site guarded on !site.IsDefault, and AgentOnGatewayDetector.IsAgentOnGatewayAsync answers false for the default slug by contract. A main-site agent running on the gateway was therefore handed the bare-metal, Docker and Proxmox LXC commands, none of which apply to it. Ask the per-address question instead - MatchGatewayAddressAsync, which is deliberately not default-site gated - and key the answer by agent rather than by site, since a site has one gateway and only one of its agents may be on it. The site-level verdict keeps its existing contract, so the speed-test surfaces that rely on it are untouched. An agent with no open tunnel falls back to its last known LAN IP: an outdated agent is exactly the one whose upgrade command this drives, and it may well be the one that is down. * Agent list: make gateway detection survive a console that is not up The per-agent question was asked with MatchGatewayAddressAsync, which resolves the gateway addresses live and has no memory. Those addresses come from the site's UniFi Console, and on an agent site the console reconnects through that agent's own tunnel - so opening the panel after a restart or an agent update asks before the console can answer, the comparison set is empty, and every agent resolves to a silent no. A gateway agent was then handed the bare-metal, Docker and Proxmox commands. The site-level verdict never showed this because it seeds from a persisted answer and keeps the last one when the console is down, which is why WAN Speed Test stayed right on the same site at the same moment. Give the per-agent question the same durability: a persisted verdict per agent, seeded before the refresh starts, with a degraded refresh keeping the last answer instead of inventing a no. Deliberately does NOT wait on the console - Settings is where a broken or unconfigured console gets fixed, so it has to stay responsive there. The existing entry points are untouched, so the speed-test consumers keep the site-level contract exactly as it was. The default site now reaches the persistence path for the first time, so it writes to the main database rather than asking for a per-site one it does not have. * TODOs for the remaining agent-on-gateway detection cleanup (#1106) Marks the call sites still using the live, memoryless MatchGatewayAddressAsync where the durable per-agent overload belongs, the one that needs the matched address rather than a yes/no and so does not drop in, the narrow gateway address set, and the uncovered first resolve. Comments and TODO.md only - no behavior change. * TODO: keep the address-set example generic * Record the known gaps the regression review turned up (#1106) The Any() reducer in SiteHasGatewayAgent: its one caller mirrors what a blank override resolves to, and SiteSpeedTestTargetResolver resolves against one agent, so a site with a gateway agent and a real-box agent makes the two disagree. Secondary sites only - the main site does not render the field. The per-agent key also puts every already-enrolled gateway agent through the cold-start window once, since nothing reads the site-level row back under the new key. Noted alongside why backfilling it is not worth building. * Adaptive SQM: give the boot script room to install its dependencies A first deploy runs the boot script over SSH with no timeout argument, so it inherited the 30 second default. The script installs its dependencies inline before it does anything else: it adds the Ookla packagecloud repo, which runs its own apt-get update and fetches a GPG key, then apt-get installs speedtest, bc and jq. On a cold apt cache or a slow WAN that comfortably outruns 30 seconds, and the deploy then tore down a deployment that was still working and reported that the boot script had failed. Give that one command five minutes, which clears a slow first install without leaving the page sitting on a boot script that has genuinely wedged. Re-deploys skip the whole block once the dependencies are present, which is why this only ever bit the first attempt. (cherry picked from commit cb8400b) * Add UPS-2U-Pro device support * Classify UniFi power devices as SmartPower * Display Smart Power device type with spacing * Address SmartPower review feedback --------- Co-authored-by: TJ @ Ozark Connect <109822114+tvancott42@users.noreply.github.com> Co-authored-by: TJ da Tuna <tjvc42@gmail.com>
…nd per-WAN vantage fixes (#1122) Cellular monitoring lost its tower distance estimate when polling moved to uiwwand, which reports no timing advance. It comes from get-cell-tower-info instead, verified against the qmicli reading it replaces, and the LTE cell id now decodes to a site and sector so neighbours sharing a tower read as such. Timing advance, cell id, tracking area, neighbour count and 5G availability are recorded, so a drift off a 5G-capable tower is dated rather than noticed days later. Reset Radio recovers a modem that has settled on an LTE anchor offering no 5G, where previously only a reboot helped. It cycles the radio for about seven seconds to force a fresh tower selection, and is offered only when the network permits 5G and the serving cell is the one withholding it - a reset cannot help when the network is gating it, and would tear down an NR leg still negotiating. Site Admin, behind a confirmation, since the modem cannot tell whether it is the active WAN. A 5G modem with no NR leg now explains itself in the empty slot rather than leaving a single box in a two-box grid. ISP Health reported every 5G NSA link as downgraded to LTE. NSA writes an LTE and a 5G point per poll, so the newest point is always the LTE half; a downgrade is now the 5G series going quiet while LTE keeps reporting. Upstream Path Discovery attributed a regional aggregator to tier-1 access ISPs. The carve-out probe exists to surface transits the ordinary targets never touch, and the near-transit walk that normally rejects it stops at the first tier-1 - which never fires when the tier-1 IS the access network, since access hops are skipped first. Discovery through the ordinary targets is unchanged, and an ISP that genuinely buys from that aggregator still finds it. Network Tools gains DNS Lookup from any vantage, forward or reverse, built on a parser covering the four nslookup dialects a UniFi estate actually produces. Ping reports what a hostname resolved to, which traceroute already did per hop. The vantage deep link now selects: links carry the specific WAN vantage rather than the agent's first, and the picker applies it once the data it needs exists rather than losing it to a slow vantage list. Device types read as names rather than raw enum members. The four provider monitors are behind the service-layer RBAC gate. Cable Modem, ONT, Starlink and Cellular were each built by the per-site registry and never DI-resolved, so the method security interceptor never applied - and because none was marked as a mutating service, the architecture tests could not see them either. Saving, deleting, enabling and resetting were reachable by any role that could reach a caller. Writes now require Admin on that site, matching the site-admin-only Settings pages that drive them; reads require Viewer, matching the monitoring cards that show them. One unreachable device could take its site's console offline. The server gave up on a proxy open two seconds before the agent stopped dialing, so the agent's own answer for a dead host never arrived and every unreachable target was misread as a dead tunnel. The server waits long enough to hear it, and only treats a timeout as a dead tunnel when the tunnel has also gone silent. Also: Latency Targets names what actually probes its targets and follows the WAN filter for both Run Probe and Add Target; WAN pickers and the vantages table order WAN1, WAN2, WAN3; the ONT card's SFP Monitoring opens the module it is showing; Performance Tweaks accepts firmware to 5.1.29; and the tour gains DNS Lookup and Reset Radio steps with a cellular predicate. The agent update is optional. DNS Lookup from an agent vantage needs the new binary and an older agent says so plainly rather than answering wrongly; everything else works with an agent of any version. Two things deliberately kept out: no session link, and no real cell identifiers — the branch history was scrubbed of a geolocatable eNB earlier, so this must not reintroduce it.
The rule fired on the coefficient of variation alone, which is scale-free: 3 clients against 1 scores exactly as 30 against 10, both landing on the 50% threshold. So a two-AP home with four clients between them was told an AP was overloaded and to lower its TX power, when a single device roaming either way flips the verdict. Two absolute floors alongside the existing ratio: the busiest AP carries at least 8 clients, and leads the quietest by at least 4. The first makes the "overloaded" claim true in clients rather than in ratio; the second keeps a gap one roam can close from counting. Placed before the RF-distance branch so the Info downgrade inherits them too.
The mean came from ctx.Clients.Count over the AP count - every client on the site, wired included - while the deviations came from each AP's own client count. Spread measured about a foreign centre is not a coefficient of variation: with more site clients than AP clients every AP sits below the mean, so the figure grows with that gap rather than with any real imbalance, and the percentage the issue prints was wrong whenever the two populations differed. Both now come from the same list. Covered by a case that clears the count floors so only the arithmetic decides: 8 clients against 4 with 36 on the site reads 68% about the site's mean and fires, and 33% about the APs' own, which is correctly silent. That test fails without this change and is the only one of the eighteen that moves.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rolls up three merged PRs for the v2.6.3 release.
Monitoring
Hovering any chart on a tab reads the same instant on all of them, tooltip and crosshair together, across Live View, Device Stats, SFP Stats, CM Stats, ONT Stats, Cellular Stats and Starlink Stats. Synced tooltips cap at five rows so a busy tab stays readable, the day is named once under the x-axis where the tick labels are times, and stacked charts sit closer together. Links out of a chart carry the WAN and the moment you were looking at. (#1121)
Cellular Stats
get-cell-tower-infoinstead, verified against the qmicli reading it replaces.ISP Health
ONT Stats
Network Performance
Device Stats
Wi-Fi Optimizer
Network Tools
Security
Fixes
Agent
The agent update is optional this release. DNS Lookup is a diagnostic tool, and from an agent vantage an older agent says so plainly rather than returning a wrong answer. Everything else works with an agent of any version, and the console fix is server-side only.