/**
* Event subscribe for matomo statistics.
* @module subscribers/matomo
* @license MIT
* @author Kai KRETSCHMANN <kai@kretschmann.consulting>
*/
const eventEmitter = require('../utils/eventer').em;
const log4js = require('log4js');
const logger = log4js.getLogger();
logger.level = process.env.LOGLEVEL || /* istanbul ignore next */ 'debug';
const MatomoTracker = require('matomo-tracker');
let matomo = null;
logger.debug(`MATOMO url ${process.env.MATOMO_URL} !`);
if ((process.env.MATOMO_URL !== undefined) && (process.env.MATOMO_URL !== null) && (process.env.MATOMO_URL !== '')) {
matomo = new MatomoTracker(process.env.MATOMO_ID, process.env.MATOMO_URL);
logger.info('MATOMO connected');
} else {
logger.warn('No matomo url defined');
}
const baseUrl = 'https://api.binarytransparency.net/';
/**
* Get remote IP number by connection or header data.
* @function getRemoteAddr
* @private
* @param {object} req The web request object
* @returns {string} IP number
*/
function getRemoteAddr (req) {
if (req.headers['x-forwarded-for']) {
const aIPs = req.headers['x-forwarded-for'].split(',');
const firstIP = aIPs[0];
logger.debug(firstIP);
return firstIP;
}
if (req.headers['x-real-ip']) return req.headers['x-real-ip'];
if (req.ip) return req.ip;
if (req._remoteAddress) return req._remoteAddress;
const sock = req.socket;
if (sock.socket) return sock.socket.remoteAddress;
return sock.remoteAddress;
}
/**
* Subscribe to apihit event.
* @function apihit
* @public
* @param {object} req The web request object
*/
eventEmitter.on('apihit', function getApiHit (req) {
logger.debug('In subscriber');
if (matomo == null) return;
const url = req.url;
const urlparts = url.split('/');
const urlMethod = urlparts[0] + '/' + urlparts[1] + '/' + urlparts[2];
const reqMethod = req.method;
const reqUseragent = req.headers['user-agent'];
const reqLanguage = req.headers['accept-language'];
logger.debug(`log ${urlMethod}`);
matomo.track({
url: baseUrl + urlMethod,
action_name: 'API call',
token_auth: process.env.MATOMO_TOKEN_AUTH,
cip: getRemoteAddr(req),
ca: 1,
ua: reqUseragent,
lang: reqLanguage,
cvar: JSON.stringify({
1: ['API version', urlparts[1]],
2: ['HTTP method', reqMethod]
})
});
});
/**
* Subscribe to grpchit event.
* @function grpchit
* @public
* @param {object} call The grpc request object
*/
eventEmitter.on('grpchit', function getApiHit (call) {
logger.debug('In subscriber');
if (matomo == null) return;
const url = call.call.handler.path;
const urlparts = url.split('/');
const urlMethod = urlparts[0] + '/' + urlparts[1] + '/' + urlparts[2];
const peerIP = call.getPeer().split(':')[0];
const reqUseragent = call.metadata.get('user-agent')[0];
logger.debug(`IP of peer: ${peerIP}`);
logger.debug(`log ${urlMethod}`);
logger.debug(`ua ${reqUseragent}`);
matomo.track({
url: baseUrl + urlMethod,
action_name: 'gRPC call',
token_auth: process.env.MATOMO_TOKEN_AUTH,
cip: peerIP,
ca: 1,
ua: reqUseragent
});
});
/**
* Subscribe to posthit event.
* @function posthit
* @public
* @param {string} urlpath The path request string
*/
eventEmitter.on('posthit', function getPostHit (urlpath) {
logger.debug('In subscriber');
if (matomo == null) return;
matomo.track({
url: baseUrl + urlpath,
action_name: 'POST call',
token_auth: process.env.MATOMO_TOKEN_AUTH
});
});
module.exports = {}