function reportHandler(clientIP, req, res, log) {
    // Attach the apiMethod method to the request, so it can used by monitoring in the server
    // eslint-disable-next-line no-param-reassign
    req.apiMethod = 'report';

    if (!isAuthorized(clientIP, req)) {
        res.writeHead(403);
        res.write(JSON.stringify(errors.AccessDenied));
        res.end();
        return;
    }

    // TODO propagate value of req.headers['x-scal-report-skip-cache']
    async.parallel({
        getUUID: cb => metadata.getUUID(log, cb),
        getMDDiskUsage: cb => metadata.getDiskUsage(log, cb),
        getDataDiskUsage: cb => data.getDiskUsage(log, cb),
        getVersion: cb => getGitVersion(cb),
        getObjectCount: cb => metadata.countItems(log, cb),
        getCRRMetrics: cb => getCRRMetrics(log, cb),
        getReplicationStates: cb => getReplicationStates(log, cb),
        getIngestionInfo: cb => getIngestionInfo(log, cb),
        getVaultReport: cb => vault.report(log, cb),
    },
    (err, results) => {
        if (err) {
            res.writeHead(500, { 'Content-Type': 'application/json' });
            res.write(JSON.stringify(err));
            log.errorEnd('could not gather report', { error: err });
        } else {
            const getObjectCount = results.getObjectCount;
            const crrStatsObj = Object.assign({}, results.getCRRMetrics);
            crrStatsObj.stalled = { count: getObjectCount.stalled || 0 };
            delete getObjectCount.stalled;
            const response = {
                utcTime: new Date(),
                uuid: results.getUUID,
                reportModelVersion: REPORT_MODEL_VERSION,

                mdDiskUsage: results.getMDDiskUsage,
                dataDiskUsage: results.getDataDiskUsage,
                serverVersion: results.getVersion,
                systemStats: getSystemStats(),
                itemCounts: getObjectCount,
                crrStats: crrStatsObj,
                repStatus: results.getReplicationStates,
                config: cleanup(config),
                capabilities: getCapabilities(),
                ingestStats: results.getIngestionInfo.metrics,
                ingestStatus: results.getIngestionInfo.status,
                vaultReport: results.getVaultReport,
            };
            monitoring.crrCacheToProm(results);
            res.writeHead(200, { 'Content-Type': 'application/json' });
            res.write(JSON.stringify(response));
            log.end().debug('report handler finished');
        }
        res.end();
    });
}
Sends back a report

@param {string} clientIP - Client IP address for filtering
@param {http~IncomingMessage} req - HTTP request object
@param {http~ServerResponse} res - HTTP response object
@param {werelogs~RequestLogger} log - request logger

@return {undefined}