getCurrentMonthSpaceStats - "broken" or just missing a new alternative?


I’ve been trying to find a way to have statistics on each page (mostly to show the end-users and managers how often a specific page and “part of the hierarchy” is being used/edited). I’ve setup Matomo and got that running, but it feels like a overly big thing for a internal knowledge base where all I want to know is some simple statistics regarding a part of the wiki and specific pages while I’m browsing it.

But I’m running into some issues :slight_smile:
I’ve found that $doc has the methods getCurrentMonthSpaceStats and getCurrentMonthPageStats to get the past 30 days views, however, it seems like a relic from the old days where XWiki only had “three levels” of documents; Root, Space and Document since getCurrentMonthSpaceStats only sees a individual increase when I use Terminal Pages and visit those pages.

Am I bad at searching or is there a method that matches getCurrentMonthSpaceStats but for a specific branch of the tree?

Or do I have to write a more fancy velocity-script with som HQL-quering to get what I want inside of XWiki? :slight_smile:

You’re most likely right and this code was probably not refactored when we introduced nested spaces and nested pages in XWiki 7.2.

That said, I’ve quickly checked the source code and it seems like it could work since:

    public DocumentStats getCurrentMonthSpaceStats(String action)
        Scope scope = ScopeFactory.createSpaceScope(this.doc.getSpace(), false);
        Range range = RangeFactory.ALL;
        Period period = PeriodFactory.getCurrentMonth();
        XWikiStatsService statisticsService = getXWikiContext().getWiki().getStatsService(getXWikiContext());
        List<DocumentStats> stats = statisticsService.getDocumentStatistics(action, scope, period, range, this.context);

calls getDocumentStatistics which ends up calling:

    private String getHqlNameFilterFromScope(Scope scope, Map<String, Object> params)
        String nameFilter;

        // Note that these queries are made to work with Oracle which treats empty strings as null.
        if (scope.getType() == Scope.SPACE_SCOPE && StringUtils.isEmpty(scope.getName())) {
            // Select all names that are not page names (i.e. they are space names), excluding empty names which
            // represent global scopes.
            nameFilter = "name not like '%.%' and (name <> '' or (name is not null and '' is null))";
        } else if (scope.getType() == Scope.GLOBAL_SCOPE && StringUtils.isEmpty(scope.getName())) {
            // Select all names that are empty (i.e. global)
            nameFilter = "name = '' or name is null";
        } else if (scope.getType() == Scope.PAGE_SCOPE && StringUtils.isEmpty(scope.getName())) {
            // Select all names that are page names
            nameFilter = "name like '%.%'";
        } else {
            nameFilter = "name like :nameFilter";
            params.put("nameFilter", scope.getPattern());

        return nameFilter;

which uses:

            nameFilter = "name like :nameFilter";
            params.put("nameFilter", scope.getPattern());

which uses:

    private String getSpacePattern()
        if ("".equals( {
            // TODO a pattern to match any space name
            return null;
        } else if (this.deep) {
            return + ".%";

For example if the current space is Sandbox, this will return Sandbox.% which would match nested spaces too.

Now it’s possible that the problem is not when querying but when storing the stats.

By default the stats feature is off because it’s not well supported.

EDIT: Checking this leads to looking at XWikiStatsServiceImpl which stores the stats.

It calls xwiki-platform/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/stats/impl/xwiki/ at e94c5d02d53a9184f151fdb2c1dcd2d59723e3a6 · xwiki/xwiki-platform · GitHub


        add(new DocumentStatsStoreItem(doc.getSpace(), currentDate, StatsUtil.PeriodType.MONTH, action, isVisit,

And in the html file it’s defined as:

    <class name="com.xpn.xwiki.stats.impl.DocumentStats" table="xwikistatsdoc">
        <id name="id" type="long" unsaved-value="undefined">
            <column name="XWS_ID" not-null="true" />
            <generator class="assigned" />
        <property name="number" type="integer" column="XWS_NUMBER" not-null="false" />
        <property name="name" type="string" column="XWS_NAME" not-null="true" length="255" index="XWDS_NAME" />

So from what I see (looking quickly without trying nor debugging) it should work fine.

If not, you could raise a jira issue. Thanks