Skip to content

Instantly share code, notes, and snippets.

@FabienLavocat
Created June 18, 2024 18:28
Show Gist options
  • Save FabienLavocat/a37be2efcb4e0fe053d2374ae0c55f6e to your computer and use it in GitHub Desktop.
Save FabienLavocat/a37be2efcb4e0fe053d2374ae0c55f6e to your computer and use it in GitHub Desktop.
Dolby Millicast - compute the bandwidth consumed by the streams between two dates
var https = require('https');
const readline = require('node:readline/promises');
const { stdin: input, stdout: output } = require('node:process');
/**
* Provide your Dolby Millicast API Secret
*/
var bearer = null;
/**
* Compute the bandwidth from this date.
* Format: YYYY-MM-DD
*/
var from = null;
/**
* Compute the bandwidth until this date.
* Format: YYYY-MM-DD
* Default: end of day today
*/
var to = null;
async function promptForParameters() {
const rl = readline.createInterface({ input, output });
if (!bearer) {
bearer = await rl.question('\x1b[33mProvide your Dolby Millicast API Secret:\x1b[0m ');
}
if (!from) {
from = await rl.question('\x1b[33mCompute the bandwidth from (YYYY-MM-DD):\x1b[0m ');
}
if (!to) {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const toDefault = tomorrow.toISOString().substring(0, 10);
to = await rl.question(`\x1b[33mCompute the bandwidth until (YYYY-MM-DD) (default is ${toDefault}):\x1b[0m `);
if (!to) {
to = toDefault;
}
}
rl.close();
}
function getStreamIdsPage(page) {
return new Promise((resolve, reject) => {
var options = {
method: 'POST',
hostname: 'api.millicast.com',
path: '/graphql',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${bearer}`,
},
};
var req = https.request(options, function (res) {
var chunks = [];
res.on('data', function (chunk) {
chunks.push(chunk);
});
res.on('end', function (chunk) {
var body = Buffer.concat(chunks);
resolve(JSON.parse(body.toString()));
});
res.on('error', function (error) {
reject(error);
});
});
var postData = JSON.stringify({
query: `query StreamStatPagination($page: Int = ${page}) {streamStatPagination( page: $page, perPage: 150, filter: { _operators: { from: { gt: "${from}" } }, AND: { _operators: { to: { lt: "${to}"} } } }) { count items { streamId from to } pageInfo { currentPage perPage pageCount itemCount hasNextPage hasPreviousPage } } }`,
});
req.write(postData);
req.end();
});
}
async function getStreamIds() {
const streamIds = [];
let page = 1;
while (true) {
const result = await getStreamIdsPage(page++);
for (let index = 0; index < result.data.streamStatPagination.items.length; index++) {
const item = result.data.streamStatPagination.items[index];
if (!streamIds.includes(item.streamId)) {
streamIds.push(item.streamId);
}
}
if (!result.data.streamStatPagination.pageInfo.hasNextPage) {
break;
}
}
return streamIds;
}
function loadStream(streamName) {
return new Promise((resolve, reject) => {
var options = {
method: 'GET',
hostname: 'api.millicast.com',
path: `/api/analytics/streams/series?resolution=Day&streamNames=${streamName}&startDate=${from}T00:00:00Z&stopDate=${to}T00:00:00Z`,
headers: {
Authorization: `Bearer ${bearer}`,
},
maxRedirects: 20,
};
var req = https.request(options, function (res) {
var chunks = [];
res.on('data', function (chunk) {
chunks.push(chunk);
});
res.on('end', function (chunk) {
var body = Buffer.concat(chunks);
resolve(JSON.parse(body.toString()));
});
res.on('error', function (error) {
reject(error);
});
});
req.end();
});
}
function toGB(bytes) {
const formatter = Intl.NumberFormat(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
const gb = bytes / 1024 / 1024 / 1024;
return formatter.format(gb);
}
async function computeBw() {
const streamIds = await getStreamIds();
var bw = 0;
for (let index = 0; index < streamIds.length; index++) {
const streamName = streamIds[index].substring(7);
const result = await loadStream(streamName);
if (result.data[streamName]) {
const bandwidth = result.data[streamName].bandwidth;
const dates = Object.keys(bandwidth);
for (let j = 0; j < dates.length; j++) {
const date = dates[j];
const bytesOut = bandwidth[date].bytesOut;
const bytesIn = bandwidth[date].bytesIn;
bw += bytesOut + bytesIn;
if (bytesIn > 0) {
const strDate = new Date(date).toISOString().substring(0, 10);
const ratio = bytesOut / bytesIn;
const bwDay = toGB(bytesOut + bytesIn);
console.log(`${streamName} - ${strDate} - IN: ${toGB(bytesIn)} GB - OUT: ${toGB(bytesOut)} GB - Ratio: ${ratio.toFixed(2)}x - Total bw: ${bwDay} GB`);
}
}
console.log();
}
}
return bw;
}
promptForParameters()
.then(computeBw)
.then((bw) => console.log(`Account bandwidth: ${toGB(bw)} GB`));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment