Skip to content

Instantly share code, notes, and snippets.

@marisademeglio
Last active November 27, 2019 07:07
Show Gist options
  • Save marisademeglio/73fa67ad4277ee9e1e5dabbc2906c0ab to your computer and use it in GitHub Desktop.
Save marisademeglio/73fa67ad4277ee9e1e5dabbc2906c0ab to your computer and use it in GitHub Desktop.
const path = require('path');
const fs = require('fs');
let logEntries = [];
let logs = fs.readdirSync('./logs');
let logfile = log => path.join(__dirname, 'logs', log);
logs.map(log => {
let filename = logfile(log);
console.log(`Processing ${filename}`);
var lines = require('fs').readFileSync(filename, 'utf-8')
.split('\n')
lines.map(line => {
if (line.substr(0, 4) == '2019') {
let timestamp = line.split('INFO')[0];
timestamp = timestamp.split(',')[0];
let [date, time] = timestamp.split(' ');
timestamp = `${date}T${time}`;
let ipaddress = '';
if (line.indexOf("Validation from") != -1) {
ipaddress = line.split('IP ')[1];
}
let logEntry = {
"timestamp": new Date(timestamp),
"executed": line.indexOf('Validation from') != -1,
"ip": ipaddress
}
logEntries.push(logEntry);
}
// else skip it, it's not a timestamped entry
})
});
// sort by date
let sortedLogEntries = logEntries.sort((a, b) => {
if (a.timestamp > b.timestamp) {
return 1;
}
else if (a.timestamp < b.timestamp) {
return -1;
}
else {
return 0;
}
});
let start = sortedLogEntries[0].timestamp;
let end = sortedLogEntries[sortedLogEntries.length - 1].timestamp;
console.log('start', start);
console.log('end', end);
let filteredLogEntries = sortedLogEntries.filter(entry => entry.executed === true);
function monthDiff(dateFrom, dateTo) {
return dateTo.getMonth() - dateFrom.getMonth() +
(12 * (dateTo.getFullYear() - dateFrom.getFullYear()))
}
function getEntriesInRange(dateFrom, dateTo) {
return filteredLogEntries.filter(entry => entry.timestamp >= dateFrom && entry.timestamp < dateTo);
}
// from here on just assume it's all in the same year and not december (no year rollover)
let numMonths = monthDiff(start, end);
let i;
let bymonth = [];
for (i = 1; i<= numMonths; i++) {
let monthEntries = getEntriesInRange(new Date(`${start.getFullYear()}-${start.getMonth() + i}-01`),
new Date(`${start.getFullYear()}-${start.getMonth() + i + 1}-01`));
let uniqueIPs = new Set(monthEntries.map(e => e.ip));
let thismonth = {"date": NiceDateStringMonth(monthEntries[0].timestamp), "entries": monthEntries, "unique": Array.from(uniqueIPs)};
bymonth.push(thismonth);
}
function NiceDateString(d){
function pad(n){return n<10 ? '0'+n : n}
return d.getFullYear()+'-'
+ pad(d.getMonth()+1)+'-'
+ pad(d.getDate());
}
function NiceDateStringMonth(d) {
function pad(n){return n<10 ? '0'+n : n}
return d.getFullYear()+'-'
+ pad(d.getMonth()+1);
}
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
const HTML = `
<html lang="en">
<head>
<meta charset="utf-8">
<title>epubcheck web stats</title>
<style>
:root {
--color1: white;
--color2: #ffebcd;
--header: #af9b7d;
}
body {
font-family: Arial
}
main table {
border-collapse: collapse;
table-layout: fixed;
width: 100%;
}
th, td {
text-align: left;
font-size: smaller;
font-weight: normal;
vertical-align: top;
padding: 2vh;
}
thead {
background: var(--header);
font-size: larger;
font-weight: bold;
}
table tbody tr:nth-child(even) {
background-color: var(--color1);
}
table tbody tr:nth-child(odd) {
background-color: var(--color2);
}
</style>
</head>
<body>
<h1>epubcheck web stats</h1>
<p>From ${NiceDateString(start)} to ${NiceDateString(end)}</p>
<p>Entries in the table below, including unique IP count, are calculated from when a visitor ran epubcheck (as opposed to just merely visiting the site).</p>
<table>
<thead><tr><th>Month</th><th>Validations</th><th>Unique IPs</th></tr></thead>
<tbody>
${bymonth.map(m => `
<tr>
<td>${m.date}</td>
<td>${numberWithCommas(m.entries.length)}</td>
<td>${numberWithCommas(m.unique.length)}</td>
</tr>`)}
</tbody>
</table>
</body>
</html>`
fs.writeFileSync("stats.html", HTML.replace(/tr>,/g, 'tr>'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment