Skip to content

[WIP] Add opt-in Usage Reporter (call-home) for the CloudStack project - #13985

Draft
wido wants to merge 2 commits into
apache:mainfrom
wido:reporter
Draft

[WIP] Add opt-in Usage Reporter (call-home) for the CloudStack project#13985
wido wants to merge 2 commits into
apache:mainfrom
wido:reporter

Conversation

@wido

@wido wido commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Description

This is a WIP / RFC to gather feedback before it is finished. Not intended to be merged as-is.

This proposes an opt-in Usage Reporter ("call-home") for CloudStack. The goal is to give the project insight into how CloudStack is actually deployed in the wild: which hypervisors, storage types, network offerings and versions are in use, and how large environments typically are. Today we simply do not know, which makes it hard to decide what to prioritise, what to deprecate and what to test.

Two parts are included:

  1. Management Server side (UsageReporter): periodically collects aggregated counters and POSTs them as JSON to an endpoint of the CloudStack project over HTTPS.
  2. Collector side (reporter/): a small Python Flask/WSGI application that validates incoming reports and stores them as JSON files on disk, one directory per environment, with the receive timestamp as filename. Submissions are rate limited and bounded per environment, and reports with an unexpected structure are rejected.

Opt-in and privacy

  • Disabled by default: usage.report.interval = 0. An operator has to explicitly set an interval (7 days recommended) and restart the Management Server.
  • usage.report.uri defaults to https://reporting.cloudstack.org/report and can be pointed elsewhere. Only HTTPS is accepted; plain HTTP is refused.
  • Only aggregated statistics are sent: counts per hypervisor type, host/cluster types, storage pool type/provider/scope, zone network and service providers, instance states/types, disk offering characteristics, and the version upgrade history. No hostnames, IP addresses, account names, UUIDs of resources, tags or any other free-form data.
  • The environment is identified by a SHA-256 hash derived from the version table, so reports from the same environment can be correlated over time without identifying it.

Open points for discussion

  • Is the set of collected metrics the right one — anything missing, anything that should not be there?
  • Where and how should the collector be hosted, and who has access to the collected reports?
  • Do we need a documented retention and publication policy for the aggregated data before this is enabled anywhere?
  • The reporter/ collector may be better off in a separate repository rather than in the main tree.
  • Documentation and tests are not written yet.

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • build/CI
  • test (unit or integration test code)

How Has This Been Tested?

Manually against a local Management Server with usage.report.interval set to a low value and the collector running locally behind HTTPS. Verified that nothing is sent with the default configuration.

The Management Server periodically sends an anonymous usage report to
an API endpoint of the CloudStack project. This is opt-in and disabled
by default (usage.report.interval = 0); only aggregated statistics are
sent, nothing that can directly identify an environment. Reports are
only sent over HTTPS.

Includes the server-side collector, a Python Flask/WSGI application
which validates incoming reports and stores them as JSON files on the
local filesystem, in a directory per environment with the receive
timestamp as filename. Submissions are rate limited and bounded per
environment and reports with unexpected structure are rejected.
@boring-cyborg boring-cyborg Bot added the Python Warning... Python code Ahead! label Aug 26, 2026
@wido wido added this to the 24.0.0 milestone Aug 26, 2026
@IvetPM

IvetPM commented Aug 27, 2026

Copy link
Copy Markdown

This is a really nice idea and will help us understand better the CloudStack users, their stack and environment specifics. IMO the information shall be limited to PMCs only, as it opens a bit of security gap for proprietary vendors to target the CloudStack users. But we can create Qly reports and publish them as blog posts on the ACS website. I was hoping for years to get such information, so really nice job!

…enses

Pin down the JSON that the management server POSTs to usage.report.uri so
any change to the wire format has to be a deliberate one.

UsageReporterTest mocks the seven DAOs the report is built from and drives
the real report builders through the real AtomicGsonAdapter, comparing the
result against a checked-in fixture, usage-report-expected.json. Keys are
sorted on both sides before comparing: AtomicLongMap is backed by a
ConcurrentHashMap and the report itself by a HashMap, so key order on the
wire is not deterministic and must not be part of the contract. Sorting
also makes a mismatch print a readable diff.

The tests document three things that are not obvious from reading the code:

 - provisioning_type keys are lowercase ("thin"/"fat"). Storage.Provisio-
   ningType overrides toString() and the adapter keys on String.valueOf(),
   so the payload does not carry the enum constant names that Gson would
   emit by default.
 - boolean counters reach the wire as the string keys "true" and "false",
   used by ha_enabled, dynamically_scalable, compute_only and
   use_local_storage.
 - a report from an empty install still carries all eight sections with
   empty counter objects, and avg_disk_size falls back to 0 rather than
   dividing by zero.

AtomicGsonAdapterTest covers the adapter on its own: null and empty maps,
counts as numbers, boolean and enum keys, and that read() consumes a null.

Also add the ASF license headers that apache-rat flags on reporter/README.md
and reporter/requirements.txt.
@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 58.04196% with 120 lines in your changes missing coverage. Please review.
✅ Project coverage is 19.75%. Comparing base (158fe4f) to head (6890a98).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...va/org/apache/cloudstack/report/UsageReporter.java 56.43% 108 Missing and 7 partials ⚠️
...ain/java/com/cloud/upgrade/dao/VersionDaoImpl.java 0.00% 5 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main   #13985      +/-   ##
============================================
+ Coverage     19.74%   19.75%   +0.01%     
- Complexity    19960    19986      +26     
============================================
  Files          6371     6373       +2     
  Lines        575784   576070     +286     
  Branches      70478    70516      +38     
============================================
+ Hits         113665   113792     +127     
- Misses       449765   449919     +154     
- Partials      12354    12359       +5     
Flag Coverage Δ
uitests 3.41% <ø> (ø)
unittests 21.03% <58.04%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@shwstppr

Copy link
Copy Markdown
Contributor

It would be definitely useful but I'm not sure how many users would want to share it. It would be useful to some control on toggling configs on the first login screen.

@DaanHoogland DaanHoogland left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code looks generally good, but prove is in the eating of the pudding.

@DaanHoogland

Copy link
Copy Markdown
Contributor

I think if we do not disclose the information to the general public we should abandon this project. It is definitely not for PMC only, or even restricted to any apache circle. Its use is for any contributor from anywhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component:management-server Python Warning... Python code Ahead!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants