Skip to content

Reports ​

What the reports are, how the numbers are built, and the two things that make them look wrong when they are not.

The report families ​

Reporting is organized into families, each its own section under the Reporting menu: Account (signups, expiry, who created what, voucher and top-up code activation and availability, and voucher groups — how many groups and people you served with vouchers each month or year, see Counting group visits with vouchers; and voucher utilization — how many codes from each batch, profile or zone were used, are still valid or expired unused, with the data, time and face value they account for), Login (active sessions, auto-login, browser fingerprints, the login record, login and login-frequency summaries — overall, per profile, per device — login errors, session concurrency, dwell time — overall and per profile — top accounts, returning accounts, a login heatmap, session termination reasons, and a zone comparison), DPI (deep packet inspection traffic by application and client), Bandwidth (a summary, usage per account, top usage, the current top consumers, and bandwidth against login volume), Impression (portal/ad impression counts), Engagement (campaign impression, click and offline summaries, survey responses, and consent/marketing reporting), Delivery log (SMS, email and PMS transaction logs), Insight (device insight, registration insight, social network insight and data), Payment (transactions), AI (the AI reporting assistant, covered on its own page), and Scheduled reports (recurring exports run on a cron rather than clicked by hand). This page is about how reporting works in general; each report's own purpose is covered where it lives in the menu.

Hourly buckets and the current hour ​

Most report numbers don't write to the report tables as they happen — they accumulate as fast in-memory counters through the hour, keyed by tenant, zone and hour. A scheduled roll-up moves the previous completed hour's counters into the hourly report tables and then deletes the counters it just processed; it deliberately skips whatever hour is still in progress. That roll-up runs once an hour, five minutes past, so a finished hour lands in the reports a few minutes after it ends.

Where report numbers come from Portal and RADIUS events are counted as they happen into live Redis counters keyed by tenant, zone and hour. A scheduled aggregation runs hourly at five past and rolls the previous completed hour into hourly bucket rows in the report tables; the hour still in progress is deliberately left out. Reports read only those buckets. The dashboard's live tiles, such as online devices and the login quota, read live state directly and skip the buckets, while its totals come from the buckets like any report. Portal + RADIUSportal pages, logins,accounting start / stop1 COUNTED AS THEY HAPPENLive countersREPORT_*:{YmdH}:…Redis, keyed per hour2 ROLLED UPAggregatorhourly, five pastscheduled hourly at :053 LIVE TILES SKIP THE BUCKETSDashboardonline devices, login quotaTOTALS COME FROM THE BUCKETS →4 PREVIOUS COMPLETED HOUR−3 h−2 h−1 hcurrent hourNOT ROLLED UP YETHOURLY BUCKETS, ONE MYSQL TABLE PER MONTHlogins · bandwidth · campaigns · devices …5 QUERIEDReportsread the buckets only
The current hour exists only in the live counters until the aggregator rolls it up, so a dashboard tile reading live state and a report reading the buckets can disagree about the last hour without either being wrong. A gap older than an hour is a different thing: then the aggregator itself has not run.

The practical effect: the current, still-running hour is never in the report tables yet. A report queried mid-hour will look short for "now" compared to a moment ago — that's not missing or lost data, it just hasn't been folded in. This is the same reason the AI reporting assistant flags a result covering today with a note that the current hour isn't included.

Time zones ​

Relative periods — "today", "this week", "last month" — resolve against the tenant's own configured timezone, not the server's or the browser's. The same convention applies wherever Kiwire reasons about dates on a tenant's behalf, including the AI reporting assistant. Because the hourly aggregation itself runs on server time, a report queried right at a day or month boundary can look a little short until the aggregation pass for that boundary hour has caught up — the same current-hour gap described above, just more noticeable at a boundary.

Exporting ​

Nearly every report screen has an Export button alongside its on-screen data view, producing a CSV of the same filtered result set rather than the raw hourly buckets. For reports an admin wants delivered regularly rather than pulled by hand, Scheduled Reports automates the export on a recurring cron instead.

Last updated:

Kiwire platform documentation